Files
be.ems/features/cm/ne.go
2023-09-15 14:11:08 +08:00

686 lines
21 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package cm
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
"ems.agt/lib/dborm"
"ems.agt/lib/global"
"ems.agt/lib/log"
"ems.agt/lib/services"
"ems.agt/restagent/config"
"github.com/go-resty/resty/v2"
"github.com/gorilla/mux"
)
var (
UriParamOmcNeConfig = config.DefaultUriPrefix + "/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig"
// NE CM export/import
NeCmUri = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/cm"
// NE info
UriNeInfo = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/neInfo"
// NE backup file
UriNeCmFile = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{neType}/neBackup/{fileName}"
CustomUriParamOmcNeConfig = config.UriPrefix + "/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig"
CustomNeCmUri = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/cm"
CustomUriNeInfo = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/neInfo"
CustomUriNeCmFile = config.UriPrefix + "/systemManagement/{apiVersion}/{neType}/neBackup/{fileName}"
)
func init() {
}
func GetNeInfo(w http.ResponseWriter, r *http.Request) {
log.Debug("GetNeInfo processing... ")
_, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
// no, _ := strconv.ParseInt(neId, 10, 64)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Error("dborm.XormGetNeInfo is failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
var response services.DataResponse
response.Data = neInfo
services.ResponseWithJson(w, http.StatusOK, response)
}
type OmcNeConfig struct {
NeId string `json:"neId" xorm:"ne_id"` // 网元标识(内部),
RmUID string `json:"rmUID" xorm:"rm_uid"` // rmUID 网元唯一标识
NeName string `json:"neName" xorm:"ne_name"` // 网元名称(内部)/友好名称(北向资源/性能等使用)
PvFlag string `json:"pvFlag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理
Province string `json:"province" xorm:"province"` // 网元所在省份
VendorName string `json:"vendorName" xorm:"vendor_name"` // 厂商名称
// ManagedBy string `json:"managedBy" xorm:"managed_by"` // 管理ManagedElement的ManagementNode对象类的DN值
Dn string `json:"dn" xorm:"dn"` // 资源里边的ManagedBy性能的Dn网络唯一标识
}
func PostNeInfo(w http.ResponseWriter, r *http.Request) {
log.Debug("PostNeInfo processing... ")
_, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
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
}
log.Debug("Body:", string(body))
neInfo := new(dborm.NeInfo)
err = json.Unmarshal(body, neInfo)
if err != nil {
log.Error("Failed to json.Unmarshal:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
neInfo.UpdateTime = time.Now().Format(time.DateTime)
log.Debug("NE info:", neInfo)
hostUri := global.CombineHostUri(neInfo.Ip, neInfo.Port)
//hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
apiUri := fmt.Sprintf(UriParamOmcNeConfig, strings.ToLower(neInfo.NeType))
requestURI2NF := fmt.Sprintf("%s%s", hostUri, apiUri)
log.Debug("requestURI2NF:", requestURI2NF)
omcNeConfig := &OmcNeConfig{
NeId: neInfo.NeId,
RmUID: neInfo.RmUID,
NeName: neInfo.NeName,
PvFlag: neInfo.PvFlag,
Province: neInfo.Province,
VendorName: neInfo.VendorName,
Dn: neInfo.Dn,
}
body, _ = json.Marshal(omcNeConfig)
client := resty.New()
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
SetBody(body).
Put(requestURI2NF)
if err != nil {
log.Error("Failed to Put:", err)
services.ResponseInternalServerError500NFConnectRefused(w)
return
}
log.Info("StatusCode: ", response.StatusCode())
if config.GetYamlConfig().OMC.Chk2Ne == false {
affected, err := dborm.XormInsertNeInfo(neInfo)
if err != nil {
log.Error("Failed to insert Ne info:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
return
} else {
respMsg := make(map[string]interface{})
switch response.StatusCode() {
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
affected, err := dborm.XormInsertNeInfo(neInfo)
if err != nil {
log.Error("Failed to dborm.XormInsertNeInfo:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
} else if affected <= 0 {
log.Infof("Not record affected to insert ne_info")
}
services.ResponseStatusOK204NoContent(w)
return
default:
log.Info("response body:", string(response.Body()))
body := new(map[string]interface{})
_ = json.Unmarshal(response.Body(), &body)
respMsg["error"] = body
}
services.ResponseWithJson(w, response.StatusCode(), respMsg)
return
}
}
func PutNeInfo(w http.ResponseWriter, r *http.Request) {
log.Debug("PutNeInfo processing... ")
_, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
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
}
neInfo := new(dborm.NeInfo)
_ = json.Unmarshal(body, neInfo)
neInfo.NeType = strings.ToUpper(neType)
neInfo.UpdateTime = time.Now().Format(time.DateTime)
log.Debug("NE info:", neInfo)
hostUri := global.CombineHostUri(neInfo.Ip, neInfo.Port)
//hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
apiUri := fmt.Sprintf(UriParamOmcNeConfig, strings.ToLower(neType))
requestURI2NF := fmt.Sprintf("%s%s", hostUri, apiUri)
log.Debug("requestURI2NF:", requestURI2NF)
omcNeConfig := &OmcNeConfig{
NeId: neInfo.NeId,
RmUID: neInfo.RmUID,
NeName: neInfo.NeName,
PvFlag: neInfo.PvFlag,
Province: neInfo.Province,
VendorName: neInfo.VendorName,
Dn: neInfo.Dn,
}
body, _ = json.Marshal(omcNeConfig)
client := resty.New()
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
SetBody(body).
Put(requestURI2NF)
if err != nil {
log.Error("Failed to Put:", err)
services.ResponseInternalServerError500NFConnectRefused(w)
return
}
log.Info("StatusCode: ", response.StatusCode())
if config.GetYamlConfig().OMC.Chk2Ne == false {
affected, err := dborm.XormUpdateNeInfo(neInfo)
if err != nil {
log.Error("Failed to update Ne info:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
return
} else {
respMsg := make(map[string]interface{})
switch response.StatusCode() {
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
affected, err := dborm.XormUpdateNeInfo(neInfo)
if err != nil {
log.Error("Failed to dborm.XormUpdateNeInfo:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
} else if affected <= 0 {
log.Infof("Not record affected to insert ne_info")
}
services.ResponseStatusOK204NoContent(w)
return
default:
log.Info("response body:", string(response.Body()))
body := new(map[string]interface{})
_ = json.Unmarshal(response.Body(), &body)
respMsg["error"] = body
}
services.ResponseWithJson(w, response.StatusCode(), respMsg)
return
}
}
func DeleteNeInfo(w http.ResponseWriter, r *http.Request) {
log.Debug("DeleteNeInfo processing... ")
_, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
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
}
neInfo := new(dborm.NeInfo)
_ = json.Unmarshal(body, neInfo)
neInfo.NeType = strings.ToUpper(neType)
neInfo.NeId = services.GetUriParamString(r, "ne_id", ",", false, false)
neInfo, err = dborm.XormGetNeInfo(neInfo.NeType, neInfo.NeId)
if err != nil || neInfo == nil {
log.Error("Failed to delete Ne info:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
log.Debug("NE info:", neInfo)
// if NE in active status, can't delete NE
if IsActiveNF(neInfo) == false {
affected, err := dborm.XormDeleteNeInfo(neInfo)
if err != nil {
log.Error("Failed to delete Ne info:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
return
}
err = global.ErrCMCannotDeleteActiveNE
log.Error(err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
func IsActiveNF(neInfo *dborm.NeInfo) bool {
log.Debug("IsActiveNF processing... ")
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
requestURI := fmt.Sprintf(config.UriPrefix+"/systemManagement/v1/elementType/%s/objectType/systemState",
strings.ToLower(neInfo.NeType))
client := resty.New()
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(hostUri + requestURI)
if err != nil {
log.Error("Failed to Get:", err)
}
switch response.StatusCode() {
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
return true
}
return false
}
func ExportCmFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("ExportCmFromNF processing... ")
_, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("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)
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
// neInfo := new(dborm.NeInfo)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Errorf("Failed to get ne_info:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
log.Debug("neInfo:", neInfo)
nePath := fmt.Sprintf("%s/etc/%s", config.GetYamlConfig().OMC.Backup, neTypeLower)
isExist, err := global.PathExists(nePath)
if err != nil {
log.Errorf("Failed to stat:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
if isExist {
err = os.RemoveAll(nePath)
if err != nil {
log.Errorf("Failed to RemoveAll:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
}
err = os.MkdirAll(nePath, os.ModePerm)
if err != nil {
log.Errorf("Failed to MkdirAll:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
var scpCmd string
ipType := global.ParseIPAddr(neInfo.Ip)
if ipType == global.IsIPv4 {
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/%s/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
} else {
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/%s/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
}
zipFile := fmt.Sprintf("%s-%s-etc-%s.zip", neTypeLower, strings.ToLower(neInfo.NeId), time.Now().Format(global.DateData))
zipCmd := fmt.Sprintf("cd %s && zip -r %s etc/%s/*", config.GetYamlConfig().OMC.Backup, zipFile, neTypeLower)
command := fmt.Sprintf("%s&&%s", scpCmd, zipCmd)
log.Debug("command:", command)
err = ExecCmd(command)
if err != nil {
log.Error("Faile to exec command:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
zipFilePath := fmt.Sprintf("%s/%s", config.GetYamlConfig().OMC.Backup, zipFile)
md5Sum, err := global.GetFileMD5Sum(zipFilePath)
if err != nil {
log.Error("Faile to md5sum:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
//log.Debug("md5Str:", md5Sum)
path := config.GetYamlConfig().OMC.Backup
neBackup := dborm.NeBackup{NeType: neTypeUpper, NeId: neId, FileName: zipFile, Path: path, Md5Sum: md5Sum}
_, err = dborm.XormInsertTableOne("ne_backup", neBackup)
if err != nil {
log.Error("Faile to XormInsertTableOne:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
//services.ResponseFileWithNameAndMD5(w, http.StatusOK, zipFile, path, md5Sum)
services.ResponseStatusOK204NoContent(w)
return
}
type ImportCMJson struct {
FileName string `json:"fileName"`
}
func ImportCmToNF(w http.ResponseWriter, r *http.Request) {
log.Debug("ImportCmToNF processing... ")
_, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("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)
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
var fileName, path string
if services.IsJsonContentType(r) {
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
}
log.Debug("Body:", string(body))
importCMJson := new(ImportCMJson)
_ = json.Unmarshal(body, importCMJson)
fileName = importCMJson.FileName
path = config.GetYamlConfig().OMC.Backup
} else {
path = config.GetYamlConfig().OMC.Upload
fileName, err = services.HandleUploadFile(r, path, "")
if err != nil {
log.Error("Faile to HandleUploadFile:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
}
filePath := fmt.Sprintf("%s/%s", path, fileName)
// neInfo := new(dborm.NeInfo)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Errorf("Failed to get ne_info:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
log.Debug("neInfo:", neInfo)
md5Sum, err := global.GetFileMD5Sum(filePath)
if err != nil {
log.Error("Faile to GetFileMD5Sum:", 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 ne_id='%s' and md5_sum='%s'", neTypeUpper, neId, md5Sum)
has, err := dborm.XormExistTableOne("ne_backup", where)
if err != nil {
log.Error("Faile to XormInsertTableOne:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else if has == false {
err = global.ErrCMInvalidBackupFile
log.Error(err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
nePath := fmt.Sprintf("%s/etc/%s", config.GetYamlConfig().OMC.Upload, neTypeLower)
isExist, err := global.PathExists(nePath)
if err != nil {
log.Errorf("Failed to stat:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
if isExist {
err = os.RemoveAll(nePath)
if err != nil {
log.Errorf("Failed to remove:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
}
unzipCmd := fmt.Sprintf("unzip -o %s -d %s", filePath, config.GetYamlConfig().OMC.Upload)
var scpCmd string
ipType := global.ParseIPAddr(neInfo.Ip)
if ipType == global.IsIPv4 {
scpCmd = fmt.Sprintf("scp -r %s/etc/%s %s@%s:%s", config.GetYamlConfig().OMC.Upload,
neTypeLower, config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.EtcDir)
} else {
scpCmd = fmt.Sprintf("scp -r %s/etc/%s %s@[%s]:%s", config.GetYamlConfig().OMC.Upload,
neTypeLower, config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.EtcDir)
}
err = ExecCmd(fmt.Sprintf("%s && %s", unzipCmd, scpCmd))
if err != nil {
log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
services.ResponseStatusOK204NoContent(w)
}
func DownloadNeBackupFile(w http.ResponseWriter, r *http.Request) {
log.Debug("DownloadNeBackupFile 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)
fileName := vars["fileName"]
if fileName == "" {
log.Error("fileName is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
sql := fmt.Sprintf("select * from ne_backup where ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
neBackup, err := dborm.XormGetDataBySQL(sql)
if err != nil {
log.Error("Faile to XormGetDataBySQL:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else if len(*neBackup) == 0 {
err := global.ErrCMNotFoundTargetBackupFile
log.Error(err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
path := (*neBackup)[0]["path"]
md5Sum := (*neBackup)[0]["md5_sum"]
services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, md5Sum)
return
}
func DeleteNeBackupFile(w http.ResponseWriter, r *http.Request) {
log.Debug("DeleteNeBackupFile 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)
fileName := vars["fileName"]
if fileName == "" {
log.Error("fileName is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
sql := fmt.Sprintf("select * from ne_backup where ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
neBackup, err := dborm.XormGetDataBySQL(sql)
if err != nil {
log.Error("Faile to XormGetDataBySQL:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else if len(*neBackup) == 0 {
err := global.ErrCMNotFoundTargetBackupFile
log.Error(err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
where := fmt.Sprintf("ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
affected, err := dborm.XormDeleteDataByWhere(where, "ne_backup")
if err != nil || affected == 0 {
log.Error("Faile to XormGetDataBySQL:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
path := (*neBackup)[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)
return
}