feat: 接口网元状态/网元列表
This commit is contained in:
243
src/framework/utils/fetch/fetch.go
Normal file
243
src/framework/utils/fetch/fetch.go
Normal file
@@ -0,0 +1,243 @@
|
||||
package fetch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Get 发送 GET 请求
|
||||
// timeout 超时时间(秒)
|
||||
func Get(url string, headers map[string]string, timeout uint8) ([]byte, error) {
|
||||
if timeout < 1 || timeout > 180 {
|
||||
timeout = 1
|
||||
}
|
||||
client := &http.Client{
|
||||
Timeout: time.Duration(timeout) * time.Second, // 设置超时时间为 5 秒
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for key, value := range headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New(resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// Post 发送 POST 请求
|
||||
func Post(url string, data url.Values, headers map[string]string) ([]byte, error) {
|
||||
client := &http.Client{}
|
||||
|
||||
req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
for key, value := range headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New(resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// PostJSON 发送 POST 请求,并将请求体序列化为 JSON 格式
|
||||
func PostJSON(url string, data any, headers map[string]string) ([]byte, error) {
|
||||
client := &http.Client{}
|
||||
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
for key, value := range headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New(resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// UploadFile 上传文件函数,接收 URL 地址、表单参数和文件对象,返回响应内容或错误信息
|
||||
func PostUploadFile(url string, params map[string]string, file *os.File) ([]byte, error) {
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
|
||||
part, err := writer.CreateFormFile("file", file.Name())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create form file: %v", err)
|
||||
}
|
||||
|
||||
_, err = io.Copy(part, file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to copy file content: %v", err)
|
||||
}
|
||||
|
||||
for key, value := range params {
|
||||
err = writer.WriteField(key, value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to write form field: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to close writer: %v", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create HTTP request: %v", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("HTTP request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("HTTP request returned status: %s", resp.Status)
|
||||
}
|
||||
|
||||
responseBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response body: %v", err)
|
||||
}
|
||||
|
||||
return responseBody, nil
|
||||
}
|
||||
|
||||
// PutJSON 发送 PUT 请求,并将请求体序列化为 JSON 格式
|
||||
func PutJSON(url string, data any, headers map[string]string) ([]byte, error) {
|
||||
client := &http.Client{}
|
||||
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("PUT", url, bytes.NewReader(jsonData))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for key, value := range headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New(resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// Delete 发送 DELETE 请求
|
||||
func Delete(url string, headers map[string]string) ([]byte, error) {
|
||||
client := &http.Client{}
|
||||
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for key, value := range headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New(resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"ems.agt/lib/global"
|
||||
systemService "ems.agt/src/modules/system/service"
|
||||
)
|
||||
|
||||
@@ -21,6 +22,10 @@ type CommontImpl struct {
|
||||
// SystemConfigInfo 系统配置信息
|
||||
func (s *CommontImpl) SystemConfigInfo() map[string]string {
|
||||
infoMap := map[string]string{}
|
||||
// 获取打包注入的全局变量信息
|
||||
infoMap["version"] = global.Version
|
||||
infoMap["buildTime"] = global.BuildTime
|
||||
infoMap["goVer"] = global.GoVer
|
||||
// 获取LOGO类型
|
||||
logoType := s.sysConfigService.SelectConfigValueByKey("sys.logo.type")
|
||||
infoMap["logoType"] = logoType
|
||||
|
||||
@@ -3,7 +3,9 @@ package controller
|
||||
import (
|
||||
"ems.agt/src/framework/i18n"
|
||||
"ems.agt/src/framework/utils/ctx"
|
||||
"ems.agt/src/framework/utils/parse"
|
||||
"ems.agt/src/framework/vo/result"
|
||||
"ems.agt/src/modules/network_element/model"
|
||||
neService "ems.agt/src/modules/network_element/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -21,22 +23,86 @@ type NeInfoController struct {
|
||||
neInfoService neService.INeInfo
|
||||
}
|
||||
|
||||
// 网元状态
|
||||
//
|
||||
// GET /state
|
||||
func (s *NeInfoController) NeState(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys struct {
|
||||
NeType string `form:"neType" binding:"required"`
|
||||
NeID string `form:"neId" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元直连
|
||||
resData, err := neService.NeState(neInfo)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg("connection failure"))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(resData))
|
||||
}
|
||||
|
||||
// 网元neType和neID查询
|
||||
//
|
||||
// GET /info
|
||||
func (s *NeInfoController) NeTypeAndID(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neType := c.Query("neType")
|
||||
neId := c.Query("neId")
|
||||
if neType == "" || neId == "" {
|
||||
var querys struct {
|
||||
NeType string `form:"neType" binding:"required"`
|
||||
NeID string `form:"neId" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
c.JSON(200, result.OkData(neInfo))
|
||||
}
|
||||
|
||||
// 网元列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *NeInfoController) NeList(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys struct {
|
||||
NeType string `form:"neType"`
|
||||
NeId string `form:"neId"`
|
||||
BandStatus string `form:"bandStatus"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询实体参数
|
||||
ne := model.NeInfo{}
|
||||
if querys.NeType != "" {
|
||||
ne.NeType = querys.NeType
|
||||
}
|
||||
if querys.NeId != "" {
|
||||
ne.NeId = querys.NeId
|
||||
}
|
||||
bandStatus := parse.Boolean(querys.BandStatus)
|
||||
neList := s.neInfoService.SelectNeList(ne, bandStatus)
|
||||
if len(neList) == 0 {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
c.JSON(200, result.OkData(neList))
|
||||
}
|
||||
|
||||
@@ -16,4 +16,9 @@ type NeInfo struct {
|
||||
NeAddress string `json:"neAddress"`
|
||||
Status string `json:"status"` // 0: 在线 1: 下线 2: 备用 3: 工程
|
||||
UpdateTime string `json:"updateTime"`
|
||||
|
||||
// ====== 非数据库字段属性 ======
|
||||
|
||||
// 服务状态
|
||||
ServerState map[string]any `json:"serverState,omitempty"`
|
||||
}
|
||||
|
||||
@@ -20,6 +20,14 @@ func Setup(router *gin.Engine) {
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewNeInfo.NeTypeAndID,
|
||||
)
|
||||
neGroup.GET("/state",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewNeInfo.NeState,
|
||||
)
|
||||
neGroup.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewNeInfo.NeList,
|
||||
)
|
||||
}
|
||||
|
||||
// 网元处理
|
||||
|
||||
@@ -8,4 +8,7 @@ import (
|
||||
type INeInfo interface {
|
||||
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
|
||||
SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo
|
||||
|
||||
// SelectNeList 查询网元列表
|
||||
SelectNeList(ne model.NeInfo) []model.NeInfo
|
||||
}
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"ems.agt/src/framework/datasource"
|
||||
"ems.agt/src/framework/logger"
|
||||
"ems.agt/src/framework/utils/repo"
|
||||
"ems.agt/src/modules/network_element/model"
|
||||
)
|
||||
|
||||
// neListSort 网元列表预设排序
|
||||
var neListSort = []string{
|
||||
"OMC",
|
||||
"MME",
|
||||
"AMF",
|
||||
"AUSF",
|
||||
"UDM",
|
||||
"SMF",
|
||||
"PCF",
|
||||
"UPF",
|
||||
"NRF",
|
||||
"NSSF",
|
||||
"IMS",
|
||||
"N3IWF",
|
||||
"NEF",
|
||||
"LMF",
|
||||
}
|
||||
|
||||
// 实例化数据层 NeInfoImpl 结构体
|
||||
var NewNeInfoImpl = &NeInfoImpl{
|
||||
selectSql: `select id, ne_type, ne_id, rm_uid, ne_name, ip, port, pv_flag, province, vendor_name, dn, ne_address, status, update_time from ne_info`,
|
||||
@@ -49,6 +70,31 @@ func (r *NeInfoImpl) convertResultRows(rows []map[string]any) []model.NeInfo {
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
|
||||
// 排序
|
||||
sort.Slice(arr, func(i, j int) bool {
|
||||
// 前一个
|
||||
after := arr[i]
|
||||
afterIndex := 0
|
||||
for i, v := range neListSort {
|
||||
if after.NeType == v {
|
||||
afterIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
// 后一个
|
||||
befter := arr[j]
|
||||
befterIndex := 0
|
||||
for i, v := range neListSort {
|
||||
if befter.NeType == v {
|
||||
befterIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
// 升序
|
||||
return afterIndex < befterIndex
|
||||
})
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
@@ -67,3 +113,34 @@ func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeIn
|
||||
}
|
||||
return model.NeInfo{}
|
||||
}
|
||||
|
||||
// SelectNeList 查询网元列表
|
||||
func (r *NeInfoImpl) SelectNeList(ne model.NeInfo) []model.NeInfo {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if ne.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, ne.NeType)
|
||||
}
|
||||
if ne.NeId != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, ne.NeId)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + " order by ne_type asc "
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
44
src/modules/network_element/service/ne_direct_link.go
Normal file
44
src/modules/network_element/service/ne_direct_link.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ems.agt/src/framework/logger"
|
||||
"ems.agt/src/framework/utils/fetch"
|
||||
"ems.agt/src/modules/network_element/model"
|
||||
)
|
||||
|
||||
// NeState 获取网元端服务状态
|
||||
func NeState(neInfo model.NeInfo) (map[string]any, error) {
|
||||
// 网元直连
|
||||
neUrl := fmt.Sprintf("http://%s:%d/api/rest/systemManagement/v1/elementType/%s/objectType/systemState", neInfo.IP, neInfo.Port, strings.ToLower(neInfo.NeType))
|
||||
resBytes, err := fetch.Get(neUrl, nil, 1)
|
||||
if err != nil {
|
||||
logger.Warnf("NeState %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 序列化结果
|
||||
var resData map[string]any
|
||||
err = json.Unmarshal(resBytes, &resData)
|
||||
if err != nil {
|
||||
logger.Warnf("NeState Unmarshal %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"neType": neInfo.NeType,
|
||||
"neId": neInfo.NeId,
|
||||
"neName": neInfo.NeName,
|
||||
"refreshTime": time.Now().UnixMilli(), // 获取时间
|
||||
"version": resData["version"],
|
||||
"capability": resData["capability"],
|
||||
"sn": resData["serialNum"],
|
||||
"expire": resData["expiryDate"],
|
||||
"cpu": resData["cpuUsage"],
|
||||
"mem": resData["memUsage"],
|
||||
}, nil
|
||||
}
|
||||
@@ -6,4 +6,7 @@ import "ems.agt/src/modules/network_element/model"
|
||||
type INeInfo interface {
|
||||
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
|
||||
SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo
|
||||
|
||||
// SelectNeList 查询网元列表
|
||||
SelectNeList(ne model.NeInfo, bandStatus bool) []model.NeInfo
|
||||
}
|
||||
|
||||
@@ -20,3 +20,24 @@ type NeInfoImpl struct {
|
||||
func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo {
|
||||
return r.NeInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID)
|
||||
}
|
||||
|
||||
// SelectNeList 查询网元列表
|
||||
func (r *NeInfoImpl) SelectNeList(ne model.NeInfo, bandStatus bool) []model.NeInfo {
|
||||
list := r.NeInfoRepository.SelectNeList(ne)
|
||||
|
||||
// 网元直连读取网元服务状态
|
||||
if bandStatus {
|
||||
neList := &list
|
||||
for i := range *neList {
|
||||
v := (*neList)[i]
|
||||
result, err := NeState(v)
|
||||
if err != nil {
|
||||
(*neList)[i].ServerState = map[string]any{}
|
||||
continue
|
||||
}
|
||||
(*neList)[i].ServerState = result
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user