liuxiaolong
2020-05-29 0bb9a4c37862e5098a596e121fb13fd12c2ca44f
install sdk tar.gz
5个文件已修改
345 ■■■■■ 已修改文件
controllers/fileController.go 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/syssetcont.go 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
extend/util/zip.go 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
router/router.go 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/SdkInstall.go 229 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/fileController.go
@@ -492,6 +492,9 @@
                    return
                }
                faceB = decodeF
            } else {
                util.ResponseFormat(c, code.ComError, "本条人脸抓拍特征为空,请检查")
                return
            }
        }
controllers/syssetcont.go
@@ -635,3 +635,29 @@
        util.ResponseFormat(c,code.UpgradeFail,err.Error())
    }
}
// @Security ApiKeyAuth
// @Summary 算法安装包开始安装
// @Description 算法安装包开始安装
// @Accept multipart/form-data
// @Produce json
// @Tags sysset
// @Param identifier formData string true "整个文件的唯一标识,目前是md5"
// @Param filename formData string true "文件名称"
// @Success 200 {string} json "{"code":200, msg:"", success:true}"
// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
// @Router /data/api-v/sysset/sdkInstall [post]
func (sset SysSetController) SdkInstall(c *gin.Context) {
    identifier := c.Request.FormValue("identifier")
    filename := c.Request.FormValue("filename")
    if identifier == "" || filename == "" {
        util.ResponseFormat(c,code.RequestParamError,"")
        return
    }
    var sv service.SysService
    if b,err := sv.SdkInstall(identifier, filename);b {
        util.ResponseFormat(c,code.UpgradeSuccess,"算法安装成功")
    } else {
        util.ResponseFormat(c,code.UpgradeFail,err.Error())
    }
}
extend/util/zip.go
@@ -5,10 +5,13 @@
    "basic.com/valib/logger.git"
    "compress/gzip"
    "errors"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "os"
    "path"
    "path/filepath"
    "strings"
)
@@ -26,7 +29,7 @@
    logger.Debug("文件名称是", FileName)
    //创建存放压缩文件的路径(如果文件夹不存在)
    if !dirExists(DesPathName) {
    if !DirExists(DesPathName) {
        os.MkdirAll(DesPathName, 0777)
    }
    logger.Debug("创建文件")
@@ -121,11 +124,11 @@
    // 清理路径字符串
    src = path.Clean(src)
    // 判断要打包的文件或目录是否存在
    if !exists(src) {
    if !Exists(src) {
        return errors.New("要打包的文件或目录不存在:" + src)
    }
    // 判断目标文件是否存在
    if fileExists(dstTar) {
    if FileExists(dstTar) {
        if failIfExist { // 不覆盖已存在的文件
            return errors.New("目标文件已经存在:" + dstTar)
        } else { // 覆盖已存在的文件
@@ -296,19 +299,87 @@
}
// 判断档案是否存在
func exists(name string) bool {
func Exists(name string) bool {
    _, err := os.Stat(name)
    return err == nil || os.IsExist(err)
}
// 判断文件是否存在
func fileExists(filename string) bool {
func FileExists(filename string) bool {
    fi, err := os.Stat(filename)
    return (err == nil || os.IsExist(err)) && !fi.IsDir()
}
// 判断目录是否存在
func dirExists(dirname string) bool {
func DirExists(dirname string) bool {
    fi, err := os.Stat(dirname)
    return (err == nil || os.IsExist(err)) && fi.IsDir()
}
}
//文件夹复制
func CopyDir(src string, dest string) {
    src_original := src
    err := filepath.Walk(src, func(src string, f os.FileInfo, err error) error {
        if f == nil {
            return err
        }
        if f.IsDir() {
            CopyDir(f.Name(), dest+"/"+f.Name())
        } else {
            fmt.Println(src)
            fmt.Println(src_original)
            fmt.Println(dest)
            dest_new := strings.Replace(src, src_original, dest, -1)
            fmt.Println(dest_new)
            fmt.Println("CopyFile:" + src + " to " + dest_new)
            CopyFile(src, dest_new)
        }
        return nil
    })
    if err != nil {
        fmt.Printf("filepath.Walk() returned %v\n", err)
    }
}
//大文件复制
func CopyFile(srcFileName string, dstFileName string) {
    //打开源文件
    srcFile, err := os.Open(srcFileName)
    if err != nil {
        log.Fatalf("源文件读取失败,原因是:%v\n", err)
    }
    defer func() {
        err = srcFile.Close()
        if err != nil {
            log.Fatalf("源文件关闭失败,原因是:%v\n", err)
        }
    }()
    //创建目标文件,稍后会向这个目标文件写入拷贝内容
    distFile, err := os.Create(dstFileName)
    if err != nil {
        log.Fatalf("目标文件创建失败,原因是:%v\n", err)
    }
    defer func() {
        err = distFile.Close()
        if err != nil {
            log.Fatalf("目标文件关闭失败,原因是:%v\n", err)
        }
    }()
    //定义指定长度的字节切片,每次最多读取指定长度
    var tmp = make([]byte, 1024*4)
    //循环读取并写入
    for {
        n, err := srcFile.Read(tmp)
        n, _ = distFile.Write(tmp[:n])
        if err != nil {
            if err == io.EOF {//读到了文件末尾,并且写入完毕,任务完成返回(关闭文件的操作由defer来完成)
                return
            } else {
                log.Fatalf("拷贝过程中发生错误,错误原因为:%v\n", err)
            }
        }
    }
}
router/router.go
@@ -257,6 +257,8 @@
        vsset.GET("/patchUpdate", ssController.PatchUpdateCheck)
        vsset.POST("/patchUpdate", ssController.PatchUpdate)
        vsset.POST("/upgrade", ssController.Upgrade)
        vsset.POST("/sdkInstall", ssController.SdkInstall)
    }
    ic := r.Group(urlPrefix + "/info")
service/SdkInstall.go
@@ -1 +1,230 @@
package service
import (
    "basic.com/dbapi.git"
    "basic.com/valib/logger.git"
    "encoding/json"
    "errors"
    "io/ioutil"
    "os"
    "path"
    "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 !installSdk(identifier, ext) {
                return false,errors.New("执行安装过程异常,请确定上传的安装包是tar.gz格式")
            }
            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 {
    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
        }
    }
    if !util.CreateDirectory(unPackPath) {
        return false
    }
    unPackFilePath := configPatchPath+"/"+identifier+ext
    err := util.UnTarGz(unPackFilePath, unPackPath)
    if err !=nil {
        logger.Debug("UnPack err:",err,"unPackFile:",unPackFilePath)
        return false
    }
    //解压完成,获取安装包中的文件,开始安装
    //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 {
                //处理授权信息
                //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 {
                            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)
                                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 {
                                //复制json启动文件
                                util.CopyFile(unPackPath+sdkType+"/"+sdkType+".json", zconfPath)
                                util.CopyDir(unPackPath+sdkType+"/"+sdkType, libPath)
                                if util.DirExists(unPackPath+sdkType+"models") {
                                    util.CopyDir(unPackPath+sdkType+"models", "/opt/vasystem/bin/")
                                }
                            }
                            ret = true
                        }
                    }
                }
            }
        }
    }
    return ret
}
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"`
}