package service import ( "basic.com/dbapi.git" "basic.com/valib/logger.git" "encoding/json" "errors" "io/ioutil" "os" "path" "path/filepath" "strconv" "strings" "webserver/extend/config" "webserver/extend/util" ) type SdkInstallService struct { } //算法安装包安装 func (sv SdkInstallService) SdkInstall(identifier string,filename string) (bool,error) { configPatchPath := "" if config.Server.PatchPath != "" { configPatchPath = config.Server.PatchPath } else { configPatchPath = "../patch" } filenameWithSuffix := path.Base(filename) ext := path.Ext(filenameWithSuffix) zipFilePath := configPatchPath + "/"+identifier+ext unPackTargetPath := configPatchPath+"/"+identifier+"_basic/" 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) } return false,errors.New("获取安装包md5失败") } if strMd5 == identifier { 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) } logger.Debug("strMd5 is", strMd5,"identifier is",identifier,"not equal") return false,errors.New("校验安装文件失败") } } else { return false,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 defer func() { if util.Exists(unPackTargetPath) { os.RemoveAll(unPackTargetPath) } if util.Exists(unPackFilePath) { os.RemoveAll(unPackFilePath) } }() if util.Exists(unPackTargetPath) { //此版本已经更新过 rmErr := os.RemoveAll(unPackTargetPath) if rmErr !=nil { return false,rmErr } } if !util.CreateDirectory(unPackTargetPath) { return false, errors.New("创建压缩文件夹失败") } logger.Debug("unPackFilePath:", unPackFilePath, "unPackPath:", unPackTargetPath) _,err := util.UnTarGzByCmd(unPackFilePath, unPackTargetPath) if err !=nil { logger.Debug("UnPack err:",err,"unPackFile:",unPackFilePath) return false, err } 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 +"/" //解压完成,获取安装包中的文件,开始安装 //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 { //处理授权信息 curMc := "" if ins.MachineCode != curMc { } //2.解析sdk.def,将so和zconf复制到/opt/vasystem/libs/文件夹下 defPath := unPackPath + "sdk.def" if util.Exists(defPath) { if defB, err := ioutil.ReadFile(defPath); err == nil { //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 } if _,ok := aInsM[skd.Def.Id]; ok { srv := SdkRegisterVo{ Id: skd.Def.Id, SdkType: skd.Def.SdkType, SdkName: skd.Def.SdkName, Icon: skd.Def.Icon, Url: skd.Def.Url, IconBlob: skd.Def.IconBlob, Version: skd.Def.Version, } 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) } paramBody := util.Struct2Map(srv) logger.Debug("sdkApi.Register paramBody:", paramBody) sdkApi.Register(paramBody) //将算法注册到数据库中 } } zconfPath := "./zconf/" libPath := "../libs/" if !util.DirExists(zconfPath) { os.MkdirAll(zconfPath, 0777) } if !util.DirExists(libPath) { os.MkdirAll(libPath, 0777) } for sdkType,_ := range soM { 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", "./zconf"); cE != nil { return false, cE } } } else { logger.Debug("unTarGzE sdkType.tar.gz err:", unTarGzE) } } else { logger.Debug("upper version has been installed") } } } else { return false, errors.New("反序列化算法定义信息失败") } } else { return false, errors.New("读取算法定义信息失败") } } else { return false, errors.New("算法定义信息丢失") } } else { return false, errors.New("反序列化授权信息失败") } } else { return false, errors.New("读取授权文件失败") } } else { return false, errors.New("授权文件不存在") } 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(curIVArr[0]) dM,dEM := strconv.Atoi(curIVArr[1]) dL,dEL := strconv.Atoi(curIVArr[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 } } type InsInc struct { OrderId string `json:"orderId"` ProductId string `json:"productId"` ActivateCode string `json:"activateCode"` MachineCode string `json:"machineCode"` UserId string `json:"userId"` SdkIds []string `json:"sdkIds"` ModuleIds []string `json:"moduleIds"` ChCount int `json:"chCount"` AuthCount int `json:"authCount"` ServeYear int `json:"serveYear"` } //算法和参数定义 type SdkDef struct { Def Sdk `json:"def"` Args []SdkArgEntity `json:"args"` } 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"` 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版本等) IconBlob string `gorm:"column:iconBlob;type:text;" json:"iconBlob"` //图片 Version string `gorm:"column:version;type:varchar(50);default:'1.0';" json:"version"` //版本号 } type SdkInsOrUpgrade struct { Sdk RemoteVersion string `json:"remoteVersion"` //商城仓库版本号 Installed bool `json:"installed"` //是否已安装 IsUpgrade bool `json:"isUpgrade"` //是否需要升级 } type SdkArgEntity struct { Id string `gorm:"primary_key;column:id" json:"id"` SdkId string `gorm:"column:sdk_id" json:"sdk_id"` Scope string `gorm:"column:scope" json:"scope"` SdkArg } type SdkArg struct { Alias string `gorm:"column:alias" json:"alias"` //参数的别名 Name string `gorm:"column:name" json:"name"` //参数名称 Type string `gorm:"column:type" json:"type"` //参数类型(整数,字符串或数组) ArgType string `gorm:"column:arg_type" json:"arg_type"` Must bool `gorm:"column:must" json:"must"` //是否必填 Unit string `gorm:"column:unit" json:"unit"` //单位 Range string `gorm:"column:range" json:"range"` //值的范围,eg:0,100表示从0到100 DefaultValue string `gorm:"column:default_value" json:"default_value"` DefaultOperator string `gorm:"column:default_operator" json:"default_operator"` Sort int `gorm:"column:sort;default:1" json:"sort"` } 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"` //算法下载地址 IconBlob string `json:"iconBlob"` //图片 Version string `json:"version"` //版本号 } type SdkRegisterArgVo struct { Scope string `json:"scope"` SdkArg Dics []SdkArgDic `json:"dics"` //如果此算法参数是被选项,需要将参数枚举值写入到字典表中 } type SdkArgDic struct { Value string `json:"value"` Name string `json:"name"` Sort int `json:"sort"` }