This commit is contained in:
2024-04-01 17:22:29 +08:00
32 changed files with 1614 additions and 274 deletions

View File

@@ -192,13 +192,13 @@ func ExtDatabaseExecSQL(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseExecSQL processing... ")
var sql []string
var err error
// var err error
_, err = services.CheckExtValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
// _, err = services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
//vars := mux.Vars(r)
//tblName := vars["objectTypeValue"]
@@ -253,11 +253,11 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseGetData processing... ")
var sql []string
token, err := services.CheckExtValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
pack := "dbrest"
vars := mux.Vars(r)
@@ -265,7 +265,7 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
dbname := vars["elementTypeValue"]
tbname := vars["objectTypeValue"]
log.Debugf("token:%s, method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", token, r.Method, module, dbname, tbname, pack)
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
@@ -299,7 +299,6 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
for i, s := range sql {
log.Tracef("SQL[%d]: %s", i, sql[i])
rows := make([]map[string]interface{}, 0)
mapRows := make(map[string]interface{})
if s != "" {
@@ -314,7 +313,7 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
querySQL = querySQL + " " + ls
}
log.Debug("querySQL:", querySQL)
rows, err = DbClient.XEngine.QueryInterface(querySQL)
rows, err := DbClient.XEngine.QueryInterface(querySQL)
if err != nil {
log.Error("SQL failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
@@ -336,11 +335,11 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseInsertData processing... ")
token, err := services.CheckExtValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
if err != nil {
@@ -355,7 +354,7 @@ func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
tbname := vars["objectTypeValue"]
pack := "dbrest"
log.Debugf("token:%s, method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", token, r.Method, module, dbname, tbname, pack)
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
@@ -400,11 +399,11 @@ func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseUpdateData processing... ")
token, err := services.CheckExtValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
module := ""
@@ -412,7 +411,7 @@ func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
tbname := vars["objectTypeValue"]
pack := "dbrest"
log.Debugf("token:%s, method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", token, r.Method, module, dbname, tbname, pack)
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
@@ -464,11 +463,11 @@ func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
func ExtDatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseDeleteData processing... ")
token, err := services.CheckExtValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
module := ""
@@ -476,7 +475,7 @@ func ExtDatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
tbname := vars["objectTypeValue"]
pack := "dbreset"
log.Debugf("token:%s, method:%s, module:%, dbname:%s, tbname:%s pack:%s", token, r.Method, module, dbname, tbname, pack)
log.Debugf("method:%s, module:%, dbname:%s, tbname:%s pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {

View File

@@ -84,18 +84,18 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam st
func ExtDatabaseBackupData(w http.ResponseWriter, r *http.Request) {
log.Debug("ExtDatabaseBackupData processing... ")
token, err := services.CheckExtValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
vars := mux.Vars(r)
module := vars["managementModule"]
dbname := vars["dataStorage"]
tbname := vars["dataObject"]
pack := "lm"
log.Debugf("token:%s, method:%s, module:%s dbname:%s, tbname:%s pack:%s", token, r.Method, module, dbname, tbname, pack)
log.Debugf("method:%s, module:%s dbname:%s, tbname:%s pack:%s", r.Method, module, dbname, tbname, pack)
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
// if err != nil {
// log.Error("Failed to get permission:", err)

View File

@@ -186,11 +186,11 @@ func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
log.Debug("PostMMLToNF processing... ")
token, err := services.CheckExtValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Request error:", err)
// return
// }
// 经过测试linux下延时需要大于100ms
// var TIME_DELAY_AFTER_WRITE time.Duration = 200
// var TIME_DEAD_LINE time.Duration = 10
@@ -214,8 +214,7 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
}
log.Debug("neType:", neType, "neId", neId)
log.Debugf("token:%s, method:%s, managementType:%s dbname:%s, tbname:%s pack:%s",
token, r.Method, module, neType, neId[0], pack)
log.Debugf("method:%s, managementType:%s dbname:%s, tbname:%s pack:%s", r.Method, module, neType, neId[0], pack)
var buf [20 * 1024]byte
//buf := make([]byte, 0)
@@ -250,7 +249,7 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
}
neInfo := new(dborm.NeInfo)
neInfo, err = dborm.XormGetNeInfo(neType, neId[0])
neInfo, err := dborm.XormGetNeInfo(neType, neId[0])
if err != nil {
log.Error("dborm.XormGetNeInfo is failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
@@ -631,11 +630,11 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
func PostMMLToOMC(w http.ResponseWriter, r *http.Request) {
log.Debug("PostMMLToOMC processing... ")
token, err := services.CheckExtValidRequest(w, r)
if err != nil {
log.Error("Failed to CheckMmlValidRequest:", err)
return
}
// token, err := services.CheckExtValidRequest(w, r)
// if err != nil {
// log.Error("Failed to CheckMmlValidRequest:", err)
// return
// }
params := r.URL.Query()
neId := params["ne_id"]
@@ -646,7 +645,7 @@ func PostMMLToOMC(w http.ResponseWriter, r *http.Request) {
}
neInfo := new(dborm.NeInfo)
neInfo, err = dborm.XormGetNeInfo("OMC", neId[0])
neInfo, err := dborm.XormGetNeInfo("OMC", neId[0])
if err != nil {
log.Error("dborm.XormGetNeInfo is failed:", err)
services.ResponseInternalServerError500DatabaseOperationFailed(w)
@@ -670,7 +669,7 @@ func PostMMLToOMC(w http.ResponseWriter, r *http.Request) {
MmlHome: config.GetYamlConfig().MML.MmlHome,
Limit: 50,
User: "",
SessionToken: token, // 旧token
SessionToken: "", // 旧token
Authorization: r.Header.Get(tokenConst.HEADER_KEY), // 请求Token
HttpUri: hostUri,
UserAgent: config.GetDefaultUserAgent(),

View File

@@ -68,6 +68,8 @@ upload:
# 软件包
- ".deb"
- ".rpm"
# 验证文件
- ".ini"
# cors 跨域
cors:

View File

@@ -26,6 +26,9 @@ const (
// 软件包
SOFTWARE = "software"
// 授权文件
LICENSE = "license"
)
// 子路径类型映射
@@ -38,4 +41,5 @@ var UploadSubpath = map[string]string{
DOWNLOAD: "下载",
CHUNK: "切片",
SOFTWARE: "软件包",
LICENSE: "授权文件",
}

View File

@@ -5,6 +5,7 @@ import (
"os"
"os/exec"
"path/filepath"
"time"
"be.ems/src/framework/config"
"be.ems/src/framework/logger"
@@ -16,9 +17,9 @@ func FileSCPLocalToNe(neIp, localPath, nePath string) error {
// scp /path/to/local/file.txt user@remote-server:/path/to/remote/directory/
neDir := fmt.Sprintf("%s@%s:%s", usernameNe, neIp, nePath)
cmd := exec.Command("scp", "-r", localPath, neDir)
_, err := cmd.CombinedOutput()
output, err := cmd.CombinedOutput()
if err != nil {
logger.Errorf("FileSCPLocalToNe %s", err.Error())
logger.Errorf("FileSCPLocalToNe %s => %s", output, err.Error())
return err
}
return nil
@@ -31,13 +32,23 @@ func FileSCPNeToLocal(neIp, nePath, localPath string) error {
logger.Errorf("FileSCPNeToLocal MkdirAll err %v", err)
return err
}
// 如果目标文件已经存在,先将目标文件重命名
if info, err := os.Stat(localPath); err == nil && !info.IsDir() {
ext := filepath.Ext(localPath)
name := localPath[0 : len(localPath)-len(ext)]
newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext)
err := os.Rename(localPath, newName)
if err != nil {
return err
}
}
usernameNe := config.Get("ne.user").(string)
// scp user@remote-server:/path/to/remote/directory/ /path/to/local/file.txt
neDir := fmt.Sprintf("%s@%s:%s", usernameNe, neIp, nePath)
cmd := exec.Command("scp", "-r", neDir, localPath)
_, err := cmd.CombinedOutput()
output, err := cmd.CombinedOutput()
if err != nil {
logger.Errorf("FileSCPNeToLocal %s", err.Error())
logger.Errorf("FileSCPNeToLocal %s => %s", output, err.Error())
return err
}
return nil

View File

@@ -11,6 +11,7 @@ import (
"time"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/cmd"
gossh "golang.org/x/crypto/ssh"
)
@@ -96,20 +97,11 @@ func (c *ConnSSH) Close() {
func (c *ConnSSH) NewClientByLocalPrivate() (*ConnSSH, error) {
c.Port = 22
c.AuthMode = "1"
usr, err := user.Current()
privateKey, err := c.CurrentUserRsaKey(false)
if err != nil {
logger.Errorf("NewClientByLocal get current user => %s", err.Error())
return nil, err
}
// 读取用户默认的私钥文件
keyPath := fmt.Sprintf("%s/.ssh/id_rsa", usr.HomeDir)
key, err := os.ReadFile(keyPath)
if err != nil {
logger.Errorf("NewClientByLocal [%s] read private key => %s", usr.Username, err.Error())
return nil, err
}
c.PrivateKey = string(key)
c.PrivateKey = privateKey
return c.NewClient()
}
@@ -134,7 +126,55 @@ func (c *ConnSSH) RunCMD(cmd string) (string, error) {
return c.LastResult, err
}
// NewClient 创建SSH客户端会话对象
// SendToAuthorizedKeys 发送当前用户私钥到远程服务器进行授权密钥
func (c *ConnSSH) SendToAuthorizedKeys() error {
publicKey, err := c.CurrentUserRsaKey(true)
if err != nil {
return err
}
authorizedKeysEntry := fmt.Sprintln(strings.TrimSpace(publicKey))
cmdStr := "echo '" + authorizedKeysEntry + "' >> ~/.ssh/authorized_keys"
_, err = c.RunCMD(cmdStr)
if err != nil {
logger.Errorf("SendAuthorizedKeys echo err %s", err.Error())
return err
}
return nil
}
// CurrentUserRsaKey 当前用户OMC使用的RSA私钥
// 默认读取私钥
// ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
// ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub
func (c *ConnSSH) CurrentUserRsaKey(publicKey bool) (string, error) {
usr, err := user.Current()
if err != nil {
logger.Errorf("CurrentUserRsaKey get => %s", err.Error())
return "", err
}
// 是否存在私钥并创建
keyPath := fmt.Sprintf("%s/.ssh/id_rsa", usr.HomeDir)
if _, err := os.Stat(keyPath); err != nil {
_, err2 := cmd.ExecWithCheck("ssh-keygen", "-t", "rsa", "-P", "", "-f", keyPath)
if err2 != nil {
logger.Errorf("CurrentUserPrivateKey ssh-keygen [%s] rsa => %s", usr.Username, err2.Error())
}
}
// 读取用户默认的文件
if publicKey {
keyPath = keyPath + ".pub"
}
key, err := os.ReadFile(keyPath)
if err != nil {
logger.Errorf("CurrentUserRsaKey [%s] read => %s", usr.Username, err.Error())
return "", fmt.Errorf("read file %s fail", keyPath)
}
return string(key), nil
}
// NewClientSession 创建SSH客户端会话对象
func (c *ConnSSH) NewClientSession(cols, rows int) (*SSHClientSession, error) {
sshSession, err := c.Client.NewSession()
if err != nil {

View File

@@ -354,3 +354,53 @@ func (s *NeHostController) CheckBySSH(c *gin.Context) {
c.JSON(200, result.OkData(data))
}
// 网元主机SSH方式授权免密发送
//
// POST /authorizedBySSH
func (s *NeHostController) AuthorizedBySSH(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeHost
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
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, result.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, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo")))
return
}
defer client.Close()
// 发送密钥
err = client.SendToAuthorizedKeys()
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(nil))
}

View File

@@ -39,15 +39,15 @@ func (s *NeInfoController) State(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeId)
if neInfo.NeId != querys.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
@@ -84,17 +84,26 @@ func (s *NeInfoController) State(c *gin.Context) {
c.JSON(200, result.OkData(resData))
}
// 网元信息列表
// 网元neType和neID查询
//
// GET /list
func (s *NeInfoController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
bandStatus := false
if v, ok := querys["bandStatus"]; ok && v != nil {
bandStatus = parse.Boolean(v)
// GET /byTypeAndID
func (s *NeInfoController) NeTypeAndID(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
}
data := s.neInfoService.SelectPage(querys, bandStatus)
c.JSON(200, result.Ok(data))
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
c.JSON(200, result.OkData(neInfo))
}
// 网元信息列表全部无分页
@@ -129,6 +138,85 @@ func (s *NeInfoController) ListAll(c *gin.Context) {
c.JSON(200, result.OkData(neList))
}
// 网元端配置文件读取
//
// GET /configFile
func (s *NeInfoController) ConfigFileRead(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
FilePath string `form:"filePath"` // 不带文件路径时进行复制覆盖本地网元配置目录
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
data := s.neInfoService.NeConfigFileRead(neInfo, querys.FilePath)
if querys.FilePath == "" {
c.JSON(200, result.OkData(data))
return
}
if len(data) > 0 {
c.JSON(200, result.OkData(data[0]))
return
}
c.JSON(200, result.ErrMsg("no data"))
}
// 网元端配置文件写入
//
// PUT /configFile
func (s *NeInfoController) ConfigFileWrite(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"`
NeID string `json:"neId" binding:"required"`
FilePath string `json:"filePath" binding:"required"`
Content string `json:"content" binding:"required"`
Sync bool `json:"sync"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeID)
if neInfo.NeId != body.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
err := s.neInfoService.NeConfigFileWirte(neInfo, body.FilePath, body.Content, body.Sync)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(nil))
}
// 网元信息列表
//
// GET /list
func (s *NeInfoController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
bandStatus := false
if v, ok := querys["bandStatus"]; ok && v != nil {
bandStatus = parse.Boolean(v)
}
data := s.neInfoService.SelectPage(querys, bandStatus)
c.JSON(200, result.Ok(data))
}
// 网元信息
//
// GET /:infoId
@@ -150,28 +238,6 @@ func (s *NeInfoController) Info(c *gin.Context) {
c.JSON(200, result.OkData(neHost))
}
// 网元neType和neID查询
//
// GET /
func (s *NeInfoController) NeTypeAndID(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
c.JSON(200, result.OkData(neInfo))
}
// 网元信息新增
//
// POST /

View File

@@ -0,0 +1,301 @@
package controller
import (
"fmt"
"strings"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
"be.ems/src/framework/utils/parse"
"be.ems/src/framework/vo/result"
"be.ems/src/modules/network_element/model"
neService "be.ems/src/modules/network_element/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 NeLicenseController 结构体
var NewNeLicense = &NeLicenseController{
neLicenseService: neService.NewNeLicenseImpl,
neInfoService: neService.NewNeInfoImpl,
}
// 网元授权激活信息请求
//
// PATH /license
type NeLicenseController struct {
// 网元授权激活信息服务
neLicenseService neService.INeLicense
// 网元信息服务
neInfoService neService.INeInfo
}
// 网元授权激活信息列表
//
// GET /list
func (s *NeLicenseController) List(c *gin.Context) {
querys := ctx.QueryMap(c)
data := s.neLicenseService.SelectPage(querys)
c.JSON(200, result.Ok(data))
}
// 网元授权激活信息
//
// GET /:licenseId
func (s *NeLicenseController) Info(c *gin.Context) {
language := ctx.AcceptLanguage(c)
licenseId := c.Param("licenseId")
if licenseId == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
neLicense := s.neLicenseService.SelectById(licenseId)
if neLicense.ID != licenseId {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
c.JSON(200, result.OkData(neLicense))
}
// 网元授权激活信息新增
//
// POST /
func (s *NeLicenseController) Add(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeLicense
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID != "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 检查属性值唯一
uniqueInfo := s.neLicenseService.CheckUniqueTypeAndID(neInfo.NeType, neInfo.NeId, "")
if !uniqueInfo {
// 网元授权激活操作【%s】失败网元类型信息已存在
msg := i18n.TTemplate(language, "neLicense.errKeyExists", map[string]any{"name": neInfo.NeType})
c.JSON(200, result.ErrMsg(msg))
return
}
// 读取授权码
code, _ := s.neLicenseService.ReadLicenseInfo(neInfo)
body.ActivationRequestCode = code
body.CreateBy = ctx.LoginUserToUserName(c)
insertId := s.neLicenseService.Insert(body)
if insertId != "" {
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
}
// 网元授权激活信息修改
//
// PUT /
func (s *NeLicenseController) Edit(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeLicense
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查属性值唯一
uniqueInfo := s.neLicenseService.CheckUniqueTypeAndID(body.NeType, body.NeId, body.ID)
if !uniqueInfo {
// 网元授权激活操作【%s】失败网元类型信息已存在
msg := i18n.TTemplate(language, "neLicense.errKeyExists", map[string]any{"name": body.NeType})
c.JSON(200, result.ErrMsg(msg))
return
}
// 检查是否存在
neLicense := s.neLicenseService.SelectById(body.ID)
if neLicense.ID != body.ID {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
body.UpdateBy = ctx.LoginUserToUserName(c)
rows := s.neLicenseService.Update(body)
if rows > 0 {
c.JSON(200, result.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
}
// 网元授权激活信息删除
//
// DELETE /:licenseIds
func (s *NeLicenseController) Remove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
licenseIds := c.Param("licenseIds")
if licenseIds == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 处理字符转id数组后去重
ids := strings.Split(licenseIds, ",")
uniqueIDs := parse.RemoveDuplicates(ids)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
rows, err := s.neLicenseService.DeleteByIds(uniqueIDs)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, result.OkMsg(msg))
}
// 网元授权激活授权申请码
//
// GET /code
func (s *NeLicenseController) Code(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeId)
if neInfo.NeId != querys.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.SelectByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
if neLicense.NeId != querys.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
// 更新授权码
code, licensePath := s.neLicenseService.ReadLicenseInfo(neInfo)
neLicense.ActivationRequestCode = code
if licensePath != "" {
neLicense.LicensePath = licensePath
} else {
neLicense.SerialNum = ""
neLicense.ExpiryDate = ""
neLicense.Status = "0"
}
neLicense.UpdateBy = ctx.LoginUserToUserName(c)
s.neLicenseService.Update(neLicense)
c.JSON(200, result.OkData(code))
}
// 网元授权激活授权文件替换
//
// POST /change
func (s *NeLicenseController) Change(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeLicense
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.HostId == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.SelectByNeTypeAndNeID(body.NeType, body.NeId)
if neLicense.NeId != body.NeId {
body.Status = "0"
body.CreateBy = ctx.LoginUserToUserName(c)
body.ID = s.neLicenseService.Insert(body)
} else {
neLicense.LicensePath = body.LicensePath
neLicense.Status = "0"
neLicense.UpdateBy = ctx.LoginUserToUserName(c)
s.neLicenseService.Update(neLicense)
}
// 进行上传替换
err = s.neLicenseService.UploadToNeHost(body)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(nil))
}
// 网元授权激活状态
//
// GET /state
func (s *NeLicenseController) State(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `form:"neType" binding:"required"`
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeId)
if neInfo.NeId != querys.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 检查是否存在授权记录
neLicense := s.neLicenseService.SelectByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
if neLicense.NeId != querys.NeId {
// 没有可访问网元授权激活数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neLicense.noData")))
return
}
// 查询网元状态
neState, err := neService.NeState(neInfo)
if err != nil {
c.JSON(200, result.ErrMsg("network element service anomaly"))
return
}
// 更新授权信息
neLicense.SerialNum = fmt.Sprint(neState["sn"])
neLicense.ExpiryDate = fmt.Sprint(neState["expire"])
code, licensePath := s.neLicenseService.ReadLicenseInfo(neInfo)
neLicense.ActivationRequestCode = code
neLicense.LicensePath = licensePath
neLicense.Status = "1"
neLicense.UpdateBy = ctx.LoginUserToUserName(c)
rows := s.neLicenseService.Update(neLicense)
if rows > 0 {
c.JSON(200, result.OkData(map[string]string{
"sn": neLicense.SerialNum,
"expire": neLicense.ExpiryDate,
}))
return
}
c.JSON(200, result.Err(nil))
}

View File

@@ -49,7 +49,7 @@ func (s *NeSoftwareController) Info(c *gin.Context) {
neSoftware := s.neSoftwareService.SelectById(softwareId)
if neSoftware.ID != softwareId {
// 没有可访问网元版本数据!
// 没有可访问网元包信息数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData")))
return
}
@@ -64,20 +64,21 @@ func (s *NeSoftwareController) Add(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeSoftware
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID != "" {
if err != nil || body.Path == "" || body.ID != "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查属性值唯一
uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndFileNameAndVersion(body.NeType, body.FileName, body.Version, "")
uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndNameAndVersion(body.NeType, body.Name, body.Version, "")
if !uniqueSoftware {
// 网元软件包操作【%s】失败网元类型与文件名版本已存在
msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.FileName})
msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.Name})
c.JSON(200, result.ErrMsg(msg))
return
}
body.CreateBy = ctx.LoginUserToUserName(c)
insertId := s.neSoftwareService.Insert(body)
if insertId != "" {
c.JSON(200, result.Ok(nil))
@@ -93,16 +94,16 @@ func (s *NeSoftwareController) Edit(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeSoftware
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil || body.ID == "" {
if err != nil || body.Path == "" || body.ID == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查属性值唯一
uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndFileNameAndVersion(body.NeType, body.FileName, body.Version, body.ID)
uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndNameAndVersion(body.NeType, body.Name, body.Version, body.ID)
if !uniqueSoftware {
// 网元软件包操作【%s】失败网元类型与文件名版本已存在
msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.FileName})
msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.Name})
c.JSON(200, result.ErrMsg(msg))
return
}
@@ -110,11 +111,12 @@ func (s *NeSoftwareController) Edit(c *gin.Context) {
// 检查是否存在
neSoftware := s.neSoftwareService.SelectById(body.ID)
if neSoftware.ID != body.ID {
// 没有可访问网元版本数据!
// 没有可访问网元包信息数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData")))
return
}
body.UpdateBy = ctx.LoginUserToUserName(c)
rows := s.neSoftwareService.Update(body)
if rows > 0 {
c.JSON(200, result.Ok(nil))
@@ -149,32 +151,40 @@ func (s *NeSoftwareController) Remove(c *gin.Context) {
c.JSON(200, result.OkMsg(msg))
}
// 网元软件包安装
// 网元软件包安装检查
//
// POST /install
func (s *NeSoftwareController) Install(c *gin.Context) {
// POST /checkInstall
func (s *NeSoftwareController) CheckInstall(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body model.NeSoftware
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil {
if err != nil || body.HostId == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 检查是否存在
neSoftwares := s.neSoftwareService.SelectList(body)
if len(neSoftwares) == 0 {
// 没有可访问网元版本数据!
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData")))
return
// 检查是否存在软件包记录
neSoftwares := s.neSoftwareService.SelectList(model.NeSoftware{
NeType: body.NeType,
Name: body.Name,
Version: body.Version,
})
if len(neSoftwares) <= 0 {
body.CreateBy = ctx.LoginUserToUserName(c)
body.ID = s.neSoftwareService.Insert(body)
} else {
neSoftware := neSoftwares[0]
neSoftware.Path = body.Path
neSoftware.Description = body.Description
neSoftware.UpdateBy = ctx.LoginUserToUserName(c)
s.neSoftwareService.Update(neSoftware)
}
neSoftware := neSoftwares[0]
// 进行安装
output, err := s.neSoftwareService.Install(neSoftware)
// 进行安装检查
cmdStrArr, err := s.neSoftwareService.UploadToNeHost(body)
if err != nil {
c.JSON(200, result.OkData(output))
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Err(nil))
c.JSON(200, result.OkData(cmdStrArr))
}

View File

@@ -78,6 +78,7 @@ func (s *NeVersionController) Add(c *gin.Context) {
return
}
body.CreateBy = ctx.LoginUserToUserName(c)
insertId := s.neVersionService.Insert(body)
if insertId != "" {
c.JSON(200, result.Ok(nil))
@@ -115,6 +116,7 @@ func (s *NeVersionController) Edit(c *gin.Context) {
return
}
body.UpdateBy = ctx.LoginUserToUserName(c)
rows := s.neVersionService.Update(body)
if rows > 0 {
c.JSON(200, result.Ok(nil))

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,6 +25,8 @@ type UDMSub struct {
ApnContext string `json:"apnContext" gorm:"column:apn_context"`
StaticIp string `json:"staticIp" gorm:"column:static_ip"`
// ====== 非数据库字段属性 ======
SubNum string `json:"subNum,omitempty" gorm:"-"` // 批量数
}

View File

@@ -41,10 +41,26 @@ func Setup(router *gin.Engine) {
// 网元信息
neInfoGroup := neGroup.Group("/info")
{
neInfoGroup.GET("/state",
middleware.PreAuthorize(nil),
controller.NewNeInfo.State,
)
neInfoGroup.GET("/byTypeAndID",
middleware.PreAuthorize(nil),
controller.NewNeInfo.NeTypeAndID,
)
neInfoGroup.GET("/listAll",
middleware.PreAuthorize(nil),
controller.NewNeInfo.ListAll,
)
neInfoGroup.GET("/configFile",
middleware.PreAuthorize(nil),
controller.NewNeInfo.ConfigFileRead,
)
neInfoGroup.PUT("/configFile",
middleware.PreAuthorize(nil),
controller.NewNeInfo.ConfigFileWrite,
)
neInfoGroup.GET("/list",
middleware.PreAuthorize(nil),
controller.NewNeInfo.List,
@@ -68,14 +84,6 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeInfo.Remove,
)
neInfoGroup.GET("/state",
middleware.PreAuthorize(nil),
controller.NewNeInfo.State,
)
neInfoGroup.GET("/byTypeAndID",
middleware.PreAuthorize(nil),
controller.NewNeInfo.NeTypeAndID,
)
}
// 网元主机
@@ -119,6 +127,11 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeHost.CheckBySSH,
)
neHostGroup.POST("/authorizedBySSH",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeHost.AuthorizedBySSH,
)
}
// 网元主机命令
@@ -203,10 +216,51 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeSoftware.Remove,
)
neSoftwareGroup.POST("/install",
neSoftwareGroup.POST("/checkInstall",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeSoftware.Install,
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeSoftware.CheckInstall,
)
}
// 网元授权激活信息
neLicenseGroup := neGroup.Group("/license")
{
neLicenseGroup.GET("/list",
middleware.PreAuthorize(nil),
controller.NewNeLicense.List,
)
neLicenseGroup.GET("/:licenseId",
middleware.PreAuthorize(nil),
controller.NewNeLicense.Info,
)
neLicenseGroup.POST("",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neLicense", collectlogs.BUSINESS_TYPE_INSERT)),
controller.NewNeLicense.Add,
)
neLicenseGroup.PUT("",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neLicense", collectlogs.BUSINESS_TYPE_UPDATE)),
controller.NewNeLicense.Edit,
)
neLicenseGroup.DELETE("/:licenseIds",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neLicense", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewNeLicense.Remove,
)
neLicenseGroup.GET("/code",
middleware.PreAuthorize(nil),
controller.NewNeLicense.Code,
)
neLicenseGroup.POST("/change",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neLicense", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewNeLicense.Change,
)
neLicenseGroup.GET("/state",
middleware.PreAuthorize(nil),
controller.NewNeLicense.State,
)
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,7 +15,7 @@ import (
// 实例化数据层 NewNeVersion 结构体
var NewNeVersionImpl = &NeVersionImpl{
selectSql: `select
id, ne_type, ne_id, version, file_path, pre_version, pre_file, new_version, new_file, status, update_time
id, ne_type, ne_id, version, path, pre_version, pre_path, new_version, new_path, status, create_by, create_time, update_by, update_time
from ne_version`,
resultMap: map[string]string{
@@ -23,12 +23,15 @@ var NewNeVersionImpl = &NeVersionImpl{
"ne_type": "NeType",
"ne_id": "NeId",
"version": "Version",
"file_path": "FilePath",
"path": "Path",
"pre_version": "PreVersion",
"pre_file": "PreFile",
"pre_path": "PrePath",
"new_version": "NewVersion",
"new_file": "NewFile",
"new_path": "NewPath",
"status": "Status",
"create_by": "CreateBy",
"create_time": "CreateTime",
"update_by": "UpdateBy",
"update_time": "UpdateTime",
},
}
@@ -139,9 +142,9 @@ func (r *NeVersionImpl) SelectList(neVersion model.NeVersion) []model.NeVersion
conditions = append(conditions, "version like concat(?, '%')")
params = append(params, neVersion.Version)
}
if neVersion.FilePath != "" {
conditions = append(conditions, "file_path like concat(?, '%')")
params = append(params, neVersion.FilePath)
if neVersion.Path != "" {
conditions = append(conditions, "path like concat(?, '%')")
params = append(params, neVersion.Path)
}
// 构建查询条件语句
@@ -151,7 +154,7 @@ func (r *NeVersionImpl) SelectList(neVersion model.NeVersion) []model.NeVersion
}
// 查询数据
querySql := r.selectSql + whereSql + " order by update_time asc "
querySql := r.selectSql + whereSql + " order by id asc "
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
@@ -223,25 +226,28 @@ func (r *NeVersionImpl) Insert(neVersion model.NeVersion) string {
if neVersion.Version != "" {
params["version"] = neVersion.Version
}
if neVersion.FilePath != "" {
params["file_path"] = neVersion.FilePath
if neVersion.Path != "" {
params["path"] = neVersion.Path
}
if neVersion.PreVersion != "" {
params["pre_version"] = neVersion.PreVersion
}
if neVersion.PreFile != "" {
params["pre_file"] = neVersion.PreFile
if neVersion.PrePath != "" {
params["pre_path"] = neVersion.PrePath
}
if neVersion.NewVersion != "" {
params["new_version"] = neVersion.NewVersion
}
if neVersion.NewFile != "" {
params["new_file"] = neVersion.NewFile
if neVersion.NewPath != "" {
params["new_path"] = neVersion.NewPath
}
if neVersion.Status != "" {
params["status"] = neVersion.Status
}
params["update_time"] = time.Now()
if neVersion.CreateBy != "" {
params["create_by"] = neVersion.CreateBy
params["create_time"] = time.Now().UnixMilli()
}
// 构建执行语句
keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params)
@@ -283,25 +289,28 @@ func (r *NeVersionImpl) Update(neVersion model.NeVersion) int64 {
if neVersion.Version != "" {
params["version"] = neVersion.Version
}
if neVersion.FilePath != "" {
params["file_path"] = neVersion.FilePath
if neVersion.Path != "" {
params["path"] = neVersion.Path
}
if neVersion.PreVersion != "" {
params["pre_version"] = neVersion.PreVersion
}
if neVersion.PreFile != "" {
params["pre_file"] = neVersion.PreFile
if neVersion.PrePath != "" {
params["pre_path"] = neVersion.PrePath
}
if neVersion.NewVersion != "" {
params["new_version"] = neVersion.NewVersion
}
if neVersion.NewFile != "" {
params["new_file"] = neVersion.NewFile
if neVersion.NewPath != "" {
params["new_path"] = neVersion.NewPath
}
if neVersion.Status != "" {
params["status"] = neVersion.Status
}
params["update_time"] = time.Now()
if neVersion.UpdateBy != "" {
params["update_by"] = neVersion.UpdateBy
params["update_time"] = time.Now().UnixMilli()
}
// 构建执行语句
keys, values := repo.KeyValueByUpdate(params)

View File

@@ -42,4 +42,13 @@ type INeInfo interface {
// CheckUniqueNeTypeAndNeId 校验同类型下标识是否唯一
CheckUniqueNeTypeAndNeId(neType, neId, infoId string) bool
// NeRunCMD 向网元发送cmd命令
NeRunCMD(neType, neId, cmd string) (string, error)
// NeConfigFileRead 网元配置文件读取 网元配置yaml文件复制到本地后通过filePath读取
NeConfigFileRead(neInfo model.NeInfo, filePath string) []string
// NeConfigFileWirte 网元配置文件写入 content内容 sync同步到网元端
NeConfigFileWirte(neInfo model.NeInfo, filePath, content string, sync bool) error
}

View File

@@ -3,10 +3,14 @@ package service
import (
"encoding/json"
"fmt"
"os"
"runtime"
"strings"
"be.ems/src/framework/constants/cachekey"
"be.ems/src/framework/logger"
"be.ems/src/framework/redis"
"be.ems/src/framework/utils/ssh"
"be.ems/src/modules/network_element/model"
"be.ems/src/modules/network_element/repository"
)
@@ -294,3 +298,139 @@ func (r *NeInfoImpl) CheckUniqueNeTypeAndNeId(neType, neId, infoId string) bool
}
return uniqueId == ""
}
// NeRunCMD 向网元发送cmd命令
func (r *NeInfoImpl) NeRunCMD(neType, neId, cmd string) (string, error) {
neInfo := r.SelectNeInfoByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId {
logger.Errorf("NeRunCMD NeType:%s NeID:%s not found", neType, neId)
return "", fmt.Errorf("neinfo not found")
}
// 带主机信息
if neInfo.HostIDs != "" {
neInfo.Hosts = r.neHostRepository.SelectByIds(strings.Split(neInfo.HostIDs, ","))
if len(neInfo.Hosts) <= 0 {
logger.Errorf("NeRunCMD Hosts %s not found", neInfo.HostIDs)
return "", fmt.Errorf("neinfo host not found")
}
}
neHost := neInfo.Hosts[0]
if neHost.HostType != "ssh" {
logger.Errorf("NeRunCMD Hosts first HostType %s not ssh", neHost.HostType)
return "", fmt.Errorf("neinfo host type not ssh")
}
var connSSH ssh.ConnSSH
neHost.CopyTo(&connSSH)
client, err := connSSH.NewClient()
if err != nil {
logger.Errorf("NeRunCMD NewClient err => %s", err.Error())
return "", fmt.Errorf("neinfo ssh client new err")
}
defer client.Close()
// 执行命令
output, err := client.RunCMD(cmd)
if err != nil {
logger.Errorf("NeRunCMD RunCMD %s err => %s", output, err.Error())
return "", fmt.Errorf("neinfo ssh run cmd err")
}
return output, nil
}
// NeConfigFileRead 网元配置文件读取 网元配置yaml文件复制到本地后通过filePath读取
func (r *NeInfoImpl) NeConfigFileRead(neInfo model.NeInfo, filePath string) []string {
files := []string{}
neTypeLower := strings.ToLower(neInfo.NeType)
// 网管本地路径
omcPath := "/usr/local/etc/omc/ne_config"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
omcPath = fmt.Sprintf("%s/%s/%s", omcPath, neTypeLower, neInfo.NeId)
// 读取文件内容
if filePath != "" {
bytes, err := os.ReadFile(fmt.Sprintf("%s/%s", omcPath, filePath))
if err != nil {
logger.Warnf("NeConfigFile ReadFile => %s", err.Error())
return files
}
files = append(files, string(bytes))
return files
}
// 删除原有配置文件
// err := os.RemoveAll(omcPath)
// if err != nil {
// logger.Warnf("NeConfigFile Remove => %s", err.Error())
// return files
// }
// 网元端配置路径
nePath := "/usr/local/etc"
nePath = fmt.Sprintf("%s/%s", nePath, neTypeLower)
// 各个网元与网元间约定配置文件
err := ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/oam_manager.yaml", omcPath+"/oam_manager.yaml")
if err == nil {
files = append(files, "oam_manager.yaml")
}
// 根据情况复制网元特殊配置
switch neTypeLower {
case "ausf":
err = ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/ausfcfg.yaml", omcPath+"/ausfcfg.yaml")
if err == nil {
files = append(files, "ausfcfg.yaml")
}
case "smf":
ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/smf_conf.yaml", omcPath+"/smf_conf.yaml")
if err == nil {
files = append(files, "smf_conf.yaml")
}
ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/smf_policy.yaml", omcPath+"/smf_policy.yaml")
if err == nil {
files = append(files, "smf_policy.yaml")
}
case "ims":
}
return files
}
// NeConfigFileWirte 网元配置文件写入 content内容 sync同步到网元端
func (r *NeInfoImpl) NeConfigFileWirte(neInfo model.NeInfo, filePath, content string, sync bool) error {
neTypeLower := strings.ToLower(neInfo.NeType)
// 网管本地路径
omcPath := "/usr/local/etc/omc/ne_config"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
localFilePath := fmt.Sprintf("%s/%s/%s/%s", omcPath, neTypeLower, neInfo.NeId, filePath)
err := os.WriteFile(localFilePath, []byte(content), 0644)
if err != nil {
logger.Warnf("NeConfigFile WriteFile => %s", err.Error())
return fmt.Errorf("please check if the file exists or write permissions")
}
// 同步到网元端
if sync {
// 网元端配置路径
neFilePath := fmt.Sprintf("/usr/local/etc/%s/%s", neTypeLower, filePath)
// 修改网元文件权限
r.NeRunCMD(neInfo.NeType, neInfo.NeId, fmt.Sprintf("sudo chmod o+w %s", neFilePath))
// 复制到网元进行覆盖
err = ssh.FileSCPLocalToNe(neInfo.IP, localFilePath, neFilePath)
if err != nil {
logger.Warnf("NeConfigFile SyncFile => %s", err.Error())
return fmt.Errorf("please check if scp remote copy is allowed")
}
}
return nil
}

View File

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

View File

@@ -0,0 +1,183 @@
package service
import (
"fmt"
"os"
"runtime"
"strings"
"time"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/utils/ssh"
"be.ems/src/modules/network_element/model"
"be.ems/src/modules/network_element/repository"
)
// 实例化服务层 NeLicenseImpl 结构体
var NewNeLicenseImpl = &NeLicenseImpl{
neLicenseRepository: repository.NewNeLicenseImpl,
}
// NeLicenseImpl 网元授权激活信息 服务层处理
type NeLicenseImpl struct {
// 网元授权激活信息表
neLicenseRepository repository.INeLicense
}
// SelectNeHostPage 分页查询列表数据
func (r *NeLicenseImpl) SelectPage(query map[string]any) map[string]any {
return r.neLicenseRepository.SelectPage(query)
}
// SelectConfigList 查询列表
func (r *NeLicenseImpl) SelectList(neLicense model.NeLicense) []model.NeLicense {
return r.neLicenseRepository.SelectList(neLicense)
}
// SelectByIds 通过ID查询
func (r *NeLicenseImpl) SelectById(id string) model.NeLicense {
if id == "" {
return model.NeLicense{}
}
neLicenses := r.neLicenseRepository.SelectByIds([]string{id})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// Insert 新增信息
func (r *NeLicenseImpl) Insert(neLicense model.NeLicense) string {
return r.neLicenseRepository.Insert(neLicense)
}
// Update 修改信息
func (r *NeLicenseImpl) Update(neLicense model.NeLicense) int64 {
return r.neLicenseRepository.Update(neLicense)
}
// DeleteByIds 批量删除信息
func (r *NeLicenseImpl) DeleteByIds(ids []string) (int64, error) {
// 检查是否存在
rowIds := r.neLicenseRepository.SelectByIds(ids)
if len(rowIds) <= 0 {
return 0, fmt.Errorf("neLicense.noData")
}
if len(rowIds) == len(ids) {
rows := r.neLicenseRepository.DeleteByIds(ids)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// SelectByTypeAndID 通过网元类型和网元ID查询
func (r *NeLicenseImpl) SelectByTypeAndID(neType, neId string) model.NeLicense {
neLicenses := r.neLicenseRepository.SelectList(model.NeLicense{
NeType: neType,
NeId: neId,
})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// CheckUniqueTypeAndID 校验网元类型和网元ID是否唯一
func (r *NeLicenseImpl) CheckUniqueTypeAndID(neType, neId, id string) bool {
uniqueId := r.neLicenseRepository.CheckUniqueTypeAndID(model.NeLicense{
NeType: neType,
NeId: neId,
})
if uniqueId == id {
return true
}
return uniqueId == ""
}
// SelectByNeTypeAndNeID 通过ne_type和ne_id查询信息
func (r *NeLicenseImpl) SelectByNeTypeAndNeID(neType, neId string) model.NeLicense {
neLicenses := r.neLicenseRepository.SelectList(model.NeLicense{
NeType: neType,
NeId: neId,
})
if len(neLicenses) > 0 {
return neLicenses[0]
}
return model.NeLicense{}
}
// ReadLicenseInfo 读取授权文件信息
// 激活申请码, 激活文件
func (r *NeLicenseImpl) ReadLicenseInfo(neInfo model.NeInfo) (string, string) {
neTypeLower := strings.ToLower(neInfo.NeType)
// 网管本地路径
omcPath := "/usr/local/etc/omc/ne_license"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
omcPath = fmt.Sprintf("%s/%s/%s", omcPath, neTypeLower, neInfo.NeId)
// 网元端授权文件路径
nePath := fmt.Sprintf("/usr/local/etc/%s/license", neTypeLower)
// 复制授权申请码到本地
err := ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/Activation_request_code.txt", omcPath+"/Activation_request_code.txt")
if err != nil {
return "", ""
}
// 读取文件内容
bytes, err := os.ReadFile(omcPath + "/Activation_request_code.txt")
if err != nil {
return "", ""
}
// 激活文件
licensePath := ""
if err = ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/system.ini", omcPath+"/system.ini"); err == nil {
licensePath = omcPath + "/system.ini"
}
return strings.TrimSpace(string(bytes)), licensePath
}
// UploadToNeHost 授权文件上传到网元主机
func (r *NeLicenseImpl) UploadToNeHost(neLicense model.NeLicense) error {
// 检查文件是否存在
omcLicensePath := file.ParseUploadFilePath(neLicense.LicensePath)
if _, err := os.Stat(omcLicensePath); err != nil {
return fmt.Errorf("file read failure")
}
// 检查网元主机
neHostInfo := NewNeHostImpl.SelectById(neLicense.HostId)
if neHostInfo.HostType != "ssh" || neHostInfo.HostID != neLicense.HostId {
return fmt.Errorf("no found host info")
}
// 网元端授权文件路径
neTypeLower := strings.ToLower(neLicense.NeType)
neLicensePath := fmt.Sprintf("/usr/local/etc/%s/license", neTypeLower)
// 修改文件夹权限
NewNeInfoImpl.NeRunCMD(neLicense.NeType, neLicense.NeId, fmt.Sprintf("sudo chmod o+w %s/", neLicensePath))
// 尝试备份授权文件
neLicensePathBack := fmt.Sprintf("%s/system_%s.ini", neLicensePath, time.Now().Format("20060102_150405"))
NewNeInfoImpl.NeRunCMD(neLicense.NeType, neLicense.NeId, fmt.Sprintf("sudo cp -rf %s/system.ini %s", neLicensePath, neLicensePathBack))
// 上传授权文件去覆盖
NewNeInfoImpl.NeRunCMD(neLicense.NeType, neLicense.NeId, fmt.Sprintf("sudo chmod o+w %s/system.ini", neLicensePath))
if err := ssh.FileSCPLocalToNe(neHostInfo.Addr, omcLicensePath, neLicensePath+"/system.ini"); err != nil {
return fmt.Errorf("error uploading license")
}
// 重启服务
if neLicense.Reload {
cmdStr := fmt.Sprintf("sudo service %s restart", neTypeLower)
if neTypeLower == "ims" {
cmdStr = "sudo ims-stop && sudo ims-start"
} else if neTypeLower == "omc" {
cmdStr = "sudo /usr/local/omc/bin/omcsvc.sh restart"
}
NewNeInfoImpl.NeRunCMD(neLicense.NeType, neLicense.NeId, cmdStr)
}
return nil
}

View File

@@ -22,12 +22,10 @@ type INeSoftware interface {
// DeleteByIds 批量删除信息
DeleteByIds(ids []string) (int64, error)
// SelectByVersionAndPath 通过文件版本和路径查询
SelectByVersionAndPath(version, path string) model.NeSoftware
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件版本是否唯一
CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool
// CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一
CheckUniqueTypeAndFileNameAndVersion(neType, fileName, version, id string) bool
// Install 安装软件包
Install(neSoftware model.NeSoftware) (string, error)
// UploadToNeHost 安装包上传到网元主机
// 返回执行命令步骤
UploadToNeHost(neSoftware model.NeSoftware) ([]string, error)
}

View File

@@ -2,7 +2,12 @@ package service
import (
"fmt"
"os"
"path/filepath"
"strings"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/utils/ssh"
"be.ems/src/modules/network_element/model"
"be.ems/src/modules/network_element/repository"
)
@@ -66,24 +71,12 @@ func (r *NeSoftwareImpl) DeleteByIds(ids []string) (int64, error) {
return 0, fmt.Errorf("delete fail")
}
// SelectByVersionAndPath 通过文件版本和路径查询
func (r *NeSoftwareImpl) SelectByVersionAndPath(version, path string) model.NeSoftware {
neSoftwares := r.neSoftwareRepository.SelectList(model.NeSoftware{
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件版本是否唯一
func (r *NeSoftwareImpl) CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool {
uniqueId := r.neSoftwareRepository.CheckUniqueTypeAndNameAndVersion(model.NeSoftware{
NeType: neType,
Name: name,
Version: version,
Path: path,
})
if len(neSoftwares) > 0 {
return neSoftwares[0]
}
return model.NeSoftware{}
}
// CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一
func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neType, fileName, version, id string) bool {
uniqueId := r.neSoftwareRepository.CheckUniqueTypeAndFileNameAndVersion(model.NeSoftware{
NeType: neType,
FileName: fileName,
Version: version,
})
if uniqueId == id {
return true
@@ -91,7 +84,54 @@ func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neType, fileName,
return uniqueId == ""
}
// Install 安装软件包
func (r *NeSoftwareImpl) Install(neSoftware model.NeSoftware) (string, error) {
return "", nil
// UploadToNeHost 安装包上传到网元主机
// 返回执行命令步骤
func (r *NeSoftwareImpl) UploadToNeHost(neSoftware model.NeSoftware) ([]string, error) {
cmdStrArr := []string{}
// 检查文件是否存在
filePath := file.ParseUploadFilePath(neSoftware.Path)
if _, err := os.Stat(filePath); err != nil {
return cmdStrArr, fmt.Errorf("file read failure")
}
fileName := filepath.Base(neSoftware.Path)
if strings.Contains(fileName, "*") {
fileName = strings.ReplaceAll(fileName, "*", "_")
}
nePath := "/tmp"
neFilePath := fmt.Sprintf("%s/%s", nePath, fileName)
// 检查网元主机
neHostInfo := NewNeHostImpl.SelectById(neSoftware.HostId)
if neHostInfo.HostType != "ssh" || neHostInfo.HostID != neSoftware.HostId {
return cmdStrArr, fmt.Errorf("no found host info")
}
// 上传软件包到 /tmp
if err := ssh.FileSCPLocalToNe(neHostInfo.Addr, filePath, neFilePath); err != nil {
return cmdStrArr, fmt.Errorf("error uploading package")
}
// 安装软件包
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo dpkg -i %s", neFilePath))
if neSoftware.NeType == "IMS" {
// 公网 PLMN地址
cmdStrArr = append(cmdStrArr, "sudo /usr/local/etc/ims/default/tools/modipplmn.sh {PUBIP} {MCC} {MNC}")
// 内网 服务地址
cmdStrArr = append(cmdStrArr, "sudo /usr/local/etc/ims/default/tools/modintraip.sh {PRIIP}")
// 10s后停止服务
cmdStrArr = append(cmdStrArr, "sudo ims-start")
cmdStrArr = append(cmdStrArr, `nohup sh -c "sleep 10s && sudo ims-stop" > /dev/null 2>&1 &`)
} else {
// 10s后停止服务
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo service %s restart", strings.ToLower(neSoftware.NeType)))
cmdStrArr = append(cmdStrArr, fmt.Sprintf(`nohup sh -c "sleep 10s && sudo service %s stop" > /dev/null 2>&1 &`, strings.ToLower(neSoftware.NeType)))
}
// 删除软件包
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo rm %s", neFilePath))
// 结束
cmdStrArr = append(cmdStrArr, fmt.Sprintf("echo '%s software install successful!'", neSoftware.NeType))
return cmdStrArr, nil
}

View File

@@ -515,7 +515,8 @@ func (r *SysUserImpl) UpdateUser(sysUser model.SysUser) int64 {
// DeleteUserByIds 批量删除用户信息
func (r *SysUserImpl) DeleteUserByIds(userIds []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(userIds))
sql := "update sys_user set del_flag = '1' where user_id in (" + placeholder + ")"
username := "CASE WHEN user_name = '' THEN user_name WHEN LENGTH(user_name) >= 36 THEN CONCAT('del_', SUBSTRING(user_name, 5, 36)) ELSE CONCAT('del_', user_name) END"
sql := fmt.Sprintf("update sys_user set del_flag = '1', user_name = %s where user_id in (%s)", username, placeholder)
parameters := repo.ConvertIdsSlice(userIds)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {

View File

@@ -196,11 +196,11 @@ func (s *WSController) SSH(c *gin.Context) {
wsClient.MsgChan <- msgByte
// 退出ssh登录
if strings.LastIndex(outputStr, "logout\r\n") != -1 {
time.Sleep(1 * time.Second)
s.wsService.CloseClient(wsClient.ID)
return
}
// if strings.LastIndex(outputStr, "logout\r\n") != -1 {
// time.Sleep(1 * time.Second)
// s.wsService.CloseClient(wsClient.ID)
// return
// }
}
}
}()
@@ -283,11 +283,11 @@ func (s *WSController) Telnet(c *gin.Context) {
wsClient.MsgChan <- msgByte
// 退出telnet登录
if strings.LastIndex(outputStr, "logout\r\n") != -1 {
time.Sleep(1 * time.Second)
s.wsService.CloseClient(wsClient.ID)
return
}
// if strings.LastIndex(outputStr, "logout\r\n") != -1 {
// time.Sleep(1 * time.Second)
// s.wsService.CloseClient(wsClient.ID)
// return
// }
}
}
}()

View File

@@ -3,6 +3,7 @@ package service
import (
"encoding/json"
"fmt"
"io"
"time"
"be.ems/src/framework/logger"
@@ -83,6 +84,11 @@ func (s *WSReceiveImpl) AsyncReceive(client *model.WSClient, reqMsg model.WSRequ
logger.Warnf("ws AsyncReceive UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
if err == io.EOF {
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
client.StopChan <- struct{}{}
}
return
}
if len(resByte) > 0 {