merge: 合并OMC分支

This commit is contained in:
TsMask
2024-07-10 14:18:48 +08:00
parent 17c0011c6b
commit 625ed57a50
260 changed files with 9167 additions and 14857 deletions

View File

@@ -25,6 +25,14 @@ func Setup(router *gin.Engine) {
// 系统可暴露的配置信息
indexGroup.GET("/sys-conf", controller.NewCommont.SysConfig)
// 系统引导初始化
guideGroup := router.Group("/bootloader")
{
guideGroup.POST("", controller.NewBootloader.Start)
guideGroup.PUT("", middleware.PreAuthorize(nil), controller.NewBootloader.Done)
guideGroup.DELETE("", middleware.PreAuthorize(nil), controller.NewBootloader.Reset)
guideGroup.PUT("/account", middleware.PreAuthorize(nil), controller.NewBootloader.Account)
}
// 验证码操作处理
indexGroup.GET("/captchaImage",

View File

@@ -9,7 +9,6 @@ import (
tokenUtils "nms_cxy/src/framework/utils/token"
"nms_cxy/src/framework/vo"
"nms_cxy/src/framework/vo/result"
libAccount "nms_cxy/src/lib_features/account"
commonModel "nms_cxy/src/modules/common/model"
commonService "nms_cxy/src/modules/common/service"
systemService "nms_cxy/src/modules/system/service"
@@ -84,9 +83,6 @@ func (s *AccountController) Login(c *gin.Context) {
)
}
// 设置登录会话-兼容旧登录方式
libAccount.SessionToken(loginBody.Username, ipaddr)
c.JSON(200, result.OkData(map[string]any{
tokenConstants.RESPONSE_FIELD: tokenStr,
}))

View File

@@ -0,0 +1,182 @@
package controller
import (
adminConstants "nms_cxy/src/framework/constants/admin"
"nms_cxy/src/framework/constants/common"
tokenConstants "nms_cxy/src/framework/constants/token"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/machine"
"nms_cxy/src/framework/utils/regular"
tokenUtils "nms_cxy/src/framework/utils/token"
"nms_cxy/src/framework/vo"
"nms_cxy/src/framework/vo/result"
commonService "nms_cxy/src/modules/common/service"
systemService "nms_cxy/src/modules/system/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 BootloaderController 结构体
var NewBootloader = &BootloaderController{
accountService: commonService.NewAccountImpl,
sysUserService: systemService.NewSysUserImpl,
}
// 系统引导初始化
//
// PATH /bootloader
type BootloaderController struct {
// 账号身份操作服务
accountService commonService.IAccount
// 用户信息服务
sysUserService systemService.ISysUser
}
// 首次引导开始
//
// POST /
func (s *BootloaderController) Start(c *gin.Context) {
// 是否完成引导
launchInfo := machine.LaunchInfo
if launchInfo == nil {
c.JSON(200, result.Err(nil))
return
}
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, result.ErrMsg("bootloader done"))
return
}
// 查询用户登录账号
sysUser := s.sysUserService.SelectUserById("1")
if sysUser.UserID != "1" {
c.JSON(200, result.ErrMsg("not found user data"))
return
}
// 登录用户信息
loginUser := vo.LoginUser{
UserID: sysUser.UserID,
DeptID: sysUser.DeptID,
User: sysUser,
Permissions: []string{adminConstants.PERMISSION},
}
// 当前请求信息
ipaddr, location := ctx.IPAddrLocation(c)
os, browser := ctx.UaOsBrowser(c)
// 生成令牌,创建系统访问记录
tokenStr := tokenUtils.Create(&loginUser, ipaddr, location, os, browser)
if tokenStr == "" {
c.JSON(200, result.Err(nil))
return
} else {
s.accountService.UpdateLoginDateAndIP(&loginUser)
}
c.JSON(200, result.OkData(map[string]any{
tokenConstants.RESPONSE_FIELD: tokenStr,
}))
}
// 首次引导完成
//
// PUT /
func (s *BootloaderController) Done(c *gin.Context) {
// 是否完成引导
launchInfo := machine.LaunchInfo
if launchInfo == nil {
c.JSON(200, result.Err(nil))
return
}
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, result.ErrMsg("bootloader done"))
return
}
// 标记引导完成
if err := machine.Bootloader(false); err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
// 清除授权信息
tokenUtils.Remove(ctx.Authorization(c))
c.JSON(200, result.Ok(nil))
}
// 引导系统数据重置
//
// DELETE /
func (s *BootloaderController) Reset(c *gin.Context) {
// 是否完成引导
launchInfo := machine.LaunchInfo
if launchInfo == nil {
c.JSON(200, result.Err(nil))
return
}
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && v.(bool) {
c.JSON(200, result.ErrMsg("bootloader not done"))
return
}
if err := machine.Reset(); err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
// 清除授权信息
tokenUtils.Remove(ctx.Authorization(c))
c.JSON(200, result.Ok(nil))
}
// 账号变更
//
// PUT /account
func (s *BootloaderController) Account(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
UserName string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
if !regular.ValidPassword(body.Password) {
// 登录密码至少包含大小写字母、数字、特殊符号且不少于6位
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.errPasswd")))
return
}
// 是否完成引导
launchInfo := machine.LaunchInfo
if launchInfo == nil {
c.JSON(200, result.Err(nil))
return
}
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, result.ErrMsg("bootloader done"))
return
}
// 查询用户登录账号
sysUser := s.sysUserService.SelectUserById("2")
if sysUser.UserID != "2" {
c.JSON(200, result.ErrMsg("not found user data"))
return
}
sysUser.UserName = body.UserName
sysUser.NickName = body.UserName
sysUser.Password = body.Password
sysUser.UpdateBy = ctx.LoginUserToUserName(c)
rows := s.sysUserService.UpdateUser(sysUser)
if rows > 0 {
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
}

View File

@@ -43,13 +43,6 @@ func (s *FileController) Download(c *gin.Context) {
return
}
routerPath := string(decodedBytes)
// 地址文件名截取
fileName := routerPath[strings.LastIndex(routerPath, "/")+1:]
// 响应头
c.Writer.Header().Set("Content-Disposition", `attachment; filename="`+url.QueryEscape(fileName)+`"`)
c.Writer.Header().Set("Accept-Ranges", "bytes")
c.Writer.Header().Set("Content-Type", "application/octet-stream")
// 断点续传
headerRange := c.GetHeader("Range")
@@ -58,6 +51,12 @@ func (s *FileController) Download(c *gin.Context) {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
// 响应头
c.Writer.Header().Set("Content-Disposition", `attachment; filename="`+url.QueryEscape(filepath.Base(routerPath))+`"`)
c.Writer.Header().Set("Accept-Ranges", "bytes")
c.Writer.Header().Set("Content-Type", "application/octet-stream")
if headerRange != "" {
c.Writer.Header().Set("Content-Range", fmt.Sprint(resultMap["range"]))
c.Writer.Header().Set("Content-Length", fmt.Sprint(resultMap["chunkSize"]))
@@ -65,7 +64,6 @@ func (s *FileController) Download(c *gin.Context) {
} else {
c.Writer.Header().Set("Content-Length", fmt.Sprint(resultMap["fileSize"]))
c.Status(200)
}
c.Writer.Write(resultMap["data"].([]byte))
}
@@ -222,7 +220,7 @@ func (s *CommontController) TransferStaticFile(c *gin.Context) {
delPrefix := strings.Replace(body.StaticPath, static["prefix"].(string), "", 1)
staticPath := strings.Replace(delPrefix, "{language}", lang, 1)
newFile := fmt.Sprintf("%s%s", dir, staticPath)
newFile := filepath.ToSlash(fmt.Sprintf("%s%s", dir, staticPath))
err = file.CopyUploadFile(body.UploadPath, newFile)
if err != nil {

View File

@@ -5,6 +5,8 @@ import (
"nms_cxy/lib/global"
"nms_cxy/src/framework/config"
"nms_cxy/src/framework/constants/common"
"nms_cxy/src/framework/utils/machine"
systemService "nms_cxy/src/modules/system/service"
)
@@ -29,6 +31,17 @@ func (s *CommontImpl) SystemConfigInfo() map[string]string {
infoMap["version"] = global.Version
infoMap["buildTime"] = global.BuildTime
infoMap["goVer"] = global.GoVer
// 系统首次使用标记
launchInfo := machine.LaunchInfo
if launchInfo != nil {
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok {
infoMap[common.LAUNCH_BOOTLOADER] = fmt.Sprint(v)
} else {
infoMap[common.LAUNCH_BOOTLOADER] = "true"
}
} else {
infoMap[common.LAUNCH_BOOTLOADER] = "true"
}
// 序列号
infoMap["serialNum"] = fmt.Sprint(config.Get("omc.sn"))
// 获取LOGO类型

View File

@@ -25,8 +25,9 @@ type BarProcessor struct {
type BarParams struct {
Duration int `json:"duration"`
TableName string `json:"tableName"`
ColName string `json:"colName"` // column name of time string
Extras string `json:"extras"` // extras condition for where
ColName string `json:"colName"` // column name of time string
Extras string `json:"extras"` // extras condition for where
SessFlag bool `json:"sessFlag"` // session flag, true: session model, false: no session
}
func (s *BarProcessor) Execute(data any) (any, error) {
@@ -74,10 +75,19 @@ func (s *BarProcessor) Execute(data any) (any, error) {
where = fmt.Sprintf("NOW()>ADDDATE(`%s`,interval %d day) and %s", params.ColName, params.Duration, params.Extras)
}
affected, err := dborm.XormDeleteDataByWhere(where, params.TableName)
if err != nil {
// panic(fmt.Sprintf("Failed to XormDeleteDataByWhere:%v", err))
return nil, err
var affected int64 = 0
if params.SessFlag {
affected, err = dborm.XormDeleteDataByWhere(where, params.TableName)
if err != nil {
// panic(fmt.Sprintf("Failed to XormDeleteDataByWhere:%v", err))
return nil, err
}
} else {
affected, err = dborm.XormDeleteDataByWhereNoSession(where, params.TableName)
if err != nil {
// panic(fmt.Sprintf("Failed to XormDeleteDataByWhere:%v", err))
return nil, err
}
}
// 返回结果,用于记录执行结果

View File

@@ -113,7 +113,8 @@ func (s *BarProcessor) Execute(data any) (any, error) {
for _, ne := range nes {
//log.Debug("ne:", ne)
sql := fmt.Sprintf("select * from ne_state where ne_type = '%s' and ne_id = '%s' order by timestamp desc limit 1", ne.NeType, ne.NeId)
sql := fmt.Sprintf("select * from ne_state where ne_type='%s' and ne_id='%s' order by `timestamp` desc limit 1", ne.NeType, ne.NeId)
log.Debug("SQL:", sql)
neState, err := dborm.XormGetDataBySQL(sql)
if err != nil {
log.Error("Failed to get ne_state:", err)
@@ -121,7 +122,7 @@ func (s *BarProcessor) Execute(data any) (any, error) {
}
if len(*neState) == 0 {
log.Warn("Not found record in ne_state:")
continue
//continue
}
//log.Debug("neState:", *neState)
@@ -150,7 +151,7 @@ func (s *BarProcessor) Execute(data any) (any, error) {
var timestamp string
if len(*neState) == 0 {
log.Infof("Not found ne_state neType:%s, neId:%s", ne.NeType, ne.NeId)
timestamp = ne.UpdateTime
timestamp = ne.UpdateTime.Format(time.DateTime)
} else {
timestamp = (*neState)[0]["timestamp"]
}
@@ -202,11 +203,13 @@ func (s *BarProcessor) Execute(data any) (any, error) {
var response *resty.Response
requestURI := fmt.Sprintf("/api/rest/faultManagement/v1/elementType/%s/objectType/alarms", ne.NeType)
restHost := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
//restHost := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
restHost := config.GetOMCHostUrl()
requestURL := fmt.Sprintf("%s%s", restHost, requestURI)
log.Debug("requestURL: POST ", requestURL)
response, err = client.R().
EnableTrace().
//SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
SetBody(body).
@@ -269,7 +272,8 @@ func (s *BarProcessor) Execute(data any) (any, error) {
var response *resty.Response
requestURI := fmt.Sprintf("/api/rest/faultManagement/v1/elementType/%s/objectType/alarms", ne.NeType)
restHost := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
//restHost := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
restHost := config.GetOMCHostUrl()
requestURL := fmt.Sprintf("%s%s", restHost, requestURI)
log.Debug("requestURL: POST ", requestURL)
response, err = client.R().

View File

@@ -117,17 +117,20 @@ func (s *BarProcessor) Execute(data any) (any, error) {
log.Trace("response body:", string(response.Body()))
state := new(SystemState)
_ = json.Unmarshal(response.Body(), &state)
var dateStr *string = nil
if state.ExpiryDate != "" && state.ExpiryDate != "-" {
dateStr = &state.ExpiryDate
}
// var dateStr *string = nil
// if state.ExpiryDate != "" && state.ExpiryDate != "-" {
// dateStr = &state.ExpiryDate
// }
neState := new(dborm.NeState)
neState.NeType = ne.NeType
neState.NeId = ne.NeId
neState.Version = state.Version
neState.Capability = state.Capability
neState.SerialNum = state.SerialNum
neState.ExpiryDate = *dateStr
// if dateStr != nil {
// neState.ExpiryDate = *dateStr
// }
neState.ExpiryDate = state.ExpiryDate
cu, _ := json.Marshal(state.CpuUsage)
neState.CpuUsage = string(cu)
mu, _ := json.Marshal(state.MemUsage)

View File

@@ -40,12 +40,17 @@ type SysJobController struct {
//
// GET /list
func (s *SysJobController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
data := s.sysJobService.SelectJobPage(querys)
rows := data["rows"].([]model.SysJob)
// 闭包函数处理多语言
language := ctx.AcceptLanguage(c)
querys := ctx.QueryMap(c)
// 多语言值转key查询
if v, ok := querys["jobName"]; ok && v != "" {
querys["jobName"] = i18n.TFindKeyPrefix(language, "job", v.(string))
}
data := s.sysJobService.SelectJobPage(querys)
rows := data["rows"].([]model.SysJob)
// 闭包函数处理多语言
converI18n := func(language string, arr *[]model.SysJob) {
for i := range *arr {
(*arr)[i].JobName = i18n.TKey(language, (*arr)[i].JobName)
@@ -314,14 +319,21 @@ func (s *SysJobController) ResetQueueJob(c *gin.Context) {
func (s *SysJobController) Export(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
querys := ctx.BodyJSONMap(c)
data := s.sysJobService.SelectJobPage(querys)
if data["total"].(int64) == 0 {
// querys := ctx.BodyJSONMap(c)
// data := s.sysJobService.SelectJobPage(querys)
// if data["total"].(int64) == 0 {
// // 导出数据记录为空
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
// return
// }
// rows := data["rows"].([]model.SysJob)
rows := s.sysJobService.SelectJobList(model.SysJob{})
if len(rows) <= 0 {
// 导出数据记录为空
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
rows := data["rows"].([]model.SysJob)
// 闭包函数处理多语言
converI18n := func(language string, arr *[]model.SysJob) {
@@ -340,10 +352,10 @@ func (s *SysJobController) Export(c *gin.Context) {
"B1": i18n.TKey(language, "job.export.jobName"),
"C1": i18n.TKey(language, "job.export.jobGroupName"),
"D1": i18n.TKey(language, "job.export.invokeTarget"),
"E1": i18n.TKey(language, "job.export.targetParams"),
"F1": i18n.TKey(language, "job.export.cronExpression"),
"G1": i18n.TKey(language, "job.export.status"),
"H1": i18n.TKey(language, "job.export.remark"),
"E1": i18n.TKey(language, "job.export.cronExpression"),
"F1": i18n.TKey(language, "job.export.status"),
"G1": i18n.TKey(language, "job.export.remark"),
// "E1": i18n.TKey(language, "job.export.targetParams"),
}
// 读取任务组名字典数据
dictSysJobGroup := s.sysDictDataService.SelectDictDataByType("sys_job_group")
@@ -370,10 +382,10 @@ func (s *SysJobController) Export(c *gin.Context) {
"B" + idx: row.JobName,
"C" + idx: sysJobGroup,
"D" + idx: row.InvokeTarget,
"E" + idx: row.TargetParams,
"F" + idx: row.CronExpression,
"G" + idx: statusValue,
"H" + idx: row.Remark,
"E" + idx: row.CronExpression,
"F" + idx: statusValue,
"G" + idx: row.Remark,
// "E" + idx: row.TargetParams,
})
}

View File

@@ -39,6 +39,7 @@ type SysJobLogController struct {
//
// GET /list
func (s *SysJobLogController) List(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询参数转换map
querys := ctx.QueryMap(c)
// 任务ID优先级更高
@@ -47,11 +48,15 @@ func (s *SysJobLogController) List(c *gin.Context) {
querys["jobName"] = jobInfo.JobName
querys["jobGroup"] = jobInfo.JobGroup
}
data := s.sysJobLogService.SelectJobLogPage(querys)
// 多语言值转key查询
if v, ok := querys["jobName"]; ok && v != "" {
querys["jobName"] = i18n.TFindKeyPrefix(language, "job", v.(string))
}
data := s.sysJobLogService.SelectJobLogPage(querys)
rows := data["rows"].([]model.SysJobLog)
// 闭包函数处理多语言
language := ctx.AcceptLanguage(c)
converI18n := func(language string, arr *[]model.SysJobLog) {
for i := range *arr {
(*arr)[i].JobName = i18n.TKey(language, (*arr)[i].JobName)
@@ -124,17 +129,24 @@ func (s *SysJobLogController) Clean(c *gin.Context) {
//
// POST /export
func (s *SysJobLogController) Export(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
querys := ctx.BodyJSONMap(c)
data := s.sysJobLogService.SelectJobLogPage(querys)
if data["total"].(int64) == 0 {
c.JSON(200, result.ErrMsg("Export data record is empty"))
// querys := ctx.BodyJSONMap(c)
// data := s.sysJobLogService.SelectJobLogPage(querys)
// if data["total"].(int64) == 0 {
// c.JSON(200, result.ErrMsg("Export data record is empty"))
// return
// }
// rows := data["rows"].([]model.SysJobLog)
rows := s.sysJobLogService.SelectJobLogList(model.SysJobLog{})
if len(rows) <= 0 {
// 导出数据记录为空
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
rows := data["rows"].([]model.SysJobLog)
// 闭包函数处理多语言
language := ctx.AcceptLanguage(c)
converI18n := func(language string, arr *[]model.SysJobLog) {
for i := range *arr {
(*arr)[i].JobName = i18n.TKey(language, (*arr)[i].JobName)
@@ -150,10 +162,11 @@ func (s *SysJobLogController) Export(c *gin.Context) {
"B1": i18n.TKey(language, "job.export.jobName"),
"C1": i18n.TKey(language, "job.export.jobGroupName"),
"D1": i18n.TKey(language, "job.export.invokeTarget"),
"E1": i18n.TKey(language, "job.export.targetParams"),
"F1": i18n.TKey(language, "job.export.jobID"),
"G1": i18n.TKey(language, "job.export.jobLogStatus"),
"H1": i18n.TKey(language, "job.export.jobLogTime"),
// "E1": i18n.TKey(language, "job.export.targetParams"),
// "F1": i18n.TKey(language, "job.export.jobID"),
"E1": i18n.TKey(language, "job.export.jobLogStatus"),
"F1": i18n.TKey(language, "job.export.jobLogTime"),
"G1": i18n.TKey(language, "log.operate.export.costTime"),
}
// 读取任务组名字典数据
dictSysJobGroup := s.sysDictDataService.SelectDictDataByType("sys_job_group")
@@ -179,10 +192,11 @@ func (s *SysJobLogController) Export(c *gin.Context) {
"B" + idx: row.JobName,
"C" + idx: sysJobGroup,
"D" + idx: row.InvokeTarget,
"E" + idx: row.TargetParams,
"F" + idx: row.JobMsg,
"G" + idx: statusValue,
"H" + idx: date.ParseDateToStr(row.CreateTime, date.YYYY_MM_DD_HH_MM_SS),
// "E" + idx: row.TargetParams,
// "F" + idx: row.JobMsg,
"E" + idx: statusValue,
"F" + idx: date.ParseDateToStr(row.CreateTime, date.YYYY_MM_DD_HH_MM_SS),
"G" + idx: row.CostTime,
})
}

View File

@@ -6,7 +6,6 @@ import (
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/date"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/monitor/model"
@@ -80,8 +79,7 @@ func (r *SysJobLogImpl) SelectJobLogPage(query map[string]any) map[string]any {
}
if ok && beginTime != "" {
conditions = append(conditions, "create_time >= ?")
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
params = append(params, beginDate.UnixMilli())
params = append(params, parse.Number(beginTime.(string)))
}
endTime, ok := query["endTime"]
if !ok {
@@ -89,8 +87,7 @@ func (r *SysJobLogImpl) SelectJobLogPage(query map[string]any) map[string]any {
}
if ok && endTime != "" {
conditions = append(conditions, "create_time <= ?")
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
params = append(params, endDate.UnixMilli())
params = append(params, parse.Number(endTime.(string)))
}
// 构建查询条件语句

View File

@@ -1,9 +1,9 @@
package controller
import (
"nms_cxy/lib/core/utils/date"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/date"
"nms_cxy/src/framework/vo/result"
"nms_cxy/src/modules/network_data/model"
neDataService "nms_cxy/src/modules/network_data/service"

View File

@@ -1,23 +1,31 @@
package controller
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/vo/result"
"nms_cxy/src/modules/network_data/model"
neDataService "nms_cxy/src/modules/network_data/service"
neService "nms_cxy/src/modules/network_element/service"
sysService "nms_cxy/src/modules/system/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 AMFController 结构体
var NewAMFController = &AMFController{
neInfoService: neService.NewNeInfoImpl,
ueEventService: neDataService.NewUEEventImpl,
ueEventService: neDataService.NewUEEventAMFImpl,
}
// 网元AMF
@@ -26,8 +34,8 @@ var NewAMFController = &AMFController{
type AMFController struct {
// 网元信息服务
neInfoService neService.INeInfo
// CDR会话事件服务
ueEventService neDataService.IUEEvent
// UE会话事件服务
ueEventService neDataService.IUEEventAMF
}
// UE会话列表
@@ -35,19 +43,19 @@ type AMFController struct {
// GET /ue/list
func (s *AMFController) UEList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys model.UEEventQuery
var querys model.UEEventAMFQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
querys.RmUID = neInfo.RmUID
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
// return
// }
// querys.RmUID = neInfo.RmUID
// 查询数据
data := s.ueEventService.SelectPage(querys)
@@ -79,3 +87,125 @@ func (s *AMFController) UERemove(c *gin.Context) {
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, result.OkMsg(msg))
}
// UE会话列表导出
//
// POST /ue/export
func (s *AMFController) UEExport(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
var querys model.UEEventAMFQuery
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 限制导出数据集
if querys.PageSize > 10000 {
querys.PageSize = 10000
}
data := s.ueEventService.SelectPage(querys)
if parse.Number(data["total"]) == 0 {
// 导出数据记录为空
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
rows := data["rows"].([]model.UEEventAMF)
// 导出文件名称
fileName := fmt.Sprintf("amf_ue_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
// 第一行表头标题
headerCells := map[string]string{
"A1": "ID",
"B1": "IMSI",
"C1": "Event Type",
"D1": "Result",
"E1": "Time",
}
// 读取字典数据 UE 事件类型
dictUEEventType := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_type")
// 读取字典数据 UE 事件认证代码类型
dictUEAauthCode := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_auth_code")
// 读取字典数据 UE 事件CM状态
dictUEEventCmState := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_cm_state")
// 从第二行开始的数据
dataCells := make([]map[string]any, 0)
for i, row := range rows {
idx := strconv.Itoa(i + 2)
// 解析 JSON 字符串为 map
var eventJSON map[string]interface{}
err := json.Unmarshal([]byte(row.EventJSONStr), &eventJSON)
if err != nil {
logger.Warnf("UEExport Error parsing JSON: %s", err.Error())
continue
}
// 取IMSI
imsi := ""
if v, ok := eventJSON["imsi"]; ok && v != nil {
imsi = v.(string)
}
// 取类型
eventType := ""
for _, v := range dictUEEventType {
if row.EventType == v.DictValue {
eventType = i18n.TKey(language, v.DictLabel)
break
}
}
// 取结果
eventResult := ""
// 取时间
timeStr := ""
if row.EventType == "auth-result" {
if v, ok := eventJSON["authTime"]; ok && v != nil {
timeStr = v.(string)
}
if v, ok := eventJSON["authCode"]; ok && v != nil {
eventResult = v.(string)
for _, v := range dictUEAauthCode {
if eventResult == v.DictValue {
eventResult = i18n.TKey(language, v.DictLabel)
break
}
}
}
}
if row.EventType == "detach" {
if v, ok := eventJSON["detachTime"]; ok && v != nil {
timeStr = v.(string)
}
eventResult = "Success"
}
if row.EventType == "cm-state" {
if v, ok := eventJSON["changeTime"]; ok && v != nil {
timeStr = v.(string)
}
if v, ok := eventJSON["status"]; ok && v != nil {
eventResult = v.(string)
for _, v := range dictUEEventCmState {
if eventResult == v.DictValue {
eventResult = i18n.TKey(language, v.DictLabel)
break
}
}
}
}
dataCells = append(dataCells, map[string]any{
"A" + idx: row.ID,
"B" + idx: imsi,
"C" + idx: eventType,
"D" + idx: eventResult,
"E" + idx: timeStr,
})
}
// 导出数据表格
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.FileAttachment(saveFilePath, fileName)
}

View File

@@ -1,23 +1,32 @@
package controller
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/date"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/vo/result"
"nms_cxy/src/modules/network_data/model"
neDataService "nms_cxy/src/modules/network_data/service"
neService "nms_cxy/src/modules/network_element/service"
sysService "nms_cxy/src/modules/system/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 IMSController 结构体
var NewIMSController = &IMSController{
neInfoService: neService.NewNeInfoImpl,
cdrEventService: neDataService.NewCDREventImpl,
cdrEventService: neDataService.NewCDREventIMSImpl,
}
// 网元IMS
@@ -27,7 +36,7 @@ type IMSController struct {
// 网元信息服务
neInfoService neService.INeInfo
// CDR会话事件服务
cdrEventService neDataService.ICDREvent
cdrEventService neDataService.ICDREventIMS
}
// CDR会话列表
@@ -35,19 +44,19 @@ type IMSController struct {
// GET /cdr/list
func (s *IMSController) CDRList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys model.CDREventQuery
var querys model.CDREventIMSQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
querys.RmUID = neInfo.RmUID
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
// return
// }
// querys.RmUID = neInfo.RmUID
// 查询数据
data := s.cdrEventService.SelectPage(querys)
@@ -79,3 +88,126 @@ func (s *IMSController) CDRRemove(c *gin.Context) {
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, result.OkMsg(msg))
}
// CDR会话列表导出
//
// POST /cdr/export
func (s *IMSController) CDRExport(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
var querys model.CDREventIMSQuery
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 限制导出数据集
if querys.PageSize > 10000 {
querys.PageSize = 10000
}
data := s.cdrEventService.SelectPage(querys)
if parse.Number(data["total"]) == 0 {
// 导出数据记录为空
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
rows := data["rows"].([]model.CDREventIMS)
// 导出文件名称
fileName := fmt.Sprintf("ims_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
// 第一行表头标题
headerCells := map[string]string{
"A1": "ID",
"B1": "Record Behavior",
"C1": "Type",
"D1": "Called",
"E1": "Caller",
"F1": "Duration",
"G1": "Result",
"H1": "Time",
}
// 读取字典数据 CDR SIP响应代码类别类型
dictCDRSipCode := sysService.NewSysDictDataImpl.SelectDictDataByType("cdr_sip_code")
// 读取字典数据 CDR 呼叫类型
dictCDRCallType := sysService.NewSysDictDataImpl.SelectDictDataByType("cdr_call_type")
// 从第二行开始的数据
dataCells := make([]map[string]any, 0)
for i, row := range rows {
idx := strconv.Itoa(i + 2)
// 解析 JSON 字符串为 map
var cdrJSON map[string]interface{}
err := json.Unmarshal([]byte(row.CDRJSONStr), &cdrJSON)
if err != nil {
logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
continue
}
// 记录类型
recordType := ""
if v, ok := cdrJSON["recordType"]; ok && v != nil {
recordType = v.(string)
}
// 被叫
called := ""
if v, ok := cdrJSON["calledParty"]; ok && v != nil {
called = v.(string)
}
// 主叫
caller := ""
if v, ok := cdrJSON["callerParty"]; ok && v != nil {
caller = v.(string)
}
// 呼叫类型
callType := "sms"
callTypeLable := "SMS"
if v, ok := cdrJSON["callType"]; ok && v != nil {
callType = v.(string)
for _, v := range dictCDRCallType {
if callType == v.DictValue {
callTypeLable = i18n.TKey(language, v.DictLabel)
break
}
}
}
// 时长
duration := "-"
if v, ok := cdrJSON["callDuration"]; ok && v != nil && callType != "sms" {
duration = fmt.Sprint(parse.Number(v))
}
// 呼叫结果 非短信都有code作为结果 sms短信都ok
callResult := "Success"
if v, ok := cdrJSON["cause"]; ok && v != nil && callType != "sms" {
cause := fmt.Sprint(v)
for _, v := range dictCDRSipCode {
if cause == v.DictValue {
callResult = i18n.TKey(language, v.DictLabel)
break
}
}
}
// 取时间
timeStr := ""
if v, ok := cdrJSON["releaseTime"]; ok && v != nil {
releaseTime := parse.Number(v)
timeStr = date.ParseDateToStr(releaseTime, date.YYYY_MM_DDTHH_MM_SSZ)
}
dataCells = append(dataCells, map[string]any{
"A" + idx: row.ID,
"B" + idx: recordType,
"C" + idx: callTypeLable,
"D" + idx: called,
"E" + idx: caller,
"F" + idx: duration,
"G" + idx: callResult,
"H" + idx: timeStr,
})
}
// 导出数据表格
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.FileAttachment(saveFilePath, fileName)
}

View File

@@ -0,0 +1,201 @@
package controller
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/date"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/vo/result"
"nms_cxy/src/modules/network_data/model"
neDataService "nms_cxy/src/modules/network_data/service"
neService "nms_cxy/src/modules/network_element/service"
sysService "nms_cxy/src/modules/system/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 MMEController 结构体
var NewMMEController = &MMEController{
neInfoService: neService.NewNeInfoImpl,
ueEventService: neDataService.NewUEEventMMEImpl,
}
// 网元MME
//
// PATH /mme
type MMEController struct {
// 网元信息服务
neInfoService neService.INeInfo
// UE会话事件服务
ueEventService neDataService.IUEEventMME
}
// UE会话列表
//
// GET /ue/list
func (s *MMEController) UEList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys model.UEEventMMEQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
// return
// }
// querys.RmUID = neInfo.RmUID
// 查询数据
data := s.ueEventService.SelectPage(querys)
c.JSON(200, result.Ok(data))
}
// UE会话删除
//
// DELETE /ue/:ueIds
func (s *MMEController) UERemove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
ueIds := c.Param("ueIds")
if ueIds == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 处理字符转id数组后去重
ids := strings.Split(ueIds, ",")
uniqueIDs := parse.RemoveDuplicates(ids)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
rows, err := s.ueEventService.DeleteByIds(uniqueIDs)
if err != nil {
c.JSON(200, result.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))
}
// UE会话列表导出
//
// POST /ue/export
func (s *MMEController) UEExport(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
var querys model.UEEventMMEQuery
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 限制导出数据集
if querys.PageSize > 10000 {
querys.PageSize = 10000
}
data := s.ueEventService.SelectPage(querys)
if parse.Number(data["total"]) == 0 {
// 导出数据记录为空
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
rows := data["rows"].([]model.UEEventMME)
// 导出文件名称
fileName := fmt.Sprintf("mme_ue_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
// 第一行表头标题
headerCells := map[string]string{
"A1": "ID",
"B1": "IMSI",
"C1": "Event Type",
"D1": "Result",
"E1": "Time",
}
// 读取字典数据 UE 事件类型
dictUEEventType := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_type")
// 读取字典数据 UE 事件认证代码类型
dictUEAauthCode := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_auth_code")
// 读取字典数据 UE 事件CM状态
dictUEEventCmState := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_cm_state")
// 从第二行开始的数据
dataCells := make([]map[string]any, 0)
for i, row := range rows {
idx := strconv.Itoa(i + 2)
// 解析 JSON 字符串为 map
var eventJSON map[string]interface{}
err := json.Unmarshal([]byte(row.EventJSONStr), &eventJSON)
if err != nil {
logger.Warnf("UEExport Error parsing JSON: %s", err.Error())
continue
}
// 取IMSI
imsi := ""
if v, ok := eventJSON["imsi"]; ok && v != nil {
imsi = v.(string)
}
// 取类型
eventType := row.EventType
for _, v := range dictUEEventType {
if row.EventType == v.DictValue {
eventType = i18n.TKey(language, v.DictLabel)
break
}
}
// 取结果
eventResult := ""
if v, ok := eventJSON["result"]; ok && v != nil {
eventResult = v.(string)
if row.EventType == "auth-result" {
for _, v := range dictUEAauthCode {
if eventResult == v.DictValue {
eventResult = i18n.TKey(language, v.DictLabel)
break
}
}
}
if row.EventType == "cm-state" {
for _, v := range dictUEEventCmState {
if eventResult == v.DictValue {
eventResult = i18n.TKey(language, v.DictLabel)
break
}
}
}
}
// 取时间
timeStr := ""
if v, ok := eventJSON["timestamp"]; ok && v != nil {
rowTime := parse.Number(v)
timeStr = date.ParseDateToStr(rowTime, date.YYYY_MM_DDTHH_MM_SSZ)
}
dataCells = append(dataCells, map[string]any{
"A" + idx: row.ID,
"B" + idx: imsi,
"C" + idx: eventType,
"D" + idx: eventResult,
"E" + idx: timeStr,
})
}
// 导出数据表格
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.FileAttachment(saveFilePath, fileName)
}

View File

@@ -0,0 +1,259 @@
package controller
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/vo/result"
"nms_cxy/src/modules/network_data/model"
neDataService "nms_cxy/src/modules/network_data/service"
neService "nms_cxy/src/modules/network_element/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 SMFController 结构体
var NewSMFController = &SMFController{
neInfoService: neService.NewNeInfoImpl,
cdrEventService: neDataService.NewCDREventSMFImpl,
}
// 网元SMF
//
// PATH /smf
type SMFController struct {
// 网元信息服务
neInfoService neService.INeInfo
// CDR会话事件服务
cdrEventService neDataService.ICDREventSMF
}
// CDR会话列表
//
// GET /cdr/list
func (s *SMFController) CDRList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys model.CDREventSMFQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
// return
// }
// querys.RmUID = neInfo.RmUID
// 查询数据
data := s.cdrEventService.SelectPage(querys)
c.JSON(200, result.Ok(data))
}
// CDR会话删除
//
// DELETE /cdr/:cdrIds
func (s *SMFController) CDRRemove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
cdrIds := c.Param("cdrIds")
if cdrIds == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 处理字符转id数组后去重
ids := strings.Split(cdrIds, ",")
uniqueIDs := parse.RemoveDuplicates(ids)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
rows, err := s.cdrEventService.DeleteByIds(uniqueIDs)
if err != nil {
c.JSON(200, result.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))
}
// CDR会话列表导出
//
// POST /cdr/export
func (s *SMFController) CDRExport(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
var querys model.CDREventSMFQuery
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 限制导出数据集
if querys.PageSize > 10000 {
querys.PageSize = 10000
}
data := s.cdrEventService.SelectPage(querys)
if parse.Number(data["total"]) == 0 {
// 导出数据记录为空
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
rows := data["rows"].([]model.CDREventSMF)
// 导出文件名称
fileName := fmt.Sprintf("smf_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
// 第一行表头标题
headerCells := map[string]string{
"A1": "ID",
"B1": "Charging ID",
"C1": "Subscriber ID Data",
"D1": "Subscriber ID Type",
"E1": "Data Volume Uplink",
"F1": "Data Volume Downlink",
"G1": "Data Total Volume",
"H1": "Duration",
"I1": "Invocation Time",
"J1": "PDU Session Charging Information",
}
// 从第二行开始的数据
dataCells := make([]map[string]any, 0)
for i, row := range rows {
idx := strconv.Itoa(i + 2)
// 解析 JSON 字符串为 map
var cdrJSON map[string]interface{}
err := json.Unmarshal([]byte(row.CDRJSONStr), &cdrJSON)
if err != nil {
logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
continue
}
// 计费ID
chargingID := ""
if v, ok := cdrJSON["chargingID"]; ok && v != nil {
chargingID = fmt.Sprint(parse.Number(v))
}
// 订阅 ID 类型
subscriptionIDType := "-"
// 订阅 ID 数据
subscriptionIDData := "-"
if v, ok := cdrJSON["subscriberIdentifier"]; ok && v != nil {
if sub, subOk := v.(map[string]any); subOk && sub != nil {
subscriptionIDType = sub["subscriptionIDType"].(string)
subscriptionIDData = sub["subscriptionIDData"].(string)
}
}
// 数据量上行链路
dataVolumeUplink := []string{}
// 数据量下行链路
dataVolumeDownlink := []string{}
// 数据总量
dataTotalVolume := []string{}
if v, ok := cdrJSON["listOfMultipleUnitUsage"]; ok && v != nil {
usageList := v.([]any)
if len(usageList) > 0 {
for _, used := range usageList {
usedUnit := used.(map[string]any)
usedUnitList := usedUnit["usedUnitContainer"].([]any)
if len(usedUnitList) > 0 {
for _, data := range usedUnitList {
udata := data.(map[string]any)
if dup, dupOk := udata["dataVolumeUplink"]; dupOk {
dataVolumeUplink = append(dataVolumeUplink, fmt.Sprint(parse.Number(dup)))
}
if ddown, ddownOk := udata["dataVolumeDownlink"]; ddownOk {
dataVolumeDownlink = append(dataVolumeDownlink, fmt.Sprint(parse.Number(ddown)))
}
if dt, dtOk := udata["dataTotalVolume"]; dtOk {
dataTotalVolume = append(dataTotalVolume, fmt.Sprint(parse.Number(dt)))
}
}
}
}
}
}
// 时长
duration := "-"
if v, ok := cdrJSON["duration"]; ok && v != nil {
duration = fmt.Sprint(parse.Number(v))
}
// 调用时间
invocationTimestamp := ""
if v, ok := cdrJSON["invocationTimestamp"]; ok && v != nil {
invocationTimestamp = v.(string)
}
// 记录打开时间
pduSessionChargingInformation := ""
if v, ok := cdrJSON["pDUSessionChargingInformation"]; ok && v != nil {
pduInfo := v.(map[string]any)
User_Identifier := ""
if v, ok := pduInfo["userIdentifier"]; ok && v != nil {
User_Identifier = v.(string)
}
SSC_Mode := ""
if v, ok := pduInfo["sSCMode"]; ok && v != nil {
SSC_Mode = v.(string)
}
RAT_Type := ""
if v, ok := pduInfo["rATType"]; ok && v != nil {
RAT_Type = v.(string)
}
DNN_ID := ""
if v, ok := pduInfo["dNNID"]; ok && v != nil {
DNN_ID = v.(string)
}
PDU_Type := ""
if v, ok := pduInfo["pDUType"]; ok && v != nil {
PDU_Type = v.(string)
}
PDU_IPv4 := ""
PDU_IPv6 := ""
if v, ok := pduInfo["pDUAddress"]; ok && v != nil {
pDUAddress := v.(map[string]any)
if addr, ok := pDUAddress["pDUIPv4Address"]; ok && addr != nil {
PDU_IPv4 = addr.(string)
}
if addr, ok := pDUAddress["pDUIPv6AddresswithPrefix"]; ok && addr != nil {
PDU_IPv6 = addr.(string)
}
}
pduSessionChargingInformation = fmt.Sprintf(`User Identifier: %s
SSC Mode: %s RAT Type: %s DNN ID: %s
PDU Type: %s
PDU IPv4 Address: %s
PDU IPv6 Addres Swith Prefix: %s`, User_Identifier, SSC_Mode, RAT_Type, DNN_ID, PDU_Type, PDU_IPv4, PDU_IPv6)
}
dataCells = append(dataCells, map[string]any{
"A" + idx: row.ID,
"B" + idx: chargingID,
"C" + idx: subscriptionIDData,
"D" + idx: subscriptionIDType,
"E" + idx: strings.Join(dataVolumeUplink, ","),
"F" + idx: strings.Join(dataVolumeDownlink, ","),
"G" + idx: strings.Join(dataTotalVolume, ","),
"H" + idx: duration,
"I" + idx: invocationTimestamp,
"J" + idx: pduSessionChargingInformation,
})
}
// 导出数据表格
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.FileAttachment(saveFilePath, fileName)
}

View File

@@ -2,18 +2,19 @@ package controller
import (
"fmt"
"path/filepath"
"strings"
"time"
mmlclient "nms_cxy/lib/core/mml_client"
"nms_cxy/src/framework/constants/uploadsubpath"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/ssh"
"nms_cxy/src/framework/utils/telnet"
"nms_cxy/src/framework/vo/result"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_data/model"
neDataService "nms_cxy/src/modules/network_data/service"
neService "nms_cxy/src/modules/network_element/service"
"github.com/gin-gonic/gin"
@@ -22,21 +23,21 @@ import (
// 实例化控制层 UDMAuthController 结构体
var NewUDMAuth = &UDMAuthController{
udmAuthService: neService.NewUDMAuthImpl,
udmAuthService: neDataService.NewUDMAuthImpl,
neInfoService: neService.NewNeInfoImpl,
}
// UDM鉴权用户请求
// UDM鉴权用户
//
// PATH /udm/auth
type UDMAuthController struct {
// UDM鉴权信息服务
udmAuthService neService.IUDMAuth
udmAuthService neDataService.IUDMAuth
// 网元信息服务
neInfoService neService.INeInfo
}
// UDM鉴权用户-获取全部保存数据
// UDM鉴权用户重载数据
//
// POST /resetData/:neId
func (s *UDMAuthController) ResetData(c *gin.Context) {
@@ -48,21 +49,21 @@ func (s *UDMAuthController) ResetData(c *gin.Context) {
}
neId = ""
data := s.udmAuthService.Save(neId)
data := s.udmAuthService.ResetData(neId)
c.JSON(200, result.OkData(data))
}
// UDM鉴权用户
// UDM鉴权用户列表
//
// GET /list
func (s *UDMAuthController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
querys["neId"] = ""
data := s.udmAuthService.Page(querys)
data := s.udmAuthService.SelectPage(querys)
c.JSON(200, result.Ok(data))
}
// UDM鉴权用户-信息
// UDM鉴权用户信息
//
// GET /:neId/:imsi
func (s *UDMAuthController) Info(c *gin.Context) {
@@ -81,10 +82,16 @@ func (s *UDMAuthController) Info(c *gin.Context) {
return
}
msg := fmt.Sprintf("dsp authdat:imsi=%s", imsi)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToMap(neInfo.IP, msg)
cmd := fmt.Sprintf("dsp authdat:imsi=%s", imsi)
data, err := telnet.ConvertToMap(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -95,31 +102,31 @@ func (s *UDMAuthController) Info(c *gin.Context) {
return
}
// 查询数据库是否存在并存入
neId = ""
var userInfo model.UDMAuth
list := s.udmAuthService.List(model.UDMAuth{NeID: neId, Imsi: imsi})
if len(list) > 0 {
userInfo = list[0]
// 返回查询的用户信息
userInfo.Amf = data["amf"]
userInfo.AlgoIndex = data["algo"]
userInfo.Opc = data["opc"]
userInfo.Ki = data["ki"]
} else {
userInfo := model.UDMAuth{
Imsi: imsi,
Amf: data["amf"],
AlgoIndex: data["algo"],
Opc: data["opc"],
Ki: data["ki"],
}
s.udmAuthService.Insert(neId, userInfo)
u := model.UDMAuth{
IMSI: imsi,
Amf: data["amf"],
Status: "1",
Ki: data["ki"],
AlgoIndex: data["algo"],
Opc: data["opc"],
NeId: neId,
}
c.JSON(200, result.OkData(userInfo))
// 查询imsi存在赋予id用于更新
list := s.udmAuthService.SelectList(u)
if len(list) > 0 {
item := list[0]
if item.ID != "" {
u.ID = item.ID
}
}
go s.udmAuthService.Insert(neId, u)
c.JSON(200, result.OkData(u))
}
// UDM鉴权用户-增加
// UDM鉴权用户新增
//
// POST /:neId
func (s *UDMAuthController) Add(c *gin.Context) {
@@ -132,7 +139,7 @@ func (s *UDMAuthController) Add(c *gin.Context) {
var body model.UDMAuth
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.Imsi == "" {
if err != nil || body.IMSI == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
@@ -144,10 +151,16 @@ func (s *UDMAuthController) Add(c *gin.Context) {
return
}
msg := fmt.Sprintf("add authdat:imsi=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.Imsi, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("add authdat:imsi=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.IMSI, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -156,12 +169,12 @@ func (s *UDMAuthController) Add(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmAuthService.Insert(neId, body)
go s.udmAuthService.Insert(neId, body)
}
c.JSON(200, result.OkData(data))
}
// UDM鉴权用户-批量添加
// UDM鉴权用户批量新增
//
// POST /:neId/:num
func (s *UDMAuthController) Adds(c *gin.Context) {
@@ -175,7 +188,7 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
var body model.UDMAuth
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.Imsi == "" {
if err != nil || body.IMSI == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
@@ -187,10 +200,16 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
return
}
msg := fmt.Sprintf("baa authdat:start_imsi=%s,sub_num=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.Imsi, num, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("baa authdat:start_imsi=%s,sub_num=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.IMSI, num, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -199,12 +218,12 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmAuthService.Inserts(neId, body, num)
go s.udmAuthService.LoadData(neId, body.IMSI, num)
}
c.JSON(200, result.OkData(data))
}
// UDM鉴权用户-修改
// UDM鉴权用户修改
//
// PUT /:neId
func (s *UDMAuthController) Edit(c *gin.Context) {
@@ -217,7 +236,7 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
var body model.UDMAuth
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.Imsi == "" {
if err != nil || body.IMSI == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
@@ -229,23 +248,29 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
return
}
msg := fmt.Sprintf("mod authdata:imsi=%s", body.Imsi)
// 修改的参数名称
if body.Ki != "" {
msg += fmt.Sprintf(",ki=%s", body.Ki)
}
if body.Amf != "" {
msg += fmt.Sprintf(",amf=%s", body.Amf)
}
if body.AlgoIndex != "" {
msg += fmt.Sprintf(",algo=%s", body.AlgoIndex)
}
if body.Opc != "" {
msg += fmt.Sprintf(",opc=%s", body.Opc)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("mod authdata:imsi=%s", body.IMSI)
// 修改的参数名称
if body.Ki != "" {
cmd += fmt.Sprintf(",ki=%s", body.Ki)
}
if body.Amf != "" {
cmd += fmt.Sprintf(",amf=%s", body.Amf)
}
if body.AlgoIndex != "" {
cmd += fmt.Sprintf(",algo=%s", body.AlgoIndex)
}
if body.Opc != "" {
cmd += fmt.Sprintf(",opc=%s", body.Opc)
}
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -254,12 +279,12 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmAuthService.Update(neId, body)
go s.udmAuthService.Insert(neId, body)
}
c.JSON(200, result.OkData(data))
}
// UDM鉴权用户-删除
// UDM鉴权用户删除
//
// DELETE /:neId/:imsi
func (s *UDMAuthController) Remove(c *gin.Context) {
@@ -286,27 +311,34 @@ func (s *UDMAuthController) Remove(c *gin.Context) {
return
}
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
resultData := map[string]string{}
for _, imsi := range uniqueIDs {
msg := fmt.Sprintf("del authdat:imsi=%s", imsi)
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("del authdat:imsi=%s", imsi)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
resultData[imsi] = err.Error()
continue
}
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmAuthService.Delete(neId, imsi)
resultData[imsi] = data
go s.udmAuthService.Delete(neId, imsi)
}
resultData[imsi] = data
}
c.JSON(200, result.OkData(resultData))
}
// UDM鉴权用户-批量删除
// UDM鉴权用户批量删除
//
// DELETE /:neId/:imsi/:num
func (s *UDMAuthController) Removes(c *gin.Context) {
@@ -326,10 +358,16 @@ func (s *UDMAuthController) Removes(c *gin.Context) {
return
}
msg := fmt.Sprintf("bde authdat:start_imsi=%s,sub_num=%s", imsi, num)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("bde authdat:start_imsi=%s,sub_num=%s", imsi, num)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -338,12 +376,12 @@ func (s *UDMAuthController) Removes(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmAuthService.Deletes(neId, imsi, num)
go s.udmAuthService.LoadData(neId, imsi, num)
}
c.JSON(200, result.OkData(data))
}
// UDM鉴权用户-导出
// UDM鉴权用户导出
//
// POST /export
func (s *UDMAuthController) Export(c *gin.Context) {
@@ -359,14 +397,14 @@ func (s *UDMAuthController) Export(c *gin.Context) {
}
if !(body.Type == "csv" || body.Type == "txt") {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserAuthFileFormat")))
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errExportType")))
return
}
neId := ""
list := s.udmAuthService.List(model.UDMAuth{NeID: neId})
list := s.udmAuthService.SelectList(model.UDMAuth{NeId: neId})
// 文件名
fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
fileName := fmt.Sprintf("udm_auth_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
filePath := fmt.Sprintf("%s/%s", file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
if body.Type == "csv" {
@@ -374,7 +412,7 @@ func (s *UDMAuthController) Export(c *gin.Context) {
data := [][]string{}
data = append(data, []string{"imsi", "ki", "algo", "amf", "opc"})
for _, v := range list {
data = append(data, []string{v.Imsi, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
data = append(data, []string{v.IMSI, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
}
// 输出到文件
err := file.WriterFileCSV(data, filePath)
@@ -388,7 +426,7 @@ func (s *UDMAuthController) Export(c *gin.Context) {
// 转换数据
data := [][]string{}
for _, v := range list {
data = append(data, []string{v.Imsi, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
data = append(data, []string{v.IMSI, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
}
// 输出到文件
err = file.WriterFileTXT(data, ",", filePath)
@@ -401,55 +439,68 @@ func (s *UDMAuthController) Export(c *gin.Context) {
c.FileAttachment(filePath, fileName)
}
// UDM鉴权用户-导入
// UDM鉴权用户导入
//
// POST /import
func (s *UDMAuthController) Import(c *gin.Context) {
language := ctx.AcceptLanguage(c)
neId := c.PostForm("neId")
if neId == "" {
var body struct {
NeId string `json:"neId" binding:"required"`
UploadPath string `json:"uploadPath" binding:"required"`
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
formFile, err := c.FormFile("file")
if err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 获取文件名
if !(strings.HasSuffix(formFile.Filename, ".csv") || strings.HasSuffix(formFile.Filename, ".txt")) {
// 判断文件名
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserAuthFileFormat")))
return
}
// 上传文件转存
upFilePath, err := file.TransferUploadFile(formFile, uploadsubpath.IMPORT, nil)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 本地文件
localPath := file.ParseUploadFilePath(upFilePath)
nePath := "/tmp" //config.Get("mml.upload").(string)
// 复制到远程
err = ssh.FileSCPLocalToNe(neInfo.IP, localPath, nePath)
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
fileName := localPath[strings.LastIndex(localPath, "/")+1:]
msg := fmt.Sprintf("import authdat:path=%s", fmt.Sprintf("%s/%s", nePath, fileName))
// 本地文件
localFilePath := file.ParseUploadFilePath(body.UploadPath)
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
// 复制到远程
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
c.JSON(200, result.ErrMsg("error uploading file"))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("import authdat:path=%s", neFilePath)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -457,15 +508,15 @@ func (s *UDMAuthController) Import(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
if strings.HasSuffix(fileName, ".csv") {
data := file.ReadFileCSV(localPath)
neId = ""
go s.udmAuthService.InsertCSV(neId, data)
if strings.HasSuffix(body.UploadPath, ".csv") {
data := file.ReadFileCSV(localFilePath)
neId := ""
go s.udmAuthService.InsertData(neId, "csv", data)
}
if strings.HasSuffix(fileName, ".txt") {
data := file.ReadFileTXT(",", localPath)
neId = ""
go s.udmAuthService.InsertTxt(neId, data)
if strings.HasSuffix(body.UploadPath, ".txt") {
data := file.ReadFileTXT(",", localFilePath)
neId := ""
go s.udmAuthService.InsertData(neId, "txt", data)
}
}
c.JSON(200, result.OkMsg(data))

View File

@@ -2,19 +2,20 @@ package controller
import (
"fmt"
"path/filepath"
"strconv"
"strings"
"time"
mmlclient "nms_cxy/lib/core/mml_client"
"nms_cxy/src/framework/constants/uploadsubpath"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/ssh"
"nms_cxy/src/framework/utils/telnet"
"nms_cxy/src/framework/vo/result"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_data/model"
neDataService "nms_cxy/src/modules/network_data/service"
neService "nms_cxy/src/modules/network_element/service"
"github.com/gin-gonic/gin"
@@ -23,21 +24,21 @@ import (
// 实例化控制层 UDMSubController 结构体
var NewUDMSub = &UDMSubController{
udmSubService: neService.NewUDMSubImpl,
udmSubService: neDataService.NewUDMSubImpl,
neInfoService: neService.NewNeInfoImpl,
}
// UDM签约用户请求
// UDM签约用户
//
// PATH /udm/sub
type UDMSubController struct {
// UDM鉴权信息服务
udmSubService neService.IUDMSub
// UDM签约信息服务
udmSubService neDataService.IUDMSub
// 网元信息服务
neInfoService neService.INeInfo
}
// UDM签约用户-获取全部保存数据
// UDM签约用户重载数据
//
// POST /resetData/:neId
func (s *UDMSubController) ResetData(c *gin.Context) {
@@ -49,21 +50,21 @@ func (s *UDMSubController) ResetData(c *gin.Context) {
}
neId = ""
data := s.udmSubService.Save(neId)
data := s.udmSubService.ResetData(neId)
c.JSON(200, result.OkData(data))
}
// UDM签约用户
// UDM签约用户列表
//
// GET /list
func (s *UDMSubController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
querys["neId"] = ""
data := s.udmSubService.Page(querys)
data := s.udmSubService.SelectPage(querys)
c.JSON(200, result.Ok(data))
}
// UDM签约用户-信息
// UDM签约用户信息
//
// GET /:neId/:imsi
func (s *UDMSubController) Info(c *gin.Context) {
@@ -82,10 +83,16 @@ func (s *UDMSubController) Info(c *gin.Context) {
return
}
msg := fmt.Sprintf("dsp udmuser:imsi=%s", imsi)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToMap(neInfo.IP, msg)
cmd := fmt.Sprintf("dsp udmuser:imsi=%s", imsi)
data, err := telnet.ConvertToMap(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -104,8 +111,9 @@ func (s *UDMSubController) Info(c *gin.Context) {
if imsMsisdnLen != -1 {
msisdn = msisdn[:imsMsisdnLen]
}
userInfo := model.UDMSub{
Imsi: imsi,
neId = ""
u := model.UDMSub{
IMSI: imsi,
Msisdn: msisdn,
Ambr: data["AMBR"],
Arfb: data["AreaForbidden"],
@@ -115,35 +123,37 @@ func (s *UDMSubController) Info(c *gin.Context) {
Nssai: data["NSSAI"],
SmfSel: data["Smf-Selection"],
Rat: fmt.Sprint(rat),
NeId: neId,
}
// 1,64,24,65,def_eps,1,2,010200000000,-
if v, ok := data["EPS-Data"]; ok {
userInfo.EpsDat = v
u.EpsDat = v
arr := strings.Split(v, ",")
userInfo.EpsFlag = arr[0]
userInfo.EpsOdb = arr[1]
userInfo.HplmnOdb = arr[2]
userInfo.Ard = arr[3]
userInfo.Epstpl = arr[4]
userInfo.ContextId = arr[5]
userInfo.ApnContext = arr[7]
userInfo.StaticIp = arr[8]
u.EpsFlag = arr[0]
u.EpsOdb = arr[1]
u.HplmnOdb = arr[2]
u.Ard = arr[3]
u.Epstpl = arr[4]
u.ContextId = arr[5]
u.ApnContext = arr[7]
// [6] 是不要的,导入和导出不用
u.StaticIp = arr[8]
}
// 查询数据库是否存在并存入更新
neId = ""
list := s.udmSubService.List(model.UDMSub{NeID: neId, Imsi: imsi})
// 查询imsi存在赋予id用于更新
list := s.udmSubService.SelectList(u)
if len(list) > 0 {
listItme := list[0]
userInfo.ID = listItme.ID
s.udmSubService.Update(neId, userInfo)
} else {
s.udmSubService.Insert(neId, userInfo)
item := list[0]
if item.ID != "" {
u.ID = item.ID
}
}
c.JSON(200, result.OkData(userInfo))
go s.udmSubService.Insert(neId, u)
c.JSON(200, result.OkData(u))
}
// UDM签约用户-增加
// UDM签约用户新增
//
// POST /:neId
func (s *UDMSubController) Add(c *gin.Context) {
@@ -156,7 +166,7 @@ func (s *UDMSubController) Add(c *gin.Context) {
var body model.UDMSub
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.Imsi == "" {
if err != nil || body.IMSI == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
@@ -168,15 +178,21 @@ func (s *UDMSubController) Add(c *gin.Context) {
return
}
msg := fmt.Sprintf("add udmuser:imsi=%s,msisdn=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
body.Imsi, body.Msisdn, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
// static_ip指给4G UE分配的静态IP没有可不带此字段名批量添加IP会自动递增
if body.StaticIp != "" {
msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("add udmuser:imsi=%s,msisdn=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
body.IMSI, body.Msisdn, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
// static_ip指给4G UE分配的静态IP没有可不带此字段名批量添加IP会自动递增
if body.StaticIp != "" {
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
}
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -185,12 +201,12 @@ func (s *UDMSubController) Add(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmSubService.Insert(neId, body)
go s.udmSubService.Insert(neId, body)
}
c.JSON(200, result.OkData(data))
}
// UDM签约用户-批量添加
// UDM签约用户批量新增
//
// POST /:neId/:num
func (s *UDMSubController) Adds(c *gin.Context) {
@@ -204,7 +220,7 @@ func (s *UDMSubController) Adds(c *gin.Context) {
var body model.UDMSub
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.Imsi == "" {
if err != nil || body.IMSI == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
@@ -216,15 +232,21 @@ func (s *UDMSubController) Adds(c *gin.Context) {
return
}
msg := fmt.Sprintf("baa udmuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
body.Imsi, body.Msisdn, num, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
// static_ip指给4G UE分配的静态IP没有可不带此字段名批量添加IP会自动递增
if body.StaticIp != "" {
msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("baa udmuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
body.IMSI, body.Msisdn, num, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
// static_ip指给4G UE分配的静态IP没有可不带此字段名批量添加IP会自动递增
if body.StaticIp != "" {
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
}
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -233,12 +255,12 @@ func (s *UDMSubController) Adds(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmSubService.Inserts(neId, body, num)
go s.udmSubService.LoadData(neId, body.IMSI, num)
}
c.JSON(200, result.OkData(data))
}
// UDM签约用户-修改
// UDM签约用户修改
//
// PUT /:neId
func (s *UDMSubController) Edit(c *gin.Context) {
@@ -251,7 +273,7 @@ func (s *UDMSubController) Edit(c *gin.Context) {
var body model.UDMSub
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.Imsi == "" {
if err != nil || body.IMSI == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
@@ -263,65 +285,71 @@ func (s *UDMSubController) Edit(c *gin.Context) {
return
}
msg := fmt.Sprintf("mod udmuser:imsi=%s", body.Imsi)
// 修改的参数名称
if body.Msisdn != "" {
msg += fmt.Sprintf(",msisdn=%s", body.Msisdn)
}
if body.Ambr != "" {
msg += fmt.Sprintf(",ambr=%s", body.Ambr)
}
if body.Nssai != "" {
msg += fmt.Sprintf(",nssai=%s", body.Nssai)
}
if body.Arfb != "" {
msg += fmt.Sprintf(",arfb=%s", body.Arfb)
}
if body.Sar != "" {
msg += fmt.Sprintf(",sar=%s", body.Sar)
}
if body.Rat != "" {
msg += fmt.Sprintf(",rat=%s", body.Rat)
}
if body.Cn != "" {
msg += fmt.Sprintf(",cn=%s", body.Cn)
}
if body.SmfSel != "" {
msg += fmt.Sprintf(",smf_sel=%s", body.SmfSel)
}
if body.SmData != "" {
msg += fmt.Sprintf(",sm_data=%s", body.SmData)
}
if body.EpsDat != "" {
msg += fmt.Sprintf(",eps_dat=%s", body.EpsDat)
}
if body.EpsFlag != "" {
msg += fmt.Sprintf(",eps_flag=%s", body.EpsFlag)
}
if body.EpsOdb != "" {
msg += fmt.Sprintf(",eps_odb=%s", body.EpsOdb)
}
if body.HplmnOdb != "" {
msg += fmt.Sprintf(",hplmn_odb=%s", body.HplmnOdb)
}
if body.Epstpl != "" {
msg += fmt.Sprintf(",epstpl=%s", body.Epstpl)
}
if body.Ard != "" {
msg += fmt.Sprintf(",ard=%s", body.Ard)
}
if body.ContextId != "" {
msg += fmt.Sprintf(",context_id=%s", body.ContextId)
}
if body.ApnContext != "" {
msg += fmt.Sprintf(",apn_context=%s", body.ApnContext)
}
if body.StaticIp != "" {
msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("mod udmuser:imsi=%s", body.IMSI)
// 修改的参数名称
if body.Msisdn != "" {
cmd += fmt.Sprintf(",msisdn=%s", body.Msisdn)
}
if body.Ambr != "" {
cmd += fmt.Sprintf(",ambr=%s", body.Ambr)
}
if body.Nssai != "" {
cmd += fmt.Sprintf(",nssai=%s", body.Nssai)
}
if body.Arfb != "" {
cmd += fmt.Sprintf(",arfb=%s", body.Arfb)
}
if body.Sar != "" {
cmd += fmt.Sprintf(",sar=%s", body.Sar)
}
if body.Rat != "" {
cmd += fmt.Sprintf(",rat=%s", body.Rat)
}
if body.Cn != "" {
cmd += fmt.Sprintf(",cn=%s", body.Cn)
}
if body.SmfSel != "" {
cmd += fmt.Sprintf(",smf_sel=%s", body.SmfSel)
}
if body.SmData != "" {
cmd += fmt.Sprintf(",sm_data=%s", body.SmData)
}
if body.EpsDat != "" {
cmd += fmt.Sprintf(",eps_dat=%s", body.EpsDat)
}
if body.EpsFlag != "" {
cmd += fmt.Sprintf(",eps_flag=%s", body.EpsFlag)
}
if body.EpsOdb != "" {
cmd += fmt.Sprintf(",eps_odb=%s", body.EpsOdb)
}
if body.HplmnOdb != "" {
cmd += fmt.Sprintf(",hplmn_odb=%s", body.HplmnOdb)
}
if body.Epstpl != "" {
cmd += fmt.Sprintf(",epstpl=%s", body.Epstpl)
}
if body.Ard != "" {
cmd += fmt.Sprintf(",ard=%s", body.Ard)
}
if body.ContextId != "" {
cmd += fmt.Sprintf(",context_id=%s", body.ContextId)
}
if body.ApnContext != "" {
cmd += fmt.Sprintf(",apn_context=%s", body.ApnContext)
}
if body.StaticIp != "" {
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
}
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -330,12 +358,12 @@ func (s *UDMSubController) Edit(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmSubService.Update(neId, body)
go s.udmSubService.Insert(neId, body)
}
c.JSON(200, result.OkData(data))
}
// UDM签约用户-删除
// UDM签约用户删除
//
// DELETE /:neId/:imsi
func (s *UDMSubController) Remove(c *gin.Context) {
@@ -362,27 +390,34 @@ func (s *UDMSubController) Remove(c *gin.Context) {
return
}
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
resultData := map[string]string{}
for _, imsi := range uniqueIDs {
msg := fmt.Sprintf("del udmuser:imsi=%s", imsi)
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("del udmuser:imsi=%s", imsi)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
resultData[imsi] = err.Error()
continue
}
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmSubService.Delete(neId, imsi)
resultData[imsi] = data
go s.udmSubService.Delete(neId, imsi)
}
resultData[imsi] = data
}
c.JSON(200, result.OkData(resultData))
}
// UDM签约用户-批量删除
// UDM签约用户批量删除
//
// DELETE /:neId/:imsi/:num
func (s *UDMSubController) Removes(c *gin.Context) {
@@ -402,10 +437,16 @@ func (s *UDMSubController) Removes(c *gin.Context) {
return
}
msg := fmt.Sprintf("bde udmuser:start_imsi=%s,sub_num=%s", imsi, num)
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("bde udmuser:start_imsi=%s,sub_num=%s", imsi, num)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -414,12 +455,12 @@ func (s *UDMSubController) Removes(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmSubService.Deletes(neId, imsi, num)
go s.udmSubService.LoadData(neId, imsi, num)
}
c.JSON(200, result.OkData(data))
}
// UDM签约用户-导出
// UDM签约用户导出
//
// POST /export
func (s *UDMSubController) Export(c *gin.Context) {
@@ -440,9 +481,9 @@ func (s *UDMSubController) Export(c *gin.Context) {
}
neId := ""
list := s.udmSubService.List(model.UDMSub{NeID: neId})
list := s.udmSubService.SelectList(model.UDMSub{NeId: neId})
// 文件名
fileName := fmt.Sprintf("OMC_SUB_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
fileName := fmt.Sprintf("udm_sub_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
filePath := fmt.Sprintf("%s/%s", file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
if body.Type == "csv" {
@@ -451,7 +492,7 @@ func (s *UDMSubController) Export(c *gin.Context) {
data = append(data, []string{"imsi", "msisdn", "ambr", "nssai", "arfb", "sar", "rat", "cn", "smf_sel", "sm_dat", "eps_dat"})
for _, v := range list {
epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
data = append(data, []string{v.IMSI, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
}
// 输出到文件
err = file.WriterFileCSV(data, filePath)
@@ -466,7 +507,7 @@ func (s *UDMSubController) Export(c *gin.Context) {
data := [][]string{}
for _, v := range list {
epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
data = append(data, []string{v.IMSI, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
}
// 输出到文件
err = file.WriterFileTXT(data, ",", filePath)
@@ -479,55 +520,68 @@ func (s *UDMSubController) Export(c *gin.Context) {
c.FileAttachment(filePath, fileName)
}
// UDM签约用户-导入
// UDM签约用户导入
//
// POST /import
func (s *UDMSubController) Import(c *gin.Context) {
language := ctx.AcceptLanguage(c)
neId := c.PostForm("neId")
if neId == "" {
var body struct {
NeId string `json:"neId" binding:"required"`
UploadPath string `json:"uploadPath" binding:"required"`
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
formFile, err := c.FormFile("file")
if err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 获取文件名
if !(strings.HasSuffix(formFile.Filename, ".csv") || strings.HasSuffix(formFile.Filename, ".txt")) {
// 判断文件名
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
return
}
// 上传文件转存
upFilePath, err := file.TransferUploadFile(formFile, uploadsubpath.IMPORT, nil)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 本地文件
localPath := file.ParseUploadFilePath(upFilePath)
nePath := "/tmp" //config.Get("mml.upload").(string)
// 复制到远程
err = ssh.FileSCPLocalToNe(neInfo.IP, localPath, nePath)
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
fileName := localPath[strings.LastIndex(localPath, "/")+1:]
msg := fmt.Sprintf("import udmuser:path=%s", fmt.Sprintf("%s/%s", nePath, fileName))
// 本地文件
localFilePath := file.ParseUploadFilePath(body.UploadPath)
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
// 复制到远程
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
c.JSON(200, result.ErrMsg("error uploading file"))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
cmd := fmt.Sprintf("import udmuser:path=%s", neFilePath)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
@@ -535,15 +589,15 @@ func (s *UDMSubController) Import(c *gin.Context) {
// 命令ok时
if strings.Contains(data, "ok") {
if strings.HasSuffix(fileName, ".csv") {
data := file.ReadFileCSV(localPath)
neId = ""
go s.udmSubService.InsertCSV(neId, data)
if strings.HasSuffix(body.UploadPath, ".csv") {
data := file.ReadFileCSV(localFilePath)
neId := ""
go s.udmSubService.InsertData(neId, "csv", data)
}
if strings.HasSuffix(fileName, ".txt") {
data := file.ReadFileTXT(",", localPath)
neId = ""
go s.udmSubService.InsertTxt(neId, data)
if strings.HasSuffix(body.UploadPath, ".txt") {
data := file.ReadFileTXT(",", localFilePath)
neId := ""
go s.udmSubService.InsertData(neId, "txt", data)
}
}
c.JSON(200, result.OkMsg(data))

View File

@@ -1,28 +0,0 @@
package model
import "time"
// CDREvent CDR会话对象 cdr_event
type CDREvent 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"`
CDRJSONStr string `json:"cdrJSON" gorm:"column:cdr_json"`
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
}
// CDREventQuery CDR会话对象查询参数结构体
type CDREventQuery struct {
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型, 暂时支持IMS
NeID string `json:"neId" form:"neId" binding:"required"`
RmUID string `json:"rmUID" form:"rmUID"`
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC MOSM MTSM
StartTime string `json:"startTime" form:"startTime"`
EndTime string `json:"endTime" form:"endTime"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序asc desc
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
}

View File

@@ -0,0 +1,30 @@
package model
import "time"
// CDREventIMS CDR会话对象IMS cdr_event_ims
type CDREventIMS 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"`
CDRJSONStr string `json:"cdrJSON" gorm:"column:cdr_json"`
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
}
// CDREventIMSQuery CDR会话对象IMS查询参数结构体
type CDREventIMSQuery struct {
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型IMS
NeID string `json:"neId" form:"neId" binding:"required"`
RmUID string `json:"rmUID" form:"rmUID"`
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC MOSM MTSM
CallerParty string `json:"callerParty" form:"callerParty"` // 主叫号码
CalledParty string `json:"calledParty" form:"calledParty"` // 被叫号码
StartTime string `json:"startTime" form:"startTime"`
EndTime string `json:"endTime" form:"endTime"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序asc desc
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
}

View File

@@ -0,0 +1,40 @@
package model
import "time"
// CDREventSMF CDR会话对象SMF cdr_event_smf
type CDREventSMF 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"`
CDRJSONStr string `json:"cdrJSON" gorm:"column:cdr_json"`
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
// ====== 非数据库字段属性 ======
// RecordType string `json:"recordType" gorm:"column:record_type"`
// ChargingID string `json:"chargingID" gorm:"column:charging_id"`
// SubscriberID string `json:"subscriberID" gorm:"column:subscriber_id"`
// Duration string `json:"duration" gorm:"column:duration"`
// DataVolumeUplink string `json:"dataVolumeUplink" gorm:"column:data_volume_uplink"`
// DataVolumeDownlink string `json:"dataVolumeDownlink" gorm:"column:data_volume_downlink"`
// DataTotalVolume string `json:"dataTotalVolume" gorm:"column:data_total_volume"`
// PDUAddress string `json:"pduAddress" gorm:"column:pdu_address"`
}
// CDREventSMFQuery CDR会话对象SMF查询参数结构体
type CDREventSMFQuery struct {
NeType string `json:"neType" form:"neType" binding:"required"` // SMF
NeID string `json:"neId" form:"neId" binding:"required"`
RmUID string `json:"rmUID" form:"rmUID"`
RecordType string `json:"recordType" form:"recordType"` // 暂时没用到
SubscriberID string `json:"subscriberID" form:"subscriberID"`
StartTime string `json:"startTime" form:"startTime"`
EndTime string `json:"endTime" form:"endTime"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序asc desc
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
}

View File

@@ -0,0 +1,17 @@
package model
// UDMAuth UDM鉴权用户对象 u_auth_user
type UDMAuth struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 默认ID
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡号
Amf string `json:"amf" gorm:"column:amf"` // ANF
Status string `json:"status" gorm:"column:status"` // 状态 默认给1
Ki string `json:"ki" gorm:"column:ki"` // ki
AlgoIndex string `json:"algoIndex" gorm:"column:algo_index"` // AlgoIndex
Opc string `json:"opc" gorm:"column:opc"` // opc
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
}
func (UDMAuth) TableName() string {
return "u_auth_user"
}

View File

@@ -4,7 +4,7 @@ package model
type UDMSub struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
Msisdn string `json:"msisdn" gorm:"column:msisdn"` // 相当手机号
Imsi string `json:"imsi" gorm:"column:imsi"` // SIM卡号
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡号
Ambr string `json:"ambr" gorm:"column:ambr"`
Nssai string `json:"nssai" gorm:"column:nssai"`
Rat string `json:"rat" gorm:"column:rat"`
@@ -14,7 +14,7 @@ type UDMSub struct {
SmData string `json:"smData" gorm:"column:sm_data"`
SmfSel string `json:"smfSel" gorm:"column:smf_sel"`
EpsDat string `json:"epsDat" gorm:"column:eps_dat"`
NeID string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
EpsFlag string `json:"epsFlag" gorm:"column:eps_flag"`
EpsOdb string `json:"epsOdb" gorm:"column:eps_odb"`
@@ -25,7 +25,8 @@ type UDMSub struct {
ApnContext string `json:"apnContext" gorm:"column:apn_context"`
StaticIp string `json:"staticIp" gorm:"column:static_ip"`
SubNum string `json:"subNum,omitempty" gorm:"-"` // 批量数
// ====== 非数据库字段属性 ======
}
func (UDMSub) TableName() string {

View File

@@ -2,24 +2,25 @@ package model
import "time"
// UEEvent UE会话对象 ue_event
type UEEvent struct {
// UEEventAMF UE会话对象AMF ue_event_amf
type UEEventAMF 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"`
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
EventType string `json:"eventType" gorm:"column:event_type"`
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"`
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
}
// UEEventQuery UE会话对象查询参数结构体
type UEEventQuery struct {
// UEEventAMFQuery UE会话对象AMF查询参数结构体
type UEEventAMFQuery struct {
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型, 暂时支持AMF
NeID string `json:"neId" form:"neId" binding:"required"`
RmUID string `json:"rmUID" form:"rmUID"`
EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state
IMSI string `json:"imsi" form:"imsi"` // imsi
StartTime string `json:"startTime" form:"startTime"`
EndTime string `json:"endTime" form:"endTime"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段

View File

@@ -0,0 +1,30 @@
package model
import "time"
// UEEventMME UE会话对象MME ue_event_mme
type UEEventMME 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"`
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"`
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
}
// UEEventMMEQuery UE会话对象MME查询参数结构体
type UEEventMMEQuery struct {
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型, 暂时支持MME
NeID string `json:"neId" form:"neId" binding:"required"`
RmUID string `json:"rmUID" form:"rmUID"`
EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state
IMSI string `json:"imsi" form:"imsi"` // imsi
StartTime string `json:"startTime" form:"startTime"`
EndTime string `json:"endTime" form:"endTime"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序asc desc
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
}

View File

@@ -4,6 +4,7 @@ import (
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/middleware"
"nms_cxy/src/framework/middleware/collectlogs"
"nms_cxy/src/framework/middleware/repeat"
"nms_cxy/src/modules/network_data/controller"
"github.com/gin-gonic/gin"
@@ -44,33 +45,58 @@ func Setup(router *gin.Engine) {
// 网元IMS
imsGroup := neDataGroup.Group("/ims")
{
// CDR会话事件列表
imsGroup.GET("/cdr/list",
middleware.PreAuthorize(nil),
controller.NewIMSController.CDRList,
)
// CDR会话删除
imsGroup.DELETE("/cdr/:cdrIds",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewIMSController.CDRRemove,
)
imsGroup.POST("/cdr/export",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewIMSController.CDRExport,
)
}
// 网元SMF
smfGroup := neDataGroup.Group("/smf")
{
smfGroup.GET("/cdr/list",
middleware.PreAuthorize(nil),
controller.NewSMFController.CDRList,
)
smfGroup.DELETE("/cdr/:cdrIds",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewSMFController.CDRRemove,
)
smfGroup.POST("/cdr/export",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewSMFController.CDRExport,
)
}
// 网元AMF
amfGroup := neDataGroup.Group("/amf")
{
// UE会话事件
amfGroup.GET("/ue/list",
middleware.PreAuthorize(nil),
controller.NewAMFController.UEList,
)
// UE会话删除
amfGroup.DELETE("/ue/:ueIds",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewAMFController.UERemove,
)
amfGroup.POST("/ue/export",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewAMFController.UEExport,
)
}
// 网元UPF
@@ -82,4 +108,130 @@ func Setup(router *gin.Engine) {
)
}
// 网元UDM 鉴权用户信息
udmAuthGroup := neDataGroup.Group("/udm/auth")
{
udmAuthGroup.PUT("/resetData/:neId",
repeat.RepeatSubmit(5),
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_CLEAN)),
controller.NewUDMAuth.ResetData,
)
udmAuthGroup.GET("/list",
middleware.PreAuthorize(nil),
controller.NewUDMAuth.List,
)
udmAuthGroup.GET("/:neId/:imsi",
middleware.PreAuthorize(nil),
controller.NewUDMAuth.Info,
)
udmAuthGroup.POST("/:neId",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewUDMAuth.Add,
)
udmAuthGroup.POST("/:neId/:num",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewUDMAuth.Adds,
)
udmAuthGroup.PUT("/:neId",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewUDMAuth.Edit,
)
udmAuthGroup.DELETE("/:neId/:imsi",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewUDMAuth.Remove,
)
udmAuthGroup.DELETE("/:neId/:imsi/:num",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewUDMAuth.Removes,
)
udmAuthGroup.POST("/export",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewUDMAuth.Export,
)
udmAuthGroup.POST("/import",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_IMPORT)),
controller.NewUDMAuth.Import,
)
}
// 网元UDM 签约用户信息
udmSubGroup := neDataGroup.Group("/udm/sub")
{
udmSubGroup.PUT("/resetData/:neId",
repeat.RepeatSubmit(5),
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_CLEAN)),
controller.NewUDMSub.ResetData,
)
udmSubGroup.GET("/list",
middleware.PreAuthorize(nil),
controller.NewUDMSub.List,
)
udmSubGroup.GET("/:neId/:imsi",
middleware.PreAuthorize(nil),
controller.NewUDMSub.Info,
)
udmSubGroup.POST("/:neId",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewUDMSub.Add,
)
udmSubGroup.POST("/:neId/:num",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewUDMSub.Adds,
)
udmSubGroup.PUT("/:neId",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewUDMSub.Edit,
)
udmSubGroup.DELETE("/:neId/:imsi",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewUDMSub.Remove,
)
udmSubGroup.DELETE("/:neId/:imsi/:num",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewUDMSub.Removes,
)
udmSubGroup.POST("/export",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewUDMSub.Export,
)
udmSubGroup.POST("/import",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_IMPORT)),
controller.NewUDMSub.Import,
)
}
// 网元MME
mmeGroup := neDataGroup.Group("/mme")
{
mmeGroup.GET("/ue/list",
middleware.PreAuthorize(nil),
controller.NewMMEController.UEList,
)
mmeGroup.DELETE("/ue/:ueIds",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewMMEController.UERemove,
)
mmeGroup.POST("/ue/export",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewMMEController.UEExport,
)
}
}

View File

@@ -2,13 +2,13 @@ package repository
import "nms_cxy/src/modules/network_data/model"
// CDR会话事件 数据层接口
type ICDREvent interface {
// CDR会话事件IMS 数据层接口
type ICDREventIMS interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.CDREventQuery) map[string]any
SelectPage(querys model.CDREventIMSQuery) map[string]any
// SelectByIds 通过ID查询
SelectByIds(cdrIds []string) []model.CDREvent
SelectByIds(cdrIds []string) []model.CDREventIMS
// DeleteByIds 批量删除信息
DeleteByIds(cdrIds []string) int64

View File

@@ -6,15 +6,14 @@ import (
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/date"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/network_data/model"
)
// 实例化数据层 CDREventImpl 结构体
var NewCDREventImpl = &CDREventImpl{
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event`,
var NewCDREventIMSImpl = &CDREventIMSImpl{
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event_ims`,
resultMap: map[string]string{
"id": "ID",
@@ -27,8 +26,8 @@ var NewCDREventImpl = &CDREventImpl{
},
}
// CDREventImpl CDR会话事件 数据层处理
type CDREventImpl struct {
// CDREventIMSImpl CDR会话事件IMS 数据层处理
type CDREventIMSImpl struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
@@ -36,10 +35,10 @@ type CDREventImpl struct {
}
// convertResultRows 将结果记录转实体结果组
func (r *CDREventImpl) convertResultRows(rows []map[string]any) []model.CDREvent {
arr := make([]model.CDREvent, 0)
func (r *CDREventIMSImpl) convertResultRows(rows []map[string]any) []model.CDREventIMS {
arr := make([]model.CDREventIMS, 0)
for _, row := range rows {
item := model.CDREvent{}
item := model.CDREventIMS{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
repo.SetFieldValue(&item, keyMapper, value)
@@ -51,7 +50,7 @@ func (r *CDREventImpl) convertResultRows(rows []map[string]any) []model.CDREvent
}
// SelectPage 根据条件分页查询
func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
func (r *CDREventIMSImpl) SelectPage(querys model.CDREventIMSQuery) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
@@ -63,19 +62,27 @@ func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
conditions = append(conditions, "rm_uid = ?")
params = append(params, querys.RmUID)
}
if querys.RmUID != "" {
conditions = append(conditions, "rm_uid = ?")
params = append(params, querys.RmUID)
}
if querys.StartTime != "" {
conditions = append(conditions, "timestamp >= ?")
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
params = append(params, beginDate.Unix())
if len(querys.StartTime) == 13 {
querys.StartTime = querys.StartTime[:10]
}
params = append(params, querys.StartTime)
}
if querys.EndTime != "" {
conditions = append(conditions, "timestamp <= ?")
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
params = append(params, endDate.Unix())
if len(querys.EndTime) == 13 {
querys.EndTime = querys.EndTime[:10]
}
params = append(params, querys.EndTime)
}
if querys.CallerParty != "" {
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.callerParty') = ?")
params = append(params, querys.CallerParty)
}
if querys.CalledParty != "" {
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.calledParty') = ?")
params = append(params, querys.CalledParty)
}
if querys.RecordType != "" {
recordTypes := strings.Split(querys.RecordType, ",")
@@ -94,11 +101,11 @@ func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
result := map[string]any{
"total": 0,
"rows": []model.CDREvent{},
"rows": []model.CDREventIMS{},
}
// 查询数量 长度为0直接返回
totalSql := "select count(1) as 'total' from cdr_event"
totalSql := "select count(1) as 'total' from cdr_event_ims"
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
if err != nil {
logger.Errorf("total err => %v", err)
@@ -144,23 +151,23 @@ func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
}
// SelectByIds 通过ID查询
func (r *CDREventImpl) SelectByIds(cdrIds []string) []model.CDREvent {
func (r *CDREventIMSImpl) SelectByIds(cdrIds []string) []model.CDREventIMS {
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
querySql := r.selectSql + " where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(cdrIds)
results, err := datasource.RawDB("", querySql, parameters)
if err != nil {
logger.Errorf("query err => %v", err)
return []model.CDREvent{}
return []model.CDREventIMS{}
}
// 转换实体
return r.convertResultRows(results)
}
// DeleteByIds 批量删除信息
func (r *CDREventImpl) DeleteByIds(cdrIds []string) int64 {
func (r *CDREventIMSImpl) DeleteByIds(cdrIds []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
sql := "delete from cdr_event where id in (" + placeholder + ")"
sql := "delete from cdr_event_ims where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(cdrIds)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {

View File

@@ -0,0 +1,15 @@
package repository
import "nms_cxy/src/modules/network_data/model"
// CDR会话事件SMF 数据层接口
type ICDREventSMF interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.CDREventSMFQuery) map[string]any
// SelectByIds 通过ID查询
SelectByIds(cdrIds []string) []model.CDREventSMF
// DeleteByIds 批量删除信息
DeleteByIds(cdrIds []string) int64
}

View File

@@ -0,0 +1,185 @@
package repository
import (
"fmt"
"strings"
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/network_data/model"
)
// 实例化数据层 CDREventSMFImpl 结构体
var NewCDREventSMFImpl = &CDREventSMFImpl{
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event_smf`,
// selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, JSON_EXTRACT(cdr_json, '$.recordType') AS record_type, JSON_EXTRACT(cdr_json, '$.chargingID') AS charging_id, JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') AS subscriber_id, JSON_EXTRACT(cdr_json, '$.duration') AS duration, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink') AS data_volume_uplink, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink') AS data_volume_downlink, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume') AS data_total_volume, JSON_EXTRACT(cdr_json, '$.pDUSessionChargingInformation.pDUAddress') AS pdu_address, created_at from cdr_event_smf`,
resultMap: map[string]string{
"id": "ID",
"ne_type": "NeType",
"ne_name": "NeName",
"rm_uid": "RmUID",
"timestamp": "Timestamp",
"cdr_json": "CDRJSONStr",
"created_at": "CreatedAt",
// "id": "ID",
// "ne_type": "NeType",
// "ne_name": "NeName",
// "rm_uid": "RmUID",
// "timestamp": "Timestamp",
// "record_type": "RecordType",
// "charging_id": "ChargingID",
// "subscriber_id": "SubscriberID",
// "duration": "Duration",
// "data_volume_uplink": "DataVolumeUplink",
// "data_volume_downlink": "DataVolumeDownlink",
// "data_total_volume": "DataTotalVolume",
// "pdu_address": "PDUAddress",
// "created_at": "CreatedAt",
},
}
// CDREventSMFImpl CDR会话事件 数据层处理
type CDREventSMFImpl struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
resultMap map[string]string
}
// convertResultRows 将结果记录转实体结果组
func (r *CDREventSMFImpl) convertResultRows(rows []map[string]any) []model.CDREventSMF {
arr := make([]model.CDREventSMF, 0)
for _, row := range rows {
item := model.CDREventSMF{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
repo.SetFieldValue(&item, keyMapper, value)
}
}
arr = append(arr, item)
}
return arr
}
// SelectPage 根据条件分页查询
func (r *CDREventSMFImpl) SelectPage(querys model.CDREventSMFQuery) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if querys.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, querys.NeType)
}
if querys.RmUID != "" {
conditions = append(conditions, "rm_uid = ?")
params = append(params, querys.RmUID)
}
if querys.StartTime != "" {
conditions = append(conditions, "timestamp >= ?")
if len(querys.StartTime) == 13 {
querys.StartTime = querys.StartTime[:10]
}
params = append(params, querys.StartTime)
}
if querys.EndTime != "" {
conditions = append(conditions, "timestamp <= ?")
if len(querys.EndTime) == 13 {
querys.EndTime = querys.EndTime[:10]
}
params = append(params, querys.EndTime)
}
if querys.RecordType != "" {
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.recordType') = ?")
params = append(params, querys.RecordType)
}
if querys.SubscriberID != "" {
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') = ?")
params = append(params, querys.SubscriberID)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
result := map[string]any{
"total": 0,
"rows": []model.CDREventSMF{},
}
// 查询数量 长度为0直接返回
totalSql := "select count(1) as 'total' from cdr_event_smf"
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
if err != nil {
logger.Errorf("total err => %v", err)
return result
}
total := parse.Number(totalRows[0]["total"])
if total == 0 {
return result
} else {
result["total"] = total
}
// 分页
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
pageSql := " limit ?,? "
params = append(params, pageNum*pageSize)
params = append(params, pageSize)
// 排序
orderSql := ""
if querys.SortField != "" {
sortSql := querys.SortField
if querys.SortOrder != "" {
if querys.SortOrder == "desc" {
sortSql += " desc "
} else {
sortSql += " asc "
}
}
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
}
// 查询数据
querySql := r.selectSql + whereSql + orderSql + pageSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
// 转换实体
result["rows"] = r.convertResultRows(results)
return result
}
// SelectByIds 通过ID查询
func (r *CDREventSMFImpl) SelectByIds(cdrIds []string) []model.CDREventSMF {
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
querySql := r.selectSql + " where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(cdrIds)
results, err := datasource.RawDB("", querySql, parameters)
if err != nil {
logger.Errorf("query err => %v", err)
return []model.CDREventSMF{}
}
// 转换实体
return r.convertResultRows(results)
}
// DeleteByIds 批量删除信息
func (r *CDREventSMFImpl) DeleteByIds(cdrIds []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
sql := "delete from cdr_event_smf where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(cdrIds)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {
logger.Errorf("delete err => %v", err)
return 0
}
return results
}

View File

@@ -7,9 +7,15 @@ type IPerfKPI interface {
// SelectGoldKPI 通过网元指标数据信息
SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any
// select from new kpi report table, exp. kpi_report_upf
SelectKpiReport(query model.GoldKPIQuery, kpiIds []string) []map[string]any
// SelectGoldKPITitle 网元对应的指标名称
SelectGoldKPITitle(neType string) []model.GoldKPITitle
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
SelectUPFTotalFlow(neType, rmUID, startDate, endDate string) map[string]any
// select upf throughput from new kpi_report
SelectUPFThroughput(neType, rmUID, startDate, endDate string) map[string]any
}

View File

@@ -86,6 +86,108 @@ func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) [
return results
}
func (r *PerfKPIImpl) SelectKpiReport(query model.GoldKPIQuery, kpiIds []string) []map[string]any {
// 查询条件拼接
var conditions []string
var params []any
var tableName string = "kpi_report_"
if query.RmUID != "" {
conditions = append(conditions, "gk.rm_uid = ?")
params = append(params, query.RmUID)
}
if query.NeType != "" {
//conditions = append(conditions, "gk.ne_type = ?")
// params = append(params, query.NeType)
tableName += strings.ToLower(query.NeType)
}
var dateStr1, dateStr2, timeStr1, timeStr2 string
if query.StartTime != "" {
dateStr1 = query.StartTime[:10]
timeStr1 = query.StartTime[11:]
}
if query.EndTime != "" {
dateStr2 = query.EndTime[:10]
timeStr2 = query.EndTime[11:]
}
if dateStr1 == dateStr2 && dateStr1 != "" {
conditions = append(conditions, "gk.`date` = ?")
params = append(params, dateStr1)
conditions = append(conditions, "gk.`start_time` >= ?")
params = append(params, timeStr1)
conditions = append(conditions, "gk.`start_time` <= ?")
params = append(params, timeStr2)
} else {
if dateStr1 != "" {
conditions = append(conditions, "(gk.`date` > ? OR (gk.`date` = ? AND gk.`start_time` >= ?))")
params = append(params, dateStr1, dateStr1, timeStr1)
}
if dateStr2 != "" {
conditions = append(conditions, "(gk.`date` < ? OR (gk.`date` = ? AND gk.`start_time` <= ?))")
params = append(params, dateStr2, dateStr2, timeStr2)
}
}
// var dateTimeStr string = "CONCAT(gk.`date`, \" \", gk.start_time)"
// if query.StartTime != "" {
// conditions = append(conditions, dateTimeStr+" >= ?")
// params = append(params, query.StartTime)
// }
// if query.EndTime != "" {
// conditions = append(conditions, dateTimeStr+" <= ?")
// params = append(params, query.EndTime)
// }
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
// 查询字段列
var dateTimeStr string = "CONCAT(gk.`date`, \" \", gk.start_time)"
timeFormat := "DATE_FORMAT(" + dateTimeStr + ", '%Y-%m-%d %H:%i:')"
secondGroup := fmt.Sprintf("LPAD(FLOOR(SECOND(gk.start_time) / %d) * %d, 2, '0')", query.Interval, query.Interval)
groupByField := fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, secondGroup)
if query.Interval > 60 {
minute := query.Interval / 60
timeFormat = "DATE_FORMAT(" + dateTimeStr + ", '%Y-%m-%d %H:')"
minuteGroup := fmt.Sprintf("LPAD(FLOOR(MINUTE(gk.start_time) / %d) * %d, 2, '0')", minute, minute)
groupByField = fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, minuteGroup)
}
var fields = []string{
groupByField,
"min(CASE WHEN gk.index != '' THEN gk.index ELSE 0 END) AS startIndex",
"min(CASE WHEN gk.ne_type != '' THEN gk.ne_type ELSE 0 END) AS neType",
"min(CASE WHEN gk.ne_name != '' THEN gk.ne_name ELSE 0 END) AS neName",
}
for i, kid := range kpiIds {
// 特殊字段只取最后一次收到的非0值
if kid == "AMF.01" || kid == "UDM.01" || kid == "UDM.02" || kid == "UDM.03" || kid == "SMF.01" {
str := fmt.Sprintf("IFNULL(SUBSTRING_INDEX(GROUP_CONCAT( CASE WHEN JSON_EXTRACT(gk.kpi_values, '$[%d].kpi_id') = '%s' THEN JSON_EXTRACT(gk.kpi_values, '$[%d].value') END ), ',', 1), 0) AS '%s'", i, kid, i, kid)
fields = append(fields, str)
} else {
str := fmt.Sprintf("sum(CASE WHEN JSON_EXTRACT(gk.kpi_values, '$[%d].kpi_id') = '%s' THEN JSON_EXTRACT(gk.kpi_values, '$[%d].value') ELSE 0 END) AS '%s'", i, kid, i, kid)
fields = append(fields, str)
}
}
fieldsSql := strings.Join(fields, ",")
// 查询数据
if query.SortField == "" {
query.SortField = "timeGroup"
}
if query.SortOrder == "" {
query.SortOrder = "desc"
}
orderSql := fmt.Sprintf(" order by %s %s", query.SortField, query.SortOrder)
querySql := fmt.Sprintf("SELECT %s FROM %s gk %s GROUP BY timeGroup %s", fieldsSql, tableName, whereSql, orderSql)
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
return results
}
// SelectGoldKPITitle 网元对应的指标名称
func (r *PerfKPIImpl) SelectGoldKPITitle(neType string) []model.GoldKPITitle {
result := []model.GoldKPITitle{}
@@ -131,3 +233,39 @@ func (r *PerfKPIImpl) SelectUPFTotalFlow(neType, rmUID, startDate, endDate strin
}
return results[0]
}
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
func (r *PerfKPIImpl) SelectUPFThroughput(neType, rmUID, startDate, endDate string) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if neType != "" {
conditions = append(conditions, "gk.ne_type = ?")
params = append(params, neType)
}
if rmUID != "" {
conditions = append(conditions, "gk.rm_uid = ?")
params = append(params, rmUID)
}
if startDate != "" {
conditions = append(conditions, "gk.date >= ?")
params = append(params, startDate)
}
if endDate != "" {
conditions = append(conditions, "gk.date <= ?")
params = append(params, endDate)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
// 查询数据
querySql := fmt.Sprintf("SELECT sum( CASE WHEN JSON_EXTRACT(gk.kpi_values, '$[2].kpi_id') = 'UPF.03' THEN JSON_EXTRACT(gk.kpi_values, '$[2].value') ELSE 0 END ) AS 'up', sum( CASE WHEN JSON_EXTRACT(gk.kpi_values, '$[5].kpi_id') = 'UPF.06' THEN JSON_EXTRACT(gk.kpi_values, '$[5].value') ELSE 0 END ) AS 'down' FROM kpi_report_upf gk %s", whereSql)
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
return results[0]
}

View File

@@ -0,0 +1,26 @@
package repository
import (
"nms_cxy/src/modules/network_data/model"
)
// UDM鉴权信息 数据层接口
type IUDMAuth interface {
// ClearAndInsert 清空ne_id后新增实体
ClearAndInsert(neId string, uArr []model.UDMAuth) int64
// SelectPage 根据条件分页查询
SelectPage(query map[string]any) map[string]any
// SelectList 根据实体查询
SelectList(u model.UDMAuth) []model.UDMAuth
// Insert 批量添加
Inserts(uArr []model.UDMAuth) int64
// Delete 删除实体
Delete(neId, imsi string) int64
// DeletePrefixByIMSI 删除前缀匹配的实体
DeletePrefixByIMSI(neId, imsi string) int64
}

View File

@@ -1,13 +1,14 @@
package repository
import (
"fmt"
"strings"
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_data/model"
)
// 实例化数据层 UDMAuthImpl 结构体
@@ -16,13 +17,13 @@ var NewUDMAuthImpl = &UDMAuthImpl{
resultMap: map[string]string{
"id": "ID",
"imsi": "Imsi",
"imsi": "IMSI",
"amf": "Amf",
"status": "Status",
"ki": "Ki",
"algo_index": "AlgoIndex",
"opc": "Opc",
"ne_id": "NeID",
"ne_id": "NeId",
},
}
@@ -50,14 +51,13 @@ func (r *UDMAuthImpl) convertResultRows(rows []map[string]any) []model.UDMAuth {
}
// ClearAndInsert 清空ne_id后新增实体
func (r *UDMAuthImpl) ClearAndInsert(neID string, authArr []model.UDMAuth) int64 {
// 清空指定ne_id
func (r *UDMAuthImpl) ClearAndInsert(neId string, uArr []model.UDMAuth) int64 {
// 指定neID时用 TRUNCATE 清空表快
_, err := datasource.ExecDB("", "TRUNCATE TABLE u_auth_user", nil)
if err != nil {
logger.Errorf("TRUNCATE err => %v", err)
}
return r.Inserts(authArr)
return r.Inserts(uArr)
}
// SelectPage 根据条件分页查询
@@ -106,11 +106,9 @@ func (r *UDMAuthImpl) SelectPage(query map[string]any) map[string]any {
params = append(params, pageSize)
// 排序
sortSql := ""
orderSql := ""
if v, ok := query["sortField"]; ok && v != "" {
if v == "imsi" {
sortSql += " order by imsi "
}
sortSql := v.(string)
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
if o == "desc" {
sortSql += " desc "
@@ -118,10 +116,11 @@ func (r *UDMAuthImpl) SelectPage(query map[string]any) map[string]any {
sortSql += " asc "
}
}
orderSql = fmt.Sprintf(" order by %s ", sortSql)
}
// 查询数据
querySql := r.selectSql + whereSql + sortSql + pageSql
querySql := r.selectSql + whereSql + orderSql + pageSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
@@ -133,17 +132,17 @@ func (r *UDMAuthImpl) SelectPage(query map[string]any) map[string]any {
}
// SelectList 根据实体查询
func (r *UDMAuthImpl) SelectList(auth model.UDMAuth) []model.UDMAuth {
func (r *UDMAuthImpl) SelectList(u model.UDMAuth) []model.UDMAuth {
// 查询条件拼接
var conditions []string
var params []any
if auth.Imsi != "" {
if u.IMSI != "" {
conditions = append(conditions, "imsi = ?")
params = append(params, auth.Imsi)
params = append(params, u.IMSI)
}
if auth.NeID != "" {
if u.NeId != "" {
conditions = append(conditions, "ne_id = ?")
params = append(params, auth.NeID)
params = append(params, u.NeId)
}
// 构建查询条件语句
@@ -164,8 +163,8 @@ func (r *UDMAuthImpl) SelectList(auth model.UDMAuth) []model.UDMAuth {
}
// Insert 批量添加
func (r *UDMAuthImpl) Inserts(authUsers []model.UDMAuth) int64 {
tx := datasource.DefaultDB().CreateInBatches(authUsers, 3000)
func (r *UDMAuthImpl) Inserts(uArr []model.UDMAuth) int64 {
tx := datasource.DefaultDB().CreateInBatches(uArr, 3000)
if err := tx.Error; err != nil {
logger.Errorf("CreateInBatches err => %v", err)
}
@@ -173,19 +172,19 @@ func (r *UDMAuthImpl) Inserts(authUsers []model.UDMAuth) int64 {
}
// Delete 删除实体
func (r *UDMAuthImpl) Delete(neID, imsi string) int64 {
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neID).Delete(&model.UDMAuth{})
func (r *UDMAuthImpl) Delete(neId, imsi string) int64 {
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neId).Delete(&model.UDMAuth{})
if err := tx.Error; err != nil {
logger.Errorf("Delete err => %v", err)
}
return tx.RowsAffected
}
// DeletePrefixImsi 删除前缀匹配的实体
func (r *UDMAuthImpl) DeletePrefixImsi(neID, imsi string) int64 {
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsi, neID).Delete(&model.UDMAuth{})
// DeletePrefixByIMSI 删除前缀匹配的实体
func (r *UDMAuthImpl) DeletePrefixByIMSI(neId, imsi string) int64 {
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsi, neId).Delete(&model.UDMAuth{})
if err := tx.Error; err != nil {
logger.Errorf("DeletePrefixImsi err => %v", err)
logger.Errorf("DeletePrefixByIMSI err => %v", err)
}
return tx.RowsAffected
}

View File

@@ -0,0 +1,26 @@
package repository
import (
"nms_cxy/src/modules/network_data/model"
)
// UDM签约信息 数据层接口
type IUDMSub interface {
// ClearAndInsert 清空ne_id后新增实体
ClearAndInsert(neId string, uArr []model.UDMSub) int64
// SelectPage 根据条件分页查询
SelectPage(query map[string]any) map[string]any
// SelectList 根据实体查询
SelectList(u model.UDMSub) []model.UDMSub
// Insert 批量添加
Inserts(uArr []model.UDMSub) int64
// Delete 删除实体
Delete(neId, imsi string) int64
// DeletePrefixByIMSI 删除前缀匹配的实体
DeletePrefixByIMSI(neId, imsi string) int64
}

View File

@@ -1,14 +1,14 @@
package repository
import (
"strconv"
"fmt"
"strings"
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_data/model"
)
// 实例化数据层 UDMSubImpl 结构体
@@ -20,7 +20,7 @@ var NewUDMSubImpl = &UDMSubImpl{
resultMap: map[string]string{
"id": "ID",
"msisdn": "Msisdn",
"imsi": "Imsi",
"imsi": "IMSI",
"ambr": "Ambr",
"nssai": "Nssai",
"rat": "Rat",
@@ -30,7 +30,7 @@ var NewUDMSubImpl = &UDMSubImpl{
"sm_data": "SmData",
"smf_sel": "SmfSel",
"eps_dat": "EpsDat",
"ne_id": "NeID",
"ne_id": "NeId",
"eps_flag": "EpsFlag",
"eps_odb": "EpsOdb",
"hplmn_odb": "HplmnOdb",
@@ -66,14 +66,14 @@ func (r *UDMSubImpl) convertResultRows(rows []map[string]any) []model.UDMSub {
}
// ClearAndInsert 清空ne_id后新增实体
func (r *UDMSubImpl) ClearAndInsert(neID string, subArr []model.UDMSub) int64 {
// 清空指定ne_id
func (r *UDMSubImpl) ClearAndInsert(neID string, u []model.UDMSub) int64 {
// 指定neID时用 TRUNCATE 清空表快
_, err := datasource.ExecDB("", "TRUNCATE TABLE u_sub_user", nil)
if err != nil {
logger.Errorf("TRUNCATE err => %v", err)
}
return r.Inserts(subArr)
return r.Inserts(u)
}
// SelectPage 根据条件分页查询字典类型
@@ -126,14 +126,9 @@ func (r *UDMSubImpl) SelectPage(query map[string]any) map[string]any {
params = append(params, pageSize)
// 排序
sortSql := ""
orderSql := ""
if v, ok := query["sortField"]; ok && v != "" {
if v == "imsi" {
sortSql += " order by imsi "
}
if v == "msisdn" {
sortSql += " order by msisdn "
}
sortSql := v.(string)
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
if o == "desc" {
sortSql += " desc "
@@ -141,10 +136,11 @@ func (r *UDMSubImpl) SelectPage(query map[string]any) map[string]any {
sortSql += " asc "
}
}
orderSql = fmt.Sprintf(" order by %s ", sortSql)
}
// 查询数据
querySql := r.selectSql + whereSql + sortSql + pageSql
querySql := r.selectSql + whereSql + orderSql + pageSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
@@ -157,17 +153,17 @@ func (r *UDMSubImpl) SelectPage(query map[string]any) map[string]any {
}
// SelectList 根据实体查询
func (r *UDMSubImpl) SelectList(subUser model.UDMSub) []model.UDMSub {
func (r *UDMSubImpl) SelectList(u model.UDMSub) []model.UDMSub {
// 查询条件拼接
var conditions []string
var params []any
if subUser.Imsi != "" {
if u.IMSI != "" {
conditions = append(conditions, "imsi = ?")
params = append(params, subUser.Imsi)
params = append(params, u.IMSI)
}
if subUser.NeID != "" {
if u.NeId != "" {
conditions = append(conditions, "ne_id = ?")
params = append(params, subUser.NeID)
params = append(params, u.NeId)
}
// 构建查询条件语句
@@ -187,126 +183,29 @@ func (r *UDMSubImpl) SelectList(subUser model.UDMSub) []model.UDMSub {
return r.convertResultRows(results)
}
// Insert 新增实体
func (r *UDMSubImpl) Insert(subUser model.UDMSub) string {
err := datasource.DefaultDB().Create(&subUser).Error
if err != nil {
logger.Errorf("Create err => %v", err)
}
return subUser.ID
}
// Insert 批量添加
func (r *UDMSubImpl) Inserts(subUser []model.UDMSub) int64 {
tx := datasource.DefaultDB().CreateInBatches(subUser, 2000)
func (r *UDMSubImpl) Inserts(uArr []model.UDMSub) int64 {
tx := datasource.DefaultDB().CreateInBatches(uArr, 2000)
if err := tx.Error; err != nil {
logger.Errorf("CreateInBatches err => %v", err)
}
return tx.RowsAffected
}
// Update 修改更新
func (r *UDMSubImpl) Update(neID string, subUser model.UDMSub) int64 {
// 查询先
var user model.UDMSub
err := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", subUser.Imsi, neID).First(&user).Error
if err != nil {
logger.Errorf("Update First err => %v", err)
}
if user.Msisdn != subUser.Msisdn {
user.Msisdn = subUser.Msisdn
}
if user.Ambr != subUser.Ambr {
user.Ambr = subUser.Ambr
}
if user.Arfb != subUser.Arfb {
user.Arfb = subUser.Arfb
}
if user.Sar != subUser.Sar {
user.Sar = subUser.Sar
}
if user.Rat != subUser.Rat {
user.Rat = subUser.Rat
}
if user.Cn != subUser.Cn {
user.Cn = subUser.Cn
}
if user.SmfSel != subUser.SmfSel {
user.SmfSel = subUser.SmfSel
}
if user.SmData != subUser.SmData {
user.SmData = subUser.SmData
}
if user.EpsDat != subUser.EpsDat {
user.EpsDat = subUser.EpsDat
}
if user.EpsFlag != subUser.EpsFlag {
user.EpsFlag = subUser.EpsFlag
}
if user.EpsDat != subUser.EpsDat {
user.EpsOdb = subUser.EpsOdb
}
if user.HplmnOdb != subUser.HplmnOdb {
user.HplmnOdb = subUser.HplmnOdb
}
if user.Epstpl != subUser.Epstpl {
user.Epstpl = subUser.Epstpl
}
if user.Ard != subUser.Ard {
user.Ard = subUser.Ard
}
if user.ContextId != subUser.ContextId {
user.ContextId = subUser.ContextId
}
if user.ApnContext != subUser.ApnContext {
user.ApnContext = subUser.ApnContext
}
if user.StaticIp != subUser.StaticIp {
user.StaticIp = subUser.StaticIp
}
tx := datasource.DefaultDB().Save(user)
if err := tx.Error; err != nil {
logger.Errorf("Update Save err => %v", err)
return 0
}
return tx.RowsAffected
}
// Delete 删除实体
func (r *UDMSubImpl) Delete(neID, imsi string) int64 {
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neID).Delete(&model.UDMSub{})
func (r *UDMSubImpl) Delete(neId, imsi string) int64 {
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neId).Delete(&model.UDMSub{})
if err := tx.Error; err != nil {
logger.Errorf("Delete err => %v", err)
}
return tx.RowsAffected
}
// DeletePrefixImsi 删除前缀匹配的实体
func (r *UDMSubImpl) DeletePrefixImsi(neID, imsi string) int64 {
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsi, neID).Delete(&model.UDMSub{})
// DeletePrefixByIMSI 删除前缀匹配的实体
func (r *UDMSubImpl) DeletePrefixByIMSI(neId, imsi string) int64 {
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsi, neId).Delete(&model.UDMSub{})
if err := tx.Error; err != nil {
logger.Errorf("DeletePrefixImsi err => %v", err)
}
return tx.RowsAffected
}
// Delete 删除范围实体
func (r *UDMSubImpl) Deletes(neID, imsi, num string) int64 {
imsiV, err := strconv.Atoi(imsi)
if err != nil {
return 0
}
numV, err := strconv.Atoi(num)
if err != nil {
return 0
}
tx := datasource.DefaultDB().Where("imsi >= ? and imsi < ? and ne_id = ?", imsiV, imsiV+numV, neID).Delete(&model.UDMSub{})
if err := tx.Error; err != nil {
logger.Errorf("Deletes err => %v", err)
logger.Errorf("DeletePrefixByIMSI err => %v", err)
}
return tx.RowsAffected
}

View File

@@ -2,13 +2,13 @@ package repository
import "nms_cxy/src/modules/network_data/model"
// UE会话事件 数据层接口
type IUEEvent interface {
// UE会话事件AMF 数据层接口
type IUEEventAMF interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.UEEventQuery) map[string]any
SelectPage(querys model.UEEventAMFQuery) map[string]any
// SelectByIds 通过ID查询
SelectByIds(ueIds []string) []model.UEEvent
SelectByIds(ueIds []string) []model.UEEventAMF
// DeleteByIds 批量删除信息
DeleteByIds(ueIds []string) int64

View File

@@ -6,15 +6,14 @@ import (
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/date"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/network_data/model"
)
// 实例化数据层 UEEventImpl 结构体
var NewUEEventImpl = &UEEventImpl{
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, event_type, event_json, created_at from ue_event`,
// 实例化数据层 UEEventAMFImpl 结构体
var NewUEEventAMFImpl = &UEEventAMFImpl{
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, event_type, event_json, created_at from ue_event_amf`,
resultMap: map[string]string{
"id": "ID",
@@ -28,8 +27,8 @@ var NewUEEventImpl = &UEEventImpl{
},
}
// UEEventImpl UE会话事件 数据层处理
type UEEventImpl struct {
// UEEventAMFImpl UE会话事件 数据层处理
type UEEventAMFImpl struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
@@ -37,10 +36,10 @@ type UEEventImpl struct {
}
// convertResultRows 将结果记录转实体结果组
func (r *UEEventImpl) convertResultRows(rows []map[string]any) []model.UEEvent {
arr := make([]model.UEEvent, 0)
func (r *UEEventAMFImpl) convertResultRows(rows []map[string]any) []model.UEEventAMF {
arr := make([]model.UEEventAMF, 0)
for _, row := range rows {
item := model.UEEvent{}
item := model.UEEventAMF{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
repo.SetFieldValue(&item, keyMapper, value)
@@ -52,7 +51,7 @@ func (r *UEEventImpl) convertResultRows(rows []map[string]any) []model.UEEvent {
}
// SelectPage 根据条件分页查询
func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
func (r *UEEventAMFImpl) SelectPage(querys model.UEEventAMFQuery) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
@@ -66,13 +65,17 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
}
if querys.StartTime != "" {
conditions = append(conditions, "timestamp >= ?")
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
params = append(params, beginDate.Unix())
if len(querys.StartTime) == 13 {
querys.StartTime = querys.StartTime[:10]
}
params = append(params, querys.StartTime)
}
if querys.EndTime != "" {
conditions = append(conditions, "timestamp <= ?")
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
params = append(params, endDate.Unix())
if len(querys.EndTime) == 13 {
querys.EndTime = querys.EndTime[:10]
}
params = append(params, querys.EndTime)
}
if querys.EventType != "" {
eventTypes := strings.Split(querys.EventType, ",")
@@ -82,6 +85,10 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
params = append(params, eventType)
}
}
if querys.IMSI != "" {
conditions = append(conditions, "JSON_EXTRACT(event_json, '$.imsi') = ?")
params = append(params, querys.IMSI)
}
// 构建查询条件语句
whereSql := ""
@@ -91,11 +98,11 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
result := map[string]any{
"total": 0,
"rows": []model.CDREvent{},
"rows": []model.UEEventAMF{},
}
// 查询数量 长度为0直接返回
totalSql := "select count(1) as 'total' from ue_event"
totalSql := "select count(1) as 'total' from ue_event_amf"
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
if err != nil {
logger.Errorf("total err => %v", err)
@@ -141,23 +148,23 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
}
// SelectByIds 通过ID查询
func (r *UEEventImpl) SelectByIds(ueIds []string) []model.UEEvent {
func (r *UEEventAMFImpl) SelectByIds(ueIds []string) []model.UEEventAMF {
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
querySql := r.selectSql + " where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(ueIds)
results, err := datasource.RawDB("", querySql, parameters)
if err != nil {
logger.Errorf("query err => %v", err)
return []model.UEEvent{}
return []model.UEEventAMF{}
}
// 转换实体
return r.convertResultRows(results)
}
// DeleteByIds 批量删除信息
func (r *UEEventImpl) DeleteByIds(ueIds []string) int64 {
func (r *UEEventAMFImpl) DeleteByIds(ueIds []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
sql := "delete from ue_event where id in (" + placeholder + ")"
sql := "delete from ue_event_amf where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(ueIds)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {

View File

@@ -0,0 +1,15 @@
package repository
import "nms_cxy/src/modules/network_data/model"
// UE会话事件MME 数据层接口
type IUEEventMME interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.UEEventMMEQuery) map[string]any
// SelectByIds 通过ID查询
SelectByIds(ueIds []string) []model.UEEventMME
// DeleteByIds 批量删除信息
DeleteByIds(ueIds []string) int64
}

View File

@@ -0,0 +1,175 @@
package repository
import (
"fmt"
"strings"
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/network_data/model"
)
// 实例化数据层 UEEventMMEImpl 结构体
var NewUEEventMMEImpl = &UEEventMMEImpl{
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, event_type, event_json, created_at from ue_event_mme`,
resultMap: map[string]string{
"id": "ID",
"ne_type": "NeType",
"ne_name": "NeName",
"rm_uid": "RmUID",
"timestamp": "Timestamp",
"event_type": "EventType",
"event_json": "EventJSONStr",
"created_at": "CreatedAt",
},
}
// UEEventMMEImpl UE会话事件 数据层处理
type UEEventMMEImpl struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
resultMap map[string]string
}
// convertResultRows 将结果记录转实体结果组
func (r *UEEventMMEImpl) convertResultRows(rows []map[string]any) []model.UEEventMME {
arr := make([]model.UEEventMME, 0)
for _, row := range rows {
item := model.UEEventMME{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
repo.SetFieldValue(&item, keyMapper, value)
}
}
arr = append(arr, item)
}
return arr
}
// SelectPage 根据条件分页查询
func (r *UEEventMMEImpl) SelectPage(querys model.UEEventMMEQuery) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if querys.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, querys.NeType)
}
if querys.RmUID != "" {
conditions = append(conditions, "rm_uid = ?")
params = append(params, querys.RmUID)
}
if querys.StartTime != "" {
conditions = append(conditions, "timestamp >= ?")
if len(querys.StartTime) == 13 {
querys.StartTime = querys.StartTime[:10]
}
params = append(params, querys.StartTime)
}
if querys.EndTime != "" {
conditions = append(conditions, "timestamp <= ?")
if len(querys.EndTime) == 13 {
querys.EndTime = querys.EndTime[:10]
}
params = append(params, querys.EndTime)
}
if querys.EventType != "" {
eventTypes := strings.Split(querys.EventType, ",")
placeholder := repo.KeyPlaceholderByQuery(len(eventTypes))
conditions = append(conditions, fmt.Sprintf("event_type in (%s)", placeholder))
for _, eventType := range eventTypes {
params = append(params, eventType)
}
}
if querys.IMSI != "" {
conditions = append(conditions, "JSON_EXTRACT(event_json, '$.imsi') = ?")
params = append(params, querys.IMSI)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
result := map[string]any{
"total": 0,
"rows": []model.UEEventMME{},
}
// 查询数量 长度为0直接返回
totalSql := "select count(1) as 'total' from ue_event_mme"
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
if err != nil {
logger.Errorf("total err => %v", err)
return result
}
total := parse.Number(totalRows[0]["total"])
if total == 0 {
return result
} else {
result["total"] = total
}
// 分页
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
pageSql := " limit ?,? "
params = append(params, pageNum*pageSize)
params = append(params, pageSize)
// 排序
orderSql := ""
if querys.SortField != "" {
sortSql := querys.SortField
if querys.SortOrder != "" {
if querys.SortOrder == "desc" {
sortSql += " desc "
} else {
sortSql += " asc "
}
}
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
}
// 查询数据
querySql := r.selectSql + whereSql + orderSql + pageSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
// 转换实体
result["rows"] = r.convertResultRows(results)
return result
}
// SelectByIds 通过ID查询
func (r *UEEventMMEImpl) SelectByIds(ueIds []string) []model.UEEventMME {
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
querySql := r.selectSql + " where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(ueIds)
results, err := datasource.RawDB("", querySql, parameters)
if err != nil {
logger.Errorf("query err => %v", err)
return []model.UEEventMME{}
}
// 转换实体
return r.convertResultRows(results)
}
// DeleteByIds 批量删除信息
func (r *UEEventMMEImpl) DeleteByIds(ueIds []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
sql := "delete from ue_event_mme where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(ueIds)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {
logger.Errorf("delete err => %v", err)
return 0
}
return results
}

View File

@@ -2,10 +2,10 @@ package service
import "nms_cxy/src/modules/network_data/model"
// CDR会话事件 服务层接口
type ICDREvent interface {
// CDR会话事件IMS 服务层接口
type ICDREventIMS interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.CDREventQuery) map[string]any
SelectPage(querys model.CDREventIMSQuery) map[string]any
// DeleteByIds 批量删除信息
DeleteByIds(cdrIds []string) (int64, error)

View File

@@ -0,0 +1,40 @@
package service
import (
"fmt"
"nms_cxy/src/modules/network_data/model"
"nms_cxy/src/modules/network_data/repository"
)
// 实例化数据层 NewCDREventIMSImpl 结构体
var NewCDREventIMSImpl = &CDREventIMSImpl{
cdrEventIMSRepository: repository.NewCDREventIMSImpl,
}
// CDREventImpl CDR会话事件IMS 服务层处理
type CDREventIMSImpl struct {
// CDR会话事件数据信息
cdrEventIMSRepository repository.ICDREventIMS
}
// SelectPage 根据条件分页查询
func (r *CDREventIMSImpl) SelectPage(querys model.CDREventIMSQuery) map[string]any {
return r.cdrEventIMSRepository.SelectPage(querys)
}
// DeleteByIds 批量删除信息
func (r *CDREventIMSImpl) DeleteByIds(cdrIds []string) (int64, error) {
// 检查是否存在
ids := r.cdrEventIMSRepository.SelectByIds(cdrIds)
if len(ids) <= 0 {
return 0, fmt.Errorf("not data")
}
if len(ids) == len(cdrIds) {
rows := r.cdrEventIMSRepository.DeleteByIds(cdrIds)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}

View File

@@ -0,0 +1,12 @@
package service
import "nms_cxy/src/modules/network_data/model"
// CDR会话事件SMF 服务层接口
type ICDREventSMF interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.CDREventSMFQuery) map[string]any
// DeleteByIds 批量删除信息
DeleteByIds(cdrIds []string) (int64, error)
}

View File

@@ -7,24 +7,21 @@ import (
"nms_cxy/src/modules/network_data/repository"
)
// 实例化数据层 CDREventImpl 结构体
var NewCDREventImpl = &CDREventImpl{
cdrEventRepository: repository.NewCDREventImpl,
var NewCDREventSMFImpl = &CDREventSMFImpl{
cdrEventRepository: repository.NewCDREventSMFImpl,
}
// CDREventImpl CDR会话事件 服务层处理
type CDREventImpl struct {
type CDREventSMFImpl struct {
// CDR会话事件数据信息
cdrEventRepository repository.ICDREvent
cdrEventRepository repository.ICDREventSMF
}
// SelectPage 根据条件分页查询
func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
func (r *CDREventSMFImpl) SelectPage(querys model.CDREventSMFQuery) map[string]any {
return r.cdrEventRepository.SelectPage(querys)
}
// DeleteByIds 批量删除信息
func (r *CDREventImpl) DeleteByIds(cdrIds []string) (int64, error) {
func (r *CDREventSMFImpl) DeleteByIds(cdrIds []string) (int64, error) {
// 检查是否存在
ids := r.cdrEventRepository.SelectByIds(cdrIds)
if len(ids) <= 0 {

View File

@@ -31,7 +31,8 @@ func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery) []map[string]any {
kpiIds = append(kpiIds, kpiId.KPIID)
}
data := r.perfKPIRepository.SelectGoldKPI(query, kpiIds)
//data := r.perfKPIRepository.SelectGoldKPI(query, kpiIds)
data := r.perfKPIRepository.SelectKpiReport(query, kpiIds)
if data == nil {
return []map[string]any{}
}
@@ -66,7 +67,8 @@ func (r *PerfKPIImpl) SelectUPFTotalFlow(neType, rmUID string, day int) map[stri
}
}
info = r.perfKPIRepository.SelectUPFTotalFlow(neType, rmUID, startDate, endDate)
//info = r.perfKPIRepository.SelectUPFTotalFlow(neType, rmUID, startDate, endDate)
info = r.perfKPIRepository.SelectUPFThroughput(neType, rmUID, startDate, endDate)
// 保存到缓存
infoJSON, _ := json.Marshal(info)

View File

@@ -0,0 +1,28 @@
package service
import "nms_cxy/src/modules/network_data/model"
// UDM鉴权信息 服务层接口
type IUDMAuth interface {
// ResetData 重置鉴权用户数据清空数据库重新同步Redis数据
ResetData(neId string) int64
// SelectPage 分页查询数据库
SelectPage(query map[string]any) map[string]any
// SelectList 查询数据库
SelectList(u model.UDMAuth) []model.UDMAuth
// Insert 从数据中读取后删除imsi再存入数据库
// imsi长度15ki长度32opc长度0或者32
Insert(neId string, u model.UDMAuth) int64
// InsertData 导入文件数据 dataType目前两种txt/csv
InsertData(neId, dataType string, data any) int64
// Delete 删除单个不重新加载
Delete(neID, imsi string) int64
// LoadData 删除范围后重新加载 num表示imsi后几位
LoadData(neID, imsi, num string) int64
}

View File

@@ -0,0 +1,146 @@
package service
import (
"fmt"
"strings"
"nms_cxy/src/framework/redis"
"nms_cxy/src/modules/network_data/model"
"nms_cxy/src/modules/network_data/repository"
)
// 实例化服务层 UDMAuthImpl 结构体
var NewUDMAuthImpl = &UDMAuthImpl{
udmAuthRepository: repository.NewUDMAuthImpl,
}
// UDM鉴权信息 服务层处理
type UDMAuthImpl struct {
// UDM鉴权信息数据信息
udmAuthRepository repository.IUDMAuth
}
// dataByRedis UDM鉴权用户 db:0 中 ausf:*
func (r *UDMAuthImpl) dataByRedis(imsi, neId string) []model.UDMAuth {
arr := []model.UDMAuth{}
key := fmt.Sprintf("ausf:%s", imsi)
ausfArr, err := redis.GetKeys("udmuser", key)
if err != nil {
return arr
}
for _, key := range ausfArr {
m, err := redis.GetHash("udmuser", key)
if err != nil {
continue
}
// 跳过-号数据
imsi := key[5:]
if strings.Contains(imsi, "-") {
continue
}
amf := ""
if v, ok := m["amf"]; ok {
amf = strings.Replace(v, "\r\n", "", 1)
}
a := model.UDMAuth{
IMSI: imsi,
Amf: amf,
Status: "1", // 默认给1
Ki: m["ki"],
AlgoIndex: m["algo"],
Opc: m["opc"],
NeId: neId,
}
arr = append(arr, a)
}
return arr
}
// ResetData 重置鉴权用户数据清空数据库重新同步Redis数据
func (r *UDMAuthImpl) ResetData(neId string) int64 {
authArr := r.dataByRedis("*", neId)
// 数据清空后添加
go r.udmAuthRepository.ClearAndInsert(neId, authArr)
return int64(len(authArr))
}
// SelectPage 分页查询数据库
func (r *UDMAuthImpl) SelectPage(query map[string]any) map[string]any {
return r.udmAuthRepository.SelectPage(query)
}
// SelectList 查询数据库
func (r *UDMAuthImpl) SelectList(u model.UDMAuth) []model.UDMAuth {
return r.udmAuthRepository.SelectList(u)
}
// Insert 从数据中读取后删除imsi再存入数据库
// imsi长度15ki长度32opc长度0或者32
func (r *UDMAuthImpl) Insert(neId string, u model.UDMAuth) int64 {
uArr := r.dataByRedis(u.IMSI, neId)
if len(uArr) > 0 {
r.udmAuthRepository.Delete(neId, u.IMSI)
return r.udmAuthRepository.Inserts(uArr)
}
return 0
}
// InsertData 导入文件数据 dataType目前两种txt/csv
func (r *UDMAuthImpl) InsertData(neId, dataType string, data any) int64 {
// imsi截取前缀,重新获取部分数据
prefixes := make(map[string]struct{})
if dataType == "csv" {
for _, v := range data.([]map[string]string) {
imsi := v["imsi"]
if len(imsi) < 6 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
}
if dataType == "txt" {
for _, v := range data.([][]string) {
imsi := v[0]
if len(imsi) < 6 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
}
// 根据前缀重新加载插入
var num int64 = 0
for prefix := range prefixes {
// 直接删除前缀的记录
r.udmAuthRepository.DeletePrefixByIMSI(neId, prefix)
// keys ausf:4600001000004*
authArr := r.dataByRedis(prefix+"*", neId)
if len(authArr) > 0 {
num += r.udmAuthRepository.Inserts(authArr)
}
}
return num
}
// Delete 删除单个不重新加载
func (r *UDMAuthImpl) Delete(neId, imsi string) int64 {
return r.udmAuthRepository.Delete(neId, imsi)
}
// LoadData 删除范围后重新加载 num表示imsi后几位
func (r *UDMAuthImpl) LoadData(neId, imsi, num string) int64 {
prefix := imsi[:len(imsi)-len(num)-1]
// 直接删除前缀的记录
delNum := r.udmAuthRepository.DeletePrefixByIMSI(neId, prefix)
// keys ausf:4600001000004*
authArr := r.dataByRedis(prefix+"*", neId)
if len(authArr) > 0 {
return r.udmAuthRepository.Inserts(authArr)
}
return delNum
}

View File

@@ -0,0 +1,28 @@
package service
import "nms_cxy/src/modules/network_data/model"
// UDM签约用户信息 服务层接口
type IUDMSub interface {
// ResetData 重置鉴权用户数据清空数据库重新同步Redis数据
ResetData(neId string) int64
// SelectPage 分页查询数据库
SelectPage(query map[string]any) map[string]any
// SelectList 查询数据库
SelectList(u model.UDMSub) []model.UDMSub
// Insert 从数据中读取后删除imsi再存入数据库
// imsi长度15ki长度32opc长度0或者32
Insert(neId string, u model.UDMSub) int64
// InsertData 导入文件数据 dataType目前两种txt/csv
InsertData(neId, dataType string, data any) int64
// Delete 删除单个不重新加载
Delete(neId, imsi string) int64
// LoadData 删除范围后重新加载 num表示imsi后几位
LoadData(neId, imsi, num string) int64
}

View File

@@ -0,0 +1,164 @@
package service
import (
"fmt"
"strings"
"nms_cxy/src/framework/redis"
"nms_cxy/src/modules/network_data/model"
"nms_cxy/src/modules/network_data/repository"
)
// 实例化服务层 UDMSubImpl 结构体
var NewUDMSubImpl = &UDMSubImpl{
udmSubRepository: repository.NewUDMSubImpl,
}
// UDM签约信息 服务层处理
type UDMSubImpl struct {
// UDM签约信息数据信息
udmSubRepository repository.IUDMSub
}
// dataByRedis UDM签约用户 db:0 中 udm-sd:*
func (r *UDMSubImpl) dataByRedis(imsi, neId string) []model.UDMSub {
arr := []model.UDMSub{}
key := fmt.Sprintf("udm-sd:%s", imsi)
udmsdArr, err := redis.GetKeys("udmuser", key)
if err != nil {
return arr
}
for _, key := range udmsdArr {
m, err := redis.GetHash("udmuser", key)
if err != nil {
continue
}
a := model.UDMSub{
IMSI: key[7:],
Msisdn: m["gpsi"], // 46003550072
SmfSel: m["smf-sel"],
SmData: m["sm-dat"], // 1-000001&cmnet&ims&3gnet
NeId: neId,
}
// def_ambr,def_nssai,0,def_arfb,def_sar,3,1,12000,1,1000,0,1,-
if v, ok := m["am-dat"]; ok {
arr := strings.Split(v, ",")
a.Ambr = arr[0]
a.Nssai = arr[1]
a.Rat = arr[2]
a.Arfb = arr[3]
a.Sar = arr[4]
a.Cn = arr[5]
}
// 1,64,24,65,def_eps,1,2,010200000000,-
if v, ok := m["eps-dat"]; ok {
arr := strings.Split(v, ",")
// 跳过非常规数据
if len(arr) > 9 {
continue
}
a.EpsDat = v
a.EpsFlag = arr[0]
a.EpsOdb = arr[1]
a.HplmnOdb = arr[2]
a.Ard = arr[3]
a.Epstpl = arr[4]
a.ContextId = arr[5]
a.ApnContext = arr[7]
// [6] 是不要的,导入和导出不用
a.StaticIp = arr[8]
}
arr = append(arr, a)
}
return arr
}
// ResetData 重置鉴权用户数据清空数据库重新同步Redis数据
func (r *UDMSubImpl) ResetData(neId string) int64 {
subArr := r.dataByRedis("*", neId)
// 数据清空后添加
go r.udmSubRepository.ClearAndInsert(neId, subArr)
return int64(len(subArr))
}
// SelectPage 分页查询数据库
func (r *UDMSubImpl) SelectPage(query map[string]any) map[string]any {
return r.udmSubRepository.SelectPage(query)
}
// SelectList 查询数据库
func (r *UDMSubImpl) SelectList(u model.UDMSub) []model.UDMSub {
return r.udmSubRepository.SelectList(u)
}
// Insert 从数据中读取后删除imsi再存入数据库
// imsi长度15ki长度32opc长度0或者32
func (r *UDMSubImpl) Insert(neId string, u model.UDMSub) int64 {
uArr := r.dataByRedis(u.IMSI, neId)
if len(uArr) > 0 {
r.udmSubRepository.Delete(neId, u.IMSI)
return r.udmSubRepository.Inserts(uArr)
}
return 0
}
// InsertData 导入文件数据 dataType目前两种txt/csv
func (r *UDMSubImpl) InsertData(neId, dataType string, data any) int64 {
// imsi截取前缀,重新获取部分数据
prefixes := make(map[string]struct{})
if dataType == "csv" {
for _, v := range data.([]map[string]string) {
imsi := v["imsi"]
if len(imsi) < 6 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
}
if dataType == "txt" {
for _, v := range data.([][]string) {
imsi := v[0]
if len(imsi) < 6 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
}
// 根据前缀重新加载插入
var num int64 = 0
for prefix := range prefixes {
// 直接删除前缀的记录
r.udmSubRepository.DeletePrefixByIMSI(neId, prefix)
// keys udm-sd:4600001000004*
subArr := r.dataByRedis(prefix+"*", neId)
if len(subArr) > 0 {
num += r.udmSubRepository.Inserts(subArr)
}
}
return num
}
// Delete 删除单个不重新加载
func (r *UDMSubImpl) Delete(neId, imsi string) int64 {
return r.udmSubRepository.Delete(neId, imsi)
}
// LoadData 删除范围后重新加载 num表示imsi后几位
func (r *UDMSubImpl) LoadData(neId, imsi, num string) int64 {
prefix := imsi[:len(imsi)-len(num)-1]
// 直接删除前缀的记录
delNum := r.udmSubRepository.DeletePrefixByIMSI(neId, prefix)
// keys udm-sd:4600001000004*
authArr := r.dataByRedis(prefix+"*", neId)
if len(authArr) > 0 {
return r.udmSubRepository.Inserts(authArr)
}
return delNum
}

View File

@@ -2,10 +2,10 @@ package service
import "nms_cxy/src/modules/network_data/model"
// UE会话事件 服务层接口
type IUEEvent interface {
// UE会话事件AMF 服务层接口
type IUEEventAMF interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.UEEventQuery) map[string]any
SelectPage(querys model.UEEventAMFQuery) map[string]any
// DeleteByIds 批量删除信息
DeleteByIds(ueIds []string) (int64, error)

View File

@@ -7,24 +7,24 @@ import (
"nms_cxy/src/modules/network_data/repository"
)
// 实例化数据层 UEEventImpl 结构体
var NewUEEventImpl = &UEEventImpl{
ueEventRepository: repository.NewUEEventImpl,
// 实例化数据层 UEEventMMEImpl 结构体
var NewUEEventMMEImpl = &UEEventMMEImpl{
ueEventRepository: repository.NewUEEventMMEImpl,
}
// UEEventImpl UE会话事件 服务层处理
type UEEventImpl struct {
// UEEventMMEImpl UE会话事件MME 服务层处理
type UEEventMMEImpl struct {
// UE会话事件数据信息
ueEventRepository repository.IUEEvent
ueEventRepository repository.IUEEventMME
}
// SelectPage 根据条件分页查询
func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
func (r *UEEventMMEImpl) SelectPage(querys model.UEEventMMEQuery) map[string]any {
return r.ueEventRepository.SelectPage(querys)
}
// DeleteByIds 批量删除信息
func (r *UEEventImpl) DeleteByIds(ueIds []string) (int64, error) {
func (r *UEEventMMEImpl) DeleteByIds(ueIds []string) (int64, error) {
// 检查是否存在
ids := r.ueEventRepository.SelectByIds(ueIds)
if len(ids) <= 0 {

View File

@@ -0,0 +1,12 @@
package service
import "nms_cxy/src/modules/network_data/model"
// UE会话事件MME 服务层接口
type IUEEventMME interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.UEEventMMEQuery) map[string]any
// DeleteByIds 批量删除信息
DeleteByIds(ueIds []string) (int64, error)
}

View File

@@ -0,0 +1,40 @@
package service
import (
"fmt"
"nms_cxy/src/modules/network_data/model"
"nms_cxy/src/modules/network_data/repository"
)
// 实例化数据层 UEEventAMFImpl 结构体
var NewUEEventAMFImpl = &UEEventAMFImpl{
ueEventRepository: repository.NewUEEventAMFImpl,
}
// UEEventAMFImpl UE会话事件AMF 服务层处理
type UEEventAMFImpl struct {
// UE会话事件数据信息
ueEventRepository repository.IUEEventAMF
}
// SelectPage 根据条件分页查询
func (r *UEEventAMFImpl) SelectPage(querys model.UEEventAMFQuery) map[string]any {
return r.ueEventRepository.SelectPage(querys)
}
// DeleteByIds 批量删除信息
func (r *UEEventAMFImpl) DeleteByIds(ueIds []string) (int64, error) {
// 检查是否存在
ids := r.ueEventRepository.SelectByIds(ueIds)
if len(ids) <= 0 {
return 0, fmt.Errorf("no data")
}
if len(ids) == len(ueIds) {
rows := r.ueEventRepository.DeleteByIds(ueIds)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}

View File

@@ -3,6 +3,7 @@ package controller
import (
"fmt"
"path/filepath"
"runtime"
"strings"
"nms_cxy/src/framework/i18n"
@@ -51,19 +52,30 @@ func (s *NeActionController) PushFile(c *gin.Context) {
return
}
// 本地文件
localPath := file.ParseUploadFilePath(body.UploadPath)
nePath := "/tmp" //config.Get("mml.upload").(string)
// 复制到远程
err := ssh.FileSCPLocalToNe(neInfo.IP, localPath, nePath)
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
// 本地文件
localFilePath := file.ParseUploadFilePath(body.UploadPath)
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
// 复制到远程
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
c.JSON(200, result.ErrMsg(fmt.Sprintf("%s : please check if scp remote copy is allowed", neInfo.NeType)))
return
}
// 网元端文件路径
fileName := localPath[strings.LastIndex(localPath, "/")+1:]
neFilePath := fmt.Sprintf("%s/%s", nePath, fileName)
c.JSON(200, result.OkData(filepath.ToSlash(neFilePath)))
}
@@ -90,14 +102,32 @@ func (s *NeActionController) PullFile(c *gin.Context) {
return
}
nePath := fmt.Sprintf("%s/%s", querys.Path, querys.FileName)
localPath := fmt.Sprintf("/tmp/omc/pullFile/%s", querys.FileName)
err := ssh.FileSCPNeToLocal(neInfo.IP, nePath, localPath)
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.FileAttachment(localPath, querys.FileName)
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
nePath := fmt.Sprintf("%s/%s", querys.Path, querys.FileName)
localFilePath := fmt.Sprintf("/tmp/omc/pullFile%s", nePath)
if runtime.GOOS == "windows" {
localFilePath = fmt.Sprintf("C:%s", localFilePath)
}
// 复制到本地
if err = sftpClient.CopyFileRemoteToLocal(nePath, localFilePath); err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.FileAttachment(localFilePath, querys.FileName)
}
// 网元端文件列表
@@ -125,7 +155,16 @@ func (s *NeActionController) Files(c *gin.Context) {
return
}
totalSize, rows, err := ssh.FileList(querys.Path, neInfo.IP, querys.Search)
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 获取文件列表
totalSize, rows, err := ssh.FileList(sshClient, querys.Path, querys.Search)
if err != nil {
c.JSON(200, result.Ok(map[string]any{
"path": querys.Path,
@@ -156,3 +195,52 @@ func (s *NeActionController) Files(c *gin.Context) {
"rows": splitRows,
}))
}
// 网元服务操作
//
// PUT /service
func (s *NeActionController) Service(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"`
NeID string `json:"neId" binding:"required"`
Action string `json:"action" binding:"required,oneof=start restart stop reboot poweroff"` // 操作行为
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeID)
if neInfo.NeId != body.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
neTypeLower := strings.ToLower(neInfo.NeType)
cmdStr := fmt.Sprintf("sudo service %s %s", neTypeLower, body.Action)
if neTypeLower == "omc" {
cmdStr = fmt.Sprintf("nohup sh -c \"sudo systemctl stop restagent && sleep 5s && sudo systemctl %s restagent\" > /dev/null 2>&1 &", body.Action)
} else if neTypeLower == "ims" {
if body.Action == "restart" {
cmdStr = "ims-stop || true && ims-start"
} else {
cmdStr = fmt.Sprintf("sudo ims-%s", body.Action)
}
}
if body.Action == "reboot" {
cmdStr = "sudo shutdown -r now"
}
if body.Action == "poweroff" {
cmdStr = "sudo shutdown -h now"
}
_, err := s.neInfoService.NeRunSSHCmd(body.NeType, body.NeID, cmdStr)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(nil))
}

View File

@@ -0,0 +1,203 @@
package controller
import (
"encoding/json"
"strings"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/vo/result"
neFetchlink "nms_cxy/src/modules/network_element/fetch_link"
"nms_cxy/src/modules/network_element/model"
neService "nms_cxy/src/modules/network_element/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// NewNeConfig 网元参数配置 实例化控制层
var NewNeConfig = &NeConfigController{
neConfigService: neService.NewNeConfigImpl,
neInfoService: neService.NewNeInfoImpl,
}
// 网元参数配置
//
// PATH /config
type NeConfigController struct {
// 网元参数配置可用属性值服务
neConfigService neService.INeConfig
// 网元信息服务
neInfoService neService.INeInfo
}
// 网元参数配置可用属性值列表
//
// GET /list
func (s *NeConfigController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
data := s.neConfigService.SelectPage(querys)
c.JSON(200, result.Ok(data))
}
// 网元参数配置可用属性值信息
//
// GET /info/:id
func (s *NeConfigController) Info(c *gin.Context) {
language := ctx.AcceptLanguage(c)
id := c.Param("id")
if id == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
data := s.neConfigService.SelectById(id)
if data.ID != id {
// 没有可访问参数配置数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neConfig.noData")))
return
}
// 将字符串转json数据
if err := json.Unmarshal([]byte(data.ParamJSONStr), &data.ParamData); err != nil {
c.JSON(400, result.CodeMsg(400, err.Error()))
return
}
c.JSON(200, result.OkData(data))
}
// 网元参数配置可用属性值新增
//
// POST /
func (s *NeConfigController) Add(c *gin.Context) {
language := ctx.AcceptLanguage(c)
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")))
return
}
// 将json数据转字符串存储
paramDataByte, err := json.Marshal(body.ParamData)
if err != nil {
c.JSON(400, result.CodeMsg(400, err.Error()))
return
}
body.ParamJSONStr = string(paramDataByte)
insertId := s.neConfigService.Insert(body)
if insertId != "" {
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
}
// 网元参数配置可用属性值修改
//
// PUT /
func (s *NeConfigController) Edit(c *gin.Context) {
language := ctx.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")))
return
}
// 检查是否存在
data := s.neConfigService.SelectById(body.ID)
if data.ID != body.ID {
// 没有可访问主机命令数据!
c.JSON(200, result.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()))
return
}
body.ParamJSONStr = string(paramDataByte)
rows := s.neConfigService.Update(body)
if rows > 0 {
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
}
// 网元参数配置可用属性值删除
//
// DELETE /:ids
func (s *NeConfigController) Remove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
ids := c.Param("ids")
if ids == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 处理字符转id数组后去重
idsArr := strings.Split(ids, ",")
uniqueIDs := parse.RemoveDuplicates(idsArr)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
rows, err := s.neConfigService.DeleteByIds(uniqueIDs)
if err != nil {
c.JSON(200, result.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))
}
// 网元参数配置可用属性值列表指定网元类型全部无分页
//
// GET /list/:neType
func (s *NeConfigController) ListByNeType(c *gin.Context) {
language := ctx.AcceptLanguage(c)
neType := c.Param("neType")
if neType == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
data := s.neConfigService.SelectNeConfigByNeType(neType)
c.JSON(200, result.OkData(data))
}
// 网元参数配置数据信息
//
// GET /data
func (s *NeConfigController) Data(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"` // 网元类型
NeId string `form:"neId" binding:"required"` // 网元ID
TopTag string `form:"topTag" binding:"required"` // 可用属性
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeId)
if neInfo.NeId != querys.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigInfo(neInfo, querys.TopTag)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(resData))
}

View File

@@ -168,8 +168,7 @@ func (s *NeHostController) Remove(c *gin.Context) {
func (s *NeHostController) Test(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeHost
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil {
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
@@ -177,8 +176,13 @@ func (s *NeHostController) Test(c *gin.Context) {
if body.HostType == "ssh" {
var connSSH ssh.ConnSSH
body.CopyTo(&connSSH)
client, err := connSSH.NewClient()
var client *ssh.ConnSSH
var err error
if body.AuthMode == "2" {
client, err = connSSH.NewClientByLocalPrivate()
} else {
client, err = connSSH.NewClient()
}
if err != nil {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
@@ -200,7 +204,13 @@ func (s *NeHostController) Test(c *gin.Context) {
return
}
defer client.Close()
c.JSON(200, result.Ok(nil))
// 是否有终止符
if strings.HasSuffix(client.LastResult, ">") || strings.HasSuffix(client.LastResult, "> ") || strings.HasSuffix(client.LastResult, "# ") {
c.JSON(200, result.Ok(nil))
} else {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
}
return
}
}
@@ -214,8 +224,7 @@ func (s *NeHostController) Cmd(c *gin.Context) {
HostID string `json:"hostId" binding:"required"` // 主机ID
Cmd string `json:"cmd" binding:"required"` // 执行命令
}
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil {
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
@@ -231,8 +240,13 @@ func (s *NeHostController) Cmd(c *gin.Context) {
if neHost.HostType == "ssh" {
var connSSH ssh.ConnSSH
neHost.CopyTo(&connSSH)
client, err := connSSH.NewClient()
var client *ssh.ConnSSH
var err error
if neHost.AuthMode == "2" {
client, err = connSSH.NewClientByLocalPrivate()
} else {
client, err = connSSH.NewClient()
}
if err != nil {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
@@ -279,17 +293,21 @@ func (s *NeHostController) Cmd(c *gin.Context) {
func (s *NeHostController) CheckBySSH(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeHost
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil {
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
var connSSH ssh.ConnSSH
body.CopyTo(&connSSH)
// 创建链接SSH客户端
client, err := connSSH.NewClient()
var client *ssh.ConnSSH
var err error
if body.AuthMode == "2" {
client, err = connSSH.NewClientByLocalPrivate()
} else {
client, err = connSSH.NewClient()
}
if err != nil {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
@@ -340,6 +358,39 @@ func (s *NeHostController) CheckBySSH(c *gin.Context) {
}
// 本地免密创建链接直连
if body.AuthMode == "2" {
data["sshLink"] = true
} else {
lcoalConnSSH := ssh.ConnSSH{
User: body.User,
Addr: body.Addr,
Port: body.Port,
}
lcoalClient, err := lcoalConnSSH.NewClientByLocalPrivate()
if err == nil {
data["sshLink"] = true
defer lcoalClient.Close()
} else {
data["sshLink"] = false
}
}
c.JSON(200, result.OkData(data))
}
// 网元主机SSH方式授权免密发送
//
// POST /authorizedBySSH
func (s *NeHostController) AuthorizedBySSH(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeHost
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil || body.AuthMode == "2" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 本地免密创建链接直连
sshLink := false
lcoalConnSSH := ssh.ConnSSH{
User: body.User,
Addr: body.Addr,
@@ -347,11 +398,31 @@ func (s *NeHostController) CheckBySSH(c *gin.Context) {
}
lcoalClient, err := lcoalConnSSH.NewClientByLocalPrivate()
if err == nil {
data["sshLink"] = true
} else {
data["sshLink"] = false
sshLink = true
defer lcoalClient.Close()
}
if sshLink {
// 连接主机成功,无需重复免密授权认证
c.JSON(200, result.OkMsg(i18n.TKey(language, "neHost.okBySSHLink")))
return
}
defer lcoalClient.Close()
c.JSON(200, result.OkData(data))
// 创建链接SSH客户端
var connSSH ssh.ConnSSH
body.CopyTo(&connSSH)
client, err := connSSH.NewClient()
if err != nil {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
// 发送密钥
err = client.SendToAuthorizedKeys()
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(nil))
}

View File

@@ -9,6 +9,7 @@ import (
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/vo/result"
neFetchlink "nms_cxy/src/modules/network_element/fetch_link"
"nms_cxy/src/modules/network_element/model"
neService "nms_cxy/src/modules/network_element/service"
@@ -18,15 +19,21 @@ import (
// 实例化控制层 NeInfoController 结构体
var NewNeInfo = &NeInfoController{
neInfoService: neService.NewNeInfoImpl,
neInfoService: neService.NewNeInfoImpl,
neLicenseService: neService.NewNeLicenseImpl,
neVersionService: neService.NewNeVersionImpl,
}
// 网元信息请求
//
// PATH /
// PATH /info
type NeInfoController struct {
// 网元信息服务
neInfoService neService.INeInfo
// 网元授权激活信息服务
neLicenseService neService.INeLicense
// 网元版本信息服务
neVersionService neService.INeVersion
}
// neStateCacheMap 网元状态缓存最后一次成功的信息
@@ -40,22 +47,22 @@ func (s *NeInfoController) State(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeId)
if neInfo.NeId != querys.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
neKey := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId)
// 网元直连
resData, err := neService.NeState(neInfo)
resData, err := neFetchlink.NeState(neInfo)
if err != nil {
mutex.Lock()
// 异常取上次缓存
@@ -85,17 +92,26 @@ func (s *NeInfoController) State(c *gin.Context) {
c.JSON(200, result.OkData(resData))
}
// 网元信息列表
// 网元neType和neID查询
//
// GET /list
func (s *NeInfoController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
bandStatus := false
if v, ok := querys["bandStatus"]; ok && v != nil {
bandStatus = parse.Boolean(v)
// GET /byTypeAndID
func (s *NeInfoController) NeTypeAndID(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
}
data := s.neInfoService.SelectPage(querys, bandStatus)
c.JSON(200, result.Ok(data))
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
c.JSON(200, result.OkData(neInfo))
}
// 网元信息列表全部无分页
@@ -106,7 +122,8 @@ func (s *NeInfoController) ListAll(c *gin.Context) {
var querys struct {
NeType string `form:"neType"`
NeId string `form:"neId"`
BandStatus string `form:"bandStatus"`
BandStatus bool `form:"bandStatus"`
BandHost bool `form:"bandHost"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
@@ -121,8 +138,7 @@ func (s *NeInfoController) ListAll(c *gin.Context) {
if querys.NeId != "" {
ne.NeId = querys.NeId
}
bandStatus := parse.Boolean(querys.BandStatus)
neList := s.neInfoService.SelectList(ne, bandStatus)
neList := s.neInfoService.SelectList(ne, querys.BandStatus, querys.BandHost)
if len(neList) == 0 {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
@@ -130,6 +146,106 @@ func (s *NeInfoController) ListAll(c *gin.Context) {
c.JSON(200, result.OkData(neList))
}
// 网元端Para5G配置文件读取
//
// GET /para5GFile
func (s *NeInfoController) Para5GFileRead(c *gin.Context) {
data, err := s.neInfoService.NeConfPara5GRead()
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(data))
}
// 网元端Para5G配置文件写入
//
// PUT /para5GFile
func (s *NeInfoController) Para5GFileWrite(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
Content map[string]any `json:"content" binding:"required"` // 内容
SyncNE []string `json:"syncNe"` // 同步到网元
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
err := s.neInfoService.NeConfPara5GWirte(body.Content, body.SyncNE)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(nil))
}
// 网元端OAM配置文件读取
//
// GET /oamFile
func (s *NeInfoController) OAMFileRead(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
data, err := s.neInfoService.NeConfOAMRead(querys.NeType, querys.NeID)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(data))
}
// 网元端OAM配置文件写入
//
// PUT /oamFile
func (s *NeInfoController) OAMFileWrite(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"`
NeID string `json:"neId" binding:"required"`
Content map[string]any `json:"content" binding:"required"` // 内容
Sync bool `json:"sync"` // 同步到网元
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeID)
if neInfo.NeId != body.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
err := s.neInfoService.NeConfOAMSync(neInfo, body.Content, body.Sync)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(nil))
}
// 网元信息列表
//
// GET /list
func (s *NeInfoController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
bandStatus := false
if v, ok := querys["bandStatus"]; ok && v != nil {
bandStatus = parse.Boolean(v)
}
data := s.neInfoService.SelectPage(querys, bandStatus)
c.JSON(200, result.Ok(data))
}
// 网元信息
//
// GET /:infoId
@@ -151,28 +267,6 @@ func (s *NeInfoController) Info(c *gin.Context) {
c.JSON(200, result.OkData(neHost))
}
// 网元neType和neID查询
//
// GET /
func (s *NeInfoController) NeTypeAndID(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
c.JSON(200, result.OkData(neInfo))
}
// 网元信息新增
//
// POST /
@@ -195,22 +289,53 @@ func (s *NeInfoController) Add(c *gin.Context) {
}
// 获取网元状态是否正常
_, err = neService.NeState(body)
body.ServerState, err = neFetchlink.NeState(body)
if err != nil {
body.Status = "1"
body.Status = "0"
} else {
// 下发网管配置信息给网元
_, err = neService.NeConfigOMC(body)
_, err = neFetchlink.NeConfigOMC(body)
if err == nil {
body.Status = "0"
body.Status = "1"
} else {
body.Status = "3"
body.Status = "2"
}
}
loginUserName := ctx.LoginUserToUserName(c)
// 新增Version信息
neVersion := model.NeVersion{
NeType: body.NeType,
NeId: body.NeId,
CreateBy: loginUserName,
}
// 新增License信息
neLicense := model.NeLicense{
NeType: body.NeType,
NeId: body.NeId,
CreateBy: loginUserName,
}
// 已有网元可获取的信息
if body.ServerState != nil {
if v, ok := body.ServerState["version"]; ok && v != nil {
neVersion.Version = v.(string)
}
if v, ok := body.ServerState["sn"]; ok && v != nil {
neLicense.SerialNum = v.(string)
}
if v, ok := body.ServerState["expire"]; ok && v != nil {
neLicense.ExpiryDate = v.(string)
neLicense.Status = "1"
}
}
s.neVersionService.Insert(neVersion)
s.neLicenseService.Insert(neLicense)
body.CreateBy = loginUserName
insertId := s.neInfoService.Insert(body)
if insertId != "" {
c.JSON(200, result.Ok(nil))
c.JSON(200, result.OkData(insertId))
return
}
c.JSON(200, result.Err(nil))
@@ -229,8 +354,8 @@ func (s *NeInfoController) Edit(c *gin.Context) {
}
// 检查属性值唯一
uniqueHostCmd := s.neInfoService.CheckUniqueNeTypeAndNeId(body.NeType, body.NeId, body.ID)
if !uniqueHostCmd {
uniqueInfo := s.neInfoService.CheckUniqueNeTypeAndNeId(body.NeType, body.NeId, body.ID)
if !uniqueInfo {
// 网元信息操作【%s】失败同类型下标识已存在
msg := i18n.TTemplate(language, "neInfo.errKeyExists", map[string]any{"key": body.NeId})
c.JSON(200, result.ErrMsg(msg))
@@ -244,21 +369,64 @@ func (s *NeInfoController) Edit(c *gin.Context) {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neInfo.noData")))
return
}
// 获取网元状态是否正常
_, err = neService.NeState(body)
if err != nil {
body.Status = "1"
} else {
// 下发网管配置信息给网元
_, err = neService.NeConfigOMC(body)
if err == nil {
body.Status = "0"
} else {
body.Status = "3"
// 赋予主机ID
if neInfo.HostIDs != "" && len(body.Hosts) > 0 {
hostIDs := strings.Split(neInfo.HostIDs, ",")
for index, id := range hostIDs {
body.Hosts[index].HostID = id
}
}
// 获取网元状态是否正常
body.ServerState, err = neFetchlink.NeState(body)
if err != nil {
body.Status = "0"
} else {
// 下发网管配置信息给网元
_, err = neFetchlink.NeConfigOMC(body)
if err == nil {
body.Status = "1"
} else {
body.Status = "2"
}
}
loginUserName := ctx.LoginUserToUserName(c)
neLicense := s.neLicenseService.SelectByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
neVersion := s.neVersionService.SelectByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
// 已有网元可获取的信息
if body.ServerState != nil {
if v, ok := body.ServerState["version"]; ok && v != nil {
neVersion.Version = v.(string)
neVersion.UpdateBy = loginUserName
}
if v, ok := body.ServerState["sn"]; ok && v != nil {
neLicense.SerialNum = v.(string)
}
if v, ok := body.ServerState["expire"]; ok && v != nil {
neLicense.ExpiryDate = v.(string)
neLicense.Status = "1"
neLicense.UpdateBy = loginUserName
}
}
if neVersion.ID != "" {
if neVersion.NeType != body.NeType || neVersion.NeId != body.NeId {
neVersion.NeType = body.NeType
neVersion.NeId = body.NeId
}
s.neVersionService.Update(neVersion)
}
if neLicense.ID != "" {
if neLicense.NeType != body.NeType || neLicense.NeId != body.NeId {
neLicense.NeType = body.NeType
neLicense.NeId = body.NeId
}
s.neLicenseService.Update(neLicense)
}
body.UpdateBy = loginUserName
rows := s.neInfoService.Update(body)
if rows > 0 {
c.JSON(200, result.Ok(nil))

View File

@@ -0,0 +1,226 @@
package controller
import (
"fmt"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/vo/result"
neFetchlink "nms_cxy/src/modules/network_element/fetch_link"
"nms_cxy/src/modules/network_element/model"
neService "nms_cxy/src/modules/network_element/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 NeLicenseController 结构体
var NewNeLicense = &NeLicenseController{
neLicenseService: neService.NewNeLicenseImpl,
neInfoService: neService.NewNeInfoImpl,
}
// 网元授权激活请求
//
// PATH /license
type NeLicenseController struct {
// 网元授权激活服务
neLicenseService neService.INeLicense
// 网元信息服务
neInfoService neService.INeInfo
}
// 网元授权激活列表
//
// GET /list
func (s *NeLicenseController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
data := s.neLicenseService.SelectPage(querys)
// 过滤屏蔽授权文件
rows := data["rows"].([]model.NeLicense)
arr := &rows
for i := range *arr {
(*arr)[i].ActivationRequestCode = "-"
(*arr)[i].LicensePath = "-"
}
c.JSON(200, result.Ok(data))
}
// 网元授权激活信息
//
// GET /:licenseId
func (s *NeLicenseController) Info(c *gin.Context) {
language := ctx.AcceptLanguage(c)
licenseId := c.Param("licenseId")
if licenseId == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neLicense := s.neLicenseService.SelectById(licenseId)
if neLicense.ID != licenseId {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
c.JSON(200, result.OkData(neLicense))
}
// 网元neType和neID查询
//
// GET /byTypeAndID
func (s *NeLicenseController) NeTypeAndID(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neLicense := s.neLicenseService.SelectByNeTypeAndNeID(querys.NeType, querys.NeId)
if neLicense.NeId != querys.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
c.JSON(200, result.OkData(neLicense))
}
// 网元授权激活授权申请码
//
// GET /code
func (s *NeLicenseController) Code(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.SelectByNeTypeAndNeID(querys.NeType, querys.NeId)
if neLicense.NeId != querys.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
// 更新授权码
code, licensePath := s.neLicenseService.ReadLicenseInfo(neLicense)
neLicense.ActivationRequestCode = code
if licensePath != "" {
neLicense.LicensePath = licensePath
} else {
neLicense.SerialNum = ""
neLicense.ExpiryDate = ""
neLicense.Status = "0"
}
neLicense.UpdateBy = ctx.LoginUserToUserName(c)
s.neLicenseService.Update(neLicense)
c.JSON(200, result.OkData(code))
}
// 网元授权激活授权文件替换
//
// POST /change
func (s *NeLicenseController) Change(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeLicense
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.LicensePath == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.SelectByNeTypeAndNeID(body.NeType, body.NeId)
if neLicense.NeId != body.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
// 更新授权记录
if body.Remark != "" {
neLicense.Remark = body.Remark
}
neLicense.LicensePath = body.LicensePath
neLicense.Status = "0"
neLicense.UpdateBy = ctx.LoginUserToUserName(c)
upRows := s.neLicenseService.Update(neLicense)
if upRows > 0 {
// 进行上传替换
err = s.neLicenseService.UploadLicense(body)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
}
// 网元授权激活状态
//
// GET /state
func (s *NeLicenseController) State(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.SelectByNeTypeAndNeID(querys.NeType, querys.NeId)
if neLicense.NeId != querys.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
// 查询网元获取IP获取网元状态
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(neLicense.NeType, neLicense.NeId)
if neInfo.NeId != neLicense.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
if neState, err := neFetchlink.NeState(neInfo); err == nil && neState["sn"] != nil {
neLicense.Status = "1"
neLicense.SerialNum = fmt.Sprint(neState["sn"])
neLicense.ExpiryDate = fmt.Sprint(neState["expire"])
code, licensePath := s.neLicenseService.ReadLicenseInfo(neLicense)
neLicense.ActivationRequestCode = code
neLicense.LicensePath = licensePath
} else {
neLicense.Status = "0"
}
// 更新授权信息
neLicense.UpdateBy = ctx.LoginUserToUserName(c)
s.neLicenseService.Update(neLicense)
if neLicense.Status == "1" {
c.JSON(200, result.OkData(map[string]string{
"sn": neLicense.SerialNum,
"expire": neLicense.ExpiryDate,
}))
return
}
c.JSON(200, result.ErrMsg(fmt.Sprintf("%s service status exception", neLicense.NeType)))
}

View File

@@ -19,15 +19,15 @@ var NewNeSoftware = &NeSoftwareController{
neSoftwareService: neService.NewNeSoftwareImpl,
}
// 网元软件包信息请求
// 网元软件包请求
//
// PATH /software
type NeSoftwareController struct {
// 网元软件包信息服务
// 网元软件包服务
neSoftwareService neService.INeSoftware
}
// 网元软件包信息列表
// 网元软件包列表
//
// GET /list
func (s *NeSoftwareController) List(c *gin.Context) {
@@ -37,7 +37,7 @@ func (s *NeSoftwareController) List(c *gin.Context) {
c.JSON(200, result.Ok(data))
}
// 网元软件包信息信息
// 网元软件包信息
//
// GET /:softwareId
func (s *NeSoftwareController) Info(c *gin.Context) {
@@ -50,7 +50,7 @@ func (s *NeSoftwareController) Info(c *gin.Context) {
neSoftware := s.neSoftwareService.SelectById(softwareId)
if neSoftware.ID != softwareId {
// 没有可访问网元版本数据!
// 没有可访问网元包信息数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData")))
return
}
@@ -58,27 +58,39 @@ func (s *NeSoftwareController) Info(c *gin.Context) {
c.JSON(200, result.OkData(neSoftware))
}
// 网元软件包信息新增
// 网元软件包新增
//
// POST /
func (s *NeSoftwareController) Add(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeSoftware
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID != "" {
if err != nil || body.Path == "" || body.ID != "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查属性值唯一
uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndFileNameAndVersion(body.NeType, body.FileName, body.Version, "")
if !uniqueSoftware {
// 网元软件包操作【%s】失败网元类型与文件名版本已存在
msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.FileName})
c.JSON(200, result.ErrMsg(msg))
return
// 找到已存在的删除后重新添加
neSoftwares := s.neSoftwareService.SelectList(model.NeSoftware{
NeType: body.NeType,
Name: body.Name,
Version: body.Version,
})
if len(neSoftwares) > 0 {
neSoftware := neSoftwares[0]
s.neSoftwareService.DeleteByIds([]string{neSoftware.ID})
}
// 检查属性值唯一
// uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndNameAndVersion(body.NeType, body.Name, body.Version, "")
// if !uniqueSoftware {
// // 网元软件包操作【%s】失败网元类型与文件名版本已存在
// msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.Name})
// c.JSON(200, result.ErrMsg(msg))
// return
// }
body.CreateBy = ctx.LoginUserToUserName(c)
insertId := s.neSoftwareService.Insert(body)
if insertId != "" {
c.JSON(200, result.Ok(nil))
@@ -87,23 +99,23 @@ func (s *NeSoftwareController) Add(c *gin.Context) {
c.JSON(200, result.Err(nil))
}
// 网元软件包信息修改
// 网元软件包修改
//
// PUT /
func (s *NeSoftwareController) Edit(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeSoftware
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID == "" {
if err != nil || body.Path == "" || body.ID == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查属性值唯一
uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndFileNameAndVersion(body.NeType, body.FileName, body.Version, body.ID)
uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndNameAndVersion(body.NeType, body.Name, body.Version, body.ID)
if !uniqueSoftware {
// 网元软件包操作【%s】失败网元类型与文件名版本已存在
msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.FileName})
msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.Name})
c.JSON(200, result.ErrMsg(msg))
return
}
@@ -111,11 +123,12 @@ func (s *NeSoftwareController) Edit(c *gin.Context) {
// 检查是否存在
neSoftware := s.neSoftwareService.SelectById(body.ID)
if neSoftware.ID != body.ID {
// 没有可访问网元版本数据!
// 没有可访问网元包信息数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData")))
return
}
body.UpdateBy = ctx.LoginUserToUserName(c)
rows := s.neSoftwareService.Update(body)
if rows > 0 {
c.JSON(200, result.Ok(nil))
@@ -124,7 +137,7 @@ func (s *NeSoftwareController) Edit(c *gin.Context) {
c.JSON(200, result.Err(nil))
}
// 网元软件包信息删除
// 网元软件包删除
//
// DELETE /:softwareIds
func (s *NeSoftwareController) Remove(c *gin.Context) {
@@ -150,10 +163,10 @@ func (s *NeSoftwareController) Remove(c *gin.Context) {
c.JSON(200, result.OkMsg(msg))
}
// 网元软件包安装
// 网元软件包设为网元新版本
//
// POST /install
func (s *NeSoftwareController) Install(c *gin.Context) {
// POST /newNeVersion
func (s *NeSoftwareController) NewNeVersion(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeSoftware
err := c.ShouldBindBodyWith(&body, binding.JSON)
@@ -162,19 +175,19 @@ func (s *NeSoftwareController) Install(c *gin.Context) {
return
}
// 检查是否存在
neSoftwares := s.neSoftwareService.SelectList(body)
if len(neSoftwares) == 0 {
// 没有可访问网元版本数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData")))
return
}
neSoftware := neSoftwares[0]
// 进行安装
output, err := s.neSoftwareService.Install(neSoftware)
if err != nil {
c.JSON(200, result.OkData(output))
// 找到已存在的软件包信息
neSoftwares := s.neSoftwareService.SelectList(model.NeSoftware{
NeType: body.NeType,
Name: body.Name,
Version: body.Version,
})
if len(neSoftwares) > 0 {
neSoftware := neSoftwares[0]
s.neSoftwareService.UpdateVersions(neSoftware, model.NeVersion{
NeType: neSoftware.NeType,
UpdateBy: ctx.LoginUserToUserName(c),
})
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))

View File

@@ -1,13 +1,9 @@
package controller
import (
"strings"
"nms_cxy/src/framework/i18n"
"nms_cxy/src/framework/utils/ctx"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/vo/result"
"nms_cxy/src/modules/network_element/model"
neService "nms_cxy/src/modules/network_element/service"
"github.com/gin-gonic/gin"
@@ -19,15 +15,15 @@ var NewNeVersion = &NeVersionController{
neVersionService: neService.NewNeVersionImpl,
}
// 网元版本信息请求
// 网元版本请求
//
// PATH /version
type NeVersionController struct {
// 网元版本信息服务
// 网元版本服务
neVersionService neService.INeVersion
}
// 网元版本信息列表
// 网元版本列表
//
// GET /list
func (s *NeVersionController) List(c *gin.Context) {
@@ -37,7 +33,7 @@ func (s *NeVersionController) List(c *gin.Context) {
c.JSON(200, result.Ok(data))
}
// 网元版本信息信息
// 网元版本信息
//
// GET /:versionId
func (s *NeVersionController) Info(c *gin.Context) {
@@ -58,94 +54,34 @@ func (s *NeVersionController) Info(c *gin.Context) {
c.JSON(200, result.OkData(neVersion))
}
// 网元版本信息新增
// 网元版本操作
//
// POST /
func (s *NeVersionController) Add(c *gin.Context) {
// POST /operate
func (s *NeVersionController) Operate(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeVersion
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID != "" {
var body struct {
Action string `json:"action" binding:"required,oneof=install upgrade rollback"` // 操作行为
NeType string `json:"neType" gorm:"ne_type" binding:"required"` // 网元类型
NeId string `json:"neId" gorm:"ne_id" binding:"required"` // 网元ID
Preinput map[string]string `json:"preinput" ` // 预先输入参数
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查属性值唯一
uniqueInfo := s.neVersionService.CheckUniqueTypeAndID(body.NeType, body.NeId, "")
if !uniqueInfo {
// 网元版本操作【%s】失败网元类型信息已存在
msg := i18n.TTemplate(language, "neVersion.errKeyExists", map[string]any{"name": body.NeType})
c.JSON(200, result.ErrMsg(msg))
return
}
insertId := s.neVersionService.Insert(body)
if insertId != "" {
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
}
// 网元版本信息修改
//
// PUT /
func (s *NeVersionController) Edit(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeVersion
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查属性值唯一
uniqueInfo := s.neVersionService.CheckUniqueTypeAndID(body.NeType, body.NeId, body.ID)
if !uniqueInfo {
// 网元版本操作【%s】失败网元类型信息已存在
msg := i18n.TTemplate(language, "neVersion.errKeyExists", map[string]any{"name": body.NeType})
c.JSON(200, result.ErrMsg(msg))
return
}
// 检查是否存在
neVersion := s.neVersionService.SelectById(body.ID)
if neVersion.ID != body.ID {
neVersion := s.neVersionService.SelectByNeTypeAndNeID(body.NeType, body.NeId)
if neVersion.NeId != body.NeId {
// 没有可访问网元版本数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neVersion.noData")))
return
}
rows := s.neVersionService.Update(body)
if rows > 0 {
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
}
// 网元版本信息删除
//
// DELETE /:versionIds
func (s *NeVersionController) Remove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
versionIds := c.Param("versionIds")
if versionIds == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 处理字符转id数组后去重
ids := strings.Split(versionIds, ",")
uniqueIDs := parse.RemoveDuplicates(ids)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
rows, err := s.neVersionService.DeleteByIds(uniqueIDs)
// 进行相关命令操作
output, err := s.neVersionService.Operate(body.Action, neVersion, body.Preinput)
if err != nil {
c.JSON(200, result.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, result.OkData(output))
}

View File

@@ -1,50 +1,15 @@
package service
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"time"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/fetch"
"nms_cxy/src/modules/network_element/model"
)
// NeState 获取网元端服务状态
func NeState(neInfo model.NeInfo) (map[string]any, error) {
// 网元状态
neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/systemState", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType))
resBytes, err := fetch.Get(neUrl, nil, 250)
if err != nil {
logger.Warnf("NeState %s", err.Error())
return nil, err
}
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Warnf("NeState Unmarshal %s", err.Error())
return nil, err
}
return map[string]any{
"neType": neInfo.NeType,
"neId": neInfo.NeId,
"neName": neInfo.NeName,
"neIP": neInfo.IP,
"refreshTime": time.Now().UnixMilli(), // 获取时间
"version": resData["version"],
"capability": resData["capability"],
"sn": resData["serialNum"],
"expire": resData["expiryDate"],
"cpu": resData["cpuUsage"],
"mem": resData["memUsage"],
"disk": resData["diskSpace"],
}, nil
}
// NeConfigOMC 网元配置对端网管信息
func NeConfigOMC(neInfo model.NeInfo) (map[string]any, error) {
// 网元配置对端网管信息
@@ -62,8 +27,8 @@ func NeConfigOMC(neInfo model.NeInfo) (map[string]any, error) {
var resData map[string]any
if err != nil {
status := err.Error()
logger.Warnf("NeConfigOMC %s", status)
if strings.HasPrefix(status, "204") {
logger.Warnf("NeConfigOMC %s Put \"%s\"", status, neUrl)
if strings.HasPrefix(status, "201") || strings.HasPrefix(status, "204") {
return resData, nil
}
return nil, err
@@ -83,3 +48,23 @@ func NeConfigOMC(neInfo model.NeInfo) (map[string]any, error) {
return resData, nil
}
// NeConfigInfo 网元配置信息
func NeConfigInfo(neInfo model.NeInfo, name string) (map[string]any, error) {
// 网元配置对端网管信息
neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/config/%s", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType), name)
resBytes, err := fetch.Get(neUrl, nil, 1000)
if err != nil {
logger.Warnf("NeConfigInfo %s Get \"%s\"", err.Error(), neUrl)
return nil, err
}
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Warnf("NeConfigInfo Unmarshal %s", err.Error())
return nil, err
}
return resData, nil
}

View File

@@ -0,0 +1,56 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"time"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/fetch"
"nms_cxy/src/modules/network_element/model"
)
// NeState 获取网元端服务状态
func NeState(neInfo model.NeInfo) (map[string]any, error) {
// 网元状态
neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/systemState", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType))
resBytes, err := fetch.Get(neUrl, nil, 1000)
if err != nil {
logger.Warnf("NeState %s", err.Error())
return nil, err
}
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Warnf("NeState Unmarshal %s", err.Error())
return nil, err
}
// 检查是否有许可时间
if v, ok := resData["expiryDate"]; ok && v != nil {
expiryDate := v.(string)
// UPF存在2000的许可时间MME会有空字符
if strings.HasPrefix(expiryDate, "2000") || expiryDate == "" {
logger.Warnf("NeState %s License Expiration Aanomaly. Get \"%s\"", neInfo.NeType, neUrl)
return nil, fmt.Errorf("%s License Expiration Aanomaly", neInfo.NeType)
}
}
return map[string]any{
"neType": neInfo.NeType,
"neId": neInfo.NeId,
"neName": neInfo.NeName,
"neIP": neInfo.IP,
"refreshTime": time.Now().UnixMilli(), // 获取时间
"version": resData["version"],
"capability": resData["capability"],
"sn": resData["serialNum"],
"expire": resData["expiryDate"],
"cpu": resData["cpuUsage"],
"mem": resData["memUsage"],
"disk": resData["diskSpace"],
}, nil
}

View File

@@ -0,0 +1,21 @@
package model
// NeConfig 网元参数配置可用属性值
type NeConfig struct {
ID string `json:"id" gorm:"id"`
NeType string `json:"neType" binding:"required" gorm:"ne_type"` // 网元类型
NeId string `json:"-" gorm:"ne_id"`
TopTag string `json:"topTag" binding:"required" gorm:"top_tag"`
TopDisplay string `json:"topDisplay" binding:"required" gorm:"top_display"`
Method string `json:"method" gorm:"method"` // 操作属性 get只读强制不可编辑删除 put可编辑 delete可删除 post可新增
ParamJSONStr string `json:"-" gorm:"param_json"` // accesss属性控制只读read-only/read/ro 读写read-write
// ====== 非数据库字段属性 ======
ParamData map[string]any `json:"paramData,omitempty" binding:"required" gorm:"-"` // 与ParamJSONStr配合转换
}
// TableName 表名称
func (*NeConfig) TableName() string {
return "param_config"
}

View File

@@ -11,7 +11,7 @@ type NeHost struct {
Addr string `json:"addr" gorm:"column:addr" binding:"required"` // 主机地址
Port int64 `json:"port" gorm:"column:port" binding:"required,number,max=65535,min=1"` // SSH端口
User string `json:"user" gorm:"column:user" binding:"required"` // 主机用户名
AuthMode string `json:"authMode" gorm:"column:auth_mode" binding:"oneof=0 1"` // 认证模式0密码 1主机私钥
AuthMode string `json:"authMode" gorm:"column:auth_mode" binding:"oneof=0 1 2"` // 认证模式0密码 1主机私钥 2已免密
Password string `json:"password" gorm:"column:password"` // 认证密码
PrivateKey string `json:"privateKey" gorm:"column:private_key"` // 认证私钥
PassPhrase string `json:"passPhrase" gorm:"column:pass_phrase"` // 认证私钥密码

View File

@@ -2,21 +2,25 @@ package model
// NeInfo 网元信息对象 ne_info
type NeInfo struct {
ID string `json:"id"`
NeType string `json:"neType" binding:"required"`
NeId string `json:"neId" binding:"required"`
RmUID string `json:"rmUid"`
NeName string `json:"neName"`
IP string `json:"ip" binding:"required"`
Port int64 `json:"port" binding:"required,number,max=65535,min=1"`
PvFlag string `json:"pvFlag" binding:"oneof=PNF VNF"` // enum('PNF','VNF')
Province string `json:"province"`
VendorName string `json:"vendorName"`
Dn string `json:"dn"`
NeAddress string `json:"neAddress"`
Status string `json:"status"` // 0: 在线 1: 下线 2: 备用 3: 待下发配置
UpdateTime string `json:"updateTime"`
HostIDs string `json:"hostIds"` // 网元主机ID组 数据格式(ssh,telnet,telnet)
ID string `json:"id" gorm:"id"`
NeType string `json:"neType" gorm:"ne_type" binding:"required"`
NeId string `json:"neId" gorm:"ne_id" binding:"required"`
RmUID string `json:"rmUid" gorm:"rm_uid"`
NeName string `json:"neName" gorm:"ne_name"`
IP string `json:"ip" gorm:"ip" binding:"required"`
Port int64 `json:"port" gorm:"port" binding:"required,number,max=65535,min=1"`
PvFlag string `json:"pvFlag" gorm:"pv_flag" binding:"oneof=PNF VNF"` // ''PNF'',''VNF''
Province string `json:"province" gorm:"province"` // 省份地域
VendorName string `json:"vendorName" gorm:"vendor_name"`
Dn string `json:"dn" gorm:"dn"`
NeAddress string `json:"neAddress" gorm:"ne_address"` // MAC地址
HostIDs string `json:"hostIds" gorm:"host_ids"` // 网元主机ID组 数据格式(ssh,telnet,telnet)
Status string `json:"status" gorm:"status"` // 0离线 1在线 2配置待下发
Remark string `json:"remark" gorm:"remark"` // 备注
CreateBy string `json:"createBy" gorm:"create_by"` // 创建者
CreateTime int64 `json:"createTime" gorm:"create_time"` // 创建时间
UpdateBy string `json:"updateBy" gorm:"update_by"` // 更新者
UpdateTime int64 `json:"updateTime" gorm:"update_time"` // 更新时间
// ====== 非数据库字段属性 ======

View File

@@ -0,0 +1,27 @@
package model
// NeLicense 网元授权激活信息 ne_license
type NeLicense struct {
ID string `json:"id" gorm:"id"`
NeType string `json:"neType" gorm:"ne_type" binding:"required"` // 网元类型
NeId string `json:"neId" gorm:"ne_id" binding:"required"` // 网元ID
ActivationRequestCode string `json:"activationRequestCode" gorm:"activation_request_code"` // 激活申请代码
LicensePath string `json:"licensePath" gorm:"license_path"` // 激活授权文件
SerialNum string `json:"serialNum" gorm:"serial_num"` // 序列号
ExpiryDate string `json:"expiryDate" gorm:"expiry_date"` // 许可证到期日期
Status string `json:"status" gorm:"status"` // 状态 0无效 1有效
Remark string `json:"remark" gorm:"remark"` // 备注
CreateBy string `json:"createBy" gorm:"create_by"` // 创建者
CreateTime int64 `json:"createTime" gorm:"create_time"` // 创建时间
UpdateBy string `json:"updateBy" gorm:"update_by"` // 更新者
UpdateTime int64 `json:"updateTime" gorm:"update_time"` // 更新时间
// ====== 非数据库字段属性 ======
Reload bool `json:"reload,omitempty" gorm:"-"` // 刷新重启网元
}
// TableName 表名称
func (*NeLicense) TableName() string {
return "ne_license"
}

View File

@@ -1,18 +1,20 @@
package model
import "time"
// NeSoftware 网元软件包 ne_software
type NeSoftware struct {
ID string `json:"id" gorm:"id"`
NeType string `json:"neType" gorm:"ne_type" binding:"required"` // 网元类型
FileName string `json:"fileName" gorm:"file_name" binding:"required"` // 包名称
Path string `json:"path" gorm:"path"` // 包路径
Version string `json:"version" gorm:"version" binding:"required"` // 包版本
Md5Sum string `json:"md5Sum" gorm:"md5_sum"` // --无使用 md5签名
Status string `json:"status" gorm:"status"` // --无使用
Comment string `json:"comment" gorm:"comment"` // 包说明
UpdateTime time.Time `json:"updateTime" gorm:"update_time"` // 上传时间
ID string `json:"id" gorm:"id"`
NeType string `json:"neType" gorm:"ne_type" binding:"required"` // 网元类型
Name string `json:"name" gorm:"name" binding:"required"` // 包名称
Path string `json:"path" gorm:"path"` // 包路径
Version string `json:"version" gorm:"version" binding:"required"` // 包版本
Description string `json:"description" gorm:"description"` // 包说明
CreateBy string `json:"createBy" gorm:"column:create_by"` // 创建者
CreateTime int64 `json:"createTime" gorm:"column:create_time"` // 创建时间
UpdateBy string `json:"updateBy" gorm:"column:update_by"` // 更新者
UpdateTime int64 `json:"updateTime" gorm:"column:update_time"` // 更新时间
// ====== 非数据库字段属性 ======
}
// TableName 表名称

View File

@@ -1,20 +1,24 @@
package model
import "time"
// NeVersion 网元版本信息 ne_version
type NeVersion struct {
ID string `json:"id" gorm:"id"`
NeType string `json:"neType" gorm:"ne_type" binding:"required"` // 网元类型
NeId string `json:"neId" gorm:"ne_id" binding:"required"` // 网元ID
Version string `json:"version" gorm:"version"` // 当前版本
FilePath string `json:"filePath" gorm:"file_path"` // 当前软件包
PreVersion string `json:"preVersion" gorm:"pre_version"` // 上一版本
PreFile string `json:"preFile" gorm:"pre_file"` // 上一版本软件
NewVersion string `json:"newVersion" gorm:"new_version"` // 一版本
NewFile string `json:"newFile" gorm:"new_file"` // 一版本软件包
Status string `json:"status" gorm:"status" binding:"oneof=Uploaded Inactive Active"` // 当前状态 (Uploaded下一版本上传 Inactive下一版本待激活 Active当前已激活)
UpdateTime time.Time `json:"updateTime" gorm:"update_time"` // 更新时间
ID string `json:"id" gorm:"id"`
NeType string `json:"neType" gorm:"ne_type" binding:"required"` // 网元类型
NeId string `json:"neId" gorm:"ne_id" binding:"required"` // 网元ID
Name string `json:"name" gorm:"name"` // 当前包名
Version string `json:"version" gorm:"version" binding:"required"` // 当前版本
Path string `json:"path" gorm:"path" binding:"required"` // 当前软件包
PreName string `json:"preName" gorm:"pre_name"` // 上一版本包
PreVersion string `json:"preVersion" gorm:"pre_version"` // 一版本
PrePath string `json:"prePath" gorm:"pre_path"` // 一版本软件包
NewName string `json:"newName" gorm:"new_name"` // 新版本包名
NewVersion string `json:"newVersion" gorm:"new_version"` // 新版本
NewPath string `json:"newPath" gorm:"new_path"` // 新版本软件包
Status string `json:"status" gorm:"status"` // 当前状态 1当前版本 2上一版本 3有新版本
CreateBy string `json:"createBy" gorm:"column:create_by"` // 创建者
CreateTime int64 `json:"createTime" gorm:"column:create_time"` // 创建时间
UpdateBy string `json:"updateBy" gorm:"column:update_by"` // 更新者
UpdateTime int64 `json:"updateTime" gorm:"column:update_time"` // 更新时间
}
// TableName 表名称

View File

@@ -1,17 +0,0 @@
package model
// UDMAuth UDM鉴权用户对象 u_auth_user
type UDMAuth struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
Imsi string `json:"imsi" gorm:"column:imsi"` // SIM卡号
Amf string `json:"amf" gorm:"column:amf"` // ANF
Status string `json:"status" gorm:"column:status"` // 状态
Ki string `json:"ki" gorm:"column:ki"` // ki
AlgoIndex string `json:"algoIndex" gorm:"column:algo_index"` // AlgoIndex
Opc string `json:"opc" gorm:"column:opc"`
NeID string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
}
func (UDMAuth) TableName() string {
return "u_auth_user"
}

View File

@@ -4,7 +4,6 @@ import (
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/middleware"
"nms_cxy/src/framework/middleware/collectlogs"
"nms_cxy/src/framework/middleware/repeat"
"nms_cxy/src/modules/network_element/controller"
"nms_cxy/src/modules/network_element/service"
@@ -36,15 +35,46 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neAction", collectlogs.BUSINESS_TYPE_IMPORT)),
controller.NewNeAction.PushFile,
)
neActionGroup.PUT("/service",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neAction", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeAction.Service,
)
}
// 网元信息
neInfoGroup := neGroup.Group("/info")
{
neInfoGroup.GET("/state",
middleware.PreAuthorize(nil),
controller.NewNeInfo.State,
)
neInfoGroup.GET("/byTypeAndID",
middleware.PreAuthorize(nil),
controller.NewNeInfo.NeTypeAndID,
)
neInfoGroup.GET("/listAll",
middleware.PreAuthorize(nil),
controller.NewNeInfo.ListAll,
)
neInfoGroup.GET("/para5GFile",
middleware.PreAuthorize(nil),
controller.NewNeInfo.Para5GFileRead,
)
neInfoGroup.PUT("/para5GFile",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeInfo.Para5GFileWrite,
)
neInfoGroup.GET("/oamFile",
middleware.PreAuthorize(nil),
controller.NewNeInfo.OAMFileRead,
)
neInfoGroup.PUT("/oamFile",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeInfo.OAMFileWrite,
)
neInfoGroup.GET("/list",
middleware.PreAuthorize(nil),
controller.NewNeInfo.List,
@@ -68,14 +98,6 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeInfo.Remove,
)
neInfoGroup.GET("/state",
middleware.PreAuthorize(nil),
controller.NewNeInfo.State,
)
neInfoGroup.GET("/byTypeAndID",
middleware.PreAuthorize(nil),
controller.NewNeInfo.NeTypeAndID,
)
}
// 网元主机
@@ -119,6 +141,11 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeHost.CheckBySSH,
)
neHostGroup.POST("/authorizedBySSH",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeHost.AuthorizedBySSH,
)
}
// 网元主机命令
@@ -160,20 +187,10 @@ func Setup(router *gin.Engine) {
middleware.PreAuthorize(nil),
controller.NewNeVersion.Info,
)
neVersionGroup.POST("",
neVersionGroup.POST("/operate",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neVersion", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeVersion.Add,
)
neVersionGroup.PUT("",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neVersion", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeVersion.Edit,
)
neVersionGroup.DELETE("/:versionIds",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neVersion", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeVersion.Remove,
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neVersion", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeVersion.Operate,
)
}
@@ -203,118 +220,76 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeSoftware.Remove,
)
neSoftwareGroup.POST("/install",
neSoftwareGroup.POST("/newNeVersion",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeSoftware.Install,
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeSoftware.NewNeVersion,
)
}
// UDM鉴权用户信息
udmAuthGroup := neGroup.Group("/udm/auth")
// 网元授权激活信息
neLicenseGroup := neGroup.Group("/license")
{
udmAuthGroup.PUT("/resetData/:neId",
repeat.RepeatSubmit(5),
neLicenseGroup.GET("/list",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_CLEAN)),
controller.NewUDMAuth.ResetData,
controller.NewNeLicense.List,
)
udmAuthGroup.GET("/list",
neLicenseGroup.GET("/:licenseId",
middleware.PreAuthorize(nil),
controller.NewUDMAuth.List,
controller.NewNeLicense.Info,
)
udmAuthGroup.GET("/:neId/:imsi",
neLicenseGroup.GET("/byTypeAndID",
middleware.PreAuthorize(nil),
controller.NewUDMAuth.Info,
controller.NewNeLicense.NeTypeAndID,
)
udmAuthGroup.POST("/:neId",
neLicenseGroup.GET("/code",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewUDMAuth.Add,
controller.NewNeLicense.Code,
)
udmAuthGroup.POST("/:neId/:num",
neLicenseGroup.POST("/change",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewUDMAuth.Adds,
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neLicense", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeLicense.Change,
)
udmAuthGroup.PUT("/:neId",
neLicenseGroup.GET("/state",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewUDMAuth.Edit,
)
udmAuthGroup.DELETE("/:neId/:imsi",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewUDMAuth.Remove,
)
udmAuthGroup.DELETE("/:neId/:imsi/:num",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewUDMAuth.Removes,
)
udmAuthGroup.POST("/export",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewUDMAuth.Export,
)
udmAuthGroup.POST("/import",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_IMPORT)),
controller.NewUDMAuth.Import,
controller.NewNeLicense.State,
)
}
// UDM签约用户信息
udmSubGroup := neGroup.Group("/udm/sub")
// 网元参数配置
neConfigGroup := neGroup.Group("/config")
{
udmSubGroup.PUT("/resetData/:neId",
repeat.RepeatSubmit(5),
neConfigGroup.GET("/list",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_CLEAN)),
controller.NewUDMSub.ResetData,
controller.NewNeConfig.List,
)
udmSubGroup.GET("/list",
neConfigGroup.GET("/info/:id",
middleware.PreAuthorize(nil),
controller.NewUDMSub.List,
controller.NewNeConfig.Info,
)
udmSubGroup.GET("/:neId/:imsi",
neConfigGroup.POST("",
middleware.PreAuthorize(nil),
controller.NewUDMSub.Info,
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeConfig.Add,
)
udmSubGroup.POST("/:neId",
neConfigGroup.PUT("",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewUDMSub.Add,
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeConfig.Edit,
)
udmSubGroup.POST("/:neId/:num",
neConfigGroup.DELETE("/:ids",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewUDMSub.Adds,
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeConfig.Remove,
)
udmSubGroup.PUT("/:neId",
neConfigGroup.GET("/list/:neType",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewUDMSub.Edit,
controller.NewNeConfig.ListByNeType,
)
udmSubGroup.DELETE("/:neId/:imsi",
neConfigGroup.GET("/data",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewUDMSub.Remove,
)
udmSubGroup.DELETE("/:neId/:imsi/:num",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewUDMSub.Removes,
)
udmSubGroup.POST("/export",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewUDMSub.Export,
)
udmSubGroup.POST("/import",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_IMPORT)),
controller.NewUDMSub.Import,
controller.NewNeConfig.Data,
)
}
}
@@ -324,4 +299,11 @@ func InitLoad() {
// 启动时,清除缓存-网元类型
service.NewNeInfoImpl.ClearNeCacheByNeType("*")
service.NewNeInfoImpl.SelectNeInfoByRmuid("")
// 启动时,网元公共参数数据记录到全局变量
if para5GMap, err := service.NewNeInfoImpl.NeConfPara5GRead(); para5GMap != nil && err == nil {
service.NewNeInfoImpl.NeConfPara5GWirte(para5GMap, nil)
}
// 启动时,清除缓存-网元参数配置可用属性值
service.NewNeConfigImpl.ClearNeCacheByNeType("*")
service.NewNeConfigImpl.RefreshByNeTypeAndNeID("*")
}

View File

@@ -0,0 +1,24 @@
package repository
import "nms_cxy/src/modules/network_element/model"
// INeConfig 网元参数配置可用属性值 数据层接口
type INeConfig interface {
// SelectPage 根据条件分页查询字典类型
SelectPage(query map[string]any) map[string]any
// SelectList 根据实体查询
SelectList(param model.NeConfig) []model.NeConfig
// SelectByIds 通过ID查询
SelectByIds(ids []string) []model.NeConfig
// Insert 新增信息
Insert(param model.NeConfig) string
// Update 修改信息
Update(param model.NeConfig) int64
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) int64
}

View File

@@ -0,0 +1,254 @@
package repository
import (
"strings"
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/network_element/model"
)
// NewNeConfigImpl 网元参数配置可用属性值 实例化数据层
var NewNeConfigImpl = &NeConfigImpl{
selectSql: `select
id, ne_type, ne_id, top_tag, top_display, method, param_json
from param_config`,
resultMap: map[string]string{
"id": "ID",
"ne_type": "NeType",
"ne_id": "NeId",
"top_tag": "TopTag",
"top_display": "TopDisplay",
"method": "Method",
"param_json": "ParamJSONStr",
},
}
// NeConfigImpl 网元参数配置可用属性值 数据层处理
type NeConfigImpl struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
resultMap map[string]string
}
// convertResultRows 将结果记录转实体结果组
func (r *NeConfigImpl) convertResultRows(rows []map[string]any) []model.NeConfig {
arr := make([]model.NeConfig, 0)
for _, row := range rows {
item := model.NeConfig{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
repo.SetFieldValue(&item, keyMapper, value)
}
}
arr = append(arr, item)
}
return arr
}
// SelectPage 根据条件分页查询字典类型
func (r *NeConfigImpl) SelectPage(query map[string]any) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if v, ok := query["neType"]; ok && v != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, v)
}
if v, ok := query["topTag"]; ok && v != "" {
conditions = append(conditions, "top_tag = ?")
params = append(params, v)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
result := map[string]any{
"total": 0,
"rows": []model.NeHost{},
}
// 查询数量 长度为0直接返回
totalSql := "select count(id) as 'total' from param_config"
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
if err != nil {
logger.Errorf("total err => %v", err)
return result
}
total := parse.Number(totalRows[0]["total"])
if total == 0 {
return result
} else {
result["total"] = total
}
// 分页
pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"])
pageSql := " limit ?,? "
params = append(params, pageNum*pageSize)
params = append(params, pageSize)
// 查询数据
querySql := r.selectSql + whereSql + pageSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
return result
}
// 转换实体
result["rows"] = r.convertResultRows(results)
return result
}
// SelectList 根据实体查询
func (r *NeConfigImpl) SelectList(param model.NeConfig) []model.NeConfig {
// 查询条件拼接
var conditions []string
var params []any
if param.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, param.NeType)
}
if param.TopTag != "" {
conditions = append(conditions, "top_tag = ?")
params = append(params, param.TopTag)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
// 查询数据
querySql := r.selectSql + whereSql + " order by id asc "
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
// 转换实体
return r.convertResultRows(results)
}
// SelectByIds 通过ID查询
func (r *NeConfigImpl) SelectByIds(ids []string) []model.NeConfig {
placeholder := repo.KeyPlaceholderByQuery(len(ids))
querySql := r.selectSql + " where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(ids)
results, err := datasource.RawDB("", querySql, parameters)
if err != nil {
logger.Errorf("query err => %v", err)
return []model.NeConfig{}
}
// 转换实体
return r.convertResultRows(results)
}
// Insert 新增信息
func (r *NeConfigImpl) Insert(param model.NeConfig) string {
// 参数拼接
params := make(map[string]any)
if param.NeType != "" {
params["ne_type"] = param.NeType
}
if param.NeId != "" {
params["ne_id"] = param.NeId
}
if param.TopTag != "" {
params["top_tag"] = param.TopTag
}
if param.TopDisplay != "" {
params["top_display"] = param.TopDisplay
}
if param.Method != "" {
params["method"] = param.Method
}
if param.ParamJSONStr != "" {
params["param_json"] = param.ParamJSONStr
}
// 构建执行语句
keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params)
sql := "insert into param_config (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
db := datasource.DefaultDB()
// 开启事务
tx := db.Begin()
// 执行插入
err := tx.Exec(sql, values...).Error
if err != nil {
logger.Errorf("insert row : %v", err.Error())
tx.Rollback()
return ""
}
// 获取生成的自增 ID
var insertedID string
err = tx.Raw("select last_insert_id()").Row().Scan(&insertedID)
if err != nil {
logger.Errorf("insert last id : %v", err.Error())
tx.Rollback()
return ""
}
// 提交事务
tx.Commit()
return insertedID
}
// Update 修改信息
func (r *NeConfigImpl) Update(param model.NeConfig) int64 {
// 参数拼接
params := make(map[string]any)
if param.NeType != "" {
params["ne_type"] = param.NeType
}
if param.NeId != "" {
params["ne_id"] = param.NeId
}
if param.TopTag != "" {
params["top_tag"] = param.TopTag
}
if param.TopDisplay != "" {
params["top_display"] = param.TopDisplay
}
if param.Method != "" {
params["method"] = param.Method
}
if param.ParamJSONStr != "" {
params["param_json"] = param.ParamJSONStr
}
// 构建执行语句
keys, values := repo.KeyValueByUpdate(params)
sql := "update param_config set " + strings.Join(keys, ",") + " where id = ?"
// 执行更新
values = append(values, param.ID)
rows, err := datasource.ExecDB("", sql, values)
if err != nil {
logger.Errorf("update row : %v", err.Error())
return 0
}
return rows
}
// DeleteByIds 批量删除信息
func (r *NeConfigImpl) DeleteByIds(ids []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(ids))
sql := "delete from param_config where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(ids)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {
logger.Errorf("delete err => %v", err)
return 0
}
return results
}

View File

@@ -175,21 +175,21 @@ func (r *NeHostImpl) SelectByIds(hostIds []string) []model.NeHost {
for i := range *arr {
passwordDe, err := crypto.StringDecryptByAES((*arr)[i].Password)
if err != nil {
logger.Errorf("selectById %s StringDecryptByAES : %v", (*arr)[i].HostID, err.Error())
logger.Errorf("selectById %s decrypt: %v", (*arr)[i].HostID, err.Error())
(*arr)[i].Password = ""
} else {
(*arr)[i].Password = passwordDe
}
privateKeyDe, err := crypto.StringDecryptByAES((*arr)[i].PrivateKey)
if err != nil {
logger.Errorf("selectById %s StringDecryptByAES : %v", (*arr)[i].HostID, err.Error())
logger.Errorf("selectById %s decrypt: %v", (*arr)[i].HostID, err.Error())
(*arr)[i].PrivateKey = ""
} else {
(*arr)[i].PrivateKey = privateKeyDe
}
passPhraseDe, err := crypto.StringDecryptByAES((*arr)[i].PassPhrase)
if err != nil {
logger.Errorf("selectById %s StringDecryptByAES : %v", (*arr)[i].HostID, err.Error())
logger.Errorf("selectById %s decrypt: %v", (*arr)[i].HostID, err.Error())
(*arr)[i].PassPhrase = ""
} else {
(*arr)[i].PassPhrase = passPhraseDe
@@ -265,7 +265,7 @@ func (r *NeHostImpl) Insert(neHost model.NeHost) string {
if neHost.Password != "" {
passwordEn, err := crypto.StringEncryptByAES(neHost.Password)
if err != nil {
logger.Errorf("insert StringEncryptByAES : %v", err.Error())
logger.Errorf("insert encrypt: %v", err.Error())
return ""
}
params["password"] = passwordEn
@@ -273,7 +273,7 @@ func (r *NeHostImpl) Insert(neHost model.NeHost) string {
if neHost.PrivateKey != "" {
privateKeyEn, err := crypto.StringEncryptByAES(neHost.PrivateKey)
if err != nil {
logger.Errorf("insert StringEncryptByAES : %v", err.Error())
logger.Errorf("insert encrypt: %v", err.Error())
return ""
}
params["private_key"] = privateKeyEn
@@ -281,7 +281,7 @@ func (r *NeHostImpl) Insert(neHost model.NeHost) string {
if neHost.PassPhrase != "" {
passPhraseEn, err := crypto.StringEncryptByAES(neHost.PassPhrase)
if err != nil {
logger.Errorf("insert StringEncryptByAES : %v", err.Error())
logger.Errorf("insert encrypt: %v", err.Error())
return ""
}
params["pass_phrase"] = passPhraseEn
@@ -294,6 +294,20 @@ func (r *NeHostImpl) Insert(neHost model.NeHost) string {
params["create_time"] = time.Now().UnixMilli()
}
// 根据认证模式清除不必要的信息
if neHost.AuthMode == "0" {
params["private_key"] = ""
params["pass_phrase"] = ""
}
if neHost.AuthMode == "1" {
params["password"] = ""
}
if neHost.AuthMode == "2" {
params["password"] = ""
params["private_key"] = ""
params["pass_phrase"] = ""
}
// 构建执行语句
keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params)
sql := "insert into ne_host (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
@@ -349,7 +363,7 @@ func (r *NeHostImpl) Update(neHost model.NeHost) int64 {
if neHost.Password != "" {
passwordEn, err := crypto.StringEncryptByAES(neHost.Password)
if err != nil {
logger.Errorf("update StringEncryptByAES : %v", err.Error())
logger.Errorf("update encrypt: %v", err.Error())
return 0
}
params["password"] = passwordEn
@@ -357,7 +371,7 @@ func (r *NeHostImpl) Update(neHost model.NeHost) int64 {
if neHost.PrivateKey != "" {
privateKeyEn, err := crypto.StringEncryptByAES(neHost.PrivateKey)
if err != nil {
logger.Errorf("update StringEncryptByAES : %v", err.Error())
logger.Errorf("update encrypt: %v", err.Error())
return 0
}
params["private_key"] = privateKeyEn
@@ -365,7 +379,7 @@ func (r *NeHostImpl) Update(neHost model.NeHost) int64 {
if neHost.PassPhrase != "" {
passPhraseEn, err := crypto.StringEncryptByAES(neHost.PassPhrase)
if err != nil {
logger.Errorf("update StringEncryptByAES : %v", err.Error())
logger.Errorf("update encrypt: %v", err.Error())
return 0
}
params["pass_phrase"] = passPhraseEn
@@ -376,6 +390,20 @@ func (r *NeHostImpl) Update(neHost model.NeHost) int64 {
params["update_time"] = time.Now().UnixMilli()
}
// 根据认证模式清除不必要的信息
if neHost.AuthMode == "0" {
params["private_key"] = ""
params["pass_phrase"] = ""
}
if neHost.AuthMode == "1" {
params["password"] = ""
}
if neHost.AuthMode == "2" {
params["password"] = ""
params["private_key"] = ""
params["pass_phrase"] = ""
}
// 构建执行语句
keys, values := repo.KeyValueByUpdate(params)
sql := "update ne_host set " + strings.Join(keys, ",") + " where host_id = ?"

View File

@@ -16,25 +16,26 @@ import (
// neListSort 网元列表预设排序
var neListSort = []string{
"OMC",
"MME",
"IMS",
"AMF",
"AUSF",
"UDM",
"SMF",
"PCF",
"UPF",
"NRF",
"NSSF",
"IMS",
"N3IWF",
"NEF",
"NRF",
"UPF",
"LMF",
"NEF",
"MME",
"N3IWF",
"MOCNGW",
"SMSC",
}
// 实例化数据层 NeInfoImpl 结构体
var NewNeInfoImpl = &NeInfoImpl{
selectSql: `select id, ne_type, ne_id, rm_uid, ne_name, ip, port, pv_flag, province, vendor_name, dn, ne_address, status, update_time, host_ids from ne_info`,
selectSql: `select id, ne_type, ne_id, rm_uid, ne_name, ip, port, pv_flag, province, vendor_name, dn, ne_address, host_ids, status, remark, create_by, create_time, update_by, update_time from ne_info`,
resultMap: map[string]string{
"id": "ID",
@@ -49,9 +50,13 @@ var NewNeInfoImpl = &NeInfoImpl{
"vendor_name": "VendorName",
"dn": "Dn",
"ne_address": "NeAddress",
"status": "Status",
"update_time": "UpdateTime",
"host_ids": "HostIDs",
"status": "Status",
"remark": "Remark",
"create_by": "CreateBy",
"create_time": "CreateTime",
"update_by": "UpdateBy",
"update_time": "UpdateTime",
},
}
@@ -298,11 +303,19 @@ func (r *NeInfoImpl) Insert(neInfo model.NeInfo) string {
if neInfo.NeAddress != "" {
params["ne_address"] = neInfo.NeAddress
}
params["status"] = neInfo.Status
params["update_time"] = time.Now()
if neInfo.HostIDs != "" {
params["host_ids"] = neInfo.HostIDs
}
if neInfo.Status != "" {
params["status"] = neInfo.Status
}
if neInfo.Remark != "" {
params["remark"] = neInfo.Remark
}
if neInfo.CreateBy != "" {
params["create_by"] = neInfo.CreateBy
params["create_time"] = time.Now().UnixMilli()
}
// 构建执行语句
keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params)
@@ -360,11 +373,17 @@ func (r *NeInfoImpl) Update(neInfo model.NeInfo) int64 {
params["vendor_name"] = neInfo.VendorName
params["dn"] = neInfo.Dn
params["ne_address"] = neInfo.NeAddress
params["status"] = neInfo.Status
params["update_time"] = time.Now()
if neInfo.HostIDs != "" {
params["host_ids"] = neInfo.HostIDs
}
params["remark"] = neInfo.Remark
if neInfo.Status != "" {
params["status"] = neInfo.Status
}
if neInfo.UpdateBy != "" {
params["update_by"] = neInfo.UpdateBy
params["update_time"] = time.Now().UnixMilli()
}
// 构建执行语句
keys, values := repo.KeyValueByUpdate(params)

View File

@@ -0,0 +1,24 @@
package repository
import "nms_cxy/src/modules/network_element/model"
// INeLicense 网元授权激活信息 数据层接口
type INeLicense interface {
// SelectPage 根据条件分页查询字典类型
SelectPage(query map[string]any) map[string]any
// SelectList 根据实体查询
SelectList(neLicense model.NeLicense) []model.NeLicense
// SelectByIds 通过ID查询
SelectByIds(ids []string) []model.NeLicense
// Insert 新增信息
Insert(neLicense model.NeLicense) string
// Update 修改信息
Update(neLicense model.NeLicense) int64
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) int64
}

View File

@@ -0,0 +1,297 @@
package repository
import (
"strings"
"time"
"nms_cxy/src/framework/datasource"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/repo"
"nms_cxy/src/modules/network_element/model"
)
// 实例化数据层 NewNeLicense 结构体
var NewNeLicenseImpl = &NeLicenseImpl{
selectSql: `select
id, ne_type, ne_id, activation_request_code, license_path, serial_num, expiry_date, status, remark, create_by, create_time, update_by, update_time
from ne_license`,
resultMap: map[string]string{
"id": "ID",
"ne_type": "NeType",
"ne_id": "NeId",
"activation_request_code": "ActivationRequestCode",
"license_path": "LicensePath",
"serial_num": "SerialNum",
"expiry_date": "ExpiryDate",
"status": "Status",
"remark": "Remark",
"create_by": "CreateBy",
"create_time": "CreateTime",
"update_by": "UpdateBy",
"update_time": "UpdateTime",
},
}
// NeLicenseImpl 网元授权激活信息 数据层处理
type NeLicenseImpl struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
resultMap map[string]string
}
// convertResultRows 将结果记录转实体结果组
func (r *NeLicenseImpl) convertResultRows(rows []map[string]any) []model.NeLicense {
arr := make([]model.NeLicense, 0)
for _, row := range rows {
item := model.NeLicense{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
repo.SetFieldValue(&item, keyMapper, value)
}
}
arr = append(arr, item)
}
return arr
}
// SelectPage 根据条件分页查询字典类型
func (r *NeLicenseImpl) SelectPage(query map[string]any) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if v, ok := query["neType"]; ok && v != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.Trim(v.(string), " "))
}
if v, ok := query["neId"]; ok && v != "" {
conditions = append(conditions, "ne_id = ?")
params = append(params, strings.Trim(v.(string), " "))
}
if v, ok := query["expiryDate"]; ok && v != "" {
conditions = append(conditions, "expiry_date = ?")
params = append(params, strings.Trim(v.(string), " "))
}
if v, ok := query["createBy"]; ok && v != "" {
conditions = append(conditions, "create_by like concat(?, '%')")
params = append(params, strings.Trim(v.(string), " "))
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
result := map[string]any{
"total": 0,
"rows": []model.NeHost{},
}
// 查询数量 长度为0直接返回
totalSql := "select count(1) as 'total' from ne_license"
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
if err != nil {
logger.Errorf("total err => %v", err)
return result
}
total := parse.Number(totalRows[0]["total"])
if total == 0 {
return result
} else {
result["total"] = total
}
// 分页
pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"])
pageSql := " limit ?,? "
params = append(params, pageNum*pageSize)
params = append(params, pageSize)
// 查询数据
querySql := r.selectSql + whereSql + pageSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
return result
}
// 转换实体
result["rows"] = r.convertResultRows(results)
return result
}
// SelectList 根据实体查询
func (r *NeLicenseImpl) SelectList(neLicense model.NeLicense) []model.NeLicense {
// 查询条件拼接
var conditions []string
var params []any
if neLicense.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, neLicense.NeType)
}
if neLicense.NeId != "" {
conditions = append(conditions, "ne_id = ?")
params = append(params, neLicense.NeId)
}
if neLicense.ExpiryDate != "" {
conditions = append(conditions, "expiry_date = ?")
params = append(params, neLicense.ExpiryDate)
}
if neLicense.CreateBy != "" {
conditions = append(conditions, "create_by like concat(?, '%')")
params = append(params, neLicense.CreateBy)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
// 查询数据
querySql := r.selectSql + whereSql + " order by id asc "
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
// 转换实体
return r.convertResultRows(results)
}
// SelectByIds 通过ID查询
func (r *NeLicenseImpl) SelectByIds(cmdIds []string) []model.NeLicense {
placeholder := repo.KeyPlaceholderByQuery(len(cmdIds))
querySql := r.selectSql + " where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(cmdIds)
results, err := datasource.RawDB("", querySql, parameters)
if err != nil {
logger.Errorf("query err => %v", err)
return []model.NeLicense{}
}
// 转换实体
return r.convertResultRows(results)
}
// Insert 新增信息
func (r *NeLicenseImpl) Insert(neLicense model.NeLicense) string {
// 参数拼接
params := make(map[string]any)
if neLicense.NeType != "" {
params["ne_type"] = neLicense.NeType
}
if neLicense.NeId != "" {
params["ne_id"] = neLicense.NeId
}
if neLicense.ActivationRequestCode != "" {
params["activation_request_code"] = neLicense.ActivationRequestCode
}
if neLicense.LicensePath != "" {
params["license_path"] = neLicense.LicensePath
}
if neLicense.SerialNum != "" {
params["serial_num"] = neLicense.SerialNum
}
if neLicense.ExpiryDate != "" {
params["expiry_date"] = neLicense.ExpiryDate
}
if neLicense.Status != "" {
params["status"] = neLicense.Status
}
if neLicense.Remark != "" {
params["remark"] = neLicense.Remark
}
if neLicense.CreateBy != "" {
params["create_by"] = neLicense.CreateBy
params["create_time"] = time.Now().UnixMilli()
}
// 构建执行语句
keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params)
sql := "insert into ne_license (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
db := datasource.DefaultDB()
// 开启事务
tx := db.Begin()
// 执行插入
err := tx.Exec(sql, values...).Error
if err != nil {
logger.Errorf("insert row : %v", err.Error())
tx.Rollback()
return ""
}
// 获取生成的自增 ID
var insertedID string
err = tx.Raw("select last_insert_id()").Row().Scan(&insertedID)
if err != nil {
logger.Errorf("insert last id : %v", err.Error())
tx.Rollback()
return ""
}
// 提交事务
tx.Commit()
return insertedID
}
// Update 修改信息
func (r *NeLicenseImpl) Update(neLicense model.NeLicense) int64 {
// 参数拼接
params := make(map[string]any)
if neLicense.NeType != "" {
params["ne_type"] = neLicense.NeType
}
if neLicense.NeId != "" {
params["ne_id"] = neLicense.NeId
}
if neLicense.ActivationRequestCode != "" {
params["activation_request_code"] = neLicense.ActivationRequestCode
}
if neLicense.LicensePath != "" {
params["license_path"] = neLicense.LicensePath
}
if neLicense.SerialNum != "" {
params["serial_num"] = neLicense.SerialNum
}
if neLicense.ExpiryDate != "" {
params["expiry_date"] = neLicense.ExpiryDate
}
if neLicense.Status != "" {
params["status"] = neLicense.Status
}
if neLicense.Remark != "" {
params["remark"] = neLicense.Remark
}
if neLicense.UpdateBy != "" {
params["update_by"] = neLicense.UpdateBy
params["update_time"] = time.Now().UnixMilli()
}
// 构建执行语句
keys, values := repo.KeyValueByUpdate(params)
sql := "update ne_license set " + strings.Join(keys, ",") + " where id = ?"
// 执行更新
values = append(values, neLicense.ID)
rows, err := datasource.ExecDB("", sql, values)
if err != nil {
logger.Errorf("update row : %v", err.Error())
return 0
}
return rows
}
// DeleteByIds 批量删除信息
func (r *NeLicenseImpl) DeleteByIds(cmdIds []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(cmdIds))
sql := "delete from ne_license where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(cmdIds)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {
logger.Errorf("delete err => %v", err)
return 0
}
return results
}

View File

@@ -22,6 +22,6 @@ type INeSoftware interface {
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) int64
// CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一
CheckUniqueTypeAndFileNameAndVersion(neSoftware model.NeSoftware) string
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一
CheckUniqueTypeAndNameAndVersion(neSoftware model.NeSoftware) string
}

View File

@@ -15,18 +15,19 @@ import (
// 实例化数据层 NewNeSoftware 结构体
var NewNeSoftwareImpl = &NeSoftwareImpl{
selectSql: `select
id, ne_type, file_name, path, version, md5_sum, status, comment, update_time
id, ne_type, name, path, version, description, create_by, create_time, update_by, update_time
from ne_software`,
resultMap: map[string]string{
"id": "ID",
"ne_type": "NeType",
"file_name": "FileName",
"name": "Name",
"path": "Path",
"version": "Version",
"md5_sum": "Md5Sum",
"status": "Status",
"comment": "Comment",
"description": "Description",
"create_by": "CreateBy",
"create_time": "CreateTime",
"update_by": "UpdateBy",
"update_time": "UpdateTime",
},
}
@@ -60,11 +61,20 @@ func (r *NeSoftwareImpl) SelectPage(query map[string]any) map[string]any {
var conditions []string
var params []any
if v, ok := query["neType"]; ok && v != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.Trim(v.(string), " "))
softwareType := v.(string)
if strings.Contains(softwareType, ",") {
softwareTypeArr := strings.Split(softwareType, ",")
placeholder := repo.KeyPlaceholderByQuery(len(softwareTypeArr))
conditions = append(conditions, "ne_type in ("+placeholder+")")
parameters := repo.ConvertIdsSlice(softwareTypeArr)
params = append(params, parameters...)
} else {
conditions = append(conditions, "ne_type = ?")
params = append(params, strings.Trim(softwareType, " "))
}
}
if v, ok := query["fileName"]; ok && v != "" {
conditions = append(conditions, "file_name like concat(?, '%')")
if v, ok := query["name"]; ok && v != "" {
conditions = append(conditions, "name like concat(?, '%')")
params = append(params, strings.Trim(v.(string), " "))
}
if v, ok := query["version"]; ok && v != "" {
@@ -133,9 +143,9 @@ func (r *NeSoftwareImpl) SelectList(neSoftware model.NeSoftware) []model.NeSoftw
conditions = append(conditions, "version = ?")
params = append(params, neSoftware.Version)
}
if neSoftware.FileName != "" {
conditions = append(conditions, "file_name like concat(?, '%')")
params = append(params, neSoftware.FileName)
if neSoftware.Name != "" {
conditions = append(conditions, "name like concat(?, '%')")
params = append(params, neSoftware.Name)
}
// 构建查询条件语句
@@ -169,8 +179,8 @@ func (r *NeSoftwareImpl) SelectByIds(cmdIds []string) []model.NeSoftware {
return r.convertResultRows(results)
}
// CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一
func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neSoftware model.NeSoftware) string {
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一
func (r *NeSoftwareImpl) CheckUniqueTypeAndNameAndVersion(neSoftware model.NeSoftware) string {
// 查询条件拼接
var conditions []string
var params []any
@@ -182,9 +192,9 @@ func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neSoftware model.N
conditions = append(conditions, "version = ?")
params = append(params, neSoftware.Version)
}
if neSoftware.FileName != "" {
conditions = append(conditions, "file_name = ?")
params = append(params, neSoftware.FileName)
if neSoftware.Name != "" {
conditions = append(conditions, "name = ?")
params = append(params, neSoftware.Name)
}
// 构建查询条件语句
@@ -215,8 +225,8 @@ func (r *NeSoftwareImpl) Insert(neSoftware model.NeSoftware) string {
if neSoftware.NeType != "" {
params["ne_type"] = neSoftware.NeType
}
if neSoftware.FileName != "" {
params["file_name"] = neSoftware.FileName
if neSoftware.Name != "" {
params["name"] = neSoftware.Name
}
if neSoftware.Path != "" {
params["path"] = neSoftware.Path
@@ -224,19 +234,11 @@ func (r *NeSoftwareImpl) Insert(neSoftware model.NeSoftware) string {
if neSoftware.Version != "" {
params["version"] = neSoftware.Version
}
if neSoftware.Md5Sum != "" {
params["md5_sum"] = neSoftware.Md5Sum
params["description"] = neSoftware.Description
if neSoftware.CreateBy != "" {
params["create_by"] = neSoftware.CreateBy
params["create_time"] = time.Now().UnixMilli()
}
if neSoftware.Status != "" {
params["status"] = neSoftware.Status
}
if neSoftware.Comment != "" {
params["comment"] = neSoftware.Comment
}
if neSoftware.Status != "" {
params["status"] = neSoftware.Status
}
params["update_time"] = time.Now()
// 构建执行语句
keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params)
@@ -272,8 +274,8 @@ func (r *NeSoftwareImpl) Update(neSoftware model.NeSoftware) int64 {
if neSoftware.NeType != "" {
params["ne_type"] = neSoftware.NeType
}
if neSoftware.FileName != "" {
params["file_name"] = neSoftware.FileName
if neSoftware.Name != "" {
params["name"] = neSoftware.Name
}
if neSoftware.Path != "" {
params["path"] = neSoftware.Path
@@ -281,19 +283,11 @@ func (r *NeSoftwareImpl) Update(neSoftware model.NeSoftware) int64 {
if neSoftware.Version != "" {
params["version"] = neSoftware.Version
}
if neSoftware.Md5Sum != "" {
params["md5_sum"] = neSoftware.Md5Sum
params["description"] = neSoftware.Description
if neSoftware.UpdateBy != "" {
params["update_by"] = neSoftware.UpdateBy
params["update_time"] = time.Now().UnixMilli()
}
if neSoftware.Status != "" {
params["status"] = neSoftware.Status
}
if neSoftware.Comment != "" {
params["comment"] = neSoftware.Comment
}
if neSoftware.Status != "" {
params["status"] = neSoftware.Status
}
params["update_time"] = time.Now()
// 构建执行语句
keys, values := repo.KeyValueByUpdate(params)

View File

@@ -21,7 +21,4 @@ type INeVersion interface {
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) int64
// CheckUniqueTypeAndID 校验网元类型和网元ID是否唯一
CheckUniqueTypeAndID(neVersion model.NeVersion) string
}

View File

@@ -1,7 +1,6 @@
package repository
import (
"fmt"
"strings"
"time"
@@ -15,20 +14,26 @@ import (
// 实例化数据层 NewNeVersion 结构体
var NewNeVersionImpl = &NeVersionImpl{
selectSql: `select
id, ne_type, ne_id, version, file_path, pre_version, pre_file, new_version, new_file, status, update_time
id, ne_type, ne_id, name, version, path, pre_name, pre_version, pre_path, new_name, new_version, new_path, status, create_by, create_time, update_by, update_time
from ne_version`,
resultMap: map[string]string{
"id": "ID",
"ne_type": "NeType",
"ne_id": "NeId",
"name": "name",
"version": "Version",
"file_path": "FilePath",
"path": "Path",
"pre_name": "preName",
"pre_version": "PreVersion",
"pre_file": "PreFile",
"pre_path": "PrePath",
"new_name": "NewName",
"new_version": "NewVersion",
"new_file": "NewFile",
"new_path": "NewPath",
"status": "Status",
"create_by": "CreateBy",
"create_time": "CreateTime",
"update_by": "UpdateBy",
"update_time": "UpdateTime",
},
}
@@ -73,8 +78,8 @@ func (r *NeVersionImpl) SelectPage(query map[string]any) map[string]any {
conditions = append(conditions, "version like concat(?, '%')")
params = append(params, strings.Trim(v.(string), " "))
}
if v, ok := query["filePath"]; ok && v != "" {
conditions = append(conditions, "file_path like concat(?, '%')")
if v, ok := query["path"]; ok && v != "" {
conditions = append(conditions, "path like concat(?, '%')")
params = append(params, strings.Trim(v.(string), " "))
}
@@ -105,7 +110,7 @@ func (r *NeVersionImpl) SelectPage(query map[string]any) map[string]any {
// 分页
pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"])
pageSql := " limit ?,? "
pageSql := " order by update_time desc limit ?,? "
params = append(params, pageNum*pageSize)
params = append(params, pageSize)
@@ -139,9 +144,13 @@ func (r *NeVersionImpl) SelectList(neVersion model.NeVersion) []model.NeVersion
conditions = append(conditions, "version like concat(?, '%')")
params = append(params, neVersion.Version)
}
if neVersion.FilePath != "" {
conditions = append(conditions, "file_path like concat(?, '%')")
params = append(params, neVersion.FilePath)
if neVersion.Path != "" {
conditions = append(conditions, "path like concat(?, '%')")
params = append(params, neVersion.Path)
}
if neVersion.Status != "" {
conditions = append(conditions, "status = ?")
params = append(params, neVersion.Status)
}
// 构建查询条件语句
@@ -151,7 +160,7 @@ func (r *NeVersionImpl) SelectList(neVersion model.NeVersion) []model.NeVersion
}
// 查询数据
querySql := r.selectSql + whereSql + " order by update_time asc "
querySql := r.selectSql + whereSql + " order by id asc "
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
@@ -175,41 +184,6 @@ func (r *NeVersionImpl) SelectByIds(cmdIds []string) []model.NeVersion {
return r.convertResultRows(results)
}
// CheckUniqueTypeAndID 校验网元类型和网元ID是否唯一
func (r *NeVersionImpl) CheckUniqueTypeAndID(neVersion model.NeVersion) string {
// 查询条件拼接
var conditions []string
var params []any
if neVersion.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, neVersion.NeType)
}
if neVersion.NeId != "" {
conditions = append(conditions, "ne_id = ?")
params = append(params, neVersion.NeId)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
} else {
return ""
}
// 查询数据
querySql := "select id as 'str' from ne_version " + whereSql + " limit 1"
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err %v", err)
return ""
}
if len(results) > 0 {
return fmt.Sprint(results[0]["str"])
}
return ""
}
// Insert 新增信息
func (r *NeVersionImpl) Insert(neVersion model.NeVersion) string {
// 参数拼接
@@ -220,28 +194,40 @@ func (r *NeVersionImpl) Insert(neVersion model.NeVersion) string {
if neVersion.NeId != "" {
params["ne_id"] = neVersion.NeId
}
if neVersion.Name != "" {
params["name"] = neVersion.Name
}
if neVersion.Version != "" {
params["version"] = neVersion.Version
}
if neVersion.FilePath != "" {
params["file_path"] = neVersion.FilePath
if neVersion.Path != "" {
params["path"] = neVersion.Path
}
if neVersion.PreName != "" {
params["pre_name"] = neVersion.PreName
}
if neVersion.PreVersion != "" {
params["pre_version"] = neVersion.PreVersion
}
if neVersion.PreFile != "" {
params["pre_file"] = neVersion.PreFile
if neVersion.PrePath != "" {
params["pre_path"] = neVersion.PrePath
}
if neVersion.NewName != "" {
params["new_name"] = neVersion.NewName
}
if neVersion.NewVersion != "" {
params["new_version"] = neVersion.NewVersion
}
if neVersion.NewFile != "" {
params["new_file"] = neVersion.NewFile
if neVersion.NewPath != "" {
params["new_path"] = neVersion.NewPath
}
if neVersion.Status != "" {
params["status"] = neVersion.Status
}
params["update_time"] = time.Now()
if neVersion.CreateBy != "" {
params["create_by"] = neVersion.CreateBy
params["create_time"] = time.Now().UnixMilli()
}
// 构建执行语句
keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params)
@@ -280,28 +266,40 @@ func (r *NeVersionImpl) Update(neVersion model.NeVersion) int64 {
if neVersion.NeId != "" {
params["ne_id"] = neVersion.NeId
}
if neVersion.Name != "" {
params["name"] = neVersion.Name
}
if neVersion.Version != "" {
params["version"] = neVersion.Version
}
if neVersion.FilePath != "" {
params["file_path"] = neVersion.FilePath
if neVersion.Path != "" {
params["path"] = neVersion.Path
}
if neVersion.PreName != "" {
params["pre_name"] = neVersion.PreName
}
if neVersion.PreVersion != "" {
params["pre_version"] = neVersion.PreVersion
}
if neVersion.PreFile != "" {
params["pre_file"] = neVersion.PreFile
if neVersion.PrePath != "" {
params["pre_path"] = neVersion.PrePath
}
if neVersion.NewName != "" {
params["new_name"] = neVersion.NewName
}
if neVersion.NewVersion != "" {
params["new_version"] = neVersion.NewVersion
}
if neVersion.NewFile != "" {
params["new_file"] = neVersion.NewFile
if neVersion.NewPath != "" {
params["new_path"] = neVersion.NewPath
}
if neVersion.Status != "" {
params["status"] = neVersion.Status
}
params["update_time"] = time.Now()
if neVersion.UpdateBy != "" {
params["update_by"] = neVersion.UpdateBy
params["update_time"] = time.Now().UnixMilli()
}
// 构建执行语句
keys, values := repo.KeyValueByUpdate(params)

View File

@@ -1,26 +0,0 @@
package repository
import (
"nms_cxy/src/modules/network_element/model"
)
// UDM鉴权信息 数据层接口
type IUDMAuth interface {
// ClearAndInsert 清空ne_id后新增实体
ClearAndInsert(neID string, authArr []model.UDMAuth) int64
// SelectPage 根据条件分页查询
SelectPage(query map[string]any) map[string]any
// SelectList 根据实体查询
SelectList(auth model.UDMAuth) []model.UDMAuth
// Insert 批量添加
Inserts(authUsers []model.UDMAuth) int64
// Delete 删除实体
Delete(neID, imsi string) int64
// DeletePrefixImsi 删除前缀匹配的实体
DeletePrefixImsi(neID, imsi string) int64
}

View File

@@ -1,35 +0,0 @@
package repository
import (
"nms_cxy/src/modules/network_element/model"
)
// UDM签约信息 数据层接口
type IUDMSub interface {
// ClearAndInsert 清空ne_id后新增实体
ClearAndInsert(neID string, subArr []model.UDMSub) int64
// SelectPage 根据条件分页查询字典类型
SelectPage(query map[string]any) map[string]any
// SelectList 根据实体查询
SelectList(subUser model.UDMSub) []model.UDMSub
// Insert 新增实体
Insert(subUser model.UDMSub) string
// Insert 批量添加
Inserts(subUser []model.UDMSub) int64
// Update 修改更新
Update(neID string, subUser model.UDMSub) int64
// Delete 删除实体
Delete(neID, imsi string) int64
// DeletePrefixImsi 删除前缀匹配的实体
DeletePrefixImsi(neID, imsi string) int64
// Delete 删除范围实体
Deletes(neID, imsi, num string) int64
}

View File

@@ -0,0 +1,33 @@
package service
import "nms_cxy/src/modules/network_element/model"
// INeConfig 网元参数配置可用属性值 服务层接口
type INeConfig interface {
// RefreshByNeType 通过ne_type刷新redis中的缓存
RefreshByNeTypeAndNeID(neType string) []model.NeConfig
// ClearNeCacheByNeType 清除网元类型参数配置缓存
ClearNeCacheByNeType(neType string) bool
// SelectNeConfigByNeType 查询网元类型参数配置
SelectNeConfigByNeType(neType string) []model.NeConfig
// SelectNeHostPage 分页查询列表数据
SelectPage(query map[string]any) map[string]any
// SelectList 根据实体查询
SelectList(param model.NeConfig) []model.NeConfig
// SelectByIds 通过ID查询
SelectById(id string) model.NeConfig
// Insert 新增信息
Insert(param model.NeConfig) string
// Update 修改信息
Update(param model.NeConfig) int64
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) (int64, error)
}

View File

@@ -0,0 +1,151 @@
package service
import (
"encoding/json"
"fmt"
"strings"
"nms_cxy/src/framework/constants/cachekey"
"nms_cxy/src/framework/redis"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_element/repository"
)
// NewNeConfigImpl 网元参数配置可用属性值 实例化服务层
var NewNeConfigImpl = &NeConfigImpl{
neConfigRepository: repository.NewNeConfigImpl,
}
// NeConfigImpl 网元参数配置可用属性值 服务层处理
type NeConfigImpl struct {
// 网元参数配置可用属性值表
neConfigRepository repository.INeConfig
}
// RefreshByNeType 通过ne_type刷新redis中的缓存
func (r *NeConfigImpl) RefreshByNeTypeAndNeID(neType string) []model.NeConfig {
// 多个
if neType == "" || neType == "*" {
neConfigList := r.neConfigRepository.SelectList(model.NeConfig{})
if len(neConfigList) > 0 {
neConfigGroup := map[string][]model.NeConfig{}
for _, v := range neConfigList {
if item, ok := neConfigGroup[v.NeType]; ok {
neConfigGroup[v.NeType] = append(item, v)
} else {
neConfigGroup[v.NeType] = []model.NeConfig{v}
}
}
for k, v := range neConfigGroup {
key := fmt.Sprintf("%sparam_config:%s", cachekey.NE_DATA_KEY, strings.ToUpper(k))
redis.Del("", key)
if len(v) > 0 {
for i, item := range v {
if err := json.Unmarshal([]byte(item.ParamJSONStr), &item.ParamData); err != nil {
continue
}
v[i] = item
}
values, _ := json.Marshal(v)
redis.Set("", key, string(values))
}
}
}
return neConfigList
}
// 单个
key := fmt.Sprintf("%sparam_config:%s", cachekey.NE_DATA_KEY, strings.ToUpper(neType))
redis.Del("", key)
neConfigList := r.neConfigRepository.SelectList(model.NeConfig{
NeType: neType,
})
if len(neConfigList) > 0 {
for i, v := range neConfigList {
if err := json.Unmarshal([]byte(v.ParamJSONStr), &v.ParamData); err != nil {
continue
}
neConfigList[i] = v
}
values, _ := json.Marshal(neConfigList)
redis.Set("", key, string(values))
}
return neConfigList
}
// ClearNeCacheByNeType 清除网元类型参数配置缓存
func (r *NeConfigImpl) ClearNeCacheByNeType(neType string) bool {
key := fmt.Sprintf("%sparam_config:%s", cachekey.NE_DATA_KEY, neType)
if neType == "*" {
key = fmt.Sprintf("%sparam_config:*", cachekey.NE_DATA_KEY)
}
keys, err := redis.GetKeys("", key)
if err != nil {
return false
}
delOk, _ := redis.DelKeys("", keys)
return delOk
}
// SelectNeConfigByNeType 查询网元类型参数配置
func (r *NeConfigImpl) SelectNeConfigByNeType(neType string) []model.NeConfig {
var neConfigList []model.NeConfig
key := fmt.Sprintf("%sparam_config:%s", cachekey.NE_DATA_KEY, strings.ToUpper(neType))
jsonStr, _ := redis.Get("", key)
if len(jsonStr) > 7 {
err := json.Unmarshal([]byte(jsonStr), &neConfigList)
if err != nil {
neConfigList = []model.NeConfig{}
}
} else {
neConfigList = r.RefreshByNeTypeAndNeID(neType)
}
return neConfigList
}
// SelectNeHostPage 分页查询列表数据
func (r *NeConfigImpl) SelectPage(query map[string]any) map[string]any {
return r.neConfigRepository.SelectPage(query)
}
// SelectConfigList 查询列表
func (r *NeConfigImpl) SelectList(param model.NeConfig) []model.NeConfig {
return r.neConfigRepository.SelectList(param)
}
// SelectByIds 通过ID查询
func (r *NeConfigImpl) SelectById(id string) model.NeConfig {
if id == "" {
return model.NeConfig{}
}
neHosts := r.neConfigRepository.SelectByIds([]string{id})
if len(neHosts) > 0 {
return neHosts[0]
}
return model.NeConfig{}
}
// Insert 新增信息
func (r *NeConfigImpl) Insert(param model.NeConfig) string {
return r.neConfigRepository.Insert(param)
}
// Update 修改信息
func (r *NeConfigImpl) Update(param model.NeConfig) int64 {
return r.neConfigRepository.Update(param)
}
// DeleteByIds 批量删除信息
func (r *NeConfigImpl) DeleteByIds(ids []string) (int64, error) {
// 检查是否存在
data := r.neConfigRepository.SelectByIds(ids)
if len(data) <= 0 {
return 0, fmt.Errorf("param.noData")
}
if len(data) == len(ids) {
rows := r.neConfigRepository.DeleteByIds(ids)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}

View File

@@ -1,6 +1,10 @@
package service
import "nms_cxy/src/modules/network_element/model"
import (
"nms_cxy/src/framework/utils/ssh"
"nms_cxy/src/framework/utils/telnet"
"nms_cxy/src/modules/network_element/model"
)
// 网元信息 服务层接口
type INeInfo interface {
@@ -24,7 +28,8 @@ type INeInfo interface {
// SelectList 查询列表
//
// bandStatus 带状态信息
SelectList(ne model.NeInfo, bandStatus bool) []model.NeInfo
// bandHost 带主机信息
SelectList(ne model.NeInfo, bandStatus bool, bandHost bool) []model.NeInfo
// SelectByIds 通过ID查询
//
@@ -41,5 +46,27 @@ type INeInfo interface {
DeleteByIds(infoIds []string) (int64, error)
// CheckUniqueNeTypeAndNeId 校验同类型下标识是否唯一
CheckUniqueNeTypeAndNeId(neType, neId, infoId string) bool
CheckUniqueNeTypeAndNeId(neType, neId, id string) bool
// NeRunSSHClient 网元主机的SSH客户端-为创建相关连接,注意结束后 Close()
NeRunSSHClient(neType, neId string) (*ssh.ConnSSH, error)
// NeRunSSHCmd 网元主机的SSH客户端发送cmd命令
NeRunSSHCmd(neType, neId, cmd string) (string, error)
// NeRunTelnetClient 网元主机的Telnet客户端-为创建相关连接,注意结束后 Close()
// num 是网元主机telnet 14100 25200
NeRunTelnetClient(neType, neId string, num int) (*telnet.ConnTelnet, error)
// neConfOAMRead 网元OAM配置文件读取
NeConfOAMRead(neType, neId string) (map[string]any, error)
// NeConfOAMSync 网元OAM配置文件生成并同步
NeConfOAMSync(neInfo model.NeInfo, content map[string]any, sync bool) error
// NeConfPara5GRead 网元公共配置文件读取
NeConfPara5GRead() (map[string]any, error)
// NeConfPara5GWirte 网元公共配置文件写入 content内容 syncNE同步到网元端NeType@NeId
NeConfPara5GWirte(content map[string]any, syncNE []string) error
}

View File

@@ -3,10 +3,18 @@ package service
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"nms_cxy/src/framework/constants/cachekey"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/redis"
"nms_cxy/src/framework/utils/parse"
"nms_cxy/src/framework/utils/ssh"
"nms_cxy/src/framework/utils/telnet"
neFetchlink "nms_cxy/src/modules/network_element/fetch_link"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_element/repository"
)
@@ -14,21 +22,20 @@ import (
// 实例化服务层 NeInfoImpl 结构体
var NewNeInfoImpl = &NeInfoImpl{
neInfoRepository: repository.NewNeInfoImpl,
neHostRepository: repository.NewNeHostImpl,
Para5GData: map[string]string{},
}
// 网元信息 服务层处理
type NeInfoImpl struct {
// 网元信息数据信息
neInfoRepository repository.INeInfo
// 网元主机连接表
neHostRepository repository.INeHost
Para5GData map[string]string
}
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo {
var neInfo model.NeInfo
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, neType, neID)
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, strings.ToUpper(neType), neID)
jsonStr, _ := redis.Get("", key)
if len(jsonStr) > 7 {
err := json.Unmarshal([]byte(jsonStr), &neInfo)
@@ -37,7 +44,7 @@ func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeIn
}
} else {
neInfo = r.neInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID)
if neInfo.NeId == neID {
if neInfo.ID != "" && neInfo.NeId == neID {
redis.Del("", key)
values, _ := json.Marshal(neInfo)
redis.Set("", key, string(values))
@@ -49,10 +56,10 @@ func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeIn
// RefreshByNeTypeAndNeID 通过ne_type和ne_id刷新redis中的缓存
func (r *NeInfoImpl) RefreshByNeTypeAndNeID(neType, neID string) model.NeInfo {
var neInfo model.NeInfo
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, neType, neID)
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, strings.ToUpper(neType), neID)
redis.Del("", key)
neInfo = r.neInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID)
if neInfo.NeId == neID {
if neInfo.ID != "" && neInfo.NeId == neID {
values, _ := json.Marshal(neInfo)
redis.Set("", key, string(values))
}
@@ -90,9 +97,9 @@ func (r *NeInfoImpl) SelectNeInfoByRmuid(rmUid string) model.NeInfo {
}
}
} else {
neInfos := r.SelectList(neInfo, false)
neInfos := r.SelectList(neInfo, false, false)
for _, v := range neInfos {
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, v.NeType, v.NeId)
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, strings.ToUpper(v.NeType), v.NeId)
redis.Del("", key)
values, _ := json.Marshal(v)
redis.Set("", key, string(values))
@@ -113,37 +120,7 @@ func (r *NeInfoImpl) SelectPage(query map[string]any, bandStatus bool) map[strin
// 网元直连读取网元服务状态
if bandStatus {
rows := data["rows"].([]model.NeInfo)
arr := &rows
for i := range *arr {
v := (*arr)[i]
result, err := NeState(v)
if err != nil {
(*arr)[i].ServerState = map[string]any{
"online": false,
}
// 网元状态设置为离线
if v.Status != "1" {
v.Status = "1"
(*arr)[i].Status = v.Status
r.neInfoRepository.Update(v)
}
continue
}
result["online"] = true
(*arr)[i].ServerState = result
// 网元状态设置为在线
if v.Status != "0" {
// 下发网管配置信息给网元
_, err = NeConfigOMC(v)
if err != nil {
v.Status = "3"
} else {
v.Status = "0"
}
(*arr)[i].Status = v.Status
r.neInfoRepository.Update(v)
}
}
r.bandNeStatus(&rows)
}
return data
@@ -152,50 +129,70 @@ func (r *NeInfoImpl) SelectPage(query map[string]any, bandStatus bool) map[strin
// SelectList 查询列表
//
// bandStatus 带状态信息
func (r *NeInfoImpl) SelectList(ne model.NeInfo, bandStatus bool) []model.NeInfo {
// bandHost 带主机信息
func (r *NeInfoImpl) SelectList(ne model.NeInfo, bandStatus bool, bandHost bool) []model.NeInfo {
list := r.neInfoRepository.SelectList(ne)
// 网元直连读取网元服务状态
if bandStatus {
neList := &list
for i := range *neList {
v := (*neList)[i]
result, err := NeState(v)
if err != nil {
(*neList)[i].ServerState = map[string]any{
"online": false,
}
// 网元状态设置为离线
if v.Status != "1" {
v.Status = "1"
(*neList)[i].Status = v.Status
r.neInfoRepository.Update(v)
}
continue
}
result["online"] = true
(*neList)[i].ServerState = result
// 网元状态设置为在线
if v.Status != "0" {
// 下发网管配置信息给网元
_, err = NeConfigOMC(v)
if err != nil {
v.Status = "3"
} else {
v.Status = "0"
}
(*neList)[i].Status = v.Status
r.neInfoRepository.Update(v)
}
}
r.bandNeStatus(&list)
}
// 网元主机信息
if bandHost {
r.bandNeHosts(&list)
}
return list
}
// bandNeStatus 网元列表项数据带网元服务状态
func (r *NeInfoImpl) bandNeStatus(arr *[]model.NeInfo) {
for i := range *arr {
v := (*arr)[i]
result, err := neFetchlink.NeState(v)
if err != nil {
(*arr)[i].ServerState = map[string]any{
"online": false,
}
// 网元状态设置为离线
if v.Status != "0" {
v.Status = "0"
(*arr)[i].Status = v.Status
r.neInfoRepository.Update(v)
}
continue
}
result["online"] = true
(*arr)[i].ServerState = result
// 网元状态设置为在线
if v.Status != "1" {
// 下发网管配置信息给网元
_, err = neFetchlink.NeConfigOMC(v)
if err == nil {
v.Status = "1"
} else {
v.Status = "2"
}
(*arr)[i].Status = v.Status
r.neInfoRepository.Update(v)
}
}
}
// bandNeHosts 网元列表项数据带网元主机信息
func (r *NeInfoImpl) bandNeHosts(arr *[]model.NeInfo) {
for i := range *arr {
v := (*arr)[i]
if v.HostIDs != "" {
(*arr)[i].Hosts = NewNeHostImpl.neHostRepository.SelectByIds(strings.Split(v.HostIDs, ","))
}
}
}
// SelectByIds 通过ID查询
//
// bandStatus 带主机信息
// bandHost 带主机信息
func (r *NeInfoImpl) SelectById(infoId string, bandHost bool) model.NeInfo {
if infoId == "" {
return model.NeInfo{}
@@ -205,7 +202,7 @@ func (r *NeInfoImpl) SelectById(infoId string, bandHost bool) model.NeInfo {
neInfo := neInfos[0]
// 带主机信息
if neInfo.HostIDs != "" && bandHost {
neInfo.Hosts = r.neHostRepository.SelectByIds(strings.Split(neInfo.HostIDs, ","))
neInfo.Hosts = NewNeHostImpl.neHostRepository.SelectByIds(strings.Split(neInfo.HostIDs, ","))
}
return neInfo
}
@@ -220,7 +217,7 @@ func (r *NeInfoImpl) Insert(neInfo model.NeInfo) string {
for _, host := range neInfo.Hosts {
host.Title = fmt.Sprintf("%s_%s_%d", strings.ToUpper(neInfo.NeType), neInfo.NeId, host.Port)
host.GroupID = "1"
hostId := r.neHostRepository.Insert(host)
hostId := NewNeHostImpl.Insert(host)
if hostId != "" {
hostIDs = append(hostIDs, hostId)
}
@@ -244,7 +241,7 @@ func (r *NeInfoImpl) Update(neInfo model.NeInfo) int64 {
if host.HostID != "" {
host.Title = fmt.Sprintf("%s_%s_%d", strings.ToUpper(neInfo.NeType), neInfo.NeId, host.Port)
host.GroupID = "1"
r.neHostRepository.Update(host)
NewNeHostImpl.Update(host)
}
}
}
@@ -269,12 +266,20 @@ func (r *NeInfoImpl) DeleteByIds(infoIds []string) (int64, error) {
for _, v := range infos {
// 主机信息删除
if v.HostIDs != "" {
hostIds := strings.Split(v.HostIDs, ",")
r.neHostRepository.DeleteByIds(hostIds)
NewNeHostImpl.DeleteByIds(strings.Split(v.HostIDs, ","))
}
// 删除License
neLicense := NewNeLicenseImpl.SelectByNeTypeAndNeID(v.NeType, v.NeId)
if neLicense.NeId == v.NeId {
NewNeLicenseImpl.DeleteByIds([]string{neLicense.ID})
}
// 删除Version
neVersion := NewNeVersionImpl.SelectByNeTypeAndNeID(v.NeType, v.NeId)
if neVersion.NeId == v.NeId {
NewNeVersionImpl.DeleteByIds([]string{neVersion.ID})
}
// 缓存信息删除
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, v.NeType, v.NeId)
redis.Del("", key)
redis.Del("", fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, v.NeType, v.NeId))
}
rows := r.neInfoRepository.DeleteByIds(infoIds)
return rows, nil
@@ -284,13 +289,510 @@ func (r *NeInfoImpl) DeleteByIds(infoIds []string) (int64, error) {
}
// CheckUniqueNeTypeAndNeId 校验同类型下标识是否唯一
func (r *NeInfoImpl) CheckUniqueNeTypeAndNeId(neType, neId, infoId string) bool {
func (r *NeInfoImpl) CheckUniqueNeTypeAndNeId(neType, neId, id string) bool {
uniqueId := r.neInfoRepository.CheckUniqueNeTypeAndNeId(model.NeInfo{
NeType: neType,
NeId: neId,
})
if uniqueId == infoId {
if uniqueId == id {
return true
}
return uniqueId == ""
}
// NeRunSSHClient 网元主机的SSH客户端-为创建相关连接,注意结束后 Close()
func (r *NeInfoImpl) NeRunSSHClient(neType, neId string) (*ssh.ConnSSH, error) {
neInfo := r.SelectNeInfoByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId {
logger.Errorf("NeRunSSHClient NeType:%s NeID:%s not found", neType, neId)
return nil, fmt.Errorf("neinfo not found")
}
// 取主机信息
if neInfo.HostIDs == "" {
logger.Errorf("NeRunSSHClient NeType:%s NeID:%s hostId not found", neType, neId)
return nil, fmt.Errorf("neinfo hostId not found")
}
neInfo.Hosts = NewNeHostImpl.neHostRepository.SelectByIds(strings.Split(neInfo.HostIDs, ","))
if len(neInfo.Hosts) <= 0 {
logger.Errorf("NeRunSSHClient Hosts %s not found", neInfo.HostIDs)
return nil, fmt.Errorf("neinfo host not found")
}
neHost := neInfo.Hosts[0] // 网元主机ssh 022
if neHost.HostType != "ssh" {
logger.Errorf("NeRunSSHClient Hosts first HostType %s not ssh", neHost.HostType)
return nil, fmt.Errorf("neinfo host type not ssh")
}
var connSSH ssh.ConnSSH
neHost.CopyTo(&connSSH)
var client *ssh.ConnSSH
var err error
if neHost.AuthMode == "2" {
client, err = connSSH.NewClientByLocalPrivate()
} else {
client, err = connSSH.NewClient()
}
if err != nil {
logger.Errorf("NeRunSSHClient NewClient err => %s", err.Error())
return nil, fmt.Errorf("neinfo ssh client new err")
}
return client, nil
}
// NeRunSSHCmd 网元主机的SSH客户端发送cmd命令
func (r *NeInfoImpl) NeRunSSHCmd(neType, neId, cmd string) (string, error) {
sshClient, err := r.NeRunSSHClient(neType, neId)
if err != nil {
return "", err
}
defer sshClient.Close()
// 执行命令
output, err := sshClient.RunCMD(cmd)
if err != nil {
logger.Errorf("NeRunSSHCmd RunCMD %s err => %s", output, err.Error())
return "", fmt.Errorf("neinfo ssh run cmd err")
}
return output, nil
}
// NeRunTelnetClient 网元主机的Telnet客户端-为创建相关连接,注意结束后 Close()
// num 是网元主机telnet 14100 25200
func (r *NeInfoImpl) NeRunTelnetClient(neType, neId string, num int) (*telnet.ConnTelnet, error) {
neInfo := r.SelectNeInfoByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId {
logger.Errorf("NeRunTelnetClient NeType:%s NeID:%s not found", neType, neId)
return nil, fmt.Errorf("neinfo not found")
}
// 取主机信息
if neInfo.HostIDs == "" {
logger.Errorf("NeRunTelnetClient NeType:%s NeID:%s hostId not found", neType, neId)
return nil, fmt.Errorf("neinfo hostId not found")
}
neInfo.Hosts = NewNeHostImpl.neHostRepository.SelectByIds(strings.Split(neInfo.HostIDs, ","))
if len(neInfo.Hosts) <= 0 {
logger.Errorf("NeRunTelnetClient Hosts %s not found", neInfo.HostIDs)
return nil, fmt.Errorf("neinfo host not found")
}
neHost := neInfo.Hosts[num]
// 创建链接Telnet客户端
var connTelnet telnet.ConnTelnet
neHost.CopyTo(&connTelnet)
telnetClient, err := connTelnet.NewClient()
if err != nil {
logger.Errorf("NeRunTelnetClient NewClient err => %s", err.Error())
return nil, fmt.Errorf("neinfo telnet client new err")
}
return telnetClient, nil
}
// neConfOAMData 网元OAM配置文件默认格式数据
func (r *NeInfoImpl) neConfOAMData() map[string]any {
return map[string]any{
"httpManageCfg": map[string]any{
"ipType": "ipv4",
// 必改
"ipv4": "172.60.5.2",
"ipv6": "",
"port": 33030,
"scheme": "http",
},
"oamConfig": map[string]any{
"enable": true,
"ipType": "ipv4",
"ipv4": "172.60.5.1", // 必改
"ipv6": "",
"port": 33030,
"scheme": "http",
"neConfig": map[string]any{ // 必改
"neId": "001",
"rmUid": "4400HX1XXX001",
"neName": "XXX_001",
"dn": "-",
"vendorName": "GD",
"province": "-",
"pvFlag": "PNF",
},
},
"snmpConfig": map[string]any{
"enable": false,
"ipType": "ipv4",
"ipv4": "172.60.5.2", // 必改
"ipv6": "",
"port": 4957,
},
"kpiConfig": map[string]any{
"enable": true,
"timer": 60, // 必改
},
// "pubConfigPath": "/usr/local/etc/conf/para5G.yaml", // 网元只会读一次后续会置空,建议不放
}
}
// neConfOAMRead 网元OAM配置文件读取
func (r *NeInfoImpl) NeConfOAMRead(neType, neId string) (map[string]any, error) {
neTypeLower := strings.ToLower(neType)
// 网管本地路径
omcPath := "/usr/local/etc/omc/ne_config"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
localFilePath := fmt.Sprintf("%s/%s/%s/%s", omcPath, neTypeLower, neId, "oam_manager.yaml")
// 读取文件内容
bytes, err := os.ReadFile(localFilePath)
if err != nil {
// logger.Warnf("NeConfOAMRead ReadFile => %s", err.Error())
// return nil, fmt.Errorf("read file error")
// 无保留文件时返回默认文件数据
oamData := r.neConfOAMData()
r.neConfOAMWirte(neType, neId, oamData, false)
return oamData, nil
}
content := string(bytes)
// 序列化Map
mapData, err := parse.ConvertConfigToMap("yaml", content)
if err != nil {
logger.Warnf("NeConfOAMRead ConvertConfigToMap => %s", err.Error())
return nil, fmt.Errorf("content convert type error")
}
return mapData, nil
}
// neConfOAMWirte 网元OAM配置文件写入 content内容 sync同步到网元端
func (r *NeInfoImpl) neConfOAMWirte(neType, neId string, content any, sync bool) error {
neTypeLower := strings.ToLower(neType)
fileName := "oam_manager.yaml"
// 网管本地路径
omcPath := "/usr/local/etc/omc/ne_config"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
localFilePath := fmt.Sprintf("%s/%s/%s/%s", omcPath, neTypeLower, neId, fileName)
// 写入文件
if err := parse.ConvertConfigToFile("yaml", localFilePath, content); err != nil {
return fmt.Errorf("please check if the file exists or write permissions")
}
// 同步到网元端
if sync {
// 网元主机的SSH客户端
sshClient, err := r.NeRunSSHClient(neType, neId)
if err != nil {
return err
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return err
}
defer sftpClient.Close()
// 网元端配置路径
neFilePath := fmt.Sprintf("/usr/local/etc/%s/%s", neTypeLower, fileName)
neFileDir := filepath.ToSlash(filepath.Dir(neFilePath))
// 修改网元文件权限
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p %s && sudo chmod 775 %s && sudo touch %s && sudo chmod o+w %s", neFileDir, neFileDir, neFilePath, neFilePath))
// 复制到网元进行覆盖
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
return fmt.Errorf("please check if scp remote copy is allowed")
}
}
return nil
}
// NeConfOAMSync 网元OAM配置文件生成并同步
func (r *NeInfoImpl) NeConfOAMSync(neInfo model.NeInfo, content map[string]any, sync bool) error {
oamData, err := r.NeConfOAMRead(neInfo.NeType, neInfo.NeId)
if oamData == nil || err != nil {
return fmt.Errorf("error read OAM file info")
}
// 网元HTTP服务
if v, ok := oamData["httpManageCfg"]; ok {
item := v.(map[string]any)
item["port"] = neInfo.Port
if strings.Contains(neInfo.IP, ":") {
item["ipType"] = "ipv6"
item["ipv6"] = neInfo.IP
}
if strings.Contains(neInfo.IP, ".") {
item["ipType"] = "ipv4"
item["ipv4"] = neInfo.IP
}
oamData["httpManageCfg"] = item
}
// 对网管HTTP配置
if v, ok := oamData["oamConfig"]; ok {
item := v.(map[string]any)
item["neConfig"] = map[string]string{
"neId": neInfo.NeId,
"rmUid": neInfo.RmUID,
"neName": neInfo.NeName,
"dn": neInfo.Dn,
"vendorName": neInfo.VendorName,
"province": neInfo.Province,
"pvFlag": neInfo.PvFlag,
}
if omcIP, ok := r.Para5GData["OMC_IP"]; ok && omcIP != "" {
if strings.Contains(omcIP, ":") {
item["ipType"] = "ipv6"
item["ipv6"] = omcIP
}
if strings.Contains(omcIP, ".") {
item["ipType"] = "ipv4"
item["ipv4"] = omcIP
}
}
if oamEnable, ok := content["oamEnable"]; ok && oamEnable != nil {
item["enable"] = parse.Boolean(oamEnable)
}
if oamPort, ok := content["oamPort"]; ok && oamPort != nil {
item["port"] = parse.Number(oamPort)
}
oamData["oamConfig"] = item
}
// 对网管SNMP配置
if v, ok := oamData["snmpConfig"]; ok {
item := v.(map[string]any)
if strings.Contains(neInfo.IP, ":") {
item["ipType"] = "ipv6"
item["ipv6"] = neInfo.IP
}
if strings.Contains(neInfo.IP, ".") {
item["ipType"] = "ipv4"
item["ipv4"] = neInfo.IP
}
if snmpEnable, ok := content["snmpEnable"]; ok && snmpEnable != nil {
item["enable"] = parse.Boolean(snmpEnable)
}
if snmpPort, ok := content["snmpPort"]; ok && snmpPort != nil {
item["port"] = parse.Number(snmpPort)
}
oamData["snmpConfig"] = item
}
// 对网管KPI上报配置
if v, ok := oamData["kpiConfig"]; ok {
item := v.(map[string]any)
if neInfo.NeType == "UPF" {
item["timer"] = 5
}
if kpiEnable, ok := content["kpiEnable"]; ok && kpiEnable != nil {
item["enable"] = parse.Boolean(kpiEnable)
}
if kpiTimer, ok := content["kpiTimer"]; ok && kpiTimer != nil {
item["timer"] = parse.Number(kpiTimer)
}
oamData["kpiConfig"] = item
}
if err := NewNeInfoImpl.neConfOAMWirte(neInfo.NeType, neInfo.NeId, oamData, sync); err != nil {
return fmt.Errorf("error wirte OAM file info")
}
return nil
}
// NeConfPara5GRead 网元公共配置文件读取
func (r *NeInfoImpl) NeConfPara5GRead() (map[string]any, error) {
// 网管本地路径
omcFilePath := "/usr/local/etc/omc/para5G.yaml"
if runtime.GOOS == "windows" {
omcFilePath = fmt.Sprintf("C:%s", omcFilePath)
}
// 读取文件内容
bytes, err := os.ReadFile(omcFilePath)
if err != nil {
logger.Warnf("NeConfPara5GRead ReadFile => %s", err.Error())
return nil, fmt.Errorf("read file error")
}
content := string(bytes)
// 序列化Map
mapData, err := parse.ConvertConfigToMap("yaml", content)
if err != nil {
logger.Warnf("NeConfPara5GRead ConvertConfigToMap => %s", err.Error())
return nil, fmt.Errorf("content convert type error")
}
return mapData, nil
}
// NeConfPara5GWirte 网元公共配置文件写入 content内容 syncNE同步到网元端NeType@NeId
func (r *NeInfoImpl) NeConfPara5GWirte(content map[string]any, syncNE []string) error {
// 网管本地路径
omcFilePath := "/usr/local/etc/omc/para5G.yaml"
if runtime.GOOS == "windows" {
omcFilePath = fmt.Sprintf("C:%s", omcFilePath)
}
if err := parse.ConvertConfigToFile("yaml", omcFilePath, content); err != nil {
return fmt.Errorf("please check if the file exists or write permissions")
}
// 同步到网元端
if len(syncNE) > 0 {
errMsg := []string{}
for _, neTI := range syncNE {
ti := strings.SplitN(neTI, "@", 2)
// 网元主机的SSH客户端
sshClient, err := r.NeRunSSHClient(ti[0], ti[1])
if err != nil {
errMsg = append(errMsg, fmt.Sprintf("%s : %s", ti, err.Error()))
continue
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
errMsg = append(errMsg, fmt.Sprintf("%s : %s", ti, err.Error()))
continue
}
defer sftpClient.Close()
// 网元端配置路径
neFilePath := "/usr/local/etc/conf/para5G.yaml"
neFileDir := filepath.ToSlash(filepath.Dir(neFilePath))
// 修改网元文件权限
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p %s && sudo chmod 775 %s && sudo touch %s && sudo chmod o+rw %s", neFileDir, neFileDir, neFilePath, neFilePath))
// 复制到网元进行覆盖
if err = sftpClient.CopyFileLocalToRemote(omcFilePath, neFilePath); err != nil {
errMsg = append(errMsg, fmt.Sprintf("%s : please check if scp remote copy is allowed", ti))
continue
}
}
if len(errMsg) > 0 {
return fmt.Errorf(strings.Join(errMsg, "\r\n"))
}
}
// 转换一份数据到全局
r.Para5GData = r.neConfPara5GDataConvert(content)
return nil
}
// NeConfPara5GConvert 网元公共配置数据转化 content网元公共配置文件读取内容
func (r *NeInfoImpl) neConfPara5GDataConvert(content map[string]any) map[string]string {
defer func() {
if err := recover(); err != nil {
logger.Errorf("NeConfPara5GDataConvert panic: %v", err)
// 文件异常就删除配置
omcFilePath := "/usr/local/etc/omc/para5G.yaml"
if runtime.GOOS == "windows" {
omcFilePath = fmt.Sprintf("C:%s", omcFilePath)
}
os.Remove(omcFilePath)
}
}()
basic := content["basic"].(map[string]any)
external := content["external"].(map[string]any)
sbi := content["sbi"].(map[string]any)
mcc := "460"
mnc := "01"
mncDomain := "001"
if plmnId, plmnIdOk := basic["plmnId"].(map[string]any); plmnIdOk {
mcc = plmnId["mcc"].(string)
mnc = plmnId["mnc"].(string)
// If a user input two digit MNC, add a leading zero
if len(mnc) == 2 {
mncDomain = fmt.Sprintf("0%s", mnc)
} else {
mncDomain = mnc
}
}
sst := "1"
sd := "000001"
if plmnId, plmnIdOk := basic["snssai"].(map[string]any); plmnIdOk {
sst = plmnId["sst"].(string)
sd = plmnId["sd"].(string)
}
n3IPAmdMask := external["upfn3_ip"].(string)
n3Arr := strings.SplitN(n3IPAmdMask, "/", 2)
n3IP := n3Arr[0]
n3Mask := "255.255.255.0"
if len(n3Arr) > 1 {
n3Mask = parse.ConvertIPMask(parse.Number(n3Arr[1]))
}
n6IPAmdMask := external["upfn6_ip"].(string)
n6Arr := strings.SplitN(n6IPAmdMask, "/", 2)
n6IP := n6Arr[0]
n6Mask := "255.255.255.0"
if len(n6Arr) > 1 {
n6Mask = parse.ConvertIPMask(parse.Number(n6Arr[1]))
}
ueIPAmdMask := external["ue_pool"].(string)
ueArr := strings.SplitN(ueIPAmdMask, "/", 2)
ueIP := ueArr[0]
ueCicr := "24"
ueMask := "255.255.255.0"
if len(ueArr) > 1 {
ueCicr = ueArr[1]
ueMask = parse.ConvertIPMask(parse.Number(ueArr[1]))
}
return map[string]string{
// basic
"TAC": basic["tac"].(string),
"MCC": mcc,
"MNC": mnc,
"MNC_DOMAIN": mncDomain,
"SST": sst,
"SD": sd,
"DNN_DATA": basic["dnn_data"].(string),
"DNN_IMS": basic["dnn_ims"].(string),
// external
"N2_IP": external["amfn2_ip"].(string),
"UE_POOL": external["ue_pool"].(string),
"UE_IP": ueIP,
"UE_MASK": ueMask,
"UE_CIDR": ueCicr,
"UPF_TYPE": external["upf_type"].(string), // StandardUPF LightUPF
"N3_IP": n3IP,
"N3_MASK": n3Mask,
"N3_GW": external["upfn3_gw"].(string),
"N3_PCI": external["upfn3_pci"].(string),
"N3_MAC": external["upfn3_mac"].(string),
"N6_IP": n6IP,
"N6_MASK": n6Mask,
"N6_GW": external["upfn6_gw"].(string),
"N6_PCI": external["upfn6_pci"].(string),
"N6_MAC": external["upfn6_mac"].(string),
"SIP_IP": external["ims_sip_ip"].(string),
"S1_MMEIP": external["mmes1_ip"].(string),
"S11_MMEIP": external["mmes11_ip"].(string),
"S10_MMEIP": external["mmes10_ip"].(string),
// sbi
"OMC_IP": sbi["omc_ip"].(string),
"IMS_IP": sbi["ims_ip"].(string),
"AMF_IP": sbi["amf_ip"].(string),
"AUSF_IP": sbi["ausf_ip"].(string),
"UDM_IP": sbi["udm_ip"].(string),
"SMF_IP": sbi["smf_ip"].(string),
"PCF_IP": sbi["pcf_ip"].(string),
"NSSF_IP": sbi["nssf_ip"].(string),
"NRF_IP": sbi["nrf_ip"].(string),
"UPF_IP": sbi["upf_ip"].(string),
"LMF_IP": sbi["lmf_ip"].(string),
"NEF_IP": sbi["nef_ip"].(string),
"MME_IP": sbi["mme_ip"].(string),
"N3IWF_IP": sbi["n3iwf_ip"].(string),
"DB_IP": sbi["db_ip"].(string),
}
}

View File

@@ -0,0 +1,34 @@
package service
import "nms_cxy/src/modules/network_element/model"
// INeLicense 网元授权激活信息 服务层接口
type INeLicense interface {
// SelectPage 根据条件分页查询字典类型
SelectPage(query map[string]any) map[string]any
// SelectList 根据实体查询
SelectList(neLicense model.NeLicense) []model.NeLicense
// SelectById 通过ID查询
SelectById(id string) model.NeLicense
// Insert 新增信息
Insert(neLicense model.NeLicense) string
// Update 修改信息
Update(neLicense model.NeLicense) int64
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) (int64, error)
// SelectByNeTypeAndNeID 通过ne_type和ne_id查询信息
SelectByNeTypeAndNeID(neType, neId string) model.NeLicense
// ReadLicenseInfo 读取授权文件信息
// 返回激活申请码, 激活文件
ReadLicenseInfo(neLicense model.NeLicense) (string, string)
// UploadLicense 授权文件上传到网元主机
UploadLicense(neLicense model.NeLicense) error
}

View File

@@ -0,0 +1,191 @@
package service
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"time"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_element/repository"
)
// 实例化服务层 NeLicenseImpl 结构体
var NewNeLicenseImpl = &NeLicenseImpl{
neLicenseRepository: repository.NewNeLicenseImpl,
}
// NeLicenseImpl 网元授权激活信息 服务层处理
type NeLicenseImpl struct {
// 网元授权激活信息表
neLicenseRepository repository.INeLicense
}
// SelectNeHostPage 分页查询列表数据
func (r *NeLicenseImpl) SelectPage(query map[string]any) map[string]any {
return r.neLicenseRepository.SelectPage(query)
}
// SelectConfigList 查询列表
func (r *NeLicenseImpl) SelectList(neLicense model.NeLicense) []model.NeLicense {
return r.neLicenseRepository.SelectList(neLicense)
}
// SelectByIds 通过ID查询
func (r *NeLicenseImpl) SelectById(id string) model.NeLicense {
if id == "" {
return model.NeLicense{}
}
neLicenses := r.neLicenseRepository.SelectByIds([]string{id})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// Insert 新增信息
func (r *NeLicenseImpl) Insert(neLicense model.NeLicense) string {
return r.neLicenseRepository.Insert(neLicense)
}
// Update 修改信息
func (r *NeLicenseImpl) Update(neLicense model.NeLicense) int64 {
return r.neLicenseRepository.Update(neLicense)
}
// DeleteByIds 批量删除信息
func (r *NeLicenseImpl) DeleteByIds(ids []string) (int64, error) {
// 检查是否存在
rowIds := r.neLicenseRepository.SelectByIds(ids)
if len(rowIds) <= 0 {
return 0, fmt.Errorf("neLicense.noData")
}
if len(rowIds) == len(ids) {
rows := r.neLicenseRepository.DeleteByIds(ids)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// SelectByTypeAndID 通过网元类型和网元ID查询
func (r *NeLicenseImpl) SelectByTypeAndID(neType, neId string) model.NeLicense {
neLicenses := r.neLicenseRepository.SelectList(model.NeLicense{
NeType: neType,
NeId: neId,
})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// SelectByNeTypeAndNeID 通过ne_type和ne_id查询信息
func (r *NeLicenseImpl) SelectByNeTypeAndNeID(neType, neId string) model.NeLicense {
neLicenses := r.neLicenseRepository.SelectList(model.NeLicense{
NeType: neType,
NeId: neId,
})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// ReadLicenseInfo 读取授权文件信息
// 返回激活申请码, 激活文件
func (r *NeLicenseImpl) ReadLicenseInfo(neLicense model.NeLicense) (string, string) {
neTypeLower := strings.ToLower(neLicense.NeType)
// 网管本地路径
omcPath := "/usr/local/etc/omc/ne_license"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
omcPath = fmt.Sprintf("%s/%s/%s", omcPath, neTypeLower, neLicense.NeId)
// 网元端授权文件路径
nePath := fmt.Sprintf("/usr/local/etc/%s/license", neTypeLower)
// 网元主机的SSH客户端
sshClient, err := NewNeInfoImpl.NeRunSSHClient(neLicense.NeType, neLicense.NeId)
if err != nil {
return "", ""
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return "", ""
}
defer sftpClient.Close()
// 复制授权申请码到本地
if err = sftpClient.CopyFileRemoteToLocal(nePath+"/Activation_request_code.txt", omcPath+"/Activation_request_code.txt"); err != nil {
return "", ""
}
// 读取文件内容
bytes, err := os.ReadFile(omcPath + "/Activation_request_code.txt")
if err != nil {
return "", ""
}
// 复制激活文件到本地
licensePath := ""
if err = sftpClient.CopyFileRemoteToLocal(nePath+"/system.ini", omcPath+"/system.ini"); err == nil {
licensePath = omcPath + "/system.ini"
}
return strings.TrimSpace(string(bytes)), licensePath
}
// UploadLicense 授权文件上传到网元主机
func (r *NeLicenseImpl) UploadLicense(neLicense model.NeLicense) error {
// 检查文件是否存在
omcLicensePath := file.ParseUploadFilePath(neLicense.LicensePath)
if _, err := os.Stat(omcLicensePath); err != nil {
return fmt.Errorf("file read failure")
}
// 网元主机的SSH客户端
sshClient, err := NewNeInfoImpl.NeRunSSHClient(neLicense.NeType, neLicense.NeId)
if err != nil {
return err
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return err
}
defer sftpClient.Close()
// 网元端授权文件路径
neTypeLower := strings.ToLower(neLicense.NeType)
neLicensePath := fmt.Sprintf("/usr/local/etc/%s/license/system.ini", neTypeLower)
neLicenseDir := filepath.ToSlash(filepath.Dir(neLicensePath))
// 修改网元文件权限
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p %s && sudo chmod 775 %s && sudo touch %s && sudo chmod o+rw %s", neLicenseDir, neLicenseDir, neLicensePath, neLicensePath))
// 尝试备份授权文件
neLicensePathBack := fmt.Sprintf("%s/system_%s.ini", neLicensePath, time.Now().Format("20060102_150405"))
sshClient.RunCMD(fmt.Sprintf("sudo cp -rf %s/system.ini %s", neLicensePath, neLicensePathBack))
// 上传授权文件去覆盖
if err := sftpClient.CopyFileLocalToRemote(omcLicensePath, neLicensePath); err != nil {
return fmt.Errorf("please check if scp remote copy is allowed")
}
// 重启服务
if neLicense.Reload {
cmdStr := fmt.Sprintf("sudo service %s restart", neTypeLower)
if neTypeLower == "ims" {
cmdStr = "ims-stop || true && ims-start"
} else if neTypeLower == "omc" {
cmdStr = "sudo systemctl restart restagent"
}
sshClient.RunCMD(cmdStr)
}
return nil
}

View File

@@ -22,12 +22,9 @@ type INeSoftware interface {
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) (int64, error)
// SelectByVersionAndPath 通过文件版本和路径查询
SelectByVersionAndPath(version, path string) model.NeSoftware
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件版本是否唯一
CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool
// CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一
CheckUniqueTypeAndFileNameAndVersion(neType, fileName, version, id string) bool
// Install 安装软件包
Install(neSoftware model.NeSoftware) (string, error)
// UpdateVersions 更新软件包对应网元的新版本
UpdateVersions(neSoftware model.NeSoftware, neVersion model.NeVersion) int64
}

View File

@@ -2,7 +2,9 @@ package service
import (
"fmt"
"os"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_element/repository"
)
@@ -42,48 +44,79 @@ func (r *NeSoftwareImpl) SelectById(id string) model.NeSoftware {
// Insert 新增信息
func (r *NeSoftwareImpl) Insert(neSoftware model.NeSoftware) string {
return r.neSoftwareRepository.Insert(neSoftware)
inserId := r.neSoftwareRepository.Insert(neSoftware)
if inserId != "" {
// 更新同类型的新包版本
neVersions := NewNeVersionImpl.SelectList(model.NeVersion{NeType: neSoftware.NeType})
if len(neVersions) > 0 {
for _, neVersion := range neVersions {
neVersion.NewName = neSoftware.Name
neVersion.NewVersion = neSoftware.Version
neVersion.NewPath = neSoftware.Path
neVersion.Status = "3"
neVersion.UpdateBy = neSoftware.CreateBy
NewNeVersionImpl.Update(neVersion)
}
}
}
return inserId
}
// Update 修改信息
func (r *NeSoftwareImpl) Update(neSoftware model.NeSoftware) int64 {
return r.neSoftwareRepository.Update(neSoftware)
rows := r.neSoftwareRepository.Update(neSoftware)
if rows > 0 {
// 更新同类型的新包版本
neVersions := NewNeVersionImpl.SelectList(model.NeVersion{
NeType: neSoftware.NeType,
Status: "3",
})
if len(neVersions) > 0 {
for _, neVersion := range neVersions {
neVersion.NewName = neSoftware.Name
neVersion.NewVersion = neSoftware.Version
neVersion.NewPath = neSoftware.Path
neVersion.Status = "3"
neVersion.UpdateBy = neSoftware.UpdateBy
NewNeVersionImpl.Update(neVersion)
}
}
}
return rows
}
// DeleteByIds 批量删除信息
func (r *NeSoftwareImpl) DeleteByIds(ids []string) (int64, error) {
// 检查是否存在
rowIds := r.neSoftwareRepository.SelectByIds(ids)
if len(rowIds) <= 0 {
rows := r.neSoftwareRepository.SelectByIds(ids)
if len(rows) <= 0 {
return 0, fmt.Errorf("neSoftware.noData")
}
if len(rowIds) == len(ids) {
if len(rows) == len(ids) {
// 遍历软件包列表进行文件删除
for _, row := range rows {
// 检查文件是否存在
filePath := file.ParseUploadFilePath(row.Path)
if _, err := os.Stat(filePath); err != nil {
continue
}
os.Remove(filePath)
}
rows := r.neSoftwareRepository.DeleteByIds(ids)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// SelectByVersionAndPath 通过文件版本和路径查询
func (r *NeSoftwareImpl) SelectByVersionAndPath(version, path string) model.NeSoftware {
neSoftwares := r.neSoftwareRepository.SelectList(model.NeSoftware{
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件版本是否唯一
func (r *NeSoftwareImpl) CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool {
uniqueId := r.neSoftwareRepository.CheckUniqueTypeAndNameAndVersion(model.NeSoftware{
NeType: neType,
Name: name,
Version: version,
Path: path,
})
if len(neSoftwares) > 0 {
return neSoftwares[0]
}
return model.NeSoftware{}
}
// CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一
func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neType, fileName, version, id string) bool {
uniqueId := r.neSoftwareRepository.CheckUniqueTypeAndFileNameAndVersion(model.NeSoftware{
NeType: neType,
FileName: fileName,
Version: version,
})
if uniqueId == id {
return true
@@ -91,7 +124,20 @@ func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neType, fileName,
return uniqueId == ""
}
// Install 安装软件包
func (r *NeSoftwareImpl) Install(neSoftware model.NeSoftware) (string, error) {
return "", nil
// UpdateVersions 更新软件包对应网元的新版本
func (r *NeSoftwareImpl) UpdateVersions(neSoftware model.NeSoftware, neVersion model.NeVersion) int64 {
var rows int64 = 0
// 更新同类型的新包版本
neVersions := NewNeVersionImpl.SelectList(neVersion)
if len(neVersions) > 0 {
for _, v := range neVersions {
v.NewName = neSoftware.Name
v.NewVersion = neSoftware.Version
v.NewPath = neSoftware.Path
v.Status = "3"
v.UpdateBy = neVersion.UpdateBy
rows += NewNeVersionImpl.Update(v)
}
}
return rows
}

View File

@@ -22,9 +22,11 @@ type INeVersion interface {
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) (int64, error)
// SelectByTypeAndID 通过网元类型和网元ID查询
SelectByTypeAndID(neType, neId string) model.NeVersion
// SelectByNeTypeAndNeID 通过网元类型和网元ID查询
SelectByNeTypeAndNeID(neType, neId string) model.NeVersion
// CheckUniqueTypeAndID 校验网元类型和网元ID是否唯一
CheckUniqueTypeAndID(neType, neId, id string) bool
// Operate 操作版本上传到网元主机执行命令
//
// action 安装行为install upgrade rollback
Operate(action string, neVersion model.NeVersion, preinput map[string]string) (string, error)
}

View File

@@ -2,7 +2,14 @@ package service
import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
"nms_cxy/src/framework/logger"
"nms_cxy/src/framework/utils/file"
"nms_cxy/src/framework/utils/ssh"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_element/repository"
)
@@ -66,8 +73,8 @@ func (r *NeVersionImpl) DeleteByIds(ids []string) (int64, error) {
return 0, fmt.Errorf("delete fail")
}
// SelectByTypeAndID 通过网元类型和网元ID查询
func (r *NeVersionImpl) SelectByTypeAndID(neType, neId string) model.NeVersion {
// SelectByNeTypeAndNeID 通过网元类型和网元ID查询
func (r *NeVersionImpl) SelectByNeTypeAndNeID(neType, neId string) model.NeVersion {
neVersions := r.neVersionRepository.SelectList(model.NeVersion{
NeType: neType,
NeId: neId,
@@ -78,14 +85,561 @@ func (r *NeVersionImpl) SelectByTypeAndID(neType, neId string) model.NeVersion {
return model.NeVersion{}
}
// CheckUniqueTypeAndID 校验网元类型和网元ID是否唯一
func (r *NeVersionImpl) CheckUniqueTypeAndID(neType, neId, id string) bool {
uniqueId := r.neVersionRepository.CheckUniqueTypeAndID(model.NeVersion{
NeType: neType,
NeId: neId,
})
if uniqueId == id {
return true
// Operate 操作版本上传到网元主机执行命令
//
// action 安装行为install upgrade rollback
func (r *NeVersionImpl) Operate(action string, neVersion model.NeVersion, preinput map[string]string) (string, error) {
// 网元主机的SSH客户端
sshClient, err := NewNeInfoImpl.NeRunSSHClient(neVersion.NeType, neVersion.NeId)
if err != nil {
return "", err
}
return uniqueId == ""
defer sshClient.Close()
// ========= 文件传输阶段 =========
softwarePath := neVersion.Path
if action == "install" || action == "upgrade" {
softwarePath = neVersion.NewPath
}
if action == "rollback" {
softwarePath = neVersion.PrePath
}
neFilePaths, err := r.operateFile(sshClient, softwarePath)
if err != nil {
return "", err
}
// ========= 安装时设置 =========
if action == "install" {
// 网元公共配置文件
para5GMap, err := NewNeInfoImpl.NeConfPara5GRead()
if para5GMap == nil || err != nil {
return "", fmt.Errorf("error read para5G file info")
}
if err := NewNeInfoImpl.NeConfPara5GWirte(para5GMap, []string{fmt.Sprintf("%s@%s", neVersion.NeType, neVersion.NeId)}); err != nil {
return "", fmt.Errorf("error wirte para5G file info")
}
}
// ========= 命令生成阶段 =========
okFlagStr, cmdStrArr, err := r.operateCommand(action, neVersion.NeType, neFilePaths)
if err != nil {
return "", err
}
// ========= 执行阶段 =========
commandLine, err := r.operateRun(sshClient, preinput, cmdStrArr, neVersion.NeType, okFlagStr)
if err != nil {
return "", err
}
// ========= 完成阶段 =========
if strings.LastIndex(commandLine, okFlagStr) > 5 {
if err := r.operateDome(action, neVersion); err != nil {
return "", err
}
}
return commandLine, nil
}
// operateDome 操作版本-文件传输阶段
func (r *NeVersionImpl) operateFile(sshClient *ssh.ConnSSH, softwarePath string) ([]string, error) {
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return nil, err
}
defer sftpClient.Close()
nePath := "/tmp"
copyFileToNeMap := map[string]string{}
// 统一处理多个文件和单个文件的情况
var softwarePaths []string
if strings.Contains(softwarePath, ",") {
softwarePaths = strings.Split(softwarePath, ",")
} else {
softwarePaths = []string{softwarePath}
}
for _, path := range softwarePaths {
// 检查文件是否存在
localFilePath := file.ParseUploadFilePath(path)
if _, err := os.Stat(localFilePath); err != nil {
return nil, fmt.Errorf("file read failure")
}
fileName := filepath.Base(path)
neFilePath := fmt.Sprintf("%s/%s", nePath, fileName)
copyFileToNeMap[localFilePath] = neFilePath
}
// 上传软件包到 /tmp
neFilePaths := []string{}
for k, v := range copyFileToNeMap {
if err = sftpClient.CopyFileLocalToRemote(k, v); err != nil {
return nil, fmt.Errorf("error uploading package")
}
neFilePaths = append(neFilePaths, v)
}
return neFilePaths, nil
}
// operateDome 操作版本-命令生成阶段
func (r *NeVersionImpl) operateCommand(action, neType string, neFilePaths []string) (string, []string, error) {
neTypeLower := strings.ToLower(neType)
// 命令终止结束标记
okFlagStr := fmt.Sprintf("%s version %s successful!", neTypeLower, action)
// 安装软件包
pkgCmdStr := fmt.Sprintf("sudo dpkg -i %s", strings.Join(neFilePaths, " "))
fileExt := filepath.Ext(strings.ToLower(neFilePaths[0]))
if strings.HasSuffix(fileExt, "rpm") {
pkgCmdStr = fmt.Sprintf("sudo rpm -Uvh %s", strings.Join(neFilePaths, " "))
}
// 组合命令输入
cmdStrArr := []string{}
if neType == "OMC" {
omcStrArr := []string{}
omcStrArr = append(omcStrArr, pkgCmdStr)
if action == "install" {
omcStrArr = append(omcStrArr, "sudo /usr/local/omc/bin/setomc.sh -m install") // 初始化数据库
} else {
omcStrArr = append(omcStrArr, "sudo /usr/local/omc/bin/setomc.sh -m upgrade") // 升级数据库
}
omcStrArr = append(omcStrArr, "sudo systemctl restart restagent") // 重启服务
omcStrArr = append(omcStrArr, fmt.Sprintf("sudo rm %s", strings.Join(neFilePaths, " "))) // 删除软件包
// 2s后安装
cmdStrArr = append(cmdStrArr, fmt.Sprintf("nohup sh -c \"sleep 2s && %s\" > /dev/null 2>&1 & \n", strings.Join(omcStrArr, " && ")))
// 结束
cmdStrArr = append(cmdStrArr, fmt.Sprintf("echo '%s' \n", okFlagStr))
return okFlagStr, cmdStrArr, nil
} else if neType == "IMS" {
if action == "install" {
para5GData := NewNeInfoImpl.Para5GData
cmdStrArr = append(cmdStrArr, pkgCmdStr+" \n")
// 公网 PLMN地址
cmdStrArr = append(cmdStrArr, fmt.Sprintf("/usr/local/etc/ims/default/tools/modipplmn.sh %s %s %s \n", para5GData["SIP_IP"], para5GData["MCC"], para5GData["MNC"]))
// 内网 服务地址
cmdStrArr = append(cmdStrArr, fmt.Sprintf("/usr/local/etc/ims/default/tools/modintraip.sh %s \n", para5GData["IMS_IP"]))
// IWF连接PCF服务
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.160/%s/g\" /usr/local/etc/iwf/iwf_conf.yaml \n", para5GData["PCF_IP"]))
// 设置 HOST
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s ims' /etc/hosts || echo '%s ims' | sudo tee -a /etc/hosts \n", para5GData["IMS_IP"], para5GData["IMS_IP"]))
mnc_mcc := fmt.Sprintf("mnc%s.mcc%s", para5GData["MNC_DOMAIN"], para5GData["MCC"])
hssHost := fmt.Sprintf("%s hss.ims.%s.3gppnetwork.org hss", para5GData["UDM_IP"], mnc_mcc)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", hssHost, hssHost))
pcrfHost := fmt.Sprintf("%s pcrf.epc.%s.3gppnetwork.org pcrf", para5GData["IMS_IP"], mnc_mcc)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", pcrfHost, pcrfHost))
imsOrgHost := fmt.Sprintf("ims.%s.3gppnetwork.org", mnc_mcc)
imsHost := fmt.Sprintf("%s %s ims", para5GData["SIP_IP"], imsOrgHost)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", imsHost, imsHost))
pcscfHost := fmt.Sprintf("%s pcscf.%s pcscf", para5GData["SIP_IP"], imsOrgHost)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", pcscfHost, pcscfHost))
icscfHost := fmt.Sprintf("%s icscf.%s icscf", para5GData["SIP_IP"], imsOrgHost)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", icscfHost, icscfHost))
scscfHost := fmt.Sprintf("%s scscf.%s scscf", para5GData["SIP_IP"], imsOrgHost)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", scscfHost, scscfHost))
mmtelHost := fmt.Sprintf("%s mmtel.%s mmtel", para5GData["SIP_IP"], imsOrgHost)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", mmtelHost, mmtelHost))
mrfcHost := fmt.Sprintf("%s mrfc.%s mrfc", para5GData["SIP_IP"], imsOrgHost)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", mrfcHost, mrfcHost))
smsHost := fmt.Sprintf("%s smsc.%s smsc", para5GData["SIP_IP"], imsOrgHost)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", smsHost, smsHost))
cmdStrArr = append(cmdStrArr, "ims-stop || true && ims-start \n")
// 30s后停止服务
// cmdStrArr = append(cmdStrArr, "nohup sh -c \"sleep 30s && sudo ims-stop\" > /dev/null 2>&1 & \n")
} else {
cmdStrArr = append(cmdStrArr, "ims-stop \n")
cmdStrArr = append(cmdStrArr, pkgCmdStr+" \n")
cmdStrArr = append(cmdStrArr, "ims-start \n")
}
} else {
if action == "install" {
para5GData := NewNeInfoImpl.Para5GData
cmdStrArr = append(cmdStrArr, pkgCmdStr+" \n")
// AMF配置修改
if neTypeLower == "amf" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/amf/default/amfcfg.yaml /usr/local/etc/amf/amfcfg.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.120/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["AMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.120/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["N2_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mcc: 001/mcc: %s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc: 01/mnc: %s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/sst: 1/sst: %s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["SST"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/sd: 000001/sd: %s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["SD"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/- 4388/- %s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["TAC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.130/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["AUSF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.140/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["UDM_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.150/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["SMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.160/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["PCF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.180/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["NRF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.200/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["LMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.210/%s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["NEF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/- internet/- %s/g\" /usr/local/etc/amf/amfcfg.yaml \n", para5GData["DNN_DATA"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s n2' /etc/hosts || echo '%s n2' | sudo tee -a /etc/hosts \n", para5GData["N2_IP"], para5GData["N2_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s amf' /etc/hosts || echo '%s amf' | sudo tee -a /etc/hosts \n", para5GData["AMF_IP"], para5GData["AMF_IP"]))
}
// AUSF配置修改
if neTypeLower == "ausf" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/ausf/default/ausfcfg.yaml /usr/local/etc/ausf/ausfcfg.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.130/%s/g\" /usr/local/etc/ausf/ausfcfg.yaml \n", para5GData["AUSF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.140/%s/g\" /usr/local/etc/ausf/ausfcfg.yaml \n", para5GData["UDM_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.180/%s/g\" /usr/local/etc/ausf/ausfcfg.yaml \n", para5GData["NRF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mcc: 001/mcc: %s/g\" /usr/local/etc/ausf/ausfcfg.yaml \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc: 01/mnc: %s/g\" /usr/local/etc/ausf/ausfcfg.yaml \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s ausf' /etc/hosts || echo '%s ausf' | sudo tee -a /etc/hosts \n", para5GData["AUSF_IP"], para5GData["AUSF_IP"]))
}
// UDM配置修改
if neTypeLower == "udm" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/udm/default/udmcfg.yaml /usr/local/etc/udm/udmcfg.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/udm/default/nssai.yaml /usr/local/etc/udm/nssai.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/udm/default/snssai.yaml /usr/local/etc/udm/snssai.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/udm/default/as.yaml /usr/local/etc/udm/as.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/udm/default/dnn.yaml /usr/local/etc/udm/dnn.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/udm/default/scscfSet.yaml /usr/local/etc/udm/scscfSet.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.180/%s/g\" /usr/local/etc/udm/udmcfg.yaml \n", para5GData["NRF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.140/%s/g\" /usr/local/etc/udm/udmcfg.yaml \n", para5GData["UDM_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.130/%s/g\" /usr/local/etc/udm/udmcfg.yaml \n", para5GData["AUSF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.120/%s/g\" /usr/local/etc/udm/udmcfg.yaml \n", para5GData["AMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mcc: 001/mcc: %s/g\" /usr/local/etc/udm/udmcfg.yaml \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc: 01/mnc: %s/g\" /usr/local/etc/udm/udmcfg.yaml \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc001.mcc001/mnc%s.mcc%s/g\" /usr/local/etc/udm/udmcfg.yaml \n", para5GData["MNC_DOMAIN"], para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc001.mcc001/mnc%s.mcc%s/g\" /usr/local/etc/udm/as.yaml \n", para5GData["MNC_DOMAIN"], para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc001.mcc001/mnc%s.mcc%s/g\" /usr/local/etc/udm/scscfSet.yaml \n", para5GData["MNC_DOMAIN"], para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/sst: 1/sst: %s/g\" /usr/local/etc/udm/nssai.yaml \n", para5GData["SST"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/sst: 1/sst: %s/g\" /usr/local/etc/udm/snssai.yaml \n", para5GData["SST"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/sd: 000001/sd: %s/g\" /usr/local/etc/udm/nssai.yaml \n", para5GData["SD"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/sd: 000001/sd: %s/g\" /usr/local/etc/udm/snssai.yaml \n", para5GData["SD"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/dnn: internet/dnn: %s/g\" /usr/local/etc/udm/snssai.yaml \n", para5GData["DNN_DATA"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/dnn: ims/dnn: %s/g\" /usr/local/etc/udm/snssai.yaml \n", para5GData["DNN_IMS"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/serviceSelection: 'internet'/serviceSelection: '%s'/g\" /usr/local/etc/udm/epsApn.yaml \n", para5GData["DNN_DATA"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/serviceSelection: 'ims'/serviceSelection: '%s'/g\" /usr/local/etc/udm/epsApn.yaml \n", para5GData["DNN_IMS"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/dnn: internet/dnn: %s/g\" /usr/local/etc/udm/dnn.yaml \n", para5GData["DNN_DATA"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/dnn: ims/dnn: %s/g\" /usr/local/etc/udm/dnn.yaml \n", para5GData["DNN_IMS"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.110/%s/g\" /usr/local/etc/udm/as.yaml \n", para5GData["SIP_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s udm' /etc/hosts || echo '%s udm' | sudo tee -a /etc/hosts \n", para5GData["UDM_IP"], para5GData["UDM_IP"]))
}
// SMF配置修改
if neTypeLower == "smf" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/smf/default/smf_conf.yaml /usr/local/etc/smf/smf_conf.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.110/%s/g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["SIP_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.120/%s/g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["AMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.140/%s/g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["UDM_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.150/%s/g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["SMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.160/%s/g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["PCF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.180/%s/g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["NRF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.190/%s/g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["UPF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s|10.2.1.0/24|%s|g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["UE_POOL"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/internet/%s/g\" /usr/local/etc/smf/smf_conf.yaml \n", para5GData["DNN_DATA"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s smf' /etc/hosts || echo '%s smf' | sudo tee -a /etc/hosts \n", para5GData["SMF_IP"], para5GData["SMF_IP"]))
}
// PCF配置修改
if neTypeLower == "pcf" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/pcf/default/pcfcfg.yaml /usr/local/etc/pcf/pcfcfg.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.120/%s/g\" /usr/local/etc/pcf/pcfcfg.yaml \n", para5GData["AMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.140/%s/g\" /usr/local/etc/pcf/pcfcfg.yaml \n", para5GData["UDM_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.160/%s/g\" /usr/local/etc/pcf/pcfcfg.yaml \n", para5GData["PCF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.180/%s/g\" /usr/local/etc/pcf/pcfcfg.yaml \n", para5GData["NRF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.210/%s/g\" /usr/local/etc/pcf/pcfcfg.yaml \n", para5GData["NEF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mcc: 001/mcc: %s/g\" /usr/local/etc/pcf/pcfcfg.yaml \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc: 01/mnc: %s/g\" /usr/local/etc/pcf/pcfcfg.yaml \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc001.mcc001/mnc%s.mcc%s/g\" /usr/local/etc/pcf/pcfcfg.yaml \n", para5GData["MNC_DOMAIN"], para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s pcf' /etc/hosts || echo '%s pcf' | sudo tee -a /etc/hosts \n", para5GData["PCF_IP"], para5GData["PCF_IP"]))
}
// NSSF配置修改
if neTypeLower == "nssf" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/nssf/default/nssfcfg.yaml /usr/local/etc/nssf/nssfcfg.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.170/%s/g\" /usr/local/etc/nssf/nssfcfg.yaml \n", para5GData["NSSF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.180/%s/g\" /usr/local/etc/nssf/nssfcfg.yaml \n", para5GData["NRF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mcc: 001/mcc: %s/g\" /usr/local/etc/nssf/nssfcfg.yaml \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc: 01/mnc: %s/g\" /usr/local/etc/nssf/nssfcfg.yaml \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s nssf' /etc/hosts || echo '%s nssf' | sudo tee -a /etc/hosts \n", para5GData["NSSF_IP"], para5GData["NSSF_IP"]))
}
// NRF配置修改
if neTypeLower == "nrf" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/nrf/default/nrfcfg.yaml /usr/local/etc/nrf/nrfcfg.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.180/%s/g\" /usr/local/etc/nrf/nrfcfg.yaml \n", para5GData["NRF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mcc: 001/mcc: %s/g\" /usr/local/etc/nrf/nrfcfg.yaml \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc: 01/mnc: %s/g\" /usr/local/etc/nrf/nrfcfg.yaml \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s nrf' /etc/hosts || echo '%s nrf' | sudo tee -a /etc/hosts \n", para5GData["NRF_IP"], para5GData["NRF_IP"]))
}
// UPF配置修改
if neTypeLower == "upf" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/upf/default/upfcfg.yaml /usr/local/etc/upf/upfcfg.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/upf/default/upfForwarder_1.yaml /usr/local/etc/upf/upfForwarder_1.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.190/%s/g\" /usr/local/etc/upf/upfcfg.yaml \n", para5GData["UPF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/localhost/%s/g\" /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["UPF_IP"]))
// UE
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N6\"/,/ueIpv4: 10.2.1.0/s/ueIpv4: 10.2.1.0/ueIpv4: %s/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["UE_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N6\"/,/ueIpv4Mask: 255.255.255.0/s/ueIpv4Mask: 255.255.255.0/ueIpv4Mask: %s/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["UE_MASK"]))
// N3
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.190/%s/g\" /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N3_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N3\"/,/ipv4Mask: 255.255.240.0/s/ipv4Mask: 255.255.240.0/ipv4Mask: %s/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N3_MASK"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N3\"/,/gatewayIpv4: 192.168.1.254/s/gatewayIpv4: 192.168.1.254/gatewayIpv4: %s/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N3_GW"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N3\"/,/interfacePCI: \"0000:00:00.0\"/s/interfacePCI: \"0000:00:00.0\"/interfacePCI: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N3_PCI"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N3\"/,/macAddr: \"00:00:00:00:00:00\"/s/macAddr: \"00:00:00:00:00:00\"/macAddr: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N3_MAC"]))
// 标准版 N6
if para5GData["UPF_TYPE"] == "StandardUPF" {
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.191/%s/g\" /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N6_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N6\"/,/ipv4Mask: 255.255.240.0/s/ipv4Mask: 255.255.240.0/ipv4Mask: %s/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N6_MASK"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N6\"/,/gatewayIpv4: 192.168.1.254/s/gatewayIpv4: 192.168.1.254/gatewayIpv4: %s/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N6_GW"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N6\"/,/interfacePCI: \"0000:00:00.0\"/s/interfacePCI: \"0000:00:00.0\"/interfacePCI: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N6_PCI"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N6\"/,/macAddr: \"00:00:00:00:00:00\"/s/macAddr: \"00:00:00:00:00:00\"/macAddr: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N6_MAC"]))
// 路由
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo ip route add '%s/%s' via '%s' \n", para5GData["UE_IP"], para5GData["UE_CIDR"], para5GData["N6_IP"]))
}
// 轻量版
if para5GData["UPF_TYPE"] == "LightUPF" {
cmdStrArr = append(cmdStrArr, "sudo sed -i \"s/192.168.8.191/0.0.0.0/g\" /usr/local/etc/upf/upfForwarder_1.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo sed -i \"s/type: upfd/type: tun/g\" /usr/local/etc/upf/upfForwarder_1.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo sed -i 's/driverType: vmxnet3/driverType: \"\"/g' /usr/local/etc/upf/upfForwarder_1.yaml \n")
}
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s upf' /etc/hosts || echo '%s upf' | sudo tee -a /etc/hosts \n", para5GData["UPF_IP"], para5GData["UPF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s upfn3' /etc/hosts || echo '%s upfn3' | sudo tee -a /etc/hosts \n", para5GData["N3_IP"], para5GData["N3_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s upfn6' /etc/hosts || echo '%s upfn6' | sudo tee -a /etc/hosts \n", para5GData["N6_IP"], para5GData["N6_IP"]))
}
// LMF配置修改 - 已不再维护导致激活License失败
// NEF配置修改 - SNMP无需License
if neTypeLower == "nef" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/nef/default/nef_conf.yaml /usr/local/etc/nef/nef_conf.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.110/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["IMS_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.120/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["AMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.130/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["AUSF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.140/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["UDM_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.150/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["SMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.160/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["PCF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.170/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["NSSF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.180/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["NRF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.190/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["UPF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.210/%s/g\" /usr/local/etc/nef/nef_conf.yaml \n", para5GData["NEF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s nef' /etc/hosts || echo '%s nef' | sudo tee -a /etc/hosts \n", para5GData["NEF_IP"], para5GData["NEF_IP"]))
}
// MME配置修改 - 4G
if neTypeLower == "mme" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/mme/default/mme.conf /usr/local/etc/mme/mme.conf \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.120/%s/g\" /usr/local/etc/mme/mme.conf \n", para5GData["AMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/172.16.5.150/%s/g\" /usr/local/etc/mme/mme.conf \n", para5GData["SMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s|192.168.8.220/20|%s|g\" /usr/local/etc/mme/mme.conf \n", para5GData["S1_MMEIP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s|172.16.5.220/24|%s|g\" /usr/local/etc/mme/mme.conf \n", para5GData["S11_MMEIP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s|172.16.5.220|%s|g\" /usr/local/etc/mme/mme.conf \n", para5GData["MME_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s|172.16.5.221/24|%s|g\" /usr/local/etc/mme/mme.conf \n", para5GData["S10_MMEIP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/mnc001.mcc001/mnc%s.mcc%s/g\" /usr/local/etc/mme/mme.conf \n", para5GData["MNC_DOMAIN"], para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/\"00101\"/\"%s%s\"/g\" /usr/local/etc/mme/mme.conf \n", para5GData["MCC"], para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i 's/MCC=\"001\"/MCC=\"%s\"/g' /usr/local/etc/mme/mme.conf \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i 's/MCC = \"001\"/MCC = \"%s\"/g' /usr/local/etc/mme/mme.conf \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i 's/MNC=\"01\";/MNC=\"%s\";/g' /usr/local/etc/mme/mme.conf \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i 's/MNC = \"01\";/MNC = \"%s\";/g' /usr/local/etc/mme/mme.conf \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i 's/TAC = \"1\";/TAC = \"%s\";/g' /usr/local/etc/mme/mme.conf \n", para5GData["TAC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i 's/TAC = 1;/TAC = %s;/g' /usr/local/etc/mme/mme.conf \n", para5GData["TAC"]))
// SMF开启
cmdStrArr = append(cmdStrArr, "sudo sed -i \"/^ *gxcfg:/,/^ *[^ ]/{s/enable: false/enable: true/;b};\" /usr/local/etc/smf/smf_conf.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s mme' /etc/hosts || echo '%s mme' | sudo tee -a /etc/hosts \n", para5GData["MME_IP"], para5GData["MME_IP"]))
}
// N3IWF配置修改
if neTypeLower == "n3iwf" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/n3iwf/default/n3iwfcfg.yaml /usr/local/etc/n3iwf/n3iwfcfg.yaml \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/MCC: 001/MCC: %s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["MCC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/MNC: 01/MNC: %s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["MNC"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.12.161/%s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["N3IWF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.12.160/%s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["N3IWF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.27/%s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["UDM_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.1.239/%s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["SMF_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.22/%s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["N2_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.1.161/%s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["N3_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.1.160/%s/g\" /usr/local/etc/n3iwf/n3iwfcfg.yaml \n", para5GData["N6_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s n3iwf' /etc/hosts || echo '%s n3iwf' | sudo tee -a /etc/hosts \n", para5GData["N3IWF_IP"], para5GData["N3IWF_IP"]))
}
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo service %s restart \n", neTypeLower))
// 30s后停止服务
// cmdStrArr = append(cmdStrArr, fmt.Sprintf("nohup sh -c \"sleep 30s && sudo service %s stop\" > /dev/null 2>&1 & \n", neTypeLower))
} else {
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo service %s stop \n", neTypeLower))
cmdStrArr = append(cmdStrArr, pkgCmdStr+" \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo service %s restart \n", neTypeLower))
}
}
// 安装操作有redis安装时需要重启
if action == "install" && (neTypeLower == "ims" || neTypeLower == "udm") {
// adb
if strings.Contains(pkgCmdStr, "adb") {
para5GData := NewNeInfoImpl.Para5GData
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/adb/default/adb.conf /usr/local/etc/adb/adb.conf \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/bind 127.0.0.1/bind %s/g\" /usr/local/etc/adb/adb.conf \n", para5GData["DB_IP"]))
cmdStrArr = append(cmdStrArr, "sudo service adb restart \n")
}
// kvdb
if strings.Contains(pkgCmdStr, "kvdb") {
para5GData := NewNeInfoImpl.Para5GData
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/kvdb/default/kvdb.conf /usr/local/etc/kvdb/kvdb.conf \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/bind 127.0.0.1/bind %s/g\" /usr/local/etc/kvdb/kvdb.conf \n", para5GData["DB_IP"]))
cmdStrArr = append(cmdStrArr, "sudo service kvdb restart \n")
}
}
// 删除软件包
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo rm %s \n", strings.Join(neFilePaths, " ")))
// 结束
cmdStrArr = append(cmdStrArr, fmt.Sprintf("echo '%s' \n", okFlagStr))
return okFlagStr, cmdStrArr, nil
}
// operateDome 操作版本-执行阶段
func (r *NeVersionImpl) operateRun(sshClient *ssh.ConnSSH, preinput map[string]string, cmdStrArr []string, neType string, okFlagStr string) (string, error) {
// ssh连接会话
clientSession, err := sshClient.NewClientSession(127, 42)
if err != nil {
return "", fmt.Errorf("neinfo ssh client session new err")
}
defer clientSession.Close()
firstRead := true // 首次命令进行记录日志信息
commandLineText := "" // 日志信息
done := make(chan bool) // 完成信号
// 超时退出 120s
timeoutTicker := time.NewTicker(120 * time.Second)
defer timeoutTicker.Stop()
// 实时读取SSH消息直接输出
msTicker := time.NewTicker(100 * time.Millisecond)
defer msTicker.Stop()
go func() {
for {
select {
case <-timeoutTicker.C:
logger.Warnf("NeVersion operateRun %s", commandLineText)
logger.Errorf("neinfo ssh client session read timeout")
done <- true
return
case <-msTicker.C:
outputByte := clientSession.Read()
if len(outputByte) > 0 {
outputStr := string(outputByte)
// 非首次进行记录命令
if !firstRead {
commandLineText += outputStr
}
// IMS预输入
if neType == "IMS" {
// IMS包 P/I/S-CSCF Config 配置覆盖
if strings.Contains(outputStr, "(P/I/S-CSCF Config)? <y/n>") {
if pisCSCF, ok := preinput["pisCSCF"]; ok && pisCSCF != "" {
clientSession.Write(fmt.Sprintf("%s \n", pisCSCF))
} else {
clientSession.Write("y \n")
}
continue
}
// MF包 etc下目录覆盖
if strings.Contains(outputStr, "/usr/local/etc/mf directory? (Yes/No, default: No)") {
if pisCSCF, ok := preinput["updateMFetc"]; ok && pisCSCF != "" {
clientSession.Write(fmt.Sprintf("%s \n", pisCSCF))
} else {
clientSession.Write("No \n")
}
continue
}
// MF包 share下目录覆盖
if strings.Contains(outputStr, "/usr/local/share/mf directory? (Yes/No, default: No)") {
if pisCSCF, ok := preinput["updateMFshare"]; ok && pisCSCF != "" {
clientSession.Write(fmt.Sprintf("%s \n", pisCSCF))
} else {
clientSession.Write("No \n")
}
continue
}
}
// 命令终止符后继续执行命令
suffix := strings.HasSuffix(outputStr, "~]# ") || strings.HasSuffix(outputStr, "~$ ")
if len(cmdStrArr) > 0 && suffix {
if firstRead {
firstRead = false
}
shiftElement := cmdStrArr[0] // 获取第一个元素
cmdStrArr = cmdStrArr[1:] // 将第一个元素从切片中移除
clientSession.Write(shiftElement)
continue
}
// 最后输出的退出标记
if strings.LastIndex(outputStr, okFlagStr) > 5 {
done <- true
break
}
}
}
}
}()
// 等待写入协程完成
<-done
return commandLineText, nil
}
// operateDome 操作版本-完成阶段
func (r *NeVersionImpl) operateDome(action string, neVersion model.NeVersion) error {
if action == "install" {
// 网元信息
neInfo := NewNeInfoImpl.SelectNeInfoByNeTypeAndNeID(neVersion.NeType, neVersion.NeId)
if neInfo.NeId != neVersion.NeId {
return fmt.Errorf("error found neinfo")
}
// ========= 网元OAM配置文件 start ==========
if err := NewNeInfoImpl.NeConfOAMSync(neInfo, nil, true); err != nil {
return fmt.Errorf("error wirte OAM file info")
}
// ========= 网元OAM配置文件 end ===========
}
// 更新Version
verInfo := r.SelectByNeTypeAndNeID(neVersion.NeType, neVersion.NeId)
if verInfo.NeId == neVersion.NeId {
curName := verInfo.Name
curVersion := verInfo.Version
curPath := verInfo.Path
if action == "install" {
verInfo.Name = neVersion.NewName
verInfo.Version = neVersion.NewVersion
verInfo.Path = neVersion.NewPath
verInfo.PreName = "-"
verInfo.PreVersion = "-"
verInfo.PrePath = "-"
verInfo.NewName = "-"
verInfo.NewVersion = "-"
verInfo.NewPath = "-"
}
if action == "upgrade" {
verInfo.Name = neVersion.NewName
verInfo.Version = neVersion.NewVersion
verInfo.Path = neVersion.NewPath
verInfo.PreName = curName
verInfo.PreVersion = curVersion
verInfo.PrePath = curPath
verInfo.NewName = "-"
verInfo.NewVersion = "-"
verInfo.NewPath = "-"
}
if action == "rollback" {
verInfo.Name = neVersion.PreName
verInfo.Version = neVersion.PreVersion
verInfo.Path = neVersion.PrePath
verInfo.PreName = curName
verInfo.PreVersion = curVersion
verInfo.PrePath = curPath
}
verInfo.Status = "1"
NewNeVersionImpl.Update(verInfo)
}
return nil
}

View File

@@ -1,37 +0,0 @@
package service
import "nms_cxy/src/modules/network_element/model"
// UDM鉴权信息 服务层接口
type IUDMAuth interface {
// Save UDM鉴权用户-获取redis全部保存数据库
Save(neID string) int64
// Page UDM鉴权用户-分页查询数据库
Page(query map[string]any) map[string]any
// List UDM鉴权用户-查询数据库
List(authUser model.UDMAuth) []model.UDMAuth
// Insert UDM鉴权用户-新增单个
// imsi长度15ki长度32opc长度0或者32
Insert(neID string, authUser model.UDMAuth) int64
// Insert UDM鉴权用户-批量添加
Inserts(neID string, authUser model.UDMAuth, num string) int64
// InsertCSV UDM鉴权用户-批量添加
InsertCSV(neID string, data []map[string]string) int64
// InsertTxt UDM鉴权用户-批量添加
InsertTxt(neID string, data [][]string) int64
// Insert UDM鉴权用户-修改更新
Update(neID string, authUser model.UDMAuth) int64
// Insert UDM鉴权用户-删除单个
Delete(neID, imsi string) int64
// Insert UDM鉴权用户-删除范围
Deletes(neID, imsi, num string) int64
}

View File

@@ -1,179 +0,0 @@
package service
import (
"fmt"
"strings"
"nms_cxy/src/framework/redis"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_element/repository"
)
// 实例化服务层 UDMAuthImpl 结构体
var NewUDMAuthImpl = &UDMAuthImpl{
udmAuthRepository: repository.NewUDMAuthImpl,
}
// UDM鉴权信息 服务层处理
type UDMAuthImpl struct {
// UDM鉴权信息数据信息
udmAuthRepository repository.IUDMAuth
}
// authDataByRedis UDM鉴权用户
func (r *UDMAuthImpl) authDataByRedis(imsi, neID string) []model.UDMAuth {
arr := []model.UDMAuth{}
key := fmt.Sprintf("ausf:%s", imsi)
ausfArr, err := redis.GetKeys("udmuser", key)
if err != nil {
return arr
}
for _, key := range ausfArr {
m, err := redis.GetHash("udmuser", key)
if err != nil {
continue
}
// 跳过-号数据
imsi := key[5:]
if strings.Contains(imsi, "-") {
continue
}
status := "1" // 默认给1
amf := ""
if v, ok := m["amf"]; ok {
amf = strings.Replace(v, "\r\n", "", 1)
}
a := model.UDMAuth{
Imsi: imsi,
Amf: amf,
Status: status,
Ki: m["ki"],
AlgoIndex: m["algo"],
Opc: m["opc"],
NeID: neID,
}
arr = append(arr, a)
}
return arr
}
// Save UDM鉴权用户-获取redis全部保存数据库
func (r *UDMAuthImpl) Save(neID string) int64 {
authArr := r.authDataByRedis("*", neID)
// 数据清空后添加
go r.udmAuthRepository.ClearAndInsert(neID, authArr)
return int64(len(authArr))
}
// Page UDM鉴权用户-分页查询数据库
func (r *UDMAuthImpl) Page(query map[string]any) map[string]any {
return r.udmAuthRepository.SelectPage(query)
}
// List UDM鉴权用户-查询数据库
func (r *UDMAuthImpl) List(authUser model.UDMAuth) []model.UDMAuth {
return r.udmAuthRepository.SelectList(authUser)
}
// Insert UDM鉴权用户-新增单个
// imsi长度15ki长度32opc长度0或者32
func (r *UDMAuthImpl) Insert(neID string, authUser model.UDMAuth) int64 {
authArr := r.authDataByRedis(authUser.Imsi, neID)
if len(authArr) > 0 {
r.udmAuthRepository.Delete(neID, authUser.Imsi)
r.udmAuthRepository.Inserts(authArr)
}
return 0
}
// Insert UDM鉴权用户-批量添加
func (r *UDMAuthImpl) Inserts(neID string, authUser model.UDMAuth, num string) int64 {
startIMSI := authUser.Imsi
startIMSI = startIMSI[:len(startIMSI)-len(num)] + "*"
// keys udm-sd:4600001000004*
authArr := r.authDataByRedis(startIMSI, neID)
if len(authArr) > 0 {
for _, v := range authArr {
r.udmAuthRepository.Delete(neID, v.Imsi)
}
return r.udmAuthRepository.Inserts(authArr)
}
return 0
}
// InsertCSV UDM鉴权用户-批量添加
func (r *UDMAuthImpl) InsertCSV(neID string, data []map[string]string) int64 {
prefixes := make(map[string]struct{})
for _, v := range data {
imsi := v["imsi"]
if len(imsi) < 5 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
// 分组插入
var num int64 = 0
for prefix := range prefixes {
r.udmAuthRepository.DeletePrefixImsi(neID, prefix)
subArr := r.authDataByRedis(prefix+"*", neID)
if len(subArr) > 0 {
num += r.udmAuthRepository.Inserts(subArr)
}
}
return num
}
// InsertTxt UDM鉴权用户-批量添加
func (r *UDMAuthImpl) InsertTxt(neID string, data [][]string) int64 {
prefixes := make(map[string]struct{})
for _, v := range data {
imsi := v[0]
if len(imsi) < 5 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
// 分组插入
var num int64 = 0
for prefix := range prefixes {
r.udmAuthRepository.DeletePrefixImsi(neID, prefix)
subArr := r.authDataByRedis(prefix+"*", neID)
if len(subArr) > 0 {
num += r.udmAuthRepository.Inserts(subArr)
}
}
return num
}
// Insert UDM鉴权用户-修改更新
func (r *UDMAuthImpl) Update(neID string, authUser model.UDMAuth) int64 {
authArr := r.authDataByRedis(authUser.Imsi, neID)
if len(authArr) > 0 {
r.udmAuthRepository.Delete(neID, authUser.Imsi)
return r.udmAuthRepository.Inserts(authArr)
}
return 0
}
// Insert UDM鉴权用户-删除单个
func (r *UDMAuthImpl) Delete(neID, imsi string) int64 {
return r.udmAuthRepository.Delete(neID, imsi)
}
// Insert UDM鉴权用户-删除范围
func (r *UDMAuthImpl) Deletes(neID, imsi, num string) int64 {
prefix := imsi[:len(imsi)-len(num)-1]
// 直接删除前缀的记录
r.udmAuthRepository.DeletePrefixImsi(neID, prefix)
// keys ausf:4600001000004*
authArr := r.authDataByRedis(prefix+"*", neID)
if len(authArr) > 0 {
return r.udmAuthRepository.Inserts(authArr)
}
return 0
}

View File

@@ -1,37 +0,0 @@
package service
import "nms_cxy/src/modules/network_element/model"
// UDM签约用户信息 服务层接口
type IUDMSub interface {
// Save UDM签约用户-获取redis全部保存数据库
Save(neID string) int64
// Page UDM签约用户-分页查询数据库
Page(query map[string]any) map[string]any
// List UDM签约用户-查询数据库
List(subUser model.UDMSub) []model.UDMSub
// Insert UDM签约用户-新增单个
// imsi长度15ki长度32opc长度0或者32
Insert(neID string, subUser model.UDMSub) int64
// Insert UDM签约用户-批量添加
Inserts(neID string, subUser model.UDMSub, num string) int64
// InsertCSV UDM签约用户-批量添加
InsertCSV(neID string, data []map[string]string) int64
// InsertTxt UDM签约用户-批量添加
InsertTxt(neID string, data [][]string) int64
// Insert UDM签约用户-修改更新
Update(neID string, subUser model.UDMSub) int64
// Insert UDM签约用户-删除单个
Delete(neID, imsi string) int64
// Insert UDM签约用户-删除范围
Deletes(neID, imsi, num string) int64
}

View File

@@ -1,195 +0,0 @@
package service
import (
"fmt"
"strings"
"nms_cxy/src/framework/redis"
"nms_cxy/src/modules/network_element/model"
"nms_cxy/src/modules/network_element/repository"
)
// 实例化服务层 UDMSubImpl 结构体
var NewUDMSubImpl = &UDMSubImpl{
udmSubRepository: repository.NewUDMSubImpl,
}
// UDM签约信息 服务层处理
type UDMSubImpl struct {
// UDM签约信息数据信息
udmSubRepository repository.IUDMSub
}
// subDataByRedis UDM签约用户
func (r *UDMSubImpl) subDataByRedis(imsi, neID string) []model.UDMSub {
arr := []model.UDMSub{}
key := fmt.Sprintf("udm-sd:%s", imsi)
udmsdArr, err := redis.GetKeys("udmuser", key)
if err != nil {
return arr
}
for _, key := range udmsdArr {
m, err := redis.GetHash("udmuser", key)
if err != nil {
continue
}
a := model.UDMSub{
Imsi: key[7:],
Msisdn: m["gpsi"], // 46003550072 strings.TrimPrefix(m["gpsi"], "86"),
SmfSel: m["smf-sel"],
SmData: m["sm-dat"], // 1-000001&cmnet&ims&3gnet
NeID: neID,
}
// def_ambr,def_nssai,0,def_arfb,def_sar,3,1,12000,1,1000,0,1,-
if v, ok := m["am-dat"]; ok {
arr := strings.Split(v, ",")
a.Ambr = arr[0]
a.Nssai = arr[1]
a.Rat = arr[2]
a.Arfb = arr[3]
a.Sar = arr[4]
a.Cn = arr[5]
}
// 1,64,24,65,def_eps,1,2,010200000000,-
if v, ok := m["eps-dat"]; ok {
arr := strings.Split(v, ",")
// 跳过非常规数据
if len(arr) > 9 {
continue
}
a.EpsDat = v
a.EpsFlag = arr[0]
a.EpsOdb = arr[1]
a.HplmnOdb = arr[2]
a.Ard = arr[3]
a.Epstpl = arr[4]
a.ContextId = arr[5]
a.ApnContext = arr[7]
// [6] 是不要的,导入和导出不用
a.StaticIp = arr[8]
}
arr = append(arr, a)
}
return arr
}
// Save UDM签约用户-获取redis全部保存数据库
func (r *UDMSubImpl) Save(neID string) int64 {
subArr := r.subDataByRedis("*", neID)
// 数据清空后添加
go r.udmSubRepository.ClearAndInsert(neID, subArr)
return int64(len(subArr))
}
// Page UDM签约用户-分页查询数据库
func (r *UDMSubImpl) Page(query map[string]any) map[string]any {
return r.udmSubRepository.SelectPage(query)
}
// List UDM签约用户-查询数据库
func (r *UDMSubImpl) List(subUser model.UDMSub) []model.UDMSub {
return r.udmSubRepository.SelectList(subUser)
}
// Insert UDM签约用户-新增单个
// imsi长度15ki长度32opc长度0或者32
func (r *UDMSubImpl) Insert(neID string, subUser model.UDMSub) int64 {
authArr := r.subDataByRedis(subUser.Imsi, neID)
if len(authArr) > 0 {
r.udmSubRepository.Delete(neID, subUser.Imsi)
r.udmSubRepository.Inserts(authArr)
}
return 0
}
// Insert UDM签约用户-批量添加
func (r *UDMSubImpl) Inserts(neID string, subUser model.UDMSub, num string) int64 {
startIMSI := subUser.Imsi
startIMSI = startIMSI[:len(startIMSI)-len(num)] + "*"
// keys udm-sd:4600001000004*
subArr := r.subDataByRedis(startIMSI, neID)
if len(subArr) > 0 {
for _, v := range subArr {
r.udmSubRepository.Delete(neID, v.Imsi)
}
return r.udmSubRepository.Inserts(subArr)
}
return 0
}
// InsertCSV UDM签约用户-批量添加
func (r *UDMSubImpl) InsertCSV(neID string, data []map[string]string) int64 {
prefixes := make(map[string]struct{})
for _, v := range data {
imsi := v["imsi"]
if len(imsi) < 5 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
// 分组插入
var num int64 = 0
for prefix := range prefixes {
r.udmSubRepository.DeletePrefixImsi(neID, prefix)
subArr := r.subDataByRedis(prefix+"*", neID)
if len(subArr) > 0 {
num += r.udmSubRepository.Inserts(subArr)
}
}
return num
}
// InsertTxt UDM签约用户-批量添加
func (r *UDMSubImpl) InsertTxt(neID string, data [][]string) int64 {
prefixes := make(map[string]struct{})
for _, v := range data {
imsi := v[0]
if len(imsi) < 5 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
// 分组插入
var num int64 = 0
for prefix := range prefixes {
r.udmSubRepository.DeletePrefixImsi(neID, prefix)
subArr := r.subDataByRedis(prefix+"*", neID)
if len(subArr) > 0 {
num += r.udmSubRepository.Inserts(subArr)
}
}
return num
}
// Insert UDM签约用户-修改更新
func (r *UDMSubImpl) Update(neID string, subUser model.UDMSub) int64 {
authArr := r.subDataByRedis(subUser.Imsi, neID)
if len(authArr) > 0 {
r.udmSubRepository.Delete(neID, subUser.Imsi)
return r.udmSubRepository.Inserts(authArr)
}
return 0
}
// Insert UDM签约用户-删除单个
func (r *UDMSubImpl) Delete(neID, imsi string) int64 {
return r.udmSubRepository.Delete(neID, imsi)
}
// Insert UDM签约用户-删除范围
func (r *UDMSubImpl) Deletes(neID, imsi, num string) int64 {
prefix := imsi[:len(imsi)-len(num)-1]
// 直接删除前缀的记录
r.udmSubRepository.DeletePrefixImsi(neID, prefix)
// keys udm-sd:4600001000004*
authArr := r.subDataByRedis(prefix+"*", neID)
if len(authArr) > 0 {
return r.udmSubRepository.Inserts(authArr)
}
return 0
}

View File

@@ -35,12 +35,17 @@ type SysConfigController struct {
//
// GET /list
func (s *SysConfigController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
data := s.sysConfigService.SelectConfigPage(querys)
rows := data["rows"].([]model.SysConfig)
// 闭包函数处理多语言
language := ctx.AcceptLanguage(c)
querys := ctx.QueryMap(c)
// 多语言值转key查询
if v, ok := querys["configName"]; ok && v != "" {
querys["configName"] = i18n.TFindKeyPrefix(language, "config", v.(string))
}
data := s.sysConfigService.SelectConfigPage(querys)
rows := data["rows"].([]model.SysConfig)
// 闭包函数处理多语言
converI18n := func(language string, arr *[]model.SysConfig) {
for i := range *arr {
(*arr)[i].ConfigName = i18n.TKey(language, (*arr)[i].ConfigName)
@@ -222,8 +227,10 @@ func (s *SysConfigController) Export(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
querys := ctx.BodyJSONMap(c)
querys["pageNum"] = 1
querys["pageSize"] = 1000
data := s.sysConfigService.SelectConfigPage(querys)
if data["total"].(int64) == 0 {
if parse.Number(data["total"]) == 0 {
// 导出数据记录为空
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return

View File

@@ -35,13 +35,13 @@ func (s *SysDeptController) List(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
// 部门ID
DeptID string `json:"deptId"`
DeptID string `form:"deptId"`
// 父部门ID
ParentID string `json:"parentId" `
ParentID string `form:"parentId" `
// 部门名称
DeptName string `json:"deptName" `
DeptName string `form:"deptName" `
// 部门状态0正常 1停用
Status string `json:"status"`
Status string `form:"status"`
}
err := c.ShouldBindQuery(&querys)
if err != nil {
@@ -49,6 +49,11 @@ func (s *SysDeptController) List(c *gin.Context) {
return
}
// 多语言值转key查询
if querys.DeptName != "" {
querys.DeptName = i18n.TFindKeyPrefix(language, "dept", querys.DeptName)
}
SysDeptController := model.SysDept{
DeptID: querys.DeptID,
ParentID: querys.ParentID,

View File

@@ -241,14 +241,21 @@ func (s *SysDictDataController) DictType(c *gin.Context) {
func (s *SysDictDataController) Export(c *gin.Context) {
language := ctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
querys := ctx.BodyJSONMap(c)
data := s.sysDictDataService.SelectDictDataPage(querys)
if data["total"].(int64) == 0 {
// querys := ctx.BodyJSONMap(c)
// data := s.sysDictDataService.SelectDictDataPage(querys)
// if data["total"].(int64) == 0 {
// // 导出数据记录为空
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
// return
// }
// rows := data["rows"].([]model.SysDictData)
rows := s.sysDictDataService.SelectDictDataList(model.SysDictData{})
if len(rows) <= 0 {
// 导出数据记录为空
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
rows := data["rows"].([]model.SysDictData)
// 闭包函数处理多语言
converI18n := func(language string, arr *[]model.SysDictData) {
@@ -267,11 +274,10 @@ func (s *SysDictDataController) Export(c *gin.Context) {
// 第一行表头标题
headerCells := map[string]string{
"A1": i18n.TKey(language, "dictData.export.code"),
"B1": i18n.TKey(language, "dictData.export.sort"),
"C1": i18n.TKey(language, "dictData.export.label"),
"D1": i18n.TKey(language, "dictData.export.value"),
"E1": i18n.TKey(language, "dictData.export.type"),
"F1": i18n.TKey(language, "dictData.export.status"),
"B1": i18n.TKey(language, "dictData.export.label"),
"C1": i18n.TKey(language, "dictData.export.value"),
"D1": i18n.TKey(language, "dictData.export.sort"),
"E1": i18n.TKey(language, "dictData.export.status"),
}
// 从第二行开始的数据
dataCells := make([]map[string]any, 0)
@@ -283,11 +289,10 @@ func (s *SysDictDataController) Export(c *gin.Context) {
}
dataCells = append(dataCells, map[string]any{
"A" + idx: row.DictCode,
"B" + idx: row.DictSort,
"C" + idx: row.DictLabel,
"D" + idx: row.DictValue,
"E" + idx: row.DictType,
"F" + idx: statusValue,
"B" + idx: row.DictLabel,
"C" + idx: row.DictValue,
"D" + idx: row.DictSort,
"E" + idx: statusValue,
})
}

Some files were not shown because too many files have changed in this diff Show More