feat: omc界面配置参数添加信令跟踪开关

This commit is contained in:
TsMask
2025-06-10 18:52:03 +08:00
parent 9be1b8fb3e
commit 4fe372f418
6 changed files with 184 additions and 97 deletions

View File

@@ -30,7 +30,7 @@ func initFlag() {
pflag.String("env", "prod", "Specify Run Environment Configuration local or prod")
// --c /etc/restconf.yaml
// -c /etc/restconf.yaml
pflag.StringP("config", "c", "./etc/restconf.yaml", "Specify Configuration File")
pflag.StringP("config", "c", "/usr/local/omc/etc/restconf.yaml", "Specify Configuration File")
// --version
// -V
pVersion := pflag.BoolP("version", "V", false, "Output program version")
@@ -171,6 +171,13 @@ func Get(key string) any {
return cfg.Get(key)
}
// Set 设置配置信息
//
// Set("redis.defaultDataSourceName", "std")
func Set(key string, value any) {
cfg.Set(key, value)
}
// GetAssetsDirFS 访问程序内全局资源访问
func GetAssetsDirFS() embed.FS {
return cfg.Get("AssetsDir").(embed.FS)

View File

@@ -2,18 +2,19 @@ package controller
import (
"encoding/json"
"strings"
"fmt"
cm_omc "be.ems/features/cm/omc"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/parse"
"be.ems/src/framework/vo/result"
neFetchlink "be.ems/src/modules/network_element/fetch_link"
"be.ems/src/modules/network_element/model"
neService "be.ems/src/modules/network_element/service"
traceService "be.ems/src/modules/trace/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// NewNeConfig 网元参数配置 实例化控制层
@@ -33,74 +34,74 @@ type NeConfigController struct {
// 网元参数配置可用属性值列表
//
// GET /list
func (s *NeConfigController) List(c *gin.Context) {
querys := ctx.QueryMapString(c)
rows, total := s.neConfigService.SelectPage(querys)
c.JSON(200, result.Ok(map[string]any{"total": total, "rows": rows}))
func (s NeConfigController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
rows, total := s.neConfigService.SelectPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// 网元参数配置可用属性值信息
//
// GET /info/:id
func (s *NeConfigController) Info(c *gin.Context) {
language := ctx.AcceptLanguage(c)
id := c.Param("id")
func (s NeConfigController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := c.Query("id")
if id == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
data := s.neConfigService.SelectById(id)
if data.ID != id {
// 没有可访问参数配置数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neConfig.noData")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfig.noData")))
return
}
// 将字符串转json数据
if err := json.Unmarshal([]byte(data.ParamJson), &data.ParamData); err != nil {
c.JSON(400, result.CodeMsg(400, err.Error()))
c.JSON(400, resp.CodeMsg(400, err.Error()))
return
}
c.JSON(200, result.OkData(data))
c.JSON(200, resp.OkData(data))
}
// 网元参数配置可用属性值新增
//
// POST /
func (s *NeConfigController) Add(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s NeConfigController) Add(c *gin.Context) {
var body model.NeConfig
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 将json数据转字符串存储
paramDataByte, err := json.Marshal(body.ParamData)
if err != nil {
c.JSON(400, result.CodeMsg(400, err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
body.ParamJson = string(paramDataByte)
insertId := s.neConfigService.Insert(body)
if insertId != "" {
c.JSON(200, result.Ok(nil))
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
}
// 网元参数配置可用属性值修改
//
// PUT /
func (s *NeConfigController) Edit(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s NeConfigController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeConfig
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
@@ -108,50 +109,50 @@ func (s *NeConfigController) Edit(c *gin.Context) {
data := s.neConfigService.SelectById(body.ID)
if data.ID != body.ID {
// 没有可访问主机命令数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neConfig.noData")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfig.noData")))
return
}
// 将json数据转字符串存储
paramDataByte, err := json.Marshal(body.ParamData)
if err != nil {
c.JSON(400, result.CodeMsg(400, err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
body.ParamJson = string(paramDataByte)
rows := s.neConfigService.Update(body)
if rows > 0 {
c.JSON(200, result.Ok(nil))
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
}
// 网元参数配置可用属性值删除
//
// DELETE /
func (s *NeConfigController) Remove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
id, okId := c.GetQuery("id")
if id == "" || !okId {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
func (s NeConfigController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := c.Query("id")
if id == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
// 处理字符转id数组后去重
idsArr := strings.Split(id, ",")
uniqueIDs := parse.RemoveDuplicates(idsArr)
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
return
}
rows, err := s.neConfigService.DeleteByIds(uniqueIDs)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, result.OkMsg(msg))
c.JSON(200, resp.OkMsg(msg))
}
// 网元参数配置可用属性值列表指定网元类型全部无分页
@@ -161,21 +162,20 @@ func (s *NeConfigController) Remove(c *gin.Context) {
// @Tags network_element/config
// @Accept json
// @Produce json
// @Param neType path string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC)
// @Param neType path string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network Element Parameter Configuration Available Attribute Values List Specify Network Element Type All Unpaged
// @Description Network Element Parameter Configuration Available Attribute Values List Specify Network Element Type All Unpaged
// @Router /ne/config/list/{neType} [get]
func (s *NeConfigController) ListByNeType(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s NeConfigController) ListByNeType(c *gin.Context) {
neType := c.Param("neType")
if neType == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: neType is empty"))
return
}
data := s.neConfigService.SelectNeConfigByNeType(neType)
c.JSON(200, result.OkData(data))
c.JSON(200, resp.OkData(data))
}
// 网元参数配置数据信息
@@ -185,7 +185,7 @@ func (s *NeConfigController) ListByNeType(c *gin.Context) {
// @Tags network_element/config
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC)
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Param paramName query string true "Available attributes, based on querying the list of attributes"
// @Success 200 {object} object "Response Results"
@@ -193,43 +193,49 @@ func (s *NeConfigController) ListByNeType(c *gin.Context) {
// @Summary Network Element Parameter Configuration Data Information
// @Description Network Element Parameter Configuration Data Information
// @Router /ne/config/data [get]
func (s *NeConfigController) DataInfo(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s NeConfigController) DataInfo(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {
NeType string `form:"neType" binding:"required"` // 网元类型
NeId string `form:"neId" binding:"required"` // 网元ID
ParamName string `form:"paramName" binding:"required"` // 可用属性
}
if err := c.ShouldBindQuery(&query); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(query.NeType, query.NeId)
neInfo := s.neInfoService.FindByNeTypeAndNeID(query.NeType, query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
if query.NeType == "OMC" {
var o *cm_omc.ConfigOMC
resData, err := o.Query(query.ParamName)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
if query.ParamName == "alarmEmailForward" || query.ParamName == "alarmSMSForward" {
var o *cm_omc.ConfigOMC
resData, err := o.Query(query.ParamName)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(resData))
return
}
c.JSON(200, result.OkData(resData))
resData := s.neConfigService.GetOMCYaml(query.ParamName)
c.JSON(200, resp.OkData(resData))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigInfo(neInfo, query.ParamName)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(resData))
c.JSON(200, resp.Ok(resData))
}
// 网元参数配置数据修改
@@ -245,8 +251,8 @@ func (s *NeConfigController) DataInfo(c *gin.Context) {
// @Summary Network element parameter configuration data modification
// @Description Network element parameter configuration data modification
// @Router /ne/config/data [put]
func (s *NeConfigController) DataEdit(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s NeConfigController) DataEdit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"` // 网元类型
NeId string `json:"neId" binding:"required"` // 网元ID
@@ -254,34 +260,48 @@ func (s *NeConfigController) DataEdit(c *gin.Context) {
ParamData map[string]any `json:"paramData" binding:"required"`
Loc string `json:"loc"` // 仅array使用与数据对象内index一致,有多层时划分嵌套层(index/subParamName/index)
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeId)
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
if body.NeType == "OMC" {
var o *cm_omc.ConfigOMC
resData, err := o.Modify(body.ParamName, body.ParamData)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
if body.ParamName == "alarmEmailForward" || body.ParamName == "alarmSMSForward" {
var o *cm_omc.ConfigOMC
resData, err := o.Modify(body.ParamName, body.ParamData)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(resData))
return
}
c.JSON(200, result.OkData(resData))
err := s.neConfigService.ModifyOMCYaml(body.ParamName, body.Loc, body.ParamData)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 重开跟踪任务信令数据通道UDP
if body.ParamName == "trace" {
traceService.NewTraceTask.CreateUDP(true)
}
c.JSON(200, resp.Ok(nil))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigUpdate(neInfo, body.ParamName, body.Loc, body.ParamData)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(resData))
c.JSON(200, resp.OkData(resData))
}
// 网元参数配置数据新增array
@@ -297,8 +317,8 @@ func (s *NeConfigController) DataEdit(c *gin.Context) {
// @Summary Network element parameter configuration data added (array)
// @Description Network element parameter configuration data added (array)
// @Router /ne/config/data [post]
func (s *NeConfigController) DataAdd(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s NeConfigController) DataAdd(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"` // 网元类型
NeId string `json:"neId" binding:"required"` // 网元ID
@@ -306,37 +326,38 @@ func (s *NeConfigController) DataAdd(c *gin.Context) {
ParamData map[string]any `json:"paramData" binding:"required"` // 数据对象
Loc string `json:"loc" binding:"required"` // 与数据对象内index一致,有多层时划分嵌套层(index/subParamName/index)
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否array
info := s.neConfigService.SelectNeConfigByNeTypeAndParamName(body.NeType, body.ParamName)
if info.ParamType != "array" {
c.JSON(400, result.CodeMsg(400, "this attribute does not support adding"))
c.JSON(200, resp.ErrMsg("this attribute does not support adding"))
return
}
// 必须含有index
_, idxOk := body.ParamData["index"]
if info.ParamType == "array" && !idxOk {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(200, resp.ErrMsg("array data must contain index"))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeId)
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigInstall(neInfo, body.ParamName, body.Loc, body.ParamData)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(resData))
c.JSON(200, resp.OkData(resData))
}
// 网元参数配置数据删除array
@@ -346,7 +367,7 @@ func (s *NeConfigController) DataAdd(c *gin.Context) {
// @Tags network_element/config
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC)
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Param paramName query string true "Available attributes, based on querying the list of attributes"
// @Param loc query string true "Array index"
@@ -355,8 +376,8 @@ func (s *NeConfigController) DataAdd(c *gin.Context) {
// @Summary Network element parameter configuration data deletion (array)
// @Description Network element parameter configuration data deletion (array)
// @Router /ne/config/data [delete]
func (s *NeConfigController) DataRemove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s NeConfigController) DataRemove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {
NeType string `form:"neType" binding:"required"` // 网元类型
NeId string `form:"neId" binding:"required"` // 网元ID
@@ -364,28 +385,29 @@ func (s *NeConfigController) DataRemove(c *gin.Context) {
Loc string `form:"loc" binding:"required"` // 与数据对象内index一致,有多层时划分嵌套层(index/subParamName/index)
}
if err := c.ShouldBindQuery(&query); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否array
info := s.neConfigService.SelectNeConfigByNeTypeAndParamName(query.NeType, query.ParamName)
if info.ParamType != "array" {
c.JSON(400, result.CodeMsg(400, "this attribute does not support adding"))
c.JSON(200, resp.ErrMsg("this attribute does not support adding"))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(query.NeType, query.NeId)
neInfo := s.neInfoService.FindByNeTypeAndNeID(query.NeType, query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigDelete(neInfo, query.ParamName, query.Loc)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(resData))
c.JSON(200, resp.OkData(resData))
}

View File

@@ -0,0 +1,56 @@
package service
import (
"fmt"
"runtime"
"strings"
"be.ems/src/framework/cmd"
"be.ems/src/framework/config"
)
// GetOMCYaml 获取OMC网元配置文件 /usr/local/etc/omc/omc.yaml
func (r NeConfig) GetOMCYaml(paramName string) []map[string]any {
if paramName == "trace" {
traceData := config.Get("trace").(map[string]any)
return []map[string]any{traceData}
}
return []map[string]any{}
}
// ModifyOMCYaml 修改OMC网元配置文件 /usr/local/etc/omc/omc.yaml
func (r NeConfig) ModifyOMCYaml(paramName, loc string, paramData any) error {
neConfig := r.SelectNeConfigByNeTypeAndParamName("OMC", paramName)
if neConfig.ParamType == "list" {
if paramName == "trace" {
configPath := fmt.Sprint(config.Get("config")) // 获取配置文件路径
paramDataMap := paramData.(map[string]any)
for k, v := range paramDataMap {
config.Set(fmt.Sprintf("trace.%s", strings.ToLower(k)), v)
if runtime.GOOS == "windows" {
continue // Windows系统不支持sed命令
}
// 修改参数较少,直接命令改文件内容
if k == "enabled" {
// sed 's/enabled: \(true\|false\) # trace enabled/enabled: true # trace enabled/' /usr/local/etc/omc/omc.yaml
cmd.Execf("sed -i 's/enabled: \\(true\\|false\\) # trace enabled/enabled: %v # trace enabled/' %s", v, configPath)
}
if k == "host" {
// sed 's/host: ".*" # trace host/host: "127.2.2.2" # trace host/' /usr/local/etc/omc/omc.yaml
cmd.Execf("sed -i 's/host: \".*\" # trace host/host: \"%v\" # trace host/' %s", v, configPath)
}
if k == "port" {
// sed 's/port: [0-9]\+ # trace port/port: 6964 # trace port/' /usr/local/etc/omc/omc.yaml
cmd.Execf("sed -i 's/port: [0-9]\\+ # trace port/port: %v # trace port/' %s", v, configPath)
}
}
// 重开跟踪任务信令数据通道UDP
// service.NewTraceTask.CreateUDP(true) 方法导致循环引用,抛给上层调用
return nil
}
}
if neConfig.ParamType == "array" {
// TODO
}
return fmt.Errorf("not found method paramName")
}