package cm import ( "bytes" "fmt" "io" "net/http" "os" "os/exec" "strconv" "strings" "ems.agt/lib/dborm" "ems.agt/lib/global" "ems.agt/lib/log" "ems.agt/lib/services" "ems.agt/restagent/config" "github.com/gorilla/mux" ) const ( SoftwareStatusUploaded = "Uploaded" SoftwareStatusInactive = "Inactive" SoftwareStatusActive = "Active" DigestsSignOkString = "digests signatures OK" SoftwareVerifiedOk = "Verified OK" ) var ( UriSoftware = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{neType}/software/{version}" UriSoftwareNE = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{neType}/software/{version}/{neId}" CustomUriSoftware = config.UriPrefix + "/systemManagement/{apiVersion}/{neType}/software/{version}" CustomUriSoftwareNE = config.UriPrefix + "/systemManagement/{apiVersion}/{neType}/software/{version}/{neId}" ) // 验证签名 func verify_signature(public_key_name string, source_cms_file string, source_file string) bytes.Buffer { cmd := exec.Command("/usr/local/omc/run/iv", "verify_signature", public_key_name, source_cms_file, source_file) var out bytes.Buffer cmd.Stdout = &out cmd.Env = append(os.Environ(), "FOO=duplicate_value", // 重复被忽略 "FOO=actual_value", // 实际被使用 ) err := cmd.Run() if err != nil { log.Error(err) } return out } func UploadSoftwareFile(w http.ResponseWriter, r *http.Request) { log.Debug("UploadSoftwareFile processing... ") _, err := services.CheckFrontValidRequest(w, r) if err != nil { log.Error("Http request error:", err) return } vars := mux.Vars(r) neType := vars["neType"] if neType == "" { log.Error("neType is empty") services.ResponseNotFound404UriNotExist(w, r) return } neTypeUpper := strings.ToUpper(neType) neTypeLower := strings.ToLower(neType) version := vars["version"] if version == "" { log.Error("version is empty") services.ResponseNotFound404UriNotExist(w, r) return } md5Param := services.GetUriParamString(r, "md5Sum", ",", false, false) // body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) // if err != nil { // log.Error("io.ReadAll is failed:", err) // services.ResponseNotFound404UriNotExist(w, r) // return // } // neSWBody := new(dborm.NeSoftware) // _ = json.Unmarshal(body, neSWBody) // log.Trace("neSoftware:", neSWBody) softwarePath := fmt.Sprintf("%s/%s", config.GetYamlConfig().OMC.Software, neTypeLower) fileName, err := services.HandleUploadFile(r, softwarePath, "") if err != nil { log.Error("Faile to HandleUploadFile:", err) services.ResponseInternalServerError500ProcessError(w, err) return } filePrefix := fileName[:strings.Index(fileName, ".zip")] filePath := fmt.Sprintf("%s/%s", softwarePath, fileName) log.Debugf("filePath:%s filePrefix:%s softwarePath:%s", filePath, filePrefix, softwarePath) cmd := exec.Command("unzip", "-o", filePath) cmd.Dir = softwarePath out, err := cmd.CombinedOutput() log.Debugf("Exec outpout:%s", string(out)) if err != nil { log.Error("Failed to unzip:", err) services.ResponseInternalServerError500ProcessError(w, err) return } md5File, err := global.GetFileMD5Sum(filePath) if err != nil { log.Error("Faile to GetFileMD5Sum:", err) services.ResponseInternalServerError500ProcessError(w, err) return } if md5File != md5Param { err = global.ErrCMNotMatchMD5File log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } rpmFileName := filePrefix + ".rpm" if config.GetYamlConfig().OMC.CheckSign { rpmFilePath := softwarePath + "/" + rpmFileName cmsFileName := rpmFileName + ".cms" cmsFilePath := softwarePath + "/" + cmsFileName log.Debugf("cmsFilePath:%s rpmFilePath:%s publicKey:%s", rpmFilePath, cmsFilePath, config.GetYamlConfig().Auth.PublicKey) result := verify_signature(config.GetYamlConfig().Auth.PublicKey, cmsFilePath, rpmFilePath) log.Debug("result:", result.String()) if !strings.Contains(result.String(), SoftwareVerifiedOk) { err = global.ErrCMNotMatchSignFile log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } // cmd := exec.Command("rpm", "-K", filePath) // out, err := cmd.CombinedOutput() // log.Debugf("Exec outpout:%s", string(out)) // if err != nil { // log.Error("Failed to execute rpm:", err) // services.ResponseInternalServerError500ProcessError(w, err) // return // } // if !strings.Contains(string(out), DigestsSignOkString) { // err = global.ErrCMNotMatchSignFile // log.Error(err) // services.ResponseInternalServerError500ProcessError(w, err) // return // } } //neBackup := dborm.NeBackup{NeType: neType, NeId: neId, Md5Sum: md5Sum} //log.Debug("neBackup:", neBackup) where := fmt.Sprintf("ne_type='%s' and version='%s'", neTypeUpper, version) has, err := dborm.XormExistTableOne("ne_software", where) if err != nil { log.Error("Faile to XormInsertTableOne:", err) services.ResponseInternalServerError500ProcessError(w, err) return } else if has { err = global.ErrCMExistSoftwareFile log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } neSoftware := dborm.NeSoftware{ NeType: neTypeUpper, FileName: rpmFileName, Path: softwarePath, Version: version, Md5Sum: md5Param, Comment: neType + " 5GC " + version, //Comment: neSWBody.Comment, } _, err = dborm.XormInsertTableOne("ne_software", neSoftware) if err != nil { log.Error("Faile to XormInsertTableOne:", err) services.ResponseInternalServerError500ProcessError(w, err) return } services.ResponseStatusOK204NoContent(w) } func UploadSoftwareMultiFile(w http.ResponseWriter, r *http.Request) { log.Info("UploadSoftwareMultiFile processing... ") _, err := services.CheckFrontValidRequest(w, r) if err != nil { log.Error("Http request error:", err) return } vars := mux.Vars(r) neType := vars["neType"] if neType == "" { log.Error("neType is empty") services.ResponseNotFound404UriNotExist(w, r) return } neTypeUpper := strings.ToUpper(neType) neTypeLower := strings.ToLower(neType) version := vars["version"] if version == "" { log.Error("version is empty") services.ResponseNotFound404UriNotExist(w, r) return } md5Param := services.GetUriParamString(r, "md5Sum", ",", false, false) softwarePath := fmt.Sprintf("%s/%s", config.GetYamlConfig().OMC.Software, neTypeLower) err = os.MkdirAll(softwarePath, os.ModePerm) if err != nil { log.Error("Failed to Mkdir:", err) services.ResponseInternalServerError500ProcessError(w, err) return } //fileName, err := services.HandleUploadFile(r, softwarePath, "") // 解析multipart/form-data请求 err = r.ParseMultipartForm(1000 << 20) // 1000MB if err != nil { log.Error("Faile to ParseMultipartForm:", err) services.ResponseInternalServerError500ProcessError(w, err) return } // 获取文件和数据 swFile := r.MultipartForm.File["file"] cmsFile := r.MultipartForm.File["cms"] data := r.MultipartForm.Value["comment"] var softwareFileName, cmsFileName, comment string // 处理软件rpm/deb文件 if len(swFile) > 0 { file := swFile[0] // 打开文件 f, err := file.Open() if err != nil { log.Error("Faile to Open:", err) services.ResponseInternalServerError500ProcessError(w, err) return } defer f.Close() // 创建本地文件 dst, err := os.Create(softwarePath + "/" + file.Filename) if err != nil { log.Error("Faile to Create:", err) services.ResponseInternalServerError500ProcessError(w, err) return } defer dst.Close() softwareFileName = file.Filename // 将文件内容拷贝到本地文件 _, err = io.Copy(dst, f) if err != nil { log.Error("Faile to Copy:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } // 处理cms文件 if len(cmsFile) > 0 { file := cmsFile[0] // 打开文件 f, err := file.Open() if err != nil { log.Error("Faile to Open:", err) services.ResponseInternalServerError500ProcessError(w, err) return } defer f.Close() // 创建本地文件 dst, err := os.Create(softwarePath + "/" + file.Filename) if err != nil { log.Error("Faile to Create:", err) services.ResponseInternalServerError500ProcessError(w, err) return } defer dst.Close() cmsFileName = file.Filename // 将文件内容拷贝到本地文件 _, err = io.Copy(dst, f) if err != nil { log.Error("Faile to Copy:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } // 处理数据 if len(data) > 0 { comment = data[0] } if config.GetYamlConfig().OMC.CheckSign && cmsFileName != "" { rpmFilePath := softwarePath + "/" + softwareFileName cmsFileName := cmsFileName cmsFilePath := softwarePath + "/" + cmsFileName log.Debugf("cmsFilePath:%s rpmFilePath:%s publicKey:%s", rpmFilePath, cmsFilePath, config.GetYamlConfig().Auth.PublicKey) result := verify_signature(config.GetYamlConfig().Auth.PublicKey, cmsFilePath, rpmFilePath) log.Debug("result:", result.String()) if !strings.Contains(result.String(), SoftwareVerifiedOk) { err = global.ErrCMNotMatchSignFile log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } // cmd := exec.Command("rpm", "-K", filePath) // out, err := cmd.CombinedOutput() // log.Debugf("Exec outpout:%s", string(out)) // if err != nil { // log.Error("Failed to execute rpm:", err) // services.ResponseInternalServerError500ProcessError(w, err) // return // } // if !strings.Contains(string(out), DigestsSignOkString) { // err = global.ErrCMNotMatchSignFile // log.Error(err) // services.ResponseInternalServerError500ProcessError(w, err) // return // } } // //neBackup := dborm.NeBackup{NeType: neType, NeId: neId, Md5Sum: md5Sum} // //log.Debug("neBackup:", neBackup) // where := fmt.Sprintf("ne_type='%s' and version='%s'", neTypeUpper, version) // has, err := dborm.XormExistTableOne("ne_software", where) // if err != nil { // log.Error("Faile to XormInsertTableOne:", err) // services.ResponseInternalServerError500ProcessError(w, err) // return // } else if has == true { // err = global.ErrCMExistSoftwareFile // log.Error(err) // services.ResponseInternalServerError500ProcessError(w, err) // return // } neSoftware := dborm.NeSoftware{ NeType: neTypeUpper, FileName: softwareFileName, Path: softwarePath, Version: version, Md5Sum: md5Param, Comment: comment, } _, err = dborm.XormInsertTableOne("ne_software", neSoftware) if err != nil { log.Error("Faile to XormInsertTableOne:", err) services.ResponseInternalServerError500ProcessError(w, err) return } services.ResponseStatusOK204NoContent(w) } func DownloadSoftwareFile(w http.ResponseWriter, r *http.Request) { log.Debug("DownloadSoftwareFile processing... ") _, err := services.CheckFrontValidRequest(w, r) if err != nil { log.Error("Request error:", err) return } vars := mux.Vars(r) neType := vars["neType"] if neType == "" { log.Error("neType is empty") services.ResponseNotFound404UriNotExist(w, r) return } neTypeUpper := strings.ToUpper(neType) //neTypeLower := strings.ToLower(neType) version := vars["version"] if version == "" { log.Error("version is empty") services.ResponseNotFound404UriNotExist(w, r) return } sql := fmt.Sprintf("select * from ne_software where ne_type='%s' and version='%s'", neTypeUpper, version) neSoftware, err := dborm.XormGetDataBySQL(sql) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return } else if len(*neSoftware) == 0 { err := global.ErrCMNotFoundTargetSoftware log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } fileName := (*neSoftware)[0]["file_name"] path := (*neSoftware)[0]["path"] md5Sum := (*neSoftware)[0]["md5_sum"] services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, md5Sum) } func DeleteSoftwareFile(w http.ResponseWriter, r *http.Request) { log.Debug("DeleteSoftwareFile processing... ") _, err := services.CheckFrontValidRequest(w, r) if err != nil { log.Error("Request error:", err) return } vars := mux.Vars(r) neType := vars["neType"] if neType == "" { log.Error("neType is empty") services.ResponseNotFound404UriNotExist(w, r) return } neTypeUpper := strings.ToUpper(neType) //neTypeLower := strings.ToLower(neType) version := vars["version"] if version == "" { log.Error("version is empty") services.ResponseNotFound404UriNotExist(w, r) return } sql := fmt.Sprintf("select * from ne_software where ne_type='%s' and version='%s'", neTypeUpper, version) neSoftware, err := dborm.XormGetDataBySQL(sql) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return } else if len(*neSoftware) == 0 { err := global.ErrCMNotFoundTargetSoftware log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } where := fmt.Sprintf("ne_type='%s' and version='%s'", neTypeUpper, version) affected, err := dborm.XormDeleteDataByWhere(where, "ne_software") if err != nil || affected == 0 { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return } fileName := (*neSoftware)[0]["file_name"] path := (*neSoftware)[0]["path"] filePath := fmt.Sprintf("%s/%s", path, fileName) err = os.Remove(filePath) if err != nil { log.Error("Faile to Remove:", err) services.ResponseInternalServerError500ProcessError(w, err) return } services.ResponseStatusOK204NoContent(w) } func DistributeSoftwareToNF(w http.ResponseWriter, r *http.Request) { log.Debug("DistributeSoftwareFile processing... ") _, err := services.CheckFrontValidRequest(w, r) if err != nil { log.Error("Http request error:", err) return } vars := mux.Vars(r) neType := vars["neType"] if neType == "" { log.Error("neType is empty") services.ResponseNotFound404UriNotExist(w, r) return } neTypeUpper := strings.ToUpper(neType) neTypeLower := strings.ToLower(neType) version := vars["version"] if version == "" { log.Error("version is empty") services.ResponseNotFound404UriNotExist(w, r) return } neId := vars["neId"] if version == "" { log.Error("neId is empty") services.ResponseNotFound404UriNotExist(w, r) return } neInfo, err := dborm.XormGetNeInfo(neTypeUpper, neId) if err != nil { log.Error("dborm.XormGetNeInfo is failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } sql := fmt.Sprintf("select * from ne_software where ne_type='%s' and version='%s'", neTypeUpper, version) neSoftware, err := dborm.XormGetDataBySQL(sql) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return } else if len(*neSoftware) == 0 { err := global.ErrCMNotFoundTargetSoftware log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neSoftware:", neSoftware) sql = fmt.Sprintf("select * from ne_version where ne_type='%s' and ne_id='%s'", neTypeUpper, neId) neVersion, err := dborm.XormGetDataBySQL(sql) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neVersion:", neVersion) sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip) mkdirCmd := fmt.Sprintf("sudo mkdir -p %s/software/%s", config.GetYamlConfig().NE.OmcDir, neTypeLower) cmd := exec.Command("ssh", sshHost, mkdirCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to mkdir:", err) services.ResponseInternalServerError500ProcessError(w, err) return } fileName := (*neSoftware)[0]["file_name"] path := (*neSoftware)[0]["path"] srcFile := fmt.Sprintf("%s/%s", path, fileName) scpDir := fmt.Sprintf("%s@%s:%s", config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.ScpDir) cmd = exec.Command("scp", "-r", srcFile, scpDir) out, err = cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip) services.ResponseInternalServerError500ProcessError(w, err) return } neFilePath := config.GetYamlConfig().NE.ScpDir + "/" + fileName cpCmd := fmt.Sprintf("sudo mv -f %s %s/software/%s", neFilePath, config.GetYamlConfig().NE.OmcDir, neTypeLower) cmd = exec.Command("ssh", sshHost, cpCmd) out, err = cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute cp command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } if len(*neVersion) == 0 { neVersionData := dborm.NeVersion{ NeType: neTypeUpper, NeId: neInfo.NeId, Version: (*neSoftware)[0]["version"], FilePath: fmt.Sprintf("%s/software/%s/%s", config.GetYamlConfig().NE.OmcDir, neTypeLower, fileName), PreVersion: "", PreFile: "", Status: SoftwareStatusInactive, } _, err = dborm.XormInsertTableOne("ne_version", neVersionData) if err != nil { log.Error("Faile to XormInsertTableOne:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } else { idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"]) neVersionData := dborm.NeVersion{ NeType: neTypeUpper, NeId: neInfo.NeId, Version: (*neSoftware)[0]["version"], FilePath: fmt.Sprintf("%s/software/%s/%s", config.GetYamlConfig().NE.OmcDir, neTypeLower, fileName), PreVersion: (*neVersion)[0]["version"], PreFile: (*neVersion)[0]["file_path"], Status: SoftwareStatusInactive, } _, err = dborm.XormUpdateTableById(idNeVersion, "ne_version", neVersionData) if err != nil { log.Error("Faile to UpdateTableById:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } services.ResponseStatusOK204NoContent(w) } func ActiveSoftwareToNF(w http.ResponseWriter, r *http.Request) { log.Debug("ActiveSoftwareToNF processing... ") _, err := services.CheckFrontValidRequest(w, r) if err != nil { log.Error("Http request error:", err) return } vars := mux.Vars(r) neType := vars["neType"] if neType == "" { log.Error("neType is empty") services.ResponseNotFound404UriNotExist(w, r) return } neTypeUpper := strings.ToUpper(neType) neTypeLower := strings.ToLower(neType) version := vars["version"] if version == "" { log.Error("version is empty") services.ResponseNotFound404UriNotExist(w, r) return } neId := vars["neId"] if version == "" { log.Error("neId is empty") services.ResponseNotFound404UriNotExist(w, r) return } neInfo, err := dborm.XormGetNeInfo(neTypeUpper, neId) if err != nil { log.Error("dborm.XormGetNeInfo is failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } sql := fmt.Sprintf("select * from ne_software where ne_type='%s' and version='%s'", neTypeUpper, version) neSoftware, err := dborm.XormGetDataBySQL(sql) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return } else if len(*neSoftware) == 0 { err := global.ErrCMNotFoundTargetSoftware log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neVersion:", neSoftware) sql = fmt.Sprintf("select * from ne_version where ne_type='%s' and ne_id='%s' and version='%s'", neTypeUpper, neId, version) neVersion, err := dborm.XormGetDataBySQL(sql) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return } else if len(*neVersion) == 0 { err := global.ErrCMNotFoundTargetNeVersion log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neVersion:", neVersion) if !config.GetYamlConfig().OMC.TestMode { filePath := (*neVersion)[0]["file_path"] sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip) fileType := global.IsRpmOrDebPackage(filePath) if fileType == 1 { rpmCmd := fmt.Sprintf("sudo rpm -Uvh '%s'", filePath) cmd := exec.Command("ssh", sshHost, rpmCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute rpm command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } else if fileType == 2 { dpkgCmd := fmt.Sprintf("sudo dpkg -i --force-all '%s'", filePath) cmd := exec.Command("ssh", sshHost, dpkgCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute dpkg command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } else { err := global.ErrCMUnknownSoftwareFormat log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } switch neTypeLower { case "omc": restartCmd := fmt.Sprintf("sudo %s/bin/omcsvc.sh restart", config.GetYamlConfig().NE.OmcDir) cmd := exec.Command("ssh", sshHost, restartCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute ssh restart omc:", err) services.ResponseInternalServerError500ProcessError(w, err) return } case "ims": restartCmd := "sudo ims-stop && sudo ims-start" cmd := exec.Command("ssh", sshHost, restartCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute ssh sudo systemctl command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } default: restartCmd := fmt.Sprintf("sudo systemctl restart %s.service", neTypeLower) cmd := exec.Command("ssh", sshHost, restartCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute ssh sudo systemctl command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } } idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"]) neVersionData := dborm.NeVersion{ Status: SoftwareStatusActive, } _, err = dborm.XormUpdateTableById(idNeVersion, "ne_version", neVersionData) if err != nil { log.Error("Faile to UpdateTableById:", err) services.ResponseInternalServerError500ProcessError(w, err) return } services.ResponseStatusOK204NoContent(w) } func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) { log.Debug("ActiveSoftwareToNF processing... ") _, err := services.CheckFrontValidRequest(w, r) if err != nil { log.Error("Http request error:", err) return } vars := mux.Vars(r) neType := vars["neType"] if neType == "" { log.Error("neType is empty") services.ResponseNotFound404UriNotExist(w, r) return } neTypeUpper := strings.ToUpper(neType) neTypeLower := strings.ToLower(neType) version := vars["version"] if version == "" { log.Error("version is empty") services.ResponseNotFound404UriNotExist(w, r) return } neId := vars["neId"] if version == "" { log.Error("neId is empty") services.ResponseNotFound404UriNotExist(w, r) return } neInfo, err := dborm.XormGetNeInfo(neTypeUpper, neId) if err != nil { log.Error("dborm.XormGetNeInfo is failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } sql := fmt.Sprintf("select * from ne_version where ne_type='%s' and ne_id='%s'", neTypeUpper, neId) neVersion, err := dborm.XormGetDataBySQL(sql) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return } else if len(*neVersion) == 0 { err := global.ErrCMNotFoundTargetNeVersion log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neVersion:", neVersion) filePath := (*neVersion)[0]["pre_file"] if filePath == "" { err := global.ErrCMNotFoundRollbackNeVersion log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } if !config.GetYamlConfig().OMC.TestMode { sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip) fileType := global.IsRpmOrDebPackage(filePath) if fileType == 1 { rpmCmd := fmt.Sprintf("sudo rpm -Uvh --oldpackage '%s'", filePath) cmd := exec.Command("ssh", sshHost, rpmCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute rpm command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } else if fileType == 2 { dpkgCmd := fmt.Sprintf("sudo dpkg -i --force-all '%s'", filePath) cmd := exec.Command("ssh", sshHost, dpkgCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute dpkg command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } else { err := global.ErrCMUnknownSoftwareFormat log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } switch neTypeLower { case "omc": restartCmd := fmt.Sprintf("sudo %s/bin/omcsvc.sh restart", config.GetYamlConfig().NE.OmcDir) cmd := exec.Command("ssh", sshHost, restartCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute ssh restart omc:", err) services.ResponseInternalServerError500ProcessError(w, err) return } case "ims": restartCmd := "sudo ims-stop && sudo ims-start" cmd := exec.Command("ssh", sshHost, restartCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute ssh sudo systemctl command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } default: restartCmd := fmt.Sprintf("sudo systemctl restart %s.service", neTypeLower) cmd := exec.Command("ssh", sshHost, restartCmd) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { log.Error("Faile to execute ssh sudo systemctl command:", err) services.ResponseInternalServerError500ProcessError(w, err) return } } } idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"]) neVersionData := dborm.NeVersion{ Version: (*neVersion)[0]["pre_version"], FilePath: (*neVersion)[0]["pre_file"], PreVersion: "-", PreFile: "-", NewVersion: (*neVersion)[0]["version"], NewFile: (*neVersion)[0]["file_path"], Status: SoftwareStatusActive, } _, err = dborm.XormUpdateTableById(idNeVersion, "ne_version", neVersionData) if err != nil { log.Error("Faile to UpdateTableById:", err) services.ResponseInternalServerError500ProcessError(w, err) return } services.ResponseStatusOK204NoContent(w) }