Refactor API tags in swagger.yaml to use shortened prefixes

- Updated tags from 'network_data' to 'ne_data' for consistency and brevity.
- Changed 'network_element' to 'ne' across various endpoints for improved readability.
- Adjusted related descriptions in the tags section to reflect the new naming conventions.
This commit is contained in:
TsMask committed 2025-08-21 14:30:09 +08:00
1 parent a72aa00f89
commit 45e226ce1a
171 files changed
+1177 -741

No files matched your search

+453
View File
@@ -0,0 +1,453 @@
package controller
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/gin-gonic/gin"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/ssh"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/utils/generate"
neService "be.ems/src/modules/ne/service"
)
// 实例化控制层 NeActionController 结构体
var NewNeAction = &NeActionController{
neInfoService: neService.NewNeInfo,
}
// 网元处理请求
//
// PATH /action
type NeActionController struct {
// 网元信息服务
neInfoService *neService.NeInfo
}
// 从本地到网元发送文件
//
// POST /pushFile
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Sending files from local to network elements
// @Description Sending files from local to network elements
// @Router /ne/action/pushFile [post]
func (s *NeActionController) PushFile(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"`
NeID string `json:"neId" binding:"required"`
UploadPath string `json:"uploadPath" binding:"required"`
DelTemp bool `json:"delTemp"` // 删除本地临时文件
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeID)
if neInfo.NeId != body.NeID || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
// 本地文件
localFilePath := file.ParseUploadFileAbsPath(body.UploadPath)
// 网元端临时目录
sshClient.RunCMD("sudo mkdir -p /tmp/omc/push && sudo chmod 777 -R /tmp/omc")
neFilePath := filepath.ToSlash(filepath.Join("/tmp/omc/push", filepath.Base(localFilePath)))
// 复制到远程
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
c.JSON(200, resp.ErrMsg("Please check if the file exists or if scp is allowed to copy remotely"))
return
}
defer func() {
if body.DelTemp {
_ = os.Remove(localFilePath)
}
}()
c.JSON(200, resp.OkData(filepath.ToSlash(neFilePath)))
}
// 从网元到本地获取文件
//
// GET /pullFile
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC) default(UPF)
// @Param neId query string true "NE ID" default(001)
// @Param path query string true "dir path" default(/var/log)
// @Param fileName query string true "file name"
// @Param delTemp query boolean false "Delete Temp File" default(false)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Getting files from the network element to the local
// @Description Getting files from the network element to the local
// @Router /ne/action/pullFile [get]
func (s *NeActionController) PullFile(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
Path string `form:"path" binding:"required"`
FileName string `form:"fileName" binding:"required"`
DelTemp bool `form:"delTemp"` // 删除本地临时文件
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
nePath := filepath.ToSlash(filepath.Join(querys.Path, querys.FileName))
fileName := generate.Code(6) + "_" + querys.FileName
localFilePath := filepath.Join("/tmp/omc/pull", fileName)
if runtime.GOOS == "windows" {
localFilePath = fmt.Sprintf("C:%s", localFilePath)
}
// 复制到本地
if err = sftpClient.CopyFileRemoteToLocal(nePath, localFilePath); err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer func() {
if querys.DelTemp {
_ = os.Remove(localFilePath)
}
}()
c.FileAttachment(localFilePath, fileName)
}
// 从网元到本地获取目录压缩为ZIP
//
// GET /pullDirZip
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC) default(UPF)
// @Param neId query string true "NE ID" default(001)
// @Param path query string true "dir path" default(/var/log)
// @Param delTemp query boolean false "Delete Temp File" default(false)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Get directories compressed to ZIP from the network element to the local area
// @Description Get directories compressed to ZIP from the network element to the local area
// @Router /ne/action/pullDirZip [get]
func (s *NeActionController) PullDirZip(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
Path string `form:"path" binding:"required"`
DelTemp bool `form:"delTemp"` // 删除本地临时文件
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
nePath := querys.Path
dirName := generate.Code(6)
localFilePath := filepath.Join("/tmp/omc/pull/", dirName)
if runtime.GOOS == "windows" {
localFilePath = fmt.Sprintf("C:%s", localFilePath)
}
// 复制到本地
localDirFilePath := filepath.Join(localFilePath, "zip")
if err = sftpClient.CopyDirRemoteToLocal(nePath, localDirFilePath); err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 压缩zip文件名
zipFileName := fmt.Sprintf("%s-%s-%s.zip", neInfo.NeType, neInfo.NeId, dirName)
zipFilePath := filepath.Join(localFilePath, zipFileName)
if err := file.CompressZipByDir(zipFilePath, localDirFilePath); err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer func() {
if querys.DelTemp {
_ = os.RemoveAll(localFilePath)
}
}()
c.FileAttachment(zipFilePath, zipFileName)
}
// 查看网元端文件内容
//
// GET /viewFile
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC) default(UPF)
// @Param neId query string true "NE ID" default(001)
// @Param path query string true "file path" default(/var/log)
// @Param fileName query string true "file name"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Viewing the contents of a file on the network element side
// @Description Viewing the contents of a file on the network element side
// @Router /ne/action/viewFile [get]
func (s *NeActionController) ViewFile(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
Path string `form:"path" binding:"required"`
FileName string `form:"fileName" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元端文件
nePath := filepath.ToSlash(filepath.Join(querys.Path, querys.FileName))
// 网元端临时目录
output, err := sshClient.RunCMD(fmt.Sprintf("cat %s", nePath))
output = strings.TrimSpace(output)
if err != nil || strings.HasPrefix(output, "ls: ") {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "file view cat error")))
return
}
c.JSON(200, resp.OkData(output))
}
// 网元端文件列表
//
// GET /files
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC) default(UPF)
// @Param neId query string true "NE ID" default(001)
// @Param path query string true "file path" default(/var/log)
// @Param pageNum query number true "pageNum" default(1)
// @Param pageSize query number true "pageSize" default(10)
// @Param search query string false "search prefix" default(upf)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary List of files on the network element side
// @Description List of files on the network element side
// @Router /ne/action/files [get]
func (s *NeActionController) Files(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
Path string `form:"path" binding:"required"`
PageNum int64 `form:"pageNum" binding:"required"`
PageSize int64 `form:"pageSize" binding:"required"`
Search string `form:"search"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 获取文件列表
rows, err := ssh.FileList(sshClient, querys.Path, querys.Search)
if err != nil {
c.JSON(200, resp.OkData(map[string]any{
"path": querys.Path,
"total": len(rows),
"rows": []ssh.FileListRow{},
}))
return
}
// 对数组进行切片分页
lenNum := int64(len(rows))
start := (querys.PageNum - 1) * querys.PageSize
end := start + querys.PageSize
var splitRows []ssh.FileListRow
if start >= lenNum {
splitRows = []ssh.FileListRow{}
} else if end >= lenNum {
splitRows = rows[start:]
} else {
splitRows = rows[start:end]
}
c.JSON(200, resp.OkData(map[string]any{
"path": querys.Path,
"total": lenNum,
"rows": splitRows,
}))
}
// 网元服务操作
//
// PUT /service
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element service operation
// @Description Network element service operation
// @Router /ne/action/service [put]
func (s *NeActionController) Service(c *gin.Context) {
language := reqctx.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.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeID)
if neInfo.NeId != body.NeID || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
neTypeLower := strings.ToLower(neInfo.NeType)
cmdStr := fmt.Sprintf("sudo systemctl %s %s", body.Action, neTypeLower)
switch neTypeLower {
case "omc":
cmdStr = fmt.Sprintf("nohup sh -c \"sudo systemctl stop omc && sleep 5s && sudo systemctl %s omc\" > /dev/null 2>&1 &", body.Action)
case "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, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.Ok(nil))
}
+394
View File
@@ -0,0 +1,394 @@
package controller
import (
"encoding/json"
"fmt"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/parse"
neFetchlink "be.ems/src/modules/ne/fetch_link"
"be.ems/src/modules/ne/model"
neService "be.ems/src/modules/ne/service"
traceService "be.ems/src/modules/trace/service"
"github.com/gin-gonic/gin"
)
// NewNeConfig 网元参数配置 实例化控制层
var NewNeConfig = &NeConfigController{
neConfigService: neService.NewNeConfig,
neInfoService: neService.NewNeInfo,
}
// 网元参数配置
//
// PATH /config
type NeConfigController struct {
neConfigService *neService.NeConfig // 网元参数配置可用属性值服务
neInfoService *neService.NeInfo // 网元信息服务
}
// 网元参数配置可用属性值列表
//
// GET /list
func (s NeConfigController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
rows, total := s.neConfigService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// 网元参数配置可用属性值信息
//
// GET /info/:id
func (s NeConfigController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := parse.Number(c.Query("id"))
if id <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
data := s.neConfigService.FindById(id)
if data.ID != id {
// 没有可访问参数配置数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfig.noData")))
return
}
// 将字符串转json数据
if err := json.Unmarshal([]byte(data.ParamJson), &data.ParamData); err != nil {
c.JSON(400, resp.CodeMsg(400, err.Error()))
return
}
c.JSON(200, resp.OkData(data))
}
// 网元参数配置可用属性值新增
//
// POST /
func (s NeConfigController) Add(c *gin.Context) {
var body model.NeConfig
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 将json数据转字符串存储
paramDataByte, err := json.Marshal(body.ParamData)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
body.ParamJson = string(paramDataByte)
insertId := s.neConfigService.Insert(body)
if insertId > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元参数配置可用属性值修改
//
// PUT /
func (s NeConfigController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeConfig
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否存在
data := s.neConfigService.FindById(body.ID)
if data.ID != body.ID {
// 没有可访问主机命令数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfig.noData")))
return
}
// 将json数据转字符串存储
paramDataByte, err := json.Marshal(body.ParamData)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
body.ParamJson = string(paramDataByte)
rows := s.neConfigService.Update(body)
if rows > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元参数配置可用属性值删除
//
// DELETE /
func (s NeConfigController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := c.Query("id")
if id == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
// 处理字符转id数组后去重
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
// 转换成int64数组类型
ids := make([]int64, 0)
for _, v := range uniqueIDs {
ids = append(ids, parse.Number(v))
}
rows, err := s.neConfigService.DeleteByIds(ids)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, resp.OkMsg(msg))
}
// 网元参数配置可用属性值列表指定网元类型全部无分页
//
// GET /list/:neType
//
// @Tags ne/config
// @Accept json
// @Produce json
// @Param neType path string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network Element Parameter Configuration Available Attribute Values List Specify Network Element Type All Unpaged
// @Description Network Element Parameter Configuration Available Attribute Values List Specify Network Element Type All Unpaged
// @Router /ne/config/list/{neType} [get]
func (s NeConfigController) ListByNeType(c *gin.Context) {
neType := c.Param("neType")
if neType == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: neType is empty"))
return
}
data := s.neConfigService.FindByNeType(neType)
c.JSON(200, resp.OkData(data))
}
// 网元参数配置数据信息
//
// GET /data
//
// @Tags ne/config
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Param paramName query string true "Available attributes, based on querying the list of attributes"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network Element Parameter Configuration Data Information
// @Description Network Element Parameter Configuration Data Information
// @Router /ne/config/data [get]
func (s NeConfigController) DataInfo(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {
NeType string `form:"neType" binding:"required"` // 网元类型
NeId string `form:"neId" binding:"required"` // 网元ID
ParamName string `form:"paramName" binding:"required"` // 可用属性
}
if err := c.ShouldBindQuery(&query); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
neInfo := s.neInfoService.FindByNeTypeAndNeID(query.NeType, query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
if query.NeType == "OMC" {
resData := s.neConfigService.GetOMCYaml(query.ParamName)
c.JSON(200, resp.OkData(resData))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigInfo(neInfo, query.ParamName)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.Ok(resData))
}
// 网元参数配置数据修改
//
// PUT /data
//
// @Tags ne/config
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element parameter configuration data modification
// @Description Network element parameter configuration data modification
// @Router /ne/config/data [put]
func (s NeConfigController) DataEdit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"` // 网元类型
NeId string `json:"neId" binding:"required"` // 网元ID
ParamName string `json:"paramName" binding:"required"`
ParamData map[string]any `json:"paramData" binding:"required"`
Loc string `json:"loc"` // 仅array使用与数据对象内index一致,有多层时划分嵌套层(index/subParamName/index)
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
if body.NeType == "OMC" {
err := s.neConfigService.ModifyOMCYaml(body.ParamName, body.Loc, body.ParamData)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 重开跟踪任务信令数据通道UDP
if body.ParamName == "trace" {
traceService.NewTraceTask.CreateUDP(true)
}
c.JSON(200, resp.Ok(nil))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigUpdate(neInfo, body.ParamName, body.Loc, body.ParamData)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(resData))
}
// 网元参数配置数据新增(array)
//
// POST /data
//
// @Tags ne/config
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element parameter configuration data added (array)
// @Description Network element parameter configuration data added (array)
// @Router /ne/config/data [post]
func (s NeConfigController) DataAdd(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"` // 网元类型
NeId string `json:"neId" binding:"required"` // 网元ID
ParamName string `json:"paramName" binding:"required"` // 根据配置可选值
ParamData map[string]any `json:"paramData" binding:"required"` // 数据对象
Loc string `json:"loc" binding:"required"` // 与数据对象内index一致,有多层时划分嵌套层(index/subParamName/index)
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否array
info := s.neConfigService.FindByNeTypeAndParamName(body.NeType, body.ParamName)
if info.ParamType != "array" {
c.JSON(200, resp.ErrMsg("this attribute does not support adding"))
return
}
// 必须含有index
_, idxOk := body.ParamData["index"]
if info.ParamType == "array" && !idxOk {
c.JSON(200, resp.ErrMsg("array data must contain index"))
return
}
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigAdd(neInfo, body.ParamName, body.Loc, body.ParamData)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(resData))
}
// 网元参数配置数据删除(array)
//
// DELETE /data
//
// @Tags ne/config
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Param paramName query string true "Available attributes, based on querying the list of attributes"
// @Param loc query string true "Array index"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element parameter configuration data deletion (array)
// @Description Network element parameter configuration data deletion (array)
// @Router /ne/config/data [delete]
func (s NeConfigController) DataRemove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {
NeType string `form:"neType" binding:"required"` // 网元类型
NeId string `form:"neId" binding:"required"` // 网元ID
ParamName string `form:"paramName" binding:"required"`
Loc string `form:"loc" binding:"required"` // 与数据对象内index一致,有多层时划分嵌套层(index/subParamName/index)
}
if err := c.ShouldBindQuery(&query); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否array
info := s.neConfigService.FindByNeTypeAndParamName(query.NeType, query.ParamName)
if info.ParamType != "array" {
c.JSON(200, resp.ErrMsg("this attribute does not support adding"))
return
}
neInfo := s.neInfoService.FindByNeTypeAndNeID(query.NeType, query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigDelete(neInfo, query.ParamName, query.Loc)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(resData))
}
@@ -0,0 +1,209 @@
package controller
import (
"fmt"
"os"
"path/filepath"
"strings"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/ne/model"
neService "be.ems/src/modules/ne/service"
systemService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
)
// NewNeConfigBackup 实例化控制层 NeConfigBackupController 结构体
var NewNeConfigBackup = &NeConfigBackupController{
neConfigBackupService: neService.NewNeConfigBackup,
neInfoService: neService.NewNeInfo,
sysConfigService: systemService.NewSysConfig,
}
// 网元配置文件备份记录
//
// PATH /config/backup
type NeConfigBackupController struct {
neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务
neInfoService *neService.NeInfo // 网元信息服务
sysConfigService *systemService.SysConfig // 参数配置服务
}
// 网元配置文件备份记录列表
//
// GET /list
func (s NeConfigBackupController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
rows, total := s.neConfigBackupService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}
// 网元配置文件备份记录信息
//
// GET /download?id=xx
func (s NeConfigBackupController) Download(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := parse.Number(c.Query("id"))
if id <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
item := s.neConfigBackupService.FindById(id)
if item.ID != id {
// 没有可访问主机命令数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfigBackup.noData")))
return
}
if _, err := os.Stat(item.Path); err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfigBackup.notFoundFile")))
return
}
c.FileAttachment(item.Path, item.Name)
}
// 网元配置文件备份记录修改
//
// PUT /
func (s NeConfigBackupController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
ID int64 `json:"id" binding:"required"` // 记录ID
Name string `json:"name" binding:"required"` // 名称
Remark string `json:"remark" binding:"required"` // 备注
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否存在
data := s.neConfigBackupService.FindById(body.ID)
if data.ID != body.ID {
// 没有可访问主机命令数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfig.noData")))
return
}
data.Name = body.Name
data.Remark = body.Remark
data.UpdateBy = reqctx.LoginUserToUserName(c)
rows := s.neConfigBackupService.Update(data)
if rows > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元配置文件备份记录删除
//
// DELETE /?id=xx
func (s NeConfigBackupController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := c.Query("id")
if id == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
// 处理字符转id数组后去重
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
// 转换成int64数组类型
ids := make([]int64, 0)
for _, v := range uniqueIDs {
ids = append(ids, parse.Number(v))
}
rows, err := s.neConfigBackupService.DeleteByIds(ids)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, resp.OkMsg(msg))
}
// 网元配置文件备份导入
//
// POST /import
func (s NeConfigBackupController) Import(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"`
NeId string `json:"neId" binding:"required"`
Type string `json:"type" binding:"required,oneof=backup upload"` // 导入类型
Path string `json:"path" binding:"required"` // 文件路径
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if !strings.HasSuffix(body.Path, ".zip") {
c.JSON(200, resp.ErrMsg("Only supports decompression of zip files"))
return
}
// 查网元
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 将zip文件解压到本地后复制到网元端
localFilePath := body.Path
if body.Type == "upload" {
localFilePath = file.ParseUploadFileAbsPath(body.Path)
}
if err := s.neConfigBackupService.FileLocalToNe(neInfo, localFilePath); err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.Ok(nil))
}
// 网元配置文件备份导出
//
// POST /export
func (s NeConfigBackupController) Export(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"`
NeId string `json:"neId" binding:"required"`
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查网元
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 将网元文件备份到本地
zipFilePath, err := s.neConfigBackupService.FileNeToLocal(neInfo)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 新增备份记录
item := model.NeConfigBackup{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
Name: filepath.Base(zipFilePath),
Path: zipFilePath,
CreateBy: reqctx.LoginUserToUserName(c),
}
s.neConfigBackupService.Insert(item)
c.FileAttachment(item.Path, item.Name)
}
+507
View File
@@ -0,0 +1,507 @@
package controller
import (
"fmt"
"strings"
"be.ems/src/framework/database/redis"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/ssh"
"be.ems/src/framework/telnet"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/ne/model"
neService "be.ems/src/modules/ne/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 NeHostController 结构体
var NewNeHost = &NeHostController{
neHostService: neService.NewNeHost,
}
// 网元主机连接请求
//
// PATH /host
type NeHostController struct {
neHostService *neService.NeHost // 网元主机连接服务
}
// 网元主机列表
//
// GET /list
func (s NeHostController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
rows, total := s.neHostService.FindByPage(query)
arr := &rows
for i := range *arr {
(*arr)[i].Password = "-"
(*arr)[i].PrivateKey = "-"
(*arr)[i].PassPhrase = "-"
}
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// 网元主机信息
//
// GET /:id
func (s NeHostController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := parse.Number(c.Param("id"))
if id <= 0 {
c.JSON(400, resp.CodeMsg(40010, "bind err: id is empty"))
return
}
neHost := s.neHostService.FindById(id)
if neHost.ID != id {
// 没有可访问主机信息数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.noData")))
return
}
c.JSON(200, resp.OkData(neHost))
}
// 网元主机新增
//
// POST /
func (s NeHostController) Add(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeHost
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.ID != 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id not is empty"))
return
}
if body.GroupID == "1" {
// 主机信息操作【%s】失败,禁止操作网元
msg := i18n.TKey(language, "neHost.banNE")
c.JSON(200, resp.ErrMsg(msg))
return
}
// 检查属性值唯一
uniqueHost := s.neHostService.CheckUniqueHostTitle(body.GroupID, body.Title, body.HostType, 0)
if !uniqueHost {
// 主机信息操作【%s】失败,同组内名称已存在
msg := i18n.TTemplate(language, "neHost.errKeyExists", map[string]any{"name": body.Title})
c.JSON(200, resp.ErrMsg(msg))
return
}
body.CreateBy = reqctx.LoginUserToUserName(c)
insertId := s.neHostService.Insert(body)
if insertId > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元主机修改
//
// PUT /
func (s NeHostController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeHost
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.ID <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
// 检查属性值唯一
uniqueHost := s.neHostService.CheckUniqueHostTitle(body.GroupID, body.Title, body.HostType, body.ID)
if !uniqueHost {
// 主机信息操作【%s】失败,同组内名称已存在
msg := i18n.TTemplate(language, "neHost.errKeyExists", map[string]any{"name": body.Title})
c.JSON(200, resp.ErrMsg(msg))
return
}
// 检查是否存在
neHost := s.neHostService.FindById(body.ID)
if neHost.ID != body.ID {
// 没有可访问主机信息数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.noData")))
return
}
body.UpdateBy = reqctx.LoginUserToUserName(c)
rows := s.neHostService.Update(body)
if rows > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元主机删除
//
// DELETE /:id
func (s NeHostController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := c.Param("id")
if id == "" {
c.JSON(400, resp.CodeMsg(40010, "bind err: id is empty"))
return
}
// 处理字符转id数组后去重
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
// 转换成int64数组类型
ids := make([]int64, 0)
for _, v := range uniqueIDs {
ids = append(ids, parse.Number(v))
}
rows, err := s.neHostService.DeleteByIds(ids, true)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, resp.OkMsg(msg))
}
// 网元主机测试连接
//
// POST /test
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element host test connection
// @Description Network element host test connection
// @Router /ne/host/test [post]
func (s NeHostController) Test(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeHost
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.HostType == "ssh" {
var connSSH ssh.ConnSSH
body.CopyTo(&connSSH)
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, resp.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
c.JSON(200, resp.Ok(nil))
return
}
if body.HostType == "telnet" {
var connTelnet telnet.ConnTelnet
body.CopyTo(&connTelnet)
client, err := connTelnet.NewClient()
if err != nil {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
// 是否有终止符
if strings.HasSuffix(client.LastResult, ">") || strings.HasSuffix(client.LastResult, "> ") || strings.HasSuffix(client.LastResult, "# ") {
c.JSON(200, resp.Ok(nil))
} else {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
}
return
}
if body.HostType == "redis" {
var connRedis redis.ConnRedis
body.CopyTo(&connRedis)
client, err := connRedis.NewClient()
if err != nil {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
c.JSON(200, resp.Ok(nil))
return
}
}
// 网元主机发送命令
//
// POST /cmd
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary The network element host sends the command
// @Description The network element host sends the command
// @Router /ne/host/cmd [post]
func (s NeHostController) Cmd(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
ID int64 `json:"id" binding:"required"` // 主机ID
Cmd string `json:"cmd" binding:"required"` // 执行命令
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否存在
neHost := s.neHostService.FindById(body.ID)
if neHost.ID != body.ID {
// 没有可访问主机信息数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.noData")))
return
}
if neHost.HostType == "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 {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
// 执行命令
output, err := client.RunCMD(body.Cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(output))
return
}
if neHost.HostType == "telnet" {
var connTelnet telnet.ConnTelnet
neHost.CopyTo(&connTelnet)
client, err := connTelnet.NewClient()
if err != nil {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
// 执行命令
output, err := client.RunCMD(body.Cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(output))
return
}
}
// 网元主机SSH方式检查服务器环境
//
// POST /checkBySSH
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Checking the server environment by SSH method of Net Element Hosting
// @Description Checking the server environment by SSH method of Net Element Hosting
// @Router /ne/host/checkBySSH [post]
func (s NeHostController) CheckBySSH(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeHost
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
var connSSH ssh.ConnSSH
body.CopyTo(&connSSH)
// 创建链接SSH客户端
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, resp.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
// 结果信息数据
data := map[string]any{
"addr": body.Addr, // 服务器地址
"kernelName": "-", // 内核名称 -s
"nodename": "-", // 网络节点主机名 -n
"kernelRelease": "-", // 内核发布版本 -r
"machine": "-", // 机器硬件名称 -m
"prettyName": "-", // 系统发行版本
"sudo": false, // 可提权
"sshLink": false, // 可直连
}
// 执行命令 检查系统环境
output, err := client.RunCMD("uname -snrm && cat /etc/os-release | grep PRETTY_NAME")
if err != nil {
c.JSON(200, resp.OkData(data))
return
}
output = strings.TrimSuffix(output, "\n")
sysInfoArr := strings.SplitN(output, "\n", 2)
if len(sysInfoArr) == 2 {
// uname -snrm
baseInfoArr := strings.SplitN(sysInfoArr[0], " ", 4)
data["kernelName"] = baseInfoArr[0]
data["nodename"] = baseInfoArr[1]
data["kernelRelease"] = baseInfoArr[2]
data["machine"] = baseInfoArr[3]
// cat /etc/os-release | grep PRETTY_NAME
prettyName := sysInfoArr[1]
index := strings.Index(prettyName, `"`)
if index != -1 {
data["prettyName"] = prettyName[index+1 : len(prettyName)-1]
}
}
// 执行命令 检查sudo权限
_, err = client.RunCMD("sudo -n uname")
if err == nil {
data["sudo"] = true
} else {
data["sudo"] = false
}
// 本地免密创建链接直连
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, resp.OkData(data))
}
// 网元主机SSH方式授权免密发送
//
// POST /authorizedBySSH
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element host SSH method of authorization for password-free sending
// @Description Network element host SSH method of authorization for password-free sending
// @Router /ne/host/authorizedBySSH [post]
func (s NeHostController) AuthorizedBySSH(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeHost
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.AuthMode == "2" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: auth mode not equals 2"))
return
}
// 本地免密创建链接直连
sshLink := false
lcoalConnSSH := ssh.ConnSSH{
User: body.User,
Addr: body.Addr,
Port: body.Port,
}
lcoalClient, err := lcoalConnSSH.NewClientByLocalPrivate()
if err == nil {
sshLink = true
defer lcoalClient.Close()
}
if sshLink {
// 连接主机成功,无需重复免密授权认证
c.JSON(200, resp.OkMsg(i18n.TKey(language, "neHost.okBySSHLink")))
return
}
// 创建链接SSH客户端
var connSSH ssh.ConnSSH
body.CopyTo(&connSSH)
client, err := connSSH.NewClient()
if err != nil {
// 连接主机失败,请检查连接参数后重试
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
// 发送密钥
err = client.SendToAuthorizedKeys()
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.Ok(nil))
}
+152
View File
@@ -0,0 +1,152 @@
package controller
import (
"fmt"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/ne/model"
neService "be.ems/src/modules/ne/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 NeHostCmdController 结构体
var NewNeHostCmd = &NeHostCmdController{
neHostCmdService: neService.NewNeHostCmd,
}
// 网元主机命令请求
//
// PATH /hostCmd
type NeHostCmdController struct {
neHostCmdService *neService.NeHostCmd // 网元主机命令服务
}
// 网元主机命令列表
//
// GET /list
func (s NeHostCmdController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
rows, total := s.neHostCmdService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// 网元主机命令信息
//
// GET /:id
func (s NeHostCmdController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := parse.Number(c.Param("id"))
if id <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
neHost := s.neHostCmdService.FindById(id)
if neHost.ID != id {
// 没有可访问主机命令数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHostCmd.noData")))
return
}
c.JSON(200, resp.OkData(neHost))
}
// 网元主机命令新增
//
// POST /
func (s NeHostCmdController) Add(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeHostCmd
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查属性值唯一
uniqueHostCmd := s.neHostCmdService.CheckUniqueGroupTitle(body.GroupID, body.Title, body.CmdType, 0)
if !uniqueHostCmd {
// 主机命令操作【%s】失败,同组内名称已存在
msg := i18n.TTemplate(language, "neHostCmd.errKeyExists", map[string]any{"name": body.Title})
c.JSON(200, resp.ErrMsg(msg))
return
}
body.CreateBy = reqctx.LoginUserToUserName(c)
insertId := s.neHostCmdService.Insert(body)
if insertId > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元主机命令修改
//
// PUT /
func (s NeHostCmdController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeHostCmd
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查属性值唯一
uniqueHostCmd := s.neHostCmdService.CheckUniqueGroupTitle(body.GroupID, body.Title, body.CmdType, body.ID)
if !uniqueHostCmd {
// 主机命令操作【%s】失败,同组内名称已存在
msg := i18n.TTemplate(language, "neHostCmd.errKeyExists", map[string]any{"name": body.Title})
c.JSON(200, resp.ErrMsg(msg))
return
}
// 检查是否存在
neHost := s.neHostCmdService.FindById(body.ID)
if neHost.ID != body.ID {
// 没有可访问主机命令数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neHostCmd.noData")))
return
}
body.UpdateBy = reqctx.LoginUserToUserName(c)
rows := s.neHostCmdService.Update(body)
if rows > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元主机命令删除
//
// DELETE /:id
func (s NeHostCmdController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := c.Param("id")
if id == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
// 处理字符转id数组后去重
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
// 转换成int64数组类型
ids := make([]int64, 0)
for _, v := range uniqueIDs {
ids = append(ids, parse.Number(v))
}
rows, err := s.neHostCmdService.DeleteByIds(ids)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, resp.OkMsg(msg))
}
+577
View File
@@ -0,0 +1,577 @@
package controller
import (
"fmt"
"strings"
"sync"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/parse"
neFetchlink "be.ems/src/modules/ne/fetch_link"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 NeInfoController 结构体
var NewNeInfo = &NeInfoController{
neInfoService: service.NewNeInfo,
neLicenseService: service.NewNeLicense,
neVersionService: service.NewNeVersion,
}
// 网元信息请求
//
// PATH /info
type NeInfoController struct {
neInfoService *service.NeInfo // 网元信息服务
neLicenseService *service.NeLicense // 网元授权激活信息服务
neVersionService *service.NeVersion // 网元版本信息服务
}
// neStateCacheMap 网元状态缓存最后一次成功的信息
var neStateCacheMap sync.Map
var mutex sync.Mutex
// 网元信息状态
//
// GET /state
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element information state
// @Description Network element information state
// @Router /ne/info/state [get]
func (s NeInfoController) State(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeId)
if neInfo.NeId != querys.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
neKey := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId)
// 网元直连
resData, err := neFetchlink.NeState(neInfo)
if err != nil {
mutex.Lock()
// 异常取上次缓存
resDataCache, ok := neStateCacheMap.Load(neKey)
if ok && resDataCache != nil {
resDataCache.(map[string]any)["online"] = false
} else {
resDataCache = map[string]any{
"online": false,
"neId": neInfo.NeId,
"neName": neInfo.NeName,
"neType": neInfo.NeType,
"neIP": neInfo.IP,
}
}
neStateCacheMap.Store(neKey, resDataCache)
mutex.Unlock()
c.JSON(200, resp.OkData(resDataCache))
return
}
// 存入缓存
resData["online"] = true
mutex.Lock()
neStateCacheMap.Store(neKey, resData)
mutex.Unlock()
c.JSON(200, resp.OkData(resData))
}
// 网元neType和neID查询
//
// GET /byTypeAndID
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element neType and neID queries
// @Description Network element neType and neID queries
// @Router /ne/info/byTypeAndID [get]
func (s NeInfoController) NeTypeAndID(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
c.JSON(200, resp.OkData(neInfo))
}
// 网元信息列表全部无分页
//
// GET /listAll
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type"
// @Param neId query string true "NE ID" default(001)
// @Param bandStatus query boolean true "With status information"
// @Param bandHost query boolean true "With host information"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary The list of network element information is all unpaginated
// @Description The list of network element information is all unpaginated
// @Router /ne/info/listAll [get]
func (s NeInfoController) ListAll(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType"`
NeId string `form:"neId"`
BandStatus bool `form:"bandStatus"`
BandHost bool `form:"bandHost"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查询实体参数
ne := model.NeInfo{}
if querys.NeType != "" {
ne.NeType = querys.NeType
}
if querys.NeId != "" {
ne.NeId = querys.NeId
}
neList := s.neInfoService.Find(ne, querys.BandStatus, querys.BandHost)
if len(neList) == 0 {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
c.JSON(200, resp.OkData(neList))
}
// 网元端Para5G配置文件读取
//
// GET /para5GFile
func (s NeInfoController) Para5GFileRead(c *gin.Context) {
data, err := s.neInfoService.NeConfPara5GRead()
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(data))
}
// 网元端Para5G配置文件写入
//
// PUT /para5GFile
func (s NeInfoController) Para5GFileWrite(c *gin.Context) {
var body struct {
Content map[string]any `json:"content" binding:"required"` // 内容
SyncNE []string `json:"syncNe"` // 同步到网元
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
err := s.neInfoService.NeConfPara5GWirte(body.Content, body.SyncNE)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.Ok(nil))
}
// 网元端OAM配置文件读取
//
// GET /oamFile
func (s NeInfoController) OAMFileRead(c *gin.Context) {
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
data, err := s.neInfoService.NeConfOAMReadSync(querys.NeType, querys.NeID)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.OkData(data))
}
// 网元端OAM配置文件写入
//
// PUT /oamFile
func (s NeInfoController) OAMFileWrite(c *gin.Context) {
language := reqctx.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.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeID)
if neInfo.NeId != body.NeID || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
err := s.neInfoService.NeConfOAMWirteSync(neInfo, body.Content, body.Sync)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.Ok(nil))
}
// 网元信息列表
//
// GET /list
//
// @Tags ne
// @Accept json
// @Produce json
// @Param bandStatus query boolean false "The result carries the state of the network element"
// @Param neId query string false "NE ID"
// @Param neType query string false "Ne Type"
// @Param pageNum query number true "pageNum" default(1)
// @Param pageSize query number true "pageSize" default(10)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element information list
// @Description Network element information list
// @Router /ne/info/list [get]
func (s NeInfoController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
bandStatus := false
if v, ok := query["bandStatus"]; ok {
bandStatus = parse.Boolean(v)
}
rows, total := s.neInfoService.FindByPage(query, bandStatus)
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}
// 网元信息
//
// GET /:id
//
// @Tags ne
// @Accept json
// @Produce json
// @Param value path string true "Row ID"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element information
// @Description Network element information
// @Router /ne/info/{value} [get]
func (s NeInfoController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := parse.Number(c.Param("id"))
if id <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
neHost := s.neInfoService.FindById(id, true)
if neHost.ID != id {
// 没有可访问网元信息数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neInfo.noData")))
return
}
c.JSON(200, resp.OkData(neHost))
}
// 网元信息新增
//
// POST /
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element information addition
// @Description Network element information addition
// @Router /ne/info [post]
func (s NeInfoController) Add(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeInfo
err := c.ShouldBindBodyWithJSON(&body)
if err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.ID != 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id not is empty"))
return
}
// 检查属性值唯一
uniqueInfo := s.neInfoService.CheckUniqueNeTypeAndNeId(body.NeType, body.NeId, 0)
if !uniqueInfo {
// 网元信息操作【%s】失败,同类型下标识已存在
msg := i18n.TTemplate(language, "neInfo.errKeyExists", map[string]any{"key": body.NeId})
c.JSON(200, resp.ErrMsg(msg))
return
}
// 获取网元状态是否正常
body.ServerState, err = neFetchlink.NeState(body)
if err != nil {
body.Status = 0
} else {
// 网元状态设置为在线
body.Status = 1
if parse.Boolean(body.ServerState["standby"]) {
body.Status = 3
}
// 下发网管配置信息给网元
if _, err = neFetchlink.NeConfigOMC(body); err != nil {
body.Status = 2
}
}
loginUserName := reqctx.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.Name = "-"
neVersion.Path = "-"
neVersion.Version = fmt.Sprint(v)
}
if v, ok := body.ServerState["capability"]; ok && v != nil {
neLicense.Capability = parse.Number(v)
}
if v, ok := body.ServerState["sn"]; ok && v != nil {
neLicense.SerialNum = fmt.Sprint(v)
}
if v, ok := body.ServerState["expire"]; ok && v != nil {
neLicense.ExpiryDate = fmt.Sprint(v)
neLicense.Status = "1"
}
}
s.neVersionService.Insert(neVersion)
s.neLicenseService.Insert(neLicense)
body.CreateBy = loginUserName
insertId := s.neInfoService.Insert(body)
if insertId > 0 {
c.JSON(200, resp.OkData(insertId))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元信息修改
//
// PUT /
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element information modification
// @Description Network element information modification
// @Router /ne/info [put]
func (s NeInfoController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeInfo
err := c.ShouldBindBodyWithJSON(&body)
if err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.ID <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
// 检查属性值唯一
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, resp.ErrMsg(msg))
return
}
// 检查是否存在
neInfo := s.neInfoService.FindById(body.ID, false)
if neInfo.ID != body.ID {
// 没有可访问网元信息数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neInfo.noData")))
return
}
// 赋予主机ID
if neInfo.HostIDs != "" && len(body.Hosts) > 0 {
hostIDs := strings.Split(neInfo.HostIDs, ",")
for index, id := range hostIDs {
body.Hosts[index].ID = parse.Number(id)
}
}
// 获取网元状态是否正常
body.ServerState, err = neFetchlink.NeState(neInfo)
if err != nil {
body.Status = 0
} else {
// 网元状态设置为在线
body.Status = 1
if parse.Boolean(body.ServerState["standby"]) {
body.Status = 3
}
// 下发网管配置信息给网元
if _, err = neFetchlink.NeConfigOMC(body); err != nil {
body.Status = 2
}
}
loginUserName := reqctx.LoginUserToUserName(c)
neLicense := s.neLicenseService.FindByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
neVersion := s.neVersionService.FindByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
// 已有网元可获取的信息
if body.ServerState != nil {
if v, ok := body.ServerState["version"]; ok && v != nil {
neVersion.Name = "-"
neVersion.Path = "-"
neVersion.Version = fmt.Sprint(v)
neVersion.UpdateBy = loginUserName
}
if v, ok := body.ServerState["capability"]; ok && v != nil {
neLicense.Capability = parse.Number(v)
}
if v, ok := body.ServerState["sn"]; ok && v != nil {
neLicense.SerialNum = fmt.Sprint(v)
}
if v, ok := body.ServerState["expire"]; ok && v != nil {
neLicense.ExpiryDate = fmt.Sprint(v)
neLicense.Status = "1"
neLicense.UpdateBy = loginUserName
}
}
if neVersion.ID <= 0 {
if neVersion.NeType != body.NeType || neVersion.NeId != body.NeId {
neVersion.NeType = body.NeType
neVersion.NeId = body.NeId
}
s.neVersionService.Update(neVersion)
}
if neLicense.ID <= 0 {
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, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元信息删除
//
// DELETE /:id
//
// @Tags ne
// @Accept json
// @Produce json
// @Param value path string true "Row ID"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element information deletion
// @Description Network element information deletion
// @Router /ne/info [delete]
func (s NeInfoController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := c.Param("id")
if id == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
// 处理字符转id数组后去重
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
// 转换成int64数组类型
ids := make([]int64, 0)
for _, v := range uniqueIDs {
ids = append(ids, parse.Number(v))
}
rows, err := s.neInfoService.DeleteByIds(ids)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, resp.OkMsg(msg))
}
+290
View File
@@ -0,0 +1,290 @@
package controller
import (
"fmt"
"strings"
"github.com/gin-gonic/gin"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/parse"
neFetchlink "be.ems/src/modules/ne/fetch_link"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/service"
)
// 实例化控制层 NeLicenseController 结构体
var NewNeLicense = &NeLicenseController{
neLicenseService: service.NewNeLicense,
neInfoService: service.NewNeInfo,
}
// 网元授权激活请求
//
// PATH /license
type NeLicenseController struct {
neLicenseService *service.NeLicense // 网元授权激活服务
neInfoService *service.NeInfo // 网元信息服务
}
// 网元授权激活列表
//
// GET /list
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string false "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string false "NE ID"
// @Param expiryDate query string false "ExpiryDate"
// @Param pageNum query number true "pageNum" default(1)
// @Param pageSize query number true "pageSize" default(10)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Net Element License Activation List
// @Description Net Element License Activation List
// @Router /ne/license/list [get]
func (s *NeLicenseController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
rows, total := s.neLicenseService.FindByPage(query)
// 过滤屏蔽授权文件
arr := &rows
for i := range *arr {
(*arr)[i].ActivationRequestCode = "-"
(*arr)[i].LicensePath = "-"
}
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// 网元授权激活信息
//
// GET /:id
func (s *NeLicenseController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := parse.Number(c.Param("id"))
if id <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
neLicense := s.neLicenseService.FindById(id)
if neLicense.ID != id {
// 没有可访问网元授权激活数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
c.JSON(200, resp.OkData(neLicense))
}
// 网元neType和neID查询
//
// GET /byTypeAndID
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element neType and neID queries
// @Description Network element neType and neID queries
// @Router /ne/license/byTypeAndID [get]
func (s *NeLicenseController) NeTypeAndID(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
neLicense := s.neLicenseService.FindByNeTypeAndNeID(querys.NeType, querys.NeId)
if neLicense.NeId != querys.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
c.JSON(200, resp.OkData(neLicense))
}
// 网元授权激活授权申请码
//
// GET /code
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network Element License Activation License Application Code
// @Description Network Element License Activation License Application Code
// @Router /ne/license/code [get]
func (s *NeLicenseController) Code(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.FindByNeTypeAndNeID(querys.NeType, querys.NeId)
if neLicense.NeId != querys.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
// 更新授权码
code, licensePath := s.neLicenseService.ReadLicenseInfo(neLicense)
neLicense.ActivationRequestCode = code
if licensePath != "" {
neLicense.LicensePath = licensePath
} else {
neLicense.Capability = 0
neLicense.SerialNum = ""
neLicense.ExpiryDate = ""
neLicense.Status = "0"
}
neLicense.UpdateBy = reqctx.LoginUserToUserName(c)
s.neLicenseService.Update(neLicense)
c.JSON(200, resp.OkData(code))
}
// 网元授权激活授权文件替换
//
// POST /change
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element authorization activation status
// @Description Network element authorization activation status
// @Router /ne/license/change [post]
func (s *NeLicenseController) Change(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeLicense
err := c.ShouldBindBodyWithJSON(&body)
if err != nil || body.LicensePath == "" {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.FindByNeTypeAndNeID(body.NeType, body.NeId)
if neLicense.NeId != body.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
// 更新授权记录
if body.Remark != "" {
neLicense.Remark = body.Remark
}
neLicense.LicensePath = body.LicensePath
neLicense.Status = "0"
neLicense.UpdateBy = reqctx.LoginUserToUserName(c)
upRows := s.neLicenseService.Update(neLicense)
if upRows > 0 {
// 进行上传替换
err = s.neLicenseService.UploadLicense(body)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元授权激活状态
//
// GET /state
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element authorization activation status
// @Description Network element authorization activation status
// @Router /ne/license/state [get]
func (s *NeLicenseController) State(c *gin.Context) {
language := reqctx.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, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.FindByNeTypeAndNeID(querys.NeType, querys.NeId)
if neLicense.NeId != querys.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
// 查询网元获取IP获取网元状态
neInfo := s.neInfoService.FindByNeTypeAndNeID(neLicense.NeType, neLicense.NeId)
if neInfo.NeId != neLicense.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
if neState, err := neFetchlink.NeState(neInfo); err == nil && neState["sn"] != nil {
neLicense.Status = "1"
neLicense.Capability = parse.Number(neState["capability"])
neLicense.SerialNum = fmt.Sprint(neState["sn"])
neLicense.ExpiryDate = fmt.Sprint(neState["expire"])
} else {
neLicense.Status = "0"
}
// 更新授权码
if neLicense.ActivationRequestCode == "" || strings.HasPrefix(neLicense.ActivationRequestCode, "SN") || neLicense.Status == "0" {
code, licensePath := s.neLicenseService.ReadLicenseInfo(neLicense)
neLicense.ActivationRequestCode = code
neLicense.LicensePath = licensePath
}
// 更新授权信息
neLicense.UpdateBy = reqctx.LoginUserToUserName(c)
s.neLicenseService.Update(neLicense)
if neLicense.Status == "1" {
c.JSON(200, resp.OkData(map[string]any{
"capability": neLicense.Capability,
"sn": neLicense.SerialNum,
"expire": neLicense.ExpiryDate,
}))
return
}
c.JSON(200, resp.ErrMsg(fmt.Sprintf("%s service status exception", neLicense.NeType)))
}
+232
View File
@@ -0,0 +1,232 @@
package controller
import (
"fmt"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 NeSoftwareController 结构体
var NewNeSoftware = &NeSoftwareController{
neSoftwareService: service.NewNeSoftware,
}
// 网元软件包请求
//
// PATH /software
type NeSoftwareController struct {
neSoftwareService *service.NeSoftware // 网元软件包服务
}
// 网元软件包列表
//
// GET /list
//
// @Tags ne
// @Accept json
// @Produce json
// @Param neType query string false "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param name query string false "Name"
// @Param version query string false "Version"
// @Param pageNum query number true "pageNum" default(1)
// @Param pageSize query number true "pageSize" default(10)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary List of Network Element Software Packages
// @Description List of Network Element Software Packages
// @Router /ne/software/list [get]
func (s NeSoftwareController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
rows, total := s.neSoftwareService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// 网元软件包信息
//
// GET /:id
func (s NeSoftwareController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := parse.Number(c.Param("id"))
if id <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
neSoftware := s.neSoftwareService.FindById(id)
if neSoftware.ID != id {
// 没有可访问网元包信息数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neSoftware.noData")))
return
}
c.JSON(200, resp.OkData(neSoftware))
}
// 网元软件包新增
//
// POST /
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Additions to the Net Element package
// @Description Additions to the Net Element package
// @Router /ne/software [post]
func (s NeSoftwareController) Add(c *gin.Context) {
var body model.NeSoftware
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.Path == "" || body.ID > 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: path is empty or id is not empty"))
return
}
// 找到已存在的删除后重新添加
neSoftwares := s.neSoftwareService.Find(model.NeSoftware{
NeType: body.NeType,
Name: body.Name,
Version: body.Version,
})
if len(neSoftwares) > 0 {
neSoftware := neSoftwares[0]
s.neSoftwareService.DeleteByIds([]int64{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, resp.ErrMsg(msg))
// return
// }
body.CreateBy = reqctx.LoginUserToUserName(c)
insertId := s.neSoftwareService.Insert(body)
if insertId > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元软件包修改
//
// PUT /
func (s NeSoftwareController) Edit(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.NeSoftware
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if body.Path == "" || body.ID == 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: path or id is empty"))
return
}
// 检查属性值唯一
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.Name})
c.JSON(200, resp.ErrMsg(msg))
return
}
// 检查是否存在
neSoftware := s.neSoftwareService.FindById(body.ID)
if neSoftware.ID != body.ID {
// 没有可访问网元包信息数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neSoftware.noData")))
return
}
body.UpdateBy = reqctx.LoginUserToUserName(c)
rows := s.neSoftwareService.Update(body)
if rows > 0 {
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
// 网元软件包删除
//
// DELETE /:id
func (s NeSoftwareController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := c.Param("id")
if id == "" {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
// 处理字符转id数组后去重
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
// 转换成int64数组类型
ids := make([]int64, 0)
for _, v := range uniqueIDs {
ids = append(ids, parse.Number(v))
}
rows, err := s.neSoftwareService.DeleteByIds(ids)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, resp.OkMsg(msg))
}
// 网元软件包设为网元新版本
//
// POST /newNeVersion
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Net Element package set to Net Element new version
// @Description Net Element package set to Net Element new version
// @Router /ne/software/newNeVersion [post]
func (s NeSoftwareController) NewNeVersion(c *gin.Context) {
var body model.NeSoftware
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
// 找到已存在的软件包信息
neSoftwares := s.neSoftwareService.Find(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: reqctx.LoginUserToUserName(c),
})
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, resp.Err(nil))
}
+98
View File
@@ -0,0 +1,98 @@
package controller
import (
"fmt"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/parse"
neService "be.ems/src/modules/ne/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 NeVersionController 结构体
var NewNeVersion = &NeVersionController{
neVersionService: neService.NewNeVersion,
}
// 网元版本请求
//
// PATH /version
type NeVersionController struct {
neVersionService *neService.NeVersion // 网元版本服务
}
// 网元版本列表
//
// GET /list
func (s *NeVersionController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
rows, total := s.neVersionService.FindByPage(query, true)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// 网元版本信息
//
// GET /:id
func (s *NeVersionController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
id := parse.Number(c.Param("id"))
if id <= 0 {
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
return
}
neVersion := s.neVersionService.FindById(id)
if neVersion.ID != id {
// 没有可访问网元版本数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neVersion.noData")))
return
}
c.JSON(200, resp.OkData(neVersion))
}
// 网元版本操作
//
// POST /operate
//
// @Tags ne
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary Network element version operation
// @Description Network element version operation
// @Router /ne/version/operate [post]
func (s *NeVersionController) Operate(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
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.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
neVersion := s.neVersionService.FindByNeTypeAndNeID(body.NeType, body.NeId)
if neVersion.NeId != body.NeId {
// 没有可访问网元版本数据!
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neVersion.noData")))
return
}
// 进行相关命令操作
output, err := s.neVersionService.Operate(body.Action, neVersion, body.Preinput)
if err != nil {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
c.JSON(200, resp.OkData(output))
}
+39
View File
@@ -0,0 +1,39 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// AlarmHistory 告警历史记录
func AlarmHistory(neInfo model.NeInfo) ([]map[string]any, error) {
// 网元参数配置信息
neUrl := fmt.Sprintf("http://%s:%d/api/rest/faultManagement/v1/elementType/%s/objectType/alarms", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType))
resBytes, err := fetch.Get(neUrl, nil, 60_000)
var resData []map[string]any
if err != nil {
errStr := err.Error()
logger.Warnf("AlarmHistory Get \"%s\"", neUrl)
if !(strings.HasPrefix(errStr, "201") || strings.HasPrefix(errStr, "202") || strings.HasPrefix(errStr, "204")) {
logger.Errorf("AlarmHistory %s", err.Error())
return nil, fmt.Errorf("NeService Alarm History Info API Error")
}
}
if len(resBytes) == 0 {
return resData, nil
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("AlarmHistory Unmarshal %s", err.Error())
return nil, err
}
return resData, nil
}
+105
View File
@@ -0,0 +1,105 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// AMFNbInfoList AMF基站信息
//
// 查询参数 {"id":"7"}
//
// 返回结果 []
func AMFNbInfoList(neInfo model.NeInfo, data map[string]string) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/amf/objectType/nbInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["id"]; ok && v != "" {
query = append(query, fmt.Sprintf("nbId=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
var resData map[string]any
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("AMFNbInfoList Get \"%s\"", neUrl)
logger.Errorf("AMFNbInfoList %s", errStr)
return nil, fmt.Errorf("NeService AMF API Error")
}
// 序列化结果 {"data":[{"id":"7","name":"NR-SA-GNB","address":"192.168.5.100:60110","ueNum":0}]}
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("AMFNbInfoList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
if arr := v.([]any); len(arr) > 0 {
result := make([]map[string]any, len(arr))
for i, item := range arr {
result[i] = item.(map[string]any)
}
return result, nil
}
}
return []map[string]any{}, nil
}
// AMFGnbStateList AMF基站状态信息,对比配置项gnbList
//
// 返回结果 []
func AMFGnbStateList(neInfo model.NeInfo) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/amf/objectType/nbState", neInfo.IP, neInfo.Port)
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("AMFGnbStateList Get \"%s\"", neUrl)
logger.Errorf("AMFGnbStateList %s", errStr)
return nil, fmt.Errorf("NeService AMF API Error")
}
// 序列化结果
// {
// "data": [
// {
// "index": 1,
// "name": "Gnb",
// "address": "192.168.8.1",
// "position": "Area-B",
// "offTime": "2024-12-30T16:31:57+08:00",
// "onTime": "2024-12-30T15:41:59+08:00",
// "state": "OFF",
// "nbName": "SA",
// "ueNum": 1
// },
// ]
// }
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("AMFGnbStateList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
if arr := v.([]any); len(arr) > 0 {
result := make([]map[string]any, len(arr))
for i, item := range arr {
result[i] = item.(map[string]any)
}
return result, nil
}
}
return []map[string]any{}, nil
}
+68
View File
@@ -0,0 +1,68 @@
// 网元HLR服务8080端口。
// 融合到UDM网元,也许是UDM的HLR服务。
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// HLRTraceStart HLR跟踪任务开始
//
// data参数 {traceID:"跟踪任务ID", imsi:"IMSI和MSISDN必填一个,都带的话以IMSI为准", msisdn:""}
func HLRTraceStart(neInfo model.NeInfo, data map[string]any) (string, error) {
// 网元参数配置新增(array)
neUrl := fmt.Sprintf("http://%s:%d/trace-manage/v1/add-task", neInfo.IP, neInfo.Port)
resBytes, err := fetch.PostJSON(neUrl, data, nil)
var resData map[string]string
if err != nil {
errStr := err.Error()
logger.Warnf("HLRTraceStart Post \"%s\"", neUrl)
logger.Errorf("HLRTraceStart %s", errStr)
return "", fmt.Errorf("NeService HLR API Error")
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("HLRTraceStart Unmarshal %s", err.Error())
return "", err
}
if v, ok := resData["code"]; ok && v == "0" {
return strings.TrimSpace(strings.ToLower(resData["message"])), nil
}
return "", fmt.Errorf("%s", resData["message"])
}
// HLRTraceStop HLR跟踪任务停止
//
// data参数 {traceIDArray: ["跟踪任务ID数组"]}
func HLRTraceStop(neInfo model.NeInfo, data map[string]any) (string, error) {
// 网元参数配置新增(array)
neUrl := fmt.Sprintf("http://%s:%d/trace-manage/v1/delete-task", neInfo.IP, neInfo.Port)
resBytes, err := fetch.PostJSON(neUrl, data, nil)
var resData map[string]string
if err != nil {
errStr := err.Error()
logger.Warnf("HLRTraceStop Post \"%s\"", neUrl)
logger.Errorf("HLRTraceStop %s", errStr)
return "", fmt.Errorf("NeService HLR API Error")
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("HLRTraceStop Unmarshal %s", err.Error())
return "", err
}
if v, ok := resData["code"]; ok && v == "0" {
return strings.TrimSpace(strings.ToLower(resData["message"])), nil
}
return "", fmt.Errorf("%s", resData["message"])
}
+100
View File
@@ -0,0 +1,100 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/ne/model"
)
// IMSUeSessionNum IMS会话数量
//
// 返回结果 0
func IMSUeSessionNum(neInfo model.NeInfo) (int64, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/ims/objectType/ueNum", neInfo.IP, neInfo.Port)
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("IMSUeSessionNum Get \"%s\"", neUrl)
logger.Errorf("IMSUeSessionNum %s", errStr)
return 0, fmt.Errorf("NeService IMS API Error")
}
// 序列化结果 {"data":{"ueNum":0}}
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("IMSUeSessionNum Unmarshal %s", err.Error())
return 0, err
}
// 固定返回字段,方便前端解析
var ueNum int64 = 0
if v, ok := resData["data"]; ok && v != nil {
if num := v.(map[string]any)["ueNum"]; num != nil {
ueNum = parse.Number(num)
}
}
return ueNum, nil
}
// IMSUeSessionList IMS会话列表
//
// 查询参数 {"imsi":"460001230000002","msisdn":"12307551232"}
//
// 返回结果 []
func IMSUeSessionList(neInfo model.NeInfo, data map[string]string) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/ims/objectType/ueInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["imsi"]; ok && v != "" {
query = append(query, fmt.Sprintf("imsi=%s", v))
}
if v, ok := data["msisdn"]; ok && v != "" {
query = append(query, fmt.Sprintf("msisdn=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("IMSUeSessionList Get \"%s\"", neUrl)
logger.Errorf("IMSUeSessionList %s", errStr)
return nil, fmt.Errorf("NeService IMS API Error")
}
// 序列化结果
// { "data":[
// {
// "activeTime": "2023-11-29 17:04:54",
// "barring": 0,
// "impu": "sip:12307551232@ims.mnc000.mcc460.3gppnetwork.org",
// "imsi": "460001230000002",
// "msisdn": "12307551232",
// "regState": 1
// }
// ] }
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("IMSUeSessionList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
if arr := v.([]any); len(arr) > 0 {
result := make([]map[string]any, len(arr))
for i, item := range arr {
result[i] = item.(map[string]any)
}
return result, nil
}
}
return []map[string]any{}, nil
}
+105
View File
@@ -0,0 +1,105 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// MMENbInfoList MME基站信息
//
// 查询参数 {"id":"7"}
//
// 返回结果 []
func MMENbInfoList(neInfo model.NeInfo, data map[string]string) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/mme/objectType/nbInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["id"]; ok && v != "" {
query = append(query, fmt.Sprintf("nbId=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
var resData map[string]any
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("MMENbInfoList Get \"%s\"", neUrl)
logger.Errorf("MMENbInfoList %s", errStr)
return nil, fmt.Errorf("NeService MME API Error")
}
// 序列化结果 {"data":[{"id":"7","name":"NR-SA-GNB","address":"192.168.5.100:60110","ueNum":0}]}
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("MMENbInfoList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
if arr := v.([]any); len(arr) > 0 {
result := make([]map[string]any, len(arr))
for i, item := range arr {
result[i] = item.(map[string]any)
}
return result, nil
}
}
return []map[string]any{}, nil
}
// MMEEnbStateList MME基站状态信息,对比配置项enbList
//
// 返回结果 []
func MMEEnbStateList(neInfo model.NeInfo) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/mme/objectType/nbState", neInfo.IP, neInfo.Port)
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("MMEEnbStateList Get \"%s\"", neUrl)
logger.Errorf("MMEEnbStateList %s", errStr)
return nil, fmt.Errorf("NeService MME API Error")
}
// 序列化结果
// {
// "data": [
// {
// "index": 1,
// "name": "Enb",
// "address": "192.168.8.1",
// "position": "Area-B",
// "offTime": "2024-12-30T16:31:57+08:00",
// "onTime": "2024-12-30T15:41:59+08:00",
// "state": "OFF",
// "nbName": "SA",
// "ueNum": 1
// },
// ]
// }
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("MMEEnbStateList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
if arr := v.([]any); len(arr) > 0 {
result := make([]map[string]any, len(arr))
for i, item := range arr {
result[i] = item.(map[string]any)
}
return result, nil
}
}
return []map[string]any{}, nil
}
+64
View File
@@ -0,0 +1,64 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// N3IWFSubInfoList N3IWF在线列表信息
//
// 查询参数 {"imsi":"460302072701181"}
//
// 返回结果 {"rows":[],"total":0}
func N3IWFSubInfoList(neInfo model.NeInfo, data map[string]string) (map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/n3iwf/objectType/ueInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["imsi"]; ok && v != "" {
query = append(query, fmt.Sprintf("imsi=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
logger.Warnf("N3IWFSubInfo Get \"%s\"", neUrl)
logger.Errorf("N3IWFSubInfo %s", err.Error())
return nil, fmt.Errorf("NeService N3IWF API Error")
}
// 序列化结果
// {
// "data": [
// {
// "activeTime": "2023-11-29 06:35:43",
// "imsi": "460302072701181",
// "nai": "0460302072701181@nai.epc.mnc030.mcc460.3gppnetwork.org",
// "regState": 1
// }
// ]
// }
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("N3IWFSubInfo Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
resData["rows"] = v.([]any)
resData["total"] = len(v.([]any))
delete(resData, "data")
} else {
resData["rows"] = []any{}
resData["total"] = 0
}
return resData, nil
}
+170
View File
@@ -0,0 +1,170 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// NeConfigOMC 网元配置对端网管信息
func NeConfigOMC(neInfo model.NeInfo) (map[string]any, error) {
// 网元配置对端网管信息
neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType))
resBytes, err := fetch.PutJSON(neUrl, map[string]any{
"neId": neInfo.NeId,
"neName": neInfo.NeName,
"port": neInfo.Port,
"province": neInfo.Province,
"pvFlag": neInfo.PvFlag,
"rmUID": neInfo.RmUID,
"vendorName": neInfo.VendorName,
"dn": neInfo.Dn,
}, nil)
var resData map[string]any
if err != nil {
errStr := err.Error()
if strings.HasPrefix(errStr, "201") || strings.HasPrefix(errStr, "204") {
return resData, nil
}
logger.Warnf("NeConfigOMC Put \"%s\"", neUrl)
logger.Errorf("NeConfigOMC %s", errStr)
return nil, fmt.Errorf("NeService Config OMC Update API Error")
}
// 200 成功无数据时
if len(resBytes) == 0 {
return resData, nil
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NeConfigOMC Unmarshal %s", err.Error())
return nil, err
}
return resData, nil
}
// NeConfigInfo 网元配置信息
func NeConfigInfo(neInfo model.NeInfo, paramName 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), paramName)
resBytes, err := fetch.Get(neUrl, nil, 30_000)
if err != nil {
logger.Warnf("NeConfigInfo Get \"%s\"", neUrl)
logger.Errorf("NeConfigInfo %s", err.Error())
return nil, fmt.Errorf("NeService Config Info API Error")
}
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NeConfigInfo Unmarshal %s", err.Error())
return nil, err
}
// 网元参数配置信息为空时是{},需要补充data属性
if _, ok := resData["data"]; !ok {
resData["data"] = []map[string]any{}
}
return resData, nil
}
// NeConfigUpdate 网元配置更新
func NeConfigUpdate(neInfo model.NeInfo, paramName, loc string, data map[string]any) (map[string]any, error) {
// array需要层级
if loc != "" {
loc = fmt.Sprintf("?loc=%v", loc)
}
// 网元参数配置新增(array)
neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/config/%s%s", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType), paramName, loc)
resBytes, err := fetch.PutJSON(neUrl, data, nil)
var resData map[string]any
if err != nil {
errStr := err.Error()
logger.Warnf("NeConfigUpdate Put \"%s\"", neUrl)
if strings.HasPrefix(errStr, "201") || strings.HasPrefix(errStr, "204") {
return resData, nil
}
logger.Errorf("NeConfigUpdate %s", errStr)
return nil, fmt.Errorf("NeService Config Update API Error")
}
// 200 成功无数据时
if len(resBytes) == 0 {
return resData, nil
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NeConfigUpdate Unmarshal %s", err.Error())
return nil, err
}
return resData, nil
}
// NeConfigAdd 网元配置新增 array
func NeConfigAdd(neInfo model.NeInfo, paramName, loc string, data map[string]any) (map[string]any, error) {
// 网元参数配置新增(array)
neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/config/%s?loc=%v", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType), paramName, loc)
resBytes, err := fetch.PostJSON(neUrl, data, nil)
var resData map[string]any
if err != nil {
errStr := err.Error()
logger.Warnf("NeConfigAdd Post \"%s\"", neUrl)
if strings.HasPrefix(errStr, "201") || strings.HasPrefix(errStr, "204") {
return resData, nil
}
logger.Errorf("NeConfigAdd %s", errStr)
return nil, fmt.Errorf("NeService Config Add API Error")
}
// 200 成功无数据时
if len(resBytes) == 0 {
return resData, nil
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NeConfigAdd Unmarshal %s", err.Error())
return nil, err
}
return resData, nil
}
// NeConfigDelete 网元配置删除 array
func NeConfigDelete(neInfo model.NeInfo, paramName, loc string) (map[string]any, error) {
// 网元参数配置删除(array)
neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/config/%s?loc=%v", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType), paramName, loc)
resBytes, err := fetch.Delete(neUrl, nil)
var resData map[string]any
if err != nil {
errStr := err.Error()
logger.Warnf("NeConfigDelete Delete \"%s\"", neUrl)
if strings.HasPrefix(errStr, "201") || strings.HasPrefix(errStr, "204") {
return resData, nil
}
logger.Errorf("NeConfigDelete %s", errStr)
return nil, fmt.Errorf("NeService Config Update API Error")
}
// 200 成功无数据时
if len(resBytes) == 0 {
return resData, nil
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NeConfigInfoDel Unmarshal %s", err.Error())
return nil, err
}
return resData, nil
}
+59
View File
@@ -0,0 +1,59 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"time"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/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.Errorf("NeState %s", err.Error())
return nil, fmt.Errorf("NeService System State API Error")
}
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("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(), // 获取时间
"standby": resData["standby"], // 是否备用服务
"version": resData["version"],
"capability": resData["capability"],
"sn": resData["serialNum"],
"expire": resData["expiryDate"],
"hostname": resData["hostName"],
"os": resData["osInfo"],
"cpu": resData["cpuUsage"],
"mem": resData["memUsage"],
"disk": resData["diskSpace"],
}, nil
}
+69
View File
@@ -0,0 +1,69 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// NeTraceAdd 网元跟踪任务新增
func NeTraceAdd(neInfo model.NeInfo, data any) (map[string]any, error) {
// 跟踪任务创建
neUrl := fmt.Sprintf("http://%s:%d/api/rest/traceManagement/v2/%s/subscriptions", neInfo.IP, neInfo.Port, neInfo.NeType)
resBytes, err := fetch.PostJSON(neUrl, data, nil)
var resData map[string]any
if err != nil {
errStr := err.Error()
if !(strings.HasPrefix(errStr, "201") || strings.HasPrefix(errStr, "400")) {
logger.Warnf("NeTraceAdd POST \"%s\"", neUrl)
logger.Errorf("NeTraceAdd %s", errStr)
return nil, fmt.Errorf("NeService Trace Add API Error")
}
}
// 200 成功无数据时
if len(resBytes) == 0 {
return resData, nil
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NeTraceAdd Unmarshal %s", err.Error())
return nil, err
}
return resData, nil
}
// NeTraceDelete 网元跟踪任务删除
func NeTraceDelete(neInfo model.NeInfo, traceId string) (map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/traceManagement/v2/%s/subscriptions?id=%s", neInfo.IP, neInfo.Port, neInfo.NeType, traceId)
resBytes, err := fetch.Delete(neUrl, nil)
var resData map[string]any
if err != nil {
errStr := err.Error()
if strings.HasPrefix(errStr, "201") || strings.HasPrefix(errStr, "204") {
return resData, nil
}
logger.Warnf("NeTraceDelete Delete \"%s\"", neUrl)
logger.Errorf("NeTraceDelete %s", errStr)
return nil, fmt.Errorf("NeService Trace Delete API Error")
}
// 200 成功无数据时
if len(resBytes) == 0 {
return resData, nil
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NeTraceDelete Unmarshal %s", err.Error())
return nil, err
}
return resData, nil
}
+95
View File
@@ -0,0 +1,95 @@
package fetchlink
import (
"encoding/json"
"fmt"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// NSSFSubInfoList NSSF在线列表信息
//
// 返回结果 {"rows":[],"total":0}
func NSSFSubInfoList(neInfo model.NeInfo) (map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/nssf/objectType/subscriptions", neInfo.IP, neInfo.Port)
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
logger.Warnf("NSSFSubInfo Get \"%s\"", neUrl)
logger.Errorf("NSSFSubInfo %s", err.Error())
return nil, fmt.Errorf("NeService NSSF API Error")
}
// 序列化结果
// {
// "data": [
// {
// "subscriptionId": "460302072701181",
// "event": "460302072701181",
// "nfNssaiAvailabilityUri": "0460302072701181@nai.epc.mnc030.mcc460.3gppnetwork.org"
// }
// ]
// }
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NSSFSubInfo Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
resData["rows"] = v.([]any)
resData["total"] = len(v.([]any))
delete(resData, "data")
} else {
resData["rows"] = []any{}
resData["total"] = 0
}
return resData, nil
}
// NSSFAvailableAMFList NSSF装载AMF信息
//
// 返回结果 {"rows":[],"total":0}
func NSSFAvailableAMFList(neInfo model.NeInfo) (map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/nssf/objectType/availableAMFs", neInfo.IP, neInfo.Port)
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
logger.Warnf("NSSFAvailableAMFList Get \"%s\"", neUrl)
logger.Errorf("NSSFAvailableAMFList %s", err.Error())
return nil, fmt.Errorf("NeService NSSF API Error")
}
// 序列化结果
// {
// "data": [
// {
// "nfId": "001",
// "amfSetId": "001"
// },
// {
// "nfId": "002",
// "amfSetId": "[001,002]"
// }
// ]
// }
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("NSSFAvailableAMFList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
resData["rows"] = v.([]any)
resData["total"] = len(v.([]any))
delete(resData, "data")
} else {
resData["rows"] = []any{}
resData["total"] = 0
}
return resData, nil
}
+280
View File
@@ -0,0 +1,280 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/ne/model"
)
// PCFRuleInfo PCF策略配置查询信息
func PCFRuleInfo(neInfo model.NeInfo, data map[string]string) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["imsi"]; ok && v != "" {
query = append(query, fmt.Sprintf("imsi=%s", v))
}
if v, ok := data["msisdn"]; ok && v != "" {
query = append(query, fmt.Sprintf("msisdn=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
var resData map[string]any
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("PCFRuleInfo Get \"%s\"", neUrl)
logger.Errorf("PCFRuleInfo %s", errStr)
return nil, fmt.Errorf("NeService PCF API Error")
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleInfo Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
if arr := v.([]any); len(arr) > 0 {
result := make([]map[string]any, len(arr))
for i, item := range arr {
result[i] = item.(map[string]any)
}
return result, nil
}
}
return []map[string]any{}, nil
}
// PCFRuleAdd PCF策略配置添加
func PCFRuleAdd(neInfo model.NeInfo, data any) error {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo", neInfo.IP, neInfo.Port)
resBytes, err := fetch.PostJSON(neUrl, data, nil)
if err != nil {
errStr := err.Error()
// 正常
if strings.HasPrefix(errStr, "201") {
return nil
}
// 错误结果
if strings.HasPrefix(errStr, "400") {
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleAdd Unmarshal %s", err.Error())
return err
}
return fmt.Errorf("%s", resData["cause"])
}
logger.Warnf("PCFRuleAdd Put \"%s\"", neUrl)
logger.Errorf("PCFRuleAdd %s", errStr)
return fmt.Errorf("NeService PCF API Error")
}
return nil
}
// PCFRuleAddBatch PCF策略配置批量添加
func PCFRuleAddBatch(neInfo model.NeInfo, data map[string]any, num int64) error {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo/batch/%d", neInfo.IP, neInfo.Port, num)
resBytes, err := fetch.PostJSON(neUrl, data, nil)
if err != nil {
errStr := err.Error()
// 正常
if strings.HasPrefix(errStr, "201") {
return nil
}
// 错误结果
if strings.HasPrefix(errStr, "400") {
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleAddBatch Unmarshal %s", err.Error())
return err
}
return fmt.Errorf("%s", resData["cause"])
}
logger.Warnf("PCFRuleAddBatch Put \"%s\"", neUrl)
logger.Errorf("PCFRuleAddBatch %s", errStr)
return fmt.Errorf("NeService PCF API Error")
}
return nil
}
// PCFRuleUpdate PCF策略配置修改
func PCFRuleUpdate(neInfo model.NeInfo, data map[string]any) error {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo", neInfo.IP, neInfo.Port)
resBytes, err := fetch.PutJSON(neUrl, data, nil)
if err != nil {
errStr := err.Error()
// 错误结果
if strings.HasPrefix(errStr, "400") {
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleUpdate Unmarshal %s", err.Error())
return err
}
return fmt.Errorf("%s", resData["cause"])
}
logger.Warnf("PCFRuleUpdate Put \"%s\"", neUrl)
logger.Errorf("PCFRuleUpdate %s", errStr)
return fmt.Errorf("NeService PCF API Error")
}
return nil
}
// PCFRuleUpdateBatch PCF策略配置批量修改
func PCFRuleUpdateBatch(neInfo model.NeInfo, data map[string]any, num int64) error {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo/batch/%d", neInfo.IP, neInfo.Port, num)
resBytes, err := fetch.PutJSON(neUrl, data, nil)
if err != nil {
errStr := err.Error()
// 错误结果
if strings.HasPrefix(errStr, "400") {
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleUpdateBatch Unmarshal %s", err.Error())
return err
}
return fmt.Errorf("%s", resData["cause"])
}
logger.Warnf("PCFRuleUpdateBatch Put \"%s\"", neUrl)
logger.Errorf("PCFRuleUpdateBatch %s", errStr)
return fmt.Errorf("NeService PCF API Error")
}
return nil
}
// PCFRuleDelete PCF策略配置删除
func PCFRuleDelete(neInfo model.NeInfo, imsi string) error {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo?imsi=%s", neInfo.IP, neInfo.Port, imsi)
resBytes, err := fetch.Delete(neUrl, nil)
if err != nil {
errStr := err.Error()
// 正常
if strings.HasPrefix(errStr, "204") {
return nil
}
// 错误结果
if strings.HasPrefix(errStr, "400") {
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleDelete Unmarshal %s", err.Error())
return err
}
return fmt.Errorf("%s", resData["cause"])
}
logger.Warnf("PCFRuleDelete Delete \"%s\"", neUrl)
logger.Errorf("PCFRuleDelete %s", errStr)
return fmt.Errorf("NeService PCF API Error")
}
return nil
}
// PCFRuleDeleteBatch PCF策略配置批量删除
func PCFRuleDeleteBatch(neInfo model.NeInfo, imsi string, num int64) error {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo/batch/%d?imsi=%s", neInfo.IP, neInfo.Port, num, imsi)
resBytes, err := fetch.Delete(neUrl, nil)
if err != nil {
errStr := err.Error()
// 正常
if strings.HasPrefix(errStr, "204") {
return nil
}
// 错误结果
if strings.HasPrefix(errStr, "400") {
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleDeleteBatch Unmarshal %s", err.Error())
return err
}
return fmt.Errorf("%s", resData["cause"])
}
logger.Warnf("PCFRuleDeleteBatch Delete \"%s\"", neUrl)
logger.Errorf("PCFRuleDeleteBatch %s", errStr)
return fmt.Errorf("NeService PCF API Error")
}
return nil
}
// PCFRuleExport PCF策略配置导出
func PCFRuleExport(neInfo model.NeInfo, data map[string]string) ([]byte, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo/file/export", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["fileType"]; ok && v != "" {
query = append(query, fmt.Sprintf("fileType=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
resBytes, err := fetch.Get(neUrl, nil, 30_000)
if err != nil {
logger.Warnf("PCFRuleExport Get \"%s\"", neUrl)
logger.Errorf("PCFRuleExport %s", err.Error())
return nil, fmt.Errorf("NeService PCF API Error")
}
return resBytes, nil
}
// PCFRuleImport PCF策略配置导入
func PCFRuleImport(neInfo model.NeInfo, data map[string]any) (string, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/pcf/objectType/ueInfo/file/import", neInfo.IP, neInfo.Port)
resBytes, err := fetch.PutJSON(neUrl, data, nil)
var resData map[string]any
if err != nil {
errStr := err.Error()
// 错误结果
if strings.HasPrefix(errStr, "400") {
// 序列化结果
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleDeleteBatch Unmarshal %s", err.Error())
return "", err
}
return "", fmt.Errorf("%s", resData["cause"])
}
logger.Warnf("PCFRuleImport Put \"%s\"", neUrl)
logger.Errorf("PCFRuleImport %s", errStr)
return "", fmt.Errorf("NeService PCF API Error")
}
// 200 成功无数据时
if len(resBytes) == 0 {
return "", nil
}
// 序列化结果
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("PCFRuleImport Unmarshal %s", err.Error())
return "", err
}
return fmt.Sprint(resData["data"]), nil
}
+98
View File
@@ -0,0 +1,98 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/ne/model"
)
// SMFSubNum SMF在线订阅用户数量 只含5G用户数据
//
// 返回结果 0
func SMFSubNum(neInfo model.NeInfo) (int64, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/smf/objectType/ueNum", neInfo.IP, neInfo.Port)
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("SMFSubNum Get \"%s\"", neUrl)
logger.Errorf("SMFSubNum %s", errStr)
return 0, fmt.Errorf("NeService SMF API Error")
}
// 序列化结果 {"data":{"ueNum":0}}
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("IMSUeSession Unmarshal %s", err.Error())
return 0, err
}
// 固定返回字段,方便前端解析
var ueNum int64 = 0
if v, ok := resData["data"]; ok && v != nil {
if num := v.(map[string]any)["ueNum"]; num != nil {
ueNum = parse.Number(num)
}
}
return ueNum, nil
}
// SMFSubInfoList SMF在线订阅用户列表信息
//
// 查询参数 {"imsi":"360000100000130","msisdn":"8612300000130","upstate":"Inactive","pageNum":"1"}
//
// 返回结果 {"rows":[],"total":0}
func SMFSubInfoList(neInfo model.NeInfo, data map[string]string) (map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/smf/objectType/ueInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["imsi"]; ok && v != "" {
query = append(query, fmt.Sprintf("imsi=%s", v))
}
if v, ok := data["msisdn"]; ok && v != "" {
query = append(query, fmt.Sprintf("msisdn=%s", v))
}
if v, ok := data["upstate"]; ok && v != "" {
query = append(query, fmt.Sprintf("upstate=%s", v))
}
// 固定页数量50条
if v, ok := data["pageNum"]; ok && v != "" {
pageNum := parse.Number(v)
query = append(query, fmt.Sprintf("pageNum=%d", pageNum))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
logger.Warnf("SMFSubInfo Get \"%s\"", neUrl)
logger.Errorf("SMFSubInfo %s", err.Error())
return nil, fmt.Errorf("NeService SMF API Error")
}
// 序列化结果 {"data":[],"total":0}
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("SMFSubInfo Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
resData["rows"] = v.([]any)
delete(resData, "data")
} else {
resData["rows"] = []any{}
}
if v, ok := resData["total"]; !ok || v == nil {
resData["total"] = 0
}
return resData, nil
}
+39
View File
@@ -0,0 +1,39 @@
// 网元UDM服务,可能是8080、33030端口服务
// 融合的UDM网元视情况调整。
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
)
// UDMImportAuth UDM导入鉴权数据
//
// data参数 {path:"服务器文件路径", k4:"可选,k4为空时Ki不加密。"}
func UDMImportAuth(udmIP string, data map[string]any) (string, error) {
// 网元参数配置新增(array)
neUrl := fmt.Sprintf("http://%s:8080/ue-manage/v1/import-auth", udmIP)
resBytes, err := fetch.PostJSON(neUrl, data, nil)
var resData map[string]string
if err != nil {
errStr := err.Error()
logger.Warnf("UDMImportAuth Post \"%s\"", neUrl)
logger.Errorf("UDMImportAuth %s", errStr)
return "", fmt.Errorf("NeService UDM API Error")
}
// 序列化结果
if err = json.Unmarshal(resBytes, &resData); err != nil {
logger.Errorf("UDMImportAuth Unmarshal %s", err.Error())
return "", err
}
if v, ok := resData["code"]; ok && v == "00000" {
return strings.TrimSpace(strings.ToLower(resData["message"])), nil
}
return "", fmt.Errorf("%s", resData["message"])
}
+24
View File
@@ -0,0 +1,24 @@
package model
// NeConfig 网元_参数配置可用属性值
type NeConfig struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" binding:"required" gorm:"column:ne_type"` // 网元类型
ParamName string `json:"paramName" binding:"required" gorm:"column:param_name"` // 参数名
ParamDisplay string `json:"paramDisplay" binding:"required" gorm:"column:param_display"` // 参数显示名
ParamType string `json:"paramType" gorm:"column:param_type"` // 参数类型 list列表单层 array数组多层
ParamJson string `json:"-" gorm:"column:param_json"` // accesss属性控制:只读read-only/read/ro 读写read-write
ParamSort int64 `json:"paramSort" gorm:"column:param_sort"` // 参数排序
ParamPerms string `json:"paramPerms" gorm:"column:param_perms"` // 操作权限 get只读 put可编辑 delete可删除 post可新增
Visible string `json:"visible" gorm:"column:visible"` // 可见性 默认public 单独网元self
UpdateTime int64 `json:"updateTime" gorm:"column:update_time"` // 更新时间
// ====== 非数据库字段属性 ======
ParamData []map[string]any `json:"paramData,omitempty" binding:"required" gorm:"-"` // 与ParamJSONStr配合转换
}
// TableName 表名称
func (*NeConfig) TableName() string {
return "ne_config"
}
+23
View File
@@ -0,0 +1,23 @@
package model
// NeConfigBackup 网元配置文件备份记录 ne_config_backup
type NeConfigBackup struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type"` // 网元类型
NeId string `json:"neId" gorm:"column:ne_id"` // 网元ID
Name string `json:"name" gorm:"column:name"` // 压缩包名称
Path string `json:"path" gorm:"column:path"` // 压缩包位置
Remark string `json:"remark" gorm:"column:remark"` // 备注
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 表名称
func (*NeConfigBackup) TableName() string {
return "ne_config_backup"
}
+41
View File
@@ -0,0 +1,41 @@
package model
import "encoding/json"
// NeHost 网元主机表 ne_host
type NeHost struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
HostType string `json:"hostType" gorm:"column:host_type" binding:"oneof=ssh telnet redis"` // 连接类型 ssh telnet redis
GroupID string `json:"groupId" gorm:"column:group_id"` // 分组(0默认 1网元 2系统)
Title string `json:"title" gorm:"column:title"` // 标题名称
Addr string `json:"addr" gorm:"column:addr" binding:"required"` // 主机地址
Port int64 `json:"port" gorm:"column:port" binding:"required,number,max=65535,min=1"` // 端口 22 4100 6379
User string `json:"user" gorm:"column:user" binding:"required"` // 认证用户名
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"` // 认证私钥密码
DBName string `json:"dbName" gorm:"column:db_name"` // 数据库名称
Remark string `json:"remark" gorm:"column:remark"` // 备注
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 表名称
func (*NeHost) TableName() string {
return "ne_host"
}
// CopyTo 网元主机信息将josn同key名的结构体复制给另一个结构体
func (m *NeHost) CopyTo(to interface{}) error {
b, err := json.Marshal(m)
if err != nil {
return err
}
if err = json.Unmarshal(b, to); err != nil {
return err
}
return nil
}
+20
View File
@@ -0,0 +1,20 @@
package model
// NeHostCmd 网元主机命令表 ne_host_cmd
type NeHostCmd struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
CmdType string `json:"cmdType" gorm:"column:cmd_type"` // 命令类型
GroupID string `json:"groupId" gorm:"column:group_id"` // 分组(0默认 1快速命令)
Title string `json:"title" gorm:"column:title" binding:"required"` // 标题名称
Command string `json:"command" gorm:"column:command" binding:"required"` // 命令字符串
Remark string `json:"remark" gorm:"column:remark"` // 备注
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 表名称
func (*NeHostCmd) TableName() string {
return "ne_host_cmd"
}
+37
View File
@@ -0,0 +1,37 @@
package model
// NeInfo 网元信息对象 ne_info
type NeInfo struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type" binding:"required"` // 网元类型
NeId string `json:"neId" gorm:"column:ne_id" binding:"required"` // 网元ID
RmUID string `json:"rmUid" gorm:"column:rm_uid"` // 网元资源唯一标识
NeName string `json:"neName" gorm:"column:ne_name"` // 网元名称
IP string `json:"ip" gorm:"column:ip" binding:"required"` // 网元服务IP
Port int64 `json:"port" gorm:"column:port" binding:"required,number,max=65535,min=1"` // 端口
PvFlag string `json:"pvFlag" gorm:"column:pv_flag" binding:"omitempty,oneof=PNF VNF"` // 网元虚拟化标识 物理PNF 虚拟VNF
Province string `json:"province" gorm:"column:province"` // 省份地域
VendorName string `json:"vendorName" gorm:"column:vendor_name"` // 厂商名称
Dn string `json:"dn" gorm:"column:dn"` // 网络标识
NeAddress string `json:"neAddress" gorm:"column:ne_address"` // MAC地址
HostIDs string `json:"hostIds" gorm:"column:host_ids"` // 网元主机ID组 数据格式(ssh,telnet) UDM(ssh,telnet,redis) UPF(ssh,telnet,telnet)
Status int64 `json:"status" gorm:"column:status"` // 网元状态 0离线 1在线 2配置待下发 3备用模式
Remark string `json:"remark" gorm:"column:remark"` // 备注
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"` // 更新时间
// ====== 非数据库字段属性 ======
// 服务状态
ServerState map[string]any `json:"serverState,omitempty" gorm:"-"`
// 主机对象组
Hosts []NeHost `json:"hosts,omitempty" gorm:"-"`
}
// TableName 表名称
func (*NeInfo) TableName() string {
return "ne_info"
}
+28
View File
@@ -0,0 +1,28 @@
package model
// NeLicense 网元授权激活信息 ne_license
type NeLicense struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type" binding:"required"` // 网元类型
NeId string `json:"neId" gorm:"column:ne_id" binding:"required"` // 网元ID
ActivationRequestCode string `json:"activationRequestCode" gorm:"column:activation_request_code"` // 激活申请代码
LicensePath string `json:"licensePath" gorm:"column:license_path"` // 激活授权文件
Capability int64 `json:"capability" gorm:"column:capability"` // 容量
SerialNum string `json:"serialNum" gorm:"column:serial_num"` // 序列号
ExpiryDate string `json:"expiryDate" gorm:"column:expiry_date"` // 许可证到期日期
Status string `json:"status" gorm:"column:status"` // 状态 0无效 1有效
Remark string `json:"remark" gorm:"column:remark"` // 备注
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"` // 更新时间
// ====== 非数据库字段属性 ======
Reload bool `json:"reload,omitempty" gorm:"-"` // 刷新重启网元
}
// TableName 表名称
func (*NeLicense) TableName() string {
return "ne_license"
}
+23
View File
@@ -0,0 +1,23 @@
package model
// NeSoftware 网元软件包 ne_software
type NeSoftware struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type" binding:"required"` // 网元类型
Name string `json:"name" gorm:"column:name" binding:"required"` // 包名称
Path string `json:"path" gorm:"column:path"` // 包路径
Version string `json:"version" gorm:"column:version" binding:"required"` // 包版本
Description string `json:"description" gorm:"column: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 表名称
func (*NeSoftware) TableName() string {
return "ne_software"
}
+27
View File
@@ -0,0 +1,27 @@
package model
// NeVersion 网元版本信息 ne_version
type NeVersion struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type" binding:"required"` // 网元类型
NeId string `json:"neId" gorm:"column:ne_id" binding:"required"` // 网元ID
Name string `json:"name" gorm:"column:name"` // 当前包名
Version string `json:"version" gorm:"column:version" binding:"required"` // 当前版本
Path string `json:"path" gorm:"column:path" binding:"required"` // 当前软件包
PreName string `json:"preName" gorm:"column:pre_name"` // 上一版本包名
PreVersion string `json:"preVersion" gorm:"column:pre_version"` // 上一版本
PrePath string `json:"prePath" gorm:"column:pre_path"` // 上一版本软件包
NewName string `json:"newName" gorm:"column:new_name"` // 新版本包名
NewVersion string `json:"newVersion" gorm:"column:new_version"` // 新版本
NewPath string `json:"newPath" gorm:"column:new_path"` // 新版本软件包
Status string `json:"status" gorm:"column: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 表名称
func (*NeVersion) TableName() string {
return "ne_version"
}
+369
View File
@@ -0,0 +1,369 @@
package ne
import (
"be.ems/src/framework/logger"
"be.ems/src/framework/middleware"
"be.ems/src/framework/middleware/collectlogs"
"be.ems/src/modules/ne/controller"
"be.ems/src/modules/ne/service"
"github.com/gin-gonic/gin"
)
// 模块路由注册
func Setup(router *gin.Engine) {
logger.Infof("开始加载 ====> ne 模块路由")
// 启动时需要的初始参数
InitLoad()
// 网元操作处理
neActionGroup := router.Group("/ne/action")
{
neActionGroup.GET("/files",
middleware.AuthorizeUser(nil),
controller.NewNeAction.Files,
)
neActionGroup.GET("/pullFile",
middleware.AuthorizeUser(nil),
controller.NewNeAction.PullFile,
)
neActionGroup.POST("/pushFile",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neAction", collectlogs.BUSINESS_TYPE_IMPORT)),
controller.NewNeAction.PushFile,
)
neActionGroup.GET("/pullDirZip",
middleware.AuthorizeUser(nil),
controller.NewNeAction.PullDirZip,
)
neActionGroup.GET("/viewFile",
middleware.AuthorizeUser(nil),
controller.NewNeAction.ViewFile,
)
neActionGroup.PUT("/service",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neAction", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeAction.Service,
)
}
// 网元信息
neInfoGroup := router.Group("/ne/info")
{
neInfoGroup.GET("/state",
middleware.AuthorizeUser(nil),
controller.NewNeInfo.State,
)
neInfoGroup.GET("/byTypeAndID",
middleware.AuthorizeUser(nil),
controller.NewNeInfo.NeTypeAndID,
)
neInfoGroup.GET("/listAll",
middleware.AuthorizeUser(nil),
controller.NewNeInfo.ListAll,
)
neInfoGroup.GET("/para5GFile",
middleware.AuthorizeUser(nil),
controller.NewNeInfo.Para5GFileRead,
)
neInfoGroup.PUT("/para5GFile",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeInfo.Para5GFileWrite,
)
neInfoGroup.GET("/oamFile",
middleware.AuthorizeUser(nil),
controller.NewNeInfo.OAMFileRead,
)
neInfoGroup.PUT("/oamFile",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeInfo.OAMFileWrite,
)
neInfoGroup.GET("/list",
middleware.AuthorizeUser(nil),
controller.NewNeInfo.List,
)
neInfoGroup.GET("/:id",
middleware.CryptoApi(false, true),
middleware.AuthorizeUser(nil),
controller.NewNeInfo.Info,
)
neInfoGroup.POST("",
middleware.CryptoApi(true, true),
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeInfo.Add,
)
neInfoGroup.PUT("",
middleware.CryptoApi(true, true),
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeInfo.Edit,
)
neInfoGroup.DELETE(":id",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeInfo.Remove,
)
}
// 网元主机
neHostGroup := router.Group("/ne/host")
{
neHostGroup.GET("/list",
middleware.AuthorizeUser(nil),
controller.NewNeHost.List,
)
neHostGroup.GET("/:id",
middleware.CryptoApi(false, true),
middleware.AuthorizeUser(nil),
controller.NewNeHost.Info,
)
neHostGroup.POST("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeHost.Add,
)
neHostGroup.PUT("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeHost.Edit,
)
neHostGroup.DELETE("/:id",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeHost.Remove,
)
neHostGroup.POST("/test",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeHost.Test,
)
neHostGroup.POST("/cmd",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeHost.Cmd,
)
neHostGroup.POST("/checkBySSH",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeHost.CheckBySSH,
)
neHostGroup.POST("/authorizedBySSH",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeHost.AuthorizedBySSH,
)
}
// 网元主机命令
neHostCmdGroup := router.Group("/ne/hostCmd")
{
neHostCmdGroup.GET("/list",
middleware.AuthorizeUser(nil),
controller.NewNeHostCmd.List,
)
neHostCmdGroup.GET("/:id",
middleware.AuthorizeUser(nil),
controller.NewNeHostCmd.Info,
)
neHostCmdGroup.POST("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHostCmd", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeHostCmd.Add,
)
neHostCmdGroup.PUT("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHostCmd", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeHostCmd.Edit,
)
neHostCmdGroup.DELETE(":id",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHostCmd", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeHostCmd.Remove,
)
}
// 网元版本信息
neVersionGroup := router.Group("/ne/version")
{
neVersionGroup.GET("/list",
middleware.AuthorizeUser(nil),
controller.NewNeVersion.List,
)
neVersionGroup.GET("/:id",
middleware.AuthorizeUser(nil),
controller.NewNeVersion.Info,
)
neVersionGroup.POST("/operate",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neVersion", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeVersion.Operate,
)
}
// 网元软件包信息
neSoftwareGroup := router.Group("/ne/software")
{
neSoftwareGroup.GET("/list",
middleware.AuthorizeUser(nil),
controller.NewNeSoftware.List,
)
neSoftwareGroup.GET("/:id",
middleware.AuthorizeUser(nil),
controller.NewNeSoftware.Info,
)
neSoftwareGroup.POST("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeSoftware.Add,
)
neSoftwareGroup.PUT("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeSoftware.Edit,
)
neSoftwareGroup.DELETE(":id",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeSoftware.Remove,
)
neSoftwareGroup.POST("/newNeVersion",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeSoftware.NewNeVersion,
)
}
// 网元授权激活信息
neLicenseGroup := router.Group("/ne/license")
{
neLicenseGroup.GET("/list",
middleware.AuthorizeUser(nil),
controller.NewNeLicense.List,
)
neLicenseGroup.GET("/:id",
middleware.AuthorizeUser(nil),
controller.NewNeLicense.Info,
)
neLicenseGroup.GET("/byTypeAndID",
middleware.AuthorizeUser(nil),
controller.NewNeLicense.NeTypeAndID,
)
neLicenseGroup.GET("/code",
middleware.AuthorizeUser(nil),
controller.NewNeLicense.Code,
)
neLicenseGroup.POST("/change",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neLicense", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeLicense.Change,
)
neLicenseGroup.GET("/state",
middleware.AuthorizeUser(nil),
controller.NewNeLicense.State,
)
}
// 网元参数配置
neConfigGroup := router.Group("/ne/config")
{
// 网元参数配置可用属性值
neConfigGroup.GET("/list",
middleware.AuthorizeUser(nil),
controller.NewNeConfig.List,
)
neConfigGroup.GET("/info/:id",
middleware.AuthorizeUser(nil),
controller.NewNeConfig.Info,
)
neConfigGroup.POST("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeConfig.Add,
)
neConfigGroup.PUT("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeConfig.Edit,
)
neConfigGroup.DELETE("",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeConfig.Remove,
)
neConfigGroup.GET("/list/:neType",
middleware.AuthorizeUser(nil),
controller.NewNeConfig.ListByNeType,
)
// 网元参数配置数据
neConfigGroup.GET("/data",
middleware.AuthorizeUser(nil),
controller.NewNeConfig.DataInfo,
)
neConfigGroup.PUT("/data",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeConfig.DataEdit,
)
neConfigGroup.POST("/data",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeConfig.DataAdd,
)
neConfigGroup.DELETE("/data",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeConfig.DataRemove,
)
}
// 网元配置文件备份记录
neConfigBackupGroup := router.Group("/ne/config/backup")
{
neConfigBackupGroup.GET("/list",
middleware.AuthorizeUser(nil),
controller.NewNeConfigBackup.List,
)
neConfigBackupGroup.GET("/download",
middleware.AuthorizeUser(nil),
controller.NewNeConfigBackup.Download,
)
neConfigBackupGroup.PUT("",
middleware.AuthorizeUser(map[string][]string{"hasPerms": {"ne:neConfigBackup:edit"}}),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfigBackup", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeConfigBackup.Edit,
)
neConfigBackupGroup.DELETE("",
middleware.AuthorizeUser(map[string][]string{"hasPerms": {"ne:neConfigBackup:remove"}}),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfigBackup", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeConfigBackup.Remove,
)
neConfigBackupGroup.POST("/import",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfigBackup", collectlogs.BUSINESS_TYPE_IMPORT)),
controller.NewNeConfigBackup.Import,
)
neConfigBackupGroup.POST("/export",
middleware.AuthorizeUser(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfigBackup", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewNeConfigBackup.Export,
)
}
}
// InitLoad 初始参数
func InitLoad() {
// 启动时,清除缓存-网元类型
service.NewNeInfo.ClearNeCacheByNeType("*")
service.NewNeInfo.FindByRmuid("")
// 启动时,网元公共参数数据记录到全局变量
if para5GMap, err := service.NewNeInfo.NeConfPara5GRead(); para5GMap != nil && err == nil {
service.NewNeInfo.NeConfPara5GWirte(para5GMap, nil)
}
// 启动时,清除缓存-网元参数配置可用属性值
service.NewNeConfig.ClearNeCacheByNeType("*")
service.NewNeConfig.RefreshByNeTypeAndNeID("*")
}
+240
View File
@@ -0,0 +1,240 @@
package ne
import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"testing"
"time"
"be.ems/src/modules/ne/model"
"gopkg.in/yaml.v3"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
const (
// 数据库
DbHost = "192.168.9.58"
DbPort = 13306
DbUser = "root"
DbPassswd = "1000omc@kp!"
DbName = "omc_db_mainv2"
// 配置文件路径
configParamDir = "../../../local/param"
// configParamFile = "*" // 目录下全部更新
configParamFile = "amf_param_config.yaml" // 单文件更新
)
func TestConfig(t *testing.T) {
fileNameList, err := getDirFileNameList(configParamDir)
if err != nil {
log.Fatal(err)
return
}
if configParamFile == "*" {
for _, v := range fileNameList {
params := parseData(filepath.Join(configParamDir, v))
if params == nil {
return
}
saveData(params)
}
} else {
params := parseData(filepath.Join(configParamDir, configParamFile))
if params == nil {
return
}
saveData(params)
}
}
// ========= Main =============
// parseData 文件转map数据
func parseData(filePaht string) []map[string]string {
data, err := parseStrToMap(filePaht)
if err != nil {
log.Printf("parseStrToMap => %s", err.Error())
return nil
}
params, err := parseParamConfig(data)
if err != nil {
log.Printf("parseParamConfig => %s", err.Error())
return nil
}
return params
}
// saveData 保存数据
func saveData(params []map[string]string) {
// 定义排序函数
sort.Slice(params, func(i, j int) bool {
paramSortI := params[i]["paramSort"]
if len(paramSortI) == 0 || paramSortI == "" {
paramSortI = "0"
}
paramSortJ := params[j]["paramSort"]
if len(paramSortJ) == 0 || paramSortJ == "" {
paramSortJ = "0"
}
// 将 age 字段转换为整数进行比较
si, _ := strconv.Atoi(paramSortI)
sj, _ := strconv.Atoi(paramSortJ)
return si < sj
})
// 遍历插入
for _, v := range params {
// 排序
paramSort := v["paramSort"]
if len(paramSort) == 0 || paramSort == "" {
paramSort = "0"
}
sort, err := strconv.ParseInt(paramSort, 10, 64)
if err != nil {
sort = 0
}
// 可见性 默认public
visible := v["visible"]
if len(visible) == 0 || visible == "" {
visible = "public"
}
neConfig := model.NeConfig{
NeType: v["neType"],
ParamName: v["paramName"],
ParamDisplay: v["paramDisplay"],
ParamType: v["paramType"],
ParamJson: v["paramJson"],
ParamPerms: v["paramPerms"],
Visible: visible,
ParamSort: sort,
}
neConfig.ID = saveDB(neConfig)
log.Println(neConfig.ID, neConfig.NeType, neConfig.ParamDisplay)
}
}
// ========= DB =============
var gdb *gorm.DB
// connDB 连接到数据库
func connDB() *gorm.DB {
if gdb != nil {
return gdb
}
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", DbUser, DbPassswd, DbHost, DbPort, DbName)
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Minute, // Slow SQL threshold
LogLevel: logger.Error, // Log level
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
ParameterizedQueries: true, // Don't include params in the SQL log
Colorful: false, // Disable color
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger})
if err != nil {
log.Fatalln(err)
}
gdb = db
return gdb
}
// saveDB 表插入或更新
func saveDB(s model.NeConfig) int64 {
db := connDB()
// 检查是否存在
var id int64
db.Raw("SELECT id FROM ne_config WHERE ne_type = ? AND param_name = ?", s.NeType, s.ParamName).Scan(&id)
// 更新时间
s.UpdateTime = time.Now().UnixMilli()
if id > 0 {
s.ID = id
db.Save(&s)
} else {
db.Create(&s)
}
return s.ID
}
// ========= Utils =============
// getDirFileNameList 获取文件目录下所有文件名称,不含目录名称
func getDirFileNameList(dirPath string) ([]string, error) {
fileNames := []string{}
dir, err := os.Open(dirPath)
if err != nil {
return fileNames, nil
}
defer dir.Close()
fileInfos, err := dir.Readdir(-1)
if err != nil {
return fileNames, err
}
for _, fileInfo := range fileInfos {
if fileInfo.Mode().IsRegular() {
fileNames = append(fileNames, fileInfo.Name())
}
}
return fileNames, nil
}
// parseStrToMap 解析内容string到map
func parseStrToMap(filePath string) (map[string]any, error) {
// 读取文件内容
bytes, err := os.ReadFile(filePath)
if err != nil {
return nil, err
}
content := string(bytes)
var configMap map[string]any
err = yaml.Unmarshal([]byte(content), &configMap)
return configMap, err
}
// parseParamConfig 解析内容文件数据
func parseParamConfig(data map[string]any) ([]map[string]string, error) {
paramMapArr := make([]map[string]string, 0)
for k, v := range data {
for ik, iv := range v.(map[string]any) {
itemMap := make(map[string]string)
itemMap["neType"] = strings.ToUpper(k)
itemMap["paramName"] = ik
for iik, iiv := range iv.(map[string]any) {
switch iik {
case "display":
itemMap["paramDisplay"] = iiv.(string)
case "sort":
itemMap["paramSort"] = fmt.Sprint(iiv)
case "visible":
itemMap["visible"] = fmt.Sprint(iiv)
case "perms", "method":
itemMap["paramPerms"] = iiv.(string)
case "list", "array": // 参数类型为数组
itemMap["paramType"] = iik
strByte, _ := json.Marshal(iiv)
itemMap["paramJson"] = string(strByte)
}
}
paramMapArr = append(paramMapArr, itemMap)
}
}
return paramMapArr, nil
}
+125
View File
@@ -0,0 +1,125 @@
package repository
import (
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/ne/model"
)
// 实例化数据层 NeConfig 结构体
var NewNeConfig = &NeConfig{}
// NeConfig 网元参数配置可用属性值 数据层处理
type NeConfig struct{}
// SelectByPage 分页查询集合
func (r NeConfig) SelectByPage(query map[string]string) ([]model.NeConfig, int64) {
tx := db.DB("").Model(&model.NeConfig{})
// 查询条件拼接
if v, ok := query["neType"]; ok && v != "" {
tx = tx.Where("ne_type = ?", v)
}
if v, ok := query["paramName"]; ok && v != "" {
tx = tx.Where("param_name = ?", v)
}
// 查询结果
var total int64 = 0
rows := []model.NeConfig{}
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return rows, total
}
// 查询数据分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
err := tx.Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows, total
}
return rows, total
}
// Select 查询集合
func (r NeConfig) Select(param model.NeConfig) []model.NeConfig {
tx := db.DB("").Model(&model.NeConfig{})
// 查询条件拼接
if param.NeType != "" {
tx = tx.Where("ne_type = ?", param.NeType)
}
if param.ParamName != "" {
tx = tx.Where("param_name = ?", param.ParamName)
}
// 查询数据
rows := []model.NeConfig{}
if err := tx.Order("param_sort asc").Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// SelectByIds 通过ID查询
func (r NeConfig) SelectByIds(ids []int64) []model.NeConfig {
rows := []model.NeConfig{}
if len(ids) <= 0 {
return rows
}
tx := db.DB("").Model(&model.NeConfig{})
// 构建查询条件
tx = tx.Where("id in ?", ids)
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// Insert 新增信息
func (r NeConfig) Insert(param model.NeConfig) int64 {
param.UpdateTime = time.Now().UnixMilli()
// 执行插入
if err := db.DB("").Create(&param).Error; err != nil {
logger.Errorf("insert err => %v", err.Error())
return 0
}
return param.ID
}
// Update 修改信息
func (r NeConfig) Update(param model.NeConfig) int64 {
if param.ID == 0 {
return 0
}
param.UpdateTime = time.Now().UnixMilli()
tx := db.DB("").Model(&model.NeConfig{})
// 构建查询条件
tx = tx.Where("id = ?", param.ID)
tx = tx.Omit("id")
// 执行更新
if err := tx.Updates(param).Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// DeleteByIds 批量删除信息
func (r NeConfig) DeleteByIds(ids []int64) int64 {
if len(ids) <= 0 {
return 0
}
tx := db.DB("").Where("id in ?", ids)
if err := tx.Delete(&model.NeConfig{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
@@ -0,0 +1,119 @@
package repository
import (
"fmt"
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/ne/model"
)
// 实例化数据层 NeConfigBackup 结构体
var NewNeConfigBackup = &NeConfigBackup{}
// NeConfigBackup 网元配置文件备份记录 数据层处理
type NeConfigBackup struct{}
// SelectByPage 分页查询集合
func (r NeConfigBackup) SelectByPage(query map[string]string) ([]model.NeConfigBackup, int64) {
tx := db.DB("").Model(&model.NeConfigBackup{})
// 查询条件拼接
if v, ok := query["neType"]; ok && v != "" {
tx = tx.Where("ne_type = ?", v)
}
if v, ok := query["neId"]; ok && v != "" {
tx = tx.Where("ne_id = ?", v)
}
if v, ok := query["name"]; ok && v != "" {
tx = tx.Where("name like ?", fmt.Sprintf("%%%s%%", v))
}
// 查询结果
var total int64 = 0
rows := []model.NeConfigBackup{}
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return rows, total
}
// 查询数据分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
err := tx.Order("id desc").Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows, total
}
return rows, total
}
// SelectByIds 通过ID查询信息
func (r NeConfigBackup) SelectByIds(ids []int64) []model.NeConfigBackup {
rows := []model.NeConfigBackup{}
if len(ids) <= 0 {
return rows
}
tx := db.DB("").Model(&model.NeConfigBackup{})
// 构建查询条件
tx = tx.Where("id in ?", ids)
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// Insert 新增信息 返回新增数据ID
func (r NeConfigBackup) Insert(item model.NeConfigBackup) int64 {
if item.CreateBy != "" {
ms := time.Now().UnixMilli()
item.UpdateBy = item.CreateBy
item.UpdateTime = ms
item.CreateTime = ms
}
// 执行插入
if err := db.DB("").Create(&item).Error; err != nil {
logger.Errorf("insert err => %v", err.Error())
return 0
}
return item.ID
}
// Update 修改信息 返回受影响行数
func (r NeConfigBackup) Update(item model.NeConfigBackup) int64 {
if item.ID <= 0 {
return 0
}
if item.UpdateBy != "" {
item.UpdateTime = time.Now().UnixMilli()
}
tx := db.DB("").Model(&model.NeConfigBackup{})
// 构建查询条件
tx = tx.Where("id = ?", item.ID)
tx = tx.Omit("id", "create_by", "create_time")
// 执行更新
if err := tx.Updates(item).Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// DeleteByIds 批量删除信息 返回受影响行数
func (r NeConfigBackup) DeleteByIds(ids []int64) int64 {
if len(ids) <= 0 {
return 0
}
if len(ids) <= 0 {
return 0
}
tx := db.DB("").Where("id in ?", ids)
if err := tx.Delete(&model.NeConfigBackup{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
+177
View File
@@ -0,0 +1,177 @@
package repository
import (
"fmt"
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/ne/model"
)
// 实例化数据层 NeHost 结构体
var NewNeHost = &NeHost{}
// NeHost 网元主机连接 数据层处理
type NeHost struct{}
// SelectByPage 分页查询集合
func (r NeHost) SelectByPage(query map[string]string) ([]model.NeHost, int64) {
tx := db.DB("").Model(&model.NeHost{})
// 查询条件拼接
if v, ok := query["hostType"]; ok && v != "" {
tx = tx.Where("host_type = ?", v)
}
if v, ok := query["groupId"]; ok && v != "" {
tx = tx.Where("group_id = ?", v)
}
if v, ok := query["title"]; ok && v != "" {
tx = tx.Where("title like ?", fmt.Sprintf("%s%%", v))
}
// 查询结果
var total int64 = 0
rows := []model.NeHost{}
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return rows, total
}
// 查询数据分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
// 排序
if sv, ok := query["sortField"]; ok && sv != "" {
sortSql := fmt.Sprint(sv)
if sortSql == "updateTime" {
sortSql = "update_time"
}
if sortSql == "createTime" {
sortSql = "create_time"
}
if ov, ok := query["sortOrder"]; ok && ov != "" {
if fmt.Sprint(ov) == "desc" {
sortSql += " desc "
} else {
sortSql += " asc "
}
}
tx = tx.Order(sortSql)
}
err := tx.Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows, total
}
return rows, total
}
// SelectByIds 通过ID查询
func (r NeHost) SelectByIds(ids []int64) []model.NeHost {
rows := []model.NeHost{}
if len(ids) <= 0 {
return rows
}
tx := db.DB("").Model(&model.NeHost{})
// 构建查询条件
tx = tx.Where("id in ?", ids)
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// Insert 新增信息
func (r NeHost) Insert(param model.NeHost) int64 {
param.UpdateTime = time.Now().UnixMilli()
// 根据认证模式清除不必要的信息
if param.AuthMode == "0" {
param.PrivateKey = ""
param.PassPhrase = ""
}
if param.AuthMode == "1" {
param.Password = ""
}
if param.AuthMode == "2" {
param.Password = ""
param.PrivateKey = ""
param.PassPhrase = ""
}
// 执行插入
if err := db.DB("").Create(&param).Error; err != nil {
logger.Errorf("insert err => %v", err.Error())
return 0
}
return param.ID
}
// Update 修改信息
func (r NeHost) Update(param model.NeHost) int64 {
if param.ID == 0 {
return 0
}
// 根据认证模式清除不必要的信息
if param.AuthMode == "0" {
param.PrivateKey = ""
param.PassPhrase = ""
}
if param.AuthMode == "1" {
param.Password = ""
}
if param.AuthMode == "2" {
param.Password = ""
param.PrivateKey = ""
param.PassPhrase = ""
}
param.UpdateTime = time.Now().UnixMilli()
tx := db.DB("").Model(&model.NeHost{})
// 构建查询条件
tx = tx.Where("id = ?", param.ID)
tx = tx.Omit("id")
// 执行更新
if err := tx.Updates(param).Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// DeleteByIds 批量删除信息
func (r NeHost) DeleteByIds(ids []int64) int64 {
if len(ids) <= 0 {
return 0
}
tx := db.DB("").Where("id in ?", ids)
if err := tx.Delete(&model.NeHost{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// CheckUnique 检查信息是否唯一 返回数据ID
func (r NeHost) CheckUnique(param model.NeHost) int64 {
tx := db.DB("").Model(&model.NeHost{})
// 查询条件拼接
if param.HostType != "" {
tx = tx.Where("host_type = ?", param.HostType)
}
if param.GroupID != "" {
tx = tx.Where("group_id = ?", param.GroupID)
}
if param.Title != "" {
tx = tx.Where("title = ?", param.Title)
}
// 查询数据
var id int64 = 0
if err := tx.Select("id").Limit(1).Find(&id).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return id
}
return id
}
+131
View File
@@ -0,0 +1,131 @@
package repository
import (
"fmt"
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/ne/model"
)
// 实例化数据层 NeHostCmd 结构体
var NewNeHostCmd = &NeHostCmd{}
// NeHostCmd 网元主机连接 数据层处理
type NeHostCmd struct{}
// SelectByPage 分页查询集合
func (r NeHostCmd) SelectByPage(query map[string]string) ([]model.NeHostCmd, int64) {
tx := db.DB("").Model(&model.NeHostCmd{})
// 查询条件拼接
if v, ok := query["cmdType"]; ok && v != "" {
tx = tx.Where("cmd_type = ?", v)
}
if v, ok := query["groupId"]; ok && v != "" {
tx = tx.Where("group_id = ?", v)
}
if v, ok := query["title"]; ok && v != "" {
tx = tx.Where("title like ?", fmt.Sprintf("%s%%", v))
}
// 查询结果
var total int64 = 0
rows := []model.NeHostCmd{}
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return rows, total
}
// 查询数据分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
err := tx.Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows, total
}
return rows, total
}
// SelectByIds 通过ID查询
func (r NeHostCmd) SelectByIds(ids []int64) []model.NeHostCmd {
rows := []model.NeHostCmd{}
if len(ids) <= 0 {
return rows
}
tx := db.DB("").Model(&model.NeHostCmd{})
// 构建查询条件
tx = tx.Where("id in ?", ids)
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// Insert 新增信息
func (r NeHostCmd) Insert(param model.NeHostCmd) int64 {
param.UpdateTime = time.Now().UnixMilli()
// 执行插入
if err := db.DB("").Create(&param).Error; err != nil {
logger.Errorf("insert err => %v", err.Error())
return 0
}
return param.ID
}
// Update 修改信息
func (r NeHostCmd) Update(param model.NeHostCmd) int64 {
if param.ID == 0 {
return 0
}
param.UpdateTime = time.Now().UnixMilli()
tx := db.DB("").Model(&model.NeHostCmd{})
// 构建查询条件
tx = tx.Where("id = ?", param.ID)
tx = tx.Omit("id")
// 执行更新
if err := tx.Updates(param).Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// DeleteByIds 批量删除信息
func (r NeHostCmd) DeleteByIds(ids []int64) int64 {
if len(ids) <= 0 {
return 0
}
tx := db.DB("").Where("id in ?", ids)
if err := tx.Delete(&model.NeHostCmd{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// CheckUnique 检查信息是否唯一 返回数据ID
func (r NeHostCmd) CheckUnique(param model.NeHostCmd) int64 {
tx := db.DB("").Model(&model.NeHostCmd{})
// 查询条件拼接
if param.CmdType != "" {
tx = tx.Where("cmd_type = ?", param.CmdType)
}
if param.GroupID != "" {
tx = tx.Where("group_id = ?", param.GroupID)
}
if param.Title != "" {
tx = tx.Where("title = ?", param.Title)
}
// 查询数据
var id int64 = 0
if err := tx.Select("id").Limit(1).Find(&id).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return id
}
return id
}
+240
View File
@@ -0,0 +1,240 @@
package repository
import (
"fmt"
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/ne/model"
)
// 实例化数据层 NeInfo 结构体
var NewNeInfo = &NeInfo{}
// NeInfo 网元信息表 数据层处理
type NeInfo struct{}
// neListSort 网元列表预设排序
func (r NeInfo) neListSort(arr []model.NeInfo) []model.NeInfo {
// neListSort 网元列表预设排序
var list = []string{
"OMC",
"IMS",
"AMF",
"AUSF",
"UDR",
"UDM",
"SMF",
"PCF",
"NSSF",
"NRF",
"UPF",
"LMF",
"NEF",
"MME",
"N3IWF",
"MOCNGW",
"SMSC",
"SMSF",
"CBC",
"CHF",
"HLR",
"SGWC",
"IP-SM-GW",
"MMTel-AS",
"I-CSCF",
"P-CSCF",
"S-CSCF",
}
// 创建优先级映射
priority := make(map[string]int)
for i, v := range list {
priority[v] = i
}
// 冒泡排序
n := len(arr)
for i := 0; i < n-1; i++ {
for j := 0; j < n-i-1; j++ {
if priority[arr[j].NeType] > priority[arr[j+1].NeType] {
// 交换元素
arr[j], arr[j+1] = arr[j+1], arr[j]
}
}
}
return arr
}
// SelectByPage 分页查询集合
func (r NeInfo) SelectByPage(query map[string]string) ([]model.NeInfo, int64) {
tx := db.DB("").Model(&model.NeInfo{})
// 查询条件拼接
if v, ok := query["neType"]; ok && v != "" {
tx = tx.Where("ne_type = ?", v)
}
if v, ok := query["neId"]; ok && v != "" {
tx = tx.Where("ne_id = ?", v)
}
if v, ok := query["rmUid"]; ok && v != "" {
tx = tx.Where("rmUid like ?", fmt.Sprintf("%s%%", v))
}
// 查询结果
var total int64 = 0
rows := []model.NeInfo{}
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return rows, total
}
// 查询数据分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
err := tx.Order("ne_type asc, ne_id asc").Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows, total
}
return r.neListSort(rows), total
}
// SelectByIds 通过ID查询
func (r NeInfo) SelectByIds(ids []int64) []model.NeInfo {
rows := []model.NeInfo{}
if len(ids) <= 0 {
return rows
}
tx := db.DB("").Model(&model.NeInfo{})
// 构建查询条件
tx = tx.Where("id in ?", ids)
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// Insert 新增信息
func (r NeInfo) Insert(neInfo model.NeInfo) int64 {
if neInfo.CreateBy != "" {
ms := time.Now().UnixMilli()
neInfo.CreateTime = ms
neInfo.UpdateTime = ms
neInfo.UpdateBy = neInfo.CreateBy
}
tx := db.DB("").Create(&neInfo)
if err := tx.Error; err != nil {
logger.Errorf("CreateInBatches err => %v", err)
}
return neInfo.ID
}
// Update 修改信息
func (r NeInfo) Update(neInfo model.NeInfo) int64 {
if neInfo.ID <= 0 {
return 0
}
if neInfo.UpdateBy != "" {
neInfo.UpdateTime = time.Now().UnixMilli()
}
neInfo.UpdateTime = time.Now().UnixMilli()
tx := db.DB("").Model(&model.NeInfo{})
// 构建查询条件
tx = tx.Where("id = ?", neInfo.ID)
tx = tx.Omit("id", "create_by", "create_time")
// 执行更新
if err := tx.Updates(neInfo).Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// DeleteByIds 批量删除信息
func (r NeInfo) DeleteByIds(ids []int64) int64 {
if len(ids) <= 0 {
return 0
}
tx := db.DB("").Where("id in ?", ids)
if err := tx.Delete(&model.NeInfo{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// SelectList 查询列表
func (r NeInfo) SelectList(neInfo model.NeInfo) []model.NeInfo {
tx := db.DB("").Model(&model.NeInfo{})
// 构建查询条件
if neInfo.NeType != "" {
tx = tx.Where("ne_type = ?", neInfo.NeType)
}
if neInfo.NeId != "" {
tx = tx.Where("ne_id = ?", neInfo.NeId)
}
// 查询数据
rows := []model.NeInfo{}
if err := tx.Order("ne_type asc, ne_id asc").Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return r.neListSort(rows)
}
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
func (r NeInfo) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo {
tx := db.DB("").Model(&model.NeInfo{})
// 构建查询条件
tx = tx.Where("ne_type = ? and ne_id = ?", neType, neID)
// 查询数据
row := model.NeInfo{}
if err := tx.Limit(1).Find(&row).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return row
}
return row
}
// CheckUniqueNeTypeAndNeId 校验同类型下标识是否唯一
func (r NeInfo) CheckUniqueNeTypeAndNeId(neInfo model.NeInfo) int64 {
tx := db.DB("").Model(&model.NeInfo{})
// 查询条件拼接
if neInfo.NeType != "" {
tx = tx.Where("ne_type = ?", neInfo.NeType)
}
if neInfo.NeId != "" {
tx = tx.Where("ne_id = ?", neInfo.NeType)
}
// 查询数据
var id int64 = 0
if err := tx.Limit(1).Select("id").Find(&id).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return id
}
return id
}
// UpdateState 修改状态
func (r NeInfo) UpdateState(id int64, status int64) int64 {
if id <= 0 {
return 0
}
tx := db.DB("").Model(&model.NeInfo{})
// 构建查询条件
tx = tx.Where("id = ?", id)
tx.Updates(map[string]any{
"status": status,
"update_time": time.Now().UnixMilli(),
})
// 执行更新
if err := tx.Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
+149
View File
@@ -0,0 +1,149 @@
package repository
import (
"fmt"
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/ne/model"
)
// 实例化数据层 NeLicense 结构体
var NewNeLicense = &NeLicense{}
// NeLicense 网元授权激活信息 数据层处理
type NeLicense struct{}
// SelectByPage 分页查询集合
func (r NeLicense) SelectByPage(query map[string]string) ([]model.NeLicense, int64) {
tx := db.DB("").Model(&model.NeLicense{})
// 查询条件拼接
if v, ok := query["neType"]; ok && v != "" {
tx = tx.Where("ne_type = ?", v)
}
if v, ok := query["neId"]; ok && v != "" {
tx = tx.Where("ne_id = ?", v)
}
if v, ok := query["expiryDate"]; ok && v != "" {
tx = tx.Where("expiry_date = ?", v)
}
if v, ok := query["serialNum"]; ok && v != "" {
tx = tx.Where("serial_num = ?", v)
}
if v, ok := query["createBy"]; ok && v != "" {
tx = tx.Where("create_by like ?", fmt.Sprintf("%s%%", v))
}
// 查询结果
var total int64 = 0
rows := []model.NeLicense{}
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return rows, total
}
// 查询数据分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
tx = tx.Order("id desc")
err := tx.Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows, total
}
return rows, total
}
// Select 查询集合
func (r NeLicense) Select(param model.NeLicense) []model.NeLicense {
tx := db.DB("").Model(&model.NeLicense{})
// 查询条件拼接
if param.NeType != "" {
tx = tx.Where("ne_type = ?", param.NeType)
}
if param.NeId != "" {
tx = tx.Where("ne_id = ?", param.NeId)
}
if param.ExpiryDate != "" {
tx = tx.Where("expiry_date = ?", param.ExpiryDate)
}
if param.CreateBy != "" {
tx = tx.Where("create_by like ?", fmt.Sprintf("%s%%", param.CreateBy))
}
// 查询数据
rows := []model.NeLicense{}
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// SelectByIds 通过ID查询
func (r NeLicense) SelectByIds(ids []int64) []model.NeLicense {
rows := []model.NeLicense{}
if len(ids) <= 0 {
return rows
}
tx := db.DB("").Model(&model.NeLicense{})
// 构建查询条件
tx = tx.Where("id in ?", ids)
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// Insert 新增信息
func (r NeLicense) Insert(neInfo model.NeLicense) int64 {
if neInfo.CreateBy != "" {
ms := time.Now().UnixMilli()
neInfo.CreateTime = ms
neInfo.UpdateTime = ms
neInfo.UpdateBy = neInfo.CreateBy
}
tx := db.DB("").Create(&neInfo)
if err := tx.Error; err != nil {
logger.Errorf("CreateInBatches err => %v", err)
}
return neInfo.ID
}
// Update 修改信息
func (r NeLicense) Update(param model.NeLicense) int64 {
if param.ID <= 0 {
return 0
}
if param.UpdateBy != "" {
param.UpdateTime = time.Now().UnixMilli()
}
param.UpdateTime = time.Now().UnixMilli()
tx := db.DB("").Model(&model.NeLicense{})
// 构建查询条件
tx = tx.Where("id = ?", param.ID)
tx = tx.Omit("id", "create_by", "create_time")
// 执行更新
if err := tx.Updates(param).Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// DeleteByIds 批量删除信息
func (r NeLicense) DeleteByIds(ids []int64) int64 {
if len(ids) <= 0 {
return 0
}
tx := db.DB("").Where("id in ?", ids)
if err := tx.Delete(&model.NeLicense{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
+171
View File
@@ -0,0 +1,171 @@
package repository
import (
"fmt"
"strings"
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/ne/model"
)
// 实例化数据层 NeSoftware 结构体
var NewNeSoftware = &NeSoftware{}
// NeSoftware 网元软件包信息 数据层处理
type NeSoftware struct{}
// SelectByPage 分页查询集合
func (r NeSoftware) SelectByPage(query map[string]string) ([]model.NeSoftware, int64) {
tx := db.DB("").Model(&model.NeSoftware{})
// 查询条件拼接
if v, ok := query["neType"]; ok && v != "" {
if strings.Contains(v, ",") {
softwareTypeArr := strings.Split(v, ",")
tx = tx.Where("ne_type in ?", softwareTypeArr)
} else {
tx = tx.Where("ne_type = ?", v)
}
}
if v, ok := query["name"]; ok && v != "" {
tx = tx.Where("name like ?", fmt.Sprintf("%s%%", v))
}
if v, ok := query["version"]; ok && v != "" {
tx = tx.Where("version like ?", fmt.Sprintf("%s%%", v))
}
// 查询结果
var total int64 = 0
rows := []model.NeSoftware{}
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return rows, total
}
// 查询数据分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
tx = tx.Order("id desc")
err := tx.Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows, total
}
return rows, total
}
// Select 查询集合
func (r NeSoftware) Select(param model.NeSoftware) []model.NeSoftware {
tx := db.DB("").Model(&model.NeSoftware{})
// 查询条件拼接
if param.NeType != "" {
tx = tx.Where("ne_type = ?", param.NeType)
}
if param.Path != "" {
tx = tx.Where("path = ?", param.Path)
}
if param.Version != "" {
tx = tx.Where("version = ?", param.Version)
}
if param.Name != "" {
tx = tx.Where("name like ?", fmt.Sprintf("%s%%", param.Name))
}
// 查询数据
rows := []model.NeSoftware{}
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// SelectByIds 通过ID查询
func (r NeSoftware) SelectByIds(ids []int64) []model.NeSoftware {
rows := []model.NeSoftware{}
if len(ids) <= 0 {
return rows
}
tx := db.DB("").Model(&model.NeSoftware{})
// 构建查询条件
tx = tx.Where("id in ?", ids)
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// Insert 新增信息
func (r NeSoftware) Insert(param model.NeSoftware) int64 {
if param.CreateBy != "" {
ms := time.Now().UnixMilli()
param.CreateTime = ms
param.UpdateTime = ms
param.UpdateBy = param.CreateBy
}
tx := db.DB("").Create(&param)
if err := tx.Error; err != nil {
logger.Errorf("CreateInBatches err => %v", err)
}
return param.ID
}
// Update 修改信息
func (r NeSoftware) Update(param model.NeSoftware) int64 {
if param.ID <= 0 {
return 0
}
if param.UpdateBy != "" {
param.UpdateTime = time.Now().UnixMilli()
}
param.UpdateTime = time.Now().UnixMilli()
tx := db.DB("").Model(&model.NeSoftware{})
// 构建查询条件
tx = tx.Where("id = ?", param.ID)
tx = tx.Omit("id", "create_by", "create_time")
// 执行更新
if err := tx.Updates(param).Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// DeleteByIds 批量删除信息
func (r NeSoftware) DeleteByIds(ids []int64) int64 {
if len(ids) <= 0 {
return 0
}
tx := db.DB("").Where("id in ?", ids)
if err := tx.Delete(&model.NeSoftware{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// CheckUnique 检查信息是否唯一 返回数据ID
func (r NeSoftware) CheckUnique(param model.NeSoftware) int64 {
tx := db.DB("").Model(&model.NeSoftware{})
// 查询条件拼接
if param.NeType != "" {
tx = tx.Where("ne_type = ?", param.NeType)
}
if param.Path != "" {
tx = tx.Where("path = ?", param.Path)
}
if param.Version != "" {
tx = tx.Where("version = ?", param.Version)
}
// 查询数据
var id int64 = 0
if err := tx.Select("id").Limit(1).Find(&id).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return id
}
return id
}
+149
View File
@@ -0,0 +1,149 @@
package repository
import (
"fmt"
"time"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/ne/model"
)
// 实例化数据层 NeVersion 结构体
var NewNeVersion = &NeVersion{}
// NeVersion 网元版本信息 数据层处理
type NeVersion struct{}
// SelectByPage 分页查询集合
func (r NeVersion) SelectByPage(query map[string]string) ([]model.NeVersion, int64) {
tx := db.DB("").Model(&model.NeVersion{})
// 查询条件拼接
if v, ok := query["neType"]; ok && v != "" {
tx = tx.Where("ne_type = ?", v)
}
if v, ok := query["neId"]; ok && v != "" {
tx = tx.Where("ne_id = ?", v)
}
if v, ok := query["version"]; ok && v != "" {
tx = tx.Where("version like ?", fmt.Sprintf("%s%%", v))
}
if v, ok := query["path"]; ok && v != "" {
tx = tx.Where("path like ?", fmt.Sprintf("%s%%", v))
}
// 查询结果
var total int64 = 0
rows := []model.NeVersion{}
// 查询数量为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return rows, total
}
// 查询数据分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
tx = tx.Order("update_time desc")
err := tx.Find(&rows).Error
if err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows, total
}
return rows, total
}
// Select 查询集合
func (r NeVersion) Select(param model.NeVersion) []model.NeVersion {
tx := db.DB("").Model(&model.NeVersion{})
// 查询条件拼接
if param.NeType != "" {
tx = tx.Where("ne_type = ?", param.NeType)
}
if param.NeId != "" {
tx = tx.Where("ne_id = ?", param.NeId)
}
if param.Version != "" {
tx = tx.Where("version like ?", fmt.Sprintf("%s%%", param.Version))
}
if param.Path != "" {
tx = tx.Where("path like ?", fmt.Sprintf("%s%%", param.Path))
}
if param.Status != "" {
tx = tx.Where("status = ?", param.Status)
}
// 查询数据
rows := []model.NeVersion{}
if err := tx.Order("id asc").Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// SelectByIds 通过ID查询
func (r NeVersion) SelectByIds(ids []int64) []model.NeVersion {
rows := []model.NeVersion{}
if len(ids) <= 0 {
return rows
}
tx := db.DB("").Model(&model.NeVersion{})
// 构建查询条件
tx = tx.Where("id in ?", ids)
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// Insert 新增信息
func (r NeVersion) Insert(param model.NeVersion) int64 {
if param.CreateBy != "" {
ms := time.Now().UnixMilli()
param.CreateTime = ms
param.UpdateTime = ms
param.UpdateBy = param.CreateBy
}
tx := db.DB("").Create(&param)
if err := tx.Error; err != nil {
logger.Errorf("CreateInBatches err => %v", err)
}
return param.ID
}
// Update 修改信息
func (r NeVersion) Update(param model.NeVersion) int64 {
if param.ID <= 0 {
return 0
}
if param.UpdateBy != "" {
param.UpdateTime = time.Now().UnixMilli()
}
param.UpdateTime = time.Now().UnixMilli()
tx := db.DB("").Model(&model.NeVersion{})
// 构建查询条件
tx = tx.Where("id = ?", param.ID)
tx = tx.Omit("id", "create_by", "create_time")
// 执行更新
if err := tx.Updates(param).Error; err != nil {
logger.Errorf("update err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
// DeleteByIds 批量删除信息
func (r NeVersion) DeleteByIds(ids []int64) int64 {
if len(ids) <= 0 {
return 0
}
tx := db.DB("").Where("id in ?", ids)
if err := tx.Delete(&model.NeVersion{}).Error; err != nil {
logger.Errorf("delete err => %v", err.Error())
return 0
}
return tx.RowsAffected
}
+162
View File
@@ -0,0 +1,162 @@
package service
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/constants"
"be.ems/src/framework/database/redis"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/repository"
)
// 实例化服务层 NeConfig 结构体
var NewNeConfig = &NeConfig{
neConfigRepository: repository.NewNeConfig,
}
// NeConfig 网元参数配置可用属性值 服务层处理
type NeConfig struct {
neConfigRepository *repository.NeConfig // 网元参数配置可用属性值表
}
// RefreshByNeType 通过ne_type刷新redis中的缓存
func (r *NeConfig) RefreshByNeTypeAndNeID(neType string) []model.NeConfig {
// 多个
if neType == "" || neType == "*" {
neConfigList := r.neConfigRepository.Select(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("%s:NeConfig:%s", constants.CACHE_NE_DATA, strings.ToUpper(k))
redis.Del("", key)
if len(v) > 0 {
for i, item := range v {
if err := json.Unmarshal([]byte(item.ParamJson), &item.ParamData); err != nil {
continue
}
v[i] = item
}
values, _ := json.Marshal(v)
redis.Set("", key, string(values), 0)
}
}
}
return neConfigList
}
// 单个
key := fmt.Sprintf("%s:NeConfig:%s", constants.CACHE_NE_DATA, strings.ToUpper(neType))
redis.Del("", key)
neConfigList := r.neConfigRepository.Select(model.NeConfig{
NeType: neType,
})
if len(neConfigList) > 0 {
for i, v := range neConfigList {
if err := json.Unmarshal([]byte(v.ParamJson), &v.ParamData); err != nil {
continue
}
neConfigList[i] = v
}
values, _ := json.Marshal(neConfigList)
redis.Set("", key, string(values), 0)
}
return neConfigList
}
// ClearNeCacheByNeType 清除网元类型参数配置缓存
func (r *NeConfig) ClearNeCacheByNeType(neType string) bool {
key := fmt.Sprintf("%s:NeConfig:%s", constants.CACHE_NE_DATA, neType)
if neType == "*" {
key = fmt.Sprintf("%s:NeConfig:*", constants.CACHE_NE_DATA)
}
keys, err := redis.GetKeys("", key)
if err != nil {
return false
}
return redis.DelKeys("", keys) == nil
}
// FindByNeType 查询网元类型参数配置
func (r *NeConfig) FindByNeType(neType string) []model.NeConfig {
var neConfigList []model.NeConfig
key := fmt.Sprintf("%s:NeConfig:%s", constants.CACHE_NE_DATA, 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
}
// FindByNeTypeAndParamName 查询网元类型参数配置By参数名
func (r *NeConfig) FindByNeTypeAndParamName(neType, paramName string) model.NeConfig {
neConfigList := r.FindByNeType(neType)
var neConfig model.NeConfig
for _, v := range neConfigList {
if v.ParamName == paramName {
neConfig = v
break
}
}
return neConfig
}
// FindByPage 分页查询列表数据
func (r *NeConfig) FindByPage(query map[string]string) ([]model.NeConfig, int64) {
return r.neConfigRepository.SelectByPage(query)
}
// Find 查询列表
func (r *NeConfig) Find(param model.NeConfig) []model.NeConfig {
return r.neConfigRepository.Select(param)
}
// FindById 通过ID查询
func (r *NeConfig) FindById(id int64) model.NeConfig {
if id <= 0 {
return model.NeConfig{}
}
neHosts := r.neConfigRepository.SelectByIds([]int64{id})
if len(neHosts) > 0 {
return neHosts[0]
}
return model.NeConfig{}
}
// Insert 新增信息
func (r *NeConfig) Insert(param model.NeConfig) int64 {
return r.neConfigRepository.Insert(param)
}
// Update 修改信息
func (r *NeConfig) Update(param model.NeConfig) int64 {
return r.neConfigRepository.Update(param)
}
// DeleteByIds 批量删除信息
func (r *NeConfig) DeleteByIds(ids []int64) (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")
}
+200
View File
@@ -0,0 +1,200 @@
package service
import (
"fmt"
"os"
"runtime"
"strings"
"time"
"be.ems/src/framework/utils/date"
"be.ems/src/framework/utils/file"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/repository"
)
// 实例化服务层 NeConfigBackup 结构体
var NewNeConfigBackup = &NeConfigBackup{
neConfigBackupRepository: repository.NewNeConfigBackup,
}
// NeConfigBackup 网元配置文件备份记录 服务层处理
type NeConfigBackup struct {
neConfigBackupRepository *repository.NeConfigBackup // 网元配置文件备份记录
}
// FindByPage 分页查询列表数据
func (s NeConfigBackup) FindByPage(query map[string]string) ([]model.NeConfigBackup, int64) {
return s.neConfigBackupRepository.SelectByPage(query)
}
// FindById 通过ID查询
func (s NeConfigBackup) FindById(id int64) model.NeConfigBackup {
if id <= 0 {
return model.NeConfigBackup{}
}
arr := s.neConfigBackupRepository.SelectByIds([]int64{id})
if len(arr) > 0 {
return arr[0]
}
return model.NeConfigBackup{}
}
// Insert 新增信息
func (s NeConfigBackup) Insert(item model.NeConfigBackup) int64 {
return s.neConfigBackupRepository.Insert(item)
}
// Update 修改信息
func (s NeConfigBackup) Update(item model.NeConfigBackup) int64 {
return s.neConfigBackupRepository.Update(item)
}
// DeleteByIds 批量删除信息
func (s NeConfigBackup) DeleteByIds(ids []int64) (int64, error) {
// 检查是否存在
data := s.neConfigBackupRepository.SelectByIds(ids)
if len(data) <= 0 {
return 0, fmt.Errorf("neConfigBackup.noData")
}
if len(data) == len(ids) {
rows := s.neConfigBackupRepository.DeleteByIds(ids)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// FileLocalToNe 网元配置文件复制到网元端覆盖
func (s NeConfigBackup) FileLocalToNe(neInfo model.NeInfo, localFile string) error {
neTypeLower := strings.ToLower(neInfo.NeType)
// 网管本地路径
omcPath := "/usr/local/omc/backup/ne_config"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
localDirPath := fmt.Sprintf("%s/%s/%s/backup/tmp_import", omcPath, neTypeLower, neInfo.NeId)
if err := file.UnZip(localFile, localDirPath); err != nil {
return fmt.Errorf("unzip err")
}
// 网元主机的SSH客户端
sshClient, err := NewNeInfo.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
return fmt.Errorf("ne info ssh client err")
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return fmt.Errorf("ne info sftp client err")
}
defer sftpClient.Close()
// 网元配置端上的临时目录
neDirTemp := fmt.Sprintf("/tmp/omc/ne_config/%s/%s", neTypeLower, neInfo.NeId)
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p /tmp/omc/ne_config && sudo chmod 777 -R /tmp/omc && sudo rm -rf %s", neDirTemp))
// 复制到网元端
if err = sftpClient.CopyDirLocalToRemote(localDirPath, neDirTemp); err != nil {
return fmt.Errorf("copy config to ne err")
}
// 配置复制到网元内
switch neTypeLower {
case "ims":
// ims目录
imsDirArr := [...]string{"bgcf", "icscf", "ismc", "mmtel", "mrf", "oam_manager.yaml", "pcscf", "scscf", "vars.cfg", "zlog"}
for _, v := range imsDirArr {
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p /usr/local/etc/ims && sudo cp -rf %s/ims/%s /usr/local/etc/ims/%v && sudo chmod 777 -R /usr/local/etc/ims/%s", neDirTemp, v, v, v))
}
// mf目录
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p /usr/local/etc/mf && sudo cp -rf %s/mf/* /usr/local/etc/mf && sudo chmod 777 -R /usr/local/etc/mf", neDirTemp))
// rtproxy目录
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p /usr/local/etc/rtproxy && sudo cp -rf %s/rtproxy/* /usr/local/etc/rtproxy && sudo chmod 777 /usr/local/etc/rtproxy/rtproxy.conf", neDirTemp))
// iwf目录
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p /usr/local/etc/iwf && sudo cp -rf %s/iwf/* /usr/local/etc/iwf && sudo chmod 777 /usr/local/etc/iwf/*.yaml", neDirTemp))
case "smsc":
chmodFile := "sudo chmod 777 /usr/local/etc/smsc/{*sys.conf,*conf.txt,conf/is41_operation.conf}"
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p /usr/local/etc/smsc/conf && sudo cp -rf %s/* /usr/local/etc/smsc && %s", neDirTemp, chmodFile))
default:
neEtcPath := fmt.Sprintf("/usr/local/etc/%s", neTypeLower)
chmodFile := fmt.Sprintf("sudo chmod 777 %s/*.yaml", neEtcPath)
if neTypeLower == "mme" {
chmodFile = fmt.Sprintf("sudo chmod 777 %s/*.{yaml,conf}", neEtcPath)
}
sshClient.RunCMD(fmt.Sprintf("sudo cp -rf %s/* %s && %s", neDirTemp, neEtcPath, chmodFile))
}
_ = os.RemoveAll(localDirPath) // 删除本地临时目录
sshClient.RunCMD(fmt.Sprintf("sudo rm -rf %s", neDirTemp)) // 删除临时目录
return nil
}
// FileNeToLocal 网元备份文件网元端复制到本地
func (s NeConfigBackup) FileNeToLocal(neInfo model.NeInfo) (string, error) {
// 网元主机的SSH客户端
sshClient, err := NewNeInfo.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
return "", fmt.Errorf("ne info ssh client err")
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return "", fmt.Errorf("ne info sftp client err")
}
defer sftpClient.Close()
neTypeLower := strings.ToLower(neInfo.NeType)
// 网管本地路径
omcPath := "/usr/local/omc/backup/ne_config"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
localDirPath := fmt.Sprintf("%s/%s/%s/from_ne_tmp", omcPath, neTypeLower, neInfo.NeId)
// 网元配置文件先复制到临时目录
sshClient.RunCMD("sudo mkdir -p /tmp/omc/ne_config && sudo chmod 777 -R /tmp/omc")
neDirTemp := fmt.Sprintf("/tmp/omc/ne_config/%s/%s", neTypeLower, neInfo.NeId)
switch neTypeLower {
case "ims":
// ims目录
sshClient.RunCMD(fmt.Sprintf("mkdir -p %s/ims", neDirTemp))
imsDirArr := [...]string{"bgcf", "icscf", "ismc", "mmtel", "mrf", "oam_manager.yaml", "pcscf", "scscf", "vars.cfg", "zlog"}
for _, v := range imsDirArr {
sshClient.RunCMD(fmt.Sprintf("sudo cp -rf /usr/local/etc/ims/%s %s/ims", v, neDirTemp))
}
// mf目录
sshClient.RunCMD(fmt.Sprintf("mkdir -p %s/mf && sudo cp -rf /usr/local/etc/mf %s", neDirTemp, neDirTemp))
// rtproxy目录
sshClient.RunCMD(fmt.Sprintf("mkdir -p %s/rtproxy && sudo cp -rf /usr/local/etc/rtproxy/rtproxy.conf %s/rtproxy", neDirTemp, neDirTemp))
// iwf目录
sshClient.RunCMD(fmt.Sprintf("mkdir -p %s/iwf && sudo cp -rf /usr/local/etc/iwf/*.yaml %s/iwf", neDirTemp, neDirTemp))
case "smsc":
sshClient.RunCMD(fmt.Sprintf("mkdir -p %s && sudo cp -rf /usr/local/etc/smsc/{*.yaml,*.conf,*conf.txt} %s", neDirTemp, neDirTemp))
sshClient.RunCMD(fmt.Sprintf("sudo cp -rf /usr/local/etc/smsc/conf %s/conf", neDirTemp))
default:
nePath := fmt.Sprintf("/usr/local/etc/%s/*.yaml", neTypeLower)
if neTypeLower == "mme" {
nePath = fmt.Sprintf("/usr/local/etc/%s/*.{yaml,conf}", neTypeLower)
}
sshClient.RunCMD(fmt.Sprintf("mkdir -p %s && sudo cp -rf %s %s", neDirTemp, nePath, neDirTemp))
}
// 网元端复制到本地
if err = sftpClient.CopyDirRemoteToLocal(neDirTemp, localDirPath); err != nil {
return "", fmt.Errorf("copy config err")
}
// 压缩zip文件名
zipFileName := fmt.Sprintf("%s-%s-etc-%s.zip", neTypeLower, neInfo.NeId, date.ParseDateToStr(time.Now(), date.YYYYMMDDHHMMSS))
zipFilePath := fmt.Sprintf("%s/%s/%s/%s", omcPath, neTypeLower, neInfo.NeId, zipFileName)
if err := file.CompressZipByDir(zipFilePath, localDirPath); err != nil {
return "", fmt.Errorf("compress zip err")
}
_ = os.RemoveAll(localDirPath) // 删除本地临时目录
sshClient.RunCMD(fmt.Sprintf("sudo rm -rf %s", neDirTemp)) // 删除临时目录
return zipFilePath, nil
}
+156
View File
@@ -0,0 +1,156 @@
package service
import (
"fmt"
"strings"
"be.ems/src/framework/config"
"github.com/tsmask/go-oam/framework/utils/parse"
)
// GetOMCYaml 获取OMC网元配置文件
func (r NeConfig) GetOMCYaml(paramName string) []map[string]any {
if paramName == "notificationEmail" {
notificationEmailData := config.Get("notification.email").(map[string]any)
for k, v := range notificationEmailData {
if k == "password" && v != nil {
notificationEmailData[k] = parse.SafeContent(fmt.Sprint(v))
}
}
return []map[string]any{notificationEmailData}
}
if paramName == "notificationSMSC" {
notificationSMSCData := config.Get("notification.smsc").(map[string]any)
for k, v := range notificationSMSCData {
if k == "password" && v != nil {
notificationSMSCData[k] = parse.SafeContent(fmt.Sprint(v))
}
}
return []map[string]any{notificationSMSCData}
}
if paramName == "trace" {
traceData := config.Get("trace").(map[string]any)
return []map[string]any{traceData}
}
return []map[string]any{}
}
// ModifyOMCYaml 修改OMC网元配置文件
func (r NeConfig) ModifyOMCYaml(paramName, loc string, paramData any) error {
neConfig := r.FindByNeTypeAndParamName("OMC", paramName)
if neConfig.ParamType == "list" {
if paramName == "notificationEmail" {
notificationEmailData := config.Get("notification.email").(map[string]any)
for k, v := range paramData.(map[string]any) {
keyLower := strings.ToLower(k)
// 改程序内
notificationEmailData[keyLower] = v
// 改文件
switch keyLower {
case "enabled":
pattern := `enabled: (true|false) # email enable`
replacement := fmt.Sprintf(`enabled: %v # email enable`, v)
return config.SedReplace(pattern, replacement)
case "list":
pattern := `list: ".*" # toEmail`
replacement := fmt.Sprintf(`list: "%v" # toEmail`, v)
return config.SedReplace(pattern, replacement)
case "title":
pattern := `title: ".*" # email title`
replacement := fmt.Sprintf(`title: "%v" # email title`, v)
return config.SedReplace(pattern, replacement)
case "smtp":
pattern := `smtp: ".*" # email smtp`
replacement := fmt.Sprintf(`smtp: "%v" # email smtp`, v)
return config.SedReplace(pattern, replacement)
case "port":
pattern := `port: [0-9]+ # email port`
replacement := fmt.Sprintf(`port: %v # email port`, v)
return config.SedReplace(pattern, replacement)
case "user":
pattern := `user: ".*" # email user`
replacement := fmt.Sprintf(`user: "%v" # email user`, v)
return config.SedReplace(pattern, replacement)
case "password":
pattern := `password: ".*" # email password`
replacement := fmt.Sprintf(`password: "%v" # email password`, v)
return config.SedReplace(pattern, replacement)
}
}
}
if paramName == "notificationSMSC" {
notificationSMSCData := config.Get("notification.smsc").(map[string]any)
for k, v := range paramData.(map[string]any) {
keyLower := strings.ToLower(k)
// 改程序内
notificationSMSCData[keyLower] = v
// 改文件
switch keyLower {
case "enabled":
pattern := `enabled: (true|false) # smsc enable`
replacement := fmt.Sprintf(`enabled: %v # smsc enable`, v)
return config.SedReplace(pattern, replacement)
case "list":
pattern := `list: ".*" # toMobile`
replacement := fmt.Sprintf(`list: "%v" # toMobile`, v)
return config.SedReplace(pattern, replacement)
case "addr":
pattern := `addr: ".*" # smsc addr`
replacement := fmt.Sprintf(`addr: "%v" # smsc addr`, v)
return config.SedReplace(pattern, replacement)
case "systemid":
pattern := `systemid: ".*" # smsc system id`
replacement := fmt.Sprintf(`systemid: "%v" # smsc system id`, v)
return config.SedReplace(pattern, replacement)
case "systemtype":
pattern := `systemtype: ".*" # smsc system type`
replacement := fmt.Sprintf(`systemtype: "%v" # smsc system type`, v)
return config.SedReplace(pattern, replacement)
case "password":
pattern := `password: ".*" # smsc password`
replacement := fmt.Sprintf(`password: "%v" # smsc password`, v)
return config.SedReplace(pattern, replacement)
case "coding":
pattern := `coding: [0-9]+ # smsc codingMap`
replacement := fmt.Sprintf(`coding: %v # smsc codingMap`, v)
return config.SedReplace(pattern, replacement)
case "servicenumber":
pattern := `servicenumber: ".*" # smsc service number`
replacement := fmt.Sprintf(`servicenumber: "%v" # smsc service number`, v)
return config.SedReplace(pattern, replacement)
}
}
}
if paramName == "trace" {
traceData := config.Get("trace").(map[string]any)
for k, v := range paramData.(map[string]any) {
keyLower := strings.ToLower(k)
// 改程序内
traceData[keyLower] = v
// 改文件
switch keyLower {
case "enabled":
pattern := `enabled: (true|false) # trace enabled`
replacement := fmt.Sprintf(`enabled: %v # trace enabled`, v)
return config.SedReplace(pattern, replacement)
case "host":
pattern := `host: ".*" # trace host`
replacement := fmt.Sprintf(`host: "%v" # trace host`, v)
return config.SedReplace(pattern, replacement)
case "port":
pattern := `port: [0-9]+ # trace port`
replacement := fmt.Sprintf(`port: %v # trace port`, v)
return config.SedReplace(pattern, replacement)
}
}
// 重开跟踪任务信令数据通道UDP
// service.NewTraceTask.CreateUDP(true) 方法导致循环引用,抛给上层调用
return nil
}
}
if neConfig.ParamType == "array" {
// TODO
}
return fmt.Errorf("not found method paramName")
}
+174
View File
@@ -0,0 +1,174 @@
package service
import (
"fmt"
"be.ems/src/framework/config"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/crypto"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/repository"
)
// 实例化服务层 NeHost 结构体
var NewNeHost = &NeHost{
neHostRepository: repository.NewNeHost,
}
// NeHost 网元主机连接 服务层处理
type NeHost struct {
neHostRepository *repository.NeHost // 网元主机连接表
}
// FindByPage 分页查询列表数据
func (r NeHost) FindByPage(query map[string]string) ([]model.NeHost, int64) {
return r.neHostRepository.SelectByPage(query)
}
// FindById 通过ID查询
func (r NeHost) FindById(hostId int64) model.NeHost {
neHost := model.NeHost{}
if hostId <= 0 {
return neHost
}
neHosts := r.neHostRepository.SelectByIds([]int64{hostId})
if len(neHosts) > 0 {
neHost := neHosts[0]
hostKey := config.Get("aes.hostKey").(string)
if neHost.Password != "" {
passwordDe, err := crypto.AESDecryptBase64(neHost.Password, hostKey)
if err != nil {
logger.Errorf("select encrypt: %v", err.Error())
return neHost
}
neHost.Password = passwordDe
}
if neHost.PrivateKey != "" {
privateKeyDe, err := crypto.AESDecryptBase64(neHost.PrivateKey, hostKey)
if err != nil {
logger.Errorf("select encrypt: %v", err.Error())
return neHost
}
neHost.PrivateKey = privateKeyDe
}
if neHost.PassPhrase != "" {
passPhraseDe, err := crypto.AESDecryptBase64(neHost.PassPhrase, hostKey)
if err != nil {
logger.Errorf("select encrypt: %v", err.Error())
return neHost
}
neHost.PassPhrase = passPhraseDe
}
return neHost
}
return model.NeHost{}
}
// Insert 批量添加
func (r NeHost) Inserts(neHosts []model.NeHost) int64 {
var num int64 = 0
for _, v := range neHosts {
hostId := r.neHostRepository.Insert(v)
if hostId > 0 {
num += 1
}
}
return num
}
// Insert 新增信息
func (r NeHost) Insert(neHost model.NeHost) int64 {
hostKey := config.Get("aes.hostKey").(string)
if neHost.Password != "" {
passwordEn, err := crypto.AESEncryptBase64(neHost.Password, hostKey)
if err != nil {
logger.Errorf("insert encrypt: %v", err.Error())
return 0
}
neHost.Password = passwordEn
}
if neHost.PrivateKey != "" {
privateKeyEn, err := crypto.AESEncryptBase64(neHost.PrivateKey, hostKey)
if err != nil {
logger.Errorf("insert encrypt: %v", err.Error())
return 0
}
neHost.PrivateKey = privateKeyEn
}
if neHost.PassPhrase != "" {
passPhraseEn, err := crypto.AESEncryptBase64(neHost.PassPhrase, hostKey)
if err != nil {
logger.Errorf("insert encrypt: %v", err.Error())
return 0
}
neHost.PassPhrase = passPhraseEn
}
return r.neHostRepository.Insert(neHost)
}
// Update 修改信息
func (r NeHost) Update(neHost model.NeHost) int64 {
hostKey := config.Get("aes.hostKey").(string)
if neHost.Password != "" {
passwordEn, err := crypto.AESEncryptBase64(neHost.Password, hostKey)
if err != nil {
logger.Errorf("update password encrypt: %v", err.Error())
return 0
}
neHost.Password = passwordEn
}
if neHost.PrivateKey != "" {
privateKeyEn, err := crypto.AESEncryptBase64(neHost.PrivateKey, hostKey)
if err != nil {
logger.Errorf("update private key encrypt: %v", err.Error())
return 0
}
neHost.PrivateKey = privateKeyEn
}
if neHost.PassPhrase != "" {
passPhraseEn, err := crypto.AESEncryptBase64(neHost.PassPhrase, hostKey)
if err != nil {
logger.Errorf("update pass phrase encrypt: %v", err.Error())
return 0
}
neHost.PassPhrase = passPhraseEn
}
return r.neHostRepository.Update(neHost)
}
// DeleteByIds 批量删除网元主机连接信息
// checkNeHost 是否检查网元主机
func (r NeHost) DeleteByIds(hostIds []int64, checkNeHost bool) (int64, error) {
// 检查是否存在
ids := r.neHostRepository.SelectByIds(hostIds)
if len(ids) <= 0 {
return 0, fmt.Errorf("neHost.noData")
}
for _, v := range ids {
if v.GroupID == "1" && checkNeHost {
// 主机信息操作【%s】失败,禁止操作网元
return 0, fmt.Errorf("neHost.banNE")
}
}
if len(ids) == len(hostIds) {
rows := r.neHostRepository.DeleteByIds(hostIds)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// CheckUniqueHostTitle 校验分组组和主机名称是否唯一
func (r NeHost) CheckUniqueHostTitle(groupId, title, hostType string, hostId int64) bool {
uniqueId := r.neHostRepository.CheckUnique(model.NeHost{
HostType: hostType,
GroupID: groupId,
Title: title,
})
if uniqueId == hostId {
return true
}
return uniqueId == 0
}
+74
View File
@@ -0,0 +1,74 @@
package service
import (
"fmt"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/repository"
)
// 实例化服务层 NeHostCmd 结构体
var NewNeHostCmd = &NeHostCmd{
neHostCmdRepository: repository.NewNeHostCmd,
}
// NeHostCmd 网元主机命令 服务层处理
type NeHostCmd struct {
neHostCmdRepository *repository.NeHostCmd // 网元主机命令表
}
// FindByPage 分页查询列表数据
func (r *NeHostCmd) FindByPage(query map[string]string) ([]model.NeHostCmd, int64) {
return r.neHostCmdRepository.SelectByPage(query)
}
// FindById 通过ID查询
func (r *NeHostCmd) FindById(id int64) model.NeHostCmd {
if id <= 0 {
return model.NeHostCmd{}
}
neHosts := r.neHostCmdRepository.SelectByIds([]int64{id})
if len(neHosts) > 0 {
return neHosts[0]
}
return model.NeHostCmd{}
}
// Insert 新增信息
func (r *NeHostCmd) Insert(neHostCmd model.NeHostCmd) int64 {
return r.neHostCmdRepository.Insert(neHostCmd)
}
// Update 修改信息
func (r *NeHostCmd) Update(neHostCmd model.NeHostCmd) int64 {
return r.neHostCmdRepository.Update(neHostCmd)
}
// DeleteByIds 批量删除信息
func (r *NeHostCmd) DeleteByIds(ids []int64) (int64, error) {
// 检查是否存在
rows := r.neHostCmdRepository.SelectByIds(ids)
if len(rows) <= 0 {
return 0, fmt.Errorf("neHostCmd.noData")
}
if len(rows) == len(ids) {
rows := r.neHostCmdRepository.DeleteByIds(ids)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// CheckUniqueGroupTitle 校验同类型组内是否唯一
func (r *NeHostCmd) CheckUniqueGroupTitle(groupId, title, cmdType string, cmdId int64) bool {
uniqueId := r.neHostCmdRepository.CheckUnique(model.NeHostCmd{
CmdType: cmdType,
GroupID: groupId,
Title: title,
})
if uniqueId == cmdId {
return true
}
return uniqueId == 0
}
File diff suppressed because it is too large. Load diff
+197
View File
@@ -0,0 +1,197 @@
package service
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"time"
"be.ems/src/framework/utils/file"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/repository"
)
// 实例化服务层 NeLicense 结构体
var NewNeLicense = &NeLicense{
neLicenseRepository: repository.NewNeLicense,
}
// NeLicense 网元授权激活信息 服务层处理
type NeLicense struct {
neLicenseRepository *repository.NeLicense // 网元授权激活信息表
}
// FindByPage 分页查询列表数据
func (r *NeLicense) FindByPage(query map[string]string) ([]model.NeLicense, int64) {
return r.neLicenseRepository.SelectByPage(query)
}
// Find 查询列表
func (r *NeLicense) Find(neLicense model.NeLicense) []model.NeLicense {
return r.neLicenseRepository.Select(neLicense)
}
// FindById 通过ID查询
func (r *NeLicense) FindById(id int64) model.NeLicense {
if id <= 0 {
return model.NeLicense{}
}
neLicenses := r.neLicenseRepository.SelectByIds([]int64{id})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// Insert 新增信息
func (r *NeLicense) Insert(neLicense model.NeLicense) int64 {
return r.neLicenseRepository.Insert(neLicense)
}
// Update 修改信息
func (r *NeLicense) Update(neLicense model.NeLicense) int64 {
return r.neLicenseRepository.Update(neLicense)
}
// DeleteByIds 批量删除信息
func (r *NeLicense) DeleteByIds(ids []int64) (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")
}
// FindByTypeAndID 通过网元类型和网元ID查询
func (r *NeLicense) FindByTypeAndID(neType, neId string) model.NeLicense {
neLicenses := r.neLicenseRepository.Select(model.NeLicense{
NeType: neType,
NeId: neId,
})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// FindByNeTypeAndNeID 通过ne_type和ne_id查询信息
func (r *NeLicense) FindByNeTypeAndNeID(neType, neId string) model.NeLicense {
neLicenses := r.neLicenseRepository.Select(model.NeLicense{
NeType: neType,
NeId: neId,
})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// ReadLicenseInfo 读取授权文件信息
// 返回激活申请码, 激活文件
func (r *NeLicense) ReadLicenseInfo(neLicense model.NeLicense) (string, string) {
neTypeLower := strings.ToLower(neLicense.NeType)
// 网管本地路径
omcPath := "/usr/local/omc/backup/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 := NewNeInfo.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"
}
activationRequestCode := string(bytes)
parts := strings.Split(activationRequestCode, "\n")
if len(parts) > 1 && strings.HasPrefix(parts[0], "SN") {
activationRequestCode = parts[1] // 获取第二行内容
}
return strings.TrimSpace(activationRequestCode), licensePath
}
// UploadLicense 授权文件上传到网元主机
func (r *NeLicense) UploadLicense(neLicense model.NeLicense) error {
// 检查文件是否存在
omcLicensePath := file.ParseUploadFileAbsPath(neLicense.LicensePath)
if _, err := os.Stat(omcLicensePath); err != nil {
return fmt.Errorf("file read failure")
}
// 网元主机的SSH客户端
sshClient, err := NewNeInfo.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 systemctl restart %s", neTypeLower)
switch neTypeLower {
case "ims":
cmdStr = "ims-stop || true && ims-start"
case "omc":
cmdStr = "sudo systemctl restart omc"
}
sshClient.RunCMD(cmdStr)
}
return nil
}
+144
View File
@@ -0,0 +1,144 @@
package service
import (
"fmt"
"os"
"be.ems/src/framework/utils/file"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/repository"
)
// 实例化服务层 NeSoftware 结构体
var NewNeSoftware = &NeSoftware{
neSoftwareRepository: repository.NewNeSoftware,
neVersionService: NewNeVersion,
}
// NeSoftware 网元软件包信息 服务层处理
type NeSoftware struct {
neSoftwareRepository *repository.NeSoftware // 网元软件包信息
neVersionService *NeVersion // 网元版本信息服务
}
// FindByPage 分页查询列表数据
func (r NeSoftware) FindByPage(query map[string]string) ([]model.NeSoftware, int64) {
return r.neSoftwareRepository.SelectByPage(query)
}
// Find 查询列表
func (r NeSoftware) Find(neSoftware model.NeSoftware) []model.NeSoftware {
return r.neSoftwareRepository.Select(neSoftware)
}
// FindById 通过ID查询
func (r NeSoftware) FindById(id int64) model.NeSoftware {
if id <= 0 {
return model.NeSoftware{}
}
neHosts := r.neSoftwareRepository.SelectByIds([]int64{id})
if len(neHosts) > 0 {
return neHosts[0]
}
return model.NeSoftware{}
}
// Insert 新增信息
func (r NeSoftware) Insert(neSoftware model.NeSoftware) int64 {
inserId := r.neSoftwareRepository.Insert(neSoftware)
if inserId > 0 {
// 更新同类型的新包版本
neVersions := r.neVersionService.Find(model.NeVersion{NeType: neSoftware.NeType}, false)
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
r.neVersionService.Update(neVersion)
}
}
}
return inserId
}
// Update 修改信息
func (r NeSoftware) Update(neSoftware model.NeSoftware) int64 {
rows := r.neSoftwareRepository.Update(neSoftware)
if rows > 0 {
// 更新同类型的新包版本
neVersions := r.neVersionService.Find(model.NeVersion{
NeType: neSoftware.NeType,
Status: "3",
}, false)
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
r.neVersionService.Update(neVersion)
}
}
}
return rows
}
// DeleteByIds 批量删除信息
func (r NeSoftware) DeleteByIds(ids []int64) (int64, error) {
// 检查是否存在
rows := r.neSoftwareRepository.SelectByIds(ids)
if len(rows) <= 0 {
return 0, fmt.Errorf("neSoftware.noData")
}
if len(rows) == len(ids) {
// 遍历软件包列表进行文件删除
for _, row := range rows {
// 检查文件是否存在
filePath := file.ParseUploadFileAbsPath(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")
}
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一
func (r NeSoftware) CheckUniqueTypeAndNameAndVersion(neType, name, version string, id int64) bool {
uniqueId := r.neSoftwareRepository.CheckUnique(model.NeSoftware{
NeType: neType,
Name: name,
Version: version,
})
if uniqueId == id {
return true
}
return uniqueId == 0
}
// UpdateVersions 更新软件包对应网元的新版本
func (r NeSoftware) UpdateVersions(neSoftware model.NeSoftware, neVersion model.NeVersion) int64 {
var rows int64 = 0
// 更新同类型的新包版本
neVersions := r.neVersionService.Find(neVersion, false)
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 += r.neVersionService.Update(v)
}
}
return rows
}
+781
View File
@@ -0,0 +1,781 @@
package service
import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
"be.ems/src/framework/ssh"
"be.ems/src/framework/utils/file"
neFetchlink "be.ems/src/modules/ne/fetch_link"
"be.ems/src/modules/ne/model"
"be.ems/src/modules/ne/repository"
)
// 实例化服务层 NeVersion 结构体
var NewNeVersion = &NeVersion{
neVersionRepository: repository.NewNeVersion,
neInfoService: NewNeInfo,
}
// NeVersion 网元版本信息 服务层处理
type NeVersion struct {
neVersionRepository *repository.NeVersion // 网元版本信息表
neInfoService *NeInfo // 网元信息数据信息
}
// FindByPage 分页查询列表数据
func (r NeVersion) FindByPage(query map[string]string, checkVersion bool) ([]model.NeVersion, int64) {
rows, total := r.neVersionRepository.SelectByPage(query)
// 网元直连检查更新网元服务版本
if checkVersion {
r.checkNeVersion(&rows)
}
return rows, total
}
// Find 查询列表
func (r NeVersion) Find(neVersion model.NeVersion, checkVersion bool) []model.NeVersion {
list := r.neVersionRepository.Select(neVersion)
// 网元直连检查更新网元服务版本
if checkVersion {
r.checkNeVersion(&list)
}
return list
}
// checkNeVersion 网元列表检查更新网元版本
func (r NeVersion) checkNeVersion(arr *[]model.NeVersion) {
for i := range *arr {
item := (*arr)[i]
// 查询网元获取IP
neInfo := r.neInfoService.FindByNeTypeAndNeID(item.NeType, item.NeId)
if neInfo.NeId != item.NeId || neInfo.IP == "" {
continue
}
result, err := neFetchlink.NeState(neInfo)
if err != nil {
continue
}
if v, ok := result["version"]; ok && v != nil {
ver := v.(string)
if ver == item.Version {
continue
}
item.Name = "-"
item.Path = "-"
item.Version = ver
}
if item.NeType != neInfo.NeType || item.NeId != neInfo.NeId {
item.NeType = neInfo.NeType
item.NeId = neInfo.NeId
}
r.Update(item)
(*arr)[i] = item
}
}
// FindById 通过ID查询
func (r NeVersion) FindById(id int64) model.NeVersion {
if id <= 0 {
return model.NeVersion{}
}
neVersions := r.neVersionRepository.SelectByIds([]int64{id})
if len(neVersions) > 0 {
return neVersions[0]
}
return model.NeVersion{}
}
// Insert 新增信息
func (r NeVersion) Insert(neVersion model.NeVersion) int64 {
return r.neVersionRepository.Insert(neVersion)
}
// Update 修改信息
func (r NeVersion) Update(neVersion model.NeVersion) int64 {
return r.neVersionRepository.Update(neVersion)
}
// DeleteByIds 批量删除信息
func (r NeVersion) DeleteByIds(ids []int64) (int64, error) {
// 检查是否存在
rowIds := r.neVersionRepository.SelectByIds(ids)
if len(rowIds) <= 0 {
return 0, fmt.Errorf("neVersion.noData")
}
if len(rowIds) == len(ids) {
rows := r.neVersionRepository.DeleteByIds(ids)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// FindByNeTypeAndNeID 通过网元类型和网元ID查询
func (r NeVersion) FindByNeTypeAndNeID(neType, neId string) model.NeVersion {
neVersions := r.neVersionRepository.Select(model.NeVersion{
NeType: neType,
NeId: neId,
})
if len(neVersions) > 0 {
return neVersions[0]
}
return model.NeVersion{}
}
// Operate 操作版本上传到网元主机执行命令
//
// action 安装行为:install upgrade rollback
func (r NeVersion) Operate(action string, neVersion model.NeVersion, preinput map[string]string) (string, error) {
// 网元主机的SSH客户端
sshClient, err := r.neInfoService.NeRunSSHClient(neVersion.NeType, neVersion.NeId)
if err != nil {
return "", err
}
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 := r.neInfoService.NeConfPara5GRead()
if para5GMap == nil || err != nil {
return "", fmt.Errorf("error read para5G file info")
}
if err := r.neInfoService.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
}
// operateFile 操作版本-文件传输阶段
func (r NeVersion) 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.ParseUploadFileAbsPath(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
}
// operateCommand 操作版本-命令生成阶段
func (r NeVersion) 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 --nosignature --nodeps --replacepkgs %s", strings.Join(neFilePaths, " "))
}
// 组合命令输入
cmdStrArr := []string{}
switch neType {
case "OMC":
omcStrArr := []string{}
if action == "install" {
// 安装软件包
pkgCmdStr = fmt.Sprintf("sudo dpkg -i %s", strings.Join(neFilePaths, " "))
if strings.HasSuffix(fileExt, "rpm") {
pkgCmdStr = fmt.Sprintf("sudo rpm -Uvh %s", strings.Join(neFilePaths, " "))
}
omcStrArr = append(omcStrArr, pkgCmdStr)
} else {
// 升级软件包
pkgCmdStr = fmt.Sprintf("sudo dpkg -i %s", strings.Join(neFilePaths, " "))
if strings.HasSuffix(fileExt, "rpm") {
pkgCmdStr = fmt.Sprintf("sudo rpm -Uvh --nosignature --nodeps --replacepkgs %s", strings.Join(neFilePaths, " "))
}
omcStrArr = append(omcStrArr, pkgCmdStr)
}
// 删除软件包
omcStrArr = append(omcStrArr, fmt.Sprintf("sudo rm %s", strings.Join(neFilePaths, " ")))
// 2s后执行omc相关命令
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo rm -f /tmp/operate_run_%s_omc.out \n", action))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("nohup sh -c \"sleep 2s && %s\" > /tmp/operate_run_%s_omc.out 2>&1 & \n", strings.Join(omcStrArr, " && "), action))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("echo '%s' \n", okFlagStr))
return okFlagStr, cmdStrArr, nil
case "IMS":
if action == "install" {
para5GData := r.neInfoService.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")
}
default:
if action == "install" {
para5GData := r.neInfoService.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"]))
// 使用UDM融合AUSF时
if para5GData["AUSF_IP"] == "172.16.5.130" {
para5GData["AUSF_IP"] = para5GData["UDM_IP"]
}
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"]))
// 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"]))
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: \"N3\"/,/driverType: .*/s/driverType: .*/driverType: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["UPF_DRIVER_TYPE"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N3\"/,/systemNetworkCardName: .*/s/systemNetworkCardName: .*/systemNetworkCardName: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N3_NIC_NAME"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N6\"/,/driverType: .*/s/driverType: .*/driverType: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["UPF_DRIVER_TYPE"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: \"N6\"/,/systemNetworkCardName: .*/s/systemNetworkCardName: .*/systemNetworkCardName: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N6_NIC_NAME"]))
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 sed -i '/- interfaceType: N3/,/driverType: .*/s/driverType: .*/driverType: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["UPF_DRIVER_TYPE"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: N3/,/systemNetworkCardName: .*/s/systemNetworkCardName: .*/systemNetworkCardName: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N3_NIC_NAME"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: N6/,/driverType: .*/s/driverType: .*/driverType: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["UPF_DRIVER_TYPE"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i '/- interfaceType: N6/,/systemNetworkCardName: .*/s/systemNetworkCardName: .*/systemNetworkCardName: \"%s\"/' /usr/local/etc/upf/upfForwarder_1.yaml \n", para5GData["N6_NIC_NAME"]))
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: .*/driverType: \"\"/g' /usr/local/etc/upf/upfForwarder_1.yaml \n")
// 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"]))
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"]))
}
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")
// hss host udm
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))
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"]))
}
// SMSC配置修改
if neTypeLower == "smsc" {
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/smsc/default/mcms_conf.txt /usr/local/etc/smsc/mcms_conf.txt \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/smsc/default/sccp.conf /usr/local/etc/smsc/sccp.conf \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/smsc/default/smsc_config.yaml /usr/local/etc/smsc/smsc_config.yaml \n")
cmdStrArr = append(cmdStrArr, "sudo cp /usr/local/etc/smsc/default/wxc2_sys.conf /usr/local/etc/smsc/wxc2_sys.conf \n")
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.240/%s/g\" /usr/local/etc/smsc/mcms_conf.txt \n", para5GData["SMSC_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.240/%s/g\" /usr/local/etc/smsc/sccp.conf \n", para5GData["SMSC_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.1.123/%s/g\" /usr/local/etc/smsc/smsc_config.yaml \n", para5GData["SMSC_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo sed -i \"s/192.168.8.240/%s/g\" /usr/local/etc/smsc/wxc2_sys.conf \n", para5GData["SMSC_IP"]))
cmdStrArr = append(cmdStrArr, fmt.Sprintf("grep -qxF '%s smsc' /etc/hosts || echo '%s smsc' | sudo tee -a /etc/hosts \n", para5GData["SMSC_IP"], para5GData["SMSC_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 := r.neInfoService.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 := r.neInfoService.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
}
// operateRun 操作版本-执行阶段
func (r NeVersion) 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:
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
}
}
// 命令终止符后继续执行命令
// "~]# ":麒麟, "~]$ ":欧拉, "~# ":NXP, "~$ ":Ubuntu
suffixStr := []string{"~]# ", "~]$ ", "~# ", "~$ "}
suffix := false
for _, v := range suffixStr {
if strings.HasSuffix(outputStr, v) {
suffix = true
break
}
}
if !suffix {
suffix = strings.LastIndex(outputStr, "# ") != -1 // 特殊内容中的终端终止符
}
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
// 将安装升级执行结果写入文件
file.WriterFileTXT(commandLineText, fmt.Sprintf("/tmp/operate_run_%s.out", neType))
return commandLineText, nil
}
// operateDome 操作版本-完成阶段
func (r NeVersion) operateDome(action string, neVersion model.NeVersion) error {
if action == "install" {
// 网元信息
neInfo := r.neInfoService.FindByNeTypeAndNeID(neVersion.NeType, neVersion.NeId)
if neInfo.NeId != neVersion.NeId {
return fmt.Errorf("error found neinfo")
}
// ========= 网元OAM配置文件 start ==========
if err := r.neInfoService.NeConfOAMWirteSync(neInfo, nil, true); err != nil {
return fmt.Errorf("error wirte OAM file info")
}
// ========= 网元OAM配置文件 end ===========
// SMSC配置修改 IMS/UDM 配置
if neInfo.NeType == "SMSC" {
para5GData := r.neInfoService.Para5GData
mnc_mcc := fmt.Sprintf("mnc%s.mcc%s", para5GData["MNC_DOMAIN"], para5GData["MCC"])
smscHost := fmt.Sprintf("%s smsc.ims.%s.3gppnetwork.org", para5GData["SMSC_IP"], mnc_mcc)
smscHostCMD := fmt.Sprintf("grep -qxF '%s' /etc/hosts || echo '%s' | sudo tee -a /etc/hosts \n", smscHost, smscHost)
smscIPCMD := fmt.Sprintf("grep -qxF '%s smsc' /etc/hosts || echo '%s smsc' | sudo tee -a /etc/hosts \n", para5GData["SMSC_IP"], para5GData["SMSC_IP"])
smsHost := fmt.Sprintf("sudo sed -i '/^%s smsc.*smsc$/c\\' /etc/hosts", para5GData["SIP_IP"])
// IMS 配置
imsNEs := r.neInfoService.Find(model.NeInfo{NeType: "IMS"}, false, false)
for _, v := range imsNEs {
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, smscIPCMD)
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, smscHostCMD)
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, smsHost)
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, "sudo sed -i '/^#!define WITH_SMS/ s/^/#/' /usr/local/etc/ims/vars.cfg")
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, "ims-stop || true && ims-start")
}
// UDM 配置
smscASName := fmt.Sprintf("sudo sed -i \"/- name: 'sms_as'/{n;s|serverName: .*|serverName: 'sip:%s:5060'|}\" /usr/local/etc/udm/as.yaml", para5GData["SMSC_IP"])
smscASAddress := fmt.Sprintf("sudo sed -i \"/- name: 'sms_as'/{n;n;n;s|diameterAddress: .*|diameterAddress: 'smsc.ims.%s.3gppnetwork.org'|}\" /usr/local/etc/udm/as.yaml", mnc_mcc)
udmNEs := r.neInfoService.Find(model.NeInfo{NeType: "UDM"}, false, false)
for _, v := range udmNEs {
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, smscIPCMD)
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, smscHostCMD)
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, smscASName)
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, smscASAddress)
r.neInfoService.NeRunSSHCmd(v.NeType, v.NeId, "sudo service udm restart")
}
}
}
// 更新Version
verInfo := r.FindByNeTypeAndNeID(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"
r.Update(verInfo)
}
return nil
}