del: 移除features、lib和sshsvc目录
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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(¶mData); 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()))
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
@@ -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.com(SSL协议端口: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)
|
||||
}
|
||||
@@ -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,
|
||||
// }
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
@@ -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), ¶ms); 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
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
@@ -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 ""
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)]
|
||||
}
|
||||
@@ -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)
|
||||
// }
|
||||
// }
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
1561
lib/dborm/dborm.go
1561
lib/dborm/dborm.go
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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")
|
||||
)
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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) {}
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
1059
lib/mmlp/parse.go
1059
lib/mmlp/parse.go
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
@@ -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] }
|
||||
@@ -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})
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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-----
|
||||
@@ -1 +0,0 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCjzE0MHy0P2sQmG1OKvArwLEzR77BwxPp+4N9NKBz8lEyNch4zoHvoLDaUJKPBMwTrScZnxhvRJNde6hz5Z0QVxZolVKV95fMfgb9YICzDfPF3Bphae5q/PBYUJNfrC9SAjQeHV4CCO6xk6LV8O/Nfw8uaXwtuN3yfpUWd5mRWKMc3GHV4vxerfKoIQZN6etLhIEYibAhCJ21P0uoWzZl7ceLmkG+6qrRSbyC0bCnrN3+wjN4bwtflrEFJk3XQGuRbVsYLzux+mMm9p22+CLPRl/FUPF3x4/wKCsqr7JDSxx80HSPhk4g/1nCTpDR9hAfF6A9ww2va/k8jMeYPBO8Owe7erLEZzvg5WQAR3Wj05eJpJD99BeC91S5KW6AFQDfDHxWWprSibd/Jj9dtct2pK2ZxW0ph9OJ49ftRhzT1iVi4UnJwnG5/qLfwl6Tnx+qnQ1If/9lY/99erCTATzFTMSImKrRz7CnuPlcw8WkzCYpWKKe0kJLkL2cRD5Qi4yk= simon@simonzhangsz
|
||||
@@ -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-----
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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.
@@ -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.
@@ -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() {
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
575
sshsvc/sshsvc.go
575
sshsvc/sshsvc.go
@@ -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 accepted,client version:%s,user:%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
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user