This commit is contained in:
2023-10-11 10:24:33 +08:00
parent 08b3a775f1
commit c6962cf537
5 changed files with 216 additions and 22 deletions

1
.gitignore vendored
View File

@@ -22,6 +22,7 @@ restagent/log/
restagent/upload/
restagent/software/
restagent/database/
restagent/license/
restagent/restagent
sshsvc/sshsvc

View File

@@ -85,3 +85,9 @@ MODIFY COLUMN `timestamp` bigint NULL DEFAULT NULL AFTER `msg_direct`;
ALTER TABLE `omc_db`.`param_config`
MODIFY COLUMN `method` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'method allow: \"get\", \"get,post,put\", \"delete\"' AFTER `top_display`;
ALTER TABLE `omc_db`.`ne_license`
MODIFY COLUMN `status` enum('ACTIVE','INACTIVE','PENDING') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'ACTIVE' AFTER `expiration_date`,
ADD COLUMN IF NOT EXISTS `path` varchar(128) NULL AFTER `status`,
ADD COLUMN IF NOT EXISTS `file_name` varchar(64) NULL AFTER `path`,
ADD COLUMN IF NOT EXISTS `comment` varchar(255) NULL AFTER `file_name`;

View File

@@ -1,8 +1,14 @@
package cm
import (
"fmt"
"io"
"net/http"
"os"
"os/exec"
"strings"
"ems.agt/lib/dborm"
"ems.agt/lib/log"
"ems.agt/lib/services"
"ems.agt/restagent/config"
@@ -11,12 +17,12 @@ import (
)
var (
// License
LicenseUri = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{neType}/license"
NeLicenseUri = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{neType}/license/{neId}"
// General License URI
UriLicense = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{elementTypeValue}/license"
UriLicenseExt = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/license"
CustomLicenseUri = config.UriPrefix + "/systemManagement/{apiVersion}/{neType}/license"
CustomNeLicenseUri = config.UriPrefix + "/systemManagement/{apiVersion}/{neType}/license/{neId}"
CustomUriLicense = config.UriPrefix + "/systemManagement/{apiVersion}/{elementTypeValue}/license"
CustomUriLicenseExt = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/license"
)
func UploadLicenseFile(w http.ResponseWriter, r *http.Request) {
@@ -39,7 +45,6 @@ func UploadLicenseFile(w http.ResponseWriter, r *http.Request) {
// neTypeLower := strings.ToLower(neType)
services.ResponseStatusOK204NoContent(w)
return
}
func DownloadLicenseFile(w http.ResponseWriter, r *http.Request) {
@@ -86,7 +91,6 @@ func DownloadLicenseFile(w http.ResponseWriter, r *http.Request) {
// md5Sum := (*neSoftware)[0]["md5_sum"]
// services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, md5Sum)
return
}
func DeleteLcenseFile(w http.ResponseWriter, r *http.Request) {
@@ -147,5 +151,183 @@ func DeleteLcenseFile(w http.ResponseWriter, r *http.Request) {
// }
services.ResponseStatusOK204NoContent(w)
return
}
func UploadLicenseFileData(w http.ResponseWriter, r *http.Request) {
log.Info("UploadLicenseFileData processing... ")
_, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Http request error:", err)
return
}
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neTypeUpper := strings.ToUpper(neType)
neTypeLower := strings.ToLower(neType)
//md5Param := services.GetUriParamString(r, "md5Sum", ",", false, false)
neId := services.GetUriParamString(r, "neId", ",", false, false)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Errorf("Failed to get ne_info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Debug("neInfo:", neInfo)
licensePath := fmt.Sprintf("%s/%s", config.GetYamlConfig().OMC.License, neTypeLower)
err = os.MkdirAll(licensePath, 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(10 << 20) // 10MB
if err != nil {
log.Error("Faile to ParseMultipartForm:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 获取文件和数据
licFile := r.MultipartForm.File["file"]
data := r.MultipartForm.Value["comment"]
var licenseFileName, comment string
// 处理软件rpm/deb文件
if len(licFile) > 0 {
file := licFile[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(licensePath + "/" + file.Filename)
if err != nil {
log.Error("Faile to Create:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
defer dst.Close()
licenseFileName = 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]
}
neLicensePath := strings.ReplaceAll(config.GetYamlConfig().NE.LicenseDir, "{neType}", neTypeLower)
srcFile := fmt.Sprintf("%s/%s", licensePath, licenseFileName)
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
}
// backup system.ini to system.ini.bak
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
cpCmd := fmt.Sprintf("sudo cp -f %s/system.ini %s/system.ini.bak", neLicensePath, neLicensePath)
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
}
// replace system.ini
neFilePath := config.GetYamlConfig().NE.ScpDir + "/" + licenseFileName
cpCmd = fmt.Sprintf("sudo cp -f %s %s/system.ini", neFilePath, neLicensePath)
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
}
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
}
}
neLicense := dborm.NeLicense{
NeType: neTypeUpper,
NeID: neId,
Status: "ACTIVE",
Path: licensePath,
FileName: licenseFileName,
Comment: comment,
}
log.Debug("neLicense:", neLicense)
_, err = dborm.XormInsertTableOne("ne_license", neLicense)
if err != nil {
log.Error("Faile to XormInsertTableOne:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
services.ResponseStatusOK204NoContent(w)
}

View File

@@ -1630,9 +1630,20 @@ func IsPermissionAllowed(token, method, module, dbname, tbname, pack string) (bo
}
type NeLicense struct {
NeType string `json:"neType" xorm:"ne_type"`
NeID string `json:"neID" xorm:"ne_id"`
Capability int `json:"capability"`
NeType string `json:"neType" xorm:"ne_type"`
NeID string `json:"neID" xorm:"ne_id"`
SerialNo string `json:"serialNo" xorm:"serial_no"`
Capcity int `json:"capcity" xorm:"capcity"`
Used int `json:"used" xorm:"used"`
FeatureEnabled string `json:"featureEnabled" xorm:"feature_enabled"`
ExpirationDate string `json:"expirationDate" xorm:"expiration_date"`
Status string `json:"status" xorm:"status"`
Path string `json:"path" xorm:"path"`
FileName string `json:"file_name" xorm:"file_name"`
Comment string `json:"comment" xorm:"comment"`
CreatedAt string `json:"createdAt" xorm:"-"`
UpdatedAt string `json:"updatedAt" xorm:"-"`
DeletedAt string `json:"deletedAt" xorm:"-"`
}
func XormAdjustmentNeLicense(neType, neID string, value int) (int64, error) {

View File

@@ -220,17 +220,11 @@ func init() {
Register("PATCH", cm.CustomUriSoftwareNE, cm.RollBackSoftwareToNF, nil)
// License management
Register("GET", cm.LicenseUri, cm.ExportCmFromNF, nil)
Register("POST", cm.LicenseUri, cm.ImportCmToNF, nil)
Register("DELETE", cm.LicenseUri, cm.ImportCmToNF, nil)
Register("POST", cm.UriLicense, cm.UploadLicenseFileData, nil)
Register("POST", cm.UriLicenseExt, cm.UploadLicenseFileData, nil)
Register("POST", cm.NeLicenseUri, cm.ExportCmFromNF, nil)
Register("PUT", cm.NeLicenseUri, cm.ImportCmToNF, nil)
Register("PATCH", cm.NeLicenseUri, cm.ImportCmToNF, nil)
Register("POST", cm.CustomNeLicenseUri, cm.ExportCmFromNF, nil)
Register("PUT", cm.CustomNeLicenseUri, cm.ImportCmToNF, nil)
Register("PATCH", cm.CustomNeLicenseUri, cm.ImportCmToNF, nil)
Register("POST", cm.CustomUriLicense, cm.UploadLicenseFileData, nil)
Register("POST", cm.CustomUriLicenseExt, cm.UploadLicenseFileData, nil)
// Trace management
Register("POST", trace.UriTraceTask, trace.PostTraceTaskToNF, nil)