diff --git a/config/etc/default/restconf.yaml b/config/etc/default/restconf.yaml index 923dd38e..74ffff47 100644 --- a/config/etc/default/restconf.yaml +++ b/config/etc/default/restconf.yaml @@ -69,6 +69,7 @@ redis: # deadLine: timeout for io read and write (second) mml: port: 4100 + port2: 5002 sleep: 200 deadLine: 10 user: admin diff --git a/database/upgrade/zupgrade.sql b/database/upgrade/zupgrade.sql index 01558a83..227c00fe 100644 --- a/database/upgrade/zupgrade.sql +++ b/database/upgrade/zupgrade.sql @@ -180,4 +180,7 @@ VALUES ( ALTER TABLE `omc_db`.`alarm` ADD INDEX IF NOT EXISTS `idx_severity_status` ( `alarm_status`, `orig_severity` -) USING BTREE; \ No newline at end of file +) USING BTREE; + +ALTER TABLE `omc_db`.`mml_system` +ADD COLUMN IF NOT EXISTS `object_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'mml' AFTER `mml_display`; \ No newline at end of file diff --git a/features/mml/mml.go b/features/mml/mml.go index 04a7a2fe..b47f87f6 100644 --- a/features/mml/mml.go +++ b/features/mml/mml.go @@ -38,12 +38,14 @@ type MMLRequest struct { var ( // MML interface UriMML = config.DefaultUriPrefix + "/operationManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml" + UriMML2 = config.DefaultUriPrefix + "/operationManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml2" UriMMLDiscard = config.DefaultUriPrefix + "/opeartionManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml" UriNeOmMml = config.DefaultUriPrefix + "/omManagement/{apiVersion}/mml/{netype}/{neid}" UriOmMmlExt = config.DefaultUriPrefix + "/{managedType}/{apiVersion}/elementType/OMC/objectType/mml" UriOmMmlInt = config.DefaultUriPrefix + "/omManagement/{apiVersion}/mml/{neType}/{neId}" CustomUriMML = config.UriPrefix + "/operationManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml" + CustomUriMML2 = config.UriPrefix + "/operationManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml2" CustomUriNeOmMml = config.UriPrefix + "/omManagement/{apiVersion}/mml/{netype}/{neid}" CustomUriOmMmlExt = config.UriPrefix + "/opeartionManagement/{apiVersion}/elementType/OMC/objectType/mml" CustomUriOmMmlInt = config.UriPrefix + "/omManagement/{apiVersion}/mml/{neType}/{neId}" @@ -61,6 +63,126 @@ func init() { } } +func PostMMLToSUPF(w http.ResponseWriter, r *http.Request) { + log.Info("PostMMLToSUPF processing... ") + + vars := mux.Vars(r) + neType := vars["elementTypeValue"] + neInfo := new(dborm.NeInfo) + params := r.URL.Query() + neId := params["ne_id"] + neInfo, err := dborm.XormGetNeInfo(neType, neId[0]) + if err != nil { + log.Error("Failed to dborm.XormGetNeInfo:", err) + services.ResponseInternalServerError500ProcessError(w, err) + return + } + + var buf [20 * 1024]byte + //buf := make([]byte, 0) + var n int + var mmlResult []string + port2 := 5002 + if config.GetYamlConfig().MML.Port2 != 0 { + port2 = config.GetYamlConfig().MML.Port2 + } + + if neInfo != nil { + hostMML := fmt.Sprintf("%s:%d", neInfo.Ip, port2) + 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(TIME_DEAD_LINE * time.Second)) + 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 + } + + 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])) + + body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) + if err != nil { + log.Error("Failed to ReadAll:", err) + services.ResponseNotFound404UriNotExist(w, r) + return + } + log.Trace("Body:", string(body)) + + mmlRequest := new(MMLRequest) + _ = json.Unmarshal(body, mmlRequest) + + for _, mml := range mmlRequest.MML { + mmlCommand := fmt.Sprintf("%s\n", mml) + _, err = conn.Write([]byte(mmlCommand)) + if err != nil { + log.Error("Failed to write:", err) + mmlResult = append(mmlResult, err.Error()) + // response := Response{mmlResult} + // services.ResponseWithJson(w, http.StatusOK, response) + // return + continue + } + 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 + continue + } + log.Trace(string(buf[0 : n-len(neType)-2])) + re1 := regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`) // 匹配包含␛的控制字符 + //re2 := regexp.MustCompile(`\x00`) // 匹配空字符 + re2 := regexp.MustCompile(`[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x1B]`) // 匹配空字符和包含␛的控制字符 + //re := regexp.MustCompile(`[\x00-\x1F\x7F]`) + result := re1.ReplaceAllString(string(buf[0:n-len(neType)-2]), "") + result = re2.ReplaceAllString(result, "") + mmlResult = append(mmlResult, result) + } + + } + + response := Response{mmlResult} + services.ResponseWithJson(w, http.StatusOK, response) +} + func PostMMLToNF(w http.ResponseWriter, r *http.Request) { log.Debug("PostMMLToNF processing... ") diff --git a/lib/routes/routes.go b/lib/routes/routes.go index d2c94e3d..cd6d2130 100644 --- a/lib/routes/routes.go +++ b/lib/routes/routes.go @@ -177,9 +177,12 @@ func init() { Register("POST", mml.UriMML, mml.PostMMLToNF, midware.LogMML) Register("POST", mml.UriMMLDiscard, mml.PostMMLToNF, nil) Register("POST", mml.UriOmMmlExt, mml.PostMMLToOMC, midware.LogMML) - Register("POST", mml.CustomUriMML, mml.PostMMLToNF, midware.LogMML) Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, midware.LogMML) + + Register("POST", mml.UriMML2, mml.PostMMLToSUPF, midware.LogMML) + Register("POST", mml.CustomUriMML2, mml.PostMMLToSUPF, midware.LogMML) + // Northbound Get NRM Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil) diff --git a/restagent/config/config.go b/restagent/config/config.go index 7dcd0c9c..75b6fc34 100644 --- a/restagent/config/config.go +++ b/restagent/config/config.go @@ -92,18 +92,24 @@ type YamlConfig struct { User string `yaml:"user"` Password string `yaml:"password"` TlsSkipVerify bool `yaml:"tlsSkipVerify"` - } `json:"email"` + } `yaml:"email"` SMS struct { ApiURL string `yaml:"apiURL"` AccessKeyID string `yaml:"AccessKeyID"` AccessKeySecret string `yaml:"accessKeySecret"` SignName string `yaml:"signName"` TemplateCode string `yaml:"templateCode"` - } `json:"sms"` + } `yaml:"sms"` + SMSC struct { + Addr string `yaml:"addr"` + UserName string `yaml:"userName"` + Password string `yaml:"password"` + } `yaml:"smsc"` } `yaml:"alarm"` MML struct { Port int `yaml:"port"` + Port2 int `yaml:"port2"` Sleep int64 `yaml:"sleep"` DeadLine int64 `yaml:"deadLine"` User string `yaml:"user"`