del: 移除features、lib和sshsvc目录

This commit is contained in:
TsMask
2025-07-15 14:38:48 +08:00
parent 2b2afd7423
commit edd93f5769
95 changed files with 0 additions and 31062 deletions

View File

@@ -1,142 +0,0 @@
package aaaa
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"github.com/go-resty/resty/v2"
"be.ems/lib/config"
"be.ems/lib/dborm"
"be.ems/lib/log"
"be.ems/lib/oauth"
"be.ems/lib/services"
)
var (
UriAAAASSO = config.DefaultUriPrefix + "/aaaa/{apiVersion}/security/sso" // for 4A external
CustomUriAAAASSO = config.UriPrefix + "/aaaa/{apiVersion}/security/sso" // for 4A external
)
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(3 * time.Second)
}
type AAAATicket struct {
Ticket string `json:"ticket"`
}
type SSOResult struct {
SSO struct {
Result string `json:"result"`
ResultMsg string `json:"result_msg"`
Ticket string `json:"ticket"`
ResultMsgcode string `json:"result_msgcode"`
Account []struct {
Accid string `json:"accid"`
} `json:"account"`
} `json:"sso"`
}
// Get system state from NF/NFs
func GetSSOFromAAAA(w http.ResponseWriter, r *http.Request) {
log.Info("GetSSOFromAAAA processing... ")
vars := r.URL.Query()
ticket := vars["ticket"]
if len(ticket) == 0 {
services.ResponseNotFound404UriNotExist(w, r)
return
}
log.Debug("ticket:", ticket)
log.Debugf("r.RemoteAddr:%s r.Host: %s", r.RemoteAddr, r.Host)
aaaaIp := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
omcIp := r.Host[:strings.Index(r.Host, ":")]
log.Debugf("aaaaIp=%s omcIp=%s", aaaaIp, omcIp)
requestURI2NF := fmt.Sprintf("http://%s:8080/qryUserByTicket", aaaaIp)
log.Debug("requestURI2NF:", requestURI2NF)
aaaaTicket := &AAAATicket{
Ticket: ticket[0],
}
body, err := json.Marshal(aaaaTicket)
if err != nil {
log.Error("Failed to json.Marshal:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
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(requestURI2NF)
if err != nil {
log.Error("Failed to Post:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Debug("response:", response)
switch response.StatusCode() {
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
ssoResult := new(SSOResult)
json.Unmarshal(response.Body(), ssoResult)
var accid string
if len(ssoResult.SSO.Account) != 0 {
accid = ssoResult.SSO.Account[0].Accid
}
log.Debug("accid:", accid)
exist, err := dborm.XormIsExistUser(accid)
if err != nil {
services.ResponseInternalServerError500ProcessError(w, err)
return
}
token := oauth.GenRandToken("aaaa") // Generate new token to session ID
affected, err := dborm.XormInsertSession(accid, r.RemoteAddr, token,
config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
if err != nil {
log.Error("Failed to XormInsertSession:", err)
if affected == -1 {
services.ResponseForbidden403MultiLoginNotAllowed(w)
} else {
services.ResponseBadRequest400IncorrectLogin(w)
}
return
}
if exist == true {
redirectUrl := fmt.Sprintf("http://%s:8888/home.html?user=%s&token=%s", omcIp, accid, token)
services.ResponseRedirect(w, redirectUrl, accid, token)
return
} else {
services.ResponseBadRequest400IncorrectLogin(w)
return
}
default:
services.ResponseForbidden403NotPermission(w)
return
}
}

View File

@@ -1,102 +0,0 @@
package cdr
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"be.ems/lib/config"
"be.ems/lib/core/ctx"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/database/db"
neService "be.ems/src/modules/network_element/service"
wsService "be.ems/src/modules/ws/service"
)
var (
UriCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrEvent"
UriCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile"
CustomUriCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrEvent"
CustomUriCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile"
)
// PostCDREventFrom 接收CDR数据请求
func PostCDREventFrom(w http.ResponseWriter, r *http.Request) {
log.Info("PostCDREventFrom processing... ")
neType := ctx.GetParam(r, "elementTypeValue")
var body struct {
NeType string `json:"neType" `
NeName string `json:"neName" `
RmUID string `json:"rmUID" `
Timestamp int `json:"timestamp" `
CDR map[string]any `json:"CDR" `
}
if err := ctx.ShouldBindJSON(r, &body); err != nil {
services.ResponseInternalServerError500ProcessError(w, err)
return
}
neTypeLower := strings.ToLower(body.NeType)
if neType == "" || neType != neTypeLower {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element types"))
return
}
// 是否存在网元
neInfo := neService.NewNeInfo.FindByRmuid(body.RmUID)
if neInfo.NeType != body.NeType || neInfo.RmUID != body.RmUID {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("network element does not exist"))
return
}
cdrByte, err := json.Marshal(body.CDR)
if err != nil {
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 执行插入表
type CDREvent struct {
ID int64 `json:"-" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type"`
NeName string `json:"neName" gorm:"column:ne_name"`
RmUid string `json:"rmUid" gorm:"column:rm_uid"`
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
CdrJson string `json:"cdrJSON" gorm:"column:cdr_json"` // data JSON String
CreatedAt int64 `json:"-" gorm:"column:created_at"` // 记录创建存储毫秒
}
data := CDREvent{
NeType: body.NeType,
NeName: body.NeName,
RmUid: body.RmUID,
Timestamp: int64(body.Timestamp) * 1000,
CdrJson: string(cdrByte),
CreatedAt: time.Now().UnixMilli(),
}
tableName := fmt.Sprintf("cdr_event_%s", neTypeLower)
if err := db.DB("").Table(tableName).Create(&data).Error; err != nil {
log.Error("Failed to insert "+tableName, err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 推送到ws订阅组
switch neInfo.NeType {
case "IMS":
if v, ok := body.CDR["recordType"]; ok && (v == "MOC" || v == "MTSM") {
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s_%s", wsService.GROUP_IMS_CDR, neInfo.NeId), data)
}
case "SMF":
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s_%s", wsService.GROUP_SMF_CDR, neInfo.NeId), data)
case "SMSC":
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s_%s", wsService.GROUP_SMSC_CDR, neInfo.NeId), data)
case "SGWC":
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s_%s", wsService.GROUP_SGWC_CDR, neInfo.NeId), data)
}
services.ResponseStatusOK204NoContent(w)
}

View File

@@ -1,95 +0,0 @@
//go:build linux
// +build linux
package cm
import (
"bytes"
"context"
"os/exec"
"time"
"be.ems/lib/log"
)
func ExecCmd(command string) error {
log.Debug("Exec command:", command)
cmd := exec.Command("/bin/bash", "-c", command)
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return err
}
/*
if err := cmd.Start(); err != nil {
log.Error("Start error: ", err)
return err
}
if err := cmd.Wait(); err != nil {
log.Error("Wait error: ", err)
return err
}
*/
return nil
}
func ExecShell(command string) error {
in := bytes.NewBuffer(nil)
cmd := exec.Command("sh")
cmd.Stdin = in
in.WriteString(command)
in.WriteString("exit\n")
if err := cmd.Start(); err != nil {
return err
}
return nil
}
func ExecOsCmd(command, os string) error {
log.Debugf("Exec %s command:%s", os, command)
var cmd *exec.Cmd
switch os {
case "Linux":
cmd = exec.Command(command)
case "Windows":
cmd = exec.Command("cmd", "/C", command)
}
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return err
}
return nil
}
func StartSSHCmdWithTimeout(duration int, sshHost, cmdStr string) error {
timeout := time.Duration(duration) * time.Second
ctx, cancel := context.WithTimeout(context.Background(), timeout) // 设置超时
defer cancel()
cmd := exec.CommandContext(ctx, "ssh", sshHost, cmdStr)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Start()
if err != nil {
return err
}
return nil
}
func RunSSHCmd(sshHost, cmdStr string) error {
cmd := exec.Command("ssh", sshHost, cmdStr)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
return err
}
return nil
}

View File

@@ -1,83 +0,0 @@
//go:build windows
// +build windows
package cm
import (
"bytes"
"context"
"os/exec"
"time"
"be.ems/lib/log"
)
func ExecCmd(command string) error {
log.Debug("Exec command:", command)
cmd := exec.Command("cmd", "/C", command)
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return err
}
/*
if err := cmd.Start(); err != nil {
log.Error("Start error: ", err)
return err
}
if err := cmd.Wait(); err != nil {
log.Error("Wait error: ", err)
return err
}
*/
return nil
}
func ExecOsCmd(command, os string) error {
log.Debugf("Exec %s command:%s", os, command)
var cmd *exec.Cmd
switch os {
case "Linux":
cmd = exec.Command(command)
case "Windows":
cmd = exec.Command("cmd", "/C", command)
}
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return err
}
return nil
}
func StartSSHCmdWithTimeout(duration int, sshHost, cmdStr string) error {
timeout := time.Duration(duration) * time.Second
ctx, cancel := context.WithTimeout(context.Background(), timeout) // 设置超时
defer cancel()
cmd := exec.CommandContext(ctx, "ssh", sshHost, cmdStr)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Start()
if err != nil {
return err
}
return nil
}
func RunSSHCmd(sshHost, cmdStr string) error {
cmd := exec.Command("ssh", sshHost, cmdStr)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
return err
}
return nil
}

View File

@@ -1,991 +0,0 @@
package cm
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"strings"
"time"
"be.ems/lib/config"
"be.ems/lib/dborm"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/constants"
"be.ems/src/framework/database/db"
neService "be.ems/src/modules/network_element/service"
"github.com/go-resty/resty/v2"
"github.com/gorilla/mux"
)
var (
// NE CM export/import
NeCmUri = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/cm"
// NE info
UriNeInfo = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/neInfo"
// NE backup file
UriNeCmFile = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{neType}/neBackup/{fileName}"
// service action uri, action: start/stop/restart
UriNeService = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/service/{action}"
// nf instance action uri, action: start/stop/restart
UriNeInstance = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/instance/{action}"
CustomNeCmUri = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/cm"
CustomUriNeInfo = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/neInfo"
CustomUriNeCmFile = config.UriPrefix + "/systemManagement/{apiVersion}/{neType}/neBackup/{fileName}"
// service action uri, action: start/stop/restart
CustomUriNeService = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/service/{action}"
// nf instance action uri, action: start/stop/restart
CustomUriNeInstance = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/instance/{action}"
)
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) {
log.Debug("GetNeInfo processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
// no, _ := strconv.ParseInt(neId, 10, 64)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Error("dborm.XormGetNeInfo is failed:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
var response services.DataResponse
response.Data = neInfo
services.ResponseWithJson(w, http.StatusOK, response)
}
type OmcNeConfig struct {
NeId string `json:"neId" xorm:"ne_id"` // 网元标识(内部),
RmUID string `json:"rmUID" xorm:"rm_uid"` // rmUID 网元唯一标识
NeName string `json:"neName" xorm:"ne_name"` // 网元名称(内部)/友好名称(北向资源/性能等使用)
PvFlag string `json:"pvFlag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理
Province string `json:"province" xorm:"province"` // 网元所在省份
VendorName string `json:"vendorName" xorm:"vendor_name"` // 厂商名称
// ManagedBy string `json:"managedBy" xorm:"managed_by"` // 管理ManagedElement的ManagementNode对象类的DN值
Dn string `json:"dn" xorm:"dn"` // 资源里边的ManagedBy性能的Dn网络唯一标识
}
func PostNeInfo(w http.ResponseWriter, r *http.Request) {
log.Debug("PostNeInfo processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neTypeUpper := strings.ToUpper(neType)
syncFlag := services.GetUriParamString(r, "sync2ne", ",", false, false)
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("Failed to o.ReadAll:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
log.Trace("Body:", string(body))
neInfo := new(dborm.NeInfo)
err = json.Unmarshal(body, neInfo)
if err != nil {
log.Error("Failed to json.Unmarshal:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
//neInfo.UpdateTime = time.Now().Format(time.DateTime)
neInfo.UpdateTime = time.Now()
log.Debug("NE info:", neInfo)
//if !config.GetYamlConfig().OMC.Chk2Ne {
if syncFlag == "false" || neTypeUpper == config.GetYamlConfig().OMC.NeType {
neInfo.Status = NEStatusMaintain
affected, err := dborm.XormInsertNeInfo(neInfo)
if err != nil {
log.Error("Failed to insert Ne info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 刷新缓存不存在结构体网元Id空字符串
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
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("%s/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig?ne_id=%s", config.DefaultUriPrefix, strings.ToLower(neInfo.NeType), neInfo.NeId)
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.ResponseInternalServerError500ProcessError(w, err)
return
} else if affected <= 0 {
log.Infof("Not record affected to insert ne_info")
}
// 刷新缓存不存在结构体网元Id空字符串
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
services.ResponseStatusOK204NoContent(w)
return
default:
log.Info("response body:", string(response.Body()))
body := new(map[string]interface{})
_ = json.Unmarshal(response.Body(), &body)
respMsg["error"] = body
}
services.ResponseWithJson(w, response.StatusCode(), respMsg)
return
}
}
func PutNeInfo(w http.ResponseWriter, r *http.Request) {
log.Debug("PutNeInfo processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neTypeLower := strings.ToLower(neType)
neTypeUpper := strings.ToUpper(neType)
syncFlag := services.GetUriParamString(r, "sync2ne", ",", false, false)
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("Failed to io.ReadAll:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
neInfo := new(dborm.NeInfo)
_ = json.Unmarshal(body, neInfo)
neInfo.NeType = strings.ToUpper(neType)
neInfo.UpdateTime = time.Now()
log.Debug("NE info:", neInfo)
//if !config.GetYamlConfig().OMC.Chk2Ne {
if syncFlag == "false" || neTypeUpper == config.GetYamlConfig().OMC.NeType {
neInfo.Status = NEStatusMaintain
affected, err := dborm.XormUpdateNeInfo(neInfo)
if err != nil {
log.Error("Failed to update Ne info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 刷新缓存不存在结构体网元Id空字符串
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
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("%s/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig?ne_id=%s", config.DefaultUriPrefix, neTypeLower, neInfo.NeId)
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{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}).
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.ResponseInternalServerError500ProcessError(w, err)
return
} else if affected <= 0 {
log.Infof("Not record affected to insert ne_info")
}
// 刷新缓存不存在结构体网元Id空字符串
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
services.ResponseStatusOK204NoContent(w)
return
default:
log.Info("response body:", string(response.Body()))
body := new(map[string]interface{})
_ = json.Unmarshal(response.Body(), &body)
respMsg["error"] = body
}
services.ResponseWithJson(w, response.StatusCode(), respMsg)
return
}
}
func DeleteNeInfo(w http.ResponseWriter, r *http.Request) {
log.Debug("DeleteNeInfo processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
neInfo := new(dborm.NeInfo)
_ = json.Unmarshal(body, neInfo)
neInfo.NeType = strings.ToUpper(neType)
neInfo.NeId = services.GetUriParamString(r, "ne_id", ",", false, false)
neInfo, err = dborm.XormGetNeInfo(neInfo.NeType, neInfo.NeId)
if err != nil || neInfo == nil {
log.Error("Failed to delete Ne info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Debug("NE info:", neInfo)
// if NE in active status, can't delete NE
if !IsActiveNF(neInfo) {
affected, err := dborm.XormDeleteNeInfo(neInfo)
if err != nil {
log.Error("Failed to delete Ne info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 刷新缓存不存在结构体网元Id空字符串
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
return
}
err = global.ErrCMCannotDeleteActiveNE
log.Error(err)
services.ResponseInternalServerError500ProcessError(w, err)
}
func IsActiveNF(neInfo *dborm.NeInfo) bool {
log.Debug("IsActiveNF processing... ")
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
requestURI := fmt.Sprintf(config.UriPrefix+"/systemManagement/v1/elementType/%s/objectType/systemState",
strings.ToLower(neInfo.NeType))
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(hostUri + requestURI)
if err != nil {
log.Error("Failed to Get:", err)
return false
}
switch response.StatusCode() {
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
return true
}
return false
}
func ExportCmFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("ExportCmFromNF processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neTypeUpper := strings.ToUpper(neType)
neTypeLower := strings.ToLower(neType)
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
// neInfo := new(dborm.NeInfo)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Errorf("Failed to get ne_info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Debug("neInfo:", neInfo)
nePath := fmt.Sprintf("%s/etc/%s", config.GetYamlConfig().OMC.Backup, neTypeLower)
isExist, err := global.PathExists(nePath)
if err != nil {
log.Errorf("Failed to stat:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
if isExist {
err = os.RemoveAll(nePath)
if err != nil {
log.Errorf("Failed to RemoveAll:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
}
err = os.MkdirAll(nePath, os.ModePerm)
if err != nil {
log.Errorf("Failed to MkdirAll:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
var scpCmd string
ipType := global.ParseIPAddr(neInfo.Ip)
omcNetypeLower := strings.ToLower(config.GetYamlConfig().OMC.NeType)
etcListIMS := "{*.yaml,mmtel,vars.cfg}"
if config.GetYamlConfig().NE.EtcListIMS != "" {
etcListIMS = config.GetYamlConfig().NE.EtcListIMS
}
switch neTypeLower {
case omcNetypeLower:
if ipType == global.IsIPv4 {
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/etc/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.OmcDir, config.GetYamlConfig().OMC.Backup, neTypeLower)
} else {
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/etc/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.OmcDir, config.GetYamlConfig().OMC.Backup, neTypeLower)
}
case "ims":
if ipType == global.IsIPv4 {
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/%s/%s %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.EtcDir, neTypeLower,
etcListIMS, config.GetYamlConfig().OMC.Backup, neTypeLower)
} else {
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/%s/%s %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.EtcDir, neTypeLower,
etcListIMS, config.GetYamlConfig().OMC.Backup, neTypeLower)
}
case "mme":
if ipType == global.IsIPv4 {
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/%s/*.conf %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
} else {
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/%s/*.conf %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
}
default:
if ipType == global.IsIPv4 {
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/%s/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
} else {
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/%s/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
}
}
zipFile := fmt.Sprintf("%s-%s-etc-%s.zip", neTypeLower, strings.ToLower(neInfo.NeId), time.Now().Format(global.DateData))
zipFilePath := config.GetYamlConfig().OMC.Backup + "/" + zipFile
zipCmd := fmt.Sprintf("cd %s/etc && zip -r %s %s/*", config.GetYamlConfig().OMC.Backup, zipFilePath, neTypeLower)
command := fmt.Sprintf("%s&&%s", scpCmd, zipCmd)
log.Debug("command:", command)
err = ExecCmd(command)
if err != nil {
log.Error("Faile to exec command:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
md5Sum, err := global.GetFileMD5Sum(zipFilePath)
if err != nil {
log.Error("Faile to md5sum:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
//log.Debug("md5Str:", md5Sum)
path := config.GetYamlConfig().OMC.Backup
neBackup := dborm.NeBackup{NeType: neTypeUpper, NeId: neId, FileName: zipFile, Path: path, Md5Sum: md5Sum}
_, err = dborm.XormInsertTableOne("ne_backup", neBackup)
if err != nil {
log.Error("Faile to XormInsertTableOne:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
//services.ResponseFileWithNameAndMD5(w, http.StatusOK, zipFile, path, md5Sum)
services.ResponseStatusOK204NoContent(w)
}
type ImportCMJson struct {
FileName string `json:"fileName"`
}
func ImportCmToNF(w http.ResponseWriter, r *http.Request) {
log.Debug("ImportCmToNF processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neTypeUpper := strings.ToUpper(neType)
neTypeLower := strings.ToLower(neType)
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
var fileName, path string
if services.IsJsonContentType(r) {
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
log.Debug("Body:", string(body))
importCMJson := new(ImportCMJson)
_ = json.Unmarshal(body, importCMJson)
fileName = importCMJson.FileName
path = config.GetYamlConfig().OMC.Backup
} else {
path = config.GetYamlConfig().OMC.Upload
fileNamePath, err := services.HandleUploadFile(r, path, "")
if err != nil {
log.Error("Faile to HandleUploadFile:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
fileName = fileNamePath
}
filePath := fmt.Sprintf("%s/%s", path, fileName)
// neInfo := new(dborm.NeInfo)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Errorf("Failed to get ne_info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Debug("neInfo:", neInfo)
md5Sum, err := global.GetFileMD5Sum(filePath)
if err != nil {
log.Error("Faile to GetFileMD5Sum:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
//neBackup := dborm.NeBackup{NeType: neType, NeId: neId, Md5Sum: md5Sum}
//log.Debug("neBackup:", neBackup)
where := fmt.Sprintf("ne_type='%s' and ne_id='%s' and md5_sum='%s'", neTypeUpper, neId, md5Sum)
has, err := dborm.XormExistTableOne("ne_backup", where)
if err != nil {
log.Error("Faile to XormInsertTableOne:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else if !has {
err = global.ErrCMInvalidBackupFile
log.Error(err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// nePath := fmt.Sprintf("%s/etc/%s", config.GetYamlConfig().OMC.Upload, neTypeLower)
// isExist, err := global.PathExists(nePath)
// if err != nil {
// log.Errorf("Failed to stat:", err)
// services.ResponseInternalServerError500ProcessError(w, err)
// return
// }
// if isExist {
// err = os.RemoveAll(nePath)
// if err != nil {
// log.Errorf("Failed to remove:", err)
// services.ResponseInternalServerError500ProcessError(w, err)
// return
// }
// }
// unzipCmd := fmt.Sprintf("unzip -o %s -d %s", filePath, config.GetYamlConfig().OMC.Upload)
// var scpCmd string
// ipType := global.ParseIPAddr(neInfo.Ip)
// if ipType == global.IsIPv4 {
// scpCmd = fmt.Sprintf("scp -r %s/etc/%s %s@%s:%s", config.GetYamlConfig().OMC.Upload,
// neTypeLower, config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.EtcDir)
// } else {
// scpCmd = fmt.Sprintf("scp -r %s/etc/%s %s@[%s]:%s", config.GetYamlConfig().OMC.Upload,
// neTypeLower, config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.EtcDir)
// }
// err = ExecCmd(fmt.Sprintf("%s && %s", unzipCmd, scpCmd))
// if err != nil {
// log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
// services.ResponseInternalServerError500ProcessError(w, err)
// return
// }
// nePath := fmt.Sprintf("%s/etc/%s", config.GetYamlConfig().OMC.Upload, neTypeLower)
// isExist, err := global.PathExists(nePath)
// if err != nil {
// log.Errorf("Failed to stat:", err)
// services.ResponseInternalServerError500ProcessError(w, err)
// return
// }
// if isExist {
// err = os.RemoveAll(nePath)
// if err != nil {
// log.Errorf("Failed to remove:", err)
// services.ResponseInternalServerError500ProcessError(w, err)
// return
// }
// }
var scpZipCmd string
ipType := global.ParseIPAddr(neInfo.Ip)
if ipType == global.IsIPv4 {
scpZipCmd = fmt.Sprintf("scp -r %s %s@%s:%s", filePath,
config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.ScpDir)
} else {
scpZipCmd = fmt.Sprintf("scp -r %s %s@[%s]:%s", filePath,
config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.ScpDir)
}
err = ExecCmd(scpZipCmd)
if err != nil {
log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
neFilePath := config.GetYamlConfig().NE.ScpDir + "/" + fileName
var unzipCmd string
if neTypeLower != "omc" {
unzipCmd = fmt.Sprintf("sudo unzip -o %s -d %s", neFilePath, config.GetYamlConfig().NE.EtcDir)
} else {
unzipCmd = fmt.Sprintf("sudo unzip -oj %s -d %s/etc", neFilePath, config.GetYamlConfig().NE.OmcDir)
}
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
cmd := exec.Command("ssh", sshHost, unzipCmd)
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("Faile to execute command:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
services.ResponseStatusOK204NoContent(w)
}
func DownloadNeBackupFile(w http.ResponseWriter, r *http.Request) {
log.Debug("DownloadNeBackupFile processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["neType"]
if neType == "" {
log.Error("neType is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neTypeUpper := strings.ToUpper(neType)
//neTypeLower := strings.ToLower(neType)
fileName := vars["fileName"]
if fileName == "" {
log.Error("fileName is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
sql := fmt.Sprintf("select * from ne_backup where ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
neBackup, err := db.RawDB("", sql, nil)
if err != nil {
log.Error("Faile to XormGetDataBySQL:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else if len(neBackup) == 0 {
err := global.ErrCMNotFoundTargetBackupFile
log.Error(err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
path := fmt.Sprint(neBackup[0]["path"])
md5Sum := fmt.Sprint(neBackup[0]["md5_sum"])
services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, md5Sum)
}
func DeleteNeBackupFile(w http.ResponseWriter, r *http.Request) {
log.Debug("DeleteNeBackupFile processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["neType"]
if neType == "" {
log.Error("neType is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neTypeUpper := strings.ToUpper(neType)
//neTypeLower := strings.ToLower(neType)
fileName := vars["fileName"]
if fileName == "" {
log.Error("fileName is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
sql := fmt.Sprintf("select * from ne_backup where ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
neBackup, err := db.RawDB("", sql, nil)
if err != nil {
log.Error("Faile to XormGetDataBySQL:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else if len(neBackup) == 0 {
err := global.ErrCMNotFoundTargetBackupFile
log.Error(err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
where := fmt.Sprintf("ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
affected, err := dborm.XormDeleteDataByWhere(where, "ne_backup")
if err != nil || affected == 0 {
log.Error("Faile to XormGetDataBySQL:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
path := neBackup[0]["path"]
filePath := fmt.Sprintf("%s/%s", path, fileName)
err = os.Remove(filePath)
if err != nil {
log.Error("Faile to Remove:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
services.ResponseStatusOK204NoContent(w)
}
func PostNeServiceAction(w http.ResponseWriter, r *http.Request) {
log.Debug("PostNeServiceAction processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
//neTypeUpper := strings.ToUpper(neType)
neTypeLower := strings.ToLower(neType)
action := vars["action"]
neId := services.GetUriParamString(r, "neId", ",", false, false)
// neInfo := new(dborm.NeInfo)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Error("Failed to get ne_info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Debug("neInfo:", neInfo)
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
switch neTypeLower {
case "omc":
// send 204 to fe firstly
services.ResponseStatusOK204NoContent(w)
//actionCmd := fmt.Sprintf("sudo %s/bin/omcsvc.sh %s", config.GetYamlConfig().NE.OmcDir, action)
actionCmd := fmt.Sprintf("sudo systemctl %s omc", action)
go RunSSHCmd(sshHost, actionCmd)
return
// cmd := exec.Command("ssh", sshHost, actionCmd)
// out, err := cmd.CombinedOutput()
// log.Debugf("Exec output: %v", string(out))
// if err != nil {
// log.Errorf("Faile to execute ssh %s omc:%v", action, err)
// services.ResponseInternalServerError500ProcessError(w, err)
// return
// }
case "ims":
switch action {
case "start", "stop":
actionCmd := fmt.Sprintf("sudo ims-%s", action)
cmd := exec.Command("ssh", sshHost, actionCmd)
out, err := cmd.CombinedOutput()
log.Debugf("Exec output: %v", string(out))
if err != nil {
log.Errorf("Faile to execute %s command:%v", actionCmd, err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
case "restart":
actionCmd := "sudo ims-stop && sudo ims-start"
cmd := exec.Command("ssh", sshHost, actionCmd)
out, err := cmd.CombinedOutput()
log.Debugf("Exec output: %v", string(out))
if err != nil {
log.Errorf("Faile to execute %s command:%v", actionCmd, err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
default:
err = global.ErrCMUnknownServiceAction
log.Errorf("%v, action:%s", err, action)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
default:
actionCmd := fmt.Sprintf("sudo systemctl %s %s.service", action, neTypeLower)
cmd := exec.Command("ssh", sshHost, actionCmd)
out, err := cmd.CombinedOutput()
log.Debugf("Exec output: %v", string(out))
if err != nil {
log.Error("Faile to execute command:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
}
services.ResponseStatusOK204NoContent(w)
}
func PostNeInstanceAction(w http.ResponseWriter, r *http.Request) {
log.Debug("PostNeInstanceAction processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
//neTypeUpper := strings.ToUpper(neType)
//neTypeLower := strings.ToLower(neType)
action := vars["action"]
neId := services.GetUriParamString(r, "neId", ",", false, false)
// neInfo := new(dborm.NeInfo)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Errorf("Failed to get ne_info:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Debug("neInfo:", neInfo)
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
switch action {
case "poweron":
actionCmd := "sudo poweron"
cmd := exec.Command("ssh", sshHost, actionCmd)
out, err := cmd.CombinedOutput()
log.Debugf("Exec output: %v", string(out))
if err != nil {
log.Error("Faile to execute ssh %s omc:", action, err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
case "poweroff":
actionCmd := "sudo poweroff"
cmd := exec.Command("ssh", sshHost, actionCmd)
out, err := cmd.CombinedOutput()
log.Debugf("Exec output: %v", string(out))
if err != nil {
log.Error("Faile to execute ssh sudo poweroff:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
case "reboot":
actionCmd := "sudo reboot"
cmd := exec.Command("ssh", sshHost, actionCmd)
out, err := cmd.CombinedOutput()
log.Debugf("Exec output: %v", string(out))
if err != nil {
log.Error("Faile to execute ssh sudo reboot:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
default:
err = global.ErrCMUnknownInstanceAction
log.Errorf("%v, action:%s", err, action)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
services.ResponseStatusOK204NoContent(w)
}

View File

@@ -1,46 +0,0 @@
package cm_omc
import (
"fmt"
"net/http"
"be.ems/lib/services"
"github.com/gin-gonic/gin"
)
func (o *ConfigOMC) Get(c *gin.Context) {
paramName := c.Param("paramName")
results, err := o.Query(paramName)
if err != nil {
c.JSON(http.StatusInternalServerError, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusOK, services.DataResp(results))
}
func (o *ConfigOMC) Post(c *gin.Context) {
err := fmt.Errorf("method not allowed")
c.JSON(http.StatusMethodNotAllowed, services.ErrResp(err.Error()))
}
func (o *ConfigOMC) Put(c *gin.Context) {
paramName := c.Param("paramName")
var paramData map[string]any
if err := c.ShouldBindJSON(&paramData); err != nil {
c.JSON(http.StatusBadRequest, services.ErrResp(err.Error()))
return
}
result, err := o.Modify(paramName, paramData)
if err != nil {
c.JSON(http.StatusInternalServerError, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusOK, services.DataResp(result))
}
func (o *ConfigOMC) Delete(c *gin.Context) {
err := fmt.Errorf("method not allowed")
c.JSON(http.StatusMethodNotAllowed, services.ErrResp(err.Error()))
}

View File

@@ -1,69 +0,0 @@
package cm_omc
import (
"fmt"
"be.ems/lib/config"
)
const (
PASSWORD_MASK = "********"
)
func (o *ConfigOMC) Query(paramName string) (any, error) {
var results []any
switch paramName {
case "alarmEmailForward":
result := config.GetYamlConfig().Alarm.EmailForward
result.Password = PASSWORD_MASK
results = append(results, result)
case "alarmSMSForward":
result := config.GetYamlConfig().Alarm.SMSCForward
result.Password = PASSWORD_MASK
results = append(results, result)
default:
return nil, fmt.Errorf("invalid source parameter")
}
return results, nil
}
func (o *ConfigOMC) Add() {
}
func (o *ConfigOMC) Modify(paramName string, paramData map[string]any) (any, error) {
var results []any
switch paramName {
case "alarmEmailForward":
param := &(config.GetYamlConfig().Alarm.EmailForward)
config.UpdateStructFromMap(param, paramData)
result := *param
results = append(results, result)
err := config.WriteOrignalConfig(config.YamlConfigInfo.FilePath, paramName, paramData)
if err != nil {
fmt.Println("failed to write config yaml file:", err)
return results, err
}
case "alarmSMSForward":
param := &(config.GetYamlConfig().Alarm.SMSCForward)
config.UpdateStructFromMap(param, paramData)
result := *param
results = append(results, result)
err := config.WriteOrignalConfig(config.YamlConfigInfo.FilePath, paramName, paramData)
if err != nil {
fmt.Println("failed to write config yaml file:", err)
return results, err
}
default:
return nil, fmt.Errorf("invalid source parameter")
}
return results, nil
}
func (o *ConfigOMC) Remove() {
}

View File

@@ -1,26 +0,0 @@
package cm_omc
type ConfigOMC struct{}
type SystemConfig struct {
ForwardFlag bool `json:"forwardFlag"`
}
type AlarmEmailForward struct {
Enable bool `json:"enable"`
EmailList string `json:"emailList"`
SMTP string `json:"smtp"`
Port uint16 `json:"port"`
User string `json:"user"`
Password string `json:"password"`
TLSSkipVerify bool `json:"tlsSkipVerify"`
}
type AlarmSMSForward struct {
Enable bool `json:"enable"`
MobileList string `json:"mobileList"`
SMSCAddr string `json:"smscAddr"`
SystemID string `json:"systemID"`
Password string `json:"password"`
SystemType string `json:"systemType"`
}

View File

@@ -1,30 +0,0 @@
package cm_omc
import (
"be.ems/src/framework/middleware"
"github.com/gin-gonic/gin"
)
// Register Routes for file_export
func Register(r *gin.RouterGroup) {
cmOMC := r.Group("/omc")
{
var o *ConfigOMC
cmOMC.GET("/config/:paramName",
middleware.AuthorizeUser(nil),
o.Get,
)
cmOMC.POST("/config/:paramName",
middleware.AuthorizeUser(nil),
o.Post,
)
cmOMC.PUT("/config/:paramName",
middleware.AuthorizeUser(nil),
o.Put,
)
cmOMC.DELETE("/config/:paramName",
middleware.AuthorizeUser(nil),
o.Delete,
)
}
}

View File

@@ -1,208 +0,0 @@
package cm
import (
"strings"
"be.ems/lib/config"
"be.ems/lib/core/ctx"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/services"
"encoding/json"
"fmt"
"io"
"net/http"
neService "be.ems/src/modules/network_element/service"
"github.com/go-resty/resty/v2"
"github.com/gorilla/mux"
)
var (
// parameter config management
ParamConfigUri = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/config/{paraName}"
CustomParamConfigUri = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/config/{paraName}"
)
func GetParamConfigFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("GetParamConfigFromNF processing... ")
neId := ctx.GetQuery(r, "ne_id")
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" || neId == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId)
var response services.DataResponse
if neInfo.NeId == neId && neInfo.NeId != "" {
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
log.Debug("requestURI2NF:", requestURI2NF)
resp, err := client.R().
EnableTrace().
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("Failed to Get from NF:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else {
_ = json.Unmarshal(resp.Body(), &response)
}
log.Debug("response:", response)
}
services.ResponseWithJson(w, http.StatusOK, response)
}
func PostParamConfigToNF(w http.ResponseWriter, r *http.Request) {
log.Debug("PostParamConfigToNF processing... ")
neId := ctx.GetQuery(r, "ne_id")
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" || neId == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId || neInfo.NeId == "" {
log.Error("neId is empty")
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
log.Debug("requestURI2NF: POST ", requestURI2NF)
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
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).
Post(requestURI2NF)
if err != nil {
log.Error("Failed to POST to NF:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
services.ResponseWithJson(w, http.StatusNoContent, response)
}
func PutParamConfigToNF(w http.ResponseWriter, r *http.Request) {
log.Debug("PutParamConfigToNF processing... ")
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// OMC配置接口 /api/rest/systemManagement/v1/elementType/omc/objectType/config/omcNeConfig
if v, ok := vars["paraName"]; ok && v == "omcNeConfig" && strings.ToLower(neType) == "omc" {
PutOMCNeConfig(w, r)
return
}
neId := ctx.GetQuery(r, "ne_id")
neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId || neInfo.NeId == "" {
log.Error("neId is empty")
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
log.Debug("requestURI2NF: PUT ", requestURI2NF)
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
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 to NF:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
services.ResponseWithJson(w, http.StatusNoContent, response)
}
// PutOMCNeConfig 网元OMC配置
//
// 目前没配置返回204
func PutOMCNeConfig(w http.ResponseWriter, r *http.Request) {
services.ResponseStatusOK204NoContent(w)
}
func DeleteParamConfigToNF(w http.ResponseWriter, r *http.Request) {
log.Debug("DeleteParamConfigToNF processing... ")
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
log.Error("elementTypeValue is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neId := ctx.GetQuery(r, "ne_id")
neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId || neInfo.NeId == "" {
log.Error("neId is empty")
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
log.Debug("requestURI2NF: DELETE ", requestURI2NF)
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"}).
Delete(requestURI2NF)
if err != nil {
log.Error("Failed to delete parameter:", err)
services.ResponseInternalServerError500NFConnectRefused(w)
return
}
services.ResponseWithJson(w, http.StatusNoContent, response)
}

View File

@@ -1,17 +0,0 @@
package cm
import (
cm_omc "be.ems/features/cm/omc"
"be.ems/lib/log"
"github.com/gin-gonic/gin"
)
func InitSubServiceRoute(r *gin.Engine) {
log.Info("======init PM group gin.Engine")
cmGroup := r.Group("/cm")
// register sub modules routes
cm_omc.Register(cmGroup)
// return featuresGroup
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,859 +0,0 @@
package dbrest
import (
"encoding/json"
"fmt"
"io"
"net/http"
"regexp"
"strings"
"be.ems/lib/config"
"be.ems/lib/core/ctx"
"be.ems/lib/dborm"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/database/db"
"github.com/gorilla/mux"
)
type XormResponse struct {
Data interface{} `json:"data"`
}
type XormInsertResponse struct {
Data interface{} `json:"data"`
}
var (
// database management rest pattern discard
XormGetDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
XormSelectDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/select/{elementTypeValue}/{objectTypeValue}"
XormInsertDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/insert/{elementTypeValue}/{objectTypeValue}"
XormUpdateDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/update/{elementTypeValue}/{objectTypeValue}"
XormDeleteDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/delete/{elementTypeValue}/{objectTypeValue}"
CustomXormGetDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
CustomXormSelectDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/select/{elementTypeValue}/{objectTypeValue}"
CustomXormInsertDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/insert/{elementTypeValue}/{objectTypeValue}"
CustomXormUpdateDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/update/{elementTypeValue}/{objectTypeValue}"
CustomXormDeleteDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/delete/{elementTypeValue}/{objectTypeValue}"
XormCommonUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for internal
XormDatabaseUri = config.DefaultUriPrefix + "/database/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for crontask
XormDataRestUri = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
XormExtDataUri = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for external
XormDataSQLUri = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for external
CustomXormCommonUri = config.UriPrefix + "/databaseManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for internal
CustomXormExtDataUri = config.UriPrefix + "/dataManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for external
CustomXormDataSQLUri = config.UriPrefix + "/dataManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for external
// 查询数据库连接情况
UriDbConnection = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/dbConnection"
CustomUriDbConnection = config.UriPrefix + "/dataManagement/{apiVersion}/dbConnection" // for external
// 终结非法的数据库连接
UriDbStop = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/dbStop"
CustomUriDbStop = config.UriPrefix + "/dataManagement/{apiVersion}/dbStop" // for external
)
func GetUriSQLArray(r *http.Request) []string {
var sa []string
vars := r.URL.Query()
// 默认SQL
if s, ok := vars["SQL"]; ok {
for _, r := range s {
if r != "" {
sa = append(sa, r)
}
}
}
// 查询总数
if totalSQL, ok := vars["totalSQL"]; ok {
if totalSQL[0] != "" {
sa = append(sa, totalSQL[0])
}
}
// 查询列表
if rowsSQL, ok := vars["rowsSQL"]; ok {
if rowsSQL[0] != "" {
sa = append(sa, rowsSQL[0])
}
}
if len(sa) == 0 {
log.Info("SQL is not exist")
return nil
}
log.Debug("SQL array:", sa)
return sa
}
// Get table name from SQL
func GetTableNameFromSQL(s string) string {
ls := strings.ToLower(s)
i1 := strings.Index(ls, "from")
i2 := strings.Index(ls, "where")
var ts string
if i1 > 0 {
if i2 > 0 && i2 > i1 {
ts = ls[i1+4 : i2]
}
if i2 < 0 {
ts = ls[i1+4:]
}
}
tn := strings.Trim(ts, " ")
log.Debug("i1:", i1, "i2:", i2, "tn:", tn)
return tn
}
func GetTableName(sql string) string {
ls := strings.ToLower(sql)
re := regexp.MustCompile(`from\s+(\S+)`)
matches := re.FindStringSubmatch(ls)
if len(matches) < 2 {
return ""
}
return matches[1]
}
func IsQuerySQL(s string) bool {
ts := strings.Trim(strings.ToLower(s), " ")
return strings.Index(ts, "select") == 0
}
// xorm Get data from database
func ExtDatabaseExecSQL(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseExecSQL processing... ")
// var err error
// _, err = services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
//vars := mux.Vars(r)
//tblName := vars["objectTypeValue"]
var sql = GetUriSQLArray(r)
// select as must, todo ...
ls := services.ExtGetUriPageLimitString(r)
// data := make([]map[string]interface{}, 0)
// xormResponse := make([]map[string]interface{}, len(sql))
var xormResponse XormResponse
data := make([]map[string]interface{}, 0)
for i, s := range sql {
log.Tracef("SQL[%d]: %s", i, sql[i])
//rows := make([]map[string]interface{}, 0)
mapRows := make(map[string]interface{})
if s != "" {
// err = XEngine.SQL(s).Find(&rows)
// if IsQuerySQL(s) == false {
// services.ResponseNotAcceptable406QuerySQLError(w)
// return
// }
querySQL := s
if i == (len(sql) - 1) {
querySQL = querySQL + " " + ls
}
log.Debug("querySQL:", querySQL)
rows, err := db.RawDB("", querySQL, nil)
if err != nil {
log.Error("SQL failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
tableName := GetTableName(s)
log.Debugf("s:%s tableName:%s", s, tableName)
mapRows[tableName] = rows
data = append(data, mapRows)
log.Trace("data:", data)
}
i++
}
xormResponse.Data = data
services.ResponseWithJson(w, http.StatusOK, xormResponse)
}
// xorm Get data from database
func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseGetData processing... ")
var sql []string
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
pack := "dbrest"
vars := mux.Vars(r)
module := ""
dbname := vars["elementTypeValue"]
tbname := vars["objectTypeValue"]
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
// log.Error("Failed to get permission:", err)
// services.ResponseForbidden403NotPermission(w)
// return
// }
// if !exist {
// log.Error("Not permission!")
// services.ResponseForbidden403NotPermission(w)
// return
// }
sql = GetUriSQLArray(r)
// select as must, todo ...
if sql == nil {
wc := services.GetUriLocString(r)
if wc == "" {
sql = append(sql, fmt.Sprintf("select * from %s", tbname))
} else {
sql = append(sql, fmt.Sprintf("select * from %s where %s", tbname, wc))
}
}
ls := services.ExtGetUriPageLimitString(r)
// data := make([]map[string]interface{}, 0)
// xormResponse := make([]map[string]interface{}, len(sql))
var xormResponse XormResponse
data := make([]map[string]interface{}, 0)
for i, s := range sql {
log.Tracef("SQL[%d]: %s", i, sql[i])
mapRows := make(map[string]interface{})
if s != "" {
// err = XEngine.SQL(s).Find(&rows)
if !IsQuerySQL(s) {
services.ResponseNotAcceptable406QuerySQLError(w)
return
}
querySQL := s
if i == (len(sql) - 1) {
querySQL = querySQL + " " + ls
}
log.Debug("querySQL:", querySQL)
rows, err := db.RawDB("", querySQL, nil)
if err != nil {
log.Error("SQL failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
tableName := GetTableName(s)
log.Debugf("s:%s tableName:%s", s, tableName)
mapRows[tableName] = rows
data = append(data, mapRows)
log.Trace("data:", data)
}
i++
}
xormResponse.Data = data
services.ResponseWithJson(w, http.StatusOK, xormResponse)
}
func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseInsertData processing... ")
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Error("io.ReadAll failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
vars := mux.Vars(r)
module := ""
dbname := vars["elementTypeValue"]
tbname := vars["objectTypeValue"]
pack := "dbrest"
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
// log.Error("Failed to get permission:", err)
// services.ResponseForbidden403NotPermission(w)
// return
// }
// if !exist {
// log.Error("permission deny!")
// services.ResponseForbidden403NotPermission(w)
// return
// }
log.Debug("Request body:", string(body), "dataObject:", tbname)
insertData := make(map[string]interface{})
_ = json.Unmarshal(body, &insertData)
tn, sql := dborm.ConstructInsertSQL(tbname, insertData)
log.Tracef("tn: %s sql :%s", tn, sql)
var affected int64
for _, s := range sql {
n, err := db.ExecDB("", s, nil)
if err != nil {
log.Error("Insert failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
affected = affected + n
}
// affected, err := InsertDataWithJson(insertData)
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow[tn] = row
// xormResponse.Data = mapRow
services.ResponseWithJson(w, http.StatusOK, mapRow)
}
func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseUpdateData processing... ")
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
module := ""
dbname := vars["elementTypeValue"]
tbname := vars["objectTypeValue"]
pack := "dbrest"
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
// log.Error("Failed to get permission:", err)
// services.ResponseForbidden403NotPermission(w)
// return
// }
// if !exist {
// log.Error("Not permission!")
// services.ResponseForbidden403NotPermission(w)
// return
// }
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
wc := services.GetUriLocString(r)
log.Debug("Request body:", string(body), "Tablename:", tbname, "wc:", wc)
updateData := make(map[string]interface{})
_ = json.Unmarshal(body, &updateData)
tn, sql := dborm.ConstructUpdateSQL(tbname, updateData, wc)
log.Tracef("tn: %s sql :%s", tn, sql)
var affected int64
for _, s := range sql {
n, err := db.ExecDB("", s, nil)
if err != nil {
log.Error("Update failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
affected = affected + n
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow[tn] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
}
func ExtDatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseDeleteData processing... ")
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
module := ""
dbname := vars["elementTypeValue"]
tbname := vars["objectTypeValue"]
pack := "dbreset"
log.Debugf("method:%s, module:%, dbname:%s, tbname:%s pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
// log.Error("Failed to get permission:", err)
// services.ResponseForbidden403NotPermission(w)
// return
// }
// if !exist {
// log.Error("Not permission!")
// services.ResponseForbidden403NotPermission(w)
// return
// }
wc := services.GetUriLocString(r)
log.Debug("Table name:", tbname, "wc:", wc)
sql := dborm.ConstructDeleteSQL(tbname, wc)
affected, err := db.ExecDB("", sql, nil)
if err != nil {
log.Error("Update failed, err:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
}
// xorm Get data from database
func DatabaseGetData(w http.ResponseWriter, r *http.Request) {
log.Debug("DatabaseGetData processing... ")
var sql []string
// _, err = services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
tblName := vars["objectTypeValue"]
sql = GetUriSQLArray(r)
// select as must, todo ...
if sql == nil {
wc := services.GetUriWhereString(r)
if wc == "" {
sql = append(sql, fmt.Sprintf("select * from %s", tblName))
} else {
sql = append(sql, fmt.Sprintf("select * from %s where %s", tblName, wc))
}
}
ls := services.GetUriPageLimitString(r)
// data := make([]map[string]interface{}, 0)
// xormResponse := make([]map[string]interface{}, len(sql))
var xormResponse XormResponse
data := make([]map[string]interface{}, 0)
for i, s := range sql {
log.Tracef("SQL[%d]: %s", i, sql[i])
mapRows := make(map[string]interface{})
if s != "" {
// err = XEngine.SQL(s).Find(&rows)
if !IsQuerySQL(s) {
services.ResponseNotAcceptable406QuerySQLError(w)
return
}
querySQL := s
if i == (len(sql) - 1) {
querySQL = querySQL + " " + ls
}
log.Debug("querySQL:", querySQL)
rows, err := db.RawDB("", querySQL, nil)
if err != nil {
log.Error("QueryInterface failed:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
tableName := GetTableName(s)
log.Debugf("s:%s tableName:%s", s, tableName)
mapRows[tableName] = rows
data = append(data, mapRows)
log.Trace("data:", data)
}
i++
}
xormResponse.Data = data
services.ResponseWithJson(w, http.StatusOK, xormResponse)
}
func DatabaseInsertData(w http.ResponseWriter, r *http.Request) {
log.Debug("DatabaseInsertData processing... ")
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Error("io.ReadAll failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
vars := mux.Vars(r)
tableName := vars["objectTypeValue"]
log.Debug("Request body:", string(body), "tableName:", tableName)
insertData := make(map[string]interface{})
_ = json.Unmarshal(body, &insertData)
// 操作日志的IP
if tableName == "operation_log" || tableName == "security_log" {
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
s := insertData["data"].([]any)
a := s[0].(map[string]any)
a["op_ip"] = ipAddr
} else if tableName == "mml_log" {
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
s := insertData["data"].([]any)
a := s[0].(map[string]any)
a["ip"] = ipAddr
}
tn, sql := dborm.ConstructInsertSQL(tableName, insertData)
log.Tracef("tn: %s sql :%s", tn, sql)
var affected int64
for _, s := range sql {
n, err := db.ExecDB("", s, nil)
if err != nil {
log.Error("Insert failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
affected = affected + n
}
// affected, err := InsertDataWithJson(insertData)
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow[tn] = row
// xormResponse.Data = mapRow
services.ResponseWithJson(w, http.StatusOK, mapRow)
}
func DatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
log.Debug("DatabaseUpdateData processing... ")
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
vars := mux.Vars(r)
tblName := vars["objectTypeValue"]
wc := services.GetUriWhereString(r)
log.Debug("Request body:", string(body), "Table name:", tblName, "wc:", wc)
updateData := make(map[string]interface{})
_ = json.Unmarshal(body, &updateData)
tn, sql := dborm.ConstructUpdateSQL(tblName, updateData, wc)
log.Tracef("tn: %s sql :%s", tn, sql)
var affected int64
for _, s := range sql {
n, err := db.ExecDB("", s, nil)
if err != nil {
log.Error("Update failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
affected = affected + n
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow[tn] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
}
func DatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
log.Debug("DatabaseDeleteData processing... ")
vars := mux.Vars(r)
tblName := vars["objectTypeValue"]
wc := services.GetUriWhereString(r)
log.Debug("Table name:", tblName, "wc:", wc)
sql := dborm.ConstructDeleteSQL(tblName, wc)
affected, err := db.ExecDB("", sql, nil)
if err != nil {
log.Error("Update failed, err:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
}
// 连接用户实例
func DbConnection(w http.ResponseWriter, r *http.Request) {
// 获取底层 SQL 数据库连接
sqlDB, err := db.DB("").DB()
if err != nil {
services.ResponseErrorWithJson(w, 400, "无连接")
return
}
// 测试数据库连接
err = sqlDB.Ping()
if err != nil {
services.ResponseErrorWithJson(w, 400, "无连接")
return
}
// 查询实例
result, err := db.RawDB("", "SHOW PROCESSLIST;", nil)
if err != nil {
services.ResponseErrorWithJson(w, 500, err.Error())
}
filterData := []map[string]any{}
for _, r := range result {
if r["User"] != "system user" {
filterData = append(filterData, r)
}
}
// Sleep连接处于空闲状态没有执行任何操作。
// Query连接正在执行一个查询语句。
// Execute连接正在执行一个准备好的 SQL 语句。
// Connect连接正在建立但尚未完成。
services.ResponseWithJson(w, 200, filterData)
}
// 关闭数据库连接
func DbStop(w http.ResponseWriter, r *http.Request) {
// 获取底层 SQL 数据库连接
sqlDB, err := db.DB("").DB()
if err != nil {
services.ResponseErrorWithJson(w, 400, "无连接")
return
}
// 测试数据库连接
err = sqlDB.Ping()
if err != nil {
services.ResponseErrorWithJson(w, 400, "无连接")
return
}
// json 請求參數獲取
var bodyArgs struct {
ID string `json:"ID" validate:"required"`
}
err = ctx.ShouldBindJSON(r, &bodyArgs)
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseErrorWithJson(w, 400, err.Error())
return
}
// 关闭
rse, err := db.ExecDB("", "KILL ?;", []any{bodyArgs.ID})
if err != nil {
services.ResponseErrorWithJson(w, 500, err.Error())
return
}
services.ResponseWithJson(w, 200, rse)
}
// xorm Get data from database
func TaskDatabaseGetData(w http.ResponseWriter, r *http.Request) {
log.Debug("DatabaseGetData processing... ")
vars := mux.Vars(r)
tblName := vars["objectTypeValue"]
var sql = GetUriSQLArray(r)
// select as must, todo ...
if sql == nil {
wc := services.GetUriWhereString(r)
if wc == "" {
sql = append(sql, fmt.Sprintf("select * from %s", tblName))
} else {
sql = append(sql, fmt.Sprintf("select * from %s where %s", tblName, wc))
}
}
ls := services.GetUriPageLimitString(r)
// data := make([]map[string]interface{}, 0)
// xormResponse := make([]map[string]interface{}, len(sql))
var xormResponse XormResponse
data := make([]map[string]interface{}, 0)
for i, s := range sql {
log.Tracef("SQL[%d]: %s", i, sql[i])
mapRows := make(map[string]interface{})
if s != "" {
// err = XEngine.SQL(s).Find(&rows)
if !IsQuerySQL(s) {
services.ResponseNotAcceptable406QuerySQLError(w)
return
}
querySQL := s
if i == (len(sql) - 1) {
querySQL = querySQL + " " + ls
}
log.Debug("querySQL:", querySQL)
rows, err := db.RawDB("", querySQL, nil)
if err != nil {
log.Error("SQL failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
tableName := GetTableName(s)
log.Debugf("s:%s tableName:%s", s, tableName)
mapRows[tableName] = rows
data = append(data, mapRows)
log.Trace("data:", data)
}
i++
}
xormResponse.Data = data
services.ResponseWithJson(w, http.StatusOK, xormResponse)
}
func TaskDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
log.Debug("DatabaseInsertData processing... ")
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Error("io.ReadAll failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
vars := mux.Vars(r)
tableName := vars["objectTypeValue"]
log.Debug("Request body:", string(body), "tableName:", tableName)
insertData := make(map[string]interface{})
_ = json.Unmarshal(body, &insertData)
tn, sql := dborm.ConstructInsertSQL(tableName, insertData)
log.Tracef("tn: %s sql :%s", tn, sql)
var affected int64
for _, s := range sql {
n, err := db.ExecDB("", s, nil)
if err != nil {
log.Error("Insert failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
affected = affected + n
}
// affected, err := InsertDataWithJson(insertData)
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow[tn] = row
// xormResponse.Data = mapRow
services.ResponseWithJson(w, http.StatusOK, mapRow)
}
func TaskDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
log.Debug("DatabaseUpdateData processing... ")
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
vars := mux.Vars(r)
tblName := vars["objectTypeValue"]
wc := services.GetUriWhereString(r)
log.Debug("Request body:", string(body), "Table name:", tblName, "wc:", wc)
updateData := make(map[string]interface{})
_ = json.Unmarshal(body, &updateData)
tn, sql := dborm.ConstructUpdateSQL(tblName, updateData, wc)
log.Tracef("tn: %s sql :%s", tn, sql)
var affected int64
for _, s := range sql {
n, err := db.ExecDB("", s, nil)
if err != nil {
log.Error("Update failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
affected = affected + n
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow[tn] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
}
func TaskDatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
log.Debug("DatabaseDeleteData processing... ")
vars := mux.Vars(r)
tblName := vars["objectTypeValue"]
wc := services.GetUriWhereString(r)
log.Debug("Table name:", tblName, "wc:", wc)
sql := dborm.ConstructDeleteSQL(tblName, wc)
affected, err := db.ExecDB("", sql, nil)
if err != nil {
log.Error("Update failed, err:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow["data"] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
}

View File

@@ -1,248 +0,0 @@
package event
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"be.ems/lib/config"
"be.ems/lib/core/ctx"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/database/db"
"be.ems/src/framework/utils/date"
"be.ems/src/framework/utils/parse"
neService "be.ems/src/modules/network_element/service"
wsService "be.ems/src/modules/ws/service"
"github.com/gin-gonic/gin"
)
var (
// 走Gin
UriUEEventAMF = "/upload-ue/v1/:eventType"
// 走Mux
UriUEEvent = config.DefaultUriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
CustomUriUEEvent = config.UriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
)
// 旧AMF上报处理
func PostUEEventFromAMF(c *gin.Context) {
log.Info("PostUEEventFromAMF processing... ")
eventType := c.Param("eventType")
if eventType == "" {
log.Error("eventType is empty")
services.ResponseNotFound404UriNotExist(c.Writer, c.Request)
return
}
var body map[string]any
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
log.Error("Failed to Unmarshal ueEvent:", err)
services.ResponseInternalServerError500ProcessError(c.Writer, err)
return
}
// 执行插入表
type UEEvent struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type"`
NeName string `json:"neName" gorm:"column:ne_name"`
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
}
timestamp := time.Now().UnixMilli()
data := UEEvent{
NeType: "AMF",
NeName: "",
RmUID: "",
Timestamp: timestamp,
EventType: eventType,
EventJSONStr: "",
CreatedAt: timestamp,
}
// 从eventJson中获取rmUID
if v, ok := body["rmUID"]; ok {
data.RmUID = fmt.Sprint(v)
} else {
data.RmUID = "4400HXAMF001"
}
if v, ok := body["neName"]; ok {
data.NeName = fmt.Sprint(v)
} else {
data.NeName = "AMF_001"
}
// 是否存在网元
neInfo := neService.NewNeInfo.FindByRmuid(data.RmUID)
if neInfo.NeType != "AMF" || neInfo.RmUID != data.RmUID {
services.ResponseInternalServerError500ProcessError(c.Writer, fmt.Errorf("network element does not exist"))
return
}
// 统一格式
eventJson := map[string]any{"cellID": 0, "gNBID": "", "imsi": "", "onlineNumber": 0, "result": "", "tacID": 0, "timestamp": 0, "time": 0, "type": eventType}
switch eventType {
case "auth-result":
// {"authCode":"200","authMessage":"成功","authTime":"2024-12-07 16:48:37","cellID":"3","gNBID":"1","imsi":"460002082100000","onlineNumber":1,"tacID":"81"}
if v, ok := body["imsi"]; ok {
eventJson["imsi"] = fmt.Sprint(v)
}
if v, ok := body["cellID"]; ok {
eventJson["cellID"] = fmt.Sprint(v)
}
if v, ok := body["gNBID"]; ok {
eventJson["gNBID"] = fmt.Sprint(v)
}
if v, ok := body["tacID"]; ok {
eventJson["tacID"] = fmt.Sprint(v)
}
if v, ok := body["onlineNumber"]; ok {
eventJson["onlineNumber"] = parse.Number(v)
}
if v, ok := body["authCode"]; ok {
eventJson["result"] = fmt.Sprint(v)
}
if v, ok := body["authTime"]; ok {
authTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS)
eventJson["timestamp"] = authTime.Unix()
eventJson["time"] = fmt.Sprint(v)
}
case "detach":
// {"detachResult":0,"detachTime":"2024-12-07 18:00:47","imsi":"460002082100000"}
if v, ok := body["imsi"]; ok {
eventJson["imsi"] = fmt.Sprint(v)
}
if v, ok := body["detachResult"]; ok {
if fmt.Sprint(v) == "0" {
eventJson["result"] = "200"
} else {
eventJson["result"] = "500"
}
}
if v, ok := body["detachTime"]; ok {
detachTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS)
eventJson["timestamp"] = detachTime.Unix()
eventJson["time"] = fmt.Sprint(v)
}
case "cm-state":
// {"changeTime":"2024-12-07 17:07:52","imsi":"460002082100000","onlineNumber":1,"status":2}
if v, ok := body["imsi"]; ok {
eventJson["imsi"] = fmt.Sprint(v)
}
if v, ok := body["onlineNumber"]; ok {
eventJson["onlineNumber"] = parse.Number(v)
}
if v, ok := body["status"]; ok {
eventJson["result"] = fmt.Sprint(v)
}
if v, ok := body["changeTime"]; ok {
changeTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS)
eventJson["timestamp"] = changeTime.Unix()
eventJson["time"] = fmt.Sprint(v)
}
}
ueByte, err := json.Marshal(eventJson)
if err != nil {
services.ResponseInternalServerError500ProcessError(c.Writer, err)
return
}
data.EventJSONStr = string(ueByte)
if err := db.DB("").Table("ue_event_amf").Create(&data).Error; err != nil {
log.Error("Failed to insert ue_event_amf", err)
services.ResponseInternalServerError500ProcessError(c.Writer, err)
return
}
// 推送到ws订阅组
if data.NeType == "AMF" {
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, data)
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, data)
}
services.ResponseStatusOK204NoContent(c.Writer)
}
// UE上报处理
func PostUEEvent(w http.ResponseWriter, r *http.Request) {
log.Info("PostUEEvent processing... ")
neType := ctx.GetParam(r, "elementTypeValue")
var body struct {
NeType string `json:"neType" `
NeName string `json:"neName" `
RmUID string `json:"rmUID" `
Timestamp int64 `json:"timestamp" `
EventType string `json:"eventType" `
EventJson map[string]any `json:"eventJSON" `
}
if err := ctx.ShouldBindJSON(r, &body); err != nil {
services.ResponseInternalServerError500ProcessError(w, err)
return
}
neTypeLower := strings.ToLower(body.NeType)
if neType == "" || neType != neTypeLower {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element types"))
return
}
// 是否存在网元
neInfo := neService.NewNeInfo.FindByRmuid(body.RmUID)
if neInfo.NeType != body.NeType || neInfo.RmUID != body.RmUID {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("network element does not exist"))
return
}
ueByte, err := json.Marshal(body.EventJson)
if err != nil {
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 执行插入表
type UEEvent struct {
ID string `json:"-" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type"`
NeName string `json:"neName" gorm:"column:ne_name"`
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String
CreatedAt int64 `json:"-" gorm:"column:created_at"` // 记录创建存储毫秒
}
data := UEEvent{
NeType: body.NeType,
NeName: body.NeName,
RmUID: body.RmUID,
Timestamp: int64(body.Timestamp) * 1000,
EventType: body.EventType,
EventJSONStr: string(ueByte),
CreatedAt: time.Now().UnixMilli(),
}
tableName := fmt.Sprintf("ue_event_%s", neTypeLower)
if err := db.DB("").Table(tableName).Create(&data).Error; err != nil {
log.Error("Failed to insert "+tableName, err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 推送到ws订阅组
if body.NeType == "MME" {
wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE, data)
wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE+"_"+neInfo.NeId, data)
}
if body.NeType == "AMF" {
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, data)
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, data)
}
services.ResponseStatusOK204NoContent(w)
}

View File

@@ -1,22 +0,0 @@
package features
import (
"be.ems/features/cm"
"be.ems/features/lm"
"be.ems/features/nbi"
"be.ems/features/pm"
"be.ems/lib/log"
"github.com/gin-gonic/gin"
)
func InitServiceEngine(r *gin.Engine) {
log.Info("======init feature group gin.Engine")
// featuresGroup := r.Group("/")
// register features routers
pm.InitSubServiceRoute(r)
lm.InitSubServiceRoute(r)
cm.InitSubServiceRoute(r)
nbi.InitSubServiceRoute(r)
// return featuresGroup
}

View File

@@ -1,141 +0,0 @@
package file
import (
"net/http"
"path/filepath"
"be.ems/lib/config"
"be.ems/lib/log"
"be.ems/lib/services"
"github.com/gorilla/mux"
)
var (
// parameter config management
UriFile = config.DefaultUriPrefix + "/fileManagement/{apiVersion}/{location}/file"
CustomUriFile = config.UriPrefix + "/fileManagement/{apiVersion}/{location}/file"
)
// func init() {
// routes.Register("POST", UriFile, UploadFile, nil)
// routes.Register("GET", UriFile, DownloadFile, nil)
// routes.Register("DELETE", UriFile, DeleteFile, nil)
// }
func UploadFile(w http.ResponseWriter, r *http.Request) {
log.Debug("UploadFile processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Http request error:", err)
// return
// }
vars := mux.Vars(r)
location := vars["location"]
if location == "" {
log.Error("location is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
params := r.URL.Query()
rename, ok := params["rename"]
if !ok {
log.Info("rename parameter is not exist")
}
log.Debug("rename:", rename)
var path, fileName string
if len(rename) > 0 {
fileName = rename[0]
}
if location == "upload" {
path = config.GetYamlConfig().OMC.Upload
fileNamePath, err := services.HandleUploadFile(r, path, fileName)
if err != nil {
log.Error("Faile to HandleUploadFile:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
fileName = fileNamePath
} else {
path = config.GetYamlConfig().OMC.FrontUpload
fileNamePath, err := services.HandleUploadFile(r, path, fileName)
if err != nil {
log.Error("Faile to HandleUploadFile:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
fileName = fileNamePath
}
log.Debugf("upload file=%s to path=%s", fileName, path)
services.ResponseStatusOK204NoContent(w)
return
}
func DownloadFile(w http.ResponseWriter, r *http.Request) {
log.Debug("DownloadFile processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
location := vars["location"]
if location == "" {
log.Error("location is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// 全路径文件下载
filePath := r.URL.Query().Get("path")
if location == "path" && filePath != "" {
// 截取文件路径
dir := filepath.Dir(filePath)
// 截取文件名
fileName := filepath.Base(filePath)
services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, dir, "")
return
}
params := r.URL.Query()
fileNames, ok := params["loc"]
if !ok {
log.Info("loc parameter is not exist")
}
var path string
if location == "upload" {
path = config.GetYamlConfig().OMC.Upload
} else {
path = config.GetYamlConfig().OMC.FrontUpload
}
for _, fileName := range fileNames {
services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, "")
}
return
}
func DeleteFile(w http.ResponseWriter, r *http.Request) {
log.Debug("DeleteFile processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
neType := vars["neType"]
if neType == "" {
log.Error("neType is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
services.ResponseStatusOK204NoContent(w)
return
}

View File

@@ -1,567 +0,0 @@
package fm
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"strings"
"be.ems/lib/config"
"be.ems/lib/core/ctx"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/constants"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/date"
neDataModel "be.ems/src/modules/network_data/model"
neDataService "be.ems/src/modules/network_data/service"
neFetchlink "be.ems/src/modules/network_element/fetch_link"
neModel "be.ems/src/modules/network_element/model"
neService "be.ems/src/modules/network_element/service"
traceService "be.ems/src/modules/trace/service"
wsService "be.ems/src/modules/ws/service"
)
const (
AlarmStatusClear = 0
AlarmStatusActive = 1
AlarmStatusClearString = "0"
AlarmStatusActiveString = "1"
)
const (
ClearTypeUnclear = 0
ClearTypeAutoClear = 1
ClearTypeManualClear = 2
)
const (
AckStateUnacked = 0
AckStateAcked = 1
)
const (
AlarmTypeCommunicationAlarm = 1
AlarmTypeEquipmentAlarm = 2
AlarmTypeProcessingFailure = 3
AlarmTypeEnvironmentalAlarm = 4
AlarmTypeQualityOfServiceAlarm = 5
)
const (
AlarmPerceivedSeverityCritical = 1
AlarmPerceivedSeverityMajor = 2
AlarmPerceivedSeverityMinor = 3
AlarmPerceivedSeverityWarning = 4
AlarmPerceivedSeverityEvent = 5
)
const (
AlarmSeqBeginNumber = 1
)
type Alarm struct {
AlarmSeq int `json:"alarmSeq"`
AlarmId string `json:"alarmId" xorm:"alarm_id"`
NeId string `json:"neId"` // 收到实际是rmUID
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"`
SpecificProblem string `json:"specificProblem"`
SpecificProblemID string `json:"specificProblemID" xorm:"specific_problem_id"`
AddInfo string `json:"addInfo"`
AckState int `json:"ackState"`
AckTime sql.NullTime `json:"ackTime"`
AckUser string `json:"ackUser"`
ClearType int `json:"clearType"` // 0: Unclear, 1: Auto clear, 2: Manual clear
ClearTime sql.NullTime `json:"clearTime"`
}
var (
// alarm management
UriAlarms = config.DefaultUriPrefix + "/faultManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/alarms"
UriAlarmsFmt = config.DefaultUriPrefix + "/faultManagement/v1/elementType/%s/objectType/alarms"
CustomUriAlarms = config.UriPrefix + "/faultManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/alarms"
CustomUriAlarmsFmt = config.UriPrefix + "/faultManagement/v1/elementType/%s/objectType/alarms"
)
// PostAlarmFromNF 网元告警数据上报接收
func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("PostAlarmFromNF processing... ")
apiVer := ctx.GetParam(r, "apiVersion")
if apiVer != global.ApiVersionV1 {
log.Error("Uri api version is invalid. apiVersion:", apiVer)
services.ResponseWithJson(w, 422, resp.CodeMsg(40422, "api version is invalid"))
return
}
var body []Alarm
if err := ctx.ShouldBindJSON(r, &body); err != nil {
services.ResponseWithJson(w, 422, resp.ErrMsg(err.Error()))
return
}
// service object
neService := neService.NewNeInfo
for _, v := range body {
log.Debug("alarmData:", v)
// 是否存在网元 neId实际是rmUID
neInfo := neService.FindByRmuid(v.NeId)
if neInfo.NeType != v.NeType {
msg := fmt.Sprintf("network element does not exist %s", v.NeId)
services.ResponseWithJson(w, 400, resp.ErrMsg(msg))
return
}
// 记录日志
alarmSaveLog(neInfo, v)
// 补充默认信息
if v.LocationInfo == "" {
v.LocationInfo = fmt.Sprintf("Remote Host:%s", r.RemoteAddr)
}
if v.AddInfo == "" {
v.AddInfo = fmt.Sprintf("NeInfo:%s", v.NeType)
}
if v.ObjectUid == "" {
v.ObjectUid = neInfo.RmUID
}
if v.ObjectName == "" {
v.ObjectName = neInfo.NeName
}
if v.ObjectType == "" {
v.ObjectType = neInfo.NeType
}
// 告警事件
if v.OrigSeverity == "Event" || v.OrigSeverity == "5" {
if v.AlarmStatus == AlarmStatusClear {
// 进行清除
clearAlarmEvent, err := alarmEventClear(neInfo, v)
if err != nil {
services.ResponseWithJson(w, 400, resp.ErrMsg(err.Error()))
return
}
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM_EVENT, neInfo.NeType, neInfo.NeId)
wsService.NewWSSend.ByGroupID(groupID, clearAlarmEvent)
}
if v.AlarmStatus == AlarmStatusActive {
// 进行新增
newAlarmEvent, err := alarmEventNew(neInfo, v)
if err != nil {
services.ResponseWithJson(w, 400, resp.ErrMsg(err.Error()))
return
}
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM_EVENT, neInfo.NeType, neInfo.NeId)
wsService.NewWSSend.ByGroupID(groupID, newAlarmEvent)
}
continue
}
if v.AlarmStatus == AlarmStatusClear {
// 进行清除
clearAlarm, err := alarmClear(neInfo, v)
if err != nil {
services.ResponseWithJson(w, 400, resp.ErrMsg(err.Error()))
return
}
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
wsService.NewWSSend.ByGroupID(groupID, clearAlarm)
}
if v.AlarmStatus == AlarmStatusActive {
// 进行新增
newAlarm, err := alarmNew(neInfo, v)
if err != nil {
services.ResponseWithJson(w, 400, resp.ErrMsg(err.Error()))
return
}
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
wsService.NewWSSend.ByGroupID(groupID, newAlarm)
}
// for alarm forward 告警转发
alarmForward(v)
}
services.ResponseStatusOK204NoContent(w)
}
// alarmTypeValue 映射值
func alarmTypeValue(str string) string {
arr := []string{"CommunicationAlarm", "EquipmentAlarm", "ProcessingFailure", "EnvironmentalAlarm", "QualityOfServiceAlarm"}
for k, v := range arr {
if v == str {
return fmt.Sprint(k + 1)
}
}
return str
}
// origSeverityValue 映射值
func origSeverityValue(str string) string {
arr := []string{"Critical", "Major", "Minor", "Warning", "Event"}
for k, v := range arr {
if v == str {
return fmt.Sprint(k + 1)
}
}
return str
}
// alarmClear 清除告警
func alarmClear(neInfo neModel.NeInfo, v Alarm) (neDataModel.Alarm, error) {
alarmService := neDataService.NewAlarm
// 检查网元告警ID是否唯一
alarmIdArr := alarmService.Find(neDataModel.Alarm{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmId: v.AlarmId,
})
if len(alarmIdArr) != 1 {
return neDataModel.Alarm{}, fmt.Errorf("[%s %s] clear alarm not exists alarmId:%s", neInfo.NeType, neInfo.NeId, v.AlarmId)
}
// 产生时间
eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ)
alarm := neDataModel.Alarm{
ID: alarmIdArr[0].ID,
NeType: neInfo.NeType,
NeId: neInfo.NeId,
NeName: neInfo.NeName,
Province: neInfo.Province,
PvFlag: neInfo.PvFlag,
AlarmSeq: alarmIdArr[0].AlarmSeq, // seq 告警序号
AlarmId: v.AlarmId,
AlarmTitle: v.AlarmTitle,
AlarmCode: int64(v.AlarmCode),
EventTime: eventTime.UnixMilli(),
AlarmType: alarmTypeValue(v.AlarmType),
OrigSeverity: origSeverityValue(v.OrigSeverity),
PerceivedSeverity: origSeverityValue(v.PerceivedSeverity),
ObjectUid: v.ObjectUid,
ObjectName: v.ObjectName,
ObjectType: v.ObjectType,
LocationInfo: v.LocationInfo,
AlarmStatus: fmt.Sprint(v.AlarmStatus),
SpecificProblem: v.SpecificProblem,
SpecificProblemId: v.SpecificProblemID,
AddInfo: v.AddInfo,
}
// 告警清除
alarm.ClearType = ClearTypeAutoClear
alarm.ClearTime = eventTime.UnixMilli()
alarm.ClearUser = neInfo.NeName
rows := alarmService.Update(alarm)
if rows > 0 {
return alarm, nil
}
return neDataModel.Alarm{}, fmt.Errorf("[%s %s] clear alarm fail", neInfo.NeType, neInfo.NeId)
}
// alarmNew 新增告警
func alarmNew(neInfo neModel.NeInfo, v Alarm) (neDataModel.Alarm, error) {
alarmService := neDataService.NewAlarm
// 检查网元告警ID是否唯一
alarmIdArr := alarmService.Find(neDataModel.Alarm{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmId: v.AlarmId,
})
if len(alarmIdArr) > 0 {
return neDataModel.Alarm{}, fmt.Errorf("[%s %s] new alarm already exists alarmId:%s", neInfo.NeType, neInfo.NeId, v.AlarmId)
}
// seq 告警序号
lastSeq := alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId)
// 产生时间
eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ)
alarm := neDataModel.Alarm{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
NeName: neInfo.NeName,
Province: neInfo.Province,
PvFlag: neInfo.PvFlag,
AlarmSeq: lastSeq + 1,
AlarmId: v.AlarmId,
AlarmTitle: v.AlarmTitle,
AlarmCode: int64(v.AlarmCode),
EventTime: eventTime.UnixMilli(),
AlarmType: alarmTypeValue(v.AlarmType),
OrigSeverity: origSeverityValue(v.OrigSeverity),
PerceivedSeverity: origSeverityValue(v.PerceivedSeverity),
ObjectUid: v.ObjectUid,
ObjectName: v.ObjectName,
ObjectType: v.ObjectType,
LocationInfo: v.LocationInfo,
AlarmStatus: fmt.Sprint(v.AlarmStatus),
SpecificProblem: v.SpecificProblem,
SpecificProblemId: v.SpecificProblemID,
AddInfo: v.AddInfo,
}
insertId := alarmService.Insert(alarm)
if insertId > 0 {
alarm.ID = insertId
return alarm, nil
}
return neDataModel.Alarm{}, fmt.Errorf("[%s %s] new alarm fail", neInfo.NeType, neInfo.NeId)
}
// alarmSaveLog 保存告警日志
func alarmSaveLog(neInfo neModel.NeInfo, v Alarm) int64 {
alarmLogService := neDataService.NewAlarmLog
eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ)
alarmLog := neDataModel.AlarmLog{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmSeq: int64(v.AlarmSeq),
AlarmId: v.AlarmId,
AlarmTitle: v.AlarmTitle,
AlarmCode: int64(v.AlarmCode),
AlarmStatus: fmt.Sprint(v.AlarmStatus),
AlarmType: alarmTypeValue(v.AlarmType),
OrigSeverity: origSeverityValue(v.OrigSeverity),
EventTime: eventTime.UnixMilli(),
}
return alarmLogService.Insert(alarmLog)
}
// alarmForward 告警转发
func alarmForward(v Alarm) {
if config.GetYamlConfig().Alarm.EmailForward.Enable {
if err := AlarmEmailForward(&v); err != nil {
log.Error("Failed to AlarmEmailForward:", err)
}
}
if config.GetYamlConfig().Alarm.SMSCForward.Enable {
if err := AlarmSMSForward(&v); err != nil {
log.Error("Failed to AlarmSMSForward:", err)
}
}
}
// alarmEventClear 清除告警事件
func alarmEventClear(neInfo neModel.NeInfo, v Alarm) (neDataModel.AlarmEvent, error) {
alarmEventService := neDataService.NewAlarmEvent
// 检查网元告警ID是否唯一
alarmIdArr := alarmEventService.Find(neDataModel.AlarmEvent{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmId: v.AlarmId,
})
if len(alarmIdArr) != 1 {
return neDataModel.AlarmEvent{}, fmt.Errorf("[%s %s] clear alarm event not exists alarmId:%s", neInfo.NeType, neInfo.NeId, v.AlarmId)
}
// 产生时间
eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ)
alarmEvent := neDataModel.AlarmEvent{
ID: alarmIdArr[0].ID,
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmSeq: alarmIdArr[0].AlarmSeq, // seq 告警序号
AlarmId: v.AlarmId,
AlarmTitle: v.AlarmTitle,
AlarmCode: int64(v.AlarmCode),
EventTime: eventTime.UnixMilli(),
ObjectUid: v.ObjectUid,
ObjectName: v.ObjectName,
ObjectType: v.ObjectType,
LocationInfo: v.LocationInfo,
AlarmStatus: fmt.Sprint(v.AlarmStatus),
SpecificProblem: v.SpecificProblem,
SpecificProblemId: v.SpecificProblemID,
AddInfo: v.AddInfo,
}
// 告警清除
alarmEvent.ClearType = ClearTypeAutoClear
alarmEvent.ClearTime = eventTime.UnixMilli()
alarmEvent.ClearUser = neInfo.NeName
rows := alarmEventService.Update(alarmEvent)
if rows > 0 {
return alarmEvent, nil
}
return neDataModel.AlarmEvent{}, fmt.Errorf("[%s %s] clear alarm event fail", neInfo.NeType, neInfo.NeId)
}
// alarmEventNew 新增告警事件
func alarmEventNew(neInfo neModel.NeInfo, v Alarm) (neDataModel.AlarmEvent, error) {
alarmEventService := neDataService.NewAlarmEvent
// 检查网元告警ID是否唯一
alarmIdArr := alarmEventService.Find(neDataModel.AlarmEvent{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmId: v.AlarmId,
})
if len(alarmIdArr) > 0 {
return neDataModel.AlarmEvent{}, fmt.Errorf("[%s %s] new alarm event already exists alarmId:%s", neInfo.NeType, neInfo.NeId, v.AlarmId)
}
// seq 告警序号
lastSeq := alarmEventService.FindAlarmEventSeqLast(neInfo.NeType, neInfo.NeId)
// 产生时间
eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ)
alarmEvent := neDataModel.AlarmEvent{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmSeq: lastSeq + 1,
AlarmId: v.AlarmId,
AlarmTitle: v.AlarmTitle,
AlarmCode: int64(v.AlarmCode),
EventTime: eventTime.UnixMilli(),
ObjectUid: v.ObjectUid,
ObjectName: v.ObjectName,
ObjectType: v.ObjectType,
LocationInfo: v.LocationInfo,
AlarmStatus: fmt.Sprint(v.AlarmStatus),
SpecificProblem: v.SpecificProblem,
SpecificProblemId: v.SpecificProblemID,
AddInfo: v.AddInfo,
}
insertId := alarmEventService.Insert(alarmEvent)
if insertId > 0 {
alarmEvent.ID = insertId
// 网元重启后,清除活动告警
if v.AlarmCode == constants.ALARM_EVENT_REBOOT {
alarmService := neDataService.NewAlarm
rows := alarmService.Find(neDataModel.Alarm{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmStatus: "1",
})
for _, v := range rows {
alarmService.AlarmClearByIds([]int64{v.ID}, "system")
}
}
// 网元重启后,有跟踪任务的需要重新补发启动任务
if v.AlarmCode == constants.ALARM_EVENT_REBOOT {
traceService.NewTraceTask.RunUnstopped(neInfo.NeType, neInfo.NeId)
}
return alarmEvent, nil
}
return neDataModel.AlarmEvent{}, fmt.Errorf("[%s %s] new alarm event fail", neInfo.NeType, neInfo.NeId)
}
// mapToAlarm 将 []map[string]any 转换为 []Alarm
func mapToAlarm(data []map[string]any) []Alarm {
var result []Alarm
// 将 []map[string]any 序列化为 JSON 字符串
jsonData, err := json.Marshal(data)
if err != nil {
log.Error("Error marshaling data:", err)
return result
}
// 反序列化到结构体
err = json.Unmarshal(jsonData, &result)
if err != nil {
log.Error("Error unmarshaling data:", err)
return result
}
return result
}
// GetAlarmFromNF 告警历史数据,从网元获取
func GetAlarmFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("GetAlarmFromNF processing... ")
neType := ctx.GetParam(r, "elementTypeValue")
neTypeLower := strings.ToLower(neType)
// Get alarms from OMC return 204
if neTypeLower == strings.ToLower(config.GetYamlConfig().OMC.NeType) {
log.Infof("Return no content alarms from %s", neType)
services.ResponseWithJson(w, 200, resp.ErrMsg("omc alarms no content"))
return
}
neInfos := neService.NewNeInfo.Find(neModel.NeInfo{}, false, false)
for _, neInfo := range neInfos {
data, err := neFetchlink.AlarmHistory(neInfo)
if err != nil {
log.Error("Failed to fetch alarm history:", err)
continue
}
if len(data) == 0 {
log.Infof("Not found sync alarms, neType=%s, neId=%s", neInfo.NeType, neInfo.NeId)
continue
}
alarms := mapToAlarm(data)
for _, v := range alarms {
// 补充默认信息
if v.LocationInfo == "" {
v.LocationInfo = fmt.Sprintf("Remote Host:%s", r.RemoteAddr)
}
if v.AddInfo == "" {
v.AddInfo = fmt.Sprintf("NeInfo:%s", v.NeType)
}
if v.ObjectUid == "" {
v.ObjectUid = neInfo.RmUID
}
if v.ObjectName == "" {
v.ObjectName = neInfo.NeName
}
if v.ObjectType == "" {
v.ObjectType = neInfo.NeType
}
// 告警事件
if v.OrigSeverity == "Event" || v.OrigSeverity == "5" {
if v.AlarmStatus == AlarmStatusClear {
// 进行清除
if _, err := alarmEventClear(neInfo, v); err != nil {
log.Error("Failed to alarmEventClear:", err)
continue
}
}
if v.AlarmStatus == AlarmStatusActive {
// 进行新增
if _, err := alarmEventNew(neInfo, v); err != nil {
log.Error("Failed to alarmEventNew:", err)
continue
}
}
continue
}
if v.AlarmStatus == AlarmStatusClear {
// 进行清除
if _, err := alarmClear(neInfo, v); err != nil {
log.Error("Failed to alarmClear:", err)
continue
}
}
if v.AlarmStatus == AlarmStatusActive {
// 进行新增
if _, err := alarmNew(neInfo, v); err != nil {
log.Error("Failed to alarmNew:", err)
continue
}
}
}
}
services.ResponseWithJson(w, 200, resp.OkMsg("sync alarms success"))
}

View File

@@ -1,129 +0,0 @@
package fm
import (
"crypto/tls"
"fmt"
"strings"
"be.ems/lib/config"
neService "be.ems/src/modules/network_element/service"
systemService "be.ems/src/modules/system/service"
"gopkg.in/gomail.v2"
)
func AlarmEmailForward(alarmData *Alarm) error {
neInfo := neService.NewNeInfo.FindByRmuid(alarmData.NeId)
alarmStatus := "Clear"
if alarmData.AlarmStatus == 1 {
alarmStatus = "Active"
}
severity := origSeverityValue(alarmData.OrigSeverity)
dictAlarmSeverity := systemService.NewSysDictData.FindByType("active_alarm_severity")
for _, v := range dictAlarmSeverity {
if v.DataValue == severity {
severity = v.DataLabel
}
}
subjectTitle := config.GetYamlConfig().Alarm.EmailForward.Title
if subjectTitle == "" {
subjectTitle = fmt.Sprintf("%s-%s-%s", alarmData.OrigSeverity, alarmData.NeName, alarmData.AlarmTitle)
}
message := fmt.Sprintf(`
<p>Alarm information</p>
<p style="text-indent:2.5em">Sequence: %d</p>
<p style="text-indent:3em">NE Name: %s</p>
<p style="text-indent:3em">NE IP: %s</p>
<p style="text-indent:4em">Title: %s</p>
<p style="text-indent:2.5em">Severity: %s</p>
<p style="text-indent:1.5em">Event Time: %s</p>
<p style="text-indent:0.5em">Alarm Status: %s</p>
<p>Automatic sent by OMC, please do not reply!</p>
`,
alarmData.AlarmSeq,
alarmData.NeName,
neInfo.IP,
alarmData.AlarmTitle,
severity,
alarmData.EventTime,
alarmStatus,
)
// message := fmt.Sprintf(`
// Alarm information
// Sequence: %d
// NE name: %s
// Title: %s
// Severity: %s
// Event Time: %s
// Automatic send by OMC, don't reply!
// `, alarmData.AlarmSeq, alarmData.NeName, alarmData.AlarmTitle, alarmData.OrigSeverity, alarmData.EventTime)
// QQ 邮箱:
// SMTP 服务器地址smtp.qq.comSSL协议端口465/994 | 非SSL协议端口25
// 163 邮箱:
// SMTP 服务器地址smtp.163.com端口25
// host := "mail.agrandtech.com"
// port := 25
// userName := "smtpext@agrandtech.com"
// password := "1000smtp@omc!"
host := config.GetYamlConfig().Alarm.EmailForward.SMTP
port := int(config.GetYamlConfig().Alarm.EmailForward.Port)
userName := config.GetYamlConfig().Alarm.EmailForward.User
password := config.GetYamlConfig().Alarm.EmailForward.Password
m := gomail.NewMessage()
m.SetHeader("From", userName) // 发件人
//m.SetHeader("From", "alias"+"<"+"aliastest"+">") // 增加发件人别名
// emails, err := dborm.XormGetAlarmForward("Email")
// if err != nil {
// log.Error("Failed to XormGetAlarmForward:", err)
// return err
// } else if emails == nil || len(*emails) == 0 {
// err := errors.New("not found forward email list")
// log.Error(err)
// return err
// }
emails := strings.Split(config.GetYamlConfig().Alarm.EmailForward.EmailList, ",")
if len(emails) == 0 {
return fmt.Errorf("not found forward email list")
}
m.SetHeader("To", emails...) // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接
//m.SetHeader("To", strings.Join(*emails, " ")) // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接
//m.SetHeader("To", "zhangshuzhong@agrandtech.com", "simonzhangsz@outlook.com") // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接
//m.SetHeader("Cc", "******@qq.com") // 抄送,可以多个
//m.SetHeader("Bcc", "******@qq.com") // 暗送,可以多个
m.SetHeader("Subject", subjectTitle) // 邮件主题
// text/html 的意思是将文件的 content-type 设置为 text/html 的形式浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。
// 可以通过 text/html 处理文本格式进行特殊处理,如换行、缩进、加粗等等
//m.SetBody("text/html", fmt.Sprintf(message, *alarm))
m.SetBody("text/html", message)
// text/plain的意思是将文件设置为纯文本的形式浏览器在获取到这种文件时并不会对其进行处理
//m.SetBody("text/plain", message)
// m.Attach("test.sh") // 附件文件,可以是文件,照片,视频等等
// m.Attach("lolcatVideo.mp4") // 视频
// m.Attach("lolcat.jpg") // 照片
d := gomail.NewDialer(
host,
port,
userName,
password,
)
// 关闭SSL协议认证
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if !config.GetYamlConfig().Alarm.EmailForward.TLSSkipVerify {
// 打开SSL协议认证
d.TLSConfig = &tls.Config{InsecureSkipVerify: false}
}
err := d.DialAndSend(m)
return writeLog(alarmData, config.GetYamlConfig().Alarm.EmailForward.EmailList, "EMAIL", err)
}

View File

@@ -1,271 +0,0 @@
package fm
import (
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"be.ems/lib/config"
"be.ems/lib/dborm"
"be.ems/lib/log"
"be.ems/src/framework/utils/date"
neDataModel "be.ems/src/modules/network_data/model"
neDataService "be.ems/src/modules/network_data/service"
neService "be.ems/src/modules/network_element/service"
"github.com/linxGnu/gosmpp"
"github.com/linxGnu/gosmpp/data"
"github.com/linxGnu/gosmpp/pdu"
)
func AlarmSMSForward(alarmData *Alarm) error {
switch config.GetYamlConfig().Alarm.SMProxy {
case "sms":
users, err := AlarmForwardBySMS(alarmData)
writeLog(alarmData, users, "SMS", err)
return err
case "smsc":
users, err := AlarmForwardBySMPP(alarmData)
writeLog(alarmData, users, "SMS", err)
return err
default:
users, err := AlarmForwardBySMPP(alarmData)
writeLog(alarmData, users, "SMS", err)
return err
}
}
func AlarmForwardBySMS(alarmData *Alarm) (string, error) {
log.Info("AlarmForwardBySMS processing... ")
SMSFforwardconfig := config.GetYamlConfig().Alarm.SMS
// 阿里云短信API的请求地址
apiURL := SMSFforwardconfig.ApiURL
// 阿里云短信API的AccessKey ID和AccessKey Secret
//accessKeyID := SMSFforwardconfig.AccessKeyID
accessKeySecret := SMSFforwardconfig.AccessKeySecret
toUsers, err := dborm.XormGetAlarmForward("SMS")
if err != nil {
log.Error("Failed to XormGetAlarmForward:", err)
return "", err
}
if toUsers == nil {
err := errors.New("not found forward phone number")
log.Error(err)
return "", err
}
userList := strings.Join(*toUsers, ",")
if len(userList) == 0 {
err := errors.New("not found forward phone number")
log.Error(err)
return "", err
}
// 短信相关参数
params := url.Values{}
params.Set("PhoneNumbers", userList)
params.Set("SignName", SMSFforwardconfig.SignName)
params.Set("TemplateCode", SMSFforwardconfig.TemplateCode)
params.Set("TemplateParam", `{"message":"alarm"}`)
// 构建请求URL
reqURL := apiURL + "?Action=SendSms&" + params.Encode()
// 创建HTTP请求
req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
log.Error("Failed to create request:", err)
return userList, err
}
// 添加请求头部
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Authorization", "APPCODE "+accessKeySecret)
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Error("Failed to send request:%v", err)
return userList, err
}
defer resp.Body.Close()
// 解析响应
switch resp.StatusCode {
case http.StatusOK, http.StatusAccepted, http.StatusNoContent, http.StatusCreated:
return userList, nil
default:
log.Error(fmt.Errorf("failed to send SMS: %s(Code=%d)", resp.Status, resp.StatusCode))
return userList, err
}
}
var smsForward = &(config.GetYamlConfig().Alarm.SMSCForward)
func AlarmForwardBySMPP(alarmData *Alarm) (string, error) {
log.Info("AlarmForwardBySMPP processing... ")
if smsForward == nil {
err := errors.New("smsForward configuration is nil")
log.Error(err)
return "", err
}
userList := smsForward.MobileList
if len(userList) == 0 {
err := errors.New("not found forward phone number")
log.Error(err)
return "", err
}
auth := gosmpp.Auth{
SMSC: smsForward.SMSCAddr,
SystemID: smsForward.SystemID,
Password: smsForward.Password,
SystemType: smsForward.SystemType,
}
trans, err := gosmpp.NewSession(
gosmpp.TXConnector(gosmpp.NonTLSDialer, auth),
gosmpp.Settings{
ReadTimeout: 2 * time.Second,
OnPDU: func(p pdu.PDU, _ bool) {
log.Debug("%+v", p)
},
OnSubmitError: func(_ pdu.PDU, err error) {
log.Error(err)
},
OnRebindingError: func(err error) {
log.Error(err)
},
OnClosed: func(state gosmpp.State) {
log.Error(state)
},
}, -1)
if err != nil {
log.Error("Failed to create SMPP new session:", err)
return "", err
}
defer func() {
if err := trans.Close(); err != nil {
log.Error(err)
}
}()
message := "Alarm Notification: " + alarmData.AlarmTitle +
" from " + alarmData.NeType + "_" + alarmData.NeId +
" at " + alarmData.EventTime
users := strings.Split(userList, ",")
for _, user := range users {
if user == "" {
continue
}
sm, err := newSubmitSM(user, message)
if err != nil {
log.Errorf("Failed to newSubmitSM %s short message: %v", user, err)
writeLog(alarmData, user, "SMS", err)
continue
}
if err = trans.Transceiver().Submit(sm); err != nil {
log.Errorf("Failed to Submit %s short message: %v", user, err)
writeLog(alarmData, user, "SMS", err)
continue
}
writeLog(alarmData, user, "SMS", nil)
}
return userList, nil
}
func writeLog(alarmData *Alarm, toUser, forwardBy string, err error) error {
var result string = fmt.Sprintf("%s Sent Successfully!", forwardBy)
if err != nil {
result = err.Error()
}
neInfo := neService.NewNeInfo.FindByRmuid(alarmData.NeId)
eventTime := date.ParseStrToDate(alarmData.EventTime, date.YYYY_MM_DDTHH_MM_SSZ)
alarmForwardLog := neDataModel.AlarmForwardLog{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
AlarmSeq: int64(alarmData.AlarmSeq),
AlarmId: alarmData.AlarmId,
AlarmTitle: alarmData.AlarmTitle,
AlarmCode: int64(alarmData.AlarmCode),
AlarmStatus: fmt.Sprint(alarmData.AlarmStatus),
AlarmType: alarmTypeValue(alarmData.AlarmType),
OrigSeverity: origSeverityValue(alarmData.OrigSeverity),
EventTime: eventTime.UnixMilli(),
Type: forwardBy,
Target: toUser,
Result: result,
}
// 记录日志
insertId := neDataService.NewAlarmForwardLog.Insert(alarmForwardLog)
if insertId <= 0 {
return fmt.Errorf("failed to insert data")
}
return nil
}
func newSubmitSM(phoneNumber string, message string) (*pdu.SubmitSM, error) {
// build up submitSM
srcAddr := pdu.NewAddress()
srcAddr.SetTon(5)
srcAddr.SetNpi(0)
err := srcAddr.SetAddress(smsForward.ServiceNumber)
if err != nil {
return nil, err
}
destAddr := pdu.NewAddress()
destAddr.SetTon(1)
destAddr.SetNpi(1)
err = destAddr.SetAddress(phoneNumber)
if err != nil {
return nil, err
}
submitSM := pdu.NewSubmitSM().(*pdu.SubmitSM)
submitSM.SourceAddr = srcAddr
submitSM.DestAddr = destAddr
dataCoding := data.FromDataCoding(smsForward.DataCoding)
err = submitSM.Message.SetMessageWithEncoding(message, dataCoding)
if err != nil {
return nil, err
}
submitSM.ProtocolID = 0
submitSM.RegisteredDelivery = 1
submitSM.ReplaceIfPresentFlag = 0
submitSM.EsmClass = 0
return submitSM, nil
}
// const (
// // Short message data coding type
// SMS_CODING_GSM7BIT byte = iota
// SMS_CODING_ASCII
// SMS_CODING_BINARY8BIT1
// SMS_CODING_LATIN1
// SMS_CODING_BINARY8BIT2
// SMS_CODING_NODEF
// SMS_CODING_CYRILLIC
// SMS_CODING_HEBREW
// SMS_CODING_UCS2
// )
// var codingMap = map[byte]data.Encoding{
// SMS_CODING_GSM7BIT: data.GSM7BIT,
// SMS_CODING_ASCII: data.ASCII,
// SMS_CODING_BINARY8BIT1: data.BINARY8BIT1,
// SMS_CODING_LATIN1: data.LATIN1,
// SMS_CODING_BINARY8BIT2: data.BINARY8BIT2,
// SMS_CODING_CYRILLIC: data.CYRILLIC,
// SMS_CODING_HEBREW: data.HEBREW,
// SMS_CODING_UCS2: data.UCS2,
// }

View File

@@ -1,565 +0,0 @@
package handle
import (
"bytes"
"encoding/json"
"io"
"net/http"
"strconv"
"strings"
"github.com/gorilla/mux"
g "github.com/gosnmp/gosnmp"
"be.ems/lib/config"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/oauth"
"be.ems/lib/services"
"be.ems/lib/session"
)
var TodoList []stTodo
type stTodo struct {
No string
Item string
Value string
}
type ErrorOAuthResponse struct {
Error map[string]interface{}
}
type FailOAuthResponse struct {
Error struct {
ErrorCode string
ErrorInfo string
}
}
type ApiResponse struct {
ResultCode string
ResultMessage interface{}
}
var globalSession = session.NewSessManager("restagent")
func init() {
conf := config.GetYamlConfig()
// Default is a pointer to a GoSNMP struct that contains sensible defaults
// eg port 161, community public, etc
g.Default.Target = conf.NE.Addr
g.Default.Port = conf.NE.Port
err := g.Default.Connect()
if err != nil {
log.Fatalf("Connect() err: %v", err)
}
//defer g.Default.Conn.Close()
}
/*
func IsValidOAuthInfo(oAuthBody OAuthBody) bool {
log.Debug("IsValidOAuthInfo processing... ")
conf := config.GetYamlConfig()
for _, o := range conf.Auth {
if oAuthBody.GrantType == o.Type && oAuthBody.UserName == o.User && oAuthBody.Value == o.Password {
return true
}
}
return false
}
func IsWrongOAuthInfo(oAuthBody OAuthBody) bool {
log.Debug("IsWrongOAuthInfo processing... ")
if oAuthBody.GrantType == "" || strings.ToLower(oAuthBody.GrantType) != "password" || oAuthBody.UserName == "" || oAuthBody.Value == "" {
return true
}
return false
}
*/
func IsValidOAuthUri(r *http.Request) bool {
vars := mux.Vars(r)
Uri := vars["apiCategory"] + "/" + vars["apiVersion"] // 获取Uri
return Uri == "securityManagement/v1"
}
func IsVallidContentType(r *http.Request) bool {
log.Debug("IsVallidContentType processing ...")
ctype := r.Header["Content-Type"]
if len(ctype) != 0 && !strings.Contains(ctype[0], "application/json") {
return false
}
return true
}
func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
log.Debug("LoginFromOMC processing... ")
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Debug(err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
// check media type(content type) only support "application/json"
/* if !IsVallidContentType(r) {
log.Debug("Invalid Content-Type")
services.ResponseUnsupportedMediaType415(w)
return
}
// check extend uri, response 404
if !IsValidOAuthUri(r) {
log.Debug("Uri is invalid")
services.ResponseNotFound404UriNotExist(w, r)
return
}
*/
// Error process ....
// response 400-7
if !json.Valid([]byte(body)) {
log.Debug("Invalid Json Format")
services.ResponseBadRequest400InvalidJson(w)
return
}
var oAuthBody oauth.OAuthBody
_ = json.Unmarshal(body, &oAuthBody) //转为json
log.Debug("body:", string(body), "oAuthBody:", oAuthBody)
defer r.Body.Close()
// response 400-5
if oauth.IsWrongOAuthInfo(oAuthBody) {
log.Debug("Wrong parameter value")
services.ResponseBadRequest400WrongParamValue(w)
return
}
/*
if oauth.IsValidOAuthInfo(oAuthBody) {
plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType)
log.Debug("Permission list:", plist)
token := globalSession.NewSession(w, r, plist)
services.ResponseStatusOK200Login(w, token)
} else {
// response 400-4
log.Debug("Authentication failed, mismatch user or password")
services.ResponseBadRequest400IncorrectLogin(w)
}
*/
// response 400-4
log.Error("Authentication failed, mismatch user or password")
services.ResponseBadRequest400IncorrectLogin(w)
}
func LogoutFromOMC(w http.ResponseWriter, r *http.Request) {
// check media type(content type) only support "application/json"
if !IsVallidContentType(r) {
log.Debug("Invalid Content-Type")
services.ResponseUnsupportedMediaType415(w)
return
}
// check extend uri, response 404
if !IsValidOAuthUri(r) {
log.Debug("Uri is invalid")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// error processing ...
// 401-1 response
token, ret := globalSession.IsCarriedToken(r)
if ret {
log.Debug("AccessToken is not carried")
services.ResponseUnauthorized401AccessTokenNotCarried(w)
return
}
// 401-2 response
if globalSession.IsValidToken(token) {
log.Debug("AccessToken fails or does not exist")
services.ResponseUnauthorized401AccessTokenNotExist(w)
return
}
globalSession.EndSession(w, r)
services.ResponseStatusOK200Null(w)
}
func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) {
log.Debug("HandshakeFromOMC processing... ")
// check media type(content type) only support "application/json"
if !IsVallidContentType(r) {
log.Debug("Invalid Content-Type")
services.ResponseUnsupportedMediaType415(w)
return
}
// check extend uri, response 404
if !IsValidOAuthUri(r) {
log.Debug("Uri is invalid")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// error processing ...
// 401-1 response
token, ret := globalSession.IsCarriedToken(r)
if !ret {
log.Debug("AccessToken is not carried")
services.ResponseUnauthorized401AccessTokenNotCarried(w)
return
}
if !globalSession.ShakeSession(token) {
// 401-2 response
log.Debug("AccessToken fails or does not exist")
services.ResponseUnauthorized401AccessTokenNotExist(w)
return
}
// 200 response
services.ResponseStatusOK200Null(w)
}
var (
MAX_RMUID_NUM = config.GetRmUIDMaxNumFromConfig()
MAX_ALARMID_NUM = config.GetAlarmIDMaxNumFromConfig()
MAX_PMUID_NUM = config.GetPmIDMaxNumFromConfig()
MAX_SUBID_NUM = config.GetSubIDMaxNumFromConfig()
MAX_URI_LEN = config.GetUriMaxLenFromConfig()
RMUID_REGEXP = config.GetRmUIDRegexpFromConfig()
)
func CheckParameterName(r *http.Request) []string {
var errorParams []string
vars := r.URL.Query()
for k, v := range vars {
log.Debug("vars:", k, v)
if k != "rmUIDs" && k != "fields" {
errorParams = append(errorParams, k)
}
}
return errorParams
}
func GetRmUIDArr(r *http.Request) []string {
vars := r.URL.Query()
rmUIDs, ok := vars["rmUIDs"]
if !ok {
log.Debug("rmUIDs is not exist")
return nil
}
var rmUIDValues []string
for _, r := range rmUIDs {
if r != "" {
rmUIDValues = global.MergeStringArr(rmUIDValues, strings.Split(r, `,`))
}
}
return rmUIDValues
}
func GetAttrNameArr(r *http.Request) []string {
vars := r.URL.Query()
fields, ok := vars["fields"]
if !ok {
log.Debug("attributeNames does not exist")
return nil
}
var attrNames []string
for _, a := range fields {
if a != "" {
attrNames = global.MergeStringArr(attrNames, strings.Split(a, `,`))
}
}
return attrNames
}
func CheckValidRmUID(rmUIDs []string) []string {
log.Debug("GetLocalRmUID processing... ")
var invalidRmUIDs []string
for _, r := range rmUIDs {
if !global.MatchRmUID(RMUID_REGEXP, r) {
invalidRmUIDs = append(invalidRmUIDs, r)
}
}
return invalidRmUIDs
}
func CheckLocalRmUID(rmUIDs []string) string {
log.Debug("GetLocalRmUID processing... ")
rmUID := config.GetRmUIDFromConfig()
for _, r := range rmUIDs {
if r == rmUID {
return rmUID
}
}
return ""
}
func GetNRMByUri(w http.ResponseWriter, r *http.Request) {
log.Debug("GetNRMByUri processing... ")
// response 414-4 uri too long ? (optional)
// todo ... ?
if bytes.Count([]byte(r.RequestURI), nil) > MAX_URI_LEN {
log.Debug("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil))
services.ResponseRequestURITooLong414UriTooLong(w)
return
}
// check media type(content type) only support "application/json"
// response 415-1
if !IsVallidContentType(r) {
log.Debug("Invalid Content-Type")
services.ResponseUnsupportedMediaType415(w)
return
}
// error processing ...
// 401-1 response
token, ret := globalSession.IsCarriedToken(r)
if !ret {
log.Debug("AccessToken is not carried")
services.ResponseUnauthorized401AccessTokenNotCarried(w)
return
}
// 401-2 response
if globalSession.IsValidToken(token) {
log.Debug("AccessToken fails or does not exist")
services.ResponseUnauthorized401AccessTokenNotExist(w)
return
}
// response 403 Forbidden, permissions deny
// todo...
plist := globalSession.GetPermissionFromSession(token)
log.Debug("permission list:", plist)
if len(plist) == 0 || !plist[0] {
log.Debug("User permission deny")
services.ResponseForbidden403NotPermission(w)
return
}
vars := mux.Vars(r)
qeuryUri := vars["apiCategory"] + "/" + vars["elementTypeValue"] + "/" + vars["objectTypeValue"]
log.Debug("Get by Uri: ", qeuryUri)
apiVer := vars["apiVersion"]
if apiVer != "v1" {
log.Debug("Uri is invalid")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// response 406-1
rmUIDValues := GetRmUIDArr(r)
if rmUIDValues == nil {
log.Debug("missing parameter: rmUIDs")
services.ResponseNotAcceptable406MissingParam(w)
return
}
// response 406-2
errorParams := CheckParameterName(r)
if errorParams != nil {
log.Debug("parameter name error: ", errorParams)
services.ResponseNotAcceptable406ParamError(w, errorParams)
return
}
// response 400-5
if len(rmUIDValues) == 0 {
log.Debug("rmUIDs is wrong or NULL")
services.ResponseBadRequest400WrongParamValue(w)
return
}
// response 414-1
if len(rmUIDValues) > MAX_RMUID_NUM {
log.Debug("rmUID greater than", MAX_RMUID_NUM)
services.ResponseRequestURITooLong414NRMNumExceed(w, MAX_RMUID_NUM)
return
}
// response 400-1
// check rmUID is valid
// todo ...
invalidRmUIDs := CheckValidRmUID(rmUIDValues)
if len(invalidRmUIDs) != 0 {
log.Debug("rmUID is invalid")
services.ResponseBadRequest400RmUIDsIsInvalid(w, invalidRmUIDs)
return
}
// response 404-2
rmUID := CheckLocalRmUID(rmUIDValues)
if rmUID == "" {
log.Debug("rmUID does not exist")
services.ResponseNotFound404NRMNotExist(w, rmUIDValues)
return
}
// response 404-1, uri is not exist in map
attrNames := GetAttrNameArr(r)
var Oids []string
Oids = *config.GetOidByFileds(qeuryUri, attrNames, &Oids)
if len(Oids) == 0 {
log.Debug("Nothing of config map")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// response 404-1, uri is not exist in map
var nameOids []config.NameOid
nameOids = *config.GetDataOidByFields(qeuryUri, attrNames, &nameOids)
if len(nameOids) == 0 {
log.Debug("Nothing of config map")
services.ResponseNotFound404UriNotExist(w, r)
return
}
result, err2 := g.Default.Get(Oids) // Get() accepts up to g.MAX_OIDS
if err2 != nil {
log.Fatalf("Get() err: %v", err2)
}
// var nameValues []config.NameValue
var nameValue config.NameValue
nameValues := make(map[string]interface{})
nameValues["rmUID"] = rmUID
for i, variable := range result.Variables {
nameValue.Name = nameOids[i].Name
log.Debugf("%d: oid: %s name: %s\n", i, variable.Name, nameValue.Name)
// if nameOids[i].Oid == variable.Name && global.IsContain(attributeNames, nameValue.Name) {
if nameOids[i].Oid == variable.Name {
// the Value of each variable returned by Get() implements
// interface{}. You could do a type switch...
switch variable.Type {
case g.OctetString:
bytes := variable.Value.([]byte)
log.Debugf("string: %s\n", string(bytes))
nameValue.Value = string(bytes)
nameValues[nameValue.Name] = nameValue.Value
case g.Integer:
value := variable.Value.(int)
log.Debugf("integer: %d\n", value)
nameValue.Value = strconv.Itoa(value)
nameValues[nameValue.Name] = nameValue.Value
case g.IPAddress:
value := variable.Value.(string)
log.Debugf("IPAddress: %s\n", variable.Value)
nameValue.Value = value
nameValues[nameValue.Name] = nameValue.Value
default:
// ... or often you're just interested in numeric values.
// ToBigInt() will return the Value as a BigInt, for plugging
// into your calculations.
log.Debugf("number: %d\n", g.ToBigInt(variable.Value))
}
}
}
getResponse := services.DataResponse{Data: nameValues}
services.ResponseWithJson(w, http.StatusOK, getResponse)
}
func RestfulPut(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
queryNo := vars["no"]
var targetTodo stTodo
for _, Todo := range TodoList {
if Todo.No == queryNo {
targetTodo = Todo
}
}
response := ApiResponse{"200", targetTodo}
services.ResponseWithJson(w, http.StatusOK, response)
}
func RestfulHead(w http.ResponseWriter, r *http.Request) {
var targetTodo stTodo
response := ApiResponse{"200", targetTodo}
services.ResponseWithJson(w, http.StatusOK, response)
}
func RemoveElement(TodoList []stTodo, No string) stTodo {
// var targetTodo stTodo
j := 0
if len(TodoList) == 0 {
return TodoList[j]
}
for i := 0; i < len(TodoList); i++ {
if TodoList[i].No != No {
if i != j {
TodoList[i], TodoList[j] = TodoList[j], TodoList[i]
}
j++
}
}
log.Debug(TodoList[j].No, TodoList[j].Item)
return TodoList[j]
}
func RestfulDelete(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
queryNo := vars["no"] //获取No
log.Debug("RestfulDelete processing... ")
targetTodo := RemoveElement(TodoList, queryNo)
response := ApiResponse{"200", targetTodo}
services.ResponseWithJson(w, http.StatusOK, response)
}
func RestfulOptions(w http.ResponseWriter, r *http.Request) {
var targetTodo stTodo
response := ApiResponse{"200", targetTodo}
services.ResponseWithJson(w, http.StatusOK, response)
}
func RestfulTrace(w http.ResponseWriter, r *http.Request) {
var targetTodo stTodo
response := ApiResponse{"200", targetTodo}
services.ResponseWithJson(w, http.StatusOK, response)
}
func RestfulPatch(w http.ResponseWriter, r *http.Request) {
var targetTodo stTodo
response := ApiResponse{"200", targetTodo}
services.ResponseWithJson(w, http.StatusOK, response)
}

View File

@@ -1,138 +0,0 @@
package file_export
import (
"encoding/json"
"net/http"
"os"
"path/filepath"
"be.ems/lib/file"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/database/db"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"github.com/gin-gonic/gin"
)
type SysJobResponse struct {
SysJob
TableName string `json:"tableName"`
TableDisplay string `json:"tableDisplay"`
FilePath string `json:"filePath"`
}
type TargetParams struct {
Hour int `json:"hour"` // hour
TableName string `json:"tableName"`
Columns []string `json:"columns"`
FilePath string `json:"filePath"` // file path
}
func (m *SysJob) GetFileExportTable(c *gin.Context) {
var results []SysJob
tx := db.DB("").Table("sys_job").Where("invoke_target=?", INVOKE_FILE_EXPORT)
if err := tx.Find(&results).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
language := reqctx.AcceptLanguage(c)
var response []SysJobResponse
for _, job := range results {
var params TargetParams
if err := json.Unmarshal([]byte(job.TargetParams), &params); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
TableDisplay := i18n.TKey(language, "table."+params.TableName)
if TableDisplay == "" {
TableDisplay = params.TableName
}
response = append(response, SysJobResponse{
SysJob: job,
TableName: params.TableName,
TableDisplay: TableDisplay,
FilePath: params.FilePath,
})
}
c.JSON(http.StatusOK, services.DataResp(response))
}
func (m *FileExport) GetFileList(c *gin.Context) {
var querys FileExportQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
files, err := file.GetFileInfo(querys.Path, querys.Suffix)
if err != nil {
log.Error("failed to GetFileInfo:", err)
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
// split files list
lenNum := int64(len(files))
start := (querys.PageNum - 1) * querys.PageSize
end := start + querys.PageSize
var splitList []file.FileInfo
if start >= lenNum {
splitList = []file.FileInfo{}
} else if end >= lenNum {
splitList = files[start:]
} else {
splitList = files[start:end]
}
total := len(files)
c.JSON(http.StatusOK, services.TotalDataResp(splitList, total))
}
func (m *FileExport) Total(c *gin.Context) {
dir := c.Query("path")
fileCount, dirCount, err := file.GetFileAndDirCount(dir)
if err != nil {
log.Error("failed to GetFileAndDirCount:", err)
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
total := fileCount + dirCount
c.JSON(http.StatusOK, services.TotalResp(int64(total)))
}
func (m *FileExport) DownloadHandler(c *gin.Context) {
dir := c.Query("path")
fileName := c.Param("fileName")
filePath := filepath.Join(dir, fileName)
file, err := os.Open(filePath)
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
defer file.Close()
if _, err := os.Stat(filePath); os.IsNotExist(err) {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.Header("Content-Disposition", "attachment; filename="+fileName)
c.Header("Content-Type", "application/octet-stream")
c.File(filePath)
}
func (m *FileExport) Delete(c *gin.Context) {
fileName := c.Param("fileName")
dir := c.Query("path")
filePath := filepath.Join(dir, fileName)
if err := os.Remove(filePath); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusNoContent, nil) // 204 No Content
}

View File

@@ -1,30 +0,0 @@
package file_export
import (
"be.ems/lib/file"
)
const (
INVOKE_FILE_EXPORT = "exportTable"
)
type SysJob struct {
JobID int64 `gorm:"column:job_id;primary_key;auto_increment" json:"job_id"` //任务ID
InvokeTarget string `gorm:"column:invoke_target" json:"invoke_target"` //调用目标字符串
TargetParams string `gorm:"column:target_params;type:json" json:"target_params,omitempty"` //调用目标传入参数
}
func (m *SysJob) TableName() string {
return "sys_job"
}
type FileExport struct {
file.FileInfo
}
type FileExportQuery struct {
Path string `form:"path" binding:"required"`
Suffix string `form:"suffix"`
PageNum int64 `form:"pageNum" binding:"required"`
PageSize int64 `form:"pageSize" binding:"required"`
}

View File

@@ -1,39 +0,0 @@
package file_export
import (
"be.ems/src/framework/middleware"
"github.com/gin-gonic/gin"
)
// Register Routes for file_export
func Register(r *gin.RouterGroup) {
lmTable := r.Group("/table")
{
var m *SysJob
lmTable.GET("/list",
middleware.AuthorizeUser(nil),
m.GetFileExportTable,
)
}
lmFile := r.Group("/file")
{
var f *FileExport
lmFile.GET("/list",
middleware.AuthorizeUser(nil),
f.GetFileList,
)
lmFile.GET("/total",
middleware.AuthorizeUser(nil),
f.Total,
)
lmFile.GET("/:fileName",
middleware.AuthorizeUser(nil),
f.DownloadHandler,
)
lmFile.DELETE("/:fileName",
middleware.AuthorizeUser(nil),
f.Delete,
)
}
}

View File

@@ -1,103 +0,0 @@
package lm
import (
"fmt"
"net/http"
"os/exec"
"time"
"be.ems/lib/config"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/database/db"
"github.com/gorilla/mux"
)
type XormResponse struct {
Data interface{} `json:"data"`
}
type XormInsertResponse struct {
Data interface{} `json:"data"`
}
var (
ExtBackupDataUri = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/{dataStorage}/{dataObject}/backup" // for external
CustomExtBackupDataUri = config.UriPrefix + "/dataManagement/{apiVersion}/{dataStorage}/{dataObject}/backup" // for external
)
// func init() {
// conf := config.GetYamlConfig()
// InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
// conf.Database.Host, conf.Database.Port, conf.Database.Name)
// }
func ExtDatabaseBackupData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseBackupData processing... ")
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
module := vars["managementModule"]
dbname := vars["dataStorage"]
tbname := vars["dataObject"]
pack := "lm"
log.Debugf("method:%s, module:%s dbname:%s, tbname:%s pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
// log.Error("Failed to get permission:", err)
// services.ResponseForbidden403NotPermission(w)
// return
// }
// if !exist {
// log.Error("permission deny!")
// services.ResponseForbidden403NotPermission(w)
// return
// }
var sql string
var filePath string
switch tbname {
case "operation_log":
filePath = fmt.Sprintf("/tmp/%s-%s.csv", tbname, time.Now().Local().Format(global.DateData))
sql = fmt.Sprintf("select * into outfile '%s' fields terminated by ',' escaped by '' optionally enclosed by '' lines terminated by '\n' from (select 'op_id','account_name','op_ip','subsys_tag','op_type','op_content','op_result','begin_time','end_time','vnf_flag','log_time' union select op_id,account_name,op_ip,subsys_tag,op_type,op_content,op_result,begin_time,end_time,vnf_flag,log_time from operation_log) b", filePath)
case "security_log":
filePath = fmt.Sprintf("/tmp/%s-%s.csv", tbname, time.Now().Local().Format(global.DateData))
sql = fmt.Sprintf("select * into outfile '%s' fields terminated by ',' escaped by '' optionally enclosed by '' lines terminated by '\n' from (select 'id','account_name','account_type','op_ip','op_type','op_content','op_result','op_time' union select id,account_name,account_type,op_ip,op_type,op_content,op_result,op_time from security_log) b", filePath)
case "alarm_log":
filePath = fmt.Sprintf("/tmp/%s-%s.csv", tbname, time.Now().Local().Format(global.DateData))
sql = fmt.Sprintf("select * into outfile '%s' fields terminated by ',' escaped by '' optionally enclosed by '' lines terminated by '\n' from (select 'id','ne_type','ne_id','alarm_seq','alarm_id','alarm_code','alarm_status','event_time','log_time' union select id,ne_type,ne_id,alarm_seq,alarm_id,alarm_code,alarm_status,event_time,log_time from alarm_log) b", filePath)
default:
log.Error("error target table")
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
affected, err := db.ExecDB("", sql, nil)
if err != nil {
log.Error("Failed to exec SQL:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
log.Debugf("filePath:%s backup dir:%s", filePath, config.GetYamlConfig().OMC.Backup)
cmd := exec.Command("cp", "-rf", filePath, config.GetYamlConfig().OMC.Backup)
out, err := cmd.CombinedOutput()
log.Debugf("Exec output: %v", string(out))
if err != nil {
log.Error("Faile to exec:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
mapRow := make(map[string]interface{})
row := map[string]interface{}{"affectedRows": affected}
mapRow[tbname] = row
services.ResponseWithJson(w, http.StatusOK, mapRow)
}

View File

@@ -1,17 +0,0 @@
// log management package
package lm
import (
"be.ems/features/lm/file_export"
"be.ems/lib/log"
"github.com/gin-gonic/gin"
)
func InitSubServiceRoute(r *gin.Engine) {
log.Info("======init Log management group gin.Engine")
lmGroup := r.Group("/lm")
// register sub modules routes
file_export.Register(lmGroup)
}

View File

@@ -1,705 +0,0 @@
package mml
import (
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"regexp"
"strings"
"time"
"be.ems/lib/config"
"be.ems/lib/core/ctx"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/mmlp"
"be.ems/lib/services"
"be.ems/src/framework/constants"
neModel "be.ems/src/modules/network_element/model"
neService "be.ems/src/modules/network_element/service"
)
// const (
// //经过测试linux下延时需要大于100ms
// TIME_DELAY_AFTER_WRITE = 200
// TIME_DEAD_LINE = 10
// )
type Response struct {
Data []string `json:"data"`
}
type MMLRequest struct {
MML []string `json:"mml"`
}
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}"
)
var (
TIME_DELAY_AFTER_WRITE time.Duration = 200
TIME_DEAD_LINE time.Duration = 10
WIN_ROW_SIZE int16 = 200
WIN_COL_SIZE int16 = 120
BUFFER_SIZE int = 65535
)
func InitMML() {
if config.GetYamlConfig().MML.Sleep != 0 {
TIME_DELAY_AFTER_WRITE = time.Duration(config.GetYamlConfig().MML.Sleep)
}
if config.GetYamlConfig().MML.DeadLine != 0 {
TIME_DEAD_LINE = time.Duration(config.GetYamlConfig().MML.DeadLine)
}
WIN_ROW_SIZE = config.GetYamlConfig().MML.SizeRow
WIN_COL_SIZE = config.GetYamlConfig().MML.SizeCol
BUFFER_SIZE = config.GetYamlConfig().MML.BufferSize
}
func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
log.Info("PostMML2ToNF processing... ")
neType := ctx.GetParam(r, "elementTypeValue")
neId := ctx.GetQuery(r, "ne_id")
if neId == "" {
log.Error("NOT FOUND ne_id")
services.ResponseBadRequest400WrongParamValue(w)
return
}
log.Debug("neType:", neType, "neId", neId)
neInfoArr := neService.NewNeInfo.Find(neModel.NeInfo{NeType: neType, NeId: neId}, false, true)
if len(neInfoArr) < 1 {
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
neInfo := neInfoArr[0]
if neInfo.NeId != neId || neInfo.IP == "" || len(neInfo.Hosts) < 2 {
services.ResponseWithJson(w, 200, map[string]any{
"code": 0,
"msg": "neInfo not found",
})
return
}
telnetHost := neInfo.Hosts[1]
buf := make([]byte, BUFFER_SIZE)
var n int
var mmlResult []string
hostMML := net.JoinHostPort(telnetHost.Addr, fmt.Sprintf("%d", telnetHost.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.Write([]byte{255, 251, 31}) // 发送WILL WINDOW SIZE
conn.Write([]byte{
255, 250, 31,
byte(WIN_COL_SIZE >> 8), byte(WIN_COL_SIZE & 0xFF),
byte(WIN_ROW_SIZE >> 8), byte(WIN_ROW_SIZE & 0xFF),
255, 240,
}) // 发送设置 WINDOW SIZE
conn.SetDeadline(time.Now().Add(TIME_DEAD_LINE * time.Second))
loginStr := fmt.Sprintf("%s\n%s\n", telnetHost.User, telnetHost.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]), "")
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... ")
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
// 经过测试linux下延时需要大于100ms
// var TIME_DELAY_AFTER_WRITE time.Duration = 200
// var TIME_DEAD_LINE time.Duration = 10
// if config.GetYamlConfig().MML.Sleep != 0 {
// TIME_DELAY_AFTER_WRITE = time.Duration(config.GetYamlConfig().MML.Sleep)
// }
// if config.GetYamlConfig().MML.DeadLine != 0 {
// TIME_DEAD_LINE = time.Duration(config.GetYamlConfig().MML.DeadLine)
// }
neType := ctx.GetParam(r, "elementTypeValue")
neId := ctx.GetQuery(r, "ne_id")
if neId == "" {
log.Error("NOT FOUND ne_id")
services.ResponseBadRequest400WrongParamValue(w)
return
}
log.Debug("neType:", neType, "neId", neId)
if strings.ToLower(neType) == "omc" {
PostMMLToOMC(w, r)
return
}
neInfoArr := neService.NewNeInfo.Find(neModel.NeInfo{NeType: neType, NeId: neId}, false, true)
if len(neInfoArr) < 1 {
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
neInfo := neInfoArr[0]
if neInfo.NeId != neId || neInfo.IP == "" || len(neInfo.Hosts) < 2 {
services.ResponseWithJson(w, 200, map[string]any{
"code": 0,
"msg": "neInfo not found",
})
return
}
telnetHost := neInfo.Hosts[1]
var buf [20 * 1024]byte
//buf := make([]byte, 0)
var n int
var mmlResult []string
switch strings.ToLower(neType) {
case "xxx":
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
log.Trace("Body:", string(body))
mmlRequest := new(MMLRequest)
_ = json.Unmarshal(body, mmlRequest)
// 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]))
// 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()
// conn.SetDeadline(time.Now().Add(10 * 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.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
// }
// log.Debug(string(buf[0:n]))
// 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]))
// 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
// }
// log.Debug(string(buf[0:n]))
// 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]))
for _, mml := range mmlRequest.MML {
hostMML := net.JoinHostPort(telnetHost.Addr, fmt.Sprintf("%d", telnetHost.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()
conn.SetDeadline(time.Now().Add(TIME_DEAD_LINE * time.Second))
loginStr := fmt.Sprintf("%s\n%s\n", telnetHost.User, telnetHost.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
continue
}
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
mmlCommand := fmt.Sprintf("%s\n", mml)
log.Debug("mml command:", mmlCommand)
_, 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]`)
// upf telnet buffer只能读取一次需要去掉前面的多余字符
//result := re1.ReplaceAllString(string(buf[config.GetYamlConfig().MML.UpfHeaderLength:n-len(neType)-2]), "")
result := re1.ReplaceAllString(string(buf[0:n-len(neType)-2]), "")
result = re2.ReplaceAllString(result, "")
mmlResult = append(mmlResult, result)
conn.Close()
//mmlResult = append(mmlResult, string(buf[0:n-len(neType)-2]))
// can't read buffer from upf telnet server, so return ok always
// mmlResult = append(mmlResult, "COMMAND OK\n")
}
case "ims":
hostMML := net.JoinHostPort(telnetHost.Addr, fmt.Sprintf("%d", telnetHost.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(TIME_DEAD_LINE * time.Second))
_, err = conn.Write([]byte(telnetHost.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.Trace(string(buf[0:n]))
_, err = conn.Write([]byte(telnetHost.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)
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\r\n", mml)
log.Debug("mml command:", mmlCommand)
_, 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)
}
default:
hostMML := net.JoinHostPort(telnetHost.Addr, fmt.Sprintf("%d", telnetHost.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(TIME_DEAD_LINE * time.Second))
loginStr := fmt.Sprintf("%s\n%s\n", telnetHost.User, telnetHost.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)
// UDM 特殊命令处理
if neType == "UDM" && mml == "dec key" {
output, err := neService.NewNeInfo.NeRunSSHCmd(neInfo.NeType, neInfo.NeId, "cat /usr/local/etc/udm/ueKeyProfile.tmp")
if err != nil {
mmlResult = append(mmlResult, err.Error())
} else {
mmlResult = append(mmlResult, output)
}
}
}
}
response := Response{mmlResult}
services.ResponseWithJson(w, http.StatusOK, response)
}
func PostMMLToOMC(w http.ResponseWriter, r *http.Request) {
log.Debug("PostMMLToOMC processing... ")
neType := "OMC" //ctx.GetParam(r, "elementTypeValue")
neId := ctx.GetQuery(r, "ne_id")
if neId == "" {
log.Error("NOT FOUND ne_id")
services.ResponseBadRequest400WrongParamValue(w)
return
}
log.Debug("neType:", neType, "neId", neId)
neInfoArr := neService.NewNeInfo.Find(neModel.NeInfo{NeType: neType, NeId: neId}, false, false)
if len(neInfoArr) < 1 {
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
neInfo := neInfoArr[0]
if neInfo.NeId != neId || neInfo.IP == "" {
services.ResponseWithJson(w, 200, map[string]any{
"code": 0,
"msg": "neInfo not found",
})
return
}
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
log.Trace("Body:", string(body))
hostUri := fmt.Sprintf("http://%s:%d", neInfo.IP, neInfo.Port)
omcMmlVar := &mmlp.MmlVar{
Version: global.Version,
Output: mmlp.DefaultFormatType,
MmlHome: config.GetYamlConfig().MML.MmlHome,
Limit: 50,
User: "",
SessionToken: "", // 旧token
Authorization: r.Header.Get(constants.HEADER_KEY), // 请求Token
HttpUri: hostUri,
UserAgent: config.GetDefaultUserAgent(),
}
mmlRequest := new(MMLRequest)
_ = json.Unmarshal(body, mmlRequest)
var mmlResult []string
mmlLine := strings.Join(mmlRequest.MML, ";")
var mmlCmds []mmlp.MmlCommand
if err = mmlp.ParseMMLCommand(mmlLine, &mmlCmds); err != nil {
response := fmt.Sprintf("parse command error: %v\n", err)
mmlResult = append(mmlResult, response)
}
for _, mmlCmd := range mmlCmds {
output, err := mmlp.TransMml2HttpReq(omcMmlVar, &mmlCmd)
if err != nil {
response := fmt.Sprintf("translate MML command error: %v]\n", err)
mmlResult = append(mmlResult, response)
}
mmlResult = append(mmlResult, string(*output))
}
response := Response{mmlResult}
services.ResponseWithJson(w, http.StatusOK, response)
}

View File

@@ -1,257 +0,0 @@
package nbi_file
import (
"archive/zip"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"time"
"be.ems/lib/dborm"
"be.ems/lib/file"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/services"
"github.com/gin-gonic/gin"
)
type SysJobResponse struct {
SysJob
TableName string `json:"tableName"`
TableDisplay string `json:"tableDisplay"`
FilePath string `json:"filePath"`
}
type TargetParams struct {
Duration int `json:"duration"`
TableName string `json:"tableName"`
Columns string `json:"columns"` // exported column name of time string
TimeCol string `json:"timeCol"` // time stamp of column name
TimeUnit string `json:"timeUnit"` // timestamp unit: second/micro/milli
Extras string `json:"extras"` // extras condition for where
FilePath string `json:"filePath"` // file path
}
func (m *FileNBI) GetFileList(c *gin.Context) {
var querys FileNBIQuery
querys.Category = c.Param("category")
querys.Type = c.Param("type")
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
if querys.Path == "" {
tableName := ""
ok := false
switch querys.Category {
case "cdr":
tableName, ok = CDRTableMapper[querys.Type]
if tableName == "" || !ok {
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type)))
return
}
case "log":
tableName, ok = LogTableMapper[querys.Type]
if tableName == "" || !ok {
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type)))
return
}
default:
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category)))
return
}
s := SysJob{}
where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName)
_, err := dborm.XEngDB().Table(s.TableName()).
Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path").
Where(where).
Get(&querys.Path)
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
}
files, err := file.GetFileInfo(querys.Path, querys.Suffix)
if err != nil {
log.Error("failed to GetFileInfo:", err)
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
// split files list
lenNum := int64(len(files))
start := (querys.PageNum - 1) * querys.PageSize
end := start + querys.PageSize
var splitList []file.FileInfo
if start >= lenNum {
splitList = []file.FileInfo{}
} else if end >= lenNum {
splitList = files[start:]
} else {
splitList = files[start:end]
}
total := len(files)
c.JSON(http.StatusOK, services.TotalDataResp(splitList, total))
}
func (m *FileNBI) Total(c *gin.Context) {
dir := c.Query("path")
fileCount, dirCount, err := file.GetFileAndDirCount(dir)
if err != nil {
log.Error("failed to GetFileAndDirCount:", err)
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
total := fileCount + dirCount
c.JSON(http.StatusOK, services.TotalResp(int64(total)))
}
func (m *FileNBI) GetSingleFileHandler(c *gin.Context) {
var querys FileNBIQuery
querys.Category = c.Param("category")
querys.Type = c.Param("type")
querys.DateIndex = c.Param("dateIndex")
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
tableName := ""
if querys.Path == "" {
ok := false
switch querys.Category {
case "cdr":
tableName, ok = CDRTableMapper[querys.Type]
if tableName == "" || !ok {
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type)))
return
}
case "log":
tableName, ok = LogTableMapper[querys.Type]
if tableName == "" || !ok {
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type)))
return
}
default:
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category)))
return
}
s := SysJob{}
where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName)
_, err := dborm.XEngDB().Table(s.TableName()).
Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path").
Where(where).
Get(&querys.Path)
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
}
fileName := tableName + "_export_" + querys.DateIndex + "0000" + ".csv"
filePath := filepath.Join(querys.Path, fileName)
file, err := os.Open(filePath)
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
defer file.Close()
if _, err := os.Stat(filePath); os.IsNotExist(err) {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.Header("Content-Disposition", "attachment; filename="+fileName)
c.Header("Content-Type", "application/octet-stream")
c.File(filePath)
}
func (m *FileNBI) GetMultiFileHandler(c *gin.Context) {
var querys FileNBIQuery
querys.Category = c.Param("category")
querys.Type = c.Param("type")
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
tableName := ""
if querys.Path == "" {
ok := false
switch querys.Category {
case "cdr":
tableName, ok = CDRTableMapper[querys.Type]
if tableName == "" || !ok {
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type)))
return
}
case "log":
tableName, ok = LogTableMapper[querys.Type]
if tableName == "" || !ok {
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type)))
return
}
default:
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category)))
return
}
s := SysJob{}
where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName)
_, err := dborm.XEngDB().Table(s.TableName()).
Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path").
Where(where).
Get(&querys.Path)
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
}
zipWriter := zip.NewWriter(c.Writer)
defer zipWriter.Close()
for _, fileName := range querys.FileNames {
filePath := filepath.Join(querys.Path, fileName)
file, err := os.Open(filePath)
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
defer file.Close()
if _, err := os.Stat(filePath); os.IsNotExist(err) {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
writer, err := zipWriter.Create(filepath.Base(fileName))
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
if _, err := io.Copy(writer, file); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
}
zipFile := tableName + "_export_" + time.Now().Local().Format(global.DateData) + ".zip"
c.Header("Content-Disposition", "attachment; filename="+zipFile)
c.Header("Content-Type", "application/zip")
//c.File(filePath)
}

View File

@@ -1,47 +0,0 @@
package nbi_file
import (
"be.ems/lib/file"
)
const (
INVOKE_FILE_EXPORT = "exportTable"
)
var CDRTableMapper map[string]string = map[string]string{
"ims": "cdr_event_ims",
"smf": "cdr_event_smf",
"smsc": "cdr_event_smsc",
"sms": "cdr_event_smsc",
}
var LogTableMapper map[string]string = map[string]string{
"operate": "sys_log_operate",
"security": "sys_log_login",
"alarm": "alarm_log",
}
type SysJob struct {
JobID int64 `gorm:"column:job_id;primary_key;auto_increment" json:"job_id"` //任务ID
InvokeTarget string `gorm:"column:invoke_target" json:"invoke_target"` //调用目标字符串
TargetParams string `gorm:"column:target_params;type:json" json:"target_params,omitempty"` //调用目标传入参数
}
func (s *SysJob) TableName() string {
return "sys_job"
}
type FileNBI struct {
file.FileInfo
}
type FileNBIQuery struct {
Category string `form:"category" binding:"required"`
Type string `form:"type" binding:"required"`
DateIndex string `form:"dateIndex"`
Path string `json:"path" form:"path"`
FileNames []string `json:"fileName" form:"fileName"`
Suffix string `form:"suffix"`
PageNum int64 `form:"pageNum"`
PageSize int64 `form:"pageSize"`
}

View File

@@ -1,26 +0,0 @@
package nbi_file
import (
"be.ems/src/framework/middleware"
"github.com/gin-gonic/gin"
)
// Register Routes for file_export
func Register(r *gin.RouterGroup) {
fileNBI := r.Group("/file")
{
var f *FileNBI
fileNBI.GET("/:category/:type/list",
middleware.AuthorizeUser(nil),
f.GetFileList,
)
fileNBI.GET("/:category/:type/:dateIndex",
middleware.AuthorizeUser(nil),
f.GetSingleFileHandler,
)
fileNBI.GET("/:category/:type",
middleware.AuthorizeUser(nil),
f.GetMultiFileHandler,
)
}
}

View File

@@ -1,258 +0,0 @@
package nbi
import (
"bytes"
"fmt"
"net/http"
"strings"
"be.ems/lib/dborm"
"github.com/go-resty/resty/v2"
"github.com/gorilla/mux"
"be.ems/lib/config"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/oauth"
"be.ems/lib/services"
)
type ErrorOAuthResponse struct {
Error map[string]interface{}
}
type FailOAuthResponse struct {
Error struct {
ErrorCode string
ErrorInfo string
}
}
type ApiResponse struct {
ResultCode string
ResultMessage interface{}
}
//var globalSession = session.NewSessManager("restagent")
var (
MAX_RMUID_NUM int
MAX_ALARMID_NUM int
MAX_PMUID_NUM int
MAX_SUBID_NUM int
MAX_URI_LEN int
RMUID_REGEXP string
)
var (
// Northbound interface
GetNRMUri = config.DefaultUriPrefix + "/resourceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
NorthboundGetAlarmUri = config.DefaultUriPrefix + "/faultManagement/{apiVersion}/alarms" // ?alarmIds={alarmIdValues}
CustomGetNRMUri = config.UriPrefix + "/resourceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
)
func CheckParameterName(r *http.Request) []string {
var errorParams []string
vars := r.URL.Query()
for k, v := range vars {
log.Debug("vars:", k, v)
if k != "rmUIDs" && k != "fields" {
errorParams = append(errorParams, k)
}
}
return errorParams
}
func GetRmUIDArr(r *http.Request) []string {
vars := r.URL.Query()
rmUIDs, ok := vars["rmUIDs"]
if !ok {
log.Debug("rmUIDs is not exist")
return nil
}
var rmUIDValues []string
for _, r := range rmUIDs {
if r != "" {
rmUIDValues = global.MergeStringArr(rmUIDValues, strings.Split(r, `,`))
}
}
return rmUIDValues
}
func GetAttrNameArr(r *http.Request) []string {
vars := r.URL.Query()
fields, ok := vars["fields"]
if !ok {
log.Debug("attributeNames does not exist")
return nil
}
var attrNames []string
for _, a := range fields {
if a != "" {
attrNames = global.MergeStringArr(attrNames, strings.Split(a, `,`))
}
}
return attrNames
}
func CheckValidRmUID(rmUIDs []string) []string {
log.Debug("CheckValidRmUID processing... ")
var invalidRmUIDs []string
for _, r := range rmUIDs {
if !global.MatchRmUID(RMUID_REGEXP, r) {
invalidRmUIDs = append(invalidRmUIDs, r)
}
}
return invalidRmUIDs
}
func CheckLocalRmUID(rmUIDs []string) string {
log.Debug("GetLocalRmUID processing... ")
rmUID := config.GetRmUIDFromConfig()
for _, r := range rmUIDs {
if r == rmUID {
return rmUID
}
}
return ""
}
func NBIGetNRMFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("NBIGetNRMFromNF processing... ")
// response 414-4 uri too long ? (optional)
// todo ... ?
if bytes.Count([]byte(r.RequestURI), nil) > config.GetUriMaxLenFromConfig() {
log.Error("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil), config.GetUriMaxLenFromConfig())
services.ResponseRequestURITooLong414UriTooLong(w)
return
}
// check media type(content type) only support "application/json"
// response 415-1
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
log.Debug("Invalid Content-Type")
services.ResponseUnsupportedMediaType415(w)
return
}
// error processing ...
// 401-1 response
token, ret := oauth.IsCarriedToken(r)
if ret == false {
log.Error("AccessToken is not carried")
services.ResponseUnauthorized401AccessTokenNotCarried(w)
return
}
// 401-2 response
if dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) == false {
log.Error("AccessToken fails or does not exist")
services.ResponseUnauthorized401AccessTokenNotExist(w)
return
}
_, err := dborm.XormUpdateSessionShakeTime(token)
if err != nil {
log.Error("Failed to update session table:", err)
services.ResponseUnauthorized401AccessTokenNotExist(w)
return
}
/*
// response 403 Forbidden, permissions deny
// todo...
plist := globalSession.GetPermissionFromSession(token)
log.Debug("permission list:", plist)
if len(plist) == 0 || plist[0] == false {
log.Debug("User permission deny")
services.ResponseForbidden403NotPermission(w)
return
}
*/
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
apiVer := vars["apiVersion"]
if apiVer != "v1" {
log.Error("Uri is invalid")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// response 406-1
rmUIDValues := GetRmUIDArr(r)
if rmUIDValues == nil {
log.Error("missing parameter: rmUIDs")
services.ResponseNotAcceptable406MissingParam(w)
return
}
// response 406-2
errorParams := CheckParameterName(r)
if errorParams != nil {
log.Error("parameter name error: ", errorParams)
services.ResponseNotAcceptable406ParamError(w, errorParams)
return
}
// response 400-5
if len(rmUIDValues) == 0 {
log.Error("rmUIDs is wrong or NULL")
services.ResponseBadRequest400WrongParamValue(w)
return
}
// response 414-1
if len(rmUIDValues) > config.GetYamlConfig().Params.RmUIDMaxNum {
log.Error("rmUID greater than", config.GetYamlConfig().Params.RmUIDMaxNum)
services.ResponseRequestURITooLong414NRMNumExceed(w, config.GetYamlConfig().Params.RmUIDMaxNum)
return
}
var response *resty.Response
respMsg := make(map[string]interface{})
for _, rmUID := range rmUIDValues {
neInfo, err := dborm.XormGetNeInfoByRmUID(neType, rmUID)
if err != nil {
log.Error("dborm.XormGetNeInfo is failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
return
}
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.Ip, neInfo.Port, r.RequestURI)
log.Debug("requestURI2NF: GET ", requestURI2NF)
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(requestURI2NF)
if err != nil {
log.Error("Failed to Get from NF:", err)
services.ResponseInternalServerError500NFConnectRefused(w)
return
}
switch response.StatusCode() {
case http.StatusOK, http.StatusAccepted, http.StatusNoContent, http.StatusCreated:
respMsg["data"] = response
default:
if response != nil {
services.TransportResponse(w, response.StatusCode(), response.Body())
}
}
}
services.TransportResponse(w, response.StatusCode(), response.Body())
}

View File

@@ -1,16 +0,0 @@
// log management package
package nbi
import (
nbi_file "be.ems/features/nbi/file"
"be.ems/lib/log"
"github.com/gin-gonic/gin"
)
func InitSubServiceRoute(r *gin.Engine) {
log.Info("======init North-Bound Interface group gin.Engine")
nbiGroup := r.Group("/nbi")
nbi_file.Register(nbiGroup)
}

View File

@@ -1,203 +0,0 @@
package nbi
import (
"bytes"
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
g "github.com/gosnmp/gosnmp"
"be.ems/lib/config"
"be.ems/lib/log"
"be.ems/lib/services"
)
func init() {
conf := config.GetYamlConfig()
// Default is a pointer to a GoSNMP struct that contains sensible defaults
// eg port 161, community public, etc
g.Default.Target = conf.NE.Addr
g.Default.Port = conf.NE.Port
err := g.Default.Connect()
if err != nil {
fmt.Printf("Connect() err: %v", err)
}
//defer g.Default.Conn.Close()
MAX_RMUID_NUM = config.GetRmUIDMaxNumFromConfig()
MAX_ALARMID_NUM = config.GetAlarmIDMaxNumFromConfig()
MAX_PMUID_NUM = config.GetPmIDMaxNumFromConfig()
MAX_SUBID_NUM = config.GetSubIDMaxNumFromConfig()
MAX_URI_LEN = config.GetUriMaxLenFromConfig()
RMUID_REGEXP = config.GetRmUIDRegexpFromConfig()
}
func GetNRMByUri(w http.ResponseWriter, r *http.Request) {
log.Debug("GetNRMByUri processing... ")
// response 414-4 uri too long ? (optional)
// todo ... ?
if bytes.Count([]byte(r.RequestURI), nil) > MAX_URI_LEN {
log.Error("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil))
services.ResponseRequestURITooLong414UriTooLong(w)
return
}
// check media type(content type) only support "application/json"
// response 415-1
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
log.Debug("Invalid Content-Type")
services.ResponseUnsupportedMediaType415(w)
return
}
// error processing ...
// 401-1 response
// token, ret := globalSession.IsCarriedToken(r)
// if ret == false {
// log.Error("AccessToken is not carried")
// services.ResponseUnauthorized401AccessTokenNotCarried(w)
// return
// }
// 401-2 response
// if globalSession.IsValidToken(token) == false {
// log.Error("AccessToken fails or does not exist")
// services.ResponseUnauthorized401AccessTokenNotExist(w)
// return
// }
// response 403 Forbidden, permissions deny
// todo...
// plist := globalSession.GetPermissionFromSession(token)
// log.Debug("permission list:", plist)
// if len(plist) == 0 || plist[0] == false {
// log.Error("User permission deny")
// services.ResponseForbidden403NotPermission(w)
// return
// }
vars := mux.Vars(r)
qeuryUri := vars["apiCategory"] + "/" + vars["elementTypeValue"] + "/" + vars["objectTypeValue"]
log.Debug("Get by Uri: ", qeuryUri)
apiVer := vars["apiVersion"]
if apiVer != "v1" {
log.Error("Uri is invalid")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// response 406-1
rmUIDValues := GetRmUIDArr(r)
if rmUIDValues == nil {
log.Error("missing parameter: rmUIDs")
services.ResponseNotAcceptable406MissingParam(w)
return
}
// response 406-2
errorParams := CheckParameterName(r)
if errorParams != nil {
log.Error("parameter name error: ", errorParams)
services.ResponseNotAcceptable406ParamError(w, errorParams)
return
}
// response 400-5
if len(rmUIDValues) == 0 {
log.Error("rmUIDs is wrong or NULL")
services.ResponseBadRequest400WrongParamValue(w)
return
}
// response 414-1
if len(rmUIDValues) > MAX_RMUID_NUM {
log.Error("rmUID greater than", MAX_RMUID_NUM)
services.ResponseRequestURITooLong414NRMNumExceed(w, MAX_RMUID_NUM)
return
}
// response 400-1
// check rmUID is valid
// todo ...
invalidRmUIDs := CheckValidRmUID(rmUIDValues)
if len(invalidRmUIDs) != 0 {
log.Error("rmUID is invalid")
services.ResponseBadRequest400RmUIDsIsInvalid(w, invalidRmUIDs)
return
}
// response 404-2
rmUID := CheckLocalRmUID(rmUIDValues)
if rmUID == "" {
log.Error("rmUID does not exist")
services.ResponseNotFound404NRMNotExist(w, rmUIDValues)
return
}
// response 404-1, uri is not exist in map
attrNames := GetAttrNameArr(r)
var Oids []string
Oids = *config.GetOidByFileds(qeuryUri, attrNames, &Oids)
if len(Oids) == 0 {
log.Error("Nothing of config map")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// response 404-1, uri is not exist in map
var nameOids []config.NameOid
nameOids = *config.GetDataOidByFields(qeuryUri, attrNames, &nameOids)
if len(nameOids) == 0 {
log.Error("Nothing of config map")
services.ResponseNotFound404UriNotExist(w, r)
return
}
result, err2 := g.Default.Get(Oids) // Get() accepts up to g.MAX_OIDS
if err2 != nil {
log.Fatalf("Get() err: %v", err2)
}
// var nameValues []config.NameValue
var nameValue config.NameValue
nameValues := make(map[string]interface{})
nameValues["rmUID"] = rmUID
for i, variable := range result.Variables {
nameValue.Name = nameOids[i].Name
log.Debugf("%d: oid: %s name: %s\n", i, variable.Name, nameValue.Name)
// if nameOids[i].Oid == variable.Name && global.IsContain(attributeNames, nameValue.Name) {
if nameOids[i].Oid == variable.Name {
// the Value of each variable returned by Get() implements
// interface{}. You could do a type switch...
switch variable.Type {
case g.OctetString:
bytes := variable.Value.([]byte)
log.Debugf("string: %s\n", string(bytes))
nameValue.Value = string(bytes)
nameValues[nameValue.Name] = nameValue.Value
case g.Integer:
value := variable.Value.(int)
log.Debugf("integer: %d\n", value)
nameValue.Value = strconv.Itoa(value)
nameValues[nameValue.Name] = nameValue.Value
case g.IPAddress:
value := variable.Value.(string)
log.Debugf("IPAddress: %s\n", variable.Value)
nameValue.Value = value
nameValues[nameValue.Name] = nameValue.Value
default:
// ... or often you're just interested in numeric values.
// ToBigInt() will return the Value as a BigInt, for plugging
// into your calculations.
log.Debugf("number: %d\n", g.ToBigInt(variable.Value))
}
}
}
getResponse := services.DataResponse{nameValues}
services.ResponseWithJson(w, http.StatusOK, getResponse)
}

View File

@@ -1,349 +0,0 @@
package kpi_c_report
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"be.ems/lib/services"
"be.ems/src/framework/database/db"
"be.ems/src/framework/utils/parse"
"github.com/gin-gonic/gin"
)
func (k *KpiCReport) Get(c *gin.Context) {
var reports []KpiCReport
var conditions []string
var params []any
var querys KpiCReportQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusBadRequest, services.ErrResp(err.Error()))
return
}
// construct condition to get
if querys.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.ToUpper(querys.NeType))
} else {
c.JSON(http.StatusBadRequest, services.ErrResp("Not found NE type"))
return
}
tableName := TableName() + "_" + strings.ToLower(querys.NeType)
dbg := db.DB("").Model(&KpiCReport{}).Table(tableName)
if querys.NeID != "" {
conditions = append(conditions, "rm_uid = (select n.rm_uid from ne_info n where n.ne_type=? and n.ne_id=?)")
params = append(params, strings.ToUpper(querys.NeType), querys.NeID)
} else {
c.JSON(http.StatusBadRequest, services.ErrResp("Not found required parameter NE ID"))
return
}
if querys.StartTime != "" {
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
params = append(params, querys.StartTime)
}
if querys.EndTime != "" {
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
params = append(params, querys.EndTime)
}
conditions = append(conditions, "kpi_values != 'null'")
whereSql := ""
if len(conditions) > 0 {
whereSql += strings.Join(conditions, " and ")
dbg = dbg.Where(whereSql, params...)
}
// page number and size
if pageSize := querys.PageSize; pageSize > 0 {
dbg = dbg.Limit(pageSize)
if pageNum := querys.PageNum; pageNum > 0 {
dbg = dbg.Offset((pageNum - 1) * pageSize)
}
}
// order by
if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
dbg = dbg.Order(orderBy)
}
//err := db.DB("").Table(tableName).Where(whereSql, params...).Find(&reports).Error
err := dbg.Find(&reports).Error
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusOK, services.DataResp(reports))
}
func (k *KpiCReport) GetReport2FE(c *gin.Context) {
var results []KpiCReport
var conditions []string
var params []any
var querys KpiCReportQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
// construct condition to get
if querys.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.ToUpper(querys.NeType))
} else {
c.JSON(http.StatusOK, services.ErrResp("Not found required parameter NE type"))
return
}
tableName := TableName() + "_" + strings.ToLower(querys.NeType)
dbg := db.DB("").Model(&KpiCReport{}).Table(tableName)
if querys.NeID != "" {
conditions = append(conditions, "rm_uid = (select n.rm_uid from ne_info n where n.ne_type=? and n.ne_id=?)")
params = append(params, querys.NeType, querys.NeID)
} else {
c.JSON(http.StatusBadRequest, services.ErrResp("Not found required parameter NE ID"))
return
}
if querys.StartTime != "" {
conditions = append(conditions, "created_at >= ?")
params = append(params, querys.StartTime)
}
if querys.EndTime != "" {
conditions = append(conditions, "created_at <= ?")
params = append(params, querys.EndTime)
}
conditions = append(conditions, "kpi_values != 'null'")
whereSql := ""
if len(conditions) > 0 {
whereSql += strings.Join(conditions, " and ")
dbg = dbg.Where(whereSql, params...)
}
// page number and size
if pageSize := querys.PageSize; pageSize > 0 {
dbg = dbg.Limit(pageSize)
if pageNum := querys.PageNum; pageNum > 0 {
dbg = dbg.Offset((pageNum - 1) * pageSize)
}
}
// order by
if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
dbg = dbg.Order(orderBy)
}
//err := db.DB("").Table(tableName).Where(whereSql, params...).Find(&reports).Error
err := dbg.Find(&results).Error
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
reports := []map[string]any{}
for _, r := range results {
report := map[string]any{
// kip_id ...
"neType": *r.NeType,
"neId": querys.NeID,
"neName": *r.NeName,
"rmUID": *r.RmUID,
"startIndex": r.Index,
"timeGroup": r.Date[:10] + " " + *r.EndTime,
"createdAt": r.CreatedAt,
"granularity": r.Granularity,
}
// 解析 JSON 字符串为 map
var kpiValues []map[string]any
err := json.Unmarshal([]byte(r.KpiValues), &kpiValues)
if err != nil {
continue
}
// 遍历 kpiValues 数组
for _, k := range kpiValues {
kpiId := fmt.Sprint(k["kpiId"])
value := parse.Number(k["value"])
formatted := fmt.Sprintf("%.3d", value)
formattedFloat, err := strconv.ParseFloat(formatted, 64)
if err != nil {
formattedFloat = 0
}
report[kpiId] = formattedFloat
}
reports = append(reports, report)
}
c.JSON(http.StatusOK, services.DataResp(reports))
}
func (k *KpiCReport) GetTotalList(c *gin.Context) {
var reports []KpiCReport
var conditions []string
var params []any
var querys KpiCReportQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
// construct condition to get
if querys.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.ToUpper(querys.NeType))
} else {
c.JSON(http.StatusOK, services.ErrResp("Not found NE type"))
return
}
tableName := TableName() + "_" + strings.ToLower(querys.NeType)
dbg := db.DB("").Model(&KpiCReport{}).Table(tableName)
if querys.StartTime != "" {
conditions = append(conditions, "created_at >= ?")
params = append(params, querys.StartTime)
}
if querys.EndTime != "" {
conditions = append(conditions, "created_at <= ?")
params = append(params, querys.EndTime)
}
conditions = append(conditions, "kpi_values != 'null'")
whereSql := ""
if len(conditions) > 0 {
whereSql += strings.Join(conditions, " and ")
dbg = dbg.Where(whereSql, params...)
}
// get total number
var total int64 = 0
err := dbg.Count(&total).Error
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
// page number and size
if pageSize := querys.PageSize; pageSize > 0 {
dbg = dbg.Limit(pageSize)
if pageNum := querys.PageNum; pageNum > 0 {
dbg = dbg.Offset((pageNum - 1) * pageSize)
}
}
// order by
if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
dbg = dbg.Order(orderBy)
}
//err := db.DB("").Table(tableName).Where(whereSql, params...).Find(&reports).Error
err = dbg.Find(&reports).Error
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusOK, services.TotalDataResp(reports, total))
}
func (k *KpiCReport) Total(c *gin.Context) {
var conditions []string
var params []any
var querys KpiCReportQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
// construct condition to get
if querys.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.ToUpper(querys.NeType))
} else {
c.JSON(http.StatusOK, services.ErrResp("Not found NE type"))
return
}
tableName := TableName() + "_" + strings.ToLower(querys.NeType)
dbg := db.DB("").Model(&KpiCReport{}).Table(tableName)
if querys.StartTime != "" {
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
params = append(params, querys.StartTime)
}
if querys.EndTime != "" {
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
params = append(params, querys.EndTime)
}
conditions = append(conditions, "kpi_values != 'null'")
whereSql := ""
if len(conditions) > 0 {
whereSql += strings.Join(conditions, " and ")
dbg = dbg.Where(whereSql, params...)
}
var total int64 = 0
err := dbg.Count(&total).Error
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusOK, services.TotalResp(total))
}
func (k *KpiCReport) Post(c *gin.Context) {
var report KpiCReport
if err := c.ShouldBindJSON(&report); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
dbg := db.DB("").Model(&KpiCReport{})
if err := dbg.Create(&report).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusCreated, services.DataResp(report))
}
func (k *KpiCReport) Put(c *gin.Context) {
var report KpiCReport
id := c.Param("id")
dbg := db.DB("").Model(&KpiCReport{})
if err := dbg.First(&report, id).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp("custom indicator report not found"))
return
}
if err := c.ShouldBindJSON(&report); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
db.DB("").Model(&KpiCReport{}).Save(&report)
c.JSON(http.StatusOK, services.DataResp(report))
}
func (k *KpiCReport) Delete(c *gin.Context) {
id := c.Param("id")
if err := db.DB("").Delete(&KpiCReport{}, id).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp("custom indicator report not found"))
return
}
c.JSON(http.StatusNoContent, nil) // 204 No Content
}
func InsertKpiCReport(neType string, report KpiCReport) {
tableName := TableName() + "_" + strings.ToLower(neType)
dbg := db.DB("").Model(&KpiCReport{})
if err := dbg.Table(tableName).Create(&report).Error; err != nil {
return
}
}

View File

@@ -1,42 +0,0 @@
package kpi_c_report
type KpiCReport struct {
ID int `gorm:"column:id;primary_key;auto_increment" json:"id"`
NeType *string `gorm:"column:ne_type;default:NULL" json:"neType,omitempty"`
NeName *string `gorm:"column:ne_name;default:" json:"neName,omitempty"`
RmUID *string `gorm:"column:rm_uid;" json:"rmUid,omitempty"`
Date string `gorm:"column:date" json:"date"` // time.Time `gorm:"column:date" json:"date"`
StartTime *string `gorm:"column:start_time" json:"startTime,omitempty"`
EndTime *string `gorm:"column:end_time" json:"endTime,omitempty"`
Index int64 `gorm:"column:index" json:"index"`
Granularity *int64 `gorm:"column:granularity" json:"granularity,omitempty"` //Time granualarity: 5/10/.../60/300 (second)
KpiValues string `gorm:"column:kpi_values" json:"kpiValues,omitempty"`
CreatedAt *int64 `gorm:"column:created_at" json:"createdAt,omitempty"`
}
type KpiCReportQuery struct {
NeType string `json:"neType" form:"neType" binding:"required"`
NeID string `json:"neId" form:"neId" binding:"required"`
RmUID string `json:"rmUID" form:"rmUID"`
StartTime string `json:"startTime" form:"startTime"`
EndTime string `json:"endTime" form:"endTime"`
UserName string `json:"userName" form:"userName"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=created_at"` // 排序字段,填写结果字段
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序asc desc
PageNum int `json:"pageNum" form:"pageNum"`
PageSize int `json:"pageSize" form:"pageSize"`
}
type KpiCReport2FE struct {
NeType string `json:"neType" gorm:"column:ne_type"`
NeId string `json:"neId"`
NeName string `json:"neName" gorm:"column:ne_name"`
RmUID string `json:"rmUid" gorm:"column:rm_uid"`
TimeGroup string `json:"timeGroup"`
StartIndex int16 `json:"startIndex" gorm:"column:index"`
Granularity int8 `json:"granularity" gorm:"column:granularity"`
}
func TableName() string {
return "kpi_c_report"
}

View File

@@ -1,43 +0,0 @@
package kpi_c_report
import (
"be.ems/src/framework/middleware"
"github.com/gin-gonic/gin"
)
// Register Routes for kpi_c_report
func Register(r *gin.RouterGroup) {
pmKPIC := r.Group("/kpiC")
{
var k *KpiCReport
pmKPIC.GET("/report",
middleware.AuthorizeUser(nil),
k.GetReport2FE,
)
pmKPIC.GET("/report/list",
middleware.AuthorizeUser(nil),
k.Get,
)
pmKPIC.GET("/report/totalList",
middleware.AuthorizeUser(nil),
k.Total,
)
pmKPIC.GET("/report/total",
middleware.AuthorizeUser(nil),
k.Total,
)
pmKPIC.POST("/report",
middleware.AuthorizeUser(nil),
k.Post,
)
pmKPIC.PUT("/report/:id",
middleware.AuthorizeUser(nil),
k.Put,
)
pmKPIC.DELETE("/report/:id",
middleware.AuthorizeUser(nil),
k.Delete,
)
}
}

View File

@@ -1,312 +0,0 @@
package kpi_c_title
import (
"fmt"
"net/http"
"regexp"
"sort"
"strconv"
"strings"
"time"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/database/db"
"be.ems/src/framework/reqctx"
"github.com/gin-gonic/gin"
)
// get customize kpi total and list
func (k *KpiCTitle) GetToalList(c *gin.Context) {
var titles []KpiCTitle
var conditions []string
var params []any
i18n := reqctx.AcceptLanguage(c)
var querys KpiCTitleQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
dbg := db.DB("").Model(&KpiCTitle{})
// construct condition to get
if neType := querys.NeType; neType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.ToUpper(neType))
}
if status := querys.Status; status != "" {
conditions = append(conditions, "status = ?")
params = append(params, status)
} else {
conditions = append(conditions, "status != '2'")
}
whereSql := ""
if len(conditions) > 0 {
whereSql += strings.Join(conditions, " and ")
dbg = dbg.Where(whereSql, params...)
}
// Get total number
var total int64 = 0
if err := dbg.Count(&total).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
// page number and size
if pageSize := querys.PageSize; pageSize > 0 {
dbg = dbg.Limit(pageSize)
if pageNum := querys.PageNum; pageNum > 0 {
dbg = dbg.Offset((pageNum - 1) * pageSize)
}
}
// order by
if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
dbg = dbg.Order(orderBy)
}
if err := dbg.Find(&titles).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
k.expressionAlias(titles, i18n)
c.JSON(http.StatusOK, services.TotalDataResp(titles, total))
//c.JSON(http.StatusOK, titles)
}
func (k *KpiCTitle) Get(c *gin.Context) {
var titles []KpiCTitle
var conditions []string
var params []any
i18n := reqctx.AcceptLanguage(c)
// construct condition to get
if neType := c.Query("neType"); neType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.ToUpper(neType))
}
if status := c.Query("status"); status != "" {
conditions = append(conditions, "status = ?")
params = append(params, status)
} else {
conditions = append(conditions, "status != '2'")
}
whereSql := ""
if len(conditions) > 0 {
whereSql += strings.Join(conditions, " and ")
}
if err := db.DB("").Where(whereSql, params...).Find(&titles).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
k.expressionAlias(titles, i18n)
c.JSON(http.StatusOK, services.DataResp(titles))
//c.JSON(http.StatusOK, titles)
}
// alias customized kpi expression with cn/en title
func (k *KpiCTitle) expressionAlias(titles []KpiCTitle, i18n string) {
var title *KpiCTitle
for i := 0; i < len(titles); i++ {
title = &titles[i]
title.ExprAlias = *title.Expression
re := regexp.MustCompile(`'([^']+)'`)
matches := re.FindAllStringSubmatch(title.ExprAlias, -1)
for _, match := range matches {
var alias, sql string
if i18n == "zh" {
sql = fmt.Sprintf("SELECT cn_title FROM kpi_title WHERE kpi_id='%s'", match[1])
} else {
sql = fmt.Sprintf("SELECT en_title FROM kpi_title WHERE kpi_id='%s'", match[1])
}
m, err := db.RawDB("", sql, nil)
if err != nil {
log.Warn("Failed to QueryRow:", err)
continue
}
if len(m) > 0 {
if i18n == "zh" {
alias = fmt.Sprintf("%v", m[0]["cn_title"])
} else {
alias = fmt.Sprintf("%v", m[0]["en_title"])
}
}
title.ExprAlias = regexp.MustCompile(match[1]).ReplaceAllString(title.ExprAlias, alias)
}
}
}
func (k *KpiCTitle) Total(c *gin.Context) {
var conditions []string
var params []any
// construct condition to get
if neType := c.Query("neType"); neType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.ToUpper(neType))
}
if status := c.Query("status"); status != "" {
conditions = append(conditions, "status = ?")
params = append(params, status)
} else {
conditions = append(conditions, "status != '2'")
}
whereSql := ""
if len(conditions) > 0 {
whereSql += strings.Join(conditions, " and ")
}
var total int64 = 0
if err := db.DB("").Table(k.TableName()).Where(whereSql, params...).Count(&total).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusOK, services.TotalResp(total))
}
func (k *KpiCTitle) Post(c *gin.Context) {
var title KpiCTitle
if err := c.ShouldBindJSON(&title); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
userName := reqctx.LoginUserToUserName(c)
title.CreatedBy = &userName
tx := db.DB("").Model(&KpiCTitle{})
result := tx.Where("ne_type=? and (kpi_id=? or title=?) and status!='2'", title.NeType, title.KpiID, title.Title).First(&title)
if result.RowsAffected > 0 {
c.JSON(http.StatusOK, services.ErrResp("custom indicator already exist"))
return
}
// Regexp match like AMF.C.01
// kpiIDRegexp := "^" + *title.NeType + "\\.C\\.[0-9]{2}$"
// ret := db.DB("").Table("kpi_c_title").
// Where("ne_type=? and kpi_id REGEXP ? ORDER BY kpi_id DESC LIMIT 1", title.NeType, kpiIDRegexp).Scan(&res)
// if err := ret.Error; err != nil {
// c.JSON(http.StatusOK, services.ErrResp(err.Error()))
// return
// }
titles := []KpiCTitle{}
ret := db.DB("").Model(&KpiCTitle{})
ret = ret.Select("kpi_id").Where("ne_type=?", title.NeType).Find(&titles)
newKpiID := *title.NeType + ".C" + ".01"
if ret.RowsAffected != 0 {
suffixInt := 1
prefixStr := fmt.Sprintf("%s.C.", *title.NeType)
sort.SliceStable(titles, func(i, j int) bool {
vi := *titles[i].KpiID
vj := *titles[j].KpiID
if strings.HasPrefix(vi, prefixStr) && strings.HasPrefix(vj, prefixStr) {
vvi := strings.Replace(vi, prefixStr, "", 1)
vvii, err := strconv.Atoi(vvi)
if err != nil {
return false
}
vvj := strings.Replace(vj, prefixStr, "", 1)
vvjj, err := strconv.Atoi(vvj)
if err != nil {
return false
}
return vvii > vvjj // desc
}
return false
})
maxKpiID := *titles[0].KpiID
prefix := maxKpiID[:len(maxKpiID)-2]
suffix := maxKpiID[len(maxKpiID)-2:]
suffixInt, err := strconv.Atoi(suffix)
if err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
if suffixInt >= MAX_KPI_C_ID {
err := fmt.Errorf("exceed the max customized KPI ID")
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
suffixInt++
newSuffix := fmt.Sprintf("%02d", suffixInt)
newKpiID = prefix + newSuffix
}
title.KpiID = &newKpiID
txx := db.DB("").Model(&KpiCTitle{})
if err := txx.Create(&title).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
kpiCReportTable := "kpi_c_report_" + strings.ToLower(*title.NeType)
if !db.DB("").Migrator().HasTable(kpiCReportTable) {
// clone table "kpi_c_report" to "kpi_c_report_{neType}"
sql := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s AS SELECT * FROM %s WHERE 1=0", kpiCReportTable, "kpi_c_report")
if _, err := db.ExecDB("", sql, nil); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
sql = fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,ADD PRIMARY KEY IF NOT EXISTS (`id`)", kpiCReportTable)
if _, err := db.ExecDB("", sql, nil); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
sql = fmt.Sprintf("ALTER TABLE %s ADD INDEX IF NOT EXISTS `idx_timestamp`(`created_at`) USING BTREE, ADD INDEX IF NOT EXISTS `idx_uid_datetime`(`rm_uid`, `date`, `start_time`) USING BTREE", kpiCReportTable)
if _, err := db.ExecDB("", sql, nil); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
}
c.JSON(http.StatusCreated, services.DataResp(title))
}
func (k *KpiCTitle) Put(c *gin.Context) {
var title KpiCTitle
id := c.Param("id")
if err := db.DB("").First(&title, id).Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp("custom indicator not found"))
return
}
if err := c.ShouldBindJSON(&title); err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
title.UpdatedAt = time.Now().UnixMilli()
db.DB("").Save(&title)
c.JSON(http.StatusOK, services.DataResp(title))
}
func (k *KpiCTitle) Delete(c *gin.Context) {
id := c.Param("id")
if err := db.DB("").Table(k.TableName()).Where("id=?", id).Update("status", "2").Error; err != nil {
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusNoContent, nil) // 204 No Content
}
func GetActiveKPICList(neType string) []KpiCTitle {
k := new([]KpiCTitle)
err := db.DB("").Where("`ne_type` = ? and `status` = '1'", neType).Find(&k).Error
if err != nil {
return nil
}
return *k
}

View File

@@ -1,33 +0,0 @@
package kpi_c_title
const (
MAX_KPI_C_ID = 99
)
type KpiCTitle struct {
ID int `gorm:"column:id;primary_key;auto_increment" json:"id"`
NeType *string `gorm:"column:ne_type" json:"neType,omitempty"`
KpiID *string `gorm:"column:kpi_id" json:"kpiId,omitempty"`
Title *string `gorm:"column:title" json:"title,omitempty"`
Expression *string `gorm:"column:expression" json:"expression,omitempty"`
ExprAlias string `gorm:"-" json:"exprAlias"`
Status string `gorm:"column:status" json:"status"` // 0-Inactive/1-Active/2-Deleted
Unit *string `gorm:"column:unit" json:"unit,omitempty"`
Description *string `gorm:"column:description" json:"description,omitempty"`
CreatedBy *string `gorm:"column:created_by" json:"createdBy,omitempty"`
UpdatedAt int64 `gorm:"column:updated_at" json:"updatedAt,omitempty"`
}
type KpiCTitleQuery struct {
ID int `json:"id" form:"id"`
NeType string `json:"neType" form:"neType"`
Status string `json:"status" form:"status"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=created_at"` // 排序字段,填写结果字段
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序asc desc
PageNum int `json:"pageNum" form:"pageNum"`
PageSize int `json:"pageSize" form:"pageSize"`
}
func (k *KpiCTitle) TableName() string {
return "kpi_c_title"
}

View File

@@ -1,39 +0,0 @@
package kpi_c_title
import (
"be.ems/src/framework/middleware"
"github.com/gin-gonic/gin"
)
// Register Routes for kpi_c_title
func Register(r *gin.RouterGroup) {
pmKPIC := r.Group("/kpiC")
{
var k *KpiCTitle
pmKPIC.GET("/title",
middleware.AuthorizeUser(nil),
k.Get,
)
pmKPIC.GET("/title/total",
middleware.AuthorizeUser(nil),
k.Total,
)
pmKPIC.GET("/title/totalList",
middleware.AuthorizeUser(nil),
k.GetToalList,
)
pmKPIC.POST("/title",
middleware.AuthorizeUser(nil),
k.Post,
)
pmKPIC.PUT("/title/:id",
middleware.AuthorizeUser(nil),
k.Put,
)
pmKPIC.DELETE("/title/:id",
middleware.AuthorizeUser(nil),
k.Delete,
)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +0,0 @@
package pm
import (
"be.ems/features/pm/kpi_c_report"
"be.ems/features/pm/kpi_c_title"
"be.ems/lib/log"
"github.com/gin-gonic/gin"
)
func InitSubServiceRoute(r *gin.Engine) {
log.Info("======init PM group gin.Engine")
pmGroup := r.Group("/pm")
// register sub modules routes
kpi_c_title.Register(pmGroup)
kpi_c_report.Register(pmGroup)
// return featuresGroup
}

View File

@@ -1,176 +0,0 @@
package security
import (
"encoding/json"
"io"
"net/http"
"strings"
"be.ems/lib/config"
"be.ems/lib/dborm"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/oauth"
"be.ems/lib/services"
)
var (
UriOauthToken = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
UriOauthHandshake = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
CustomUriOauthToken = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
CustomUriOauthHandshake = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
)
func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
log.Info("LoginFromOMC processing... ")
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Error("Failed to ReadAll:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
// check media type(content type) only support "application/json"
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
log.Debug("Invalid Content-Type")
services.ResponseUnsupportedMediaType415(w)
return
}
// // check extend uri, response 404
// if !IsValidOAuthUri(r) {
// log.Debug("Uri is invalid")
// services.ResponseNotFound404UriNotExist(w, r)
// return
// }
// Error process ....
// response 400-7
if !json.Valid([]byte(body)) {
log.Error("Invalid Json Format")
services.ResponseBadRequest400InvalidJson(w)
return
}
var oAuthBody oauth.OAuthBody
_ = json.Unmarshal(body, &oAuthBody) //转为json
//log.Debug("body:", string(body), "oAuthBody:", oAuthBody)
defer r.Body.Close()
// response 400-5
if oauth.IsWrongOAuthInfo(oAuthBody) {
log.Error("Wrong parameter value")
services.ResponseBadRequest400WrongParamValue(w)
return
}
/*
if oauth.IsValidOAuthInfo(oAuthBody) {
plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType)
log.Debug("Permission list:", plist)
token := globalSession.NewSession(w, r, plist)
services.ResponseStatusOK200Login(w, token)
} else {
// response 400-4
log.Debug("Authentication failed, mismatch user or password")
services.ResponseBadRequest400IncorrectLogin(w)
}
*/
token := oauth.GenRandToken("omc") // Generate new token to session ID
sourceAddr := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
affected, err := dborm.XormInsertSession(oAuthBody.UserName, sourceAddr, token,
config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
if err != nil {
log.Error("Failed to XormInsertSession:", err)
if affected == -1 {
services.ResponseForbidden403MultiLoginNotAllowed(w)
} else {
services.ResponseBadRequest400IncorrectLogin(w)
}
return
}
services.ResponseBadRequest400IncorrectLogin(w)
}
func LogoutFromOMC(w http.ResponseWriter, r *http.Request) {
log.Info("LogoutFromOMC processing... ")
// token, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
// // check media type(content type) only support "application/json"
// if services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) == false {
// log.Error("Invalid Content-Type")
// services.ResponseUnsupportedMediaType415(w)
// return
// }
// // check extend uri, response 404
// if !services.IsValidOAuthUri(r) {
// log.Error("Uri is invalid")
// services.ResponseNotFound404UriNotExist(w, r)
// return
// }
// // error processing ...
// // 401-1 response
// token, ret := oauth.IsCarriedToken(r)
// if ret == false {
// log.Error("AccessToken is not carried")
// services.ResponseUnauthorized401AccessTokenNotCarried(w)
// return
// }
// se, err := dborm.XormLogoutUpdateSession(token)
// if err != nil {
// log.Error("Uri is invalid")
// services.ResponseNotFound404UriNotExist(w, r)
// return
// }
// 清除缓存用户信息
// account.ClearLoginUser(se.AccountId)
services.ResponseStatusOK200Null(w)
}
func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) {
log.Info("HandshakeFromOMC processing... ")
// check media type(content type) only support "application/json"
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
log.Debug("Invalid Content-Type")
services.ResponseUnsupportedMediaType415(w)
return
}
// check extend uri, response 404
if !services.IsValidOAuthUri(r) {
log.Error("Uri is invalid")
services.ResponseNotFound404UriNotExist(w, r)
return
}
// error processing ...
// 401-1 response
token, ret := oauth.IsCarriedToken(r)
if !ret {
log.Error("AccessToken is not carried")
services.ResponseUnauthorized401AccessTokenNotCarried(w)
return
}
_, err := dborm.XormUpdateSessionShakeTime(token)
if err != nil {
log.Error("Uri is invalid")
services.ResponseNotFound404UriNotExist(w, r)
return
}
services.ResponseStatusOK200Null(w)
}

View File

@@ -1,45 +0,0 @@
package sm
import (
"net/http"
"time"
"be.ems/lib/config"
"be.ems/lib/log"
"be.ems/lib/services"
_ "github.com/go-sql-driver/mysql"
)
var (
// Get OMC local time
UriOMCLocalTime = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/OMC/objectType/time"
CustomUriOMCLocalTime = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/OMC/objectType/time"
)
type OMCLocalTime struct {
Timestamp int64 `json:"timestamp"` // 时间戳 (单位:毫秒)
TimeZone int `json:"timeZone"` // 本地时区偏移(单位:秒)
}
func GetOMCLocalTime(w http.ResponseWriter, r *http.Request) {
log.Debug("GetOMCLocalTime processing... ")
// _, err := services.CheckFrontValidRequest(w, r)
// if err != nil {
// log.Error("Http request error:", err)
// return
// }
t := time.Now()
_, offset := t.Zone()
localTime := OMCLocalTime{
Timestamp: t.UnixMilli(),
TimeZone: offset,
}
response := services.DataResponse{
Data: localTime,
}
services.ResponseWithJson(w, http.StatusOK, response)
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,243 +0,0 @@
//go:build linux
// +build linux
package state
import (
"encoding/binary"
"fmt"
"os"
"runtime"
"syscall"
"time"
"be.ems/lib/log"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/disk"
"github.com/shirou/gopsutil/v4/mem"
"github.com/shirou/gopsutil/v4/process"
)
type SysInfo struct {
SysCpuPercent uint16 // x%
MyCpuPercent uint16 // x%, CPU percent of current proccess
SysTotalRam uint32 // KB
MyUsedRam uint32 // RAM usage of current proccess, KB
SysRamUsedPercent uint16 // x%
PartitionNum byte
PartitionInfo []PartitionInfo // usage of each partition
}
const MAX_PARTITION_NUM byte = 32
func GetSysStat() ([]byte, int) {
// Get sys info
var sysInfo SysInfo
err := GetSysInfo(&sysInfo)
if err != nil {
return nil, 0
}
//log.Tracef("current sys info: %v", sysInfo)
// build ems buffer
var data []byte = make([]byte, 1024)
var len int
var i byte
binary.BigEndian.PutUint16(data[0:], sysInfo.MyCpuPercent) //x% * 100
binary.BigEndian.PutUint16(data[2:], sysInfo.SysCpuPercent) //x% * 100
binary.BigEndian.PutUint32(data[4:], sysInfo.SysTotalRam) // KB
binary.BigEndian.PutUint32(data[8:], sysInfo.MyUsedRam) // KB
binary.BigEndian.PutUint16(data[12:], sysInfo.SysRamUsedPercent) //x% * 100
data[14] = sysInfo.PartitionNum
for i = 0; i < sysInfo.PartitionNum; i++ {
binary.BigEndian.PutUint32(data[15+8*(i):], sysInfo.PartitionInfo[i].Total) // MB
binary.BigEndian.PutUint32(data[15+8*(i)+4:], sysInfo.PartitionInfo[i].Used) // MB
}
len = int(15 + 8*sysInfo.PartitionNum)
//log.Tracef("current sys stat buf: %v, len: %d", data, len)
return data, len
}
var pProc *process.Process = nil
func GetSYsCpuPercent() float64 {
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
if err != nil {
return 0.0
} else {
return totalPercent[0]
}
}
func GetSysInfo(sysInfo *SysInfo) error {
// sys cpu percent
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
if err != nil {
sysInfo.SysCpuPercent = 0
} else {
sysInfo.SysCpuPercent = uint16(totalPercent[0] * 100)
}
if pProc == nil {
checkPid := os.Getpid()
pProc, err = process.NewProcess(int32(checkPid))
if err != nil {
log.Tracef("get process info error %v", err)
return err
}
}
// self cpu percent
percent, err := pProc.Percent(0) //(2*time.Second)
if err != nil {
log.Tracef("get process cpu percent error %v", err)
sysInfo.MyCpuPercent = 0
} else {
sysInfo.MyCpuPercent = uint16(percent * 100)
}
// self RAM(KB)
myRam, err := pProc.MemoryInfo()
if err != nil {
log.Tracef("get self memory info error %v", err)
sysInfo.MyUsedRam = 0
} else {
sysInfo.MyUsedRam = uint32(myRam.RSS / 1024)
}
// system RAM(KB)
sysRam, err := mem.VirtualMemory()
if err != nil {
log.Tracef("gett sys memory info error %v", err)
sysInfo.SysTotalRam = 0
sysInfo.SysRamUsedPercent = 0
} else {
sysInfo.SysTotalRam = uint32(sysRam.Total / 1024)
sysInfo.SysRamUsedPercent = uint16(sysRam.UsedPercent * 100)
}
// partition usage
GetPartitions(sysInfo)
return nil
}
func getProcess() *process.Process {
checkPid := os.Getpid()
ret, _ := process.NewProcess(int32(checkPid))
return ret
}
func GetSystemCpuInfo() {
physicalCnt, _ := cpu.Counts(false)
logicalCnt, _ := cpu.Counts(true)
log.Tracef("physical count:%d logical count:%d", physicalCnt, logicalCnt)
totalPercent, _ := cpu.Percent(3*time.Second, false) // per cpu is false
perPercents, _ := cpu.Percent(3*time.Second, true) // per cpu is true
log.Tracef("total percent:%v per percents:%v", totalPercent, perPercents)
}
func GetProcessCpuPercent() {
p := getProcess()
percent, err := p.Percent(0)
if err != nil {
log.Tracef("error %v", err)
}
numcpu := runtime.NumCPU()
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
if percent < 0.0 {
log.Tracef("Err CPU Percent of Process: %f, CPU num: %d", percent, numcpu)
} else {
log.Tracef("get process CPU percent: %f, CPU num: %d", percent, numcpu)
}
}
func GetProcessMemoryInfo() {
p := getProcess()
v, err := p.MemoryInfo()
if err != nil {
log.Tracef("getting memory info error %v", err)
}
log.Tracef("get process memory info %v", v)
info, _ := mem.VirtualMemory()
fmt.Println(info)
}
func GetPartitions(sysInfo *SysInfo) {
sysInfo.PartitionNum = 0
//sysInfo.PartitionInfo = make([]PartitionInfo, MAX_PARTITION_NUM, MAX_PARTITION_NUM)
infos, _ := disk.Partitions(true)
for _, info := range infos {
GetOnePartitionUsage(info.Mountpoint, sysInfo)
if sysInfo.PartitionNum >= MAX_PARTITION_NUM {
break
}
}
}
func GetOnePartitionUsage(path string, sysInfo *SysInfo) int {
info, err := disk.Usage(path)
if err != nil {
return -1
}
if info.Total <= 0 { // info.Used/(1024 * 1024)MB
return 0
}
var partition PartitionInfo
partition.Total = uint32(info.Total / 1024 / 1024)
partition.Used = uint32(info.Used / 1024 / 1024)
sysInfo.PartitionInfo = append(sysInfo.PartitionInfo, partition)
sysInfo.PartitionNum++
/*data, err := json.MarshalIndent(info, "", " ")
if err != nil {
return -1
}
fmt.Println(string(data))*/
return 1
}
func getOS() string {
var osname string
if runtime.GOOS == "linux" {
osname = "GNU/Linux"
}
return osname
}
func utsnameToString(unameArray [65]int8) string {
var byteString [65]byte
var indexLength int
for ; unameArray[indexLength] != 0 && indexLength < 65; indexLength++ {
byteString[indexLength] = uint8(unameArray[indexLength])
}
return string(byteString[:indexLength])
}
func getUnameStr() string {
var utsname = syscall.Utsname{}
err := syscall.Uname(&utsname)
if err == nil {
name := utsnameToString(utsname.Sysname)
node := utsnameToString(utsname.Nodename)
release := utsnameToString(utsname.Release)
version := utsnameToString(utsname.Version)
machine := utsnameToString(utsname.Machine)
//domain:= utsnameToString(utsname.Domainname)
osName := getOS()
return fmt.Sprintf("%s %s %s %s %s %s", name, node,
release, version, machine, osName)
}
return ""
}

View File

@@ -1,231 +0,0 @@
//go:build windows
// +build windows
package state
import (
"encoding/binary"
"fmt"
"os"
"runtime"
"syscall"
"time"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/disk"
"github.com/shirou/gopsutil/v4/mem"
"github.com/shirou/gopsutil/v4/process"
)
type SysInfo struct {
SysCpuPercent uint16 // x%
MyCpuPercent uint16 // x%, CPU percent of current proccess
SysTotalRam uint32 // KB
MyUsedRam uint32 // RAM usage of current proccess, KB
SysRamUsedPercent uint16 // x%
PartitionNum byte
PartitionInfo []PartitionInfo // usage of each partition
}
const MAX_PARTITION_NUM byte = 32
func GetSysStat() ([]byte, int) {
// Get sys info
var sysInfo SysInfo
err := GetSysInfo(&sysInfo)
if err != nil {
return nil, 0
}
//fmt.Printf("current sys info: %v", sysInfo)
// build ems buffer
var data []byte = make([]byte, 1024)
var len int
var i byte
binary.BigEndian.PutUint16(data[0:], sysInfo.MyCpuPercent) //x% * 100
binary.BigEndian.PutUint16(data[2:], sysInfo.SysCpuPercent) //x% * 100
binary.BigEndian.PutUint32(data[4:], sysInfo.SysTotalRam) // KB
binary.BigEndian.PutUint32(data[8:], sysInfo.MyUsedRam) // KB
binary.BigEndian.PutUint16(data[12:], sysInfo.SysRamUsedPercent) //x% * 100
data[14] = sysInfo.PartitionNum
for i = 0; i < sysInfo.PartitionNum; i++ {
binary.BigEndian.PutUint32(data[15+8*(i):], sysInfo.PartitionInfo[i].Total) // MB
binary.BigEndian.PutUint32(data[15+8*(i)+4:], sysInfo.PartitionInfo[i].Used) // MB
}
len = int(15 + 8*sysInfo.PartitionNum)
//fmt.Printf("current sys stat buf: %v, len: %d", data, len)
return data, len
}
var pProc *process.Process = nil
func GetSYsCpuPercent() float64 {
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
if err != nil {
return 0.0
} else {
return totalPercent[0]
}
}
func GetSysInfo(sysInfo *SysInfo) error {
// sys cpu percent
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
if err != nil {
sysInfo.SysCpuPercent = 0
} else {
sysInfo.SysCpuPercent = uint16(totalPercent[0] * 100)
}
if pProc == nil {
checkPid := os.Getpid()
pProc, err = process.NewProcess(int32(checkPid))
if err != nil {
fmt.Printf("get process info error %v", err)
return err
}
}
// self cpu percent
percent, err := pProc.Percent(0) //(2*time.Second)
if err != nil {
fmt.Printf("get process cpu percent error %v", err)
sysInfo.MyCpuPercent = 0
} else {
sysInfo.MyCpuPercent = uint16(percent * 100)
}
// self RAM(KB)
myRam, err := pProc.MemoryInfo()
if err != nil {
fmt.Printf("get self memory info error %v", err)
sysInfo.MyUsedRam = 0
} else {
sysInfo.MyUsedRam = uint32(myRam.RSS / 1024)
}
// system RAM(KB)
sysRam, err := mem.VirtualMemory()
if err != nil {
fmt.Printf("gett sys memory info error %v", err)
sysInfo.SysTotalRam = 0
sysInfo.SysRamUsedPercent = 0
} else {
sysInfo.SysTotalRam = uint32(sysRam.Total / 1024)
sysInfo.SysRamUsedPercent = uint16(sysRam.UsedPercent * 100)
}
// partition usage
GetPartitions(sysInfo)
return nil
}
func getProcess() *process.Process {
checkPid := os.Getpid()
ret, _ := process.NewProcess(int32(checkPid))
return ret
}
func GetSystemCpuInfo() {
physicalCnt, _ := cpu.Counts(false)
logicalCnt, _ := cpu.Counts(true)
fmt.Printf("physical count:%d logical count:%d\n", physicalCnt, logicalCnt)
totalPercent, _ := cpu.Percent(3*time.Second, false) // per cpu is false
perPercents, _ := cpu.Percent(3*time.Second, true) // per cpu is true
fmt.Printf("total percent:%v per percents:%v\n", totalPercent, perPercents)
}
func GetProcessCpuPercent() {
p := getProcess()
percent, err := p.Percent(0)
if err != nil {
fmt.Printf("error %v", err)
}
numcpu := runtime.NumCPU()
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
if percent < 0.0 {
fmt.Printf("Err CPU Percent of Process: %f, CPU num: %d", percent, numcpu)
} else {
fmt.Printf("get process CPU percent: %f, CPU num: %d", percent, numcpu)
}
}
func GetProcessMemoryInfo() {
p := getProcess()
v, err := p.MemoryInfo()
if err != nil {
fmt.Printf("getting memory info error %v", err)
}
fmt.Printf("get process memory info %v\n", v)
info, _ := mem.VirtualMemory()
fmt.Println(info)
}
func GetPartitions(sysInfo *SysInfo) {
sysInfo.PartitionNum = 0
//sysInfo.PartitionInfo = make([]PartitionInfo, MAX_PARTITION_NUM, MAX_PARTITION_NUM)
infos, _ := disk.Partitions(true)
for _, info := range infos {
GetOnePartitionUsage(info.Mountpoint, sysInfo)
if sysInfo.PartitionNum >= MAX_PARTITION_NUM {
break
}
}
}
func GetOnePartitionUsage(path string, sysInfo *SysInfo) int {
info, err := disk.Usage(path)
if err != nil {
return -1
}
if info.Total <= 0 { // info.Used/(1024 * 1024)MB
return 0
}
var partition PartitionInfo
partition.Total = uint32(info.Total / 1024 / 1024)
partition.Used = uint32(info.Used / 1024 / 1024)
sysInfo.PartitionInfo = append(sysInfo.PartitionInfo, partition)
sysInfo.PartitionNum++
/*data, err := json.MarshalIndent(info, "", " ")
if err != nil {
return -1
}
fmt.Println(string(data))*/
return 1
}
func getOS() string {
var osname string
if runtime.GOOS == "linux" {
osname = "GNU/Linux"
}
return osname
}
func utsnameToString(unameArray [65]int8) string {
var byteString [65]byte
var indexLength int
for ; unameArray[indexLength] != 0 && indexLength < 65; indexLength++ {
byteString[indexLength] = uint8(unameArray[indexLength])
}
return string(byteString[:indexLength])
}
func getUnameStr() string {
osInfo, _ := syscall.GetVersion()
return fmt.Sprintf("Widnows %d", osInfo)
}

View File

@@ -1,29 +0,0 @@
package state
import (
"be.ems/lib/log"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/mem"
)
func getCpuNumber() int {
// 获取CPU信息
cpuInfo, err := cpu.Info()
if err != nil {
log.Errorf("Failed to get CPU info: %v", err)
return 0
}
log.Tracef("CPU info: %+v", cpuInfo)
return len(cpuInfo)
}
func getTotalMemory() int {
// 获取内存信息
memInfo, err := mem.VirtualMemory()
if err != nil {
log.Errorf("Failed to get memory info: %v", err)
return 0
}
log.Tracef("Memory info: %+v", memInfo)
return int(memInfo.Total)
}

View File

@@ -1,833 +0,0 @@
package ue
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"be.ems/lib/config"
"be.ems/lib/core/ctx"
"be.ems/lib/dborm"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/constants"
neDataModel "be.ems/src/modules/network_data/model"
neDataService "be.ems/src/modules/network_data/service"
neService "be.ems/src/modules/network_element/service"
"github.com/go-resty/resty/v2"
"github.com/gorilla/mux"
)
// AmfNBInfo AMF的NodeB信息
type AmfNBInfo struct {
ID string `json:"id"` //NodeB ID
Name string `json:"name"` // NodeB name
Address string `json:"address"` // 基站地址
UENum int `jons:"ueNum"` // UE数量
}
// SmfUENum SMF在线用户数
type SmfUENum struct {
UENum int `json:"ueNum"` // 当前在线用户数
}
// SmfUEInfo SMF在线用户信息
type SmfUEInfo struct {
IMSI string `json:"imsi"`
MSISDN string `json:"msisdn"`
RatType string `json:"ratType"`
PduSessionInfo []struct {
PduSessionID int `json:"pduSessionID"`
IPv4 string `json:"ipv4"`
IPv6 string `json:"ipv6"`
Dnn string `json:"dnn"`
Tai string `json:"tai"`
SstSD string `json:"sstSD"`
UpfN3IP string `json:"upfN3IP"`
RanN3IP string `json:"ranN3IP"`
Activetime string `json:"activeTime"`
UpState string `json:"upState"`
} `json:"pduSessionInfo"`
}
// ImsUEInfo IMS在线用户信息
type ImsUEInfo struct {
IMSI string `json:"imsi"`
MSISDN string `json:"msisdn"`
IMPU string `json:"impu"`
Barring int `json:"barring"`
RegState int `json:"regState"`
Activetime string `json:"activeTime"`
}
// N3iwfUEInfo N3IWF在线用户信息
type N3iwfUEInfo struct {
IMSI string `json:"imsi"`
NAI string `json:"nai"`
RegState int `json:"regState"`
Activetime string `json:"activeTime"`
}
type N3iwfUEData struct {
Data []N3iwfUEInfo `json:"data"`
}
var (
UriNBState = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/nbState"
UriNBInfo = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/nbInfo"
UriUEInfo = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueInfo"
UriUENum = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueNum"
UriPCFUser = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo"
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"
CustomUriNBState = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/nbState"
CustomUriNBInfo = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/nbInfo"
CustomUriUEInfo = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueInfo"
CustomUriUENum = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueNum"
CustomUriPCFUser = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo"
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()
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(500 * time.Millisecond)
}
// 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{constants.HEADER_KEY: r.Header.Get(constants.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{constants.HEADER_KEY: r.Header.Get(constants.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.Debug("GetUEInfoFromNF processing... ")
neId := ctx.GetQuery(r, "neId")
neType := ctx.GetParam(r, "elementTypeValue")
if neType == "" || neId == "" {
log.Error("elementTypeValue/neId is empty")
services.ResponseNotFound404UriNotExist(w, r)
return
}
neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId)
var response services.MapResponse
if neInfo.NeId == neId && neInfo.NeId != "" {
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
log.Debug("requestURI2NF:", requestURI2NF)
resp, err := client.R().
EnableTrace().
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("Failed to Get from NF:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else {
_ = json.Unmarshal(resp.Body(), &response)
}
log.Debug("response:", response)
}
services.ResponseWithJson(w, http.StatusOK, response)
}
// POST User Info from NF/NFs
func PostPCFUserInfo(w http.ResponseWriter, r *http.Request) {
log.Info("PostPCFUserInfo processing... ")
// vars := mux.Vars(r)
// neType := vars["elementTypeValue"]
// if neType == "" {
// services.ResponseNotFound404UriNotExist(w, r)
// return
// }
//neTypeLower := strings.ToLower(neType)
neType := "PCF"
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)
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
client.SetTimeout(1 * time.Minute)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.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"}).
SetBody(body).
Post(requestURI2NF)
if err != nil {
log.Error("Failed to post:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else {
var response services.MapResponse
_ = json.Unmarshal(resp.Body(), &response)
services.ResponseWithJson(w, resp.StatusCode(), response)
return
}
}
// PUT PCF User Info from NF/NFs
func PutPCFUserInfo(w http.ResponseWriter, r *http.Request) {
log.Info("PutPCFUserInfo processing... ")
// vars := mux.Vars(r)
// neType := vars["elementTypeValue"]
// if neType == "" {
// services.ResponseNotFound404UriNotExist(w, r)
// return
// }
//neTypeLower := strings.ToLower(neType)
neType := "PCF"
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)
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
log.Error("io.ReadAll is failed:", err)
services.ResponseNotFound404UriNotExist(w, r)
return
}
client.SetTimeout(1 * time.Minute)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.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"}).
SetBody(body).
Put(requestURI2NF)
if err != nil {
log.Error("Failed to put:", 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 DeletePCFUserInfo(w http.ResponseWriter, r *http.Request) {
log.Info("DeletePCFUserInfo processing... ")
// vars := mux.Vars(r)
// neType := vars["elementTypeValue"]
// if neType == "" {
// services.ResponseNotFound404UriNotExist(w, r)
// return
// }
//neTypeLower := strings.ToLower(neType)
neType := "PCF"
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{constants.HEADER_KEY: r.Header.Get(constants.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"}).
Delete(requestURI2NF)
if err != nil {
log.Error("Failed to delete:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else {
w.WriteHeader(resp.StatusCode())
w.Write(resp.Body())
// var response services.MapResponse
// _ = json.Unmarshal(resp.Body(), &response)
// services.ResponseWithJson(w, resp.StatusCode(), response)
return
}
}
// Get UEInfo from SMF
func GetUENumFromNF(w http.ResponseWriter, r *http.Request) {
log.Info("GetUENumFromNF processing... ")
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
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{constants.HEADER_KEY: r.Header.Get(constants.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 Radio Info from NF/NFs
func GetNBInfoFromNF(w http.ResponseWriter, r *http.Request) {
log.Info("GetNBInfoFromNF processing... ")
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
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{constants.HEADER_KEY: r.Header.Get(constants.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
}
}
// PostNBInfoFromNF 接收Radio数据请求
func PostNBInfoFromNF(w http.ResponseWriter, r *http.Request) {
log.Info("PostNBInfoFromNF processing... ")
neType := ctx.GetParam(r, "elementTypeValue")
var body struct {
NeType string `json:"neType" `
NeName string `json:"neName" `
RmUID string `json:"rmUID"`
StateList []struct {
Address string `json:"address" `
Name string `json:"name" `
Position string `json:"position" `
NbName string `json:"nbName" `
State string `json:"state" ` // "OFF" or "ON"
OffTime string `json:"offTime" ` //if State=OFF, will set it
OnTime string `json:"onTime" ` //if State=ON , will set it
}
}
if err := ctx.ShouldBindJSON(r, &body); err != nil {
services.ResponseInternalServerError500ProcessError(w, err)
return
}
neTypeLower := strings.ToLower(body.NeType)
if neType == "" || neType != neTypeLower {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element types"))
return
}
neInfo := neService.NewNeInfo.FindByRmuid(body.RmUID)
if neInfo.RmUID != body.RmUID {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element rmUID"))
return
}
if len(body.StateList) == 0 {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("no stateList"))
return
}
nbStateService := neDataService.NewNBState
for _, v := range body.StateList {
if v.Address == "" || v.State == "" {
continue
}
timeStr := v.OffTime
if v.State == "ON" {
timeStr = v.OnTime
}
nbStateService.Insert(neDataModel.NBState{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
RmUid: neInfo.RmUID,
Address: v.Address,
Name: v.Name,
Position: v.Position,
NbName: v.NbName,
State: v.State,
Time: timeStr,
})
}
services.ResponseStatusOK204NoContent(w)
}
// Get Radio Info from NF/NFs
func GetNBInfoAllFromNF(w http.ResponseWriter, r *http.Request) {
log.Info("GetNBInfoAllFromNF processing... ")
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
if neType == "" {
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)
//var ret error
var statusCode int = 500
var dataResponse []services.MapResponse
var neInfos []dborm.NeInfo
dborm.XormGetNeInfo2(neType, neIDs, &neInfos)
for _, neInfo := range neInfos {
// 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
// }
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{constants.HEADER_KEY: r.Header.Get(constants.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("Failed to GET:", err)
continue
// services.ResponseInternalServerError500ProcessError(w, err)
// return
} else {
switch resp.StatusCode() {
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
var response services.MapResponse
_ = json.Unmarshal(resp.Body(), &response)
dataResponse = append(dataResponse, response)
statusCode = http.StatusOK
}
}
}
var response services.DataResponse
response.Data = dataResponse
services.ResponseWithJson(w, statusCode, response)
}
// Get GetUEInfoFileExportNF from NF/NFs
func GetUEInfoFileExportNF(w http.ResponseWriter, r *http.Request) {
log.Info("GetUEInfoFromNF processing... ")
// vars := mux.Vars(r)
// neType := vars["elementTypeValue"]
// if neType == "" {
// 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("PCF", 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)
client.SetTimeout(3 * time.Minute)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.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 {
w.WriteHeader(resp.StatusCode())
w.Write(resp.Body())
// var response services.MapResponse
// _ = json.Unmarshal(resp.Body(), &response)
// services.ResponseWithJson(w, resp.StatusCode(), response)
return
}
}

View File

@@ -1,64 +0,0 @@
package aes
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
)
func AesEncrypt(orig string, key string) string {
// 转成字节数组
origData := []byte(orig)
k := []byte(key)
// 分组秘钥
block, _ := aes.NewCipher(k)
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 补全码
origData = PKCS7Padding(origData, blockSize)
// 加密模式
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
// 创建数组
cryted := make([]byte, len(origData))
// 加密
blockMode.CryptBlocks(cryted, origData)
return base64.StdEncoding.EncodeToString(cryted)
}
func AesDecrypt(cryted string, key string) string {
// 转成字节数组
crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
k := []byte(key)
// 分组秘钥
block, _ := aes.NewCipher(k)
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 加密模式
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
// 创建数组
orig := make([]byte, len(crytedByte))
// 解密
blockMode.CryptBlocks(orig, crytedByte)
// 去补全码
orig = PKCS7UnPadding(orig)
return string(orig)
}
// 补码
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
padding := blocksize - len(ciphertext)%blocksize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// 去码
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}

View File

@@ -1,475 +0,0 @@
package config
import (
"bufio"
"fmt"
"os"
"reflect"
"strings"
"be.ems/lib/global"
"be.ems/lib/log"
"gopkg.in/yaml.v3"
)
// Yaml struct of config
type YamlConfig struct {
Logger struct {
File string `yaml:"file"`
Level string `yaml:"level"`
Duration int `yaml:"duration"`
Count int `yaml:"count"`
} `yaml:"logger"`
OMC struct {
UriPrefix string `yaml:"uriPrefix"`
NeType string `yaml:"neType"`
NeId string `yaml:"neId"`
RmUID string `yaml:"rmUID"`
NeName string `yaml:"neName"`
Province string `yaml:"province"`
Vendor string `yaml:"vendor"`
Dn string `yaml:"dn"`
Chk2Ne bool `yaml:"chk2ne"`
Capability uint32 `yaml:"capability"`
Sn string `yaml:"sn"`
ExpiryDate string `yaml:"expiryDate"`
CheckSign bool `yaml:"checksign"`
RootDir string `yaml:"rootDir"`
BinDir string `yaml:"binDir"`
Backup string `yaml:"backup"`
Upload string `yaml:"upload"`
FrontUpload string `yaml:"frontUpload"`
FrontTraceDir string `yaml:"frontTraceDir"`
Software string `yaml:"software"`
License string `yaml:"license"`
GtpUri string `yaml:"gtpUri"`
CheckContentType bool `yaml:"checkContentType"`
TestMode bool `yaml:"testMode"`
RBACMode bool `yaml:"rbacMode"`
RunDir string `yaml:"runDir"`
CmdTimeout int `yaml:"cmdTimeout"`
} `yaml:"omc"`
Alarm AlarmConfig `yaml:"alarm"`
MML MMLParam `yaml:"mml"`
NE struct {
Addr string `yaml:"addr"`
Port uint16 `yaml:"port"`
User string `yaml:"user"`
EtcDir string `yaml:"etcdir"`
BinDir string `yaml:"bindir"`
OmcDir string `yaml:"omcdir"`
ScpDir string `yaml:"scpdir"`
LicenseDir string `yaml:"licensedir"`
EtcListIMS string `yaml:"etcListIMS"`
EtcListDefault string `yaml:"etcListDefault"`
DpkgOverwrite bool `yaml:"dpkgOverwrite"`
DpkgTimeout int `yaml:"dpkgTimeout"`
} `yaml:"ne"`
Auth struct {
Crypt string `yaml:"crypt"`
Token bool `yaml:"token"`
Expires uint32 `yaml:"expires"`
Session string `yaml:"session"`
PublicKey string `yaml:"publicKey"`
PrivateKey string `yaml:"privateKey"`
} `yaml:"auth"`
Params struct {
RmUIDMaxNum int `yaml:"rmuidmaxnum"`
AlarmIDMaxNum int `yaml:"alarmidmaxnum"`
PmIDMaxNum int `yaml:"pmidmaxnum"`
SubIDMaxNum int `yaml:"subidmaxnum"`
UriMaxLen int `yaml:"urimaxlen"`
RmUIDRegexp string `yaml:"rmuidregexp"`
} `yaml:"params"`
TestConfig struct {
Enabled bool `yaml:"enabled"`
File string `yaml:"file"`
} `yaml:"testConfig"`
}
// type DbConfig struct {
// Type string `yaml:"type"`
// User string `yaml:"user"`
// Password string `yaml:"password"`
// Host string `yaml:"host"`
// Port string `yaml:"port"`
// Name string `yaml:"name"`
// ConnParam string `yaml:"connParam,omitempty"`
// Backup string `yaml:"backup"`
// }
type AlarmConfig struct {
SplitEventAlarm bool `yaml:"splitEventAlarm"`
//ForwardAlarm bool `yaml:"forwardAlarm"`
EmailForward struct {
Enable bool `yaml:"enable" json:"enable"`
EmailList string `yaml:"emailList" json:"emailList"`
Title string `yaml:"title" json:"title"`
SMTP string `yaml:"smtp" json:"smtp"`
Port uint16 `yaml:"port" json:"port"`
User string `yaml:"user" json:"user"`
Password string `yaml:"password" json:"password"`
TLSSkipVerify bool `yaml:"tlsSkipVerify" json:"tlsSkipVerify"`
} `yaml:"alarmEmailForward"`
SMSCForward struct {
Enable bool `yaml:"enable" json:"enable"`
MobileList string `yaml:"mobileList" json:"mobileList"`
SMSCAddr string `yaml:"smscAddr" json:"smscAddr"`
SystemID string `yaml:"systemID" json:"systemID"`
Password string `yaml:"password" json:"password"`
SystemType string `yaml:"systemType" json:"systemType"`
DataCoding byte `yaml:"dataCoding" json:"dataCoding"`
ServiceNumber string `yaml:"serviceNumber" json:"serviceNumber"`
} `yaml:"alarmSMSForward"`
SMS struct {
ApiURL string `yaml:"apiURL"`
AccessKeyID string `yaml:"AccessKeyID"`
AccessKeySecret string `yaml:"accessKeySecret"`
SignName string `yaml:"signName"`
TemplateCode string `yaml:"templateCode"`
} `yaml:"smsForward"`
SMProxy string `yaml:"smProxy"`
}
type MMLParam struct {
Sleep int64 `yaml:"sleep"`
DeadLine int64 `yaml:"deadLine"`
SizeRow int16 `yaml:"sizeRow"`
SizeCol int16 `yaml:"sizeCol"`
BufferSize int `yaml:"bufferSize"`
MmlHome string `yaml:"mmlHome"`
}
type TestDatas struct {
UDM struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"udm"`
AUSF struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"ausf"`
AMF struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"amf"`
SMF struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"smf"`
UPF struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"upf"`
}
type NeTestData struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
}
type TestDataMap struct {
NeTestDatas []map[string]NeTestData
}
var yamlConfig YamlConfig = NewYamlConfig()
type YamlConfigFile struct {
FilePath string `json:"filePath"`
ConfigLines YamlConfig `json:"configLines"`
OrignalLines []string `json:"orignalLines"`
}
var YamlConfigInfo YamlConfigFile = YamlConfigFile{
ConfigLines: NewYamlConfig(),
}
// set default value for yaml config
func NewYamlConfig() YamlConfig {
return YamlConfig{
// Database: DbConfig{
// Type: "mysql",
// ConnParam: "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True",
// },
MML: MMLParam{
SizeRow: 200,
SizeCol: 120,
BufferSize: 65535,
},
Alarm: AlarmConfig{
SplitEventAlarm: true,
},
}
}
func ReadConfig(configFile string) {
YamlConfigInfo.FilePath = configFile
yamlFile, err := os.ReadFile(configFile)
if err != nil {
fmt.Println("Read yaml config file error:", err)
os.Exit(2)
}
// fmt.Println("yamlfile:", string(yamlFile))
err = yaml.Unmarshal(yamlFile, &YamlConfigInfo.ConfigLines)
if err != nil {
fmt.Println("Unmarshal error:", err)
os.Exit(3)
}
yamlConfig = YamlConfigInfo.ConfigLines
ReadOriginalConfig(configFile)
}
func ReadOriginalConfig(configFile string) {
// 读取原始YAML文件
inputFile, err := os.Open(configFile)
if err != nil {
fmt.Println("failed to open:", err)
os.Exit(3)
}
defer inputFile.Close()
scanner := bufio.NewScanner(inputFile)
for scanner.Scan() {
YamlConfigInfo.OrignalLines = append(YamlConfigInfo.OrignalLines, scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Println("failed to scanner:", err)
os.Exit(3)
}
}
func WriteOrignalConfig(configFile string, paramName string, paramData map[string]any) error {
lines := YamlConfigInfo.OrignalLines
for i, line := range lines {
if strings.Contains(line, paramName) {
for k, v := range paramData {
// find the first line nearby the paramName
for j := i + 1; j < len(lines); j++ {
if strings.Contains(lines[j], k+":") {
index := strings.Index(lines[j], k)
// Determine the type of v
switch v := v.(type) {
case string:
lines[j] = lines[j][:index] + fmt.Sprintf("%s: \"%s\"", k, v)
// case int:
// lines[j] = lines[j][:index] + fmt.Sprintf("%s: %d", k, v)
// case float64:
// lines[j] = lines[j][:index] + fmt.Sprintf("%s: %f", k, v)
case bool:
lines[j] = lines[j][:index] + fmt.Sprintf("%s: %t", k, v)
default:
lines[j] = lines[j][:index] + fmt.Sprintf("%s: %v", k, v)
}
break
}
}
}
break
}
}
// write back to yaml file
outputFile, err := os.Create(configFile)
if err != nil {
fmt.Println(err)
return err
}
defer outputFile.Close()
writer := bufio.NewWriter(outputFile)
for _, line := range YamlConfigInfo.OrignalLines {
writer.WriteString(line + "\n")
}
writer.Flush()
return nil
}
func WriteYamlConfig(newConfigData YamlConfig, configFile string) error {
// 将配置转换回YAML数据
newYamlData, err := yaml.Marshal(&newConfigData)
if err != nil {
log.Errorf("Failed to marshal YAML: %v", err)
return err
}
// 将新的YAML数据写入文件
err = os.WriteFile(configFile, newYamlData, 0644)
if err != nil {
log.Errorf("Failed to write YAML file: %v", err)
return err
}
return nil
}
var mapYaml map[string]interface{}
func ReadParamConfig(fileName string) *map[string]interface{} {
file, err := os.ReadFile(fileName)
if err != nil {
fmt.Println("Read yaml file error:", err)
}
mapYaml = make(map[string]interface{})
err = yaml.Unmarshal(file, &mapYaml)
if err != nil {
fmt.Printf("yaml.Unmarshal: %v when to struct", err)
}
// fmt.Println("mapYaml:", mapYaml)
return &mapYaml
}
func UpdateStructFromMap(s any, updates map[string]any) {
v := reflect.ValueOf(s).Elem()
t := v.Type()
for key, value := range updates {
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.Tag.Get("json") == key {
structField := v.FieldByName(field.Name)
if structField.IsValid() && structField.CanSet() {
// Convert value to the appropriate type if necessary
convertedValue := reflect.ValueOf(value).Convert(structField.Type())
if structField.Type() == convertedValue.Type() {
structField.Set(convertedValue)
}
}
break
}
}
}
}
func GetYamlConfig() *YamlConfig {
return &YamlConfigInfo.ConfigLines
}
func GetAuthFromConfig() interface{} {
return yamlConfig.Auth
}
func GetExpiresFromConfig() uint32 {
return yamlConfig.Auth.Expires
}
func GetRmUIDFromConfig() string {
return yamlConfig.OMC.RmUID
}
func GetRmUIDRegexpFromConfig() string {
return yamlConfig.Params.RmUIDRegexp
}
func GetRmUIDMaxNumFromConfig() int {
return yamlConfig.Params.RmUIDMaxNum
}
func GetAlarmIDMaxNumFromConfig() int {
return yamlConfig.Params.AlarmIDMaxNum
}
func GetPmIDMaxNumFromConfig() int {
return yamlConfig.Params.PmIDMaxNum
}
func GetSubIDMaxNumFromConfig() int {
return yamlConfig.Params.SubIDMaxNum
}
func GetUriMaxLenFromConfig() int {
return yamlConfig.Params.UriMaxLen
}
func GetLogLevel() log.LogLevel {
var logLevel log.LogLevel
switch strings.ToLower(yamlConfig.Logger.Level) {
case "trace":
logLevel = log.LOG_TRACE
case "info":
logLevel = log.LOG_INFO
case "debug":
logLevel = log.LOG_DEBUG
case "warn":
logLevel = log.LOG_WARN
case "error":
logLevel = log.LOG_ERROR
case "fatal":
logLevel = log.LOG_FATAL
case "off":
logLevel = log.LOG_OFF
default:
logLevel = log.LOG_DEBUG
}
return logLevel
}
var (
DefaultUriPrefix string = "/api/rest"
UriPrefix string = "/omc/rest"
//TestDataUDM []map[string]interface{}
TDatas map[string]NeTestData
)
func ReadTestConfigYaml(pfile string) (ret error) {
file, err := os.ReadFile(pfile)
if err != nil {
return err
}
err = yaml.Unmarshal(file, &TDatas)
if err != nil {
fmt.Println("Failed to Unmarshal:", err)
return err
}
return nil
}
func GetDefaultUserAgent() string {
return "OMC/" + global.Version
}
// const defaultConfigFile = "./etc/restconf.yaml"
// func init() {
// cfile := flag.String("c", defaultConfigFile, "config file")
// pv := flag.Bool("version", false, "print version")
// ph := flag.Bool("help", false, "print help")
// //global.BuildTime = "Wed May 31 18:24:04 CST 2023"
// //global.GoVer = "go version go1.15.7 linux/arm64"
// flag.Parse()
// if *pv {
// fmt.Printf("OMC restagent version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
// os.Exit(0)
// }
// if *ph {
// flag.Usage()
// os.Exit(0)
// }
// // 使用viper读取配置
// conf.InitConfig(*cfile)
// ReadConfig(*cfile)
// if GetYamlConfig().OMC.UriPrefix != "" {
// UriPrefix = GetYamlConfig().OMC.UriPrefix
// }
// if GetYamlConfig().TestConfig.Enabled {
// ReadTestConfigYaml(GetYamlConfig().TestConfig.File)
// }
// }

View File

@@ -1,111 +0,0 @@
package config
import (
"io/ioutil"
"log"
"gopkg.in/yaml.v3"
"be.ems/lib/global"
)
type Uri2Object struct {
Uri string `yaml:"uri"`
Object []Object `yaml:"object"`
}
type Object struct {
Name string `yaml:"name"`
Syntax string `yaml:"syntax"`
Oid string `yaml:"oid"`
}
var uri2Object []Uri2Object
func ReadMap(pfile string) (ret error) {
file, err := ioutil.ReadFile(pfile)
if err != nil {
log.Println(err)
return err
}
err = yaml.Unmarshal(file, &uri2Object)
if err != nil {
log.Println(err)
return err
}
/*
for _, v := range uri2Object {
log.Println(v)
}
*/
return nil
}
func GetOid(uri string, oids *[]string) *[]string {
for _, v := range uri2Object {
if uri == v.Uri {
for _, o := range v.Object {
*oids = append(*oids, o.Oid)
}
}
}
return oids
}
func GetOidByFileds(uri string, fields []string, oids *[]string) *[]string {
for _, v := range uri2Object {
if uri == v.Uri {
for _, o := range v.Object {
if global.IsContain(o.Name, fields) || len(fields) == 0 {
*oids = append(*oids, o.Oid)
}
}
}
}
return oids
}
type NameOid struct {
Name string
Oid string
}
type NameValue struct {
Name string
Value string
}
func GetDataOid(Uri string, nameOids *[]NameOid) *[]NameOid {
var nameOid NameOid
for _, v := range uri2Object {
if Uri == v.Uri {
for _, o := range v.Object {
nameOid.Name = o.Name
nameOid.Oid = o.Oid
*nameOids = append(*nameOids, nameOid)
}
}
}
return nameOids
}
func GetDataOidByFields(uri string, fields []string, nameOids *[]NameOid) *[]NameOid {
var nameOid NameOid
for _, v := range uri2Object {
if uri == v.Uri {
for _, o := range v.Object {
nameOid.Name = o.Name
nameOid.Oid = o.Oid
if len(fields) == 0 || global.IsContainP(nameOid.Name, &fields, len(fields)) {
*nameOids = append(*nameOids, nameOid)
}
}
}
}
return nameOids
}

View File

@@ -1,185 +0,0 @@
package ctx
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"be.ems/src/framework/constants"
"be.ems/src/framework/token"
"github.com/gorilla/mux"
)
// GetParam 地址栏参数{id}
func GetParam(r *http.Request, key string) string {
vars := mux.Vars(r)
v, ok := vars[key]
if ok {
return v
}
return ""
}
// GetQuery 查询参数
func GetQuery(r *http.Request, key string) string {
return r.URL.Query().Get(key)
}
// GetHeader 请求头参数
func GetHeader(r *http.Request, key string) string {
return r.Header.Get(key)
}
// QueryMap 查询参数转换Map
func QueryMap(r *http.Request) map[string]any {
queryValues := r.URL.Query()
queryParams := make(map[string]any)
for key, values := range queryValues {
queryParams[key] = values[0]
}
return queryParams
}
// ShouldBindQuery 查询参数读取json请求结构团体 &xxx
func ShouldBindQuery(r *http.Request, args any) error {
queryParams := QueryMap(r)
body, err := json.Marshal(queryParams)
if err != nil {
return err
}
return json.Unmarshal(body, args)
}
// ShouldBindJSON 读取json请求结构团体 &xxx
func ShouldBindJSON(r *http.Request, args any) error {
body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) // 设置较大的长度,例如 1<<20 (1MB)
if err != nil {
return err
}
err = json.Unmarshal(body, args)
return err
}
// JSON 相应json数据
func JSON(w http.ResponseWriter, code int, data any) {
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
response, err := json.Marshal(data)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
} else {
w.WriteHeader(code)
w.Write(response)
}
}
// 将文件导出到外部下载
func FileAttachment(w http.ResponseWriter, r *http.Request, filepath, filename string) {
w.Header().Set("Content-Disposition", `attachment; filename=`+url.QueryEscape(filename))
w.Header().Set("Content-Type", "application/octet-stream")
http.ServeFile(w, r, filepath)
}
// 将文件上传保存到指定目录
// file, handler, err := r.FormFile("file")
// SaveUploadedFile uploads the form file to specific dst.
func SaveUploadedFile(r *http.Request, dst string) error {
// 解析请求中的文件
_, handler, err := r.FormFile("file")
if err != nil {
return err
}
src, err := handler.Open()
if err != nil {
return err
}
defer src.Close()
if err = os.MkdirAll(filepath.Dir(dst), 0750); err != nil {
return err
}
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, src)
return err
}
/// ==== 登录用户信息, 通过中间件后预置入
// Authorization 解析请求头
func Authorization(r *http.Request) string {
// Query请求查询
if authQuery := r.URL.Query().Get(constants.ACCESS_TOKEN); authQuery != "" {
return authQuery
}
// Header请求头
if authHeader := r.Header.Get(constants.ACCESS_TOKEN); authHeader != "" {
return authHeader
}
// Query请求查询
if authQuery := r.URL.Query().Get(constants.ACCESS_TOKEN_QUERY); authQuery != "" {
return authQuery
}
// Header请求头
authHeader := r.Header.Get(constants.HEADER_KEY)
if authHeader == "" {
return ""
}
// 拆分 Authorization 请求头,提取 JWT 令牌部分
tokenStr := strings.Replace(authHeader, constants.HEADER_PREFIX, "", 1)
if len(tokenStr) > 64 {
return strings.TrimSpace(tokenStr) // 去除可能存在的空格
}
return ""
}
// ContextKey 定义自定义类型作为键
type ContextKey string
// LoginUser 登录用户信息需要Authorize中间件
func LoginUser(r *http.Request) (token.UserInfo, error) {
// 获取请求头标识信息
tokenStr := Authorization(r)
if tokenStr == "" {
return token.UserInfo{}, fmt.Errorf("not token info")
}
if tokenStr == "" {
return token.UserInfo{}, fmt.Errorf("authorization token is empty")
}
// 验证令牌
claims, err := token.UserTokenVerify(tokenStr, "access")
if err != nil {
return token.UserInfo{}, err
}
// 获取缓存的用户信息
info := token.UserInfoGet(claims)
if info.UserId <= 0 {
return token.UserInfo{}, fmt.Errorf("invalid login user information")
}
return info, nil
}
// LoginUserToUserName 登录用户信息-用户名称
func LoginUserToUserName(r *http.Request) string {
loginUser, err := LoginUser(r)
if err != nil {
return ""
}
return loginUser.User.UserName
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,119 +0,0 @@
package evaluate
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"math"
"regexp"
"strconv"
"strings"
)
// Parse and caculate expression
func CalcExpr(expr string, paramValues map[string]any) (float64, error) {
// match parameter with ''
re := regexp.MustCompile(`'([^']+)'`)
matches := re.FindAllStringSubmatch(expr, -1)
// replace to value
for _, match := range matches {
paramName := match[1]
value, exists := paramValues[paramName]
if !exists {
return 0, fmt.Errorf("parameter '%s' not found", paramName)
}
expr = strings.Replace(expr, match[0], fmt.Sprintf("%v", value), 1)
}
// expression to evaluate
result, err := evalExpr(expr)
if math.IsNaN(result) {
return 0.0, err
}
return result, err
}
// eval 解析和计算表达式
func evalExpr(expr string) (float64, error) {
//fset := token.NewFileSet()
node, err := parser.ParseExpr(expr)
if err != nil {
return 0, err
}
return evalNode(node)
}
// EvaluateExpr 解析并计算给定的表达式
func EvalExpr(expr string, values map[string]any) (float64, error) {
// 解析表达式
node, err := parser.ParseExpr(expr)
if err != nil {
return 0, err
}
// 遍历 AST 并替换变量
ast.Inspect(node, func(n ast.Node) bool {
if ident, ok := n.(*ast.Ident); ok {
if val, ok := values[ident.Name]; ok {
// 替换标识符为对应值
ident.Name = fmt.Sprintf("%v", val)
}
}
return true
})
// 计算表达式
return evalNode(node)
}
// eval 递归计算 AST 节点
func evalNode(node ast.Node) (float64, error) {
var result float64
switch n := node.(type) {
case *ast.BinaryExpr:
left, err := evalNode(n.X)
if err != nil {
return 0, err
}
right, err := evalNode(n.Y)
if err != nil {
return 0, err
}
switch n.Op {
case token.ADD:
result = left + right
case token.SUB:
result = left - right
case token.MUL:
result = left * right
case token.QUO:
if right == 0 {
return math.NaN(), fmt.Errorf("divisor cannot be zero")
}
result = left / right
}
case *ast.BasicLit:
var err error
result, err = strconv.ParseFloat(n.Value, 64)
if err != nil {
return 0, err
}
case *ast.Ident:
val, err := strconv.ParseFloat(n.Name, 64)
if err != nil {
return 0, fmt.Errorf("unsupported expression: %s", n.Name)
}
result = val
case *ast.ParenExpr:
return evalNode(n.X) // 递归评估括号中的表达式
default:
return 0, fmt.Errorf("unsupported expression: %T", n)
}
return result, nil
}

View File

@@ -1,27 +0,0 @@
package file
import (
"os"
"path/filepath"
)
func GetFileAndDirCount(dir string) (int, int, error) {
var fileCount, dirCount int
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == dir {
return nil // 跳过当前目录
}
if info.IsDir() {
dirCount++
} else {
fileCount++
}
return nil
})
return fileCount, dirCount, err
}

View File

@@ -1,78 +0,0 @@
//go:build linux
// +build linux
package file
import (
"fmt"
"os"
"os/user"
"path/filepath"
"syscall"
)
type FileInfo struct {
FileType string `json:"fileType"` // file type: file/directory
FileMode string `json:"fileMode"` // file mode
LinkCount int64 `json:"linkCount"` // link count
Owner string `json:"owner"` // owner
Group string `json:"group"` // group
Size int64 `json:"size"` // size: xx byte
ModifiedTime int64 `json:"modifiedTime"` // last modified time:seconds
FilePath string `json:"filePath"` // file path
FileName string `json:"fileName"` // file name
}
func GetFileInfo(dir, suffix string) ([]FileInfo, error) {
var files []FileInfo
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == dir {
return nil // 跳过当前目录
}
fileType := "file"
if info.IsDir() {
fileType = "directory"
} else if info.Mode()&os.ModeSymlink != 0 {
fileType = "symlink"
}
// check if match suffix
if (suffix != "" && filepath.Ext(path) == suffix) || suffix == "" {
stat, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return fmt.Errorf("not a syscall.Stat_t")
}
userInfo, err := user.LookupId(fmt.Sprint(stat.Uid))
if err != nil {
return err
}
groupInfo, err := user.LookupGroupId(fmt.Sprint(stat.Gid))
if err != nil {
return err
}
fileInfo := FileInfo{
FileType: fileType,
FileMode: info.Mode().String(),
LinkCount: int64(info.Sys().(*syscall.Stat_t).Nlink),
Owner: userInfo.Username,
Group: groupInfo.Name,
Size: info.Size(),
ModifiedTime: info.ModTime().Unix(),
FilePath: dir,
FileName: info.Name(),
}
files = append(files, fileInfo)
}
return nil
})
if err != nil {
return nil, err
}
return files, nil
}

View File

@@ -1,63 +0,0 @@
//go:build windows
// +build windows
package file
import (
"os"
"path/filepath"
)
type FileInfo struct {
FileType string `json:"fileType"` // file type: file/directory
FileMode string `json:"fileMode"` // file mode
LinkCount int64 `json:"linkCount"` // link count
Owner string `json:"owner"` // owner
Group string `json:"group"` // group
Size int64 `json:"size"` // size: xx byte
ModifiedTime int64 `json:"modifiedTime"` // last modified time:seconds
FilePath string `json:"filePath"` // file path
FileName string `json:"fileName"` // file name
}
func GetFileInfo(dir, suffix string) ([]FileInfo, error) {
var files []FileInfo
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == dir {
return nil // 跳过当前目录
}
fileType := "file"
if info.IsDir() {
fileType = "directory"
} else if info.Mode()&os.ModeSymlink != 0 {
fileType = "symlink"
}
// check if match suffix
if (suffix != "" && filepath.Ext(path) == suffix) || suffix == "" {
fileInfo := FileInfo{
FileType: fileType,
FileMode: info.Mode().String(),
LinkCount: 0,
Owner: "-",
Group: "-",
Size: info.Size(),
ModifiedTime: info.ModTime().Unix(),
FilePath: dir,
FileName: info.Name(),
}
files = append(files, fileInfo)
}
return nil
})
if err != nil {
return nil, err
}
return files, nil
}

View File

@@ -1,47 +0,0 @@
//go:build linux
// +build linux
package global
import (
"bytes"
"os/exec"
)
func ExecCmd(command string) ([]byte, error) {
cmd := exec.Command("/bin/bash", "-c", command)
out, err := cmd.CombinedOutput()
if err != nil {
return nil, err
}
return out, nil
}
func ExecShell(command string) error {
in := bytes.NewBuffer(nil)
cmd := exec.Command("sh")
cmd.Stdin = in
in.WriteString(command)
in.WriteString("exit\n")
if err := cmd.Start(); err != nil {
return err
}
return nil
}
func ExecOsCmd(command, os string) ([]byte, error) {
var cmd *exec.Cmd
switch os {
case "Linux":
cmd = exec.Command(command)
case "Windows":
cmd = exec.Command("cmd", "/C", command)
}
out, err := cmd.CombinedOutput()
if err != nil {
return nil, err
}
return out, nil
}

View File

@@ -1,34 +0,0 @@
//go:build windows
// +build windows
package global
import (
"os/exec"
)
func ExecCmd(command string) ([]byte, error) {
cmd := exec.Command("cmd", "/C", command)
out, err := cmd.CombinedOutput()
if err != nil {
return nil, err
}
return out, nil
}
func ExecOsCmd(command, os string) ([]byte, error) {
var cmd *exec.Cmd
switch os {
case "Linux":
cmd = exec.Command(command)
case "Windows":
cmd = exec.Command("cmd", "/C", command)
}
out, err := cmd.CombinedOutput()
if err != nil {
return nil, err
}
return out, nil
}

View File

@@ -1,65 +0,0 @@
package global
import "errors"
// 跨package引用的首字母大写
const (
RequestBodyMaxLen = 2000000
ApiVersionV1 = "v1"
ApiVersionV2 = "v2"
LineBreak = "\n"
)
const (
DateTime = "2006-01-02 15:04:05"
DateData = "20060102150405"
DateHour = "2006010215"
DateZone = "2006-01-02 15:04:05 +0000 UTC"
)
const (
MaxInt32Number = 2147483647
)
const (
MaxLimitData = 1000
)
var (
Version string = "-"
BuildTime string = "-"
GoVer string = "-"
)
var (
DefaultUriPrefix = "/api/rest"
)
var (
ErrParamsNotAdapted = errors.New("the number of params is not adapted")
// PM module error message
ErrPMNotFoundData = errors.New("not found PM data")
// CM module error message
ErrCMNotFoundTargetNE = errors.New("not found target NE")
ErrCMCannotDeleteActiveNE = errors.New("can not delete an active NE")
ErrCMInvalidBackupFile = errors.New("invalid backup file")
ErrCMNotMatchMD5File = errors.New("md5 not match between file and url")
ErrCMNotMatchSignFile = errors.New("digests signatures not match in the file")
ErrCMExistSoftwareFile = errors.New("exist the same software package file")
ErrCMNotFoundTargetSoftware = errors.New("not found the target software package")
ErrCMNotFoundTargetNeVersion = errors.New("not found the target NE version")
ErrCMNotFoundRollbackNeVersion = errors.New("not found the rollback NE version")
ErrCMUnknownServiceAction = errors.New("unknown service action")
ErrCMUnknownInstanceAction = errors.New("unknown instance action")
ErrCMNotFoundTargetBackupFile = errors.New("not found the target NE backup")
ErrCMUnknownSoftwareFormat = errors.New("unknown software package format") // 未知软件包格式
// TRACE module error message
ErrTraceFailedDistributeToNEs = errors.New("failed to distribute trace task to target NEs")
ErrTraceNotCarriedTaskID = errors.New("not carried task id in request url")
// MML module error define
ErrMmlInvalidCommandFormat = errors.New("invalid mml command format")
)

View File

@@ -1,728 +0,0 @@
package global
import (
"archive/zip"
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
"path/filepath"
"reflect"
"regexp"
"sort"
"strings"
"time"
)
const (
IsIPv4 = "IPv4"
IsIPv6 = "IPv6"
NonIP = "NonIp"
)
type em struct{}
func GetPkgName() string {
return reflect.TypeOf(em{}).PkgPath()
}
// interface{} change to map[string]interface{}
// interface{} data is []interface{}
func ListToMap(list interface{}, key string) map[string]interface{} {
res := make(map[string]interface{})
arr := ToSlice(list)
for _, row := range arr {
immutable := reflect.ValueOf(row)
val := immutable.FieldByName(key).String()
res[val] = row
}
return res
}
// interface{} change to []interface{}
func ToSlice(arr interface{}) []interface{} {
ret := make([]interface{}, 0)
v := reflect.ValueOf(arr)
if v.Kind() != reflect.Slice {
ret = append(ret, arr)
return ret
}
l := v.Len()
for i := 0; i < l; i++ {
ret = append(ret, v.Index(i).Interface())
}
return ret
}
var TodoList []Todo
type Todo struct {
Id int64
Item string
}
// JSON序列化方式
func jsonStructToMap(TodoList Todo) (map[string]interface{}, error) {
// 结构体转json
strRet, err := json.Marshal(TodoList)
if err != nil {
return nil, err
}
// json转map
var mRet map[string]interface{}
err1 := json.Unmarshal(strRet, &mRet)
if err1 != nil {
return nil, err1
}
return mRet, nil
}
func IsContain(item string, items []string) bool {
for _, e := range items {
if e == item {
return true
}
}
return false
}
func IsContainP(item string, items *[]string, size int) bool {
for i := 0; i < size; i++ {
if (*items)[i] == item {
return true
}
}
return false
}
// 将字符串 分割成 字符串数组
// @s分割符
func SplitString(str string, s string) []string {
sa := strings.Split(str, s)
return sa
}
//  合并字符串数组
func MergeStringArr(a, b []string) []string {
var arr []string
for _, i := range a {
arr = append(arr, i)
}
for _, j := range b {
arr = append(arr, j)
}
return arr
}
// 数组去重
func UniqueStringArr(m []string) []string {
d := make([]string, 0)
tempMap := make(map[string]bool, len(m))
for _, v := range m { // 以值作为键名
if tempMap[v] == false {
tempMap[v] = true
d = append(d, v)
}
}
return d
}
//  合并整型数组
func MergeArr(a, b []int) []int {
var arr []int
for _, i := range a {
arr = append(arr, i)
}
for _, j := range b {
arr = append(arr, j)
}
return arr
}
// 数组去重
func UniqueArr(m []int) []int {
d := make([]int, 0)
tempMap := make(map[int]bool, len(m))
for _, v := range m { // 以值作为键名
if tempMap[v] == false {
tempMap[v] = true
d = append(d, v)
}
}
return d
}
// 升序
func AscArr(e []int) []int {
sort.Ints(e[:])
return e
}
// 降序
func DescArr(e []int) []int {
sort.Sort(sort.Reverse(sort.IntSlice(e)))
return e
}
func MatchRmUID(p string, s string) bool {
match, _ := regexp.MatchString(p, s)
return match
}
type OrderedMap struct {
Order []string
Map map[string]interface{}
}
func (om *OrderedMap) UnmarshalJson(b []byte) error {
json.Unmarshal(b, &om.Map)
index := make(map[string]int)
for key := range om.Map {
om.Order = append(om.Order, key)
esc, _ := json.Marshal(key) //Escape the key
index[key] = bytes.Index(b, esc)
}
sort.Slice(om.Order, func(i, j int) bool { return index[om.Order[i]] < index[om.Order[j]] })
return nil
}
func (om OrderedMap) MarshalJson() ([]byte, error) {
var b []byte
buf := bytes.NewBuffer(b)
buf.WriteRune('{')
l := len(om.Order)
for i, key := range om.Order {
km, err := json.Marshal(key)
if err != nil {
return nil, err
}
buf.Write(km)
buf.WriteRune(':')
vm, err := json.Marshal(om.Map[key])
if err != nil {
return nil, err
}
buf.Write(vm)
if i != l-1 {
buf.WriteRune(',')
}
fmt.Println(buf.String())
}
buf.WriteRune('}')
fmt.Println(buf.String())
return buf.Bytes(), nil
}
func GetBodyCopy(r *http.Request) (*bytes.Buffer, error) {
// If r.bodyBuf present, return the copy
// if r.bodyBuf != nil {
// return bytes.NewBuffer(r.bodyBuf.Bytes()), nil
// }
// Maybe body is `io.Reader`.
// Note: Resty user have to watchout for large body size of `io.Reader`
if r.Body != nil {
b, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
// Restore the Body
// close(r.Body)
r.Body = io.NopCloser(bytes.NewReader(b))
// Return the Body bytes
return bytes.NewBuffer(b), nil
}
return nil, nil
}
func UnmarshalBody(r *http.Request, v *interface{}, maxLen int64) error {
body, err := io.ReadAll(io.LimitReader(r.Body, maxLen))
if err != nil {
return err
}
return json.Unmarshal(body, v)
}
func SetNotifyUrl(ip string, port uint16, uri string) string {
return fmt.Sprintf("http://%s:%d%s", ip, port, uri)
}
func GetIps() (ips []string, err error) {
interfaceAddr, err := net.InterfaceAddrs()
if err != nil {
return ips, err
}
for _, address := range interfaceAddr {
ipNet, isVailIpNet := address.(*net.IPNet)
// 检查ip地址判断是否回环地址
if isVailIpNet && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
ips = append(ips, ipNet.IP.String())
}
}
}
return ips, nil
}
func GetCurrentTimeSliceIndexByPeriod(t time.Time, period int) int {
index := int((t.Hour()*60+t.Minute())/period) - 1
if index < 0 {
return int(24*60/period) - 1
}
return index
}
var (
cst *time.Location
)
// RFC3339ToDateTime convert rfc3339 value to china standard time layout
func RFC3339ToDateTime(value string) (string, error) {
ts, err := time.Parse(time.RFC3339, value)
if err != nil {
return "", err
}
return ts.In(cst).Format("2006-01-02 15:04:05"), nil
}
// CreateTimeDir 根据当前时间格式来创建文件夹
func CreateTimeDir(fmt string, path string) string {
folderName := time.Now().Format(fmt)
folderPath := filepath.Join(path, folderName)
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
// 必须分成两步:先创建文件夹、再修改权限
os.Mkdir(folderPath, 0664) //0644也可以os.ModePerm
os.Chmod(folderPath, 0664)
}
return folderPath
}
// CreateDir 根据传入的目录名和路径来创建文件夹
func CreateDir(folderName string, path string) string {
folderPath := filepath.Join(path, folderName)
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
// 必须分成两步:先创建文件夹、再修改权限
os.MkdirAll(folderPath, 0664) //0644也可以os.ModePerm
os.Chmod(folderPath, 0664)
}
return folderPath
}
func GetFmtTimeString(srcFmt string, timeString string, dstFmt string) string {
t, _ := time.ParseInLocation(srcFmt, timeString, time.Local)
return t.Format(dstFmt)
}
func GetFileMD5Sum(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
defer file.Close()
md5 := md5.New()
_, err = io.Copy(md5, file)
if err != nil {
return "", err
}
md5str := hex.EncodeToString(md5.Sum(nil))
return md5str, nil
}
// PathExists check path is exist or no
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil { //文件或者目录存在
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// PathExists check path is exist or no
func FilePathExists(filePath string) (bool, error) {
_, err := os.Stat(filePath)
if err == nil { //文件或者目录存在
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func GetDayDuration(d1, d2 string) int64 {
a, _ := time.Parse("2006-01-02", d1)
b, _ := time.Parse("2006-01-02", d2)
d := a.Sub(b)
return (int64)(d.Hours() / 24)
}
func GetSecondsSinceDatetime(datetimeStr string) (int64, error) {
loc1, _ := time.LoadLocation("Local")
// 解析日期时间字符串为时间对象
datetime, err := time.ParseInLocation(time.DateTime, datetimeStr, loc1)
if err != nil {
return 0, err
}
// 计算时间差
duration := time.Since(datetime)
// 获取时间差的秒数
seconds := int64(duration.Seconds())
return seconds, nil
}
func GetSecondDuration(time1, time2 string) (int64, error) {
loc1, _ := time.LoadLocation("Local")
// 解析日期时间字符串为时间对象
t1, err := time.ParseInLocation(time.DateTime, time1, loc1)
if err != nil {
return 0, err
}
t2, err := time.ParseInLocation(time.DateTime, time2, loc1)
if err != nil {
return 0, err
}
// 计算时间差
duration := t2.Sub(t1)
// 获取时间差的秒数
seconds := int64(duration.Seconds())
return seconds, nil
}
// 0: invalid ip
// 4: IPv4
// 6: IPv6
func ParseIP(s string) (net.IP, int) {
ip := net.ParseIP(s)
if ip == nil {
return nil, 0
}
for i := 0; i < len(s); i++ {
switch s[i] {
case '.':
return ip, 4
case ':':
return ip, 6
}
}
return nil, 0
}
func BytesCombine1(pBytes ...[]byte) []byte {
return bytes.Join(pBytes, []byte(""))
}
func BytesCombine(pBytes ...[]byte) []byte {
length := len(pBytes)
s := make([][]byte, length)
for index := 0; index < length; index++ {
s[index] = pBytes[index]
}
sep := []byte("")
return bytes.Join(s, sep)
}
func ParseIPAddr(ip string) string {
ipAddr := net.ParseIP(ip)
if ipAddr != nil {
if ipAddr.To4() != nil {
return IsIPv4
} else {
return IsIPv6
}
}
return NonIP
}
func CombineHostUri(ip string, port string) string {
var hostUri string = ""
ipType := ParseIPAddr(ip)
if ipType == IsIPv4 {
hostUri = fmt.Sprintf("http://%s:%v", ip, port)
} else {
hostUri = fmt.Sprintf("http://[%s]:%v", ip, port)
}
return hostUri
}
func StructToMap(obj interface{}) map[string]interface{} {
objValue := reflect.ValueOf(obj)
objType := objValue.Type()
m := make(map[string]interface{})
for i := 0; i < objValue.NumField(); i++ {
field := objValue.Field(i)
fieldName := objType.Field(i).Name
m[fieldName] = field.Interface()
}
return m
}
// ToMap 结构体转为Map[string]interface{}
func ToMap(in interface{}, tagName string) (map[string]interface{}, error) {
out := make(map[string]interface{})
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct { // 非结构体返回错误提示
return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v)
}
t := v.Type()
// 遍历结构体字段
// 指定tagName值为map中key;字段值为map中value
for i := 0; i < v.NumField(); i++ {
fi := t.Field(i)
if tagValue := fi.Tag.Get(tagName); tagValue != "" {
out[tagValue] = v.Field(i).Interface()
}
}
return out, nil
}
func ZipOneFile(srcFile, dstZip string, pathFlag bool) error {
zipFile, err := os.Create(dstZip)
if err != nil {
return err
}
defer zipFile.Close()
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
fileToCompress, err := os.Open(srcFile)
if err != nil {
return err
}
defer fileToCompress.Close()
var fileInZip io.Writer
if pathFlag {
fileInZip, err = zipWriter.Create(srcFile)
if err != nil {
return err
}
} else {
// 获取文件的基本名称
fileName := filepath.Base(fileToCompress.Name())
fileInZip, err = zipWriter.Create(fileName)
if err != nil {
return err
}
}
_, err = io.Copy(fileInZip, fileToCompress)
if err != nil {
return err
}
return nil
}
func ZipDirectoryFile(srcDir, dstZip string) error {
// Create a new zip file
zipfileWriter, err := os.Create(dstZip)
if err != nil {
return err
}
defer zipfileWriter.Close()
// Create a new zip archive
zipWriter := zip.NewWriter(zipfileWriter)
defer zipWriter.Close()
// Walk through the directory and add files to the zip archive
err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// Create a new file header for the current file
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
// Set the name of the file within the zip archive
header.Name = filepath.Join(filepath.Base(srcDir), path[len(srcDir):])
// If the current file is a directory, skip it
if info.IsDir() {
return nil
}
// Create a new file in the zip archive
fileWriter, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
// Open the current file
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
// Copy the contents of the current file to the zip archive
_, err = io.Copy(fileWriter, file)
if err != nil {
return err
}
return nil
})
return err
}
// 判断软件包是rpm或者deb, 1:rpm, 2:deb, 0:unknown format
func JudgeRpmOrDebPackage(filePath string) (int, error) {
var fileType int = 0
file, err := os.Open(filePath)
if err != nil {
return fileType, err
}
defer file.Close()
// Read the first 6 bytes of the file
header := make([]byte, 6)
_, err = file.Read(header)
if err != nil {
return fileType, err
}
// Check the magic numbers to determine the package format
if string(header) == "!<arch>" {
fileType = 1
} else if string(header) == "!<arch\n" || string(header) == "!<arch\r" {
fileType = 2
} else {
fileType = 0
}
return fileType, nil
}
func isRpmPackage(file *os.File) bool {
// RPM packages start with the magic number "EDABEEDB"
magic := []byte{0xED, 0xAB, 0xEE, 0xDB}
buffer := make([]byte, len(magic))
_, err := file.Read(buffer)
if err != nil && err != io.EOF {
return false
}
return string(buffer) == string(magic)
}
func isDebPackage(file *os.File) bool {
// DEB packages start with the magic number "!<arch>\n"
magic := []byte("!<arch>\n")
buffer := make([]byte, len(magic))
_, err := file.Read(buffer)
if err != nil && err != io.EOF {
return false
}
return string(buffer) == string(magic)
}
func CheckRpmOrDebPackage(filePath string) (int, error) {
var fileType int = 0
file, err := os.Open(filePath)
if err != nil {
return fileType, err
}
defer file.Close()
isRpm := isRpmPackage(file)
isDeb := isDebPackage(file)
if isRpm {
fileType = 1
} else if isDeb {
fileType = 2
} else {
fileType = 0
}
return fileType, nil
}
func IsRpmOrDebPackage(filePath string) int {
var fileType int = 0
if strings.Contains(filePath, ".rpm") {
fileType = 1
} else if strings.Contains(filePath, ".deb") {
fileType = 2
} else {
fileType = 0
}
return fileType
}
func RecurseStructToMap(obj any) map[string]any {
out := make(map[string]any)
v := reflect.ValueOf(obj)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
// 递归函数,用于处理嵌套结构体
var recurse func(reflect.Value) any
recurse = func(value reflect.Value) any {
if value.Kind() == reflect.Struct {
nestedOut := make(map[string]any)
for i := 0; i < value.NumField(); i++ {
nestedOut[value.Type().Field(i).Name] = recurse(value.Field(i))
}
return nestedOut
} else if value.Kind() == reflect.Ptr {
return recurse(value.Elem())
}
return value.Interface()
}
t := v.Type()
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
out[t.Field(i).Name] = recurse(f)
}
return out
}

View File

@@ -1,338 +0,0 @@
// logger for omc/ems
package log
import (
"fmt"
"io"
"log"
)
// LogLevel defines a log level
type LogLevel int
// enum all LogLevels
const (
// following level also match syslog.Priority value
LOG_TRACE LogLevel = iota
LOG_DEBUG
LOG_INFO
LOG_WARN
LOG_ERROR
LOG_FATAL
LOG_OFF
LOG_NODEF
)
// default log options
const (
DEFAULT_LOG_PREFIX = "omc"
DEFAULT_LOG_FLAG = log.Lshortfile | log.Ldate | log.Lmicroseconds
DEFAULT_LOG_LEVEL = LOG_DEBUG
DEFAULT_CALL_DEPTH = 3
)
// Logger is a logger interface
type Logger interface {
Fatal(v ...interface{})
Fatalf(format string, v ...interface{})
Error(v ...interface{})
Errorf(format string, v ...interface{})
Warn(v ...interface{})
Warnf(format string, v ...interface{})
Info(v ...interface{})
Infof(format string, v ...interface{})
Debug(v ...interface{})
Debugf(format string, v ...interface{})
Trace(v ...interface{})
Tracef(format string, v ...interface{})
Level() LogLevel
LevelString() string
SetLevel(l LogLevel)
}
var _ Logger = DiscardLogger{}
// DiscardLogger don't log implementation for ILogger
type DiscardLogger struct{}
// Trace empty implementation
func (DiscardLogger) Trace(v ...interface{}) {}
// Tracef empty implementation
func (DiscardLogger) Tracef(format string, v ...interface{}) {}
// Debug empty implementation
func (DiscardLogger) Debug(v ...interface{}) {}
// Debugf empty implementation
func (DiscardLogger) Debugf(format string, v ...interface{}) {}
// Info empty implementation
func (DiscardLogger) Info(v ...interface{}) {}
// Infof empty implementation
func (DiscardLogger) Infof(format string, v ...interface{}) {}
// Warn empty implementation
func (DiscardLogger) Warn(v ...interface{}) {}
// Warnf empty implementation
func (DiscardLogger) Warnf(format string, v ...interface{}) {}
// Error empty implementation
func (DiscardLogger) Error(v ...interface{}) {}
// Errorf empty implementation
func (DiscardLogger) Errorf(format string, v ...interface{}) {}
// Fatal empty implementation
func (DiscardLogger) Fatal(v ...interface{}) {}
// Fatalf empty implementation
func (DiscardLogger) Fatalf(format string, v ...interface{}) {}
// Level empty implementation
func (DiscardLogger) Level() LogLevel {
return LOG_NODEF
}
// Level empty implementation
func (DiscardLogger) LevelString() string {
return ""
}
// SetLevel empty implementation
func (DiscardLogger) SetLevel(l LogLevel) {}
// EmsLogger is the default implment of ILogger
type EmsLogger struct {
TRACE *log.Logger
DEBUG *log.Logger
INFO *log.Logger
WARN *log.Logger
ERROR *log.Logger
FATAL *log.Logger
level LogLevel
levelString []string
depth int
}
var _ Logger = &EmsLogger{}
// NewEmsLogger use a special io.Writer as logger output
func NewEmsLogger(out io.Writer) *EmsLogger {
return NewEmsLogger2(out, DEFAULT_LOG_PREFIX, DEFAULT_LOG_FLAG)
}
// NewEmsLogger2 let you customrize your logger prefix and flag
func NewEmsLogger2(out io.Writer, prefix string, flag int) *EmsLogger {
return NewEmsLogger3(out, prefix, flag, DEFAULT_LOG_LEVEL)
}
// NewEmsLogger3 let you customrize your logger prefix and flag and logLevel
func NewEmsLogger3(out io.Writer, prefix string, flag int, l LogLevel) *EmsLogger {
return &EmsLogger{
TRACE: log.New(out, fmt.Sprintf("[%s] [trace] ", prefix), flag),
DEBUG: log.New(out, fmt.Sprintf("[%s] [debug] ", prefix), flag),
INFO: log.New(out, fmt.Sprintf("[%s] [info ] ", prefix), flag),
WARN: log.New(out, fmt.Sprintf("[%s] [warn ] ", prefix), flag),
ERROR: log.New(out, fmt.Sprintf("[%s] [error] ", prefix), flag),
FATAL: log.New(out, fmt.Sprintf("[%s] [fatal] ", prefix), flag),
level: l,
levelString: []string{"trace", "debug", "info", "warn", "error", "fatal"},
depth: DEFAULT_CALL_DEPTH,
}
}
// Trace implement ILogger
func (s *EmsLogger) Trace(v ...interface{}) {
if s.level <= LOG_TRACE {
_ = s.TRACE.Output(s.depth, fmt.Sprintln(v...))
}
}
// Tracef implement ILogger
func (s *EmsLogger) Tracef(format string, v ...interface{}) {
if s.level <= LOG_TRACE {
_ = s.TRACE.Output(s.depth, fmt.Sprintf(format, v...))
}
}
// Debug implement ILogger
func (s *EmsLogger) Debug(v ...interface{}) {
if s.level <= LOG_DEBUG {
_ = s.DEBUG.Output(s.depth, fmt.Sprintln(v...))
}
}
// Debugf implement ILogger
func (s *EmsLogger) Debugf(format string, v ...interface{}) {
if s.level <= LOG_DEBUG {
_ = s.DEBUG.Output(s.depth, fmt.Sprintf(format, v...))
}
}
// Info implement ILogger
func (s *EmsLogger) Info(v ...interface{}) {
if s.level <= LOG_INFO {
_ = s.INFO.Output(s.depth, fmt.Sprintln(v...))
}
}
// Infof implement ILogger
func (s *EmsLogger) Infof(format string, v ...interface{}) {
if s.level <= LOG_INFO {
_ = s.INFO.Output(s.depth, fmt.Sprintf(format, v...))
}
}
// Warn implement ILogger
func (s *EmsLogger) Warn(v ...interface{}) {
if s.level <= LOG_WARN {
_ = s.WARN.Output(s.depth, fmt.Sprintln(v...))
}
}
// Warnf implement ILogger
func (s *EmsLogger) Warnf(format string, v ...interface{}) {
if s.level <= LOG_WARN {
_ = s.WARN.Output(s.depth, fmt.Sprintf(format, v...))
}
}
// Error implement ILogger
func (s *EmsLogger) Error(v ...interface{}) {
if s.level <= LOG_ERROR {
_ = s.ERROR.Output(s.depth, fmt.Sprintln(v...))
}
}
// Errorf implement ILogger
func (s *EmsLogger) Errorf(format string, v ...interface{}) {
if s.level <= LOG_ERROR {
_ = s.ERROR.Output(s.depth, fmt.Sprintf(format, v...))
}
}
// Warn implement ILogger
func (s *EmsLogger) Fatal(v ...interface{}) {
if s.level <= LOG_FATAL {
_ = s.FATAL.Output(s.depth, fmt.Sprintln(v...))
}
}
// Warnf implement ILogger
func (s *EmsLogger) Fatalf(format string, v ...interface{}) {
if s.level <= LOG_FATAL {
_ = s.FATAL.Output(s.depth, fmt.Sprintf(format, v...))
}
}
// Level implement ILogger
func (s *EmsLogger) Level() LogLevel {
return s.level
}
// Level implement ILogger
func (s *EmsLogger) LevelString() string {
return s.levelString[s.level]
}
// SetLevel implement ILogger
func (s *EmsLogger) SetLevel(l LogLevel) {
s.level = l
}
var Elogger Logger
func InitLogger(logFile string, period int, count int, prefix string, logLevel LogLevel) io.Writer {
/*
logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
if err != nil {
panic(err)
}
*/
logWriter := getLogWriter(logFile, period, count)
Elogger = NewEmsLogger3(logWriter, prefix, DEFAULT_LOG_FLAG, logLevel)
// fmt.Printf("logFile=%s, period=%d, count=%d, prefix=%s, logLevel=%s\n", logFile, period, count, prefix, GetLevelString())
return logWriter
}
// Trace implement ILogger
func Trace(v ...interface{}) {
Elogger.Trace(v...)
}
// Tracef implement ILogger
func Tracef(format string, v ...interface{}) {
Elogger.Tracef(format, v...)
}
// Debug implement ILogger
func Debug(v ...interface{}) {
Elogger.Debug(v...)
}
// Debugf implement ILogger
func Debugf(format string, v ...interface{}) {
Elogger.Debugf(format, v...)
}
// Info implement ILogger
func Info(v ...interface{}) {
Elogger.Info(v...)
}
// Infof implement ILogger
func Infof(format string, v ...interface{}) {
Elogger.Infof(format, v...)
}
// Warn implement ILogger
func Warn(v ...interface{}) {
Elogger.Warn(v...)
}
// Warnf implement ILogger
func Warnf(format string, v ...interface{}) {
Elogger.Warnf(format, v...)
}
// Error implement ILogger
func Error(v ...interface{}) {
Elogger.Error(v...)
}
// Errorf implement ILogger
func Errorf(format string, v ...interface{}) {
Elogger.Errorf(format, v...)
}
// Warn implement ILogger
func Fatal(v ...interface{}) {
Elogger.Fatal(v...)
}
// Warnf implement ILogger
func Fatalf(format string, v ...interface{}) {
Elogger.Fatalf(format, v...)
}
// Level implement ILogger
func GetLevel() LogLevel {
return Elogger.Level()
}
// Level implement ILogger
func GetLevelString() string {
return Elogger.LevelString()
}
// SetLevel implement ILogger
func SetLevel(l LogLevel) {
Elogger.SetLevel(l)
}

View File

@@ -1,71 +0,0 @@
package log
import (
"io"
"time"
rotatelogs "github.com/lestrrat/go-file-rotatelogs"
)
type WriteSyncer interface {
io.Writer
Sync() error
}
// 得到LogWriter
func getLogWriter(filePath string, period, count int) WriteSyncer {
warnIoWriter := getWriter(filePath, period, count)
return addSync(warnIoWriter)
}
// 日志文件切割
func getWriter(filename string, period, count int) io.Writer {
// 保存日志count天每period小时分割一次日志
duration := time.Hour * time.Duration(period)
var logfile string
if period >= 24 {
logfile = filename + "-%Y%m%d"
} else {
logfile = filename + "-%Y%m%d%H"
}
hook, err := rotatelogs.New(
logfile,
rotatelogs.WithLinkName(filename),
// rotatelogs.WithMaxAge(duration),
rotatelogs.WithRotationCount(count),
rotatelogs.WithRotationTime(duration),
rotatelogs.WithLocation(time.Local),
)
//保存日志30天每1分钟分割一次日志
/*
hook, err := rotatelogs.New(
filename+"_%Y%m%d%H%M.log",
rotatelogs.WithLinkName(filename),
rotatelogs.WithMaxAge(time.Hour*24*30),
rotatelogs.WithRotationTime(time.Minute*1),
)
*/
if err != nil {
panic(err)
}
return hook
}
func addSync(w io.Writer) WriteSyncer {
switch w := w.(type) {
case WriteSyncer:
return w
default:
return writerWrapper{w}
}
}
type writerWrapper struct {
io.Writer
}
func (w writerWrapper) Sync() error {
return nil
}

View File

@@ -1,89 +0,0 @@
//go:build !windows && !nacl && !plan9
// +build !windows,!nacl,!plan9
package log
import (
"fmt"
"log/syslog"
)
var _ Logger = &SyslogLogger{}
// SyslogLogger will be depricated
type SyslogLogger struct {
w *syslog.Writer
}
// NewSyslogLogger implements Logger
func NewSyslogLogger(w *syslog.Writer) *SyslogLogger {
return &SyslogLogger{w: w}
}
// Trace log content as Trace
func (s *SyslogLogger) Trace(v ...interface{}) {
_ = s.w.Trace(fmt.Sprint(v...))
}
// Tracef log content as Trace and format
func (s *SyslogLogger) Tracef(format string, v ...interface{}) {
_ = s.w.Trace(fmt.Sprintf(format, v...))
}
// Debug log content as Debug
func (s *SyslogLogger) Debug(v ...interface{}) {
_ = s.w.Debug(fmt.Sprint(v...))
}
// Debugf log content as Debug and format
func (s *SyslogLogger) Debugf(format string, v ...interface{}) {
_ = s.w.Debug(fmt.Sprintf(format, v...))
}
// Error log content as Error
func (s *SyslogLogger) Error(v ...interface{}) {
_ = s.w.Err(fmt.Sprint(v...))
}
// Errorf log content as Errorf and format
func (s *SyslogLogger) Errorf(format string, v ...interface{}) {
_ = s.w.Err(fmt.Sprintf(format, v...))
}
// Info log content as Info
func (s *SyslogLogger) Info(v ...interface{}) {
_ = s.w.Info(fmt.Sprint(v...))
}
// Infof log content as Infof and format
func (s *SyslogLogger) Infof(format string, v ...interface{}) {
_ = s.w.Info(fmt.Sprintf(format, v...))
}
// Warn log content as Warn
func (s *SyslogLogger) Warn(v ...interface{}) {
_ = s.w.Warn(fmt.Sprint(v...))
}
// Warnf log content as Warnf and format
func (s *SyslogLogger) Warnf(format string, v ...interface{}) {
_ = s.w.Warn(fmt.Sprintf(format, v...))
}
// Fatal log content as Fatal
func (s *SyslogLogger) Fatal(v ...interface{}) {
_ = s.w.Fatal(fmt.Sprint(v...))
}
// Fatalf log content as Fatalf and format
func (s *SyslogLogger) Fatalf(format string, v ...interface{}) {
_ = s.w.Fatal(fmt.Sprintf(format, v...))
}
// Level shows log level
func (s *SyslogLogger) Level() LogLevel {
return LOG_NODEF
}
// SetLevel always return error, as current log/syslog package doesn't allow to set priority level after syslog.Writer created
func (s *SyslogLogger) SetLevel(l LogLevel) {}

View File

@@ -1,80 +0,0 @@
package midware
import (
"net/http"
"strings"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/constants"
"github.com/gorilla/mux"
)
func LoggerTrace(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Do stuff here
log.Trace("Http Trace Info:")
log.Trace(" From Host:", r.RemoteAddr)
log.Trace(" To Host:", r.Host)
log.Debug(" RequestUri:", r.RequestURI)
log.Trace(" Method:", r.Method)
log.Trace(" Proto:", r.Proto)
log.Trace(" ContentLength:", r.ContentLength)
log.Trace(" User-Agent:", r.Header.Get("User-Agent"))
log.Trace(" Content-Type:", r.Header.Get("Content-Type"))
log.Trace(" AccessToken:", r.Header.Get("AccessToken"))
log.Trace(" Authorization:", r.Header.Get(constants.HEADER_KEY))
log.Trace("Trace End=====")
//body, _ := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
// nop-close to ready r.Body !!!
//r.Body = ioutil.NopCloser(bytes.NewReader(body))
//log.Trace("Body:", string(body))
// Call the next handler, which can be another middleware in the chain, or the final handler.
// if r.Method == "OPTIONS" {
// services.ResponseStatusOK201Accepted(w)
// return
// }
next.ServeHTTP(w, r)
})
}
// 已禁用
func OptionProcess(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
services.ResponseStatusOK201Accepted(w)
return
}
next.ServeHTTP(w, r)
})
}
// 已禁用
func CheckPermission(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("AccessToken")
vars := mux.Vars(r)
management := vars["managedType"]
element := vars["elementTypeValue"]
object := vars["objectTypeValue"]
pack := "*"
if token != "" && element != "oauth" {
log.Debugf("token:%s, method:%s, management:%s, element:%s, object:%s, pack:%s", token, r.Method, management, element, object, pack)
exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), management, element, object, pack)
if err != nil {
log.Error("Failed to get permission:", err)
services.ResponseForbidden403NotPermission(w)
return
}
if !exist {
log.Error("Not permission!")
services.ResponseForbidden403NotPermission(w)
return
}
}
next.ServeHTTP(w, r)
})
}

View File

@@ -1,60 +0,0 @@
package midware
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"be.ems/lib/core/ctx"
"be.ems/lib/log"
"be.ems/src/framework/database/db"
"be.ems/src/framework/utils/date"
)
// LogMML mml操作日志搜集
func LogMML(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 读取请求体内容
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
// 解析json内参数
var bodyArgs map[string]any
_ = json.Unmarshal(bytes.Clone(body), &bodyArgs)
// 将请求体内容存储在临时缓冲区中
buffer := bytes.NewBuffer(body)
r.Body = io.NopCloser(buffer)
next.ServeHTTP(w, r)
// 收尾存入数据库的参数
mmlCmd := bodyArgs["mml"].([]any)[0]
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
neType := ctx.GetParam(r, "elementTypeValue")
neId := ctx.GetQuery(r, "ne_id")
timeStr := date.ParseDateToStr(time.Now(), date.YYYY_MM_DD_HH_MM_SS)
// 响应内容长度和状态码作为结果
str := strings.TrimSuffix(fmt.Sprintf("%v", w), "}")
strArr := strings.Split(str, " ")
size := strArr[1]
status := strArr[2]
contentType := w.Header().Get("Content-Type")
resultStr := fmt.Sprintf(`{"status":"%s","size":"%s","content-type":"%s"}`, status, size, contentType)
// 用户名
username := ctx.LoginUserToUserName(r)
// 执行插入
sql := "insert into mml_log (user,ip,ne_type,ne_id,mml,result,log_time)values(?,?,?,?,?,?,?)"
_, sqlerr := db.ExecDB("", sql, []any{username, ipAddr, neType, neId, mmlCmd, resultStr, timeStr})
if sqlerr != nil {
log.Errorf("insert row : %v", sqlerr.Error())
}
})
}

View File

@@ -1,135 +0,0 @@
package midware
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"reflect"
"runtime"
"strings"
"time"
"be.ems/lib/core/ctx"
"be.ems/src/framework/constants"
"be.ems/src/framework/ip2region"
"be.ems/src/framework/middleware/collectlogs"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/system/model"
"be.ems/src/modules/system/service"
)
// 敏感属性字段进行掩码
var maskProperties []string = []string{
"password",
"oldPassword",
"newPassword",
"confirmPassword",
}
// LogOperate 操作日志搜集
func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
// 只对前端发送的数据进行记录
appCodeStr := r.Header.Get("X-App-Code")
if appCodeStr == "" {
next.ServeHTTP(w, r)
return
}
// 函数名
funcName := runtime.FuncForPC(reflect.ValueOf(next).Pointer()).Name()
lastDotIndex := strings.LastIndex(funcName, "/")
funcName = funcName[lastDotIndex+1:]
// 用户名
username := ctx.LoginUserToUserName(r)
// 解析ip地址
ip := strings.Split(r.RemoteAddr, ":")[0]
ipaddr := ip2region.ClientIP(ip)
location := "-" //ip2region.RealAddressByIp(ipaddr)
// 操作日志记录
operLog := model.SysLogOperate{
Title: options.Title,
BusinessType: options.BusinessType,
OperaMethod: funcName,
OperaUrl: r.RequestURI,
OperaUrlMethod: r.Method,
OperaIp: ipaddr,
OperaLocation: location,
OperaBy: username,
}
// 是否需要保存request参数和值
if options.IsSaveRequestData && (r.Method == "POST" || r.Method == "PUT") {
// 读取请求体内容
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
// 解析json内参数
var bodyArgs map[string]any
_ = json.Unmarshal(bytes.Clone(body), &bodyArgs)
// 将请求体内容存储在临时缓冲区中
buffer := bytes.NewBuffer(body)
r.Body = io.NopCloser(buffer)
params := bodyArgs
for k, v := range params {
// 敏感属性字段进行掩码
for _, s := range maskProperties {
if s == k {
params[k] = parse.SafeContent(v.(string))
break
}
}
}
jsonStr, _ := json.Marshal(params)
paramsStr := string(jsonStr)
if len(paramsStr) > 2000 {
paramsStr = paramsStr[:2000]
}
operLog.OperaParam = paramsStr
}
next.ServeHTTP(w, r)
// 响应内容长度和状态码作为结果
str := strings.TrimSuffix(fmt.Sprintf("%v", w), "}")
strArr := strings.Split(str, " ")
size := strArr[1]
status := strArr[2]
// 响应状态
if status == "200" || status == "204" {
operLog.StatusFlag = constants.STATUS_YES
} else {
operLog.StatusFlag = constants.STATUS_NO
}
// 是否需要保存response参数和值
if options.IsSaveResponseData {
contentDisposition := w.Header().Get("Content-Disposition")
contentType := w.Header().Get("Content-Type")
content := contentType + contentDisposition
msg := fmt.Sprintf(`{"status":"%s","size":"%s","content-type":"%s"}`, status, size, content)
operLog.OperaMsg = msg
}
// 日志记录时间
duration := time.Since(startTime)
operLog.CostTime = duration.Milliseconds()
operLog.OperaTime = time.Now().UnixMilli()
// 保存操作记录到数据库
service.NewSysLogOperate.Insert(operLog)
})
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,157 +0,0 @@
package oauth
import (
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"math/rand"
"net/http"
"strings"
"time"
"be.ems/lib/log"
"golang.org/x/crypto/bcrypt"
)
func RandAccessToken(n int) (ret string) {
allString := "52661fbd-6b84-4fc2-aa1e-17879a5c6c9b"
ret = ""
for i := 0; i < n; i++ {
r := rand.Intn(len(allString))
ret = ret + allString[r:r+1]
}
return ret
}
const letterBytes = "abcdef0123456789"
const (
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
var src = rand.NewSource(time.Now().UnixNano())
func RandStringBytes(n int) string {
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
b[i] = letterBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
}
return string(b)
}
func GenRandToken(prefix string) string {
if prefix == "" {
return RandStringBytes(8) + "-" + RandStringBytes(4) + "-" +
RandStringBytes(4) + "-" + RandStringBytes(4) + "-" + RandStringBytes(12)
} else {
return prefix + "-" + RandStringBytes(8) + "-" + RandStringBytes(4) + "-" +
RandStringBytes(4) + "-" + RandStringBytes(4) + "-" + RandStringBytes(12)
}
}
type OAuthBody struct {
GrantType string
UserName string
Value string
}
/*
func IsValidOAuthInfo(oAuthBody OAuthBody) bool {
log.Debug("IsValidOAuthInfo processing... ")
conf := config.GetYamlConfig()
for _, o := range conf.Auth {
if oAuthBody.GrantType == o.Type && oAuthBody.UserName == o.User && oAuthBody.Value == o.Password {
return true
}
}
return false
}
*/
func IsWrongOAuthInfo(oAuthBody OAuthBody) bool {
log.Debug("IsWrongOAuthInfo processing... ")
if oAuthBody.GrantType == "" || strings.ToLower(oAuthBody.GrantType) != "password" ||
oAuthBody.UserName == "" || oAuthBody.Value == "" {
return true
}
return false
}
func GetTokenFromHttpRequest(r *http.Request) string {
for k, v := range r.Header {
log.Tracef("k:%s, v:%s", k, v)
if strings.ToLower(k) == "accesstoken" && len(v) != 0 {
log.Trace("AccessToken:", v[0])
return v[0]
}
}
return ""
}
// IsCarriedToken check token is carried
func IsCarriedToken(r *http.Request) (string, bool) {
token := GetTokenFromHttpRequest(r)
if token == "" {
return "", false
}
return token, true
}
// Bcrypt Encrypt 加密明文密码
func BcryptEncrypt(password string) (string, error) {
hashedBytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(hashedBytes), err
}
// Bcrypt Compare 密文校验
func BcryptCompare(hashedPassword, password string) error {
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
}
// sha256 crypt
func GetSHA256HashCode(stringMessage string) string {
message := []byte(stringMessage) //字符串转化字节数组
//创建一个基于SHA256算法的hash.Hash接口的对象
hash := sha256.New() //sha-256加密
//输入数据
hash.Write(message)
//计算哈希值
bytes := hash.Sum(nil)
//将字符串编码为16进制格式,返回字符串
hashCode := hex.EncodeToString(bytes)
//返回哈希值
return hashCode
}
// sha512 crypt
func GetSHA512HashCode(stringMessage string) string {
message := []byte(stringMessage) //字符串转化字节数组
//创建一个基于SHA256算法的hash.Hash接口的对象
hash := sha512.New() //SHA-512加密
//输入数据
hash.Write(message)
//计算哈希值
bytes := hash.Sum(nil)
//将字符串编码为16进制格式,返回字符串
hashCode := hex.EncodeToString(bytes)
//返回哈希值
return hashCode
}

View File

@@ -1,37 +0,0 @@
package pair
type Pair struct {
Key int
Value int
}
type PairList []Pair
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with index i
// must sort before the element with index j.
//
// If both Less(i, j) and Less(j, i) are false,
// then the elements at index i and j are considered equal.
// Sort may place equal elements in any order in the final result,
// while Stable preserves the original input order of equal elements.
//
// Less must describe a transitive ordering:
// - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
// - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
//
// Note that floating-point comparison (the < operator on float32 or float64 values)
// is not a transitive ordering when not-a-number (NaN) values are involved.
// See Float64Slice.Less for a correct implementation for floating-point values.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
func (p PairList) Len() int { return len(p) }
func (p PairList) Less(i, j int) bool { return p[i].Value < p[j].Value }
func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }

View File

@@ -1,318 +0,0 @@
package routes
import (
"net/http"
// "log"
"be.ems/features/aaaa"
"be.ems/features/cdr"
"be.ems/features/cm"
"be.ems/features/dbrest"
"be.ems/features/event"
"be.ems/features/file"
"be.ems/features/fm"
"be.ems/features/lm"
"be.ems/features/mml"
"be.ems/features/pm"
"be.ems/features/security"
"be.ems/features/sm"
"be.ems/features/state"
"be.ems/features/ue"
"be.ems/lib/midware"
"be.ems/lib/services"
"be.ems/src/framework/middleware/collectlogs"
"github.com/gorilla/mux"
)
type Router struct {
Method string
Pattern string
Handler http.HandlerFunc
Middleware mux.MiddlewareFunc
}
var routers []Router
func init() {
Register("POST", security.UriOauthToken, security.LoginFromOMC, nil)
Register("POST", security.UriOauthHandshake, security.HandshakeFromOMC, nil)
Register("DELETE", security.UriOauthToken, security.LogoutFromOMC, nil)
Register("POST", security.CustomUriOauthToken, security.LoginFromOMC, nil)
Register("DELETE", security.CustomUriOauthToken, security.LogoutFromOMC, nil)
Register("POST", security.CustomUriOauthHandshake, security.HandshakeFromOMC, nil)
// System state
Register("GET", state.UriSysState, state.GetStateFromNF, nil)
Register("GET", state.UriSysState2, state.GetStateFromNF, nil)
Register("GET", state.UriSysInfoAll, state.GetAllSysinfoFromNF, nil)
Register("GET", state.UriSysInfoOne, state.GetOneSysinfoFromNF, nil)
Register("GET", state.UriLicenseInfoAll, state.GetAllLicenseInfoFromNF, nil)
Register("GET", state.UriLicenseInfoOne, state.GetOneLicenseInfoFromNF, nil)
Register("GET", state.CustomUriSysState, state.GetStateFromNF, nil)
Register("GET", state.CustomUriSysState2, state.GetStateFromNF, nil)
Register("GET", state.CustomUriSysInfoAll, state.GetAllSysinfoFromNF, nil)
Register("GET", state.CustomUriSysInfoOne, state.GetOneSysinfoFromNF, nil)
Register("GET", state.CustomUriLicenseInfoAll, state.GetAllLicenseInfoFromNF, nil)
Register("GET", state.CustomUriLicenseInfoOne, state.GetOneLicenseInfoFromNF, nil)
Register("GET", sm.UriOMCLocalTime, sm.GetOMCLocalTime, nil)
Register("GET", sm.CustomUriOMCLocalTime, sm.GetOMCLocalTime, nil)
// database management
Register("GET", dbrest.XormGetDataUri, dbrest.DatabaseGetData, nil)
Register("GET", dbrest.XormSelectDataUri, dbrest.DatabaseGetData, nil)
Register("POST", dbrest.XormInsertDataUri, dbrest.DatabaseInsertData, nil)
Register("PUT", dbrest.XormUpdateDataUri, dbrest.DatabaseUpdateData, nil)
Register("DELETE", dbrest.XormDeleteDataUri, dbrest.DatabaseDeleteData, nil)
Register("GET", dbrest.CustomXormGetDataUri, dbrest.DatabaseGetData, nil)
Register("GET", dbrest.CustomXormSelectDataUri, dbrest.DatabaseGetData, nil)
Register("POST", dbrest.CustomXormInsertDataUri, dbrest.DatabaseInsertData, nil)
Register("PUT", dbrest.CustomXormUpdateDataUri, dbrest.DatabaseUpdateData, nil)
Register("DELETE", dbrest.CustomXormDeleteDataUri, dbrest.DatabaseDeleteData, nil)
Register("GET", dbrest.XormCommonUri, dbrest.DatabaseGetData, nil)
Register("POST", dbrest.XormCommonUri, dbrest.DatabaseInsertData, nil)
Register("PUT", dbrest.XormCommonUri, dbrest.DatabaseUpdateData, nil)
Register("DELETE", dbrest.XormCommonUri, dbrest.DatabaseDeleteData, nil)
Register("GET", dbrest.XormDatabaseUri, dbrest.TaskDatabaseGetData, nil)
Register("POST", dbrest.XormDatabaseUri, dbrest.TaskDatabaseInsertData, nil)
Register("PUT", dbrest.XormDatabaseUri, dbrest.TaskDatabaseUpdateData, nil)
Register("DELETE", dbrest.XormDatabaseUri, dbrest.TaskDatabaseDeleteData, nil)
Register("GET", dbrest.CustomXormCommonUri, dbrest.DatabaseGetData, nil)
Register("POST", dbrest.CustomXormCommonUri, dbrest.DatabaseInsertData, nil)
Register("PUT", dbrest.CustomXormCommonUri, dbrest.DatabaseUpdateData, nil)
Register("DELETE", dbrest.CustomXormCommonUri, dbrest.DatabaseDeleteData, nil)
Register("GET", dbrest.XormDataRestUri, dbrest.ExtDatabaseGetData, nil)
Register("POST", dbrest.XormDataRestUri, dbrest.ExtDatabaseInsertData, nil)
Register("PUT", dbrest.XormDataRestUri, dbrest.ExtDatabaseUpdateData, nil)
Register("DELETE", dbrest.XormDataRestUri, dbrest.ExtDatabaseDeleteData, nil)
Register("GET", dbrest.XormExtDataUri, dbrest.ExtDatabaseGetData, nil)
Register("POST", dbrest.XormExtDataUri, dbrest.ExtDatabaseInsertData, nil)
Register("PUT", dbrest.XormExtDataUri, dbrest.ExtDatabaseUpdateData, nil)
Register("DELETE", dbrest.XormExtDataUri, dbrest.ExtDatabaseDeleteData, nil)
Register("GET", dbrest.CustomXormExtDataUri, dbrest.ExtDatabaseGetData, nil)
Register("POST", dbrest.CustomXormExtDataUri, dbrest.ExtDatabaseInsertData, nil)
Register("PUT", dbrest.CustomXormExtDataUri, dbrest.ExtDatabaseUpdateData, nil)
Register("DELETE", dbrest.CustomXormExtDataUri, dbrest.ExtDatabaseDeleteData, nil)
// alarm restful Register
Register("POST", fm.UriAlarms, fm.PostAlarmFromNF, nil)
Register("Get", fm.UriAlarms, fm.GetAlarmFromNF, nil)
Register("POST", fm.CustomUriAlarms, fm.PostAlarmFromNF, nil)
Register("Get", fm.CustomUriAlarms, fm.GetAlarmFromNF, nil)
// performance restful Register
Register("POST", pm.PerformanceUri, pm.PostKPIReportFromNF, nil)
Register("POST", pm.MeasureTaskUri, pm.PostMeasureTaskToNF, midware.LogOperate(collectlogs.OptionNew("MeasureTask", collectlogs.BUSINESS_TYPE_INSERT)))
Register("PUT", pm.MeasureTaskUri, pm.PutMeasureTaskToNF, midware.LogOperate(collectlogs.OptionNew("MeasureTask", collectlogs.BUSINESS_TYPE_UPDATE)))
Register("DELETE", pm.MeasureTaskUri, pm.DeleteMeasureTaskToNF, midware.LogOperate(collectlogs.OptionNew("MeasureTask", collectlogs.BUSINESS_TYPE_DELETE)))
Register("PATCH", pm.MeasureTaskUri, pm.PatchMeasureTaskToNF, midware.LogOperate(collectlogs.OptionNew("MeasureTask", collectlogs.BUSINESS_TYPE_UPDATE)))
Register("POST", pm.MeasureReportUri, pm.PostMeasureReportFromNF, midware.LogOperate(collectlogs.OptionNew("MeasureTask", collectlogs.BUSINESS_TYPE_UPDATE)))
Register("POST", pm.MeasurementUri, pm.PostMeasurementFromNF, nil)
Register("GET", pm.MeasurementUri, pm.GetMeasurementFromNF, nil)
Register("POST", pm.CustomPerformanceUri, pm.PostKPIReportFromNF, nil)
Register("POST", pm.CustomMeasureTaskUri, pm.PostMeasureTaskToNF, nil)
Register("PUT", pm.CustomMeasureTaskUri, pm.PutMeasureTaskToNF, nil)
Register("DELETE", pm.CustomMeasureTaskUri, pm.DeleteMeasureTaskToNF, nil)
Register("PATCH", pm.CustomMeasureTaskUri, pm.PatchMeasureTaskToNF, nil)
Register("POST", pm.CustomMeasureReportUri, pm.PostMeasureReportFromNF, nil)
Register("POST", pm.CustomMeasurementUri, pm.PostMeasurementFromNF, nil)
Register("GET", pm.CustomMeasurementUri, pm.GetMeasurementFromNF, nil)
// parameter config management
Register("GET", cm.ParamConfigUri, cm.GetParamConfigFromNF, nil)
Register("POST", cm.ParamConfigUri, cm.PostParamConfigToNF, midware.LogOperate(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_INSERT)))
Register("PUT", cm.ParamConfigUri, cm.PutParamConfigToNF, midware.LogOperate(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_UPDATE)))
Register("DELETE", cm.ParamConfigUri, cm.DeleteParamConfigToNF, midware.LogOperate(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_INSERT)))
Register("GET", cm.CustomParamConfigUri, cm.GetParamConfigFromNF, nil)
Register("POST", cm.CustomParamConfigUri, cm.PostParamConfigToNF, nil)
Register("PUT", cm.CustomParamConfigUri, cm.PutParamConfigToNF, nil)
Register("DELETE", cm.CustomParamConfigUri, cm.DeleteParamConfigToNF, nil)
// Get/Create/Modify/Delete NE info
Register("GET", cm.UriNeInfo, cm.GetNeInfo, nil)
Register("POST", cm.UriNeInfo, cm.PostNeInfo, midware.LogOperate(collectlogs.OptionNew("NE Info", collectlogs.BUSINESS_TYPE_INSERT)))
Register("PUT", cm.UriNeInfo, cm.PutNeInfo, midware.LogOperate(collectlogs.OptionNew("NE Info", collectlogs.BUSINESS_TYPE_UPDATE)))
Register("DELETE", cm.UriNeInfo, cm.DeleteNeInfo, midware.LogOperate(collectlogs.OptionNew("NE Info", collectlogs.BUSINESS_TYPE_DELETE)))
// Get/Create/Modify/Delete NE info
Register("GET", cm.CustomUriNeInfo, cm.GetNeInfo, nil)
Register("POST", cm.CustomUriNeInfo, cm.PostNeInfo, nil)
Register("PUT", cm.CustomUriNeInfo, cm.PutNeInfo, nil)
Register("DELETE", cm.CustomUriNeInfo, cm.DeleteNeInfo, nil)
//ne service action handle
Register("POST", cm.UriNeService, cm.PostNeServiceAction, nil)
//ne service action handle
Register("POST", cm.UriNeInstance, cm.PostNeInstanceAction, nil)
// Post MML command to NF
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, nil)
Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, nil)
// post mml2 (standard upf port=5002)
Register("POST", mml.UriMML2, mml.PostMML2ToNF, midware.LogMML)
Register("POST", mml.CustomUriMML2, mml.PostMML2ToNF, nil)
// Northbound Get NRM
// Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
// Register("GET", nbi.CustomGetNRMUri, nbi.NBIGetNRMFromNF, nil)
// Import/Export NF CM
Register("GET", cm.NeCmUri, cm.ExportCmFromNF, nil)
Register("POST", cm.NeCmUri, cm.ImportCmToNF, midware.LogOperate(collectlogs.OptionNew("Import NF", collectlogs.BUSINESS_TYPE_INSERT)))
Register("GET", cm.UriNeCmFile, cm.DownloadNeBackupFile, nil)
Register("DELETE", cm.UriNeCmFile, cm.DeleteNeBackupFile, midware.LogOperate(collectlogs.OptionNew("Delete NF Backup", collectlogs.BUSINESS_TYPE_DELETE)))
Register("GET", cm.CustomNeCmUri, cm.ExportCmFromNF, nil)
Register("POST", cm.CustomNeCmUri, cm.ImportCmToNF, nil)
Register("GET", cm.CustomUriNeCmFile, cm.DownloadNeBackupFile, nil)
Register("DELETE", cm.CustomUriNeCmFile, cm.DeleteNeBackupFile, nil)
// Software management
Register("GET", cm.UriSoftware, cm.DownloadSoftwareFile, nil)
//Register("POST", cm.UriSoftware, cm.UploadSoftwareFile, nil)
Register("POST", cm.UriSoftware, cm.UploadSoftwareMultiFile, midware.LogOperate(collectlogs.OptionNew("Software", collectlogs.BUSINESS_TYPE_UPDATE)))
Register("DELETE", cm.UriSoftware, cm.DeleteSoftwareFile, midware.LogOperate(collectlogs.OptionNew("Software", collectlogs.BUSINESS_TYPE_DELETE)))
Register("POST", cm.UriSoftwareNE, cm.DistributeSoftwareToNF, midware.LogOperate(collectlogs.OptionNew("Software", collectlogs.BUSINESS_TYPE_OTHER)))
Register("PUT", cm.UriSoftwareNE, cm.ActiveSoftwareToNF, midware.LogOperate(collectlogs.OptionNew("Software", collectlogs.BUSINESS_TYPE_OTHER)))
Register("PATCH", cm.UriSoftwareNE, cm.RollBackSoftwareToNF, midware.LogOperate(collectlogs.OptionNew("Software", collectlogs.BUSINESS_TYPE_OTHER)))
Register("GET", cm.CustomUriSoftware, cm.DownloadSoftwareFile, nil)
Register("POST", cm.CustomUriSoftware, cm.UploadSoftwareFile, nil)
Register("DELETE", cm.CustomUriSoftware, cm.DeleteSoftwareFile, nil)
Register("POST", cm.CustomUriSoftwareNE, cm.DistributeSoftwareToNF, nil)
Register("PUT", cm.CustomUriSoftwareNE, cm.ActiveSoftwareToNF, nil)
Register("PATCH", cm.CustomUriSoftwareNE, cm.RollBackSoftwareToNF, nil)
// file management
Register("POST", file.UriFile, file.UploadFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_INSERT)))
Register("GET", file.UriFile, file.DownloadFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_OTHER)))
Register("DELETE", file.UriFile, file.DeleteFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_DELETE)))
Register("POST", file.CustomUriFile, file.UploadFile, nil)
Register("GET", file.CustomUriFile, file.DownloadFile, nil)
Register("DELETE", file.CustomUriFile, file.DeleteFile, nil)
// AAAA
Register("GET", aaaa.UriAAAASSO, aaaa.GetSSOFromAAAA, nil)
// AAAA
Register("GET", aaaa.CustomUriAAAASSO, aaaa.GetSSOFromAAAA, nil)
// UEInfo: SMF
Register("GET", ue.UriUEInfo, ue.GetUEInfoFromNF, nil)
Register("GET", ue.CustomUriUEInfo, ue.GetUEInfoFromNF, nil)
// UEInfo: PCF
Register("GET", ue.UriPCFUser, ue.GetUEInfoFromNF, nil)
Register("GET", ue.CustomUriPCFUser, ue.GetUEInfoFromNF, nil)
Register("POST", ue.UriPCFUser, ue.PostPCFUserInfo, nil)
Register("POST", ue.CustomUriPCFUser, ue.PostPCFUserInfo, nil)
Register("PUT", ue.UriPCFUser, ue.PutPCFUserInfo, nil)
Register("PUT", ue.CustomUriPCFUser, ue.PutPCFUserInfo, nil)
Register("DELETE", ue.UriPCFUser, ue.DeletePCFUserInfo, nil)
Register("DELETE", ue.CustomUriPCFUser, ue.DeletePCFUserInfo, nil)
// PCFUEInfo: batch add/modify/delete
Register("POST", ue.UriPCFUserM, ue.PostPCFUserInfo, nil)
Register("POST", ue.CustomUriPCFUserM, ue.PostPCFUserInfo, nil)
Register("PUT", ue.UriPCFUserM, ue.PutPCFUserInfo, nil)
Register("PUT", ue.CustomUriPCFUserM, ue.PutPCFUserInfo, nil)
Register("DELETE", ue.UriPCFUserM, ue.DeletePCFUserInfo, nil)
Register("DELETE", ue.CustomUriPCFUserM, ue.DeletePCFUserInfo, nil)
//PCF User file
Register("GET", ue.UriPCFUserFileExport, ue.GetUEInfoFileExportNF, nil)
Register("PUT", ue.UriPCFUserFileImport, ue.PutPCFUserInfo, nil)
// UE Number
Register("GET", ue.UriUENum, ue.GetUENumFromNF, nil)
Register("GET", ue.CustomUriUENum, ue.GetUENumFromNF, nil)
// NBInfo
Register("GET", ue.UriNBInfo, ue.GetNBInfoFromNF, nil)
Register("GET", ue.CustomUriNBInfo, ue.GetNBInfoFromNF, nil)
Register("POST", ue.UriNBState, ue.PostNBInfoFromNF, nil)
Register("POST", ue.CustomUriNBState, ue.PostNBInfoFromNF, 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)
// cdr event
Register("POST", cdr.UriCDREvent, cdr.PostCDREventFrom, nil)
Register("POST", cdr.CustomUriCDREvent, cdr.PostCDREventFrom, nil)
// UE event 上报的UE事件
Register("POST", event.UriUEEvent, event.PostUEEvent, nil)
// UE event AMF上报的UE事件, 无前缀给到Gin处理
//Register("POST", event.UriUEEvent, event.PostUEEventFromAMF, nil)
// 数据库连接情况
Register("GET", dbrest.UriDbConnection, dbrest.DbConnection, nil)
Register("GET", dbrest.CustomUriDbConnection, dbrest.DbConnection, nil)
Register("POST", dbrest.UriDbStop, dbrest.DbStop, nil)
Register("POST", dbrest.CustomUriDbStop, dbrest.DbStop, nil)
// 日志表备份
Register("POST", lm.ExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
Register("POST", lm.CustomExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
}
// To resolv rest POST/PUT/DELETE/PATCH cross domain
func OptionsProc(w http.ResponseWriter, r *http.Request) {
services.ResponseStatusOK204NoContent(w)
}
func NewRouter() *mux.Router {
r := mux.NewRouter()
// set custom handle for status 404/405
// r.NotFoundHandler = services.CustomResponseNotFound404Handler()
// r.MethodNotAllowedHandler = services.CustomResponseMethodNotAllowed405Handler()
r.Use(midware.LoggerTrace)
// r.Use(midware.Cors)
// r.Use(midware.OptionProcess)
// r.Use(midware.ArrowIPAddr)
for _, router := range routers {
rt := r.Methods(router.Method).Subrouter()
rt.HandleFunc(router.Pattern, router.Handler)
if router.Middleware != nil {
rt.Use(router.Middleware)
}
}
return r
}
func Register(method, pattern string, handler http.HandlerFunc, middleware mux.MiddlewareFunc) {
routers = append(routers, Router{method, pattern, handler, middleware})
}

View File

@@ -1,56 +0,0 @@
//go:build linux
// +build linux
package run
import (
"bytes"
"os/exec"
"be.ems/lib/log"
)
func ExecCmd(command, path string) ([]byte, error) {
log.Debug("Exec command:", command)
cmd := exec.Command("/bin/bash", "-c", command)
cmd.Dir = path
out, err := cmd.CombinedOutput()
if err != nil {
return out, err
}
return out, nil
}
func ExecShell(command string) error {
in := bytes.NewBuffer(nil)
cmd := exec.Command("sh")
cmd.Stdin = in
in.WriteString(command)
in.WriteString("exit\n")
if err := cmd.Start(); err != nil {
return err
}
return nil
}
func ExecOsCmd(command, os string) error {
log.Debugf("Exec %s command:%s", os, command)
var cmd *exec.Cmd
switch os {
case "Linux":
cmd = exec.Command(command)
case "Windows":
cmd = exec.Command("cmd", "/C", command)
}
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return err
}
return nil
}

View File

@@ -1,45 +0,0 @@
//go:build wasm
// +build wasm
package run
import (
"os/exec"
"be.ems/lib/log"
)
func ExecCmd(command, path string) ([]byte, error) {
log.Debug("Exec command:", command)
cmd := exec.Command("cmd", "/C", command)
cmd.Dir = path
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return out, err
}
return out, nil
}
func ExecOsCmd(command, os string) error {
log.Debugf("Exec %s command:%s", os, command)
var cmd *exec.Cmd
switch os {
case "Linux":
cmd = exec.Command(command)
case "Windows":
cmd = exec.Command("cmd", "/C", command)
}
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return err
}
return nil
}

View File

@@ -1,45 +0,0 @@
//go:build windows
// +build windows
package run
import (
"os/exec"
"be.ems/lib/log"
)
func ExecCmd(command, path string) ([]byte, error) {
log.Debug("Exec command:", command)
cmd := exec.Command("cmd", "/C", command)
cmd.Dir = path
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return out, err
}
return out, nil
}
func ExecOsCmd(command, os string) error {
log.Debugf("Exec %s command:%s", os, command)
var cmd *exec.Cmd
switch os {
case "Linux":
cmd = exec.Command(command)
case "Windows":
cmd = exec.Command("cmd", "/C", command)
}
out, err := cmd.CombinedOutput()
log.Tracef("Exec output: %v", string(out))
if err != nil {
log.Error("exe cmd error: ", err)
return err
}
return nil
}

View File

@@ -1,426 +0,0 @@
package services
import (
"bufio"
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"strconv"
"strings"
"be.ems/lib/log"
)
const (
RootPath = "uploads/"
ChunkRootPath = "uploads_tmp/"
)
var (
// FilesMax 限制上传文件的大小为7 MB
FilesMax int64 = 32 << 20
// ValuesMax 限制POST字段内容的大小
ValuesMax int64 = 512
)
func GetPostFile(w http.ResponseWriter, r *http.Request) {
//获取文件流,第三个返回值是错误对象
file, header, _ := r.FormFile("file")
//读取文件流为[]byte
b, err := io.ReadAll(file)
if err != nil {
log.Error("Failed to ReadAll:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
//把文件保存到指定位置
err = os.WriteFile("./upload/test.zip", b, 0644)
if err != nil {
log.Error("Failed to WriteFile:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
//输出上传时文件名
log.Debug("filename:", header.Filename)
}
func GetUploadFile(w http.ResponseWriter, r *http.Request) {
log.Debug("GetUploadFile processing...")
file, err := os.Create("./test.zip")
if err != nil {
log.Error("Failed to Create:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
_, err = io.Copy(file, r.Body)
if err != nil {
log.Error("Failed to Copy:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
}
func GetUploadFormFile(w http.ResponseWriter, r *http.Request) {
// 设置最大的内存限制为32MB
r.ParseMultipartForm(32 << 20)
file, handler, err := r.FormFile("file")
if err != nil {
log.Error("Failed to FormFile:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
defer file.Close()
log.Debug("Header:%v", handler.Header)
f, err := os.OpenFile("./"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Error("Failed to OpenFile:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
defer f.Close()
_, err = io.Copy(f, file)
if err != nil {
log.Error("Failed to Copy:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
log.Debug("File uploaded successfully:", handler.Filename)
}
func HandleUploadFile(r *http.Request, path, newFileName string) (string, error) {
var filePath, fileName string
reader, err := r.MultipartReader()
if err != nil {
log.Error("Failed to MultipartReader:", err)
return "", err
}
for {
part, err := reader.NextPart()
if err == io.EOF {
break
} else if err != nil {
log.Error("Failed to NextPart:", err)
return "", err
}
log.Debugf("FileName=[%s], FormName=[%s]", part.FileName(), part.FormName())
if part.FileName() == "" { // this is FormData
data, _ := io.ReadAll(part)
log.Debugf("FormData=[%s]", string(data))
} else { // This is FileData
if newFileName != "" {
fileName = newFileName
} else {
fileName = part.FileName()
}
err := os.MkdirAll(path, os.ModePerm)
if err != nil {
log.Error("Failed to Mkdir:", err)
return "", err
}
filePath = path + "/" + fileName
file, err := os.Create(filePath)
if err != nil {
log.Error("Failed to Create:", err)
return "", err
}
defer file.Close()
_, err = io.Copy(file, part)
if err != nil {
log.Error("Failed to Copy:", err)
return "", err
}
}
}
return fileName, nil
}
type UploadMultiFileData struct {
SoftwareFileName string `json:"softwareFileName"`
CmsFileName string `json:"cmsFileName"`
Datas map[string][]string `json:"datas"`
}
func HandleUploadMultiFile(r *http.Request, path, newFileName string) (*UploadMultiFileData, error) {
fileData := new(UploadMultiFileData)
// 解析multipart/form-data请求
err := r.ParseMultipartForm(100 << 20) // 100MB
if err != nil {
return fileData, err
}
// 获取文件和数据
softwareFile := r.MultipartForm.File["file"]
cmsFile := r.MultipartForm.File["cms"]
fileData.Datas = r.MultipartForm.Value
// 处理文件
if len(softwareFile) > 0 {
file := softwareFile[0]
// 打开文件
f, err := file.Open()
if err != nil {
return fileData, err
}
defer f.Close()
// 创建本地文件
dst, err := os.Create(path + "/" + file.Filename)
if err != nil {
return fileData, err
}
defer dst.Close()
fileData.SoftwareFileName = file.Filename
// 将文件内容拷贝到本地文件
_, err = io.Copy(dst, f)
if err != nil {
return fileData, err
}
}
// 处理文件
if len(cmsFile) > 0 {
file := cmsFile[0]
// 打开文件
f, err := file.Open()
if err != nil {
return fileData, err
}
defer f.Close()
// 创建本地文件
dst, err := os.Create(path + "/" + file.Filename)
if err != nil {
return fileData, err
}
defer dst.Close()
fileData.CmsFileName = file.Filename
// 将文件内容拷贝到本地文件
_, err = io.Copy(dst, f)
if err != nil {
return fileData, err
}
}
return fileData, nil
}
func HandleUploadFormFile(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(32 << 20)
//mForm := r.MultipartForm
for k := range r.MultipartForm.File {
// k is the key of file part
file, fileHeader, err := r.FormFile(k)
if err != nil {
fmt.Println("inovke FormFile error:", err)
return
}
defer file.Close()
fmt.Printf("the uploaded file: name[%s], size[%d], header[%#v]\n",
fileHeader.Filename, fileHeader.Size, fileHeader.Header)
// store uploaded file into local path
localFileName := "./upload/" + fileHeader.Filename
out, err := os.Create(localFileName)
if err != nil {
fmt.Printf("failed to open the file %s for writing", localFileName)
return
}
defer out.Close()
_, err = io.Copy(out, file)
if err != nil {
fmt.Printf("copy file err:%s\n", err)
return
}
fmt.Printf("file %s uploaded ok\n", fileHeader.Filename)
}
}
func PostFileHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("PostFileHandler processing... ")
if !strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data") {
// 不支持的 Content-Type 类型
fmt.Println("Invalid Content-Type: ", r.Header.Get("Content-Type"))
http.Error(w, " Unsupported Content-Type Types", http.StatusBadRequest)
return
}
// 整个请求的主体大小设置为7.5Mb
r.Body = http.MaxBytesReader(w, r.Body, FilesMax+ValuesMax)
reader, err := r.MultipartReader()
if err != nil {
fmt.Println(err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
for {
// A Part represents a single part in a multipart body.
part, err := reader.NextPart()
if err != nil {
if err == io.EOF {
break
}
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fileName := part.FileName()
formName := part.FormName()
var buf = &bytes.Buffer{}
// 非文件字段部分大小限制验证非文件字段go中filename会是空
if fileName == "" {
// "请求主体中非文件字段" + formName + "超出大小限制"
var limitError = fmt.Sprintf("Non-file field %s in request body exceeds size limit", formName)
err = uploadSizeLimit(buf, part, ValuesMax, limitError)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
continue
}
// 文件字段部分大小限制验证
// "请求主体中文件字段" + fileName + "超出大小限制"
var limitError = fmt.Sprintf("File field %s in request body exceeds size limit", fileName)
err = uploadSizeLimit(buf, part, FilesMax, limitError)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 文件创建部分
if err := uploadFileHandle(r.Header, fileName, buf); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 非逻辑内容,仅为测试使用
var chunkNumber = r.Header.Get("chunk-number")
if chunkNumber == "" {
// "文件"+fileName+"上传成功"
http.Error(w, fmt.Sprintf("File %s uploaded successfully", fileName), http.StatusOK)
} else {
// "分片文件 %s %s 上传成功"
http.Error(w, fmt.Sprintf("Sliced file %s %s uploaded successfully.", fileName, chunkNumber), http.StatusOK)
}
}
}
// 上传内容大小限制
func uploadSizeLimit(buf *bytes.Buffer, part *multipart.Part, maxLimit int64, limitError string) error {
n, err := io.CopyN(buf, part, maxLimit+1)
if err != nil && err != io.EOF {
fmt.Println("PostFileHandler:", err)
return err
}
maxLimit -= n
if maxLimit < 0 {
return fmt.Errorf("%s", limitError)
}
return nil
}
// uploadFileHandle handle upload file
func uploadFileHandle(header http.Header, fileName string, buf *bytes.Buffer) error {
var chunkNumberStr = header.Get("chunk-number")
// 1.普通文件上传处理
if chunkNumberStr == "" {
//创建文件并写入文件内容
return createFile(RootPath+fileName, buf.Bytes())
}
// 2.分片文件上传处理
//2.1读取分片编号
chunkNumber, err := strconv.Atoi(chunkNumberStr)
if err != nil {
return err
}
//2.2创建分片文件并写入分片内容
if err := createFile(fmt.Sprintf(ChunkRootPath+fileName+"%d.chunk", chunkNumber), buf.Bytes()); err != nil {
return err
}
//2.3确认是否上传完毕
if header.Get("chunk-final") == "true" {
//2.4合并文件
if err := mergeChunkFiles(fileName); err != nil {
return err
}
//2.5删除分片
for i := 0; ; i++ {
chunFileName := fmt.Sprintf(ChunkRootPath+fileName+"%d.chunk", i)
err := os.Remove(chunFileName)
if err != nil {
if os.IsNotExist(err) {
break
}
return err
}
}
}
return nil
}
// 创建文件并写入内容
func createFile(fileName string, res []byte) error {
newFile, err := os.Create(fileName)
if err != nil {
return err
}
defer func() {
_ = newFile.Close()
}()
bufferedWriter := bufio.NewWriter(newFile)
_, err = bufferedWriter.Write(res)
if err != nil && err != io.EOF {
return err
}
return bufferedWriter.Flush()
}
// 合并分片文件
func mergeChunkFiles(fileName string) error {
var (
n int64
err error
)
finalFile, err := os.Create(RootPath + fileName)
if err != nil {
return err
}
defer finalFile.Close()
// 将分片内容写入最终文件
for i := 0; ; i++ {
chunFile, err := os.Open(fmt.Sprintf(ChunkRootPath+fileName+"%d.chunk", i))
if err != nil {
if os.IsNotExist(err) {
break
}
return err
}
n, err = io.Copy(finalFile, chunFile)
if err != nil {
return err
}
err = chunFile.Close()
if err != nil {
return err
}
if n < 1 {
break
}
}
return nil
}

View File

@@ -1,39 +0,0 @@
package services
import "be.ems/src/framework/resp"
const (
CODE_FAIL = resp.CODE_ERROR
CODE_SUCC = resp.CODE_SUCCESS
)
func ErrResp(msg string) map[string]any {
return map[string]any{"code": CODE_FAIL, "msg": msg}
}
func DataResp(data any) map[string]any {
return map[string]any{"code": CODE_SUCC, "data": data}
}
func SuccMessageResp() map[string]any {
return map[string]any{"code": CODE_SUCC, "msg": "success"}
}
func TotalResp(total int64) map[string]any {
return map[string]any{"code": CODE_SUCC, "total": total}
}
func TotalDataResp(data any, total any) map[string]any {
return map[string]any{"code": CODE_SUCC, "data": map[string]any{
"rows": data, "total": total,
}, "msg": "success"}
}
func SuccResp(va map[string]any) map[string]any {
resp := make(map[string]any)
resp["code"] = CODE_SUCC
for k, v := range va {
resp[k] = v
}
return resp
}

View File

@@ -1,983 +0,0 @@
package services
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"mime/multipart"
"os"
"path/filepath"
// "log"
"net/http"
"net/url"
"strconv"
"strings"
"be.ems/lib/config"
"be.ems/lib/dborm"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/oauth"
"github.com/gorilla/mux"
)
type NameValue struct {
Name string
Value string
}
type NameOid struct {
Name string
Oid string
}
type DataResponse struct {
Data interface{} `json:"data"`
}
type MapResponse map[string]any
type NullResponse struct {
nil interface{}
}
type ErrorResponse struct {
Error interface{} `json:"error"`
}
type ErrorMessage struct {
ErrorCode string `json:"errorCode"`
ErrorInfo string `json:"errorInfo"`
}
type SucceedOAuthResponse struct {
AccessToken string `json:"accessToken"`
Expires string `json:"expires"`
// Enum: "0": 不需要修改密码, "1": "FirstLogin",首次登录, "2": PasswordAboutToExpire, 密码即将过期
ChangePasswordFlag int `json:"changePasswordFlag"`
GroupName string `json:"groupName"`
Roles []string `json:"roles"`
Perms []string `json:"perms"`
}
type ServiceResponse struct {
}
func GetUriParamString(r *http.Request, paramName string, sep string, brackets bool, apostr bool) string {
vars := r.URL.Query()
s, ok := vars[paramName]
if !ok {
log.Infof("Parameter Name is not exist, %s", paramName)
return ""
}
if apostr {
for i := 0; i < len(s); i++ {
s[i] = "'" + s[i] + "'"
}
}
pn := strings.Join(s, sep)
if brackets {
pn = fmt.Sprintf("(%s)", pn)
}
return pn
}
func GetUriWhereString(r *http.Request) string {
return GetUriParamString(r, "WHERE", " and ", false, false)
}
func GetUriLocString(r *http.Request) string {
return GetUriParamString(r, "loc", " and ", false, false)
}
func GetUriPageLimitString(r *http.Request) string {
vars := r.URL.Query()
p, ok := vars["PAGE"]
if !ok {
log.Info("page param is not exist")
return ""
}
l, ok := vars["LIMIT"]
if !ok {
log.Info("limit param is not exist")
return ""
}
li, _ := strconv.Atoi(l[0])
pi, _ := strconv.Atoi(p[0])
ls := fmt.Sprintf("limit %d, %d", li*(pi-1), li)
log.Debug("Limit array:", ls)
return ls
}
func ExtGetUriPageLimitString(r *http.Request) string {
vars := r.URL.Query()
p, ok := vars["page"]
if !ok {
log.Info("page param is not exist")
p = append(p, "1")
}
l, ok := vars["limit"]
if !ok {
log.Info("limit param is not exist")
l = append(l, strconv.Itoa(global.MaxLimitData))
}
limit, _ := strconv.Atoi(l[0])
if limit > global.MaxLimitData {
limit = global.MaxLimitData
}
page, _ := strconv.Atoi(p[0])
limitStr := fmt.Sprintf("limit %d, %d", limit*(page-1), limit)
log.Debug("limitStr:", limitStr)
return limitStr
}
func IsJsonContentType(r *http.Request) bool {
hType := r.Header.Get("Content-Type")
return strings.Contains(hType, "application/json")
}
func IsValidOAuthUri(r *http.Request) bool {
vars := mux.Vars(r)
apiVer := vars["apiVersion"] // 获取Uri
return apiVer == "v1"
}
func IsVallidContentType(r *http.Request, checkFlag bool) bool {
log.Debug("IsVallidContentType processing ...")
/*
ctype := r.Header["Content-Type"]
log.Debug("ctype:", ctype)
if len(ctype) != 0 && !strings.Contains(ctype[0], "application/json") {
return false
}
*/
if strings.Contains(r.Header.Get("Content-Type"), "application/json") || !checkFlag {
return true
}
return false
}
func CheckParameterName(r *http.Request) []string {
var errorParams []string
vars := r.URL.Query()
for k, v := range vars {
log.Debug("vars:", k, v)
if k != "rmUIDs" && k != "fields" {
errorParams = append(errorParams, k)
}
}
return errorParams
}
func GetRmUIDArr(r *http.Request) []string {
vars := r.URL.Query()
rmUIDs, ok := vars["rmUIDs"]
if !ok {
log.Info("rmUIDs is not exist")
return nil
}
var rmUIDValues []string
for _, r := range rmUIDs {
if r != "" {
rmUIDValues = global.MergeStringArr(rmUIDValues, strings.Split(r, `,`))
}
}
return rmUIDValues
}
func GetAttrNameArr(r *http.Request) []string {
vars := r.URL.Query()
fields, ok := vars["fields"]
if !ok {
log.Info("attributeNames does not exist")
return nil
}
var attrNames []string
for _, a := range fields {
if a != "" {
attrNames = global.MergeStringArr(attrNames, strings.Split(a, `,`))
}
}
return attrNames
}
func CheckValidRmUID(rmUIDs []string) []string {
log.Debug("CheckValidRmUID processing... ")
var invalidRmUIDs []string
for _, r := range rmUIDs {
if !global.MatchRmUID(config.GetRmUIDRegexpFromConfig(), r) {
invalidRmUIDs = append(invalidRmUIDs, r)
}
}
return invalidRmUIDs
}
func CheckLocalRmUID(rmUIDs []string) string {
log.Debug("GetLocalRmUID processing... ")
rmUID := config.GetRmUIDFromConfig()
for _, r := range rmUIDs {
if r == rmUID {
return rmUID
}
}
return ""
}
func GetParamsArrByName(paramName string, r *http.Request) []string {
vars := r.URL.Query()
pns, ok := vars[paramName]
if !ok {
log.Infof("%s is not exist", paramName)
return nil
}
var pnArr []string
for _, pn := range pns {
if pn != "" {
pnArr = global.MergeStringArr(pnArr, strings.Split(pn, `,`))
}
}
return pnArr
}
func GetOperationTypeFromHttpRequest(r *http.Request) string {
for k, v := range r.Header {
log.Tracef("k:%s, v:%s", k, v)
if strings.ToLower(k) == "operationtype" && len(v) != 0 {
log.Trace("OperationType:", v[0])
return v[0]
}
}
return ""
}
func CheckNorthboundValidRequest(w http.ResponseWriter, r *http.Request) (string, error) {
log.Debug("CheckNorthboundValidRequest processing... ")
var token string = ""
var err error
var ret bool
// response 414-4 uri too long ? (optional)
// todo ... ?
if bytes.Count([]byte(r.RequestURI), nil) > config.GetUriMaxLenFromConfig() {
log.Error("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil), config.GetUriMaxLenFromConfig())
ResponseRequestURITooLong414UriTooLong(w)
return token, err
}
// check media type(content type) only support "application/json"
// response 415-1
if !IsJsonContentType(r) {
log.Error("invalid Content-Type")
ResponseUnsupportedMediaType415(w)
return token, err
}
// error processing ...
// 401-1 response
token, ret = oauth.IsCarriedToken(r)
if !ret {
log.Error("accessToken is not carried")
ResponseUnauthorized401AccessTokenNotCarried(w)
return token, err
}
// 401-2 response
if !dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) {
log.Error("accessToken fails or does not exist")
ResponseUnauthorized401AccessTokenNotExist(w)
return token, err
}
if operType := GetOperationTypeFromHttpRequest(r); operType != "auto" {
_, err = dborm.XormUpdateSessionShakeTime(token)
if err != nil {
log.Error("Failed to update session table:", err)
ResponseUnauthorized401AccessTokenNotExist(w)
return token, err
}
}
vars := mux.Vars(r)
apiVer := vars["apiVersion"]
if apiVer != global.ApiVersionV1 {
log.Error("Uri is invalid")
ResponseNotFound404UriNotExist(w, r)
return token, err
}
// response 406-1
rmUIDValues := GetRmUIDArr(r)
if rmUIDValues == nil {
log.Error("missing parameter: rmUIDs")
ResponseNotAcceptable406MissingParam(w)
return token, err
}
// response 406-2
errorParams := CheckParameterName(r)
if errorParams != nil {
log.Error("parameter name error: ", errorParams)
ResponseNotAcceptable406ParamError(w, errorParams)
return token, err
}
// response 400-5
if len(rmUIDValues) == 0 {
log.Error("rmUIDs is wrong or NULL")
ResponseBadRequest400WrongParamValue(w)
return token, err
}
// response 414-1
if len(rmUIDValues) > config.GetYamlConfig().Params.RmUIDMaxNum {
log.Error("rmUID greater than", config.GetYamlConfig().Params.RmUIDMaxNum)
ResponseRequestURITooLong414NRMNumExceed(w, config.GetYamlConfig().Params.RmUIDMaxNum)
return token, err
}
return token, nil
}
func CheckCommonValidRequest(w http.ResponseWriter, r *http.Request) (string, error) {
log.Debug("CheckCommonValidRequest processing... ")
var token string = ""
var err error
var ret bool
// response 414-4 uri too long ? (optional)
// todo ... ?
if bytes.Count([]byte(r.RequestURI), nil) > config.GetUriMaxLenFromConfig() {
log.Error("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil), config.GetUriMaxLenFromConfig())
ResponseRequestURITooLong414UriTooLong(w)
return token, err
}
// check media type(content type) only support "application/json"
// response 415-1
if !IsJsonContentType(r) {
log.Error("Invalid Content-Type")
ResponseUnsupportedMediaType415(w)
return token, err
}
// error processing ...
// 401-1 response
token, ret = oauth.IsCarriedToken(r)
if !ret {
log.Error("accessToken is not carried")
ResponseUnauthorized401AccessTokenNotCarried(w)
return token, err
}
// 401-2 response
if !dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) {
log.Error("accessToken fails or does not exist")
ResponseUnauthorized401AccessTokenNotExist(w)
return token, err
}
if operType := GetOperationTypeFromHttpRequest(r); operType != "auto" {
_, err = dborm.XormUpdateSessionShakeTime(token)
if err != nil {
log.Error("Failed to update session table:", err)
ResponseUnauthorized401AccessTokenNotExist(w)
return token, err
}
}
vars := mux.Vars(r)
apiVer := vars["apiVersion"]
if apiVer != global.ApiVersionV1 {
log.Error("Uri is invalid")
ResponseNotFound404UriNotExist(w, r)
return token, err
}
return token, nil
}
func CheckUserPermission(token, method, module, dbname, tbname, pack string) (bool, error) {
if config.GetYamlConfig().OMC.RBACMode {
if module == "" {
module = "*"
}
if dbname == "" {
dbname = "*"
}
if tbname == "" {
tbname = "*"
}
exist, err := dborm.IsPermissionAllowed(token, method, module, dbname, tbname, pack)
if err != nil {
return false, err
}
if !exist {
return false, nil
}
}
return true, nil
}
func IsLocalhost(host string) bool {
if strings.Contains(host, "127.0.0.1") || strings.Contains(host, "::1") {
return true
}
return false
}
func CheckFrontValidRequest(w http.ResponseWriter, r *http.Request) (string, error) {
log.Debug("CheckFrontValidRequest processing... ")
var token string = ""
// var err error
// var ret bool
// // response 414-4 uri too long ? (optional)
// // todo ... ?
// if bytes.Count([]byte(r.RequestURI), nil) > config.GetUriMaxLenFromConfig() {
// err = errors.New("request Uri too long")
// log.Errorf("Request Uri too long: bytes=%d, MaxLen=%d", bytes.Count([]byte(r.RequestURI), nil), config.GetUriMaxLenFromConfig())
// ResponseRequestURITooLong414UriTooLong(w)
// return token, err
// }
// /*
// // check media type(content type) only support "application/json"
// // response 415-1
// if !IsVallidContentType(r) {
// err := errors.New("Invalid Content-Type")
// log.Error(err)
// ResponseUnsupportedMediaType415(w)
// return err
// }
// */
// // error processing ...
// // 401-1 response
// if config.GetYamlConfig().Auth.Token && !IsLocalhost(r.RemoteAddr) {
// token, ret = oauth.IsCarriedToken(r)
// if !ret {
// err = errors.New("accessToken is not carried")
// log.Error(err)
// ResponseUnauthorized401AccessTokenNotCarried(w)
// return token, err
// }
// // 401-2 response
// if !dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) {
// err = errors.New("accessToken fails or does not exist")
// log.Error(err)
// ResponseUnauthorized401AccessTokenNotExist(w)
// return token, err
// }
// if operType := GetOperationTypeFromHttpRequest(r); operType != "auto" {
// _, err = dborm.XormUpdateSessionShakeTime(token)
// if err != nil {
// log.Error("Failed to update session table:", err)
// ResponseUnauthorized401AccessTokenNotExist(w)
// return token, err
// }
// }
// }
// vars := mux.Vars(r)
// apiVer := vars["apiVersion"]
// if apiVer != global.ApiVersionV1 {
// err = errors.New("uri is invalid")
// log.Error(err)
// ResponseNotFound404UriNotExist(w, r)
// return token, err
// }
return token, nil
}
func CheckExtValidRequest(w http.ResponseWriter, r *http.Request) (string, error) {
log.Debug("CheckExtValidRequest processing... ")
var token string = ""
var err error
var ret bool
// error processing ...
// 401-1 response
if config.GetYamlConfig().Auth.Token {
token, ret = oauth.IsCarriedToken(r)
if !ret {
err = errors.New("accessToken is not carried")
log.Error(err)
ResponseUnauthorized401AccessTokenNotCarried(w)
return token, err
}
// 401-2 response
if !dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) {
err = errors.New("accessToken fails or does not exist")
log.Error(err)
ResponseUnauthorized401AccessTokenNotExist(w)
return token, err
}
if operType := GetOperationTypeFromHttpRequest(r); operType != "auto" {
_, err = dborm.XormUpdateSessionShakeTime(token)
if err != nil {
log.Error("Failed to update session table:", err)
ResponseUnauthorized401AccessTokenNotExist(w)
return token, err
}
}
}
vars := mux.Vars(r)
apiVer := vars["apiVersion"]
if apiVer != global.ApiVersionV1 {
err = errors.New("uri is invalid")
log.Error(err)
ResponseNotFound404UriNotExist(w, r)
return token, err
}
return token, nil
}
func ResponseStatusOK200Login(w http.ResponseWriter, token string) {
var oAuthResponse SucceedOAuthResponse
oAuthResponse.AccessToken = token
oAuthResponse.Expires = strconv.Itoa((int)(config.GetExpiresFromConfig()))
ResponseWithJson(w, http.StatusOK, oAuthResponse)
}
func ResponseStatusOK200Null(w http.ResponseWriter) {
response := NullResponse{""}
ResponseWithJson(w, http.StatusOK, response)
}
func ResponseStatusOK204NoContent(w http.ResponseWriter) {
ResponseWithJson(w, http.StatusNoContent, "")
}
func ResponseStatusOK201Accepted(w http.ResponseWriter) {
ResponseWithJson(w, http.StatusAccepted, "")
}
type SSORedirect struct {
User string `json:"user"`
Token string `json:"token"`
}
func ResponseRedirect(w http.ResponseWriter, redirectUrl, user, token string) {
w.Header().Set("Cache-Control", "must-revalidate, no-store")
w.Header().Set("Content-Type", " text/html;charset=UTF-8")
w.Header().Set("Location", redirectUrl) //跳转地址设置
//w.WriteHeader(http.StatusTemporaryRedirect) //重定向!
ssoRedirect := &SSORedirect{user, token}
ResponseWithJson(w, http.StatusTemporaryRedirect, *ssoRedirect)
}
func ResponseBadRequest400RmUIDsIsInvalid(w http.ResponseWriter, rmUIDs []string) {
errorMessage := ErrorMessage{"1", "rmUIDs is invalid:" + strings.Join(rmUIDs, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
}
func ResponseBadRequest400DuplicateSubId(w http.ResponseWriter, SubIds string) {
errorMessage := ErrorMessage{"2", "Duplicate with resource subscription id:" + SubIds}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
}
func ResponseBadRequest400DuplicateAlarmId(w http.ResponseWriter, AlarmIds string) {
errorMessage := ErrorMessage{"3", "Duplicate with alarm subscription id: " + AlarmIds}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
}
func ResponseBadRequest400IncorrectLogin(w http.ResponseWriter) {
errorMessage := ErrorMessage{"4", "incorrect username and password"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
}
func ResponseBadRequest400WrongParamValue(w http.ResponseWriter) {
errorMessage := ErrorMessage{"5", "wrong parameter value"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
}
func ResponseBadRequest400CMCALoginError(w http.ResponseWriter) {
errorMessage := ErrorMessage{"6", "CMCA centralized authentication login error"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
}
func ResponseBadRequest400InvalidJson(w http.ResponseWriter) {
errorMessage := ErrorMessage{"7", "invalid json format"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusUnauthorized, errorResponse)
}
func ResponseUnauthorized401AccessTokenNotCarried(w http.ResponseWriter) {
errorMessage := ErrorMessage{"1", "accessToken is not carried"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusUnauthorized, errorResponse)
}
func ResponseUnauthorized401AccessTokenNotExist(w http.ResponseWriter) {
errorMessage := ErrorMessage{"2", "accessToken fails or does not exist"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusUnauthorized, errorResponse)
}
func ResponseForbidden403NotPermission(w http.ResponseWriter) {
errorMessage := ErrorMessage{"1", "do not have the operation permissions"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusForbidden, errorResponse)
}
func ResponseForbidden403MultiLoginNotAllowed(w http.ResponseWriter) {
errorMessage := ErrorMessage{"2", "multiple logins are not allowed"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusForbidden, errorResponse)
}
func ResponseNotFound404UriNotExist(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
ResponseStatusOK204NoContent(w)
return
}
errorMessage := ErrorMessage{"1", "the requested URI does not exist"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func ResponseNotFound404UriNotExistExt(w http.ResponseWriter) {
errorMessage := ErrorMessage{"1", "the requested URI does not exist"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func CustomResponseNotFound404Handler() http.Handler {
return http.HandlerFunc(ResponseNotFound404UriNotExist)
}
func ResponseNotFound404NRMNotExist(w http.ResponseWriter, rmUIDs []string) {
errorMessage := ErrorMessage{"2", "rmUIDs does not exist: " + strings.Join(rmUIDs, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func ResponseNotFound404PMNotExist(w http.ResponseWriter, rmUIDs []string) {
errorMessage := ErrorMessage{"3", "rmUIDs does not exist: " + strings.Join(rmUIDs, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func ResponseNotFound404AlarmNotExist(w http.ResponseWriter, AlarmIds []string) {
errorMessage := ErrorMessage{"4", "alarmIds does not exist: " + strings.Join(AlarmIds, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func ResponseNotFound404GetSubscriptionNotExist(w http.ResponseWriter, SubIds []string) {
errorMessage := ErrorMessage{"5", "subscription id does not exist: " + strings.Join(SubIds, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func ResponseNotFound404DeleteSubscriptionNotExist(w http.ResponseWriter, SubIds []string) {
errorMessage := ErrorMessage{"6", "subscription id does not exist: " + strings.Join(SubIds, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func ResponseNotFound404GetAlarmSubscriptionNotExist(w http.ResponseWriter, SubIds []string) {
errorMessage := ErrorMessage{"7", "subscription id does not exist: " + strings.Join(SubIds, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func ResponseNotFound404DeleteAlarmSubscriptionNotExist(w http.ResponseWriter, SubIds []string) {
errorMessage := ErrorMessage{"8", "subscription id does not exist: " + strings.Join(SubIds, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotFound, errorResponse)
}
func ResponseMethodNotAllowed405(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
ResponseStatusOK204NoContent(w)
return
}
errorMessage := ErrorMessage{"1", "method not allowed"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusMethodNotAllowed, errorResponse)
}
func CustomResponseMethodNotAllowed405Handler() http.Handler {
return http.HandlerFunc(ResponseMethodNotAllowed405)
}
func ResponseNotAcceptable406MissingParam(w http.ResponseWriter) {
errorMessage := ErrorMessage{"1", "missing parameter: rmUIDs"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotAcceptable, errorResponse)
}
func ResponseNotAcceptable406ParamError(w http.ResponseWriter, errorParamsName []string) {
errorMessage := ErrorMessage{"2", "parameter name error: " + strings.Join(errorParamsName, ",")}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotAcceptable, errorResponse)
}
func ResponseNotAcceptable406QuerySQLError(w http.ResponseWriter) {
errorMessage := ErrorMessage{"3", "wrong or non-query SQL statement"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusNotAcceptable, errorResponse)
}
func ResponseRequestEntityTooLarge413SubscriptionExceed(w http.ResponseWriter, num int) {
errorMessage := ErrorMessage{"1", "the number of subscriptions greater than " + strconv.Itoa(num)}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusRequestEntityTooLarge, errorResponse)
}
func ResponseRequestEntityTooLarge413BodyToLarge(w http.ResponseWriter) {
errorMessage := ErrorMessage{"2", "the request entity too large"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusRequestEntityTooLarge, errorResponse)
}
func ResponseRequestURITooLong414NRMNumExceed(w http.ResponseWriter, num int) {
errorMessage := ErrorMessage{"1", "the number of NRM rmUIDs greater than " + strconv.Itoa(num)}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusRequestURITooLong, errorResponse)
}
func ResponseRequestURITooLong414AlarmNumExceed(w http.ResponseWriter, num int) {
errorMessage := ErrorMessage{"2", "the number of alarmIds greater than " + strconv.Itoa(num)}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusRequestURITooLong, errorResponse)
}
func ResponseRequestURITooLong414PMNumExceed(w http.ResponseWriter, num int) {
errorMessage := ErrorMessage{"3", "the number of PM rmUIDs greater than " + strconv.Itoa(num)}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusRequestURITooLong, errorResponse)
}
func ResponseRequestURITooLong414UriTooLong(w http.ResponseWriter) {
errorMessage := ErrorMessage{"3", "request URI too long"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusRequestURITooLong, errorResponse)
}
func ResponseUnsupportedMediaType415(w http.ResponseWriter) {
errorMessage := ErrorMessage{"1", "unsupported media type"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusUnsupportedMediaType, errorResponse)
}
func ResponseInternalServerError500NFConnectRefused(w http.ResponseWriter) {
errorMessage := ErrorMessage{"1", "internal server error, NF connnect refused"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusInternalServerError, errorResponse)
}
func ResponseInternalServerError500DatabaseOperationFailed(w http.ResponseWriter) {
errorMessage := ErrorMessage{"2", "internal server error, database opration failed"}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusInternalServerError, errorResponse)
}
func ResponseInternalServerError500ProcessError(w http.ResponseWriter, err error) {
em := fmt.Sprintf("internal server error: %v", err)
errorMessage := ErrorMessage{"3", em}
errorResponse := ErrorResponse{errorMessage}
ResponseWithJson(w, http.StatusInternalServerError, errorResponse)
}
func ResponseWithJson(w http.ResponseWriter, code int, payload interface{}) {
log.Trace("payload: ", payload)
response, _ := json.Marshal(payload)
SetResponseHeader(w)
w.WriteHeader(code)
w.Write(response)
log.Trace("Response Code:", code)
log.Trace("Response Body:", string(response))
}
func ResponseWithZip(w http.ResponseWriter, payload interface{}) {
response, _ := json.Marshal(payload)
SetResponseHeader(w)
w.WriteHeader(http.StatusOK)
w.Write(response)
log.Trace("Response Body:", string(response))
}
func TransportResponse(w http.ResponseWriter, code int, payload []byte) {
var tempBody, transBody interface{}
switch code {
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
json.Unmarshal(payload, &tempBody)
transBody = DataResponse{tempBody}
default:
json.Unmarshal(payload, &tempBody)
transBody = ErrorResponse{tempBody}
}
response, _ := json.Marshal(transBody)
log.Trace("transBody: ", transBody)
SetResponseHeader(w)
w.WriteHeader(code)
w.Write(response)
log.Trace("response: ", string(response))
}
func ResponseWithUnsortJson(w http.ResponseWriter, code int, payload map[string]interface{}) {
var om global.OrderedMap
om.Map = payload
response, _ := om.MarshalJson()
log.Trace("payload: ", payload)
SetResponseHeader(w)
w.WriteHeader(code)
w.Write(response)
log.Trace("response: ", string(response))
}
func ResponseErrorWithJson(w http.ResponseWriter, code int, nameValue interface{}) {
response := make(map[string]interface{})
response["error"] = nameValue
ResponseWithJson(w, code, response)
}
func SetCommonResponseHeader(w http.ResponseWriter) {
// 设置Vary头部
w.Header().Set("Vary", "Origin")
w.Header().Set("Keep-Alive", "timeout=5")
// To solve cross domain issue
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
w.Header().Set("Access-Control-Allow-Credentials", "true")
// 响应最大时间值
w.Header().Set("Access-Control-Max-Age", "31536000")
}
func SetResponseHeader(w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
SetCommonResponseHeader(w)
}
// Creates a new file upload http request with optional extra params
func ResponseUploadFile(w http.ResponseWriter, code int, params map[string]string, paramName, path string) {
file, err := os.Open(path)
if err != nil {
log.Errorf("Failed to open: %v", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile(paramName, filepath.Base(path))
if err != nil {
log.Error("Failed to CreateFormFile:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
_, err = io.Copy(part, file)
if err != nil {
log.Error("Failed to Copy:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
for key, val := range params {
_ = writer.WriteField(key, val)
}
err = writer.Close()
if err != nil {
log.Error("Failed to Close:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
SetCommonResponseHeader(w)
w.Header().Set("Content-Type", writer.FormDataContentType())
w.WriteHeader(code)
w.Write(body.Bytes())
}
func ResponseFile(w http.ResponseWriter, code int, filePath string) {
fileBytes, err := os.ReadFile(filePath)
if err != nil {
log.Error("Failed to ReadFile:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
SetCommonResponseHeader(w)
w.Header().Set("Content-Type", "application/octet-stream")
w.WriteHeader(code)
w.Write(fileBytes)
}
func ResponseFileWithNameAndMD5(w http.ResponseWriter, code int, fileName, path, md5Sum string) {
filePath := path + "/" + fileName
fileBytes, err := os.ReadFile(filePath)
if err != nil {
log.Error("Failed to ReadFile:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
SetCommonResponseHeader(w)
encodedFileName := url.PathEscape(fileName)
w.Header().Set("Content-Disposition", `attachment; filename="`+encodedFileName+`"`)
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("User-File", fileName)
w.Header().Set("MD5-Sum", md5Sum)
w.WriteHeader(code)
w.Write(fileBytes)
}
func ResponseHtmlContent(w http.ResponseWriter, code int, filePath string) {
htmlContent, err := os.ReadFile(filePath)
if err != nil {
log.Error("Failed to ReadFile:", err)
ResponseInternalServerError500ProcessError(w, err)
return
}
SetCommonResponseHeader(w)
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(code)
w.Write(htmlContent)
}
// RouterItem 路由项
type RouterItem struct {
Method string
Pattern string
Handler http.HandlerFunc
Middleware mux.MiddlewareFunc
}

View File

@@ -1,168 +0,0 @@
package session
import (
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"net/http"
"strconv"
"strings"
"sync"
"time"
"be.ems/lib/config"
"be.ems/lib/log"
"be.ems/lib/oauth"
)
// SessionMgr session manager
type SessManager struct {
name string
expires int64
lock sync.RWMutex
sessions map[string]*Session
}
// Session
type Session struct {
token string
time time.Time
permission []bool
values map[interface{}]interface{}
}
// NewSessionMgr create session manager
func NewSessManager(name string) *SessManager {
smgr := &SessManager{name: name, expires: (int64)(config.GetExpiresFromConfig()), sessions: make(map[string]*Session)}
go smgr.SessionGC()
return smgr
}
// NewSession create session
func (smgr *SessManager) NewSession(w http.ResponseWriter, r *http.Request, plist []bool) string {
smgr.lock.Lock()
defer smgr.lock.Unlock()
token := oauth.GenRandToken("omc") // Generate new token to session ID
session := &Session{token: token, time: time.Now(), permission: plist, values: make(map[interface{}]interface{})}
smgr.sessions[token] = session
return token
}
// EndSession
func (smgr *SessManager) EndSession(w http.ResponseWriter, r *http.Request) {
token := smgr.GetTokenFromHttpRequest(r)
smgr.lock.Lock()
defer smgr.lock.Unlock()
delete(smgr.sessions, token)
}
// Handshake session, restart session
func (smgr *SessManager) ShakeSession(token string) bool {
smgr.lock.Lock()
defer smgr.lock.Unlock()
for _, s := range smgr.sessions {
if token == s.token {
log.Debug("session time:", s.time)
s.time = time.Now()
return true
}
}
return false
}
// EndSessionByID end the session by session ID
func (smgr *SessManager) DeleteSession(token string) {
smgr.lock.Lock()
defer smgr.lock.Unlock()
delete(smgr.sessions, token)
}
// SetSessionValue set value fo session
func (smgr *SessManager) SetSessionValue(token string, key interface{}, value interface{}) error {
smgr.lock.Lock()
defer smgr.lock.Unlock()
if session, ok := smgr.sessions[token]; ok {
session.values[key] = value
return nil
}
return fmt.Errorf("invalid session ID")
}
// GetSessionValue get value fo session
func (smgr *SessManager) GetSessionValue(token string, key interface{}) (interface{}, error) {
smgr.lock.RLock()
defer smgr.lock.RUnlock()
if session, ok := smgr.sessions[token]; ok {
if val, ok := session.values[key]; ok {
return val, nil
}
}
return nil, fmt.Errorf("invalid session ID")
}
func (smgr *SessManager) GetTokenFromHttpRequest(r *http.Request) string {
for k, v := range r.Header {
if strings.ToLower(k) == "accesstoken" && len(v) != 0 {
log.Debug("AccessToken:", v[0])
return v[0]
}
}
return ""
}
// IsValidToken check token is valid or not
func (smgr *SessManager) IsValidToken(token string) bool {
smgr.lock.Lock()
defer smgr.lock.Unlock()
if _, ok := smgr.sessions[token]; ok {
return true
}
return false
}
// IsCarriedToken check token is carried
func (smgr *SessManager) IsCarriedToken(r *http.Request) (string, bool) {
token := smgr.GetTokenFromHttpRequest(r)
if token == "" {
return "", false
}
return token, true
}
// GetPermissionFromSession get permission from session by token
func (smgr *SessManager) GetPermissionFromSession(token string) []bool {
if s, ok := smgr.sessions[token]; ok {
return s.permission
}
return nil
}
// SessionGC maintain session
func (smgr *SessManager) SessionGC() {
smgr.lock.Lock()
defer smgr.lock.Unlock()
for token, session := range smgr.sessions {
if session.time.Unix()+smgr.expires < time.Now().Unix() {
delete(smgr.sessions, token)
}
}
time.AfterFunc(time.Duration(smgr.expires)*time.Second, func() { smgr.SessionGC() })
}
// NewSessionID generate unique ID
func (smgr *SessManager) NewSessionID() string {
b := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
nano := time.Now().UnixNano()
return strconv.FormatInt(nano, 10)
}
return base64.URLEncoding.EncodeToString(b)
}

View File

@@ -1,38 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAo8xNDB8tD9rEJhtTirwK8CxM0e+wcMT6fuDfTSgc/JRMjXIeM6B7
6Cw2lCSjwTME60nGZ8Yb0STXXuoc+WdEFcWaJVSlfeXzH4G/WCAsw3zxdwaYWnuavzwWFC
TX6wvUgI0Hh1eAgjusZOi1fDvzX8PLml8Lbjd8n6VFneZkVijHNxh1eL8Xq3yqCEGTenrS
4SBGImwIQidtT9LqFs2Ze3Hi5pBvuqq0Um8gtGwp6zd/sIzeG8LX5axBSZN10BrkW1bGC8
7sfpjJvadtvgiz0ZfxVDxd8eP8CgrKq+yQ0scfNB0j4ZOIP9Zwk6Q0fYQHxegPcMNr2v5P
IzHmDwTvDsHu3qyxGc74OVkAEd1o9OXiaSQ/fQXgvdUuSlugBUA3wx8Vlqa0om3fyY/XbX
LdqStmcVtKYfTiePX7UYc09YlYuFJycJxuf6i38Jek58fqp0NSH//ZWP/fXqwkwE8xUzEi
Jiq0c+wp7j5XMPFpMwmKViintJCS5C9nEQ+UIuMpAAAFiMzUaEPM1GhDAAAAB3NzaC1yc2
EAAAGBAKPMTQwfLQ/axCYbU4q8CvAsTNHvsHDE+n7g300oHPyUTI1yHjOge+gsNpQko8Ez
BOtJxmfGG9Ek117qHPlnRBXFmiVUpX3l8x+Bv1ggLMN88XcGmFp7mr88FhQk1+sL1ICNB4
dXgII7rGTotXw781/Dy5pfC243fJ+lRZ3mZFYoxzcYdXi/F6t8qghBk3p60uEgRiJsCEIn
bU/S6hbNmXtx4uaQb7qqtFJvILRsKes3f7CM3hvC1+WsQUmTddAa5FtWxgvO7H6Yyb2nbb
4Is9GX8VQ8XfHj/AoKyqvskNLHHzQdI+GTiD/WcJOkNH2EB8XoD3DDa9r+TyMx5g8E7w7B
7t6ssRnO+DlZABHdaPTl4mkkP30F4L3VLkpboAVAN8MfFZamtKJt38mP121y3akrZnFbSm
H04nj1+1GHNPWJWLhScnCcbn+ot/CXpOfH6qdDUh//2Vj/316sJMBPMVMxIiYqtHPsKe4+
VzDxaTMJilYop7SQkuQvZxEPlCLjKQAAAAMBAAEAAAGATRJTapG8zUn9o4SWIaBrcSkXGG
0000sMJuk+iPqH8R0CjEeXCGnKA6vSHpDC8KRF+0QidC/WZOl14XY9HelGMwxghJI4sG2j
oT6WvyuchHtkzsGurFyeqr7mEKJpanKNkdNKKJe2oxDbBDwvMP6wfG4PflqccUbwf9nvUO
XYbmYPntAGbkNUKt+kze+1Khti4IUkGwxEMoSEvdubRBGH13r17dEmkWnDIUqi0+JVMxVR
IsyVsfBTUAFmUu1ssPgFnD81z9G9OTic2A5zd+QDfXlJWbjJACtuM/4IotkZZ/M6rsVlYn
AY8Vqfs/8C53giSF5R4iiR29FIU3Luts9dJJQyQ94rXunK00iifyh18qisBKwh9rjxYn3J
wFeZeXzKRg/cLuY1Z74QBWjWzukadvu7dC9bWFZ2k3zKBPTodcpXr1QDwFT4mgEYAFXbQN
8RjFGZrhr2jbsnoM71QlcGv9RjxMPNep+BwnYvPSZ1Piu3nmQqNtysg6ur3ZEHJeLVAAAA
wHZ5m4TECDOgkL138faHQycfd9Yi/Yj1akSwVvtGpiPd35ir1bOp52H/Ea3ymDwh6PvOSk
NjpvwqCXSX5nIQWrQQiDHMKA4pCfAtzbJ68fhWmfzWUaWGIcrnhnoxXzMYgXS/Gp6fwqOf
5JH4jm3uM5knXLTz0E0WofYnLgDo6CAuANl9bSQDfPYh8tuNndoQd9190r+15uLhv/pIM7
MsZzifBrE2cgSBIunIERdQbD9JwNCeDPIrV8aQbOJDyuJDbwAAAMEA1nYx8GVZM/0cSZqG
V9C4i6debJEep2k91z7XvjFRZJrTYYZavWJPEUmmqNjsJg0Bdad4g3SdK2iJ4W5CHzDm2S
Zn08j7on/ybcD2c1ZnXbwKrzPXRymc62xxwSDD95m/R5cSvN/Pmy57QfymQNPaNXMkhKq1
nzF56bljW0FHVFnrgUHpbLUOEc0QHXO4d2PaUNptLVxquOJI/VDW2GKKQWaIsdYKPJEDO9
GBe/LaUDzodd1s1isly86DLEgT2HwbAAAAwQDDhgO/kOI1N0jMOpE5gotcrhQc353jrP16
mKOdcp9MVHiioRybsyRdnbDIYKXbQz2ZRwmz2RBh55uPQjLcfi82GlIm2rdTL8KzP9vLpc
WAbZ7dcbv1lLyIlr4Yf33LgAChxJQTGNad771cwYFrtwTYk16O0Mdv302L0DgDTJUvhzJb
0ZuIk2nmzumSH1pOYmZl8Oa+UM7YSZNCWEpM7/S5laNISQ6dF/yy6Del2sQk/1/JCMUK0d
GLCkyCiaW9igsAAAASc2ltb25Ac2ltb256aGFuZ3N6AQ==
-----END OPENSSH PRIVATE KEY-----

View File

@@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCjzE0MHy0P2sQmG1OKvArwLEzR77BwxPp+4N9NKBz8lEyNch4zoHvoLDaUJKPBMwTrScZnxhvRJNde6hz5Z0QVxZolVKV95fMfgb9YICzDfPF3Bphae5q/PBYUJNfrC9SAjQeHV4CCO6xk6LV8O/Nfw8uaXwtuN3yfpUWd5mRWKMc3GHV4vxerfKoIQZN6etLhIEYibAhCJ21P0uoWzZl7ceLmkG+6qrRSbyC0bCnrN3+wjN4bwtflrEFJk3XQGuRbVsYLzux+mMm9p22+CLPRl/FUPF3x4/wKCsqr7JDSxx80HSPhk4g/1nCTpDR9hAfF6A9ww2va/k8jMeYPBO8Owe7erLEZzvg5WQAR3Wj05eJpJD99BeC91S5KW6AFQDfDHxWWprSibd/Jj9dtct2pK2ZxW0ph9OJ49ftRhzT1iVi4UnJwnG5/qLfwl6Tnx+qnQ1If/9lY/99erCTATzFTMSImKrRz7CnuPlcw8WkzCYpWKKe0kJLkL2cRD5Qi4yk= simon@simonzhangsz

View File

@@ -1,38 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAo8xNDB8tD9rEJhtTirwK8CxM0e+wcMT6fuDfTSgc/JRMjXIeM6B7
6Cw2lCSjwTME60nGZ8Yb0STXXuoc+WdEFcWaJVSlfeXzH4G/WCAsw3zxdwaYWnuavzwWFC
TX6wvUgI0Hh1eAgjusZOi1fDvzX8PLml8Lbjd8n6VFneZkVijHNxh1eL8Xq3yqCEGTenrS
4SBGImwIQidtT9LqFs2Ze3Hi5pBvuqq0Um8gtGwp6zd/sIzeG8LX5axBSZN10BrkW1bGC8
7sfpjJvadtvgiz0ZfxVDxd8eP8CgrKq+yQ0scfNB0j4ZOIP9Zwk6Q0fYQHxegPcMNr2v5P
IzHmDwTvDsHu3qyxGc74OVkAEd1o9OXiaSQ/fQXgvdUuSlugBUA3wx8Vlqa0om3fyY/XbX
LdqStmcVtKYfTiePX7UYc09YlYuFJycJxuf6i38Jek58fqp0NSH//ZWP/fXqwkwE8xUzEi
Jiq0c+wp7j5XMPFpMwmKViintJCS5C9nEQ+UIuMpAAAFiMzUaEPM1GhDAAAAB3NzaC1yc2
EAAAGBAKPMTQwfLQ/axCYbU4q8CvAsTNHvsHDE+n7g300oHPyUTI1yHjOge+gsNpQko8Ez
BOtJxmfGG9Ek117qHPlnRBXFmiVUpX3l8x+Bv1ggLMN88XcGmFp7mr88FhQk1+sL1ICNB4
dXgII7rGTotXw781/Dy5pfC243fJ+lRZ3mZFYoxzcYdXi/F6t8qghBk3p60uEgRiJsCEIn
bU/S6hbNmXtx4uaQb7qqtFJvILRsKes3f7CM3hvC1+WsQUmTddAa5FtWxgvO7H6Yyb2nbb
4Is9GX8VQ8XfHj/AoKyqvskNLHHzQdI+GTiD/WcJOkNH2EB8XoD3DDa9r+TyMx5g8E7w7B
7t6ssRnO+DlZABHdaPTl4mkkP30F4L3VLkpboAVAN8MfFZamtKJt38mP121y3akrZnFbSm
H04nj1+1GHNPWJWLhScnCcbn+ot/CXpOfH6qdDUh//2Vj/316sJMBPMVMxIiYqtHPsKe4+
VzDxaTMJilYop7SQkuQvZxEPlCLjKQAAAAMBAAEAAAGATRJTapG8zUn9o4SWIaBrcSkXGG
0000sMJuk+iPqH8R0CjEeXCGnKA6vSHpDC8KRF+0QidC/WZOl14XY9HelGMwxghJI4sG2j
oT6WvyuchHtkzsGurFyeqr7mEKJpanKNkdNKKJe2oxDbBDwvMP6wfG4PflqccUbwf9nvUO
XYbmYPntAGbkNUKt+kze+1Khti4IUkGwxEMoSEvdubRBGH13r17dEmkWnDIUqi0+JVMxVR
IsyVsfBTUAFmUu1ssPgFnD81z9G9OTic2A5zd+QDfXlJWbjJACtuM/4IotkZZ/M6rsVlYn
AY8Vqfs/8C53giSF5R4iiR29FIU3Luts9dJJQyQ94rXunK00iifyh18qisBKwh9rjxYn3J
wFeZeXzKRg/cLuY1Z74QBWjWzukadvu7dC9bWFZ2k3zKBPTodcpXr1QDwFT4mgEYAFXbQN
8RjFGZrhr2jbsnoM71QlcGv9RjxMPNep+BwnYvPSZ1Piu3nmQqNtysg6ur3ZEHJeLVAAAA
wHZ5m4TECDOgkL138faHQycfd9Yi/Yj1akSwVvtGpiPd35ir1bOp52H/Ea3ymDwh6PvOSk
NjpvwqCXSX5nIQWrQQiDHMKA4pCfAtzbJ68fhWmfzWUaWGIcrnhnoxXzMYgXS/Gp6fwqOf
5JH4jm3uM5knXLTz0E0WofYnLgDo6CAuANl9bSQDfPYh8tuNndoQd9190r+15uLhv/pIM7
MsZzifBrE2cgSBIunIERdQbD9JwNCeDPIrV8aQbOJDyuJDbwAAAMEA1nYx8GVZM/0cSZqG
V9C4i6debJEep2k91z7XvjFRZJrTYYZavWJPEUmmqNjsJg0Bdad4g3SdK2iJ4W5CHzDm2S
Zn08j7on/ybcD2c1ZnXbwKrzPXRymc62xxwSDD95m/R5cSvN/Pmy57QfymQNPaNXMkhKq1
nzF56bljW0FHVFnrgUHpbLUOEc0QHXO4d2PaUNptLVxquOJI/VDW2GKKQWaIsdYKPJEDO9
GBe/LaUDzodd1s1isly86DLEgT2HwbAAAAwQDDhgO/kOI1N0jMOpE5gotcrhQc353jrP16
mKOdcp9MVHiioRybsyRdnbDIYKXbQz2ZRwmz2RBh55uPQjLcfi82GlIm2rdTL8KzP9vLpc
WAbZ7dcbv1lLyIlr4Yf33LgAChxJQTGNad771cwYFrtwTYk16O0Mdv302L0DgDTJUvhzJb
0ZuIk2nmzumSH1pOYmZl8Oa+UM7YSZNCWEpM7/S5laNISQ6dF/yy6Del2sQk/1/JCMUK0d
GLCkyCiaW9igsAAAASc2ltb25Ac2ltb256aGFuZ3N6AQ==
-----END OPENSSH PRIVATE KEY-----

View File

@@ -1,185 +0,0 @@
package config
import (
"flag"
"fmt"
"os"
"strings"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/sshsvc/logmml"
"gopkg.in/yaml.v3"
)
type DbConfig struct {
Type string `yaml:"type"`
User string `yaml:"user"`
Password string `yaml:"password"`
Host string `yaml:"host"`
Port string `yaml:"port"`
Name string `yaml:"name"`
ConnParam string `yaml:"connParam,omitempty"`
Backup string `yaml:"backup"`
}
// Yaml struct of config
type YamlConfig struct {
Logger struct {
File string `yaml:"file"`
Level string `yaml:"level"`
Duration int `yaml:"duration"`
Count int `yaml:"count"`
} `yaml:"logger"`
Logmml struct {
File string `yaml:"file"`
Duration int `yaml:"duration"`
Count int `yaml:"count"`
Level string `yaml:"level"`
} `yaml:"logmml"`
Sshd struct {
ListenAddr string `yaml:"listenAddr"`
ListenPort uint16 `yaml:"listenPort"`
PrivateKey string `yaml:"privateKey"`
MaxConnNum int `yaml:"maxConnNum"`
Timeout uint16 `yaml:"timeout"`
Session string `yaml:"session"`
MmlHome string `yaml:"mmlHome"`
UserName string `yaml:"userName"`
Password string `yaml:"password"`
AuthType string `yaml:"authType"`
TagNE string `yaml:"tagNE"`
} `yaml:"sshd"`
TelnetServer struct {
ListenAddr string `yaml:"listenAddr"`
ListenPort uint16 `yaml:"listenPort"`
MaxConnNum int `yaml:"maxConnNum"`
Timeout uint16 `yaml:"timeout"`
Session string `yaml:"session"`
MmlHome string `yaml:"mmlHome"`
UserName string `yaml:"userName"`
Password string `yaml:"password"`
AuthType string `yaml:"authType"`
TagNE string `yaml:"tagNE"`
} `yaml:"telnetServer"`
SNMPServer struct {
ListenAddr string `yaml:"listenAddr"`
ListenPort uint16 `yaml:"listenPort"`
UserName string `yaml:"userName"`
AuthPass string `yaml:"authPass"`
AuthProto string `yaml:"authProto"`
PrivPass string `yaml:"privPass"`
PrivProto string `yaml:"privProto"`
EngineID string `yaml:"engineID"`
TrapPort uint16 `yaml:"trapPort"`
TrapListen bool `yaml:"trapListen"`
TrapBool bool `yaml:"trapBool"`
TrapTick uint16 `yaml:"trapTick"`
TimeOut uint16 `yaml:"timeOut"`
TrapTarget string `yaml:"trapTarget"`
} `yaml:"snmpServer"`
Database DbConfig `yaml:"database"`
OMC struct {
HttpUri string `yaml:"httpUri"`
UserCrypt string `yaml:"userCrypt"`
} `yaml:"omc"`
}
var yamlConfig YamlConfig = NewYamlConfig()
// set default value for yaml config
func NewYamlConfig() YamlConfig {
return YamlConfig{
Database: DbConfig{
Type: "mysql",
ConnParam: "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True",
},
}
}
func ReadConfig(configFile string) {
yamlFile, err := os.ReadFile(configFile)
if err != nil {
fmt.Println("Read yaml config file error:", err)
os.Exit(2)
}
err = yaml.Unmarshal(yamlFile, &yamlConfig)
if err != nil {
fmt.Println("Unmarshal error:", err)
os.Exit(3)
}
}
func GetYamlConfig() *YamlConfig {
return &yamlConfig
}
func GetLogLevel() log.LogLevel {
var logLevel log.LogLevel
switch strings.ToLower(yamlConfig.Logger.Level) {
case "trace":
logLevel = log.LOG_TRACE
case "info":
logLevel = log.LOG_INFO
case "debug":
logLevel = log.LOG_DEBUG
case "warn":
logLevel = log.LOG_WARN
case "error":
logLevel = log.LOG_ERROR
case "fatal":
logLevel = log.LOG_FATAL
case "off":
logLevel = log.LOG_OFF
default:
logLevel = log.LOG_DEBUG
}
return logLevel
}
func GetLogMmlLevel() logmml.LogLevel {
var logLevel logmml.LogLevel
switch strings.ToLower(yamlConfig.Logmml.Level) {
case "cmd", "command":
logLevel = logmml.LOG_CMD
case "ret", "result":
logLevel = logmml.LOG_RET
default:
logLevel = logmml.LOG_CMD
}
return logLevel
}
func GetDefaultUserAgent() string {
return "OMC-sshsvc/" + global.Version
}
const DefaultConfigFile = "./etc/sshsvc.yaml"
func init() {
cfile := flag.String("c", DefaultConfigFile, "config file")
pv := flag.Bool("v", false, "print version")
pversion := flag.Bool("version", false, "print version")
ph := flag.Bool("h", false, "print help")
phelp := flag.Bool("help", false, "print help")
flag.Parse()
if *pv || *pversion {
fmt.Printf("OMC sshsvc version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
os.Exit(0)
}
if *ph || *phelp {
flag.Usage()
os.Exit(0)
}
ReadConfig(*cfile)
}

View File

@@ -1,161 +0,0 @@
package dborm
import (
"database/sql"
"fmt"
"time"
"be.ems/lib/log"
_ "github.com/go-sql-driver/mysql"
"xorm.io/xorm"
"xorm.io/xorm/core"
)
const (
TableNameMeasureTask = "measure_task"
TableNameNeInfo = "ne_info"
)
type Menu struct {
Id int `json:"id"`
Title string `json:"title"`
Icon string `json:"icon"`
Href string `json:"href"`
ParentId int `json:"parent_id"`
Remark int `json:"remark"`
}
type DatabaseClient struct {
dbType string
dbUrl string
dbConnMaxLifetime time.Duration
dbMaxIdleConns int
dbMaxOpenConns int
IsShowSQL bool
XEngine *xorm.Engine
}
var DbClient DatabaseClient
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
DbClient.dbType = dbType
DbClient.dbConnMaxLifetime = 0
DbClient.dbMaxIdleConns = 0
DbClient.dbMaxOpenConns = 0
if log.GetLevel() == log.LOG_TRACE {
DbClient.IsShowSQL = true
}
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
var err error
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
if err != nil {
log.Error("Failed to connet database:", err)
return err
}
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
DbClient.XEngine.DatabaseTZ = time.Local // 必须
DbClient.XEngine.TZLocation = time.Local // 必须
if DbClient.IsShowSQL {
DbClient.XEngine.ShowSQL(true)
}
xEngine = DbClient.XEngine
return nil
}
// func InitDbClient() error {
// db := config.GetYamlConfig().Database
// DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", db.User, db.Password, db.Host, db.Port, db.Name)
// DbClient.dbType = db.Type
// DbClient.dbConnMaxLifetime = 0
// DbClient.dbMaxIdleConns = 0
// DbClient.dbMaxOpenConns = 0
// if log.GetLevel() == log.LOG_TRACE {
// DbClient.IsShowSQL = true
// }
// log.Debugf("dbType:%s dbUrl:%s:******@tcp(%s:%s)/%s", DbClient.dbType, db.User, db.Host, db.Port, db.Name)
// var err error
// DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
// if err != nil {
// log.Error("Failed to connet database:", err)
// return err
// }
// DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
// DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
// DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
// if DbClient.IsShowSQL {
// DbClient.XEngine.ShowSQL(true)
// }
// xEngine = DbClient.XEngine
// return nil
// }
var xEngine *xorm.Engine
func XormConnectDatabase(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) (*xorm.Engine, error) {
sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
dbUser, dbPassword, dbHost, dbPort, dbName)
log.Debugf("dbType:%s Connect to:%s:******@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
dbType, dbUser, dbHost, dbPort, dbName)
var err error
xEngine, err = xorm.NewEngine(dbType, sqlStr) //1、Create xorm engine
if err != nil {
log.Error("Failed to connect database:", err)
return nil, err
}
if log.GetLevel() == log.LOG_TRACE {
xEngine.ShowSQL(true)
}
return xEngine, nil
}
func XCoreDB() *core.DB {
return xEngine.DB()
}
func XEngDB() *xorm.Engine {
return xEngine
}
type Session struct {
Id int `json:"id" xorm:"pk 'id' autoincr"`
AccountId string `json:"accountId" xorm:"account_id"`
Name string `json:"name" xorm:"name"`
Host string `json:"host" xorm:"host"`
AccessToken string `json:"accessToken" xorm:"access_token"`
Expires uint32 `json:"expires" xorm:"expires"`
Status string `json:"status" xorm:"status"`
LoginTime string `json:"loginTime" xorm:"-"`
ShakeTime sql.NullTime `son:"shakeTime" xorm:"shake_time"`
LogoutTime sql.NullTime `json:"logoutTime" xorm:"logout_time"`
}
// XormUpdateSession update session
func XormLogoutUpdateSession(token string) (Session, error) {
log.Info("XormLogoutUpdateSession processing... ")
session := Session{Status: "offline", AccessToken: token}
session.LogoutTime.Valid = true
session.LogoutTime.Time = time.Now()
xSession := xEngine.NewSession()
defer xSession.Close()
_, err := xSession.Table("session").Where("access_token = ?", token).Update(session)
xSession.Commit()
// 查询记录返回
if err == nil {
session := Session{}
_, err = xSession.Table("session").Where("access_token = ?", token).Get(&session)
return session, err
}
return session, err
}

View File

@@ -1,89 +0,0 @@
# file: log file name
# level: /trace/debug/info/warn/error/fatal, default: debug
# duration: rotation time with xx hours, example: 1/12/24 hours
# count: rotation count of log, default is 30 rotation
logger:
file: d:/omc.git/be.ems/sshsvc/log/sshsvc.log
level: trace
duration: 24
count: 30
# file: MML log file name
# duration: rotation time with xx hours, example: 1/12/24 hours
# count: rotation count of log, default is 30 rotation
# level: cmd/ret log cmd/log cmd & result
logmml:
file: d:/omc.git/be.ems/sshsvc/mmllog/omcmml.log
duration: 24
count: 30
level: ret
# ssh service listen ipv4/v6 and port, support multiple routines
# ip: 0.0.0.0 or ::0, support IPv4/v6
# session: single/multiple session for one user
# authType: local/radius
sshd:
listenAddr: 0.0.0.0
listenPort: 32222
privateKey: ./.ssh/id_rsa
maxConnNum: 2
timeout: 1800
session: multiple
mmlHome: ./mmlhome
userName: manager
password: pass123
authType: local
tagNE: hlr
# authType: local/omc
telnetServer:
listenAddr: 0.0.0.0
listenPort: 32323
maxConnNum: 2
timeout: 1800
session: multiple
mmlHome: ./mmlhome
userName: manager
password: pass123
authType: local
tagNE: hlr
# authproto: NoAuth/MD5/SHA
# privProto: NoPriv/DES/AES/AES192/AES256
snmpServer:
listenAddr: '[::]'
listenPort: 34957
userName: manager
authPass: pass123
authproto: MD5
privPass: "3F2A1B4C5D6E7F8A9B0C1D2E3F4A5B6C7D8E9F0A1B2C3D4E"
privProto: DES
#engineID: "800007db03360102101101"
engineID: "8000000004323030313a6462383a3a39313636"
trapPort: 34958
trapListen: false
trapBool: false
trapTick: 60
timeOut: 5
trapTarget: "2001:db8::9219"
database:
type: mysql
user: administrator
password: "*86#ROtartsinim"
host: 192.168.13.117
port: 3306
name: OMC_PUB
connParam: charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True
omc:
httpUri: http://127.0.0.1:3040
userCrypt: bcrypt
ne:
port: 4100
sleep: 200
user: admin
password: admin

View File

@@ -1,187 +0,0 @@
// logger for omc/ems
package logmml
import (
"fmt"
"io"
"log"
)
// LogLevel defines a log level
type LogLevel int
// enum all LogLevels
const (
// following level also match syslog.Priority value
LOG_RET LogLevel = iota
LOG_CMD
LOG_OFF
LOG_NODEF
)
// default log options
const (
DEFAULT_LOG_PREFIX = "omc:mml"
DEFAULT_LOG_FLAG = log.Ldate | log.Ltime | log.Lmsgprefix
DEFAULT_LOG_LEVEL = LOG_CMD
DEFAULT_CALL_DEPTH = 0
)
// Logger is a logger interface
type Logger interface {
Ret(v ...interface{})
Retf(format string, v ...interface{})
Cmd(v ...interface{})
Cmdf(format string, v ...interface{})
Level() LogLevel
LevelString() string
SetLevel(l LogLevel)
}
var _ Logger = DiscardLogger{}
// DiscardLogger don't log implementation for ILogger
type DiscardLogger struct{}
// Trace empty implementation
func (DiscardLogger) Ret(v ...interface{}) {}
// Tracef empty implementation
func (DiscardLogger) Retf(format string, v ...interface{}) {}
// Debug empty implementation
func (DiscardLogger) Cmd(v ...interface{}) {}
// Debugf empty implementation
func (DiscardLogger) Cmdf(format string, v ...interface{}) {}
// Level empty implementation
func (DiscardLogger) Level() LogLevel {
return LOG_NODEF
}
// Level empty implementation
func (DiscardLogger) LevelString() string {
return ""
}
// SetLevel empty implementation
func (DiscardLogger) SetLevel(l LogLevel) {}
// EmsLogger is the default implment of ILogger
type MMLLogger struct {
RET *log.Logger
CMD *log.Logger
level LogLevel
levelString []string
//depth int
}
var _ Logger = &MMLLogger{}
// NewEmsLogger2 let you customrize your logger prefix and flag
func NewMmlLogger2(out io.Writer, prefix string, flag int) *MMLLogger {
return NewMmlLogger3(out, prefix, flag, DEFAULT_LOG_LEVEL)
}
// NewEmsLogger3 let you customrize your logger prefix and flag and logLevel
func NewMmlLogger3(out io.Writer, prefix string, flag int, l LogLevel) *MMLLogger {
return &MMLLogger{
RET: log.New(out, fmt.Sprintf("[%s] [ret]: ", prefix), flag),
CMD: log.New(out, fmt.Sprintf("[%s] [cmd]: ", prefix), flag),
level: l,
levelString: []string{"ret", "cmd"},
//depth: DEFAULT_CALL_DEPTH,
}
}
// Trace implement ILogger
func (s *MMLLogger) Ret(v ...interface{}) {
if s.level <= LOG_RET {
//_ = s.RET.Output(s.depth, fmt.Sprintln(v...))
_ = s.RET.Output(0, fmt.Sprintln(v...))
}
}
// Tracef implement ILogger
func (s *MMLLogger) Retf(format string, v ...interface{}) {
if s.level <= LOG_RET {
_ = s.RET.Output(0, fmt.Sprintf(format, v...))
}
}
// Debug implement ILogger
func (s *MMLLogger) Cmd(v ...interface{}) {
if s.level <= LOG_CMD {
_ = s.CMD.Output(0, fmt.Sprintln(v...))
}
}
// Debugf implement ILogger
func (s *MMLLogger) Cmdf(format string, v ...interface{}) {
if s.level <= LOG_CMD {
_ = s.CMD.Output(0, fmt.Sprintf(format, v...))
}
}
// Info implement ILogger
// Level implement ILogger
func (s *MMLLogger) Level() LogLevel {
return s.level
}
// Level implement ILogger
func (s *MMLLogger) LevelString() string {
return s.levelString[s.level]
}
// SetLevel implement ILogger
func (s *MMLLogger) SetLevel(l LogLevel) {
s.level = l
}
var Elogger Logger
func InitMmlLogger(logFile string, period int, count int, prefix string, logLevel LogLevel) {
logWriter := getLogWriter(logFile, period, count)
Elogger = NewMmlLogger3(logWriter, prefix, DEFAULT_LOG_FLAG, logLevel)
fmt.Printf("logFile=%s, period=%d, count=%d, prefix=%s, logLevel=%s\n", logFile, period, count, prefix, GetLevelString())
}
// Trace implement ILogger
func Ret(v ...interface{}) {
Elogger.Ret(v...)
}
// Tracef implement ILogger
func Retf(format string, v ...interface{}) {
Elogger.Retf(format, v...)
}
// Debug implement ILogger
func Cmd(v ...interface{}) {
Elogger.Cmd(v...)
}
// Debugf implement ILogger
func Cmdf(format string, v ...interface{}) {
Elogger.Cmdf(format, v...)
}
// Level implement ILogger
func GetLevel() LogLevel {
return Elogger.Level()
}
// Level implement ILogger
func GetLevelString() string {
return Elogger.LevelString()
}
// SetLevel implement ILogger
func SetLevel(l LogLevel) {
Elogger.SetLevel(l)
}

View File

@@ -1,71 +0,0 @@
package logmml
import (
"io"
"time"
rotatelogs "github.com/lestrrat/go-file-rotatelogs"
)
type WriteSyncer interface {
io.Writer
Sync() error
}
// 得到LogWriter
func getLogWriter(filePath string, period, count int) WriteSyncer {
warnIoWriter := getWriter(filePath, period, count)
return addSync(warnIoWriter)
}
// 日志文件切割
func getWriter(filename string, period, count int) io.Writer {
// 保存日志count天每period小时分割一次日志
duration := time.Hour * time.Duration(period)
var logfile string
if period >= 24 {
logfile = filename + "-%Y%m%d"
} else {
logfile = filename + "-%Y%m%d%H"
}
hook, err := rotatelogs.New(
logfile,
rotatelogs.WithLinkName(filename),
// rotatelogs.WithMaxAge(duration),
rotatelogs.WithRotationCount(count),
rotatelogs.WithRotationTime(duration),
rotatelogs.WithLocation(time.Local),
)
//保存日志30天每1分钟分割一次日志
/*
hook, err := rotatelogs.New(
filename+"_%Y%m%d%H%M.log",
rotatelogs.WithLinkName(filename),
rotatelogs.WithMaxAge(time.Hour*24*30),
rotatelogs.WithRotationTime(time.Minute*1),
)
*/
if err != nil {
panic(err)
}
return hook
}
func addSync(w io.Writer) WriteSyncer {
switch w := w.(type) {
case WriteSyncer:
return w
default:
return writerWrapper{w}
}
}
type writerWrapper struct {
io.Writer
}
func (w writerWrapper) Sync() error {
return nil
}

View File

@@ -1,18 +0,0 @@
# Makefile for OMC-OMC-crontask project
PROJECT = OMC
VERSION = 2.2503.2
LIBDIR = be.ems/lib
BINNAME = sshsvc
.PHONY: build $(BINNAME)
build $(BINNAME):
go build -o $(BINNAME) -v -ldflags "-s -w -X '$(LIBDIR)/global.Version=$(VERSION)' \
-X '$(LIBDIR)/global.BuildTime=`date`' \
-X '$(LIBDIR)/global.GoVer=`go version`'"
run: $(BINNAME)
./$(BINNAME)
clean:
rm ./$(BINNAME)

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -1,656 +0,0 @@
--
-- CINTEL-MIB.my
-- MIB generated by MG-SOFT Visual MIB Builder Version 7.0 Build 209
-- Friday, December 16, 2011 at 15:52:13
--
CINTEL-MIB DEFINITIONS ::= BEGIN
IMPORTS
enterprises, TimeTicks, MODULE-IDENTITY
FROM SNMPv2-SMI
TEXTUAL-CONVENTION
FROM SNMPv2-TC;
-- 1.3.6.1.4.1.1379.2
cintelSS MODULE-IDENTITY
LAST-UPDATED "201706041222Z" -- June 04, 2017 at 12:22 GMT
ORGANIZATION
"CINTEL"
CONTACT-INFO
"cintel
support@cintel.com.cn"
DESCRIPTION
"The MIB module for cintel's Softswitch products."
REVISION "201706041223Z" -- June 04, 2017 at 12:23 GMT
DESCRIPTION
"This is the first release version of the MIB"
::= { cintelNS 2 }
--
-- Type definitions
--
AdminStateChoices ::= INTEGER
{
locked(0),
unlocked(1),
shutDown(2)
}
OperStateChoices ::= INTEGER
{
disable(0),
enable(1)
}
AvailStateChoices ::= INTEGER
{
inTest(0),
failed(1),
powerOff(2),
offLine(3),
onLine(4),
dependency(5),
degraded(6),
notInstalled(7)
}
--
-- Textual conventions
--
-- TEXTUAL-CONVENTION MACRO ::=
-- BEGIN
-- TYPE NOTATION ::=
-- DisplayPart
-- "STATUS" Status
-- "DESCRIPTION" Text
-- ReferPart
-- "SYNTAX" Syntax
--
-- VALUE NOTATION ::=
-- value(VALUE Syntax)
--
-- DisplayPart ::=
-- "DISPLAY-HINT" Text
-- | empty
--
-- Status ::=
-- "current"
-- | "deprecated"
-- | "obsolete"
--
-- ReferPart ::=
-- "REFERENCE" Text
-- | empty
--
-- -- -- uses the NVT ASCII character set
-- Text ::= """" string """"
--
-- Syntax ::=
-- type(ObjectSyntax)
-- | "BITS" "{" Kibbles "}"
-- Kibbles ::=
-- Kibble
-- | Kibbles "," Kibble
-- Kibble ::=
-- identifier "(" nonNegativeNumber ")"
-- END
DisplayString8 ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"8a"
STATUS current
DESCRIPTION
"Represents textual information taken from the NVT ASCII
character set, as defined in pages 4, 10-11 of RFC 854.
To summarize RFC 854, the NVT ASCII repertoire specifies:
- the use of character codes 0-127 (decimal)
- the graphics characters (32-126) are interpreted as
US ASCII
- NUL, LF, CR, BEL, BS, HT, VT and FF have the special
meanings specified in RFC 854
- the other 25 codes have no standard interpretation
- the sequence 'CR LF' means newline
- the sequence 'CR NUL' means carriage-return
- an 'LF' not preceded by a 'CR' means moving to the
same column on the next line.
- the sequence 'CR x' for any x other than LF or NUL is
illegal. (Note that this also means that a string may
end with either 'CR LF' or 'CR NUL', but not with CR.)
Any object defined using this syntax may not exceed 255
characters in length."
SYNTAX OCTET STRING (SIZE (0..8))
DisplayString16 ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"16a"
STATUS current
DESCRIPTION
"A version of DisplayString that contains only 16 characters most."
SYNTAX OCTET STRING (SIZE (0..16))
DisplayString32 ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"32a"
STATUS current
DESCRIPTION
"A version of DisplayString that contains only 32 characters most."
SYNTAX OCTET STRING (SIZE (0..32))
DisplayString64 ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"64a"
STATUS current
DESCRIPTION
"A version of DisplayString that contains only 64 characters most."
SYNTAX OCTET STRING (SIZE (0..64))
DisplayString ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"255a"
STATUS current
DESCRIPTION
"A version of DisplayString that contains only 255 characters most."
SYNTAX OCTET STRING (SIZE (0..255))
RowStatus ::= TEXTUAL-CONVENTION
STATUS current
DESCRIPTION
"The RowStatus textual convention is used to manage the
creation and deletion of conceptual rows, and is used as the
value of the SYNTAX clause for the status column of a
conceptual row (as described in Section 7.7.1 of [2].)
The status column has six defined values:
- `active', which indicates that the conceptual row is
available for use by the managed device;
- `notInService', which indicates that the conceptual
row exists in the agent, but is unavailable for use by
the managed device (see NOTE below);
- `notReady', which indicates that the conceptual row
exists in the agent, but is missing information
necessary in order to be available for use by the
managed device;
- `createAndGo', which is supplied by a management
station wishing to create a new instance of a
conceptual row and to have its status automatically set
to active, making it available for use by the managed
device;
- `createAndWait', which is supplied by a management
station wishing to create a new instance of a
conceptual row (but not make it available for use by
the managed device); and,
- `destroy', which is supplied by a management station
wishing to delete all of the instances associated with
an existing conceptual row.
Whereas five of the six values (all except `notReady') may
be specified in a management protocol set operation, only
three values will be returned in response to a management
protocol retrieval operation: `notReady', `notInService' or
`active'. That is, when queried, an existing conceptual row
has only three states: it is either available for use by
the managed device (the status column has value `active');
it is not available for use by the managed device, though
the agent has sufficient information to make it so (the
status column has value `notInService'); or, it is not
available for use by the managed device, and an attempt to
make it so would fail because the agent has insufficient
information (the state column has value `notReady').
NOTE WELL
This textual convention may be used for a MIB table,
irrespective of whether the values of that table's
conceptual rows are able to be modified while it is
active, or whether its conceptual rows must be taken
out of service in order to be modified. That is, it is
the responsibility of the DESCRIPTION clause of the
status column to specify whether the status column must
not be `active' in order for the value of some other
column of the same conceptual row to be modified. If
such a specification is made, affected columns may be
changed by an SNMP set PDU if the RowStatus would not
be equal to `active' either immediately before or after
processing the PDU. In other words, if the PDU also
contained a varbind that would change the RowStatus
value, the column in question may be changed if the
RowStatus was not equal to `active' as the PDU was
received, or if the varbind sets the status to a value
other than 'active'.
Also note that whenever any elements of a row exist, the
RowStatus column must also exist.
To summarize the effect of having a conceptual row with a
status column having a SYNTAX clause value of RowStatus,
consider the following state diagram:
STATE
+--------------+-----------+-------------+-------------
| A | B | C | D
| |status col.|status column|
|status column | is | is |status column
ACTION |does not exist| notReady | notInService| is active
--------------+--------------+-----------+-------------+-------------
set status |noError ->D|inconsist- |inconsistent-|inconsistent-
column to | or | entValue| Value| Value
createAndGo |inconsistent- | | |
| Value| | |
--------------+--------------+-----------+-------------+-------------
set status |noError see 1|inconsist- |inconsistent-|inconsistent-
column to | or | entValue| Value| Value
createAndWait |wrongValue | | |
--------------+--------------+-----------+-------------+-------------
set status |inconsistent- |inconsist- |noError |noError
column to | Value| entValue| |
active | | | |
| | or | |
| | | |
| |see 2 ->D| ->D| ->D
--------------+--------------+-----------+-------------+-------------
set status |inconsistent- |inconsist- |noError |noError ->C
column to | Value| entValue| |
notInService | | | |
| | or | | or
| | | |
| |see 3 ->C| ->C|wrongValue
--------------+--------------+-----------+-------------+-------------
set status |noError |noError |noError |noError
column to | | | |
destroy | ->A| ->A| ->A| ->A
--------------+--------------+-----------+-------------+-------------
set any other |see 4 |noError |noError |see 5
column to some| | | |
value | | see 1| ->C| ->D
--------------+--------------+-----------+-------------+-------------
(1) goto B or C, depending on information available to the
agent.
(2) if other variable bindings included in the same PDU,
provide values for all columns which are missing but
required, then return noError and goto D.
(3) if other variable bindings included in the same PDU,
provide values for all columns which are missing but
required, then return noError and goto C.
(4) at the discretion of the agent, the return value may be
either:
inconsistentName: because the agent does not choose to
create such an instance when the corresponding
RowStatus instance does not exist, or
inconsistentValue: if the supplied value is
inconsistent with the state of some other MIB object's
value, or
noError: because the agent chooses to create the
instance.
If noError is returned, then the instance of the status
column must also be created, and the new state is B or C,
depending on the information available to the agent. If
inconsistentName or inconsistentValue is returned, the row
remains in state A.
(5) depending on the MIB definition for the column/table,
either noError or inconsistentValue may be returned.
NOTE: Other processing of the set request may result in a
response other than noError being returned, e.g.,
wrongValue, noCreation, etc.
Conceptual Row Creation
There are four potential interactions when creating a
conceptual row: selecting an instance-identifier which is
not in use; creating the conceptual row; initializing any
objects for which the agent does not supply a default; and,
making the conceptual row available for use by the managed
device.
Interaction 1: Selecting an Instance-Identifier
The algorithm used to select an instance-identifier varies
for each conceptual row. In some cases, the instance-
identifier is semantically significant, e.g., the
destination address of a route, and a management station
selects the instance-identifier according to the semantics.
In other cases, the instance-identifier is used solely to
distinguish conceptual rows, and a management station
without specific knowledge of the conceptual row might
examine the instances present in order to determine an
unused instance-identifier. (This approach may be used, but
it is often highly sub-optimal; however, it is also a
questionable practice for a naive management station to
attempt conceptual row creation.)
Alternately, the MIB module which defines the conceptual row
might provide one or more objects which provide assistance
in determining an unused instance-identifier. For example,
if the conceptual row is indexed by an integer-value, then
an object having an integer-valued SYNTAX clause might be
defined for such a purpose, allowing a management station to
issue a management protocol retrieval operation. In order
to avoid unnecessary collisions between competing management
stations, `adjacent' retrievals of this object should be
different.
Finally, the management station could select a pseudo-random
number to use as the index. In the event that this index
was already in use and an inconsistentValue was returned in
response to the management protocol set operation, the
management station should simply select a new pseudo-random
number and retry the operation.
A MIB designer should choose between the two latter
algorithms based on the size of the table (and therefore the
efficiency of each algorithm). For tables in which a large
number of entries are expected, it is recommended that a MIB
object be defined that returns an acceptable index for
creation. For tables with small numbers of entries, it is
recommended that the latter pseudo-random index mechanism be
used.
Interaction 2: Creating the Conceptual Row
Once an unused instance-identifier has been selected, the
management station determines if it wishes to create and
activate the conceptual row in one transaction or in a
negotiated set of interactions.
Interaction 2a: Creating and Activating the Conceptual Row
The management station must first determine the column
requirements, i.e., it must determine those columns for
which it must or must not provide values. Depending on the
complexity of the table and the management station's
knowledge of the agent's capabilities, this determination
can be made locally by the management station. Alternately,
the management station issues a management protocol get
operation to examine all columns in the conceptual row that
it wishes to create. In response, for each column, there
are three possible outcomes:
- a value is returned, indicating that some other
management station has already created this conceptual
row. We return to interaction 1.
- the exception `noSuchInstance' is returned,
indicating that the agent implements the object-type
associated with this column, and that this column in at
least one conceptual row would be accessible in the MIB
view used by the retrieval were it to exist. For those
columns to which the agent provides read-create access,
the `noSuchInstance' exception tells the management
station that it should supply a value for this column
when the conceptual row is to be created.
- the exception `noSuchObject' is returned, indicating
that the agent does not implement the object-type
associated with this column or that there is no
conceptual row for which this column would be
accessible in the MIB view used by the retrieval. As
such, the management station can not issue any
management protocol set operations to create an
instance of this column.
Once the column requirements have been determined, a
management protocol set operation is accordingly issued.
This operation also sets the new instance of the status
column to `createAndGo'.
When the agent processes the set operation, it verifies that
it has sufficient information to make the conceptual row
available for use by the managed device. The information
available to the agent is provided by two sources: the
management protocol set operation which creates the
conceptual row, and, implementation-specific defaults
supplied by the agent (note that an agent must provide
implementation-specific defaults for at least those objects
which it implements as read-only). If there is sufficient
information available, then the conceptual row is created, a
`noError' response is returned, the status column is set to
`active', and no further interactions are necessary (i.e.,
interactions 3 and 4 are skipped). If there is insufficient
information, then the conceptual row is not created, and the
set operation fails with an error of `inconsistentValue'.
On this error, the management station can issue a management
protocol retrieval operation to determine if this was
because it failed to specify a value for a required column,
or, because the selected instance of the status column
already existed. In the latter case, we return to
interaction 1. In the former case, the management station
can re-issue the set operation with the additional
information, or begin interaction 2 again using
`createAndWait' in order to negotiate creation of the
conceptual row.
NOTE WELL
Regardless of the method used to determine the column
requirements, it is possible that the management
station might deem a column necessary when, in fact,
the agent will not allow that particular columnar
instance to be created or written. In this case, the
management protocol set operation will fail with an
error such as `noCreation' or `notWritable'. In this
case, the management station decides whether it needs
to be able to set a value for that particular columnar
instance. If not, the management station re-issues the
management protocol set operation, but without setting
a value for that particular columnar instance;
otherwise, the management station aborts the row
creation algorithm.
Interaction 2b: Negotiating the Creation of the Conceptual
Row
The management station issues a management protocol set
operation which sets the desired instance of the status
column to `createAndWait'. If the agent is unwilling to
process a request of this sort, the set operation fails with
an error of `wrongValue'. (As a consequence, such an agent
must be prepared to accept a single management protocol set
operation, i.e., interaction 2a above, containing all of the
columns indicated by its column requirements.) Otherwise,
the conceptual row is created, a `noError' response is
returned, and the status column is immediately set to either
`notInService' or `notReady', depending on whether it has
sufficient information to make the conceptual row available
for use by the managed device. If there is sufficient
information available, then the status column is set to
`notInService'; otherwise, if there is insufficient
information, then the status column is set to `notReady'.
Regardless, we proceed to interaction 3.
Interaction 3: Initializing non-defaulted Objects
The management station must now determine the column
requirements. It issues a management protocol get operation
to examine all columns in the created conceptual row. In
the response, for each column, there are three possible
outcomes:
- a value is returned, indicating that the agent
implements the object-type associated with this column
and had sufficient information to provide a value. For
those columns to which the agent provides read-create
access (and for which the agent allows their values to
be changed after their creation), a value return tells
the management station that it may issue additional
management protocol set operations, if it desires, in
order to change the value associated with this column.
- the exception `noSuchInstance' is returned,
indicating that the agent implements the object-type
associated with this column, and that this column in at
least one conceptual row would be accessible in the MIB
view used by the retrieval were it to exist. However,
the agent does not have sufficient information to
provide a value, and until a value is provided, the
conceptual row may not be made available for use by the
managed device. For those columns to which the agent
provides read-create access, the `noSuchInstance'
exception tells the management station that it must
issue additional management protocol set operations, in
order to provide a value associated with this column.
- the exception `noSuchObject' is returned, indicating
that the agent does not implement the object-type
associated with this column or that there is no
conceptual row for which this column would be
accessible in the MIB view used by the retrieval. As
such, the management station can not issue any
management protocol set operations to create an
instance of this column.
If the value associated with the status column is
`notReady', then the management station must first deal with
all `noSuchInstance' columns, if any. Having done so, the
value of the status column becomes `notInService', and we
proceed to interaction 4.
Interaction 4: Making the Conceptual Row Available
Once the management station is satisfied with the values
associated with the columns of the conceptual row, it issues
a management protocol set operation to set the status column
to `active'. If the agent has sufficient information to
make the conceptual row available for use by the managed
device, the management protocol set operation succeeds (a
`noError' response is returned). Otherwise, the management
protocol set operation fails with an error of
`inconsistentValue'.
NOTE WELL
A conceptual row having a status column with value
`notInService' or `notReady' is unavailable to the
managed device. As such, it is possible for the
managed device to create its own instances during the
time between the management protocol set operation
which sets the status column to `createAndWait' and the
management protocol set operation which sets the status
column to `active'. In this case, when the management
protocol set operation is issued to set the status
column to `active', the values held in the agent
supersede those used by the managed device.
If the management station is prevented from setting the
status column to `active' (e.g., due to management station
or network failure) the conceptual row will be left in the
`notInService' or `notReady' state, consuming resources
indefinitely. The agent must detect conceptual rows that
have been in either state for an abnormally long period of
time and remove them. It is the responsibility of the
DESCRIPTION clause of the status column to indicate what an
abnormally long period of time would be. This period of
time should be long enough to allow for human response time
(including `think time') between the creation of the
conceptual row and the setting of the status to `active'.
In the absense of such information in the DESCRIPTION
clause, it is suggested that this period be approximately 5
minutes in length. This removal action applies not only to
newly-created rows, but also to previously active rows which
are set to, and left in, the notInService state for a
prolonged period exceeding that which is considered normal
for such a conceptual row.
Conceptual Row Suspension
When a conceptual row is `active', the management station
may issue a management protocol set operation which sets the
instance of the status column to `notInService'. If the
agent is unwilling to do so, the set operation fails with an
error of `wrongValue'. Otherwise, the conceptual row is
taken out of service, and a `noError' response is returned.
It is the responsibility of the DESCRIPTION clause of the
status column to indicate under what circumstances the
status column should be taken out of service (e.g., in order
for the value of some other column of the same conceptual
row to be modified).
Conceptual Row Deletion
For deletion of conceptual rows, a management protocol set
operation is issued which sets the instance of the status
column to `destroy'. This request may be made regardless of
the current value of the status column (e.g., it is possible
to delete conceptual rows which are either `notReady',
`notInService' or `active'.) If the operation succeeds,
then all instances associated with the conceptual row are
immediately removed."
SYNTAX INTEGER
{
active(1),
notInService(2),
notReady(3),
createAndGo(4),
createAndWait(5),
destroy(6)
}
-- the following two values are states:
-- these values may be read or written
-- the following value is a state:
-- this value may be read, but not written
-- the following three values are
-- actions: these values may be written,
-- but are never read
TimeStamp ::= TEXTUAL-CONVENTION
STATUS current
DESCRIPTION
"The value of the sysUpTime object at which a specific
occurrence happened. The specific occurrence must be
defined in the description of any object defined using this
type."
SYNTAX TimeTicks
--
-- Node definitions
--
-- 1.3.6.1.4.1.1379
cintelNS OBJECT IDENTIFIER ::= { enterprises 1379 }
END
--
-- CINTEL-MIB.my
--

Binary file not shown.

View File

@@ -1,901 +0,0 @@
package mml
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"math"
"net/http"
"regexp"
"strconv"
"strings"
"ems.agt/lib/dborm"
"ems.agt/lib/global"
"ems.agt/lib/log"
"github.com/go-resty/resty/v2"
"golang.org/x/crypto/ssh"
)
type Param struct {
Name string `json:"name"`
Value string `json:"value"`
}
type MmlCommand struct {
Operation string `json:"operation"`
Object string `json:"object"`
Params []Param `json:"params"`
PaList []string `json:"paList"`
AaList []string `json:"aaList"`
AaMap map[string]interface{} `json:"aaMap"`
NaMap map[string]interface{} `json:"naMap"`
AaUri []string `json:"aaUri"`
AaLoc []string `json:"aaLoc"` // for loc parameter
}
type MmlVar struct {
Version string `json:"version"`
Output string `json:"output"`
Limit int `json:"limit"`
User string `json:"user"`
Token string `josn:"token"`
}
var OmcMmlVar *MmlVar
func init() {
OmcMmlVar = &MmlVar{
Version: "16.1.1",
Output: DefaultFormatType,
Limit: 50,
}
}
func SetOmcMmlVarOutput(output string) {
OmcMmlVar.Output = output
}
func SetOmcMmlVarLimit(limit int) {
OmcMmlVar.Limit = limit
}
func splitByColon(str string) []string {
return splitBy(str, ':')
}
func splitByComma(str string) []string {
return splitBy(str, ',')
}
func splitBy(str string, sep rune) []string {
var result []string
var stack []string
var current []rune
var quotes, apoFlag bool = false, false
for _, c := range str {
if c == '{' || c == '[' || (c == '\'' && apoFlag == false) || (c == '"' && quotes == false) { // "'"
apoFlag = true
quotes = true
stack = append(stack, string(c))
} else if c == '}' || c == ']' || (c == '\'' && apoFlag == true) || (c == '"' && quotes == true) {
apoFlag = false
quotes = false
if len(stack) > 0 {
stack = stack[:len(stack)-1]
}
}
if c == sep && len(stack) == 0 {
result = append(result, string(current))
current = []rune{}
} else {
current = append(current, c)
}
}
result = append(result, string(current))
return result
}
func ParseMMLCommand(mmlStr string, mmlComms *[]MmlCommand) error {
log.Info("ParseMMLCommand processing ...")
log.Debug("mmlStr: ", mmlStr)
mc := new(MmlCommand)
reg := regexp.MustCompile(`\s*;\s*`)
mmls := reg.Split(mmlStr, -1)
for _, mml := range mmls {
log.Trace("mml:", mml)
if len(mml) == 0 {
continue
}
//reg := regexp.MustCompile(`\s*:\s*`)
//ms := reg.Split(mml, -1)
ms := splitByColon(mml)
if len(ms) < 1 || len(ms) > 2 {
err := global.ErrMmlInvalidCommandFormat
log.Error(err)
return err
}
if len(ms) == 2 {
cmd := strings.Trim(ms[0], " ")
reg = regexp.MustCompile(`\s+`)
cs := reg.Split(cmd, -1)
//cs := strings.Split(cmd, " ")
if len(cs) == 2 {
mc.Operation = cs[0]
mc.Object = cs[1]
} else {
err := global.ErrMmlInvalidCommandFormat
log.Error(err)
return err
}
//reg = regexp.MustCompile(`\s*,\s*`)
//reg = regexp.MustCompile(`(?U)(?<!\{[^{}]*),(?![^{}]*\})|(?<!\"[^\"]*),(?![^\"]*\")|(?<!\[[^\[\]]*),(?![^\[\]]*\])`)
//reg = regexp.MustCompile(`,[^'"\(\)]+`)
//params := reg.Split(ms[1], -1)
params := splitByComma(strings.Trim(ms[1], " "))
//params := strings.Split(ms[1], ",")
for _, p := range params {
log.Trace("p:", p)
if p == "" {
continue
}
mc.PaList = append(mc.PaList, p)
reg = regexp.MustCompile(`\s*=\s*`)
pvs := reg.Split(p, -1)
log.Trace("pvs:", pvs)
if len(pvs) == 2 {
mc.Params = append(mc.Params, Param{Name: pvs[0], Value: pvs[1]})
} else {
err := global.ErrMmlInvalidCommandFormat
log.Error(err)
return err
}
}
} else if len(ms) == 1 {
cmd := ms[0]
reg = regexp.MustCompile(`\s+`)
cs := reg.Split(cmd, -1)
//cs := strings.Split(cmd, " ")
if len(cs) == 2 {
mc.Operation = cs[0]
mc.Object = cs[1]
} else {
err := global.ErrMmlInvalidCommandFormat
log.Error(err)
return err
}
} else {
err := global.ErrMmlInvalidCommandFormat
log.Error(err)
return err
}
err := ParseMMLAlias(mc)
if err != nil {
err := global.ErrMmlInvalidCommandFormat
log.Error(err)
return err
}
*mmlComms = append(*mmlComms, *mc)
}
return nil
}
func ParseMMLAlias(mml *MmlCommand) error {
where := fmt.Sprintf("operation='%s' AND object='%s'", mml.Operation, mml.Object)
mc, err := dborm.XormGetMmlCommand("mml_command", where)
if err != nil {
log.Error("Failed to XormGetMmlCommand: ", err)
return err
}
if mc == nil {
err := errors.New("Not found mml map")
log.Error(err)
return err
}
log.Debug("mml command: ", mc)
aaMap := make(map[string]interface{})
naMap := make(map[string]interface{})
for _, pn := range mml.Params {
log.Trace("pn: ", pn)
for _, param := range mc.ParamJson {
log.Trace("param: ", param)
var pv string
if pn.Name == param.Name {
if param.Apostr == "true" {
pv = fmt.Sprintf("'%v'", pn.Value)
} else {
pv = fmt.Sprintf("%v", pn.Value)
}
var aa, av string
if param.Alias != "" {
aa = fmt.Sprintf("%s=%v", param.Alias, pv)
av = fmt.Sprintf("%v", pv)
switch param.Type {
case "int":
aaMap[param.Alias] = pn.Value
naMap[param.Alias] = pn.Value
default:
aaMap[param.Alias] = pv
naMap[param.Alias] = fmt.Sprintf("%v", pn.Value)
}
} else {
aa = fmt.Sprintf("%s=%v", param.Name, pv)
av = fmt.Sprintf("%v", pv)
switch param.Type {
case "int":
aaMap[param.Name] = pn.Value
naMap[param.Name] = pn.Value
default:
aaMap[param.Name] = pv
naMap[param.Name] = fmt.Sprintf("%v", pn.Value)
}
}
if param.Loc == "" || param.Loc == "true" {
mml.AaLoc = append(mml.AaLoc, aa)
mml.AaUri = append(mml.AaUri, av)
}
//mml.AaMap = append(mml.AaMap, aaMap)
mml.AaList = append(mml.AaList, aa)
break
}
}
}
mml.AaMap = aaMap
mml.NaMap = naMap
log.Trace("mml.AaMap: ", mml.AaMap)
log.Trace("mml.NaMap: ", mml.NaMap)
log.Trace("mml.AaList: ", mml.AaList)
return nil
}
func ParseMMLParams(mmlComms *[]MmlCommand) error {
for _, mml := range *mmlComms {
where := fmt.Sprintf("operation='%s' AND object='%s'", mml.Operation, mml.Object)
mc, err := dborm.XormGetMmlCommand("mml_command", where)
if err != nil {
log.Error("Failed to XormGetMmlCommand: ", err)
return err
}
if mc == nil {
err := errors.New("Not found mml map")
log.Error(err)
return err
}
log.Debug("mml command: ", mc)
for _, pn := range mml.Params {
log.Trace("pn: ", pn)
for _, param := range mc.ParamJson {
log.Trace("param: ", param)
var pv string
if pn.Name == param.Name {
if param.Apostr == "true" {
pv = fmt.Sprintf("'%v'", pn.Value)
} else {
pv = fmt.Sprintf("%v", pn.Value)
}
var aa string
aaMap := make(map[string]interface{})
if param.Alias != "" {
aa = fmt.Sprintf("%s=%v", param.Alias, pv)
switch param.Type {
case "int":
aaMap[param.Alias] = pn.Value
case "string":
aaMap[param.Alias] = pv
}
} else {
aa = fmt.Sprintf("%s=%v", param.Name, pv)
switch param.Type {
case "int":
aaMap[param.Name] = pn.Value
case "string":
aaMap[param.Name] = pv
}
}
//mml.AaMap = append(mml.AaMap, aaMap)
mml.AaList = append(mml.AaList, aa)
break
}
}
}
log.Trace("mml.AaMap: ", mml.AaMap)
log.Trace("mml.AaList: ", mml.AaList)
*mmlComms = append(*mmlComms, mml)
}
return nil
}
func parseRequestUri(httpUri string, mmlMap *dborm.MmlHttpMap, mml *MmlCommand) string {
requestURI := fmt.Sprintf("%s%s", httpUri, mmlMap.URI)
if mmlMap.ExtUri != "" && len(mml.AaUri) > 0 {
extUri := strings.Join(mml.AaUri, "/")
requestURI = requestURI + fmt.Sprintf(mmlMap.ExtUri, extUri)
}
if mmlMap.Params != "" {
params := strings.Join(mml.AaLoc, "+and+")
params = strings.ReplaceAll(params, " ", "+") // replace " " to "+"
log.Trace("params:", params)
if mmlMap.ParamTag == "SQL" && strings.TrimSpace(params) != "" {
params = "+where+" + params
}
requestURI = fmt.Sprintf("%s%s%s", requestURI, mmlMap.Params, params)
}
return requestURI
}
func TransMml2HttpReq(sshConn *ssh.ServerConn, httpUri, uerAgent string, mml *MmlCommand) (*[]byte, error) {
log.Info("TransMml2HttpReq processing ...")
log.Debug("mml: ", mml)
where := fmt.Sprintf("operation='%s' AND object='%s'", mml.Operation, mml.Object)
mmlMap, err := dborm.XormGetMmlHttpMap("mml_http_map", where)
if err != nil {
log.Error("Failed to XormGetMmlHttpMap: ", err)
return ParseErrorOutput(err), err
}
if mmlMap == nil {
err := errors.New("Not found mml map")
log.Error(err)
return ParseErrorOutput(err), err
}
log.Trace("mmlMap: ", mmlMap)
if mmlMap.Output == "" {
mmlMap.Output = "{}"
}
outputJson := new(dborm.MmlOutput)
err = json.Unmarshal([]byte(mmlMap.Output), outputJson)
if err != nil {
log.Error("Failed to Unmarshal:", err)
return ParseErrorOutput(err), err
}
log.Trace("outputJson: ", outputJson)
inputJson := new(dborm.MmlInput)
log.Trace("mmlMap.Input: ", mmlMap.Input)
if mmlMap.Input == "" {
mmlMap.Input = "{}"
}
err = json.Unmarshal([]byte(mmlMap.Input), inputJson)
if err != nil {
log.Error("Failed to Unmarshal:", err)
return ParseErrorOutput(err), err
}
log.Trace("inputJson: ", inputJson)
var requestURI string
var output *[]byte
client := resty.New()
switch strings.ToLower(mmlMap.Method) {
case "get":
requestURI = parseRequestUri(httpUri, mmlMap, mml)
log.Debugf("method: Get requestURI: %s", requestURI)
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": fmt.Sprintf("%x", sshConn.SessionID())}).
SetHeaders(map[string]string{"User-Agent": uerAgent}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(requestURI)
if err != nil {
log.Error("Failed to Get:", err)
output = ParseErrorOutput(err)
} else {
output = ParseOutputResponse(outputJson, response)
}
case "post":
requestURI = parseRequestUri(httpUri, mmlMap, mml)
body := ParseInputBody(inputJson, mml)
log.Debugf("method: Post requestURI: %s", requestURI)
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": fmt.Sprintf("%x", sshConn.SessionID())}).
SetHeaders(map[string]string{"User-Agent": uerAgent}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
SetBody(*body).
Post(requestURI)
if err != nil {
log.Error("Failed to Post:", err)
output = ParseErrorOutput(err)
} else {
output = ParseOutputResponse(outputJson, response)
}
case "put":
requestURI = parseRequestUri(httpUri, mmlMap, mml)
body := ParseInputBody(inputJson, mml)
log.Debugf("method: Put requestURI: %s", requestURI)
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": fmt.Sprintf("%x", sshConn.SessionID())}).
SetHeaders(map[string]string{"User-Agent": uerAgent}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
SetBody(*body).
Put(requestURI)
if err != nil {
log.Error("Failed to Put:", err)
output = ParseErrorOutput(err)
} else {
output = ParseOutputResponse(outputJson, response)
}
case "delete":
requestURI = parseRequestUri(httpUri, mmlMap, mml)
log.Debugf("method: Delete requestURI: %s", requestURI)
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": fmt.Sprintf("%x", sshConn.SessionID())}).
SetHeaders(map[string]string{"User-Agent": uerAgent}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Delete(requestURI)
if err != nil {
log.Error("Failed to Delete:", err)
output = ParseErrorOutput(err)
} else {
output = ParseOutputResponse(outputJson, response)
}
case "patch":
requestURI = parseRequestUri(httpUri, mmlMap, mml)
log.Debugf("method: patch requestURI: %s", requestURI)
response, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": fmt.Sprintf("%x", sshConn.SessionID())}).
SetHeaders(map[string]string{"User-Agent": uerAgent}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Patch(requestURI)
if err != nil {
log.Error("Failed to Patch:", err)
output = ParseErrorOutput(err)
} else {
output = ParseOutputResponse(outputJson, response)
}
default:
err := errors.New("not found mml command")
log.Error(err)
output = ParseErrorOutput(err)
}
return output, nil
}
const (
MaxMmlOutputBufferSize = 1000000
FormatTypeJson = "json"
FormatTypeTable = "table"
DefaultFormatType = FormatTypeTable
)
const (
RetCodeSucceeded = 0
RetCodeFailed = 0
)
func ParseInputBody(inputJson *dborm.MmlInput, mml *MmlCommand) *[]byte {
inputBody := make(map[string]interface{})
log.Trace("mml.NaMap:", mml.NaMap)
log.Trace("mml.AaMap:", mml.AaMap)
if strings.ToLower(inputJson.BodyFmt) == "putdb" {
for _, icol := range inputJson.Cols {
log.Trace("icol:", icol)
mml.NaMap[icol.Name] = icol.Value
}
inputBody[inputJson.BodyKey] = mml.NaMap
} else {
inputParams := make([]map[string]interface{}, 0)
inputParams = append(inputParams, mml.NaMap)
inputBody[inputJson.BodyKey] = inputParams
}
body, err := json.Marshal(inputBody)
if err != nil {
log.Error("Failed to marshal:", err)
}
log.Trace("inputBody:", inputBody)
log.Trace("body:", string(body))
return &body
}
func ParseOutputResponse(outputJson *dborm.MmlOutput, response *resty.Response) *[]byte {
var output []byte
var str bytes.Buffer
switch response.StatusCode() {
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
if OmcMmlVar.Output == FormatTypeJson {
code := fmt.Sprintf("StatusCode = %d status %s\n\n", response.StatusCode(), response.Status())
title := formatTitle(outputJson.Title)
json.Indent(&str, response.Body(), "", " ")
log.Trace(str.String())
output = global.BytesCombine1([]byte(code), []byte(title), str.Bytes(), []byte("\n"))
} else {
log.Trace("Body:", string(response.Body()))
mapDatas := make(map[string]interface{}, 0)
err := json.Unmarshal(response.Body(), &mapDatas)
if err != nil {
log.Error("Failed to json.Unmarshal:", err)
//output = *ParseErrorOutput(err)
output = *ParseErrorOutput(string(response.Body()))
return &output
}
log.Trace("mapDatas:", mapDatas)
switch strings.ToLower(outputJson.RetFmt) {
case "getdb":
if len(mapDatas) > 0 {
var data interface{}
for _, data = range mapDatas {
log.Trace("data:", data)
break
}
if len(data.([]interface{})) > 0 {
table := (data.([]interface{}))[0]
log.Trace("table:", table)
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
title := formatTitle(outputJson.Title)
fmtResults := ParseTableOutput(outputJson, table)
output = global.BytesCombine1([]byte(code), []byte(title), []byte(fmtResults))
}
}
case "deletedb":
var data interface{}
for _, data = range mapDatas {
log.Trace("data:", data)
break
}
if len(data.(map[string]interface{})) > 0 {
table := data.(map[string]interface{})
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
fmtResults := ParseDBOperOutput(outputJson, table)
output = global.BytesCombine1([]byte(code), []byte(fmtResults))
}
case "postdb":
var data interface{}
for _, data = range mapDatas {
log.Trace("data:", data)
break
}
if len(data.(map[string]interface{})) > 0 {
table := data.(map[string]interface{})
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
fmtResults := ParseDBOperOutput(outputJson, table)
output = global.BytesCombine1([]byte(code), []byte(fmtResults))
}
case "putdb":
var data interface{}
for _, data = range mapDatas {
log.Trace("data:", data)
break
}
if len(data.(map[string]interface{})) > 0 {
table := data.(map[string]interface{})
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
fmtResults := ParseDBOperOutput(outputJson, table)
output = global.BytesCombine1([]byte(code), []byte(fmtResults))
}
case "getnf":
if len(mapDatas) > 0 {
var data interface{}
for _, data = range mapDatas {
log.Trace("data:", data)
break
}
if len(data.([]interface{})) > 0 {
//table := (data.([]interface{}))[0]
//log.Trace("table:", table)
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
title := formatTitle(outputJson.Title)
fmtResults := ParseNFTableOutput(outputJson, data)
output = global.BytesCombine1([]byte(code), []byte(title), []byte(fmtResults))
}
}
default:
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
output = global.BytesCombine1([]byte(code))
}
}
default:
if OmcMmlVar.Output == FormatTypeJson {
code := fmt.Sprintf("StatusCode = %d status %s\n\n", response.StatusCode(), response.Status())
//title := formatTitle("Network Element Information")
json.Indent(&str, response.Body(), "", " ")
log.Trace(str.String())
output = global.BytesCombine1([]byte(code), str.Bytes(), []byte("\n"))
} else {
log.Trace("Body:", string(response.Body()))
mapResults := make(map[string]interface{}, 0)
err := json.Unmarshal(response.Body(), &mapResults)
if err != nil {
log.Error("Failed to json.Unmarshal:", err)
output = *ParseErrorOutput(string(response.Body()))
} else {
log.Trace("mapResults:", mapResults)
errResult := mapResults["error"]
log.Trace("errResult:", errResult)
if len(errResult.(map[string]interface{})) > 0 {
errCode, _ := strconv.Atoi(fmt.Sprintf("%v", errResult.(map[string]interface{})["errorCode"]))
errorInfo := errResult.(map[string]interface{})["errorInfo"]
output = []byte(fmt.Sprintf(outputJson.ErrMsg, errCode, errorInfo))
}
}
}
}
return &output
}
func ParseDBOperOutput(outputJson *dborm.MmlOutput, cols any) string {
var colOutput []dborm.ColOutput = outputJson.Cols
var value, retFmtCols string
if len(cols.(map[string]interface{})) > 0 {
if len(colOutput) > 0 {
coln := colOutput[0].Name
value = fmt.Sprintf("%v", cols.(map[string]interface{})[coln])
log.Tracef("coln:%s value:%s", coln, value)
retFmtCols = colOutput[0].Display + " = " + value + "\n\n"
}
}
return retFmtCols
}
func ParseNFTableOutput(outputJson *dborm.MmlOutput, cols any) string {
var colOutput []dborm.ColOutput
var fmtColName string
var colName []string
var spaceNum int = 1
var alignmentM, alignmentSN, alignmentSV string = "Left", "Right", "Left"
if outputJson.SepSpaceNum != 0 {
spaceNum = outputJson.SepSpaceNum
}
if outputJson.AlignmentM != "" {
alignmentM = outputJson.AlignmentM
}
if outputJson.AlignmentSN != "" {
alignmentSN = outputJson.AlignmentSN
}
if outputJson.AlignmentSV != "" {
alignmentSV = outputJson.AlignmentSV
}
maxLength := math.MinInt64
for _, coln := range outputJson.Cols {
log.Trace("coln:", coln)
if len(coln.Display) > maxLength {
maxLength = len(coln.Display)
}
if coln.Length < len(coln.Display) {
coln.Length = len(coln.Display)
}
colName = append(colName, ParseAlignmentOutput(coln.Length, alignmentM, coln.Display))
colOutput = append(colOutput, coln)
}
fmtColName = formatLineBySpace(&colName, spaceNum)
log.Trace("fmtColName:", fmtColName)
var retFmtCols string
var fmtColValues []string
var numberResult int
// for _, colnvs := range cols.([]interface{}) {
// log.Trace("colnvs:", colnvs)
// if colnvs == nil {
// break
// }
numberResult = len(cols.([]interface{}))
if numberResult == 1 && outputJson.SingleList == true {
colnv := cols.([]interface{})[0]
log.Trace("colnv:", colnv)
var fmtNV []string
for _, coln := range colOutput {
fmtName := ParseAlignmentOutput(maxLength, alignmentSN, coln.Display)
log.Tracef("alignmentSN:%s fmtName:%s", alignmentSN, fmtName)
value := fmt.Sprintf("%v", colnv.(map[string]interface{})[coln.Name])
fmtValue := ParseAlignmentOutput(coln.Length, alignmentSV, value)
fmtNV = append(fmtNV, fmtName+": "+fmtValue)
}
fmtResults := strings.Join(fmtNV, "\n")
log.Tracef("fmtResults:\n%s", fmtResults)
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
retFmtCols = fmtResults + "\n\n" + fmtEnd
log.Tracef("retFmtCols:\n%s", retFmtCols)
return retFmtCols
} else {
for i := 0; i < numberResult; i++ {
colnv := cols.([]interface{})[i]
log.Trace("colnv:", colnv)
var colValues []string
var newVal []string
for _, coln := range colOutput {
value := fmt.Sprintf("%v", colnv.(map[string]interface{})[coln.Name])
if len(coln.Alias) != 0 {
enumVal, _ := strconv.Atoi(value)
value = parseEnumAlias(&(coln.Alias), enumVal)
}
newVal = append(newVal, ParseAlignmentOutput(coln.Length, alignmentM, value))
}
colValues = append(colValues, formatLineBySpace(&newVal, spaceNum))
log.Trace("colValues:", colValues)
fmtColValues = append(fmtColValues, strings.Join(colValues, "\n"))
log.Trace("fmtColValues:", fmtColValues)
}
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
retFmtCols = fmtColName + "\n\n" + strings.Join(fmtColValues, "\n") + "\n\n" + fmtEnd
log.Tracef("retFmtCols:\n%s", retFmtCols)
return retFmtCols
}
}
func ParseTableOutput(outputJson *dborm.MmlOutput, cols any) string {
var colOutput []dborm.ColOutput
var fmtColName string
var colName []string
var spaceNum int = 1
var alignmentM, alignmentSN, alignmentSV string = "Left", "Right", "Left"
if outputJson.SepSpaceNum != 0 {
spaceNum = outputJson.SepSpaceNum
}
if outputJson.AlignmentM != "" {
alignmentM = outputJson.AlignmentM
}
if outputJson.AlignmentSN != "" {
alignmentSN = outputJson.AlignmentSN
}
if outputJson.AlignmentSV != "" {
alignmentSV = outputJson.AlignmentSV
}
maxLength := math.MinInt64
for _, coln := range outputJson.Cols {
log.Trace("coln:", coln)
if len(coln.Display) > maxLength {
maxLength = len(coln.Display)
}
if coln.Length < len(coln.Display) {
coln.Length = len(coln.Display)
}
colName = append(colName, ParseAlignmentOutput(coln.Length, alignmentM, coln.Display))
colOutput = append(colOutput, coln)
}
fmtColName = formatLineBySpace(&colName, spaceNum)
log.Trace("fmtColName:", fmtColName)
var retFmtCols string
var fmtColValues []string
var numberResult int
for _, colnvs := range cols.(map[string]interface{}) {
log.Trace("colnvs:", colnvs)
if colnvs == nil {
break
}
numberResult = len(colnvs.([]interface{}))
if numberResult == 1 && outputJson.SingleList == true {
colnv := colnvs.([]interface{})[0]
log.Trace("colnv:", colnv)
var fmtNV []string
for _, coln := range colOutput {
fmtName := ParseAlignmentOutput(maxLength, alignmentSN, coln.Display)
log.Tracef("alignmentSN:%s fmtName:%s", alignmentSN, fmtName)
value := fmt.Sprintf("%v", colnv.(map[string]interface{})[coln.Name])
fmtValue := ParseAlignmentOutput(coln.Length, alignmentSV, value)
fmtNV = append(fmtNV, fmtName+": "+fmtValue)
}
fmtResults := strings.Join(fmtNV, "\n")
log.Tracef("fmtResults:\n%s", fmtResults)
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
retFmtCols = fmtResults + "\n\n" + fmtEnd
log.Tracef("retFmtCols:\n%s", retFmtCols)
return retFmtCols
} else {
for i := 0; i < numberResult; i++ {
colnv := colnvs.([]interface{})[i]
log.Trace("colnv:", colnv)
var colValues []string
var newVal []string
for _, coln := range colOutput {
value := fmt.Sprintf("%v", colnv.(map[string]interface{})[coln.Name])
if len(coln.Alias) != 0 {
enumVal, _ := strconv.Atoi(value)
value = parseEnumAlias(&(coln.Alias), enumVal)
}
newVal = append(newVal, ParseAlignmentOutput(coln.Length, alignmentM, value))
}
colValues = append(colValues, formatLineBySpace(&newVal, spaceNum))
log.Trace("colValues:", colValues)
fmtColValues = append(fmtColValues, strings.Join(colValues, "\n"))
log.Trace("fmtColValues:", fmtColValues)
}
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
retFmtCols = fmtColName + "\n\n" + strings.Join(fmtColValues, "\n") + "\n\n" + fmtEnd
log.Tracef("retFmtCols:\n%s", retFmtCols)
return retFmtCols
}
}
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
retFmtCols = fmtColName + "\n" + strings.Join(fmtColValues, "\n") + "\n\n" + fmtEnd
log.Tracef("retFmtCols:\n%s", retFmtCols)
return retFmtCols
}
func parseEnumAlias(alias *[]string, enumVal int) string {
return (*alias)[enumVal]
}
func formatLineBySpace(strArray *[]string, spaceNum int) string {
space := strings.Repeat(" ", spaceNum)
return strings.Join(*strArray, space)
}
func ParseAlignmentOutput(length int, alignment string, str string) string {
spaceLen := length - len(str)
if spaceLen < 0 {
log.Warnf("len(str=%s)=%d more length=%d", str, len(str), length)
spaceLen = 0
}
var retStr string
switch alignment {
case "Left":
suffix := strings.Repeat(" ", spaceLen)
retStr = str + suffix
case "Right":
prefix := strings.Repeat(" ", spaceLen)
retStr = prefix + str
log.Tracef("retStr:%s", retStr)
case "Middle":
prefix := strings.Repeat(" ", int(math.Ceil(float64(spaceLen)/2)))
suffix := strings.Repeat(" ", int(math.Floor(float64(spaceLen)/2)))
retStr = prefix + str + suffix
}
log.Tracef("length=%d, spaceLne=%d, alignment=%s, str=%s, retStr=%s", length, spaceLen, alignment, str, retStr)
return retStr
}
func ParseErrorOutput(err any) *[]byte {
var output []byte
var formatType string = DefaultFormatType
if formatType == FormatTypeJson {
output = []byte(fmt.Sprintf("ErrorCode = 1 Error message: %v\n\n", err))
} else {
output = []byte(fmt.Sprintf("RetCode = -1 operation failed: %v\n\n", err))
}
return &output
}
func formatTitle(title string) string {
var builder strings.Builder
builder.WriteString(title)
builder.WriteString("\n")
for i := 0; i < len(title); i++ {
builder.WriteString("-")
}
builder.WriteString("\n")
return builder.String()
}
func formatTableOutput() {
}

View File

@@ -1,26 +0,0 @@
#!/bin/bash
TargetIP="[2001:db8::9166]"
PORT="34957"
OID=".1.3.6.1.4.1.1379.2.3.3.3.1.1.9.0"
case "$1" in
1)
echo -n "Set HLR state link down ... "
snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} ${OID} i 1 >/dev/null
echo "done"
;;
2)
echo -n "Set HLR state link up ... "
snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} ${OID} i 2 >/dev/null
echo "done"
;;
3)
echo -n "Set HLR state authentication failure ... "
snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} ${OID} i 3 >/dev/null
echo "done"
;;
*)
echo "Unknown state ($1)"
;;
esac

View File

@@ -1,553 +0,0 @@
package snmp
import (
"flag"
"fmt"
"log"
"net"
"os"
"path/filepath"
"strings"
"time"
g "github.com/gosnmp/gosnmp"
"github.com/slayercat/GoSNMPServer"
"github.com/slayercat/GoSNMPServer/mibImps"
)
type SNMPService struct {
ListenAddr string
ListenPort uint16
UserName string
AuthPass string
AuthProto string
PrivPass string
PrivProto string
EngineID string
TrapPort uint16
TrapListen bool
TrapBool bool
TrapTick uint16
TimeOut uint16
TrapTarget string
ListenHost string
TrapHost string
SysName string
SysDescr string
SysLocation string
SysContact string
SysStatus string
SysService int
}
func (s *SNMPService) getAuthProto() g.SnmpV3AuthProtocol {
switch s.AuthProto {
case "NoAuth":
return g.NoAuth
case "MD5":
return g.MD5
case "SHA":
return g.SHA
default:
}
return g.MD5
}
func (s *SNMPService) getPrivProto() g.SnmpV3PrivProtocol {
switch s.PrivProto {
case "NoPriv":
return g.NoPriv
case "DES":
return g.DES
case "AES":
return g.AES
case "AES192":
return g.AES192
case "AES256":
return g.AES256
default:
}
return g.DES
}
func (s *SNMPService) setSecParamsList() []g.UsmSecurityParameters {
var secParamsList = []g.UsmSecurityParameters{
{
UserName: s.UserName,
AuthenticationProtocol: s.getAuthProto(),
AuthenticationPassphrase: s.AuthPass,
PrivacyProtocol: s.getPrivProto(),
PrivacyPassphrase: s.PrivPass,
AuthoritativeEngineID: s.EngineID,
},
// {
// UserName: "myuser2",
// AuthenticationProtocol: g.SHA,
// AuthenticationPassphrase: "mypassword2",
// PrivacyProtocol: g.DES,
// PrivacyPassphrase: "myprivacy2",
// AuthoritativeEngineID: s.EngineID,
// },
// {
// UserName: "myuser2",
// AuthenticationProtocol: g.MD5,
// AuthenticationPassphrase: "mypassword2",
// PrivacyProtocol: g.AES,
// PrivacyPassphrase: "myprivacy2",
// AuthoritativeEngineID: s.EngineID,
// },
}
return secParamsList
}
func (s *SNMPService) StartSNMPServer() {
// 设置引擎启动次数和引varvar
var engineBoots uint32 = 1
//var engineTime uint32 = uint32(time.Now().Unix() % 2147483647) // 使用当前时间初始化
//var engineTime uint32 = 3600 // 使用当前时间初始化
master := GoSNMPServer.MasterAgent{
Logger: GoSNMPServer.NewDefaultLogger(),
SecurityConfig: GoSNMPServer.SecurityConfig{
NoSecurity: true,
AuthoritativeEngineBoots: engineBoots,
// OnGetAuthoritativeEngineTime: func() uint32 {
// return engineTime
// },
//AuthoritativeEngineID: GoSNMPServer.SNMPEngineID{EngineIDData: "0x800007DB03360102101100"},
Users: s.setSecParamsList(),
},
SubAgents: []*GoSNMPServer.SubAgent{
{
UserErrorMarkPacket: false,
CommunityIDs: []string{"public", "private"}, // SNMPv1 and SNMPv2c community strings
OIDs: s.handleOIDs(),
//OIDs: mibImps.All(),
},
},
}
server := GoSNMPServer.NewSNMPServer(master)
err := server.ListenUDP("udp", s.ListenHost)
if err != nil {
log.Fatalf("Error in listen: %+v", err)
}
server.ServeForever()
}
func (s *SNMPService) handleOIDs() []*GoSNMPServer.PDUValueControlItem {
customOIDs := []*GoSNMPServer.PDUValueControlItem{
{
OID: "1.3.6.1.4.1.1379.2.3.3.3.1.1.1.0",
Type: g.OctetString,
OnGet: func() (value interface{}, err error) {
return s.SysName, nil
},
OnSet: func(value interface{}) error {
// 将[]uint8转换为string
if v, ok := value.([]uint8); ok {
s.SysName = string(v)
log.Printf("Set request for OID 1.3.6.1.4.1.1379.2.3.3.3.1.1.1.0 with value %v", s.SysName)
return nil
}
return nil
},
},
{
OID: ".1.3.6.1.4.1.1379.2.3.3.3.1.1.2.0",
Type: g.OctetString,
OnGet: func() (value interface{}, err error) {
return s.SysStatus, nil
},
OnSet: func(value interface{}) error {
// 将[]uint8转换为string
if v, ok := value.([]uint8); ok {
s.SysStatus = string(v)
log.Printf("Set request for OID 1.3.6.1.4.1.1379.2.3.3.3.1.1.2.0 with value %v", s.SysStatus)
return nil
}
return nil
},
},
{
OID: ".1.3.6.1.4.1.1379.2.3.3.3.1.1.3.0",
Type: g.OctetString,
OnGet: func() (value interface{}, err error) {
return s.SysDescr, nil
},
OnSet: func(value interface{}) error {
// 将[]uint8转换为string
if v, ok := value.([]uint8); ok {
s.SysDescr = string(v)
log.Printf("Set request for OID .1.3.6.1.4.1.1379.2.3.3.3.1.1.3.0 with value %v", s.SysDescr)
return nil
}
return nil
},
},
{
OID: ".1.3.6.1.4.1.1379.2.3.3.3.1.1.4.0",
Type: g.OctetString,
OnGet: func() (value interface{}, err error) {
return s.SysLocation, nil
},
OnSet: func(value interface{}) error {
// 将[]uint8转换为string
if v, ok := value.([]uint8); ok {
s.SysLocation = string(v)
log.Printf("Set request for OID .1.3.6.1.4.1.1379.2.3.3.3.1.1.4.0 with value %v", s.SysLocation)
return nil
}
return nil
},
},
{
OID: ".1.3.6.1.4.1.1379.2.3.3.3.1.1.5.0",
Type: g.OctetString,
OnGet: func() (value interface{}, err error) {
return s.SysContact, nil
},
OnSet: func(value interface{}) error {
// 将[]uint8转换为string
if v, ok := value.([]uint8); ok {
s.SysContact = string(v)
log.Printf("Set request for OID .1.3.6.1.4.1.1379.2.3.3.3.1.1.5.0 with value %v", s.SysContact)
return nil
}
return nil
},
},
{
OID: ".1.3.6.1.4.1.1379.2.3.3.3.1.1.7.0",
Type: g.TimeTicks,
OnGet: func() (value interface{}, err error) {
return uint32(time.Now().Unix()), nil
},
},
{
OID: ".1.3.6.1.4.1.1379.2.3.3.3.1.1.9.0",
Type: g.Integer,
OnGet: func() (value interface{}, err error) {
return s.SysService, nil
},
OnSet: func(value interface{}) error {
if v, ok := value.(int); ok {
s.SysService = v
log.Printf("Set request for OID .1.3.6.1.4.1.1379.2.3.3.3.1.1.9.0 with value %v", s.SysService)
return nil
}
return nil
},
},
}
// 为 GETBULK 新增处理 OIDs
bulkOIDs := &GoSNMPServer.PDUValueControlItem{
OID: ".1.3.6.1.4.1.1379.2.3.3.3.1.1", // 这里是您想要支持 GETBULK 的 OID 前缀
Type: g.OctetString,
OnGet: func() (value interface{}, err error) {
// 假设我们返回一百度值,您可以根据您的实现进行调整
values := []interface{}{s.SysName, s.SysStatus, s.SysDescr, s.SysLocation, s.SysContact, uint32(time.Now().Unix()), s.SysService} // 可以从其他结构中获取真实值
return values, nil
},
}
customOIDs = append(customOIDs, bulkOIDs)
// 获取mibImps.All()返回的OID列表
mibOIDs := mibImps.All()
// 使用Map来检测并移除重复的OID
oidMap := make(map[string]*GoSNMPServer.PDUValueControlItem)
for _, oid := range customOIDs {
oidMap[oid.OID] = oid
}
for _, oid := range mibOIDs {
if _, exists := oidMap[oid.OID]; !exists {
oidMap[oid.OID] = oid
} else {
log.Printf("Duplicate OID found: %s", oid.OID)
}
}
// 将Map转换为Slice
allOIDs := make([]*GoSNMPServer.PDUValueControlItem, 0, len(oidMap))
for _, oid := range oidMap {
allOIDs = append(allOIDs, oid)
}
return allOIDs
}
func (s *SNMPService) StartTrapServer() {
flag.Usage = func() {
fmt.Printf("Usage:\n")
fmt.Printf(" %s\n", filepath.Base(os.Args[0]))
flag.PrintDefaults()
}
tl := g.NewTrapListener()
tl.OnNewTrap = s.MyTrapHandler
usmTable := g.NewSnmpV3SecurityParametersTable(g.NewLogger(log.New(os.Stdout, "", 0)))
for i := range s.setSecParamsList() {
sp := &s.setSecParamsList()[i] // 使用指针
err := usmTable.Add(sp.UserName, sp)
if err != nil {
usmTable.Logger.Print(err)
}
}
// 设置引擎启动次数和引varvar
//var engineBoots uint32 = 1
// var engineTime uint32 = uint32(time.Now().Unix() % 2147483647) // 使用当前时间初始化
//var engineTime uint32 = 3600 // 使用当前时间初始化
gs := &g.GoSNMP{
Target: s.TrapTarget,
Port: s.TrapPort,
Transport: "udp",
Timeout: time.Duration(s.TimeOut) * time.Second, // 设置超时时间为x秒
Version: g.Version3, // Always using version3 for traps, only option that works with all SNMP versions simultaneously
MsgFlags: g.NoAuthNoPriv,
SecurityModel: g.UserSecurityModel,
SecurityParameters: &g.UsmSecurityParameters{
UserName: s.UserName,
AuthoritativeEngineID: s.EngineID,
AuthoritativeEngineBoots: 1,
//AuthoritativeEngineTime: 3600,
AuthenticationProtocol: s.getAuthProto(),
AuthenticationPassphrase: s.AuthPass,
PrivacyProtocol: s.getPrivProto(),
PrivacyPassphrase: s.PrivPass,
},
//TrapSecurityParametersTable: usmTable,
ContextEngineID: s.EngineID,
ContextName: "v3test",
}
tl.Params = gs
tl.Params.Logger = g.NewLogger(log.New(os.Stdout, "", 0))
// 定时发送Trap
if s.TrapBool {
go s.SendPeriodicTraps(gs)
}
go s.monitorNetwork(gs)
if s.TrapListen {
err := tl.Listen(s.TrapHost)
if err != nil {
log.Panicf("error in listen: %s", err)
}
}
}
func (s *SNMPService) MyTrapHandler(packet *g.SnmpPacket, addr *net.UDPAddr) {
log.Printf("got trapdata from %s\n", addr.IP)
for _, v := range packet.Variables {
switch v.Type {
case g.OctetString:
b := v.Value.([]byte)
fmt.Printf("OID: %s, string: %x\n", v.Name, b)
default:
log.Printf("trap: %+v\n", v)
}
}
}
func (s *SNMPService) SendPeriodicTraps(gs *g.GoSNMP) {
err := gs.Connect()
if err != nil {
log.Fatalf("Connect() err: %v", err)
}
defer gs.Conn.Close()
ticker := time.NewTicker(time.Duration(s.TrapTick) * time.Second) // 每10秒发送一次Trap
defer ticker.Stop()
for range ticker.C { // 每x秒发送一次Trap
trap := g.SnmpTrap{
Variables: []g.SnmpPDU{
{
Name: ".1.3.6.1.2.1.1.3.0",
Type: g.TimeTicks,
Value: uint32(time.Now().Unix()),
},
{
Name: ".1.3.6.1.6.3.1.1.4.1.0",
Type: g.ObjectIdentifier,
Value: ".1.3.6.1.6.3.1.1.5.1",
},
},
}
_, err = gs.SendTrap(trap)
if err != nil {
log.Printf("error sending trap: %s", err)
} else {
log.Printf("trap sent successfully")
}
}
}
// 1. 设备链路连接失败时发送Trap (LinkDown)
func (s *SNMPService) sendLinkDownTrap(gs *g.GoSNMP, ifIndex int, ifDescr string) {
err := gs.Connect()
if err != nil {
log.Fatalf("Connect() err: %v", err)
}
defer gs.Conn.Close()
trap := g.SnmpTrap{
Variables: []g.SnmpPDU{
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.1", // linkDown
Type: g.OctetString,
Value: ".1.3.6.1.4.1.1379.2.3.3.3.3.1",
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.1.1", // ifIndex
Type: g.Integer,
Value: ifIndex,
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.1.2", // ifDescr
Type: g.OctetString,
Value: ifDescr,
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.4", // severity OID
Type: g.Integer,
Value: 2, // event
},
},
}
_, err = gs.SendTrap(trap)
if err != nil {
log.Printf("error sending LinkDown trap: %s", err)
} else {
log.Printf("LinkDown trap sent successfully")
}
}
// 2. 设备链路恢复正常时发送Trap (LinkUp)
func (s *SNMPService) sendLinkUpTrap(gs *g.GoSNMP, ifIndex int, ifDescr string) {
err := gs.Connect()
if err != nil {
log.Fatalf("Connect() err: %v", err)
}
defer gs.Conn.Close()
trap := g.SnmpTrap{
Variables: []g.SnmpPDU{
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.2", // linkUp
Type: g.OctetString,
Value: ".1.3.6.1.4.1.1379.2.3.3.3.3.2",
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.2.1", // ifIndex
Type: g.Integer,
Value: ifIndex,
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.2.2", // ifDescr
Type: g.OctetString,
Value: ifDescr,
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.4", // severity OID
Type: g.Integer,
Value: 5, // event
},
},
}
_, err = gs.SendTrap(trap)
if err != nil {
log.Printf("error sending LinkUp trap: %s", err)
} else {
log.Printf("LinkUp trap sent successfully")
}
}
// 3. 设备鉴权失败时发送Trap (AuthenticationFailure)
func (s *SNMPService) sendAuthFailureTrap(gs *g.GoSNMP, username, descr string) {
err := gs.Connect()
if err != nil {
log.Fatalf("Connect() err: %v", err)
}
defer gs.Conn.Close()
trap := g.SnmpTrap{
Variables: []g.SnmpPDU{
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.3", // authenticationFailure
Type: g.OctetString,
Value: ".1.3.6.1.4.1.1379.2.3.3.3.3.3",
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.3.1", // 自定义OID用于记录失败的用户名
Type: g.OctetString,
Value: username,
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.3.3.2", // 自定义OID用于记录描述
Type: g.OctetString,
Value: descr,
},
{
Name: ".1.3.6.1.4.1.1379.2.3.3.3.4", // severity OID
Type: g.Integer,
Value: 4, // event
},
},
}
_, err = gs.SendTrap(trap)
if err != nil {
log.Printf("error sending AuthenticationFailure trap: %s", err)
} else {
log.Printf("AuthenticationFailure trap sent successfully")
}
}
func (s *SNMPService) monitorNetwork(gs *g.GoSNMP) {
// 假设有一个函数 checkLinkStatus 返回链路状态
for {
serviceStatus := s.checkServiceStatus()
switch strings.ToUpper(serviceStatus) {
case "LINK_DOWN":
index := 1
ifDescr := fmt.Sprintf("Link(index=%d) DOWN", index)
s.sendLinkDownTrap(gs, index, ifDescr) // 假设接口索引为1
s.SysService = 0
case "LINK_UP":
index := 1
ifDescr := fmt.Sprintf("Link(index=%d) UP", index)
s.sendLinkUpTrap(gs, index, ifDescr) // 假设接口索引为1
s.SysService = 0
case "AUTH_FAILURE":
descr := "Authentication Failure"
s.sendAuthFailureTrap(gs, s.UserName, descr)
s.SysService = 0
default:
}
time.Sleep(10 * time.Second) // 每10秒检查一次
}
}
func (s *SNMPService) checkServiceStatus() string {
switch s.SysService {
case 1:
return "LINK_DOWN"
case 2:
return "LINK_UP"
case 3:
return "AUTH_FAILURE"
default:
}
return "NORMAL"
}

View File

@@ -1,575 +0,0 @@
package main
import (
"bufio"
"fmt"
"io"
"net"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/mmlp"
"be.ems/sshsvc/config"
"be.ems/sshsvc/dborm"
"be.ems/sshsvc/logmml"
"be.ems/sshsvc/snmp"
omctelnet "be.ems/sshsvc/telnet"
//"github.com/gliderlabs/ssh"
"golang.org/x/crypto/ssh"
"golang.org/x/term"
)
var conf *config.YamlConfig
var (
telnetCC int
sshCC int
telnetMu sync.Mutex
sshMu sync.Mutex
)
func init() {
conf = config.GetYamlConfig()
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:sshsvc", config.GetLogLevel())
fmt.Printf("OMC sshsvc version: %s\n", global.Version)
log.Infof("========================= OMC sshsvc startup =========================")
log.Infof("OMC sshsvc version: %s %s %s", global.Version, global.BuildTime, global.GoVer)
db := conf.Database
err := dborm.InitDbClient(db.Type, db.User, db.Password, db.Host, db.Port, db.Name, db.ConnParam)
if err != nil {
fmt.Println("dborm.initDbClient err:", err)
os.Exit(1)
}
logmml.InitMmlLogger(conf.Logmml.File, conf.Logmml.Duration, conf.Logmml.Count, "omc", config.GetLogMmlLevel())
}
// readPrivateKey 读取SSH私钥如果不存在则生成新的密钥对
func readPrivateKey() ssh.Signer {
// 检查私钥文件是否存在
if _, err := os.Stat(conf.Sshd.PrivateKey); os.IsNotExist(err) {
// 如果文件不存在,创建目录并生成密钥
dir := filepath.Dir(conf.Sshd.PrivateKey)
if err := os.MkdirAll(dir, 0700); err != nil {
log.Fatal("Failed to create .ssh directory:", err)
os.Exit(2)
}
// 使用ssh-keygen命令生成密钥对
cmd := exec.Command("ssh-keygen", "-t", "rsa", "-P", "", "-f", conf.Sshd.PrivateKey)
if err := cmd.Run(); err != nil {
log.Fatal("Failed to generate SSH key:", err)
os.Exit(2)
}
}
// 读取SSH密钥对
privateKeyBytes, err := os.ReadFile(conf.Sshd.PrivateKey)
if err != nil {
log.Fatal("Failed to ReadFile", err)
os.Exit(2)
}
privateKey, err := ssh.ParsePrivateKey(privateKeyBytes)
if err != nil {
log.Fatal("Failed to ParsePrivateKey", err)
os.Exit(3)
}
return privateKey
}
func main() {
// 配置SSH服务器
serverConfig := &ssh.ServerConfig{
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
// 这里可以进行密码验证逻辑,例如检查用户名和密码是否匹配
// validUser, _, err := dborm.XormCheckLoginUser(conn.User(), string(password), conf.OMC.UserCrypt)
// if err != nil {
// return nil, err
// }
// if validUser == true {
// sessionToken := fmt.Sprintf("%x", conn.SessionID()) // Generate new token to session ID
// sourceAddr := conn.RemoteAddr().String()
// timeOut := uint32(conf.Sshd.Timeout)
// sessionMode := conf.Sshd.Session
// log.Debugf("token:%s sourceAddr:%s", sessionToken, sourceAddr)
// affected, err := dborm.XormInsertSession(conn.User(), sourceAddr, sessionToken, timeOut, sessionMode)
// if err != nil {
// log.Error("Failed to insert Session table:", err)
// return nil, err
// }
// if affected == -1 {
// err := errors.New("Failed to get session")
// log.Error(err)
// return nil, err
// }
// return nil, nil
// }
if handleAuth(conf.Sshd.AuthType, conn.User(), string(password)) {
return nil, nil
}
return nil, fmt.Errorf("invalid user or password")
},
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
// 这里可以进行公钥验证逻辑,例如检查用户的公钥是否在允许的公钥列表中
return nil, fmt.Errorf("public key authentication is failed")
},
}
privateKey := readPrivateKey()
serverConfig.AddHostKey(privateKey)
// 启动SSH服务器
hostUri := fmt.Sprintf("%s:%d", conf.Sshd.ListenAddr, conf.Sshd.ListenPort)
listener, err := net.Listen("tcp", hostUri)
if err != nil {
log.Fatal("Failed to Listen: ", err)
os.Exit(4)
}
//fmt.Printf("MML SSH server startup, listen port%d\n", conf.Sshd.ListenPort)
// 启动telnet服务器
//telnetUri := fmt.Sprintf("%s:%d", conf.TelnetServer.ListenAddr, conf.TelnetServer.ListenPort)
// telnetListener, err := net.Listen("tcp", telnetUri)
// if err != nil {
// log.Fatal("Failed to Listen: ", err)
// os.Exit(4)
// }
//fmt.Printf("MML Telnet server startup, listen port%d\n", conf.TelnetServer.ListenPort)
// telnetconn, err := telnetListener.Accept()
// if err != nil {
// log.Fatal("Failed to accept telnet connection: ", err)
// os.Exit(6)
// }
telnetSvc := omctelnet.TelnetHandler{
ListenAddr: conf.TelnetServer.ListenAddr,
ListenPort: conf.TelnetServer.ListenPort,
UserName: conf.TelnetServer.UserName,
Password: conf.TelnetServer.Password,
AuthType: conf.TelnetServer.AuthType,
MaxConnNum: conf.TelnetServer.MaxConnNum,
TagNE: conf.TelnetServer.TagNE,
ListenHost: conf.TelnetServer.ListenAddr + ":" + strconv.Itoa(int(conf.TelnetServer.ListenPort)),
}
go telnetSvc.StartTelnetServer()
// go StartTelnetServer(telnetSvc.ListenHost)
snmpSvc := snmp.SNMPService{
ListenAddr: conf.SNMPServer.ListenAddr,
ListenPort: conf.SNMPServer.ListenPort,
UserName: conf.SNMPServer.UserName,
AuthPass: conf.SNMPServer.AuthPass,
AuthProto: conf.SNMPServer.AuthProto,
PrivPass: conf.SNMPServer.PrivPass,
PrivProto: conf.SNMPServer.PrivProto,
EngineID: conf.SNMPServer.EngineID,
TrapPort: conf.SNMPServer.TrapPort,
TrapListen: conf.SNMPServer.TrapListen,
TrapBool: conf.SNMPServer.TrapBool,
TrapTick: conf.SNMPServer.TrapTick,
TimeOut: conf.SNMPServer.TimeOut,
TrapTarget: conf.SNMPServer.TrapTarget,
ListenHost: conf.SNMPServer.ListenAddr + ":" + strconv.Itoa(int(conf.SNMPServer.ListenPort)),
TrapHost: conf.SNMPServer.ListenAddr + ":" + strconv.Itoa(int(conf.SNMPServer.TrapPort)),
SysName: "HLR-0",
SysStatus: "Normal",
SysDescr: "HLR server(sysNO=0)",
SysLocation: "Shanghai",
SysContact: "",
SysService: 0,
}
go snmpSvc.StartSNMPServer()
go snmpSvc.StartTrapServer()
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal("Failed to Accept: ", err)
os.Exit(5)
}
go handleSSHConnection(conn, serverConfig)
}
}
func handleAuth(authType, userName, password string) bool {
switch authType {
case "local":
if userName == conf.Sshd.UserName && password == conf.Sshd.Password {
return true
}
return false
case "radius":
exist, err := dborm.XEngDB().Table("OMC_PUB.sysUser").Where("userName=? AND password=md5(?)", userName, password).Exist()
if err != nil {
return false
}
return exist
case "omc":
default:
}
return false
}
func StartTelnetServer(addr string) {
listener, err := net.Listen("tcp", addr)
if err != nil {
fmt.Println("Error starting Telnet server:", err)
return
}
defer listener.Close()
fmt.Println("Telnet server started on", addr)
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting Telnet connection:", err)
continue
}
telnetMu.Lock()
if telnetCC >= int(conf.TelnetServer.MaxConnNum) {
telnetMu.Unlock()
io.WriteString(conn, "Connection limit reached. Try again later.\r\n")
conn.Close()
continue
}
telnetCC++
telnetMu.Unlock()
go handleTelnetConnection(conn)
}
}
func handleTelnetConnection(conn net.Conn) {
defer func() {
telnetMu.Lock()
telnetCC--
telnetMu.Unlock()
}()
defer conn.Close()
reader := bufio.NewReader(conn)
writer := bufio.NewWriter(conn)
// 发送欢迎信息
writer.WriteString("Welcome to the Telnet server!\r\n")
writer.Flush()
// 请求用户名
writer.WriteString("Username: ")
writer.Flush()
user, _ := reader.ReadString('\n')
user = strings.TrimSpace(user)
// 关闭回显模式
writer.Write([]byte{255, 251, 1}) // IAC WILL ECHO
writer.Flush()
// 请求密码
writer.WriteString("Password: ")
writer.Flush()
// 读取密码并清除控制序列
var passBuilder strings.Builder
for {
b, err := reader.ReadByte()
if err != nil {
return
}
if b == '\n' || b == '\r' {
break
}
if b == 255 { // IAC
reader.ReadByte() // 忽略下一个字节
reader.ReadByte() // 忽略下一个字节
} else {
passBuilder.WriteByte(b)
}
}
pass := passBuilder.String()
// 恢复回显模式
writer.Write([]byte{255, 252, 1}) // IAC WONT ECHO
writer.Flush()
if handleAuth(conf.TelnetServer.AuthType, user, pass) {
writer.WriteString("\r\nAuthentication successful!\r\n")
writer.Flush()
HandleCommands(user, conf.TelnetServer.TagNE, reader, writer)
} else {
writer.WriteString("\r\nAuthentication failed!\r\n")
writer.Flush()
}
}
// 处理命令输
func HandleCommands(user, tag string, reader *bufio.Reader, writer *bufio.Writer) {
header := fmt.Sprintf("[%s@%s]> ", user, tag)
clearLine := "\033[2K\r" // ANSI 转义序列,用于清除当前行
for {
var commandBuilder strings.Builder
for {
b, err := reader.ReadByte()
if err != nil {
return
}
if b == '\n' || b == '\r' {
break
}
if b == '\xff' || b == '\xfe' || b == '\x01' {
continue
}
if b == 127 { // 处理退格键
if commandBuilder.Len() > 0 {
// 手动截断字符串
command := commandBuilder.String()
command = command[:len(command)-1]
commandBuilder.Reset()
commandBuilder.WriteString(command)
writer.WriteString("\b \b") // 回显退格
writer.Flush()
}
} else {
// 回显用户输入的字符
writer.WriteByte(b)
writer.Flush()
commandBuilder.WriteByte(b)
}
}
command := strings.TrimSpace(commandBuilder.String())
// 处理其他命令
switch command {
case "hello":
writer.WriteString("\r\nHello, world!\r\n")
case "time":
writer.WriteString(fmt.Sprintf("\r\nCurrent time: %s\r\n", time.Now().Format(time.RFC1123)))
case "exit", "quit":
writer.WriteString("\r\nGoodbye!\r\n")
writer.Flush()
return
case "":
default:
writer.WriteString("\r\nUnknown command\r\n")
writer.Flush()
}
writer.WriteString(clearLine + header)
writer.Flush()
}
}
func handleSSHConnection(conn net.Conn, serverConfig *ssh.ServerConfig) {
// SSH握手
sshConn, chans, reqs, err := ssh.NewServerConn(conn, serverConfig)
if err != nil {
log.Error("Failed to NewServerConn: ", err)
return
}
log.Infof("SSH connect acceptedclient version%suser%s", sshConn.ClientVersion(), sshConn.User())
// 处理SSH请求
go ssh.DiscardRequests(reqs)
// 处理SSH通道
for newChannel := range chans {
if newChannel.ChannelType() != "session" {
newChannel.Reject(ssh.UnknownChannelType, "unsupported channel type")
continue
}
channel, requests, err := newChannel.Accept()
if err != nil {
log.Error("Failed to NewServerConn: ", err)
continue
}
sshMu.Lock()
sshCC++
if sshCC > int(conf.Sshd.MaxConnNum) {
sshMu.Unlock()
log.Error("Maximum number of connections exceeded")
channel.Write([]byte(fmt.Sprintf("Connection limit reached (limit=%d). Try again later.\r\n", conf.Sshd.MaxConnNum)))
conn.Close()
continue
}
sshMu.Unlock()
go handleSSHChannel(conn, sshConn, channel, requests)
}
}
func handleSSHChannel(conn net.Conn, sshConn *ssh.ServerConn, channel ssh.Channel, requests <-chan *ssh.Request) {
for req := range requests {
switch req.Type {
case "exec":
// 执行远程命令
command := strings.TrimSpace(string(req.Payload))[4:]
//cmd := exec.Command(
cmd := exec.Command("cmd", "/C", command)
cmd.Stdin = channel
cmd.Stdout = channel
cmd.Stderr = channel.Stderr()
log.Trace("command:", command)
err := cmd.Run()
if err != nil {
log.Error("Failed to cmd.Run: ", err)
}
channel.SendRequest("exit-status", false, []byte{0, 0, 0, 0})
channel.Close()
closeConnection(conn)
// case "shell":
// // 处理交互式shell会话
// // 在这里添加您的处理逻辑例如启动一个shell进程并将其连接到channel
// // 请注意处理交互式shell会话需要更复杂的逻辑您可能需要使用类似于pty包来处理终端相关的操作
// channel.Write([]byte("交互式shell会话已启动\n"))
// channel.Close()
// handleSSHShell(user, channel)
case "pty-req":
log.Info("A pty-req processing...")
req.Reply(true, nil)
handleSSHShell(sshConn, channel)
channel.SendRequest("exit-status", false, []byte{0, 0, 0, 0})
channel.Close()
closeConnection(conn)
log.Info("Channel closed")
default:
req.Reply(false, nil)
}
}
}
func closeConnection(conn net.Conn) {
sshMu.Lock()
conn.Close()
sshCC--
sshMu.Unlock()
}
func handleSSHShell(sshConn *ssh.ServerConn, channel ssh.Channel) {
//conf = config.GetYamlConfig()
// 检查通道是否支持终端
omcMmlVar := &mmlp.MmlVar{
Version: global.Version,
Output: mmlp.DefaultFormatType,
MmlHome: conf.Sshd.MmlHome,
Limit: conf.Sshd.MaxConnNum,
User: sshConn.User(),
SessionToken: fmt.Sprintf("%x", sshConn.SessionID()),
HttpUri: conf.OMC.HttpUri,
UserAgent: config.GetDefaultUserAgent(),
TagNE: conf.Sshd.TagNE,
}
term := term.NewTerminal(channel, fmt.Sprintf("[%s@%s]> ", omcMmlVar.User, omcMmlVar.TagNE))
msg := fmt.Sprintf("\r\nWelcome to the %s server!\r\n", strings.ToUpper(omcMmlVar.TagNE))
term.Write([]byte(msg))
msg = fmt.Sprintf("Last login: %s from %s \r\n\r\n", time.Now().Format(time.RFC1123), sshConn.RemoteAddr())
term.Write([]byte(msg))
// 启动交互式shell会话
for {
line, err := term.ReadLine()
if err != nil {
if err == io.EOF {
break
}
log.Error("Failed to read line: ", err)
break
}
cmdline := strings.TrimSpace(line)
if cmdline != "" {
logmml.Cmd(cmdline)
}
var response string
switch cmdline {
case "hello":
term.Write([]byte("Hello, world!\r\n"))
goto continueLoop
case "time":
response = fmt.Sprintf("Current time: %s\r\n", time.Now().Format(time.RFC1123))
term.Write([]byte(response))
goto continueLoop
case "exit", "quit":
goto exitLoop
case "":
goto continueLoop
case "help":
response = fmt.Sprintf("Usage: %s\n", line)
term.Write([]byte(response))
goto continueLoop
case "dsp variables":
response = fmt.Sprintf("version: %s\n Output: %s\n", omcMmlVar.Version, omcMmlVar.Output)
term.Write([]byte(response))
goto continueLoop
case "set mml output=json":
// mmlp.SetOmcMmlVarOutput("json")
omcMmlVar.Output = "json"
response = fmt.Sprintf("set ok, mmlVar.output = %s\n", omcMmlVar.Output)
term.Write([]byte(response))
goto continueLoop
case "set mml output=table":
// mmlp.SetOmcMmlVarOutput("table")
omcMmlVar.Output = "table"
response = fmt.Sprintf("set ok, mmlVar.output = %s\n", omcMmlVar.Output)
term.Write([]byte(response))
goto continueLoop
default:
var mmlCmds []mmlp.MmlCommand
mmlLine := strings.TrimSpace(line)
if err = mmlp.ParseMMLCommand(mmlLine, &mmlCmds); err != nil {
response = fmt.Sprintf("parse command error: %v\n", err)
term.Write([]byte(response))
goto continueLoop
}
// if err = mmlp.ParseMMLParams(&mmlCmds); err != nil {
// response := fmt.Sprintf("#2 parse command error: %v\n", err)
// term.Write([]byte(response))
// }
for _, mmlCmd := range mmlCmds {
output, err := mmlp.TransMml2HttpReq(omcMmlVar, &mmlCmd)
if err != nil {
response = fmt.Sprintf("translate MML command error: %v\n", err)
term.Write([]byte(response))
goto continueLoop
}
response = string(*output)
term.Write(*output)
}
goto continueLoop
}
continueLoop:
if response != "" {
logmml.Ret(response)
}
continue
exitLoop:
token := fmt.Sprintf("%x", sshConn.SessionID())
_, err = dborm.XormLogoutUpdateSession(token)
if err != nil {
log.Error("Failed to XormLogoutUpdateSession:", err)
}
break
}
}

View File

@@ -1,198 +0,0 @@
package omctelnet
import (
"bufio"
"fmt"
"io"
"net"
"strings"
"sync"
"time"
"be.ems/sshsvc/dborm"
)
type TelnetHandler struct {
ListenAddr string
ListenPort uint16
UserName string
Password string
AuthType string
MaxConnNum int
TagNE string
ListenHost string
connCount int
mu sync.Mutex
}
func (t *TelnetHandler) handleTelnetAuth(authType, userName, password string) bool {
switch authType {
case "local":
if userName == t.UserName && password == t.Password {
return true
}
return false
case "radius", "omc":
exist, err := dborm.XEngDB().Table("OMC_PUB.sysUser").Where("userName=? AND password=md5(?)", userName, password).Exist()
if err != nil {
return false
}
return exist
default:
}
return false
}
func (t *TelnetHandler) StartTelnetServer() {
listener, err := net.Listen("tcp", t.ListenHost)
if err != nil {
fmt.Println("Error starting Telnet server:", err)
return
}
defer listener.Close()
fmt.Println("Telnet server started on", t.ListenHost)
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting Telnet connection:", err)
continue
}
t.mu.Lock()
if t.connCount >= int(t.MaxConnNum) {
t.mu.Unlock()
msg := fmt.Sprintf("Connection limit reached (limit=%d). Try again later.\r\n", t.MaxConnNum)
io.WriteString(conn, msg)
conn.Close()
continue
}
t.connCount++
t.mu.Unlock()
go t.handleTelnetConnection(conn)
}
}
func (t *TelnetHandler) handleTelnetConnection(conn net.Conn) {
defer func() {
t.mu.Lock()
t.connCount--
t.mu.Unlock()
}()
defer conn.Close()
reader := bufio.NewReader(conn)
writer := bufio.NewWriter(conn)
// 发送欢迎信息
writer.WriteString(fmt.Sprintf("\r\nWelcome to the %s server!\r\n", strings.ToUpper(t.TagNE)))
writer.Flush()
// 请求用户名
writer.WriteString("Username: ")
writer.Flush()
user, _ := reader.ReadString('\n')
user = strings.TrimSpace(user)
// 关闭回显模式
writer.Write([]byte{255, 251, 1}) // IAC WILL ECHO
writer.Flush()
// 请求密码
writer.WriteString("Password: ")
writer.Flush()
// 读取密码并清除控制序列
var passBuilder strings.Builder
for {
b, err := reader.ReadByte()
if err != nil {
return
}
if b == '\n' || b == '\r' {
break
}
if b == 255 { // IAC
reader.ReadByte() // 忽略下一个字节
reader.ReadByte() // 忽略下一个字节
} else {
passBuilder.WriteByte(b)
}
}
pass := passBuilder.String()
// 恢复回显模式
writer.Write([]byte{255, 252, 1}) // IAC WONT ECHO
writer.Flush()
if t.handleTelnetAuth(t.AuthType, user, pass) {
msg := fmt.Sprintf("\r\n\r\nLast login: %s from %s \r\n\r\n", time.Now().Format(time.RFC1123), conn.RemoteAddr())
writer.WriteString(msg)
writer.Flush()
t.HandleCommands(user, t.TagNE, reader, writer)
} else {
writer.WriteString("\r\nAuthentication failed!\r\n")
writer.Flush()
}
}
// 处理命令输
func (t *TelnetHandler) HandleCommands(user, tag string, reader *bufio.Reader, writer *bufio.Writer) {
header := fmt.Sprintf("[%s@%s]> ", user, tag)
clearLine := "\033[2K\r" // ANSI 转义序列,用于清除当前行
for {
var commandBuilder strings.Builder
for {
b, err := reader.ReadByte()
if err != nil {
return
}
if b == '\n' || b == '\r' {
break
}
if b == '\xff' || b == '\xfe' || b == '\x01' {
continue
}
if b == 127 { // 处理退格键
if commandBuilder.Len() > 0 {
// 手动截断字符串
command := commandBuilder.String()
command = command[:len(command)-1]
commandBuilder.Reset()
commandBuilder.WriteString(command)
writer.WriteString("\b \b") // 回显退格
writer.Flush()
}
} else {
// 回显用户输入的字符
writer.WriteByte(b)
writer.Flush()
commandBuilder.WriteByte(b)
}
}
command := strings.TrimSpace(commandBuilder.String())
// 处理其他命令
switch command {
case "hello":
writer.WriteString("\r\nHello, world!\r\n")
case "time":
writer.WriteString(fmt.Sprintf("\r\nCurrent time: %s\r\n", time.Now().Format(time.RFC1123)))
case "exit", "quit":
writer.WriteString("\r\n\r\nGoodbye!\r\n")
writer.Flush()
return
case "":
default:
writer.WriteString("\r\nUnknown command\r\n")
writer.Flush()
}
writer.WriteString(clearLine + header)
writer.Flush()
}
}