package service import ( "basic.com/dbapi.git" //"basic.com/dbapi.git" "basic.com/valib/logger.git" "encoding/json" "errors" "io/ioutil" "os" "path" "path/filepath" "webserver/extend/config" "webserver/extend/util" ) //算法安装包安装 func (sv SysService) SdkInstall(identifier string,filename string) (bool,error) { configPatchPath := "" if config.Server.PatchPath != "" { configPatchPath = config.Server.PatchPath } else { configPatchPath = "/opt/vasystem/patch" } filenameWithSuffix := path.Base(filename) ext := path.Ext(filenameWithSuffix) zipFilePath := configPatchPath + "/"+identifier+ext if util.Exists(zipFilePath) { strMd5, e := util.FileMd5(zipFilePath) if e !=nil || strMd5 == "" { return false,errors.New("获取安装包md5失败") } if strMd5 == identifier { if _,insE := installSdk(identifier, ext); insE != nil { return false, insE } return true,nil } else { 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 = "/opt/vasystem/patch" } //1.解压缩更新包 unPackPath := configPatchPath+"/"+identifier+"_basic/" if util.Exists(unPackPath) { //此版本已经更新过 rmErr := os.RemoveAll(unPackPath) if rmErr !=nil { return false,rmErr } } if !util.CreateDirectory(unPackPath) { return false, errors.New("创建压缩文件夹失败") } unPackFilePath := configPatchPath+"/"+identifier+ext logger.Debug("unPackFilePath:", unPackFilePath, "unPackPath:", unPackPath) _,err := util.UnTarGzByCmd(unPackFilePath, unPackPath) if err !=nil { logger.Debug("UnPack err:",err,"unPackFile:",unPackFilePath) return false, err } targetFileName := "" err = filepath.Walk(unPackPath, 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 = unPackPath + 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 if err = json.Unmarshal(defB, &skDefArr);err == nil { //注册算法信息和算法参数到dbserver var sdkApi dbapi.SdkApi for _,skd := range skDefArr { 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, } 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 := "/opt/vasystem/bin/zconf/" libPath := "/opt/vasystem/libs/" if !util.DirExists(zconfPath) { os.MkdirAll(zconfPath, 0777) } if !util.DirExists(libPath) { os.MkdirAll(libPath, 0777) } for sdkType,_ := range soM { //先解压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", "/opt/vasystem/bin/zconf"); cE != nil { return false, cE } } } else { logger.Debug("unTarGzE sdkType.tar.gz err:", unTarGzE) } } } 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 } 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版本等) } 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"` //算法下载地址 } 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"` }