1
0

marge: 合并代码

This commit is contained in:
TsMask
2023-12-29 20:22:43 +08:00
parent 615ab2eb2e
commit 3c5c77b881
39 changed files with 1571 additions and 289 deletions

View File

@@ -3,7 +3,9 @@ package controller
import (
"ems.agt/src/framework/i18n"
"ems.agt/src/framework/utils/ctx"
"ems.agt/src/framework/utils/parse"
"ems.agt/src/framework/vo/result"
"ems.agt/src/modules/network_element/model"
neService "ems.agt/src/modules/network_element/service"
"github.com/gin-gonic/gin"
)
@@ -21,22 +23,86 @@ type NeInfoController struct {
neInfoService neService.INeInfo
}
// 网元状态
//
// GET /state
func (s *NeInfoController) NeState(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
}
// 网元直连
resData, err := neService.NeState(neInfo)
if err != nil {
c.JSON(200, result.ErrMsg("connection failure"))
return
}
c.JSON(200, result.OkData(resData))
}
// 网元neType和neID查询
//
// GET /info
func (s *NeInfoController) NeTypeAndID(c *gin.Context) {
language := ctx.AcceptLanguage(c)
neType := c.Query("neType")
neId := c.Query("neId")
if neType == "" || neId == "" {
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(neType, neId)
if neInfo.NeId != 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
}
c.JSON(200, result.OkData(neInfo))
}
// 网元列表
//
// GET /list
func (s *NeInfoController) NeList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType"`
NeId string `form:"neId"`
BandStatus string `form:"bandStatus"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询实体参数
ne := model.NeInfo{}
if querys.NeType != "" {
ne.NeType = querys.NeType
}
if querys.NeId != "" {
ne.NeId = querys.NeId
}
bandStatus := parse.Boolean(querys.BandStatus)
neList := s.neInfoService.SelectNeList(ne, bandStatus)
if len(neList) == 0 {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
c.JSON(200, result.OkData(neList))
}

View File

@@ -5,6 +5,7 @@ import (
"ems.agt/src/framework/i18n"
"ems.agt/src/framework/utils/ctx"
"ems.agt/src/framework/vo/result"
"ems.agt/src/modules/network_element/model"
neService "ems.agt/src/modules/network_element/service"
"github.com/gin-gonic/gin"
)
@@ -30,13 +31,7 @@ type PerfKPIController struct {
// GET /data
func (s *PerfKPIController) GoldKPI(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
StartTime string `form:"startTime" binding:"required"`
EndTime string `form:"endTime" binding:"required"`
Interval int64 `form:"interval" binding:"required"`
}
var querys model.GoldKPIQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
@@ -47,12 +42,10 @@ func (s *PerfKPIController) GoldKPI(c *gin.Context) {
if startTime.IsZero() {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
}
startTimeStr := startTime.Format(date.YYYY_MM_DD_HH_MM_SS)
endTime := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
if startTime.IsZero() {
if endTime.IsZero() {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
}
endTimeStr := endTime.Format(date.YYYY_MM_DD_HH_MM_SS)
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
@@ -60,16 +53,10 @@ func (s *PerfKPIController) GoldKPI(c *gin.Context) {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 获取数据指标id
var kpiIds []string
kpiTitles := s.perfKPIService.SelectGoldKPITitle(neInfo.NeType)
for _, kpiId := range kpiTitles {
kpiIds = append(kpiIds, kpiId.KPIID)
}
querys.RmUID = neInfo.RmUID
// 查询数据
kpiData := s.perfKPIService.SelectGoldKPI(neInfo.RmUID, neInfo.NeType, startTimeStr, endTimeStr, kpiIds, querys.Interval)
kpiData := s.perfKPIService.SelectGoldKPI(querys)
c.JSON(200, result.OkData(kpiData))
}

View File

@@ -11,6 +11,7 @@ import (
"ems.agt/src/framework/i18n"
"ems.agt/src/framework/utils/ctx"
"ems.agt/src/framework/utils/file"
"ems.agt/src/framework/utils/parse"
"ems.agt/src/framework/utils/ssh"
"ems.agt/src/framework/vo/result"
"ems.agt/src/modules/network_element/model"
@@ -89,6 +90,11 @@ func (s *UDMAuthController) Info(c *gin.Context) {
return
}
if len(data) == 0 {
c.JSON(200, result.ErrMsg("No Auth Data"))
return
}
// 查询数据库是否存在并存入
neId = ""
var userInfo model.UDMAuth
@@ -265,6 +271,14 @@ func (s *UDMAuthController) Remove(c *gin.Context) {
return
}
// 处理字符转id数组后去重
imsiArr := strings.Split(imsi, ",")
uniqueIDs := parse.RemoveDuplicates(imsiArr)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
@@ -272,21 +286,24 @@ func (s *UDMAuthController) Remove(c *gin.Context) {
return
}
msg := fmt.Sprintf("del authdat:imsi=%s", imsi)
resultData := map[string]string{}
for _, imsi := range uniqueIDs {
msg := fmt.Sprintf("del authdat:imsi=%s", imsi)
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
if err != nil {
resultData[imsi] = err.Error()
}
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmAuthService.Delete(neId, imsi)
resultData[imsi] = data
}
}
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmAuthService.Delete(neId, imsi)
}
c.JSON(200, result.OkData(data))
c.JSON(200, result.OkData(resultData))
}
// UDM鉴权用户-批量删除
@@ -342,7 +359,7 @@ func (s *UDMAuthController) Export(c *gin.Context) {
}
if !(body.Type == "csv" || body.Type == "txt") {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportFileFormat")))
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserAuthFileFormat")))
return
}

View File

@@ -12,6 +12,7 @@ import (
"ems.agt/src/framework/i18n"
"ems.agt/src/framework/utils/ctx"
"ems.agt/src/framework/utils/file"
"ems.agt/src/framework/utils/parse"
"ems.agt/src/framework/utils/ssh"
"ems.agt/src/framework/vo/result"
"ems.agt/src/modules/network_element/model"
@@ -90,6 +91,11 @@ func (s *UDMSubController) Info(c *gin.Context) {
return
}
if len(data) == 0 {
c.JSON(200, result.ErrMsg("No Subs Data"))
return
}
// 解析返回的数据
cnType, _ := strconv.ParseInt(data["CNType"][:4], 0, 64)
rat, _ := strconv.ParseInt(data["RAT"][:4], 0, 64)
@@ -341,6 +347,14 @@ func (s *UDMSubController) Remove(c *gin.Context) {
return
}
// 处理字符转id数组后去重
imsiArr := strings.Split(imsi, ",")
uniqueIDs := parse.RemoveDuplicates(imsiArr)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
@@ -348,21 +362,24 @@ func (s *UDMSubController) Remove(c *gin.Context) {
return
}
msg := fmt.Sprintf("del udmuser:imsi=%s", imsi)
resultData := map[string]string{}
for _, imsi := range uniqueIDs {
msg := fmt.Sprintf("del udmuser:imsi=%s", imsi)
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
// 发送MML
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
if err != nil {
resultData[imsi] = err.Error()
}
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmSubService.Delete(neId, imsi)
resultData[imsi] = data
}
}
// 命令ok时
if strings.Contains(data, "ok") {
neId = ""
s.udmSubService.Delete(neId, imsi)
}
c.JSON(200, result.OkData(data))
c.JSON(200, result.OkData(resultData))
}
// UDM签约用户-批量删除
@@ -418,7 +435,7 @@ func (s *UDMSubController) Export(c *gin.Context) {
}
if !(body.Type == "csv" || body.Type == "txt") {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportFileFormat")))
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
return
}

View File

@@ -16,4 +16,9 @@ type NeInfo struct {
NeAddress string `json:"neAddress"`
Status string `json:"status"` // 0: 在线 1: 下线 2: 备用 3: 工程
UpdateTime string `json:"updateTime"`
// ====== 非数据库字段属性 ======
// 服务状态
ServerState map[string]any `json:"serverState,omitempty"`
}

View File

@@ -9,3 +9,15 @@ type GoldKPITitle struct {
CnTitle string `json:"cnTitle" gorm:"column:cn_title"`
EnTitle string `json:"enTitle" gorm:"column:en_title"`
}
// GoldKPIQuery 黄金指标查询参数结构体
type GoldKPIQuery struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
StartTime string `form:"startTime" binding:"required"`
EndTime string `form:"endTime" binding:"required"`
Interval int64 `form:"interval" binding:"required"`
RmUID string `form:"rmUID"`
SortField string `form:"sortField" binding:"omitempty,oneof=timeGroup"`
SortOrder string `form:"sortOrder" binding:"omitempty,oneof=asc desc"`
}

View File

@@ -20,6 +20,14 @@ func Setup(router *gin.Engine) {
middleware.PreAuthorize(nil),
controller.NewNeInfo.NeTypeAndID,
)
neGroup.GET("/state",
middleware.PreAuthorize(nil),
controller.NewNeInfo.NeState,
)
neGroup.GET("/list",
middleware.PreAuthorize(nil),
controller.NewNeInfo.NeList,
)
}
// 网元处理

View File

@@ -8,4 +8,7 @@ import (
type INeInfo interface {
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo
// SelectNeList 查询网元列表
SelectNeList(ne model.NeInfo) []model.NeInfo
}

View File

@@ -1,12 +1,33 @@
package repository
import (
"sort"
"strings"
"ems.agt/src/framework/datasource"
"ems.agt/src/framework/logger"
"ems.agt/src/framework/utils/repo"
"ems.agt/src/modules/network_element/model"
)
// neListSort 网元列表预设排序
var neListSort = []string{
"OMC",
"MME",
"AMF",
"AUSF",
"UDM",
"SMF",
"PCF",
"UPF",
"NRF",
"NSSF",
"IMS",
"N3IWF",
"NEF",
"LMF",
}
// 实例化数据层 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 from ne_info`,
@@ -49,6 +70,31 @@ func (r *NeInfoImpl) convertResultRows(rows []map[string]any) []model.NeInfo {
}
arr = append(arr, item)
}
// 排序
sort.Slice(arr, func(i, j int) bool {
// 前一个
after := arr[i]
afterIndex := 0
for i, v := range neListSort {
if after.NeType == v {
afterIndex = i
break
}
}
// 后一个
befter := arr[j]
befterIndex := 0
for i, v := range neListSort {
if befter.NeType == v {
befterIndex = i
break
}
}
// 升序
return afterIndex < befterIndex
})
return arr
}
@@ -67,3 +113,34 @@ func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeIn
}
return model.NeInfo{}
}
// SelectNeList 查询网元列表
func (r *NeInfoImpl) SelectNeList(ne model.NeInfo) []model.NeInfo {
// 查询条件拼接
var conditions []string
var params []any
if ne.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, ne.NeType)
}
if ne.NeId != "" {
conditions = append(conditions, "ne_id = ?")
params = append(params, ne.NeId)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
// 查询数据
querySql := r.selectSql + whereSql + " order by ne_type asc "
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
// 转换实体
return r.convertResultRows(results)
}

View File

@@ -4,8 +4,8 @@ import "ems.agt/src/modules/network_element/model"
// 性能统计 数据层接口
type IPerfKPI interface {
// SelectGoldKPI 通过ne_type和ne_id查询网元信息
SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any
// SelectGoldKPI 通过网元指标数据信息
SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any
// SelectGoldKPITitle
SelectGoldKPITitle(neType string) []model.GoldKPITitle

View File

@@ -16,25 +16,25 @@ var NewPerfKPIImpl = &PerfKPIImpl{}
type PerfKPIImpl struct{}
// SelectGoldKPI 通过网元指标数据信息
func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any {
func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if rmUID != "" {
if query.RmUID != "" {
conditions = append(conditions, "gk.rm_uid = ?")
params = append(params, rmUID)
params = append(params, query.RmUID)
}
if neType != "" {
if query.NeType != "" {
conditions = append(conditions, "gk.ne_type = ?")
params = append(params, neType)
params = append(params, query.NeType)
}
if startTime != "" {
if query.StartTime != "" {
conditions = append(conditions, "gk.start_time >= ?")
params = append(params, startTime)
params = append(params, query.StartTime)
}
if endTime != "" {
if query.EndTime != "" {
conditions = append(conditions, "gk.start_time <= ?")
params = append(params, endTime)
params = append(params, query.EndTime)
}
// 构建查询条件语句
whereSql := ""
@@ -44,7 +44,7 @@ func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime str
// 查询字段列
timeFormat := "DATE_FORMAT(gk.start_time, '%Y-%m-%d %H:')"
minuteGroup := fmt.Sprintf("LPAD(FLOOR(MINUTE(gk.start_time) / %d) * %d, 2, '0')", interval, interval)
minuteGroup := fmt.Sprintf("LPAD(FLOOR(MINUTE(gk.start_time) / %d) * %d, 2, '0')", query.Interval, query.Interval)
groupByField := fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, minuteGroup)
var fields = []string{
groupByField,
@@ -58,7 +58,14 @@ func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime str
fieldsSql := strings.Join(fields, ",")
// 查询数据
querySql := fmt.Sprintf("SELECT %s FROM gold_kpi gk %s GROUP BY timeGroup", fieldsSql, whereSql)
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 gold_kpi gk %s GROUP BY timeGroup %s", fieldsSql, whereSql, orderSql)
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)

View File

@@ -0,0 +1,44 @@
package service
import (
"encoding/json"
"fmt"
"strings"
"time"
"ems.agt/src/framework/logger"
"ems.agt/src/framework/utils/fetch"
"ems.agt/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, 1)
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,
"refreshTime": time.Now().UnixMilli(), // 获取时间
"version": resData["version"],
"capability": resData["capability"],
"sn": resData["serialNum"],
"expire": resData["expiryDate"],
"cpu": resData["cpuUsage"],
"mem": resData["memUsage"],
}, nil
}

View File

@@ -6,4 +6,7 @@ import "ems.agt/src/modules/network_element/model"
type INeInfo interface {
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo
// SelectNeList 查询网元列表
SelectNeList(ne model.NeInfo, bandStatus bool) []model.NeInfo
}

View File

@@ -20,3 +20,24 @@ type NeInfoImpl struct {
func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo {
return r.NeInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID)
}
// SelectNeList 查询网元列表
func (r *NeInfoImpl) SelectNeList(ne model.NeInfo, bandStatus bool) []model.NeInfo {
list := r.NeInfoRepository.SelectNeList(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{}
continue
}
(*neList)[i].ServerState = result
}
}
return list
}

View File

@@ -4,8 +4,8 @@ import "ems.agt/src/modules/network_element/model"
// 性能统计 数据层接口
type IPerfKPI interface {
// SelectGoldKPI 通过ne_type和ne_id查询网元信息
SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any
// SelectGoldKPI 通过网元指标数据信息
SelectGoldKPI(query model.GoldKPIQuery) []map[string]any
// SelectGoldKPITitle
SelectGoldKPITitle(neType string) []model.GoldKPITitle

View File

@@ -17,8 +17,15 @@ type PerfKPIImpl struct {
}
// SelectGoldKPI 通过网元指标数据信息
func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any {
data := r.perfKPIRepository.SelectGoldKPI(rmUID, neType, startTime, endTime, kpiIds, interval)
func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery) []map[string]any {
// 获取数据指标id
var kpiIds []string
kpiTitles := r.perfKPIRepository.SelectGoldKPITitle(query.NeType)
for _, kpiId := range kpiTitles {
kpiIds = append(kpiIds, kpiId.KPIID)
}
data := r.perfKPIRepository.SelectGoldKPI(query, kpiIds)
if data == nil {
return []map[string]any{}
}

View File

@@ -62,12 +62,8 @@ func (r *UDMAuthImpl) authDataByRedis(imsi, neID string) []model.UDMAuth {
// Save UDM鉴权用户-获取redis全部保存数据库
func (r *UDMAuthImpl) Save(neID string) int64 {
var num int64 = 0
authArr := r.authDataByRedis("*", neID)
// 数据清空
if len(authArr) == 0 {
return num
}
// 数据清空后添加
go r.udmAuthRepository.ClearAndInsert(neID, authArr)
return int64(len(authArr))
}

View File

@@ -78,12 +78,8 @@ func (r *UDMSubImpl) subDataByRedis(imsi, neID string) []model.UDMSub {
// Save UDM签约用户-获取redis全部保存数据库
func (r *UDMSubImpl) Save(neID string) int64 {
var num int64 = 0
subArr := r.subDataByRedis("*", neID)
// 数据清空
if len(subArr) == 0 {
return num
}
// 数据清空后添加
go r.udmSubRepository.ClearAndInsert(neID, subArr)
return int64(len(subArr))
}