diff --git a/features/cm/ne.go b/features/cm/ne.go index 300a88a..a92b935 100644 --- a/features/cm/ne.go +++ b/features/cm/ne.go @@ -43,8 +43,28 @@ var ( CustomUriNeInstance = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/instance/{action}" ) -func init() { +const ( + NEStatusActive = 0 + NEStatusOffline = 1 + NEStatusStandby = 2 + NEStatusMaintain = 3 +) +var client = resty.New() + +func init() { + /* + client. + SetTimeout(10 * time.Second). + SetRetryCount(1). + SetRetryWaitTime(1 * time.Second). + SetRetryMaxWaitTime(2 * time.Second). + SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) { + return 0, errors.New("quota exceeded") + }) + */ + client. + SetTimeout(time.Duration(1 * time.Second)) } func GetNeInfo(w http.ResponseWriter, r *http.Request) { @@ -69,7 +89,7 @@ func GetNeInfo(w http.ResponseWriter, r *http.Request) { neInfo, err := dborm.XormGetNeInfo(neType, neId) if err != nil { log.Error("dborm.XormGetNeInfo is failed:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } @@ -105,9 +125,10 @@ func PostNeInfo(w http.ResponseWriter, r *http.Request) { services.ResponseNotFound404UriNotExist(w, r) return } + syncFlag := services.GetUriParamString(r, "sync2ne", ",", false, false) body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) if err != nil { - log.Error("io.ReadAll is failed:", err) + log.Error("Failed to o.ReadAll:", err) services.ResponseNotFound404UriNotExist(w, r) return } @@ -123,41 +144,13 @@ func PostNeInfo(w http.ResponseWriter, r *http.Request) { 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 { + //if !config.GetYamlConfig().OMC.Chk2Ne { + if syncFlag == "false" { + neInfo.Status = NEStatusMaintain affected, err := dborm.XormInsertNeInfo(neInfo) if err != nil { log.Error("Failed to insert Ne info:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } @@ -167,13 +160,43 @@ func PostNeInfo(w http.ResponseWriter, r *http.Request) { services.ResponseWithJson(w, http.StatusOK, mapRow) return } else { + 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) + 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.ResponseInternalServerError500ProcessError(w, err) + return + } + log.Info("StatusCode: ", response.StatusCode()) + respMsg := make(map[string]interface{}) switch response.StatusCode() { case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: + neInfo.Status = NEStatusActive affected, err := dborm.XormInsertNeInfo(neInfo) if err != nil { log.Error("Failed to dborm.XormInsertNeInfo:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } else if affected <= 0 { log.Infof("Not record affected to insert ne_info") @@ -208,9 +231,10 @@ func PutNeInfo(w http.ResponseWriter, r *http.Request) { services.ResponseNotFound404UriNotExist(w, r) return } + syncFlag := services.GetUriParamString(r, "sync2ne", ",", false, false) body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) if err != nil { - log.Error("io.ReadAll is failed:", err) + log.Error("Failed to io.ReadAll:", err) services.ResponseNotFound404UriNotExist(w, r) return } @@ -221,41 +245,13 @@ func PutNeInfo(w http.ResponseWriter, r *http.Request) { 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 { + //if !config.GetYamlConfig().OMC.Chk2Ne { + if syncFlag == "false" { + neInfo.Status = NEStatusMaintain affected, err := dborm.XormUpdateNeInfo(neInfo) if err != nil { log.Error("Failed to update Ne info:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } @@ -265,13 +261,43 @@ func PutNeInfo(w http.ResponseWriter, r *http.Request) { services.ResponseWithJson(w, http.StatusOK, mapRow) return } else { + 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) + 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.ResponseInternalServerError500ProcessError(w, err) + return + } + log.Info("StatusCode: ", response.StatusCode()) + respMsg := make(map[string]interface{}) switch response.StatusCode() { case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: + neInfo.Status = NEStatusActive affected, err := dborm.XormUpdateNeInfo(neInfo) if err != nil { log.Error("Failed to dborm.XormUpdateNeInfo:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } else if affected <= 0 { log.Infof("Not record affected to insert ne_info") @@ -321,7 +347,7 @@ func DeleteNeInfo(w http.ResponseWriter, r *http.Request) { neInfo, err = dborm.XormGetNeInfo(neInfo.NeType, neInfo.NeId) if err != nil || neInfo == nil { log.Error("Failed to delete Ne info:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("NE info:", neInfo) @@ -331,7 +357,7 @@ func DeleteNeInfo(w http.ResponseWriter, r *http.Request) { affected, err := dborm.XormDeleteNeInfo(neInfo) if err != nil { log.Error("Failed to delete Ne info:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } @@ -353,7 +379,6 @@ func IsActiveNF(neInfo *dborm.NeInfo) bool { 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()}). @@ -361,6 +386,7 @@ func IsActiveNF(neInfo *dborm.NeInfo) bool { Get(hostUri + requestURI) if err != nil { log.Error("Failed to Get:", err) + return false } switch response.StatusCode() { @@ -395,7 +421,7 @@ func ExportCmFromNF(w http.ResponseWriter, r *http.Request) { neInfo, err := dborm.XormGetNeInfo(neType, neId) if err != nil { log.Errorf("Failed to get ne_info:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neInfo:", neInfo) @@ -561,7 +587,7 @@ func ImportCmToNF(w http.ResponseWriter, r *http.Request) { neInfo, err := dborm.XormGetNeInfo(neType, neId) if err != nil { log.Errorf("Failed to get ne_info:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neInfo:", neInfo) @@ -802,7 +828,7 @@ func PostNeServiceAction(w http.ResponseWriter, r *http.Request) { neInfo, err := dborm.XormGetNeInfo(neType, neId) if err != nil { log.Error("Failed to get ne_info:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neInfo:", neInfo) @@ -888,7 +914,7 @@ func PostNeInstanceAction(w http.ResponseWriter, r *http.Request) { neInfo, err := dborm.XormGetNeInfo(neType, neId) if err != nil { log.Errorf("Failed to get ne_info:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) + services.ResponseInternalServerError500ProcessError(w, err) return } log.Debug("neInfo:", neInfo) diff --git a/features/cm/software.go b/features/cm/software.go index 535a0fe..34bb73a 100644 --- a/features/cm/software.go +++ b/features/cm/software.go @@ -225,7 +225,7 @@ func UploadSoftwareMultiFile(w http.ResponseWriter, r *http.Request) { //fileName, err := services.HandleUploadFile(r, softwarePath, "") // 解析multipart/form-data请求 - err = r.ParseMultipartForm(200 << 20) // 200MB + err = r.ParseMultipartForm(1000 << 20) // 1000MB if err != nil { log.Error("Faile to ParseMultipartForm:", err) services.ResponseInternalServerError500ProcessError(w, err) diff --git a/features/fm/alarm.go b/features/fm/alarm.go index e1ad6c0..06be5fe 100644 --- a/features/fm/alarm.go +++ b/features/fm/alarm.go @@ -23,8 +23,10 @@ import ( ) const ( - AlarmStatusClear = 0 - AlarmStatusActive = 1 + AlarmStatusClear = 0 + AlarmStatusActive = 1 + AlarmStatusClearString = "0" + AlarmStatusActiveString = "1" ) const ( diff --git a/features/mml/mml.go b/features/mml/mml.go index eeb1004..841b7fa 100644 --- a/features/mml/mml.go +++ b/features/mml/mml.go @@ -264,6 +264,80 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) { // mmlResult = append(mmlResult, "COMMAND OK\n") } case "ims": + hostMML := fmt.Sprintf("%s:%d", neInfo.Ip, config.GetYamlConfig().MML.Port) + conn, err := net.Dial("tcp", hostMML) + if err != nil { + errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err) + log.Error(errMsg) + mmlResult = append(mmlResult, errMsg) + response := Response{mmlResult} + services.ResponseWithJson(w, http.StatusOK, response) + return + } + defer conn.Close() + + // localAddr := conn.LocalAddr() + // remoteAddr := conn.RemoteAddr() + // if localAddr == nil || remoteAddr == nil { + // errMsg := fmt.Sprintf("connect invalid: localAddr=%v, remoteAddr=%v", localAddr, remoteAddr) + // log.Error(errMsg) + // mmlResult = append(mmlResult, errMsg) + // response := Response{mmlResult} + // services.ResponseWithJson(w, http.StatusOK, response) + // return + // } + conn.SetDeadline(time.Now().Add(10 * time.Second)) + + _, err = conn.Write([]byte(config.GetYamlConfig().MML.User + "\r\n")) + if err != nil { + log.Error("Failed to write:", err) + mmlResult = append(mmlResult, err.Error()) + response := Response{mmlResult} + services.ResponseWithJson(w, http.StatusOK, response) + return + } + time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE) + + n, err = conn.Read(buf[0:]) + if err != nil { + log.Error("Failed to read:", err) + mmlResult = append(mmlResult, err.Error()) + response := Response{mmlResult} + services.ResponseWithJson(w, http.StatusOK, response) + return + } + log.Debug(string(buf[0:n])) + + _, err = conn.Write([]byte(config.GetYamlConfig().MML.Password + "\r\n")) + if err != nil { + log.Error("Failed to write:", err) + mmlResult = append(mmlResult, err.Error()) + response := Response{mmlResult} + services.ResponseWithJson(w, http.StatusOK, response) + return + } + time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE) + + // loginStr := fmt.Sprintf("%s\r\n%s\r\n", config.GetYamlConfig().MML.User, config.GetYamlConfig().MML.Password) + // _, err = conn.Write([]byte(loginStr)) + // if err != nil { + // log.Error("Failed to write:", err) + // mmlResult = append(mmlResult, err.Error()) + // response := Response{mmlResult} + // services.ResponseWithJson(w, http.StatusOK, response) + // return + // } + // time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE) + + n, err = conn.Read(buf[0:]) + if err != nil { + log.Error("Failed to read:", err) + mmlResult = append(mmlResult, err.Error()) + response := Response{mmlResult} + services.ResponseWithJson(w, http.StatusOK, response) + return + } + log.Trace(string(buf[0 : n-len(neType)-2])) body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) if err != nil { log.Error("io.ReadAll is failed:", err) @@ -276,81 +350,7 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) { _ = json.Unmarshal(body, mmlRequest) for _, mml := range mmlRequest.MML { - hostMML := fmt.Sprintf("%s:%d", neInfo.Ip, config.GetYamlConfig().MML.Port) - conn, err := net.Dial("tcp", hostMML) - if err != nil { - errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err) - log.Error(errMsg) - mmlResult = append(mmlResult, errMsg) - response := Response{mmlResult} - services.ResponseWithJson(w, http.StatusOK, response) - return - } - defer conn.Close() - - // localAddr := conn.LocalAddr() - // remoteAddr := conn.RemoteAddr() - // if localAddr == nil || remoteAddr == nil { - // errMsg := fmt.Sprintf("connect invalid: localAddr=%v, remoteAddr=%v", localAddr, remoteAddr) - // log.Error(errMsg) - // mmlResult = append(mmlResult, errMsg) - // response := Response{mmlResult} - // services.ResponseWithJson(w, http.StatusOK, response) - // return - // } - conn.SetDeadline(time.Now().Add(10 * time.Second)) - - _, err = conn.Write([]byte(config.GetYamlConfig().MML.User + "\n")) - if err != nil { - log.Error("Failed to write:", err) - mmlResult = append(mmlResult, err.Error()) - response := Response{mmlResult} - services.ResponseWithJson(w, http.StatusOK, response) - return - } - time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE) - - n, err = conn.Read(buf[0:]) - if err != nil { - log.Error("Failed to read:", err) - mmlResult = append(mmlResult, err.Error()) - response := Response{mmlResult} - services.ResponseWithJson(w, http.StatusOK, response) - return - } - log.Debug(string(buf[0:n])) - - _, err = conn.Write([]byte(config.GetYamlConfig().MML.Password + "\n")) - if err != nil { - log.Error("Failed to write:", err) - mmlResult = append(mmlResult, err.Error()) - response := Response{mmlResult} - services.ResponseWithJson(w, http.StatusOK, response) - return - } - time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE) - - // loginStr := fmt.Sprintf("%s\n%s\n", config.GetYamlConfig().MML.User, config.GetYamlConfig().MML.Password) - // _, err = conn.Write([]byte(loginStr)) - // if err != nil { - // log.Error("Failed to write:", err) - // mmlResult = append(mmlResult, err.Error()) - // response := Response{mmlResult} - // services.ResponseWithJson(w, http.StatusOK, response) - // return - // } - - n, err = conn.Read(buf[0:]) - if err != nil { - log.Error("Failed to read:", err) - mmlResult = append(mmlResult, err.Error()) - response := Response{mmlResult} - services.ResponseWithJson(w, http.StatusOK, response) - return - } - log.Trace(string(buf[0 : n-len(neType)-2])) - - mmlCommand := fmt.Sprintf("%s\n", mml) + mmlCommand := fmt.Sprintf("%s\r\n", mml) log.Debug("mml command:", mmlCommand) _, err = conn.Write([]byte(mmlCommand)) if err != nil { @@ -377,11 +377,9 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) { re2 := regexp.MustCompile(`[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x1B]`) // 匹配空字符和包含␛的控制字符 //re := regexp.MustCompile(`[\x00-\x1F\x7F]`) // upf telnet buffer只能读取一次,需要去掉前面的多余字符 - //result := re1.ReplaceAllString(string(buf[0:n-len(neType)-2]), "") - result := re1.ReplaceAllString(string(buf[0:]), "") + result := re1.ReplaceAllString(string(buf[0:n-len(neType)-2]), "") result = re2.ReplaceAllString(result, "") mmlResult = append(mmlResult, result) - conn.Close() } default: hostMML := fmt.Sprintf("%s:%d", neInfo.Ip, config.GetYamlConfig().MML.Port) diff --git a/features/state/getstate.go b/features/state/getstate.go index 786c76e..8f3a937 100644 --- a/features/state/getstate.go +++ b/features/state/getstate.go @@ -154,7 +154,12 @@ func init() { return 0, errors.New("quota exceeded") }) */ - client.SetTimeout(3 * time.Second) + client. + SetTimeout(time.Duration(400 * time.Millisecond)) + // SetRetryCount(1). + // SetRetryWaitTime(time.Duration(1 * time.Second)). + // SetRetryMaxWaitTime(time.Duration(2 * time.Second)) + //client.SetTimeout(2 * time.Second) } func NeStatusEnumToStr(intStatus int) string { @@ -216,7 +221,7 @@ func GetOneLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { if neType != omcNeTypeLower { log.Debugf("r.RemoteAddr: %s omcNeTypeLower: %s", r.RemoteAddr, omcNeTypeLower) var requestURI2NF string - if config.GetYamlConfig().OMC.TestMode == true && strings.ToLower(neType) != "udm" { + if config.GetYamlConfig().OMC.TestMode && strings.ToLower(neType) != "udm" { var udmNEs []dborm.NeInfo err := dborm.XormGetNeInfoByNeType("UDM", &udmNEs) if err != nil { @@ -245,7 +250,7 @@ func GetOneLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). Get(requestURI2NF) if err != nil { - log.Error("Get system state from NF is failed:", err) + log.Error("Failed to get system state:", err) services.ResponseInternalServerError500ProcessError(w, err) return } else { @@ -266,6 +271,9 @@ func GetOneLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { } //neItem := strings.ToUpper(neType) + "/" + neId result, err = global.ToMap(*licenseInfo, "json") + if err != nil { + log.Warn("Failed to map:", err) + } } } else { systemState := GetEMSState(neInfo.Ip) @@ -279,6 +287,9 @@ func GetOneLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { ExpiryDate: systemState.ExpiryDate, } result, err = global.ToMap(*licenseInfo, "json") + if err != nil { + log.Warn("Failed to map:", err) + } // neItem := strings.ToUpper(neType) + "/" + neId // result[neItem] = sysInfo } @@ -306,6 +317,11 @@ func GetAllLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { var neList []dborm.NeInfo _, err = dborm.XormGetAllNeInfo(&neList) + if err != nil { + log.Error("Failed to XormGetAllNeInfo:", err) + services.ResponseInternalServerError500ProcessError(w, err) + return + } omcNeTypeLower := "omc" if config.GetYamlConfig().OMC.NeType != "" { omcNeTypeLower = strings.ToLower(config.GetYamlConfig().OMC.NeType) @@ -321,7 +337,7 @@ func GetAllLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { // requestURI2NF := fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState", // hostUri, strings.ToLower(ne.NeType)) var requestURI2NF string - if config.GetYamlConfig().OMC.TestMode == true && strings.ToLower(ne.NeType) != "udm" { + if config.GetYamlConfig().OMC.TestMode && strings.ToLower(ne.NeType) != "udm" { var udmNEs []dborm.NeInfo err := dborm.XormGetNeInfoByNeType("UDM", &udmNEs) if err != nil { @@ -342,7 +358,7 @@ func GetAllLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { } log.Debug("requestURI2NF:", requestURI2NF) - resp, err := client.R(). + resp, err := client.SetTimeout(time.Duration(1 * time.Second)).R(). EnableTrace(). SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). SetHeaders(map[string]string{"accessToken": token}). @@ -369,6 +385,9 @@ func GetAllLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { ExpiryDate: systemState.ExpiryDate, } result, err = global.ToMap(*licenseInfo, "json") + if err != nil { + log.Warn("Failed to map:", err) + } // neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId // result[neItem] = sysInfo } @@ -384,6 +403,9 @@ func GetAllLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { ExpiryDate: systemState.ExpiryDate, } result, err = global.ToMap(*licenseInfo, "json") + if err != nil { + log.Warn("Failed to map:", err) + } // neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId // result[neItem] = sysInfo } @@ -441,7 +463,7 @@ func GetOneSysinfoFromNF(w http.ResponseWriter, r *http.Request) { if neType != omcNeTypeLower { log.Debugf("r.RemoteAddr: %s omcNeTypeLower: %s", r.RemoteAddr, omcNeTypeLower) var requestURI2NF string - if config.GetYamlConfig().OMC.TestMode == true && strings.ToLower(neType) != "udm" { + if config.GetYamlConfig().OMC.TestMode && strings.ToLower(neType) != "udm" { var udmNEs []dborm.NeInfo err := dborm.XormGetNeInfoByNeType("UDM", &udmNEs) if err != nil { @@ -515,6 +537,9 @@ func GetOneSysinfoFromNF(w http.ResponseWriter, r *http.Request) { } //neItem := strings.ToUpper(neType) + "/" + neId result, err = global.ToMap(*sysInfo, "json") + if err != nil { + log.Warn("Failed to map:", err) + } } } else { systemState := GetEMSState(neInfo.Ip) @@ -533,6 +558,9 @@ func GetOneSysinfoFromNF(w http.ResponseWriter, r *http.Request) { Status: NeStatusEnumToStr(neInfo.Status), } result, err = global.ToMap(*sysInfo, "json") + if err != nil { + log.Warn("Failed to map:", err) + } // neItem := strings.ToUpper(neType) + "/" + neId // result[neItem] = sysInfo } @@ -560,6 +588,11 @@ func GetAllSysinfoFromNF(w http.ResponseWriter, r *http.Request) { var neList []dborm.NeInfo _, err = dborm.XormGetAllNeInfo(&neList) + if err != nil { + log.Error("Failed to XormGetAllNeInfo:", err) + services.ResponseInternalServerError500ProcessError(w, err) + return + } omcNeTypeLower := "omc" if config.GetYamlConfig().OMC.NeType != "" { omcNeTypeLower = strings.ToLower(config.GetYamlConfig().OMC.NeType) @@ -575,7 +608,7 @@ func GetAllSysinfoFromNF(w http.ResponseWriter, r *http.Request) { // requestURI2NF := fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState", // hostUri, strings.ToLower(ne.NeType)) var requestURI2NF string - if config.GetYamlConfig().OMC.TestMode == true && strings.ToLower(ne.NeType) != "udm" { + if config.GetYamlConfig().OMC.TestMode && strings.ToLower(ne.NeType) != "udm" { var udmNEs []dborm.NeInfo err := dborm.XormGetNeInfoByNeType("UDM", &udmNEs) if err != nil { @@ -596,7 +629,7 @@ func GetAllSysinfoFromNF(w http.ResponseWriter, r *http.Request) { } log.Debug("requestURI2NF:", requestURI2NF) - resp, err := client.R(). + resp, err := client.SetTimeout(time.Duration(1 * time.Second)).R(). EnableTrace(). SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). SetHeaders(map[string]string{"accessToken": token}). @@ -651,6 +684,9 @@ func GetAllSysinfoFromNF(w http.ResponseWriter, r *http.Request) { // neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId // result[neItem] = sysInfo result, err = global.ToMap(*sysInfo, "json") + if err != nil { + log.Warn("Failed to map:", err) + } } } else { port, _ := strconv.Atoi(ne.Port) @@ -672,6 +708,9 @@ func GetAllSysinfoFromNF(w http.ResponseWriter, r *http.Request) { // neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId // result[neItem] = sysInfo result, err = global.ToMap(*sysInfo, "json") + if err != nil { + log.Warn("Failed to map:", err) + } } data = append(data, result) @@ -785,6 +824,9 @@ func GetStateFromNF(w http.ResponseWriter, r *http.Request) { ErrorCode: "1", ErrorInfo: "Internal server error, NF connnect refused", } result["error"] = errorMessage + SN, Version, _ := dborm.XormGetNEStateInfo(ne.NeType, ne.NeId) + result["serialNum"] = SN + result["version"] = Version } else { systemState := make(map[string]interface{}) _ = json.Unmarshal(resp.Body(), &systemState) diff --git a/features/ue/ue.go b/features/ue/ue.go index 164a605..fb20dcd 100644 --- a/features/ue/ue.go +++ b/features/ue/ue.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/http" + "strings" "time" "ems.agt/lib/dborm" @@ -79,6 +80,8 @@ var ( UriPCFUserM = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/batch/{number}" UriPCFUserFileImport = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/file/import" UriPCFUserFileExport = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/file/export" + UriNSSFAvailableAMFs = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/availableAMFs" + UriNSSFSubscriptions = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/subscriptions" CustomUriNBInfo = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/nbInfo" CustomUriUEInfo = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueInfo" @@ -87,6 +90,8 @@ var ( CustomUriPCFUserM = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/batch/{number}" CustomUriPCFUserFileImport = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/file/import" CustomUriPCFUserFileExport = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/file/export" + CustomUriNSSFAvailableAMFs = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/availableAMFs" + CustomUriNSSFSubscriptions = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/subscriptions" ) var client = resty.New() @@ -105,6 +110,134 @@ func init() { client.SetTimeout(3 * time.Second) } +// Get AvailableAMFs from NSSF +func GetAvailableAMFsFromNSSF(w http.ResponseWriter, r *http.Request) { + log.Info("GetAvailableAMFsFromNSSF processing... ") + + vars := mux.Vars(r) + neType := vars["elementTypeValue"] + if strings.ToLower(neType) != "nssf" { + services.ResponseNotFound404UriNotExist(w, r) + return + } + //neTypeLower := strings.ToLower(neType) + var neId string + neIds := services.GetParamsArrByName("neId", r) + if len(neIds) == 1 { + neId = neIds[0] + } else { + services.ResponseNotFound404UriNotExist(w, r) + return + } + + token, err := services.CheckFrontValidRequest(w, r) + if err != nil { + log.Error("Request error:", err) + return + } + log.Debug("token:", token) + + neInfo, err := dborm.XormGetNeInfo(neType, neId) + if err != nil { + log.Error("Failed to XormGetNeInfo:", err) + services.ResponseInternalServerError500ProcessError(w, err) + return + } else if neInfo == nil { + err := global.ErrCMNotFoundTargetNE + log.Error(global.ErrCMNotFoundTargetNE) + services.ResponseInternalServerError500ProcessError(w, err) + return + } + log.Trace("neInfo:", neInfo) + + hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port) + requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI) + + log.Debug("requestURI2NF:", requestURI2NF) + + resp, err := client.R(). + EnableTrace(). + SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{"accessToken": token}). + SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). + SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). + Get(requestURI2NF) + if err != nil { + log.Error("Get system state from NF is failed:", err) + services.ResponseInternalServerError500ProcessError(w, err) + return + } else { + var response services.MapResponse + _ = json.Unmarshal(resp.Body(), &response) + services.ResponseWithJson(w, resp.StatusCode(), response) + return + } +} + +// Get Subscriptions from NSSF +func GetSubscriptionsFromNSSF(w http.ResponseWriter, r *http.Request) { + log.Info("GetSubscriptionsFromNSSF processing... ") + + vars := mux.Vars(r) + neType := vars["elementTypeValue"] + if strings.ToLower(neType) != "nssf" { + services.ResponseNotFound404UriNotExist(w, r) + return + } + //neTypeLower := strings.ToLower(neType) + var neId string + neIds := services.GetParamsArrByName("neId", r) + if len(neIds) == 1 { + neId = neIds[0] + } else { + services.ResponseNotFound404UriNotExist(w, r) + return + } + + token, err := services.CheckFrontValidRequest(w, r) + if err != nil { + log.Error("Request error:", err) + return + } + log.Debug("token:", token) + + neInfo, err := dborm.XormGetNeInfo(neType, neId) + if err != nil { + log.Error("Failed to XormGetNeInfo:", err) + services.ResponseInternalServerError500ProcessError(w, err) + return + } else if neInfo == nil { + err := global.ErrCMNotFoundTargetNE + log.Error(global.ErrCMNotFoundTargetNE) + services.ResponseInternalServerError500ProcessError(w, err) + return + } + log.Trace("neInfo:", neInfo) + + hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port) + requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI) + + log.Debug("requestURI2NF:", requestURI2NF) + + resp, err := client.R(). + EnableTrace(). + SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{"accessToken": token}). + SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). + SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). + Get(requestURI2NF) + if err != nil { + log.Error("Get system state from NF is failed:", err) + services.ResponseInternalServerError500ProcessError(w, err) + return + } else { + var response services.MapResponse + _ = json.Unmarshal(resp.Body(), &response) + services.ResponseWithJson(w, resp.StatusCode(), response) + return + } +} + // Get UEInfo from NF/NFs func GetUEInfoFromNF(w http.ResponseWriter, r *http.Request) { log.Info("GetUEInfoFromNF processing... ") diff --git a/lib/dborm/dborm.go b/lib/dborm/dborm.go index 3bc0ebd..bc6586c 100644 --- a/lib/dborm/dborm.go +++ b/lib/dborm/dborm.go @@ -200,12 +200,12 @@ func XormGetNeInfo(neType string, neId string) (*NeInfo, error) { log.Debug("XormGetNeInfo processing... ") neInfo := new(NeInfo) - has, err := xEngine.Where("status='0' and ne_type=? and ne_id=?", strings.ToUpper(neType), neId).Get(neInfo) + has, err := xEngine.Where("status in ('0','3') and ne_type=? and ne_id=?", strings.ToUpper(neType), neId).Get(neInfo) if err != nil { log.Error("Failed to get table ne_info from database:", err) return nil, err - } else if has == false { - log.Infof("Not found ne_info from database, status='0', neType=%s, neId=%s", neType, neId) + } else if !has { + log.Infof("Not found ne_info from database, status in ('0','3'), neType=%s, neId=%s", neType, neId) return nil, nil } @@ -217,11 +217,11 @@ func XormGetNeInfoByRmUID(neType string, rmUID string) (*NeInfo, error) { log.Debug("XormGetNeInfoByRmUID processing... ") neInfo := new(NeInfo) - has, err := xEngine.Where("status='0' and ne_type=? and rm_uid=?", strings.ToUpper(neType), rmUID).Get(neInfo) + has, err := xEngine.Where("status in ('0','3') and ne_type=? and rm_uid=?", strings.ToUpper(neType), rmUID).Get(neInfo) if err != nil { log.Error("Failed to get table ne_info from database:", err) return nil, err - } else if has == false { + } else if !has { log.Infof("Not found ne_info from database, status='0', neType=%s, neId=%s", neType, rmUID) return nil, nil } @@ -234,7 +234,7 @@ func XormGetAllNeInfo(nes *[]NeInfo) (*[]NeInfo, error) { log.Debug("XormGetAllNeInfo processing... ") ne := new(NeInfo) - rows, err := xEngine.Table("ne_info").Where("status='0'").Rows(ne) + rows, err := xEngine.Table("ne_info").Where("status in ('0','3')").Rows(ne) if err != nil { log.Error("Failed to get table ne_info from database:", err) return nil, err @@ -256,7 +256,7 @@ func XormGetNeInfoByNeType(neType string, nes *[]NeInfo) error { log.Debug("XormGetNeInfoByNeType processing... ") ne := new(NeInfo) - rows, err := xEngine.Table("ne_info").Where("status='0' and ne_type=?", neType).Rows(ne) + rows, err := xEngine.Table("ne_info").Where("status in ('0','3') and ne_type=?", neType).Rows(ne) if err != nil { log.Error("Failed to get table ne_info from database:", err) return err @@ -283,7 +283,7 @@ func XormInsertNeInfo(neInfo *NeInfo) (int64, error) { xSession := xEngine.NewSession() defer xSession.Close() ex, _ := xEngine.Table("ne_info").Where("status = '1' and ne_type = ? and ne_id = ?", neInfo.NeType, neInfo.NeId).Exist() - if ex == true { + if ex { neInfo.Status = 0 affected, err = xSession.Where("ne_type = ? and ne_id = ?", neInfo.NeType, neInfo.NeId).Update(neInfo) } else { @@ -298,7 +298,7 @@ func XormUpdateNeInfo(neInfo *NeInfo) (int64, error) { xSession := xEngine.NewSession() defer xSession.Close() - affected, err := xSession.ID(neInfo.Id).Update(neInfo) + affected, err := xSession.ID(neInfo.Id).MustCols("status").Update(neInfo) xSession.Commit() return affected, err } @@ -1124,7 +1124,9 @@ type Alarm struct { PVFlag string `json:"pvFlag" xorm:"pv_flag"` NeName string `json:"neName"` NeType string `json:"neType"` + ObjectUid string `json:"objectUid" xorm:"object_uid"` ObjectName string `json:"objectName" xorm:"object_name"` + ObjectType string `json:"objectType" xorm:"object_type"` LocationInfo string `json:"locationInfo"` Province string `json:"province"` AlarmStatus int `json:"alarmStatus"` @@ -1820,3 +1822,80 @@ func XormGetTraceRawMsg(id int) (int64, []byte, error) { return timestamp, rawMsg, nil } + +func XormGetNEStateInfo(neType, neID string) (string, string, error) { + SN := "-" + Version := "-" + _, err := xEngine.Table("ne_state"). + Where("ne_type=? and ne_id=?", neType, neID). + Desc("timestamp"). + Cols("serial_num", "version"). + Limit(1). + Get(&SN, &Version) + return SN, Version, err +} + +type NeState struct { + Id int `json:"id" xorm:"pk 'id' autoincr"` + NeType string `json:"neType" xorm:"ne_type"` + NeId string `json:"neId" xorm:"ne_id"` + Version string `json:"version" xorm:"column 'version' VARCHAR(16)"` + Capability uint32 `json:"capability" xorm:"capability"` + SerialNum string `json:"serialNum" xorm:"serial_num"` + ExpiryDate string `json:"expiryDate" xorm:"expiry_date"` + CpuUsage string `json:"cpuUsage" xorm:"cpu_usage"` + MemUsage string `json:"memUsage" xorm:"mem_usage"` + DiskSpace string `json:"diskSpace" xorm:"disk_space"` + Timestamp string `json:"timestamp" xorm:"-" ` +} + +func XormInsertNeState(neState *NeState) (int64, error) { + log.Debug("XormInsertNeState processing... ") + + var affected int64 = 0 + + session := xEngine.NewSession() + defer session.Close() + affected, err := session.InsertOne(neState) + if err != nil { + return 0, err + } + err = session.Commit() + if err != nil { + return 0, err + } + return affected, err +} + +type AlarmDefine struct { + AlarmId string `json:"alarmId" xorm:"alarm_id"` + AlarmCode int `json:"alarmCode" xorm:"alarm_code"` + AlarmTitle string `json:"alarmTitle" xorm:"alarm_title"` + NeType string `json:"neType" xorm:"ne_type"` + AlarmType string `json:"alarmType" xorm:"alarm_type"` + OrigSeverity string `json:"origSeverity" xorm:"orig_severity"` + ObjectUid string `json:"objectUid" xorm:"object_uid"` + ObjectName string `json:"objectName" xorm:"object_name"` + ObjectType string `json:"objectType" xorm:"object_type"` + LocationInfo string `json:"locationInfo"` + SpecificProblem string `json:"specificProblem"` + SpecificProblemId string `json:"specificProblemId" xorm:"specific_problem_id"` + AddInfo string `json:"addInfo" xorm:"add_info"` + Threshold int64 `json:"threshold" xorm:"threshold"` + Status string `json:"status" xorm:"status"` +} + +func XormGetAlarmDefine(alarmCode string) (*AlarmDefine, error) { + log.Debug("XormGetAlarmDefine processing... ") + + alarmDefine := new(AlarmDefine) + _, err := xEngine. + Where("alarm_code=? and status='Active'", alarmCode). + Get(alarmDefine) + if err != nil { + log.Error("Failed to get table alarm_define from database:", err) + return nil, err + } + + return alarmDefine, nil +} diff --git a/lib/routes/routes.go b/lib/routes/routes.go index 7b4b56f..ae10e59 100644 --- a/lib/routes/routes.go +++ b/lib/routes/routes.go @@ -287,6 +287,14 @@ func init() { Register("GET", ue.UriNBInfo, ue.GetNBInfoFromNF, nil) Register("GET", ue.CustomUriNBInfo, ue.GetNBInfoFromNF, nil) + // NSSF AvailableAMFs + Register("GET", ue.UriNSSFAvailableAMFs, ue.GetAvailableAMFsFromNSSF, nil) + Register("GET", ue.CustomUriNSSFAvailableAMFs, ue.GetAvailableAMFsFromNSSF, nil) + + // NSSF Subscriptions + Register("GET", ue.UriNSSFSubscriptions, ue.GetSubscriptionsFromNSSF, nil) + Register("GET", ue.CustomUriNSSFSubscriptions, ue.GetSubscriptionsFromNSSF, nil) + // 进程网络 Register("GET", psnet.UriWs, psnet.ProcessWs, nil) Register("POST", psnet.UriStop, psnet.StopProcess, nil) diff --git a/restagent/etc/restconf.yaml b/restagent/etc/restconf.yaml index a1c4c01..e01a49b 100644 --- a/restagent/etc/restconf.yaml +++ b/restagent/etc/restconf.yaml @@ -38,7 +38,7 @@ database: type: mysql user: root # password: "1000omc@kp!" - # host: "192.168.5.57" + # host: "192.168.2.166" # port: 33066 # name: omc_db backup: d:/local.git/ems.agt/restagent/database @@ -62,7 +62,7 @@ redis: password: "" db: 0 # Redis db_num # 多个数据源时可以用这个指定默认的数据源 - defaultDataSourceName: "default" + defaultDataSourceName: "default" # upfHeaderLength: spare upf buffer, must destroy mml: @@ -76,7 +76,7 @@ mml: # NE config ne: - user: agtuser + user: root etcdir: /usr/local/etc bindir: /usr/local/bin omcdir: /usr/local/omc @@ -97,7 +97,7 @@ omc: vendor: "" dn: 4600 chk2ne: false - sn: 13750650 + sn: "-" checksign: false rootDir: ./ binDir: ./bin diff --git a/restagent/makefile b/restagent/makefile index 68fcf75..49c5444 100644 --- a/restagent/makefile +++ b/restagent/makefile @@ -1,7 +1,7 @@ # Makefile for rest agent project PROJECT = OMC -VERSION = 2.2312.8 +VERSION = 2.2312.10 PLATFORM = amd64 ARMPLATFORM = aarch64 BUILDDIR = ../../build diff --git a/restagent/restagent.go b/restagent/restagent.go index 540f782..d18445f 100644 --- a/restagent/restagent.go +++ b/restagent/restagent.go @@ -197,7 +197,15 @@ func main() { } else { go HttpListen(listen, app) } - + } + if rest.IPv4 != "0.0.0.0" { + // 默认启动localhost侦听 + listenLocal := "127.0.0.1" + ":" + strconv.Itoa(int(rest.Port)) + if strings.ToLower(rest.Scheme) == "https" { + go HttpListenTLS(listenLocal, rest.CaFile, rest.CertFile, rest.KeyFile, app) + } else { + go HttpListen(listenLocal, app) + } } // ipv6 goroutines if rest.IPv6 != "" { @@ -208,6 +216,16 @@ func main() { go HttpListen(listenv6, app) } } + + // if rest.IPv6 != "::" { + // // 默认启动localhost侦听 + // listenv6Local := "[" + "::1" + "]" + ":" + strconv.Itoa(int(rest.Port)) + // if strings.ToLower(rest.Scheme) == "https" { + // go HttpListenTLS(listenv6Local, rest.CaFile, rest.CertFile, rest.KeyFile, app) + // } else { + // go HttpListen(listenv6Local, app) + // } + // } } if conf.WebServer.Enabled { diff --git a/src/framework/config/config/config.default.yaml b/src/framework/config/config/config.default.yaml index ee82bb5..e9d9f05 100644 --- a/src/framework/config/config/config.default.yaml +++ b/src/framework/config/config/config.default.yaml @@ -1,7 +1,7 @@ # 项目信息 framework: name: "CN EMS" - version: "2.2312.9" + version: "2.2312.10" # 应用服务配置 server: diff --git a/src/framework/middleware/pre_authorize.go b/src/framework/middleware/pre_authorize.go index 81f4289..c64717e 100644 --- a/src/framework/middleware/pre_authorize.go +++ b/src/framework/middleware/pre_authorize.go @@ -14,7 +14,7 @@ import ( ) /**无Token可访问白名单 */ -var URL_WHITE_LIST = []string{"/performanceManagement", "/faultManagement"} +var URL_WHITE_LIST = []string{"/performanceManagement", "/faultManagement", "/systemState"} // PreAuthorize 用户身份授权认证校验 // diff --git a/src/framework/utils/fetch/fetch.go b/src/framework/utils/fetch/fetch.go new file mode 100644 index 0000000..38a8ec3 --- /dev/null +++ b/src/framework/utils/fetch/fetch.go @@ -0,0 +1,243 @@ +package fetch + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "mime/multipart" + "net/http" + "net/url" + "os" + "strings" + "time" +) + +// Get 发送 GET 请求 +// timeout 超时时间(秒) +func Get(url string, headers map[string]string, timeout uint8) ([]byte, error) { + if timeout < 1 || timeout > 180 { + timeout = 1 + } + client := &http.Client{ + Timeout: time.Duration(timeout) * time.Second, // 设置超时时间为 5 秒 + } + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + + for key, value := range headers { + req.Header.Set(key, value) + } + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, errors.New(resp.Status) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return body, nil +} + +// Post 发送 POST 请求 +func Post(url string, data url.Values, headers map[string]string) ([]byte, error) { + client := &http.Client{} + + req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode())) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + for key, value := range headers { + req.Header.Set(key, value) + } + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, errors.New(resp.Status) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return body, nil +} + +// PostJSON 发送 POST 请求,并将请求体序列化为 JSON 格式 +func PostJSON(url string, data any, headers map[string]string) ([]byte, error) { + client := &http.Client{} + + jsonData, err := json.Marshal(data) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData)) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/json") + + for key, value := range headers { + req.Header.Set(key, value) + } + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, errors.New(resp.Status) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return body, nil +} + +// UploadFile 上传文件函数,接收 URL 地址、表单参数和文件对象,返回响应内容或错误信息 +func PostUploadFile(url string, params map[string]string, file *os.File) ([]byte, error) { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + part, err := writer.CreateFormFile("file", file.Name()) + if err != nil { + return nil, fmt.Errorf("failed to create form file: %v", err) + } + + _, err = io.Copy(part, file) + if err != nil { + return nil, fmt.Errorf("failed to copy file content: %v", err) + } + + for key, value := range params { + err = writer.WriteField(key, value) + if err != nil { + return nil, fmt.Errorf("failed to write form field: %v", err) + } + } + + err = writer.Close() + if err != nil { + return nil, fmt.Errorf("failed to close writer: %v", err) + } + + req, err := http.NewRequest("POST", url, body) + if err != nil { + return nil, fmt.Errorf("failed to create HTTP request: %v", err) + } + + req.Header.Set("Content-Type", writer.FormDataContentType()) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("HTTP request failed: %v", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("HTTP request returned status: %s", resp.Status) + } + + responseBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response body: %v", err) + } + + return responseBody, nil +} + +// PutJSON 发送 PUT 请求,并将请求体序列化为 JSON 格式 +func PutJSON(url string, data any, headers map[string]string) ([]byte, error) { + client := &http.Client{} + + jsonData, err := json.Marshal(data) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("PUT", url, bytes.NewReader(jsonData)) + if err != nil { + return nil, err + } + + for key, value := range headers { + req.Header.Set(key, value) + } + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, errors.New(resp.Status) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return body, nil +} + +// Delete 发送 DELETE 请求 +func Delete(url string, headers map[string]string) ([]byte, error) { + client := &http.Client{} + + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + for key, value := range headers { + req.Header.Set(key, value) + } + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, errors.New(resp.Status) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return body, nil +} diff --git a/src/modules/common/service/commont.impl.go b/src/modules/common/service/commont.impl.go index 218d20d..2d976d4 100644 --- a/src/modules/common/service/commont.impl.go +++ b/src/modules/common/service/commont.impl.go @@ -1,6 +1,10 @@ package service import ( + "fmt" + + "ems.agt/lib/global" + "ems.agt/src/framework/config" systemService "ems.agt/src/modules/system/service" ) @@ -21,6 +25,12 @@ type CommontImpl struct { // SystemConfigInfo 系统配置信息 func (s *CommontImpl) SystemConfigInfo() map[string]string { infoMap := map[string]string{} + // 获取打包注入的全局变量信息 + infoMap["version"] = global.Version + infoMap["buildTime"] = global.BuildTime + infoMap["goVer"] = global.GoVer + // 序列号 + infoMap["serialNum"] = fmt.Sprint(config.Get("omc.sn")) // 获取LOGO类型 logoType := s.sysConfigService.SelectConfigValueByKey("sys.logo.type") infoMap["logoType"] = logoType diff --git a/src/modules/crontask/processor/genNeStateAlarm/genNeStateAlarm.go b/src/modules/crontask/processor/genNeStateAlarm/genNeStateAlarm.go new file mode 100644 index 0000000..8d1e61a --- /dev/null +++ b/src/modules/crontask/processor/genNeStateAlarm/genNeStateAlarm.go @@ -0,0 +1,309 @@ +package genNeStateAlarm + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + "strings" + "time" + + "ems.agt/features/fm" + "ems.agt/lib/dborm" + "ems.agt/lib/global" + "ems.agt/lib/log" + "ems.agt/restagent/config" + "ems.agt/src/framework/cron" + "github.com/go-resty/resty/v2" +) + +var NewProcessor = &BarProcessor{ + progress: 0, + count: 0, +} + +// bar 队列任务处理 +type BarProcessor struct { + // 任务进度 + progress int + // 执行次数 + count int +} +type BarParams struct { + AlarmID string `json:"alarmID"` + AlarmCode int `json:"alarmCode"` + AlarmTitle string `json:"alarmTitle"` + AlarmType string `json:"alarmType"` + OrigSeverity string `json:"origSeverity"` + ObjectUID string `json:"objectUID"` + ObjectName string `json:"objectName"` + ObjectType string `json:"objectType"` + SpecificProblem string `json:"specificProblem"` + SpecificProblemID string `json:"specificProblemID"` + AddInfo string `json:"AddInfo"` + Threshold int64 `json:"threshold"` +} + +// type BarParams struct { +// Duration int `json:"duration"` +// } + +type Alarm struct { + Id int `json:"-" xorm:"pk 'id' autoincr"` + AlarmSeq int `json:"alarmSeq"` + AlarmId string `json:"alarmId" xorm:"alarm_id"` + NeId string `json:"neId"` + AlarmCode int `json:"alarmCode"` + AlarmTitle string `json:"alarmTitle"` + EventTime string `json:"eventTime"` + AlarmType string `json:"alarmType"` + OrigSeverity string `json:"origSeverity"` + PerceivedSeverity string `json:"perceivedSeverity"` + PVFlag string `json:"pvFlag" xorm:"pv_flag"` + NeName string `json:"neName"` + NeType string `json:"neType"` + ObjectUid string `json:"objectUid" xorm:"object_uid"` + ObjectName string `json:"objectName" xorm:"object_name"` + ObjectType string `json:"objectType" xorm:"object_type"` + LocationInfo string `json:"locationInfo"` + Province string `json:"province"` + AlarmStatus int `json:"alarmStatus" xorm:"alarm_status"` + SpecificProblem string `json:"specificProblem"` + SpecificProblemID string `json:"specificProblemID" xorm:"specific_problem_id"` + AddInfo string `json:"addInfo"` + + // ClearType int `json:"-" xorm:"clear_type"` // 0: Unclear, 1: Auto clear, 2: Manual clear + // ClearTime sql.NullTime `json:"-" xorm:"clear_time"` +} + +var client = resty.New() + +func init() { + client. + SetTimeout(time.Duration(400 * time.Millisecond)) +} + +func (s *BarProcessor) Execute(data any) (any, error) { + var err error + + s.count++ + options := data.(cron.JobData) + sysJob := options.SysJob + var alarmDefine BarParams + + err = json.Unmarshal([]byte(sysJob.TargetParams), &alarmDefine) + if err == nil { + log.Error("Failed to Unmarshal:", err) + return nil, err + } + + var nes []dborm.NeInfo + _, err = dborm.XormGetAllNeInfo(&nes) + if err != nil { + log.Error("Failed to get all ne info:", err) + return nil, err + } + + succActiveAlarmNum := 0 + failActiveAlarmNum := 0 + succClearAlarmNum := 0 + failClearAlarmNum := 0 + + for _, ne := range nes { + //log.Debug("ne:", ne) + + sql := fmt.Sprintf("select * from ne_state where ne_type = '%s' and ne_id = '%s' order by timestamp desc limit 1", ne.NeType, ne.NeId) + neState, err := dborm.XormGetDataBySQL(sql) + if err != nil { + log.Error("Failed to get ne_state:", err) + continue + } + if len(*neState) == 0 { + log.Warn("Not found record in ne_state:") + continue + } + //log.Debug("neState:", *neState) + + // params := "10000" + + // alarmDefine, err := dborm.XormGetAlarmDefine(params) + // if err != nil { + // log.Error("Failed to get alarm_define:", err) + // continue + // } else if alarmDefine == nil { + // log.Error("Not found data from alarm_define") + // continue + // } + + // log.Debug("alarmDefine:", alarmDefine) + + sql = fmt.Sprintf("select * from alarm where alarm_id = '%s' and ne_type='%s' and ne_id = '%s' order by event_time desc limit 1", + alarmDefine.AlarmID, ne.NeType, ne.RmUID) + alarm, err := dborm.XormGetDataBySQL(sql) + if err != nil { + log.Error("Failed to get alarm:", err) + continue + } + //log.Debug("alarm:", *alarm) + + var timestamp string + if len(*neState) == 0 { + log.Infof("Not found ne_state neType:%s, neId:%s", ne.NeType, ne.NeId) + timestamp = ne.UpdateTime + } else { + timestamp = (*neState)[0]["timestamp"] + } + + // 解析日期时间字符串为时间对象 + seconds, err := global.GetSecondsSinceDatetime(timestamp) + if err != nil { + log.Error("Failed to GetSecondsSinceDatetime:", err) + continue + } + log.Debugf("timestamp:%s seconds:%d", timestamp, seconds) + + if seconds <= alarmDefine.Threshold { + if len(*alarm) == 0 || (*alarm)[0]["alarm_status"] == fm.AlarmStatusClearString { + continue + } + + // clear alarm, todo + var alarmSeq int = 1 + threshold := strconv.FormatInt(alarmDefine.Threshold, 10) + SpecificProblem := strings.ReplaceAll(alarmDefine.SpecificProblem, "{threshold}", threshold) + locationInfo := fmt.Sprintf("SystemManagement.State: NE heartbeat timestamp=%s,threshold=%v", timestamp, alarmDefine.Threshold) + alarmData := &Alarm{ + AlarmSeq: alarmSeq, + AlarmId: alarmDefine.AlarmID, + NeId: ne.RmUID, + NeType: ne.NeType, + NeName: ne.NeName, + Province: ne.Province, + PVFlag: ne.PvFlag, + AlarmCode: alarmDefine.AlarmCode, + AlarmTitle: alarmDefine.AlarmTitle, + AlarmType: alarmDefine.AlarmType, + AlarmStatus: fm.AlarmStatusClear, + OrigSeverity: alarmDefine.OrigSeverity, + ObjectUid: alarmDefine.ObjectUID, + ObjectName: alarmDefine.ObjectName, + ObjectType: alarmDefine.ObjectType, + LocationInfo: locationInfo, + SpecificProblem: SpecificProblem, + SpecificProblemID: alarmDefine.SpecificProblemID, + AddInfo: alarmDefine.AddInfo, + EventTime: time.Now().Local().Format(time.RFC3339), + } + + alarmArray := &[]Alarm{*alarmData} + body, _ := json.Marshal(alarmArray) + //log.Debug("body: ", string(body)) + + var response *resty.Response + requestURI := fmt.Sprintf("/api/rest/faultManagement/v1/elementType/%s/objectType/alarms", ne.NeType) + restHost := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port) + requestURL := fmt.Sprintf("%s%s", restHost, requestURI) + log.Debug("requestURL: POST ", requestURL) + 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). + Post(requestURL) + if err != nil { + log.Error("Failed to post:", err) + failClearAlarmNum++ + continue + } + + log.Debug("StatusCode: ", response.StatusCode()) + switch response.StatusCode() { + case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: + log.Debug("response body:", string(response.Body())) + body := new(map[string]interface{}) + _ = json.Unmarshal(response.Body(), &body) + succClearAlarmNum++ + default: + log.Debug("response body:", string(response.Body())) + body := new(map[string]interface{}) + _ = json.Unmarshal(response.Body(), &body) + failClearAlarmNum++ + } + } else { + var alarmSeq int = 1 + if len(*alarm) > 0 && (*alarm)[0]["alarm_status"] == fm.AlarmStatusActiveString { + log.Info("System state alarm has exist") + continue + } + + threshold := strconv.FormatInt(alarmDefine.Threshold, 10) + SpecificProblem := strings.ReplaceAll(alarmDefine.SpecificProblem, "{threshold}", threshold) + locationInfo := fmt.Sprintf("SystemManagement.State: NE heartbeat timestamp=%s,threshold=%v", timestamp, alarmDefine.Threshold) + alarmData := &Alarm{ + AlarmSeq: alarmSeq, + AlarmId: alarmDefine.AlarmID, + NeId: ne.RmUID, + NeType: ne.NeType, + NeName: ne.NeName, + Province: ne.Province, + PVFlag: ne.PvFlag, + AlarmCode: alarmDefine.AlarmCode, + AlarmTitle: alarmDefine.AlarmTitle, + AlarmType: alarmDefine.AlarmType, + AlarmStatus: fm.AlarmStatusActive, + OrigSeverity: alarmDefine.OrigSeverity, + ObjectUid: alarmDefine.ObjectUID, + ObjectName: alarmDefine.ObjectName, + ObjectType: alarmDefine.ObjectType, + LocationInfo: locationInfo, + SpecificProblem: SpecificProblem, + SpecificProblemID: alarmDefine.SpecificProblemID, + AddInfo: alarmDefine.AddInfo, + EventTime: time.Now().Local().Format(time.RFC3339), + } + + alarmArray := &[]Alarm{*alarmData} + body, _ := json.Marshal(alarmArray) + //log.Debug("body: ", string(body)) + + var response *resty.Response + requestURI := fmt.Sprintf("/api/rest/faultManagement/v1/elementType/%s/objectType/alarms", ne.NeType) + restHost := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port) + requestURL := fmt.Sprintf("%s%s", restHost, requestURI) + log.Debug("requestURL: POST ", requestURL) + 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). + Post(requestURL) + if err != nil { + log.Error("Failed to post:", err) + failActiveAlarmNum++ + continue + } + + log.Debug("StatusCode: ", response.StatusCode()) + switch response.StatusCode() { + case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: + log.Debug("response body:", string(response.Body())) + body := new(map[string]interface{}) + _ = json.Unmarshal(response.Body(), &body) + succActiveAlarmNum++ + default: + log.Debug("response body:", string(response.Body())) + body := new(map[string]interface{}) + _ = json.Unmarshal(response.Body(), &body) + failActiveAlarmNum++ + } + } + } + + // 返回结果,用于记录执行结果 + return map[string]any{ + "succActiveAlarmNum": succActiveAlarmNum, + "failActiveAlarmNum": failActiveAlarmNum, + "succClearAlarmNum": succClearAlarmNum, + "failClearAlarmNum": failClearAlarmNum, + }, nil +} diff --git a/src/modules/crontask/processor/getStateFromNE/getStateFromNE.go b/src/modules/crontask/processor/getStateFromNE/getStateFromNE.go new file mode 100644 index 0000000..4752490 --- /dev/null +++ b/src/modules/crontask/processor/getStateFromNE/getStateFromNE.go @@ -0,0 +1,167 @@ +package getStateFromNE + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "ems.agt/lib/dborm" + "ems.agt/lib/log" + "ems.agt/restagent/config" + "github.com/go-resty/resty/v2" +) + +var NewProcessor = &BarProcessor{ + progress: 0, + count: 0, +} + +// bar 队列任务处理 +type BarProcessor struct { + // 任务进度 + progress int + // 执行次数 + count int +} + +type BarParams struct { + Duration int `json:"duration"` +} + +type CpuUsage struct { + NfCpuUsage uint16 `json:"nfCpuUsage"` + SysCpuUsage uint16 `json:"sysCpuUsage"` +} + +type MemUsage struct { + TotalMem uint32 `json:"totalMem"` + NfUsedMem uint32 `json:"nfUsedMem"` + SysMemUsage uint16 `json:"sysMemUsage"` +} + +type PartitionInfo struct { + Total uint32 `json:"total"` // MB + Used uint32 `json:"used"` // MB +} + +type DiskSpace struct { + PartitionNum uint8 `json:"partitionNum"` + + PartitionInfo []PartitionInfo `json:"partitionInfo"` +} + +type SystemState struct { + Version string `json:"version"` + Capability uint32 `json:"capability"` + SerialNum string `json:"serialNum"` + ExpiryDate string `json:"expiryDate"` + //Timestamp string `json:"timestamp"` + + CpuUsage CpuUsage `json:"cpuUsage"` + MemUsage MemUsage `json:"memUsage"` + + DiskSpace DiskSpace `json:"diskSpace"` +} + +var client = resty.New() + +func init() { + /* + client. + SetTimeout(10 * time.Second). + SetRetryCount(1). + SetRetryWaitTime(1 * time.Second). + SetRetryMaxWaitTime(2 * time.Second). + SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) { + return 0, errors.New("quota exceeded") + }) + */ + client. + SetTimeout(time.Duration(400 * time.Millisecond)) + // SetRetryCount(1). + // SetRetryWaitTime(time.Duration(1 * time.Second)). + // SetRetryMaxWaitTime(time.Duration(2 * time.Second)) + //client.SetTimeout(2 * time.Second) +} + +func (s *BarProcessor) Execute(data any) (any, error) { + var err error + + s.count++ + // options := data.(cron.JobData) + // // sysJob := options.SysJob + // // var params BarParams + + // // // err := json.Unmarshal([]byte(sysJob.TargetParams), ¶ms) + // // // if err == nil { + // // // duration = params.Duration + // // // } + + var nes []dborm.NeInfo + _, err = dborm.XormGetAllNeInfo(&nes) + if err != nil { + log.Error("Failed to get all ne info:", err) + return nil, err + } + + failNum := 0 + succNum := 0 + for _, ne := range nes { + requestURI := fmt.Sprintf("/api/rest/systemManagement/v1/elementType/%s/objectType/systemState", strings.ToLower(ne.NeType)) + requestURL := fmt.Sprintf("http://%s:%s%s", ne.Ip, ne.Port, requestURI) + log.Debug("requestURL: Get", requestURL) + 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(requestURL) + if err != nil { + log.Error("Failed to Get:", err) + failNum++ + continue + } + + log.Debug("StatusCode: ", response.StatusCode()) + switch response.StatusCode() { + case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: + log.Debug("response body:", string(response.Body())) + state := new(SystemState) + _ = json.Unmarshal(response.Body(), &state) + neState := new(dborm.NeState) + neState.NeType = ne.NeType + neState.NeId = ne.NeId + neState.Version = state.Version + neState.Capability = state.Capability + neState.SerialNum = state.SerialNum + neState.ExpiryDate = state.ExpiryDate + cu, _ := json.Marshal(state.CpuUsage) + neState.CpuUsage = string(cu) + mu, _ := json.Marshal(state.MemUsage) + neState.MemUsage = string(mu) + ds, _ := json.Marshal(state.DiskSpace) + neState.DiskSpace = string(ds) + log.Debug("neState:", neState) + _, err := dborm.XormInsertNeState(neState) + if err != nil { + log.Error("Failed to insert ne_state:", err) + failNum++ + continue + } + succNum++ + default: + log.Debug("response body:", string(response.Body())) + body := new(map[string]interface{}) + _ = json.Unmarshal(response.Body(), &body) + failNum++ + } + } + + // 返回结果,用于记录执行结果 + return map[string]any{ + "succNum": succNum, + "failNum": failNum, + }, nil +} diff --git a/src/modules/crontask/processor/processor.go b/src/modules/crontask/processor/processor.go index 4a0d8ae..cab305d 100644 --- a/src/modules/crontask/processor/processor.go +++ b/src/modules/crontask/processor/processor.go @@ -5,6 +5,8 @@ import ( "ems.agt/src/modules/crontask/processor/backupEtcFromNE" "ems.agt/src/modules/crontask/processor/delExpiredNeBackup" "ems.agt/src/modules/crontask/processor/deleteExpiredRecord" + "ems.agt/src/modules/crontask/processor/genNeStateAlarm" + "ems.agt/src/modules/crontask/processor/getStateFromNE" monitorsysresource "ems.agt/src/modules/crontask/processor/monitor_sys_resource" ) @@ -16,4 +18,6 @@ func InitCronQueue() { cron.CreateQueue("delExpiredNeBackup", delExpiredNeBackup.NewProcessor) cron.CreateQueue("deleteExpiredRecord", deleteExpiredRecord.NewProcessor) cron.CreateQueue("backupEtcFromNE", backupEtcFromNE.NewProcessor) + cron.CreateQueue("getStateFromNE", getStateFromNE.NewProcessor) + cron.CreateQueue("genNeStateAlarm", genNeStateAlarm.NewProcessor) } diff --git a/src/modules/monitor/controller/sys_job_log.go b/src/modules/monitor/controller/sys_job_log.go index ac942e0..85a8a82 100644 --- a/src/modules/monitor/controller/sys_job_log.go +++ b/src/modules/monitor/controller/sys_job_log.go @@ -43,22 +43,9 @@ func (s *SysJobLogController) List(c *gin.Context) { querys := ctx.QueryMap(c) data := s.sysJobLogService.SelectJobLogPage(querys) - language := ctx.AcceptLanguage(c) - - // 反查多语言key - querys["jobName"] = i18n.ValueKey(language, querys["jobName"].(string)) - dataI18n := s.sysJobLogService.SelectJobLogPage(querys) - totalI18n := parse.Number(dataI18n["total"]) - if totalI18n != 0 { - rows := data["rows"].([]model.SysJobLog) - total := parse.Number(data["total"]) - rowsI18n := dataI18n["rows"].([]model.SysJobLog) - data["rows"] = append(rows, rowsI18n...) - data["total"] = total + totalI18n - } - rows := data["rows"].([]model.SysJobLog) // 闭包函数处理多语言 + language := ctx.AcceptLanguage(c) converI18n := func(language string, arr *[]model.SysJobLog) { for i := range *arr { (*arr)[i].JobName = i18n.TKey(language, (*arr)[i].JobName) diff --git a/src/modules/monitor/repository/sys_job.impl.go b/src/modules/monitor/repository/sys_job.impl.go index 19040fa..196601f 100644 --- a/src/modules/monitor/repository/sys_job.impl.go +++ b/src/modules/monitor/repository/sys_job.impl.go @@ -234,9 +234,7 @@ func (r *SysJobImpl) InsertJob(sysJob model.SysJob) string { if sysJob.InvokeTarget != "" { params["invoke_target"] = sysJob.InvokeTarget } - if sysJob.TargetParams != "" { - params["target_params"] = sysJob.TargetParams - } + params["target_params"] = sysJob.TargetParams if sysJob.CronExpression != "" { params["cron_expression"] = sysJob.CronExpression } @@ -252,9 +250,7 @@ func (r *SysJobImpl) InsertJob(sysJob model.SysJob) string { if sysJob.SaveLog != "" { params["save_log"] = sysJob.SaveLog } - if sysJob.Remark != "" { - params["remark"] = sysJob.Remark - } + params["remark"] = sysJob.Remark if sysJob.CreateBy != "" { params["create_by"] = sysJob.CreateBy params["create_time"] = time.Now().UnixMilli() @@ -300,9 +296,7 @@ func (r *SysJobImpl) UpdateJob(sysJob model.SysJob) int64 { if sysJob.InvokeTarget != "" { params["invoke_target"] = sysJob.InvokeTarget } - if sysJob.TargetParams != "" { - params["target_params"] = sysJob.TargetParams - } + params["target_params"] = sysJob.TargetParams if sysJob.CronExpression != "" { params["cron_expression"] = sysJob.CronExpression } @@ -318,9 +312,7 @@ func (r *SysJobImpl) UpdateJob(sysJob model.SysJob) int64 { if sysJob.SaveLog != "" { params["save_log"] = sysJob.SaveLog } - if sysJob.Remark != "" { - params["remark"] = sysJob.Remark - } + params["remark"] = sysJob.Remark if sysJob.UpdateBy != "" { params["update_by"] = sysJob.UpdateBy params["update_time"] = time.Now().UnixMilli() diff --git a/src/modules/network_element/controller/ne_info.go b/src/modules/network_element/controller/ne_info.go index d8f8a7c..b34116b 100644 --- a/src/modules/network_element/controller/ne_info.go +++ b/src/modules/network_element/controller/ne_info.go @@ -3,7 +3,9 @@ package controller import ( "ems.agt/src/framework/i18n" "ems.agt/src/framework/utils/ctx" + "ems.agt/src/framework/utils/parse" "ems.agt/src/framework/vo/result" + "ems.agt/src/modules/network_element/model" neService "ems.agt/src/modules/network_element/service" "github.com/gin-gonic/gin" ) @@ -21,22 +23,86 @@ type NeInfoController struct { neInfoService neService.INeInfo } +// 网元状态 +// +// GET /state +func (s *NeInfoController) NeState(c *gin.Context) { + language := ctx.AcceptLanguage(c) + var querys struct { + NeType string `form:"neType" binding:"required"` + NeID string `form:"neId" binding:"required"` + } + if err := c.ShouldBindQuery(&querys); err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID) + if neInfo.NeId != querys.NeID || neInfo.IP == "" { + c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) + return + } + + // 网元直连 + resData, err := neService.NeState(neInfo) + if err != nil { + c.JSON(200, result.ErrMsg("connection failure")) + return + } + + c.JSON(200, result.OkData(resData)) +} + // 网元neType和neID查询 // // GET /info func (s *NeInfoController) NeTypeAndID(c *gin.Context) { language := ctx.AcceptLanguage(c) - neType := c.Query("neType") - neId := c.Query("neId") - if neType == "" || neId == "" { + var querys struct { + NeType string `form:"neType" binding:"required"` + NeID string `form:"neId" binding:"required"` + } + if err := c.ShouldBindQuery(&querys); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } - neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(neType, neId) - if neInfo.NeId != neId || neInfo.IP == "" { + neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID) + if neInfo.NeId != querys.NeID || neInfo.IP == "" { c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } c.JSON(200, result.OkData(neInfo)) } + +// 网元列表 +// +// GET /list +func (s *NeInfoController) NeList(c *gin.Context) { + language := ctx.AcceptLanguage(c) + var querys struct { + NeType string `form:"neType"` + NeId string `form:"neId"` + BandStatus string `form:"bandStatus"` + } + if err := c.ShouldBindQuery(&querys); err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + // 查询实体参数 + ne := model.NeInfo{} + if querys.NeType != "" { + ne.NeType = querys.NeType + } + if querys.NeId != "" { + ne.NeId = querys.NeId + } + bandStatus := parse.Boolean(querys.BandStatus) + neList := s.neInfoService.SelectNeList(ne, bandStatus) + if len(neList) == 0 { + c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) + return + } + c.JSON(200, result.OkData(neList)) +} diff --git a/src/modules/network_element/controller/perf_kpi.go b/src/modules/network_element/controller/perf_kpi.go index 05919a0..aadc7aa 100644 --- a/src/modules/network_element/controller/perf_kpi.go +++ b/src/modules/network_element/controller/perf_kpi.go @@ -5,6 +5,7 @@ import ( "ems.agt/src/framework/i18n" "ems.agt/src/framework/utils/ctx" "ems.agt/src/framework/vo/result" + "ems.agt/src/modules/network_element/model" neService "ems.agt/src/modules/network_element/service" "github.com/gin-gonic/gin" ) @@ -30,13 +31,7 @@ type PerfKPIController struct { // GET /data func (s *PerfKPIController) GoldKPI(c *gin.Context) { language := ctx.AcceptLanguage(c) - var querys struct { - NeType string `form:"neType" binding:"required"` - NeID string `form:"neId" binding:"required"` - StartTime string `form:"startTime" binding:"required"` - EndTime string `form:"endTime" binding:"required"` - Interval int64 `form:"interval" binding:"required"` - } + var querys model.GoldKPIQuery if err := c.ShouldBindQuery(&querys); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return @@ -47,12 +42,10 @@ func (s *PerfKPIController) GoldKPI(c *gin.Context) { if startTime.IsZero() { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) } - startTimeStr := startTime.Format(date.YYYY_MM_DD_HH_MM_SS) endTime := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS) - if startTime.IsZero() { + if endTime.IsZero() { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) } - endTimeStr := endTime.Format(date.YYYY_MM_DD_HH_MM_SS) // 查询网元获取IP neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID) @@ -60,16 +53,10 @@ func (s *PerfKPIController) GoldKPI(c *gin.Context) { c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } - - // 获取数据指标id - var kpiIds []string - kpiTitles := s.perfKPIService.SelectGoldKPITitle(neInfo.NeType) - for _, kpiId := range kpiTitles { - kpiIds = append(kpiIds, kpiId.KPIID) - } + querys.RmUID = neInfo.RmUID // 查询数据 - kpiData := s.perfKPIService.SelectGoldKPI(neInfo.RmUID, neInfo.NeType, startTimeStr, endTimeStr, kpiIds, querys.Interval) + kpiData := s.perfKPIService.SelectGoldKPI(querys) c.JSON(200, result.OkData(kpiData)) } diff --git a/src/modules/network_element/controller/udm_auth.go b/src/modules/network_element/controller/udm_auth.go index d1acc52..09f1afe 100644 --- a/src/modules/network_element/controller/udm_auth.go +++ b/src/modules/network_element/controller/udm_auth.go @@ -11,6 +11,7 @@ import ( "ems.agt/src/framework/i18n" "ems.agt/src/framework/utils/ctx" "ems.agt/src/framework/utils/file" + "ems.agt/src/framework/utils/parse" "ems.agt/src/framework/utils/ssh" "ems.agt/src/framework/vo/result" "ems.agt/src/modules/network_element/model" @@ -89,6 +90,11 @@ func (s *UDMAuthController) Info(c *gin.Context) { return } + if len(data) == 0 { + c.JSON(200, result.ErrMsg("No Auth Data")) + return + } + // 查询数据库是否存在并存入 neId = "" var userInfo model.UDMAuth @@ -265,6 +271,14 @@ func (s *UDMAuthController) Remove(c *gin.Context) { return } + // 处理字符转id数组后去重 + imsiArr := strings.Split(imsi, ",") + uniqueIDs := parse.RemoveDuplicates(imsiArr) + if len(uniqueIDs) <= 0 { + c.JSON(200, result.Err(nil)) + return + } + // 查询网元获取IP neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId) if neInfo.NeId != neId || neInfo.IP == "" { @@ -272,21 +286,24 @@ func (s *UDMAuthController) Remove(c *gin.Context) { return } - msg := fmt.Sprintf("del authdat:imsi=%s", imsi) + resultData := map[string]string{} + for _, imsi := range uniqueIDs { + msg := fmt.Sprintf("del authdat:imsi=%s", imsi) - // 发送MML - data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg) - if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) - return + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg) + if err != nil { + resultData[imsi] = err.Error() + } + // 命令ok时 + if strings.Contains(data, "ok") { + neId = "" + s.udmAuthService.Delete(neId, imsi) + resultData[imsi] = data + } } - // 命令ok时 - if strings.Contains(data, "ok") { - neId = "" - s.udmAuthService.Delete(neId, imsi) - } - c.JSON(200, result.OkData(data)) + c.JSON(200, result.OkData(resultData)) } // UDM鉴权用户-批量删除 @@ -342,7 +359,7 @@ func (s *UDMAuthController) Export(c *gin.Context) { } if !(body.Type == "csv" || body.Type == "txt") { - c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportFileFormat"))) + c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserAuthFileFormat"))) return } diff --git a/src/modules/network_element/controller/udm_sub.go b/src/modules/network_element/controller/udm_sub.go index df73862..02fd34c 100644 --- a/src/modules/network_element/controller/udm_sub.go +++ b/src/modules/network_element/controller/udm_sub.go @@ -12,6 +12,7 @@ import ( "ems.agt/src/framework/i18n" "ems.agt/src/framework/utils/ctx" "ems.agt/src/framework/utils/file" + "ems.agt/src/framework/utils/parse" "ems.agt/src/framework/utils/ssh" "ems.agt/src/framework/vo/result" "ems.agt/src/modules/network_element/model" @@ -90,6 +91,11 @@ func (s *UDMSubController) Info(c *gin.Context) { return } + if len(data) == 0 { + c.JSON(200, result.ErrMsg("No Subs Data")) + return + } + // 解析返回的数据 cnType, _ := strconv.ParseInt(data["CNType"][:4], 0, 64) rat, _ := strconv.ParseInt(data["RAT"][:4], 0, 64) @@ -341,6 +347,14 @@ func (s *UDMSubController) Remove(c *gin.Context) { return } + // 处理字符转id数组后去重 + imsiArr := strings.Split(imsi, ",") + uniqueIDs := parse.RemoveDuplicates(imsiArr) + if len(uniqueIDs) <= 0 { + c.JSON(200, result.Err(nil)) + return + } + // 查询网元获取IP neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId) if neInfo.NeId != neId || neInfo.IP == "" { @@ -348,21 +362,24 @@ func (s *UDMSubController) Remove(c *gin.Context) { return } - msg := fmt.Sprintf("del udmuser:imsi=%s", imsi) + resultData := map[string]string{} + for _, imsi := range uniqueIDs { + msg := fmt.Sprintf("del udmuser:imsi=%s", imsi) - // 发送MML - data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg) - if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) - return + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg) + if err != nil { + resultData[imsi] = err.Error() + } + // 命令ok时 + if strings.Contains(data, "ok") { + neId = "" + s.udmSubService.Delete(neId, imsi) + resultData[imsi] = data + } } - // 命令ok时 - if strings.Contains(data, "ok") { - neId = "" - s.udmSubService.Delete(neId, imsi) - } - c.JSON(200, result.OkData(data)) + c.JSON(200, result.OkData(resultData)) } // UDM签约用户-批量删除 @@ -418,7 +435,7 @@ func (s *UDMSubController) Export(c *gin.Context) { } if !(body.Type == "csv" || body.Type == "txt") { - c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportFileFormat"))) + c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat"))) return } diff --git a/src/modules/network_element/model/ne_info.go b/src/modules/network_element/model/ne_info.go index 941e7a0..ad13c4a 100644 --- a/src/modules/network_element/model/ne_info.go +++ b/src/modules/network_element/model/ne_info.go @@ -16,4 +16,9 @@ type NeInfo struct { NeAddress string `json:"neAddress"` Status string `json:"status"` // 0: 在线 1: 下线 2: 备用 3: 工程 UpdateTime string `json:"updateTime"` + + // ====== 非数据库字段属性 ====== + + // 服务状态 + ServerState map[string]any `json:"serverState,omitempty"` } diff --git a/src/modules/network_element/model/perf_kpi.go b/src/modules/network_element/model/perf_kpi.go index def0164..108d81f 100644 --- a/src/modules/network_element/model/perf_kpi.go +++ b/src/modules/network_element/model/perf_kpi.go @@ -9,3 +9,15 @@ type GoldKPITitle struct { CnTitle string `json:"cnTitle" gorm:"column:cn_title"` EnTitle string `json:"enTitle" gorm:"column:en_title"` } + +// GoldKPIQuery 黄金指标查询参数结构体 +type GoldKPIQuery struct { + NeType string `form:"neType" binding:"required"` + NeID string `form:"neId" binding:"required"` + StartTime string `form:"startTime" binding:"required"` + EndTime string `form:"endTime" binding:"required"` + Interval int64 `form:"interval" binding:"required"` + RmUID string `form:"rmUID"` + SortField string `form:"sortField" binding:"omitempty,oneof=timeGroup"` + SortOrder string `form:"sortOrder" binding:"omitempty,oneof=asc desc"` +} diff --git a/src/modules/network_element/network_element.go b/src/modules/network_element/network_element.go index 866095e..6ae71f7 100644 --- a/src/modules/network_element/network_element.go +++ b/src/modules/network_element/network_element.go @@ -20,6 +20,14 @@ func Setup(router *gin.Engine) { middleware.PreAuthorize(nil), controller.NewNeInfo.NeTypeAndID, ) + neGroup.GET("/state", + middleware.PreAuthorize(nil), + controller.NewNeInfo.NeState, + ) + neGroup.GET("/list", + middleware.PreAuthorize(nil), + controller.NewNeInfo.NeList, + ) } // 网元处理 diff --git a/src/modules/network_element/repository/ne_info.go b/src/modules/network_element/repository/ne_info.go index 1f4adcd..5286839 100644 --- a/src/modules/network_element/repository/ne_info.go +++ b/src/modules/network_element/repository/ne_info.go @@ -8,4 +8,7 @@ import ( type INeInfo interface { // SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息 SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo + + // SelectNeList 查询网元列表 + SelectNeList(ne model.NeInfo) []model.NeInfo } diff --git a/src/modules/network_element/repository/ne_info.impl.go b/src/modules/network_element/repository/ne_info.impl.go index f3615bd..e52cf3f 100644 --- a/src/modules/network_element/repository/ne_info.impl.go +++ b/src/modules/network_element/repository/ne_info.impl.go @@ -1,12 +1,33 @@ package repository import ( + "sort" + "strings" + "ems.agt/src/framework/datasource" "ems.agt/src/framework/logger" "ems.agt/src/framework/utils/repo" "ems.agt/src/modules/network_element/model" ) +// neListSort 网元列表预设排序 +var neListSort = []string{ + "OMC", + "MME", + "AMF", + "AUSF", + "UDM", + "SMF", + "PCF", + "UPF", + "NRF", + "NSSF", + "IMS", + "N3IWF", + "NEF", + "LMF", +} + // 实例化数据层 NeInfoImpl 结构体 var NewNeInfoImpl = &NeInfoImpl{ selectSql: `select id, ne_type, ne_id, rm_uid, ne_name, ip, port, pv_flag, province, vendor_name, dn, ne_address, status, update_time from ne_info`, @@ -49,6 +70,31 @@ func (r *NeInfoImpl) convertResultRows(rows []map[string]any) []model.NeInfo { } arr = append(arr, item) } + + // 排序 + sort.Slice(arr, func(i, j int) bool { + // 前一个 + after := arr[i] + afterIndex := 0 + for i, v := range neListSort { + if after.NeType == v { + afterIndex = i + break + } + } + // 后一个 + befter := arr[j] + befterIndex := 0 + for i, v := range neListSort { + if befter.NeType == v { + befterIndex = i + break + } + } + // 升序 + return afterIndex < befterIndex + }) + return arr } @@ -67,3 +113,34 @@ func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeIn } return model.NeInfo{} } + +// SelectNeList 查询网元列表 +func (r *NeInfoImpl) SelectNeList(ne model.NeInfo) []model.NeInfo { + // 查询条件拼接 + var conditions []string + var params []any + if ne.NeType != "" { + conditions = append(conditions, "ne_type = ?") + params = append(params, ne.NeType) + } + if ne.NeId != "" { + conditions = append(conditions, "ne_id = ?") + params = append(params, ne.NeId) + } + + // 构建查询条件语句 + whereSql := "" + if len(conditions) > 0 { + whereSql += " where " + strings.Join(conditions, " and ") + } + + // 查询数据 + querySql := r.selectSql + whereSql + " order by ne_type asc " + results, err := datasource.RawDB("", querySql, params) + if err != nil { + logger.Errorf("query err => %v", err) + } + + // 转换实体 + return r.convertResultRows(results) +} diff --git a/src/modules/network_element/repository/perf_kpi.go b/src/modules/network_element/repository/perf_kpi.go index 3035dca..2c21acd 100644 --- a/src/modules/network_element/repository/perf_kpi.go +++ b/src/modules/network_element/repository/perf_kpi.go @@ -4,8 +4,8 @@ import "ems.agt/src/modules/network_element/model" // 性能统计 数据层接口 type IPerfKPI interface { - // SelectGoldKPI 通过ne_type和ne_id查询网元信息 - SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any + // SelectGoldKPI 通过网元指标数据信息 + SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any // SelectGoldKPITitle SelectGoldKPITitle(neType string) []model.GoldKPITitle diff --git a/src/modules/network_element/repository/perf_kpi.impl.go b/src/modules/network_element/repository/perf_kpi.impl.go index 7a45f48..e6aadde 100644 --- a/src/modules/network_element/repository/perf_kpi.impl.go +++ b/src/modules/network_element/repository/perf_kpi.impl.go @@ -16,25 +16,25 @@ var NewPerfKPIImpl = &PerfKPIImpl{} type PerfKPIImpl struct{} // SelectGoldKPI 通过网元指标数据信息 -func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any { +func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any { // 查询条件拼接 var conditions []string var params []any - if rmUID != "" { + if query.RmUID != "" { conditions = append(conditions, "gk.rm_uid = ?") - params = append(params, rmUID) + params = append(params, query.RmUID) } - if neType != "" { + if query.NeType != "" { conditions = append(conditions, "gk.ne_type = ?") - params = append(params, neType) + params = append(params, query.NeType) } - if startTime != "" { + if query.StartTime != "" { conditions = append(conditions, "gk.start_time >= ?") - params = append(params, startTime) + params = append(params, query.StartTime) } - if endTime != "" { + if query.EndTime != "" { conditions = append(conditions, "gk.start_time <= ?") - params = append(params, endTime) + params = append(params, query.EndTime) } // 构建查询条件语句 whereSql := "" @@ -44,7 +44,7 @@ func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime str // 查询字段列 timeFormat := "DATE_FORMAT(gk.start_time, '%Y-%m-%d %H:')" - minuteGroup := fmt.Sprintf("LPAD(FLOOR(MINUTE(gk.start_time) / %d) * %d, 2, '0')", interval, interval) + minuteGroup := fmt.Sprintf("LPAD(FLOOR(MINUTE(gk.start_time) / %d) * %d, 2, '0')", query.Interval, query.Interval) groupByField := fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, minuteGroup) var fields = []string{ groupByField, @@ -58,7 +58,14 @@ func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime str fieldsSql := strings.Join(fields, ",") // 查询数据 - querySql := fmt.Sprintf("SELECT %s FROM gold_kpi gk %s GROUP BY timeGroup", fieldsSql, whereSql) + if query.SortField == "" { + query.SortField = "timeGroup" + } + if query.SortOrder == "" { + query.SortOrder = "desc" + } + orderSql := fmt.Sprintf(" order by %s %s", query.SortField, query.SortOrder) + querySql := fmt.Sprintf("SELECT %s FROM gold_kpi gk %s GROUP BY timeGroup %s", fieldsSql, whereSql, orderSql) results, err := datasource.RawDB("", querySql, params) if err != nil { logger.Errorf("query err => %v", err) diff --git a/src/modules/network_element/service/ne_direct_link.go b/src/modules/network_element/service/ne_direct_link.go new file mode 100644 index 0000000..ef29ed6 --- /dev/null +++ b/src/modules/network_element/service/ne_direct_link.go @@ -0,0 +1,44 @@ +package service + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "ems.agt/src/framework/logger" + "ems.agt/src/framework/utils/fetch" + "ems.agt/src/modules/network_element/model" +) + +// NeState 获取网元端服务状态 +func NeState(neInfo model.NeInfo) (map[string]any, error) { + // 网元直连 + neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/systemState", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType)) + resBytes, err := fetch.Get(neUrl, nil, 1) + if err != nil { + logger.Warnf("NeState %s", err.Error()) + return nil, err + } + + // 序列化结果 + var resData map[string]any + err = json.Unmarshal(resBytes, &resData) + if err != nil { + logger.Warnf("NeState Unmarshal %s", err.Error()) + return nil, err + } + + return map[string]any{ + "neType": neInfo.NeType, + "neId": neInfo.NeId, + "neName": neInfo.NeName, + "refreshTime": time.Now().UnixMilli(), // 获取时间 + "version": resData["version"], + "capability": resData["capability"], + "sn": resData["serialNum"], + "expire": resData["expiryDate"], + "cpu": resData["cpuUsage"], + "mem": resData["memUsage"], + }, nil +} diff --git a/src/modules/network_element/service/ne_info.go b/src/modules/network_element/service/ne_info.go index 715892b..e6e611b 100644 --- a/src/modules/network_element/service/ne_info.go +++ b/src/modules/network_element/service/ne_info.go @@ -6,4 +6,7 @@ import "ems.agt/src/modules/network_element/model" type INeInfo interface { // SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息 SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo + + // SelectNeList 查询网元列表 + SelectNeList(ne model.NeInfo, bandStatus bool) []model.NeInfo } diff --git a/src/modules/network_element/service/ne_info.impl.go b/src/modules/network_element/service/ne_info.impl.go index bd5d41a..484d7c8 100644 --- a/src/modules/network_element/service/ne_info.impl.go +++ b/src/modules/network_element/service/ne_info.impl.go @@ -20,3 +20,24 @@ type NeInfoImpl struct { func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo { return r.NeInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID) } + +// SelectNeList 查询网元列表 +func (r *NeInfoImpl) SelectNeList(ne model.NeInfo, bandStatus bool) []model.NeInfo { + list := r.NeInfoRepository.SelectNeList(ne) + + // 网元直连读取网元服务状态 + if bandStatus { + neList := &list + for i := range *neList { + v := (*neList)[i] + result, err := NeState(v) + if err != nil { + (*neList)[i].ServerState = map[string]any{} + continue + } + (*neList)[i].ServerState = result + } + } + + return list +} diff --git a/src/modules/network_element/service/perf_kpi.go b/src/modules/network_element/service/perf_kpi.go index 201d2f8..decd5dc 100644 --- a/src/modules/network_element/service/perf_kpi.go +++ b/src/modules/network_element/service/perf_kpi.go @@ -4,8 +4,8 @@ import "ems.agt/src/modules/network_element/model" // 性能统计 数据层接口 type IPerfKPI interface { - // SelectGoldKPI 通过ne_type和ne_id查询网元信息 - SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any + // SelectGoldKPI 通过网元指标数据信息 + SelectGoldKPI(query model.GoldKPIQuery) []map[string]any // SelectGoldKPITitle SelectGoldKPITitle(neType string) []model.GoldKPITitle diff --git a/src/modules/network_element/service/perf_kpi.impl.go b/src/modules/network_element/service/perf_kpi.impl.go index 4003239..da2f7d0 100644 --- a/src/modules/network_element/service/perf_kpi.impl.go +++ b/src/modules/network_element/service/perf_kpi.impl.go @@ -17,8 +17,15 @@ type PerfKPIImpl struct { } // SelectGoldKPI 通过网元指标数据信息 -func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any { - data := r.perfKPIRepository.SelectGoldKPI(rmUID, neType, startTime, endTime, kpiIds, interval) +func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery) []map[string]any { + // 获取数据指标id + var kpiIds []string + kpiTitles := r.perfKPIRepository.SelectGoldKPITitle(query.NeType) + for _, kpiId := range kpiTitles { + kpiIds = append(kpiIds, kpiId.KPIID) + } + + data := r.perfKPIRepository.SelectGoldKPI(query, kpiIds) if data == nil { return []map[string]any{} } diff --git a/src/modules/network_element/service/udm_auth.impl.go b/src/modules/network_element/service/udm_auth.impl.go index 75a051a..cd1ac30 100644 --- a/src/modules/network_element/service/udm_auth.impl.go +++ b/src/modules/network_element/service/udm_auth.impl.go @@ -62,12 +62,8 @@ func (r *UDMAuthImpl) authDataByRedis(imsi, neID string) []model.UDMAuth { // Save UDM鉴权用户-获取redis全部保存数据库 func (r *UDMAuthImpl) Save(neID string) int64 { - var num int64 = 0 authArr := r.authDataByRedis("*", neID) - // 有数据才清空 - if len(authArr) == 0 { - return num - } + // 数据清空后添加 go r.udmAuthRepository.ClearAndInsert(neID, authArr) return int64(len(authArr)) } diff --git a/src/modules/network_element/service/udm_sub.impl.go b/src/modules/network_element/service/udm_sub.impl.go index 45fc5cd..3bc27c5 100644 --- a/src/modules/network_element/service/udm_sub.impl.go +++ b/src/modules/network_element/service/udm_sub.impl.go @@ -78,12 +78,8 @@ func (r *UDMSubImpl) subDataByRedis(imsi, neID string) []model.UDMSub { // Save UDM签约用户-获取redis全部保存数据库 func (r *UDMSubImpl) Save(neID string) int64 { - var num int64 = 0 subArr := r.subDataByRedis("*", neID) - // 有数据才清空 - if len(subArr) == 0 { - return num - } + // 数据清空后添加 go r.udmSubRepository.ClearAndInsert(neID, subArr) return int64(len(subArr)) } diff --git a/src/modules/system/service/sys_role.impl.go b/src/modules/system/service/sys_role.impl.go index 2530cc0..ebc5b09 100644 --- a/src/modules/system/service/sys_role.impl.go +++ b/src/modules/system/service/sys_role.impl.go @@ -57,12 +57,10 @@ func (r *SysRoleImpl) SelectRoleById(roleId string) model.SysRole { // UpdateRole 修改角色信息 func (r *SysRoleImpl) UpdateRole(sysRole model.SysRole) int64 { rows := r.sysRoleRepository.UpdateRole(sysRole) - if rows > 0 { + if rows > 0 && len(sysRole.MenuIds) > 0 { // 删除角色与菜单关联 r.sysRoleMenuRepository.DeleteRoleMenu([]string{sysRole.RoleID}) - if len(sysRole.MenuIds) > 0 { - r.insertRoleMenu(sysRole.RoleID, sysRole.MenuIds) - } + r.insertRoleMenu(sysRole.RoleID, sysRole.MenuIds) } return rows }