sunty
2020-08-20 9d88c7c467f8d93af4aab9ba0b6d6c01c2ffc546
service/SdkInstall.go
@@ -2,41 +2,101 @@
import (
   "basic.com/dbapi.git"
   "basic.com/pubsub/protomsg.git"
   "basic.com/valib/licence.git"
   "basic.com/valib/logger.git"
   "encoding/json"
   "errors"
   "io/ioutil"
   "os"
   "path"
   "path/filepath"
   "strconv"
   "strings"
   "webserver/extend/config"
   "webserver/extend/util"
   reqUtil "webserver/extend/util"
)
type SdkInstallService struct {
}
func (sv SdkInstallService) Active(cod string, sdkId string) (interface{},error) {
   //使用激活码激活算法
   url := "http://"+config.ShopConf.Url+"/data/api-s/sdk/activeByAINode"
   machineCode := licence.GetMachineCode()
   if machineCode == "" {
      logger.Debug("获取机器码失败")
      return nil, errors.New("获取机器码失败")
   }
   paramBody := map[string]interface{}{
      "code": cod,
      "sdkId": sdkId,
      "machineCode": machineCode,
   }
   header := map[string]string {
      "Authorization": token,
   }
   respBody, err := reqUtil.DoPostRequest(url, reqUtil.CONTENT_TYPE_JSON, paramBody, nil, header)
   if err != nil {
      logger.Debug("DoPostRequest err:", err)
      return nil, err
   }
   var res dbapi.Result
   if err = json.Unmarshal(respBody, &res); err != nil {
      logger.Debug("unmarshal err:", err)
      return nil, err
   }
   if !res.Success {
      logger.Debug("res.Data:", res.Data)
      return nil, errors.New("请求商城失败")
   }
   return res.Data, nil
}
//算法安装包安装
func (sv SysService) SdkInstall(identifier string,filename string) (bool,error) {
func (sv SdkInstallService) SdkInstall(identifier string,filename string) (bool,error) {
   configPatchPath := ""
   if config.Server.PatchPath != "" {
      configPatchPath = config.Server.PatchPath
   } else {
      configPatchPath = "/opt/vasystem/patch"
      configPatchPath = "../patch"
   }
   filenameWithSuffix := path.Base(filename)
   ext := path.Ext(filenameWithSuffix)
   zipFilePath := configPatchPath + "/"+identifier+ext
   unPackTargetPath := configPatchPath+"/"+identifier+"_basic/"
   md5DirPath := configPatchPath+"/"+identifier
   if util.Exists(zipFilePath) {
      strMd5, e := util.FileMd5(zipFilePath)
      if e !=nil || strMd5 == "" {
         go os.Remove(zipFilePath)
         if util.DirExists(unPackTargetPath) {
            go os.RemoveAll(unPackTargetPath)
         }
         if util.DirExists(md5DirPath) {
            go os.RemoveAll(md5DirPath)
         }
         return false,errors.New("获取安装包md5失败")
      }
      if strMd5 == identifier {
         if !installSdk(identifier, ext) {
            return false,errors.New("执行安装过程异常,请确定上传的安装包是tar.gz格式")
         if _,insE := installSdk(identifier, ext); insE != nil {
            return false, insE
         }
         return true,nil
      } else {
         go os.Remove(zipFilePath)
         if util.DirExists(unPackTargetPath) {
            go os.RemoveAll(unPackTargetPath)
         }
         if util.DirExists(md5DirPath) {
            go os.RemoveAll(md5DirPath)
         }
         logger.Debug("strMd5 is", strMd5,"identifier is",identifier,"not equal")
         return false,errors.New("校验安装文件失败")
      }
@@ -45,43 +105,164 @@
   }
}
//安装sdk
func installSdk(identifier string, ext string) bool {
//解压上传的算法安装包
func unPackPatchPackage(identifier string, ext string) (bool,error) {
   configPatchPath := ""
   if config.Server.PatchPath != "" {
      configPatchPath = config.Server.PatchPath
   } else {
      configPatchPath = "/opt/vasystem/patch"
      configPatchPath = "../patch"
   }
   //1.解压缩更新包
   unPackPath := configPatchPath+"/"+identifier+"_basic/"
   if util.Exists(unPackPath) {
   unPackTargetPath := configPatchPath+"/"+identifier+"_basic/"
   unPackFilePath := configPatchPath+"/"+identifier+ext
   if util.Exists(unPackTargetPath) {
      //此版本已经更新过
      rmErr := os.RemoveAll(unPackPath)
      rmErr := os.RemoveAll(unPackTargetPath)
      if rmErr !=nil {
         return false
         return false,rmErr
      }
   }
   if !util.CreateDirectory(unPackPath) {
      return false
   if !util.CreateDirectory(unPackTargetPath) {
      return false, errors.New("创建压缩文件夹失败")
   }
   unPackFilePath := configPatchPath+"/"+identifier+ext
   err := util.UnTarGz(unPackFilePath, unPackPath)
   logger.Debug("unPackFilePath:", unPackFilePath, "unPackPath:", unPackTargetPath)
   _,err := util.UnTarGzByCmd(unPackFilePath, unPackTargetPath)
   if err !=nil {
      logger.Debug("UnPack err:",err,"unPackFile:",unPackFilePath)
      return false
      return false, err
   }
   return true, nil
}
func (sv SdkInstallService) ShowInstallInfo(identifier string, filename string) (bool, map[string]interface{}, error) {
   configPatchPath := ""
   if config.Server.PatchPath != "" {
      configPatchPath = config.Server.PatchPath
   } else {
      configPatchPath = "../patch"
   }
   unPackTargetPath := configPatchPath+"/"+identifier+"_basic/"
   isValid := false
   defer func() {
      if !isValid {
         filenameWithSuffix := path.Base(filename)
         ext := path.Ext(filenameWithSuffix)
         unPackFilePath := configPatchPath+"/"+identifier+ext
         md5DirPath := configPatchPath+"/"+identifier
         if util.Exists(unPackTargetPath) {
            os.RemoveAll(unPackTargetPath)
         }
         if util.Exists(unPackFilePath) {
            os.RemoveAll(unPackFilePath)
         }
         if util.DirExists(md5DirPath) {
            go os.RemoveAll(md5DirPath)
         }
      }
   }()
   if util.Exists(unPackTargetPath) {
      targetFileName := ""
      err := filepath.Walk(unPackTargetPath, func(path string, f os.FileInfo, err error) error {
         if f == nil {
            return err
         }
         if f.IsDir() {
            targetFileName = f.Name()
         }
         return nil
      })
      if err != nil {
         return isValid, nil, errors.New("非法的安装包")
      } else {
         unPackPath := unPackTargetPath + targetFileName +"/"
         //解压完成,获取安装包中的文件,开始安装
         //1.解析安装说明ins.inc
         incPath := unPackPath+"ins.inc"
         if util.Exists(incPath) {
            if incB, err := ioutil.ReadFile(incPath); err == nil {
               var ins InsInc
               if err = json.Unmarshal(incB, &ins); err == nil {
                  return true, map[string]interface{} {
                     "sdkName": ins.ProductName,
                     "installVersion": ins.InstallVersion,
                     "installContent": ins.InstallContent,
                  }, nil
               } else {
                  return false, nil, errors.New("非法的安装包")
               }
            } else {
               return false, nil, errors.New("非法的安装包")
            }
         } else {
            return false, nil, errors.New("非法的安装包")
         }
      }
   } else {
      return isValid, nil, errors.New("安装包已不存在")
   }
}
//安装sdk
func installSdk(identifier string, ext string) (bool, error) {
   configPatchPath := ""
   if config.Server.PatchPath != "" {
      configPatchPath = config.Server.PatchPath
   } else {
      configPatchPath = "../patch"
   }
   //1.解压缩更新包
   unPackTargetPath := configPatchPath+"/"+identifier+"_basic/"
   unPackFilePath := configPatchPath+"/"+identifier+ext
   md5DirPath := configPatchPath+"/"+identifier
   defer func() {
      if util.Exists(unPackTargetPath) {
         os.RemoveAll(unPackTargetPath)
      }
      if util.Exists(unPackFilePath) {
         os.RemoveAll(unPackFilePath)
      }
      if util.DirExists(md5DirPath) {
         go os.RemoveAll(md5DirPath)
      }
   }()
   if !util.Exists(unPackTargetPath) {//安装包不存在
      return false, errors.New("安装文件已不存在")
   }
   targetFileName := ""
   err := filepath.Walk(unPackTargetPath, func(path string, f os.FileInfo, err error) error {
      if f == nil {
         return err
      }
      if f.IsDir() {
         targetFileName = f.Name()
      }
      return nil
   })
   if err != nil {
      return false, err
   }
   unPackPath := unPackTargetPath + targetFileName +"/"
   if !util.Exists(unPackPath) {
      return false, errors.New("安装文件已不存在")
   }
   //解压完成,获取安装包中的文件,开始安装
   //1.解析安装说明ins.inc
   incPath := unPackPath+"ins.inc"
   ret := false
   if util.Exists(incPath) {
      if incB, err := ioutil.ReadFile(incPath);err == nil {
         var ins InsInc
         if err = json.Unmarshal(incB, &ins); err == nil {
            //处理授权信息
            curMc := ""
            if ins.MachineCode != curMc {
            }
            //2.解析sdk.def,将so和zconf复制到/opt/vasystem/libs/文件夹下
            defPath := unPackPath + "sdk.def"
            if util.Exists(defPath) {
@@ -89,43 +270,69 @@
                  //3.将算法so、依赖文件、zconf、
                  soM := make(map[string]SdkDef)
                  var skDefArr []SdkDef
                  nInsM := make(map[string]string)
                  aInsM := make(map[string]string)
                  if err = json.Unmarshal(defB, &skDefArr);err == nil {
                     var sdkApi dbapi.SdkApi
                     for _,skd := range skDefArr {
                        //注册算法信息和算法参数到dbserver
                        //先看此算法有没有注册,如果已安装,比对版本号
                        bf, curDbSdk := sdkApi.GetById(skd.Def.Id)
                        if bf {
                           bytes, _ := json.Marshal(curDbSdk)
                           var sm map[string]interface{}
                           unE :=  json.Unmarshal(bytes, &sm)
                           if unE != nil {
                              continue
                           }
                           sdkVersion, ok := sm["version"]
                           if ok { //有版本号
                              vStr := sdkVersion.(string)
                              if shouldVersionBeUpgrade(vStr, skd.Def.Version) { //比对版本号确定是否需要安装
                                 nInsM[skd.Def.SdkType] = skd.Def.SdkType
                                 aInsM[skd.Def.Id] = skd.Def.Id
                              }
                           } else {
                              nInsM[skd.Def.SdkType] = skd.Def.SdkType
                              aInsM[skd.Def.Id] = skd.Def.Id
                           }
                        } else {
                           nInsM[skd.Def.SdkType] = skd.Def.SdkType
                           aInsM[skd.Def.Id] = skd.Def.Id
                        }
                        if _,ok := soM[skd.Def.SdkType];!ok {
                           soM[skd.Def.SdkType] = skd
                        }
                        srv := SdkRegisterVo{
                           Id: skd.Def.Id,
                           SdkType: skd.Def.SdkType,
                           SdkName: skd.Def.SdkName,
                           Icon: skd.Def.Icon,
                           Url: skd.Def.Url,
                        }
                        for _,ag := range skd.Args {
                           sra := SdkRegisterArgVo{
                              Scope: ag.Scope,
                        if _,ok := aInsM[skd.Def.Id]; ok {
                           srv := SdkRegisterVo{}
                           srv.SdkCommon = skd.Def.SdkCommon
                           for _,ag := range skd.Args {
                              sra := SdkRegisterArgVo{
                                 Scope: ag.Scope,
                              }
                              sra.SdkArg = SdkArg{
                                 Alias: ag.Alias,
                                 Name: ag.Name,
                                 Type: ag.Type,
                                 ArgType: ag.ArgType,
                                 Must: ag.Must,
                                 Unit: ag.Unit,
                                 Range: ag.Range,
                                 DefaultValue: ag.DefaultValue,
                                 DefaultOperator: ag.DefaultOperator,
                                 Sort: ag.Sort,
                              }
                              srv.Args = append(srv.Args,  sra)
                           }
                           sra.SdkArg = SdkArg{
                              Alias: ag.Alias,
                              Name: ag.Name,
                              Type: ag.Type,
                              ArgType: ag.ArgType,
                              Must: ag.Must,
                              Unit: ag.Unit,
                              Range: ag.Range,
                              DefaultValue: ag.DefaultValue,
                              DefaultOperator: ag.DefaultOperator,
                              Sort: ag.Sort,
                           }
                           srv.Args = append(srv.Args,  sra)
                           paramBody := util.Struct2Map(srv)
                           logger.Debug("sdkApi.Register paramBody:", paramBody)
                           sdkApi.Register(paramBody) //将算法注册到数据库中
                        }
                        paramBody := util.Struct2Map(srv)
                        sdkApi.Register(paramBody) //将算法注册到数据库中
                     }
                     zconfPath := "/opt/vasystem/bin/zconf/"
                     libPath := "/opt/vasystem/libs/"
                     zconfPath := "./zconf/"
                     libPath := "../libs/"
                     if !util.DirExists(zconfPath) {
                        os.MkdirAll(zconfPath, 0777)
                     }
@@ -133,22 +340,105 @@
                        os.MkdirAll(libPath, 0777)
                     }
                     for sdkType,_ := range soM {
                        //复制json启动文件
                        util.CopyFile(unPackPath+sdkType+"/zconf/"+sdkType+".json", zconfPath)
                        util.CopyDir(unPackPath+sdkType+"/"+sdkType, libPath)
                        if util.DirExists(unPackPath+sdkType+"/models") {
                           util.CopyDir(unPackPath+sdkType+"/models", "/opt/vasystem/bin/")
                        if _,iOk := nInsM[sdkType];iOk {
                           //先解压SdkType.tar.gz文件
                           if unTarGzE := util.UnTarGz(unPackPath+sdkType+".tar.gz", unPackPath);unTarGzE == nil {
                              //复制json启动文件
                              if util.Exists(unPackPath+sdkType+"/zconf/"+sdkType+".json") {
                                 util.CopyFile(unPackPath+sdkType+"/zconf/"+sdkType+".json", zconfPath+sdkType+".json")
                              }
                              if util.DirExists(unPackPath+sdkType) {
                                 if _,cE := util.CopyDirByCmd(unPackPath+sdkType, libPath);cE != nil {
                                    return false, cE
                                 }
                              }
                              if util.DirExists(unPackPath+sdkType+"/models") {
                                 if _,cE := util.CopyDirByCmd(unPackPath+sdkType+"/models", "./"); cE != nil {
                                    return false, cE
                                 }
                                 //拷贝完成后删除libs下sdkType文件夹下models
                              }
                              if util.DirExists(libPath+sdkType+"/models") {
                                 os.RemoveAll(libPath+sdkType+"/models")
                              }
                              if util.DirExists(libPath+sdkType+"/zconf") {
                                 os.RemoveAll(libPath+sdkType+"/zconf")
                              }
                           } else {
                              logger.Debug("unTarGzE sdkType.tar.gz err:", unTarGzE)
                           }
                        } else {
                           logger.Debug("upper version has been installed")
                        }
                     }
                     ret = true
                  } else {
                     logger.Debug("反序列化算法定义信息失败")
                     return false, errors.New("错误的安装包")
                  }
               } else {
                  logger.Debug("读取算法定义信息失败")
                  return false, errors.New("错误的安装包")
               }
            } else {
               logger.Debug("算法定义信息丢失")
               return false, errors.New("错误的安装包")
            }
         } else {
            logger.Debug("反序列化授权信息失败")
            return false, errors.New("错误的安装包")
         }
      } else {
         logger.Debug("读取授权文件失败")
         return false, errors.New("错误的安装包")
      }
   } else {
      return false, errors.New("错误的安装包")
   }
   return ret
   return true, nil
}
func shouldVersionBeUpgrade(curVersion,dstVersion string) bool {
   if curVersion == "" {
      return true
   }
   if dstVersion == "" {
      return false
   }
   curIVArr := strings.Split(curVersion, ".")
   dstIVArr := strings.Split(dstVersion, ".")
   if len(curIVArr) !=3 || len(dstIVArr) != 3{
      return false
   }
   cH,cEH := strconv.Atoi(curIVArr[0])
   cM,cEM := strconv.Atoi(curIVArr[1])
   cL,cEL := strconv.Atoi(curIVArr[2])
   dH,dEH := strconv.Atoi(dstIVArr[0])
   dM,dEM := strconv.Atoi(dstIVArr[1])
   dL,dEL := strconv.Atoi(dstIVArr[2])
   if cEH !=nil || cEM != nil || cEL != nil || dEH != nil ||dEM !=nil || dEL !=nil {
      return false
   }
   if cH > dH {
      return false
   } else if cH == dH {
      if cM > dM {
         return false
      } else if cM == dM {
         if cL > dL {
            return false
         } else if cL == dL {
            return false
         } else {
            return true
         }
      } else {
         return true
      }
   } else {
      return true
   }
}
@@ -163,6 +453,10 @@
   ChCount          int       `json:"chCount"`
   AuthCount          int       `json:"authCount"`
   ServeYear         int       `json:"serveYear"`
   ProductName       string       `json:"productName"`
   InstallVersion       string       `json:"installVersion"`
   InstallContent       string       `json:"installContent"`
}
//算法和参数定义
@@ -172,18 +466,48 @@
}
type Sdk struct {
   Id             string       `gorm:"column:id;primary_key;type:varchar(50);unique;not null;" json:"id"`
   IpcId         string       `gorm:"column:ipc_id" json:"ipc_id"`
   SdkType       string       `gorm:"column:sdk_type" json:"sdk_type"`
   SdkName       string       `gorm:"column:sdk_name" json:"sdk_name" example:"人脸检测"`
   Icon          string       `gorm:"column:icon" json:"icon,omitempty"`
   Url           string       `gorm:"column:url" json:"url,omitempty" example:"http://ip:port/govideo/sdk/1"`
   SdkCommon
   CreateTime       string       `gorm:"column:create_time" json:"create_time"`
   CreateBy       string       `gorm:"column:create_by" json:"create_by"`
   UpdateTime       string       `gorm:"column:update_time" json:"update_time"`
   Enable          bool       `gorm:"column:enable;default:1" json:"enable"`
   DelFlag       int       `gorm:"column:del_flag;default:0" json:"del_flag"`
   Env          string       `gorm:"column:env" json:"env"` //运行环境及结果说明,json格式,包含so_file_path,runtime,param,depends(cuda版本,opencv版本,tensorflow版本等)
   Args          []SdkArg    `json:"args"`
}
func (sc *SdkCommon) copyFromProto(pSdk protomsg.Sdk) {
   sc.Id = pSdk.Id
   sc.IpcId = pSdk.IpcId
   sc.SdkType = pSdk.SdkType
   sc.SdkName = pSdk.SdkName
   sc.Icon = pSdk.Icon
   sc.Url = pSdk.Url
   sc.IconBlob = pSdk.IconBlob
   sc.Version = pSdk.Version
   sc.ArgDef = pSdk.ArgDef
   sc.RuleSo = pSdk.RuleSo
}
type SdkCommon struct {
   Id             string             `json:"id"`
   IpcId         string             `json:"ipc_id"`
   SdkType       string             `json:"sdk_type"`//人脸检测:FaceDetect,人脸提取:FaceExtract,人脸比对:FaceCompare,行为:Yolo
   SdkName       string             `json:"sdk_name"`    //算法名称
   Icon          string             `json:"icon"`       //算法图标
   Url           string             `json:"url"`        //算法下载地址
   IconBlob       string             `json:"iconBlob"` //图片
   Version       string             `json:"version"` //版本号
   EnTrack       bool             `json:"enTrack"`  //是否开启跟踪
   ArgDef          string             `json:"argDef"`   //算法默认参数定义
   RuleSo          string             `json:"rule_so"`
}
type SdkInsOrUpgrade struct {
   Sdk
   RemoteVersion    string        `json:"remoteVersion"` //商城仓库版本号
   Installed       bool        `json:"installed"` //是否已安装
   IsUpgrade       bool        `json:"isUpgrade"` //是否需要升级
}
type SdkArgEntity struct {
@@ -208,23 +532,19 @@
type SdkRegisterVo struct {
   Id       string `json:"id"`
   SdkType string `json:"sdk_type"`//人脸检测:FaceDetect,人脸提取:FaceExtract,人脸比对:FaceCompare,行为:Yolo
   SdkName string `json:"sdk_name"`    //算法名称
   Args    []SdkRegisterArgVo `json:"args"` //算法参数
   Icon    string `json:"icon"`       //算法图标
   Url     string `json:"url"`                       //算法下载地址
   SdkCommon
   Args          []SdkRegisterArgVo    `json:"args"` //算法参数
}
type SdkRegisterArgVo struct {
   Scope string `json:"scope"`
   Scope          string          `json:"scope"`
   SdkArg
   Dics []SdkArgDic `json:"dics"` //如果此算法参数是被选项,需要将参数枚举值写入到字典表中
   Dics          []SdkArgDic    `json:"dics"` //如果此算法参数是被选项,需要将参数枚举值写入到字典表中
}
type SdkArgDic struct {
   Value string `json:"value"`
   Name string `json:"name"`
   Sort int `json:"sort"`
   Value          string          `json:"value"`
   Name          string          `json:"name"`
   Sort          int          `json:"sort"`
}