From e7ae390f6ece927a5ff95150e0f3b873dca87ecb Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 27 Oct 2025 15:15:27 +0800 Subject: [PATCH] =?UTF-8?q?ref:=20=E9=87=8D=E6=9E=84=E7=BD=91=E5=85=83?= =?UTF-8?q?=E7=8A=B6=E6=80=81=EF=BC=8C=E6=8F=90=E5=8D=87=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E7=BD=91=E5=85=83=E5=88=97=E8=A1=A8=E5=B8=A6=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E9=80=9F=E5=BA=A6=20Refactor=20network=20element=20state=20man?= =?UTF-8?q?agement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed the NE state endpoint and related service logic from the network_data module. - Introduced a new NEStateController to handle network element state records. - Implemented NEState service and repository for managing state records in the database. - Updated NEInfo and NeLicense controllers to utilize the new NEState service for fetching and saving state information. - Enhanced state handling in the websocket processor to reflect the latest state of network elements. - Added caching logic for network element states using Redis. - Improved error handling and response formatting for state queries. --- build/database/lite/install/ne_state.sql | 12 +- build/database/lite/upgrade/upg_ne_state.sql | 38 ++++ build/database/std/install/ne_state.sql | 16 +- build/database/std/upgrade/upg_ne_state.sql | 44 ++--- .../ne_alarm_state_check_cmd.go | 91 +++------- src/modules/network_data/network_data.go | 9 - src/modules/network_data/service/ne_state.go | 31 ---- .../network_element/controller/ne_info.go | 167 +++++++----------- .../network_element/controller/ne_license.go | 25 ++- .../controller/ne_state.go} | 13 +- .../model/ne_state.go | 14 +- .../network_element/network_element.go | 9 + .../repository/ne_state.go | 40 +++-- .../network_element/repository/ne_version.go | 20 +++ .../network_element/service/ne_info.go | 48 +++-- .../network_element/service/ne_state.go | 137 ++++++++++++++ .../network_element/service/ne_version.go | 27 +-- src/modules/ws/processor/ne_state.go | 30 ++-- 18 files changed, 428 insertions(+), 343 deletions(-) create mode 100644 build/database/lite/upgrade/upg_ne_state.sql delete mode 100644 src/modules/network_data/service/ne_state.go rename src/modules/{network_data/controller/all_ne_state.go => network_element/controller/ne_state.go} (85%) rename src/modules/{network_data => network_element}/model/ne_state.go (65%) rename src/modules/{network_data => network_element}/repository/ne_state.go (70%) create mode 100644 src/modules/network_element/service/ne_state.go diff --git a/build/database/lite/install/ne_state.sql b/build/database/lite/install/ne_state.sql index 08a6528b..a5fb5930 100644 --- a/build/database/lite/install/ne_state.sql +++ b/build/database/lite/install/ne_state.sql @@ -6,16 +6,20 @@ CREATE TABLE "ne_state" ( "id" integer NOT NULL, "ne_type" text(16), "ne_id" text(32), - "version" text(16), - "capability" integer, + "ne_version" text(16), + "standby" integer, + "nb_number" integer, + "ue_number" integer, "serial_num" text(16), "expiry_date" text(10), + "hostname" text(32), + "os" text(196), "sys_cpu_usage" integer, "sys_mem_usage" integer, "sys_disk_usage" integer, "nf_cpu_usage" integer, "nf_mem_used" integer, - "create_time" integer, + "refresh_time" integer, PRIMARY KEY ("id") ); @@ -26,7 +30,7 @@ CREATE INDEX "idx_type_id_time" ON "ne_state" ( "ne_type" ASC, "ne_id" ASC, - "create_time" ASC + "refresh_time" ASC ); -- ---------------------------- diff --git a/build/database/lite/upgrade/upg_ne_state.sql b/build/database/lite/upgrade/upg_ne_state.sql new file mode 100644 index 00000000..cc61e90d --- /dev/null +++ b/build/database/lite/upgrade/upg_ne_state.sql @@ -0,0 +1,38 @@ +-- ---------------------------- +-- Table structure for ne_state +-- ---------------------------- +DROP TABLE IF EXISTS "ne_state"; +CREATE TABLE "ne_state" ( + "id" integer NOT NULL, + "ne_type" text(16), + "ne_id" text(32), + "ne_version" text(16), + "standby" integer, + "nb_number" integer, + "ue_number" integer, + "serial_num" text(16), + "expiry_date" text(10), + "hostname" text(32), + "os" text(196), + "sys_cpu_usage" integer, + "sys_mem_usage" integer, + "sys_disk_usage" integer, + "nf_cpu_usage" integer, + "nf_mem_used" integer, + "refresh_time" integer, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- Indexes structure for table ne_state +-- ---------------------------- +CREATE INDEX IF NOT EXISTS "idx_type_id_time" +ON "ne_state" ( + "ne_type" ASC, + "ne_id" ASC, + "refresh_time" ASC +); + +-- ---------------------------- +-- Records of ne_state +-- ---------------------------- diff --git a/build/database/std/install/ne_state.sql b/build/database/std/install/ne_state.sql index 6d44ed7e..a305bed3 100644 --- a/build/database/std/install/ne_state.sql +++ b/build/database/std/install/ne_state.sql @@ -7,20 +7,24 @@ SET FOREIGN_KEY_CHECKS = 0; DROP TABLE IF EXISTS `ne_state`; CREATE TABLE `ne_state` ( `id` int NOT NULL AUTO_INCREMENT, - `ne_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '', - `ne_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '', - `version` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '版本', - `capability` bigint DEFAULT '0' COMMENT '用户容量', + `ne_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '网元类型', + `ne_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '网元ID', + `ne_version` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '网元版本', + `standby` int DEFAULT '0' COMMENT '主备状态 0-主 1-备', + `nb_number` int DEFAULT '0' COMMENT '基站容量', + `ue_number` int DEFAULT '0' COMMENT '用户容量', `serial_num` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '序列号', `expiry_date` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '许可证到期日期', + `hostname` varchar(32) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '主机名 hostname', + `os` varchar(196) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '操作系统 uname', `sys_cpu_usage` float DEFAULT '0' COMMENT 'cpu使用率-sys', `sys_mem_usage` float DEFAULT '0' COMMENT '内存使用率-sys', `sys_disk_usage` float DEFAULT '0' COMMENT '磁盘使用率-sys', `nf_cpu_usage` float DEFAULT '0' COMMENT 'cpu使用率-nf', `nf_mem_used` bigint DEFAULT '0' COMMENT '内存使用KB-nf', - `create_time` bigint DEFAULT '0' COMMENT '创建时间', + `refresh_time` bigint DEFAULT '0' COMMENT '刷新时间', PRIMARY KEY (`id`) USING BTREE, - KEY `idx_type_id_time` (`ne_type`,`ne_id`,`create_time`) USING BTREE COMMENT 'idx_state_ne_type_id_at' + KEY `idx_type_id_time` (`ne_type`,`ne_id`,`refresh_time`) USING BTREE COMMENT 'idx_state_ne_type_id_at' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='网元_状态记录内存/CPU/磁盘'; SET FOREIGN_KEY_CHECKS=1; diff --git a/build/database/std/upgrade/upg_ne_state.sql b/build/database/std/upgrade/upg_ne_state.sql index 53efbb5b..33ad4d93 100644 --- a/build/database/std/upgrade/upg_ne_state.sql +++ b/build/database/std/upgrade/upg_ne_state.sql @@ -1,49 +1,29 @@ -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; - -- -- Table structure for table `ne_state` -- -CREATE TABLE IF NOT EXISTS `ne_state` ( +DROP TABLE IF EXISTS `ne_state`; +CREATE TABLE `ne_state` ( `id` int NOT NULL AUTO_INCREMENT, - `ne_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '', - `ne_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '', - `version` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '版本', - `capability` bigint DEFAULT '0' COMMENT '用户容量', + `ne_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '网元类型', + `ne_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '网元ID', + `ne_version` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '网元版本', + `standby` int DEFAULT '0' COMMENT '主备状态 0-主 1-备', + `nb_number` int DEFAULT '0' COMMENT '基站容量', + `ue_number` int DEFAULT '0' COMMENT '用户容量', `serial_num` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '序列号', `expiry_date` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '许可证到期日期', + `hostname` varchar(32) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '主机名 hostname', + `os` varchar(196) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '操作系统 uname', `sys_cpu_usage` float DEFAULT '0' COMMENT 'cpu使用率-sys', `sys_mem_usage` float DEFAULT '0' COMMENT '内存使用率-sys', `sys_disk_usage` float DEFAULT '0' COMMENT '磁盘使用率-sys', `nf_cpu_usage` float DEFAULT '0' COMMENT 'cpu使用率-nf', `nf_mem_used` bigint DEFAULT '0' COMMENT '内存使用KB-nf', - `create_time` bigint DEFAULT '0' COMMENT '创建时间', + `refresh_time` bigint DEFAULT '0' COMMENT '刷新时间', PRIMARY KEY (`id`) USING BTREE, - KEY `idx_type_id_time` (`ne_type`,`ne_id`,`create_time`) USING BTREE COMMENT 'idx_state_ne_type_id_at' + KEY `idx_type_id_time` (`ne_type`,`ne_id`,`refresh_time`) USING BTREE COMMENT 'idx_state_ne_type_id_at' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='网元_状态记录内存/CPU/磁盘'; -- ---------------------------- -- COLUMN for ne_state -- ---------------------------- -ALTER TABLE `ne_state` DROP COLUMN `cpu_usage`; -ALTER TABLE `ne_state` DROP COLUMN `mem_usage`; -ALTER TABLE `ne_state` DROP COLUMN `disk_space`; -ALTER TABLE `ne_state` DROP COLUMN `timestamp`; -ALTER TABLE `ne_state` DROP INDEX `idx_ne_type_id`; -ALTER TABLE `ne_state` DROP INDEX `idx_timestamp`; -ALTER TABLE `ne_state` MODIFY COLUMN `ne_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' AFTER `id`; -ALTER TABLE `ne_state` MODIFY COLUMN `ne_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' AFTER `ne_type`; -ALTER TABLE `ne_state` MODIFY COLUMN `version` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '版本' AFTER `ne_id`; -ALTER TABLE `ne_state` MODIFY COLUMN `capability` bigint(20) NULL DEFAULT 0 COMMENT '用户容量' AFTER `version`; -ALTER TABLE `ne_state` MODIFY COLUMN `serial_num` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '序列号' AFTER `capability`; -ALTER TABLE `ne_state` MODIFY COLUMN `expiry_date` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '许可证到期日期' AFTER `serial_num`; -ALTER TABLE `ne_state` ADD COLUMN `sys_cpu_usage` float NULL DEFAULT 0 COMMENT 'cpu使用率-sys' AFTER `expiry_date`; -ALTER TABLE `ne_state` ADD COLUMN `sys_mem_usage` float NULL DEFAULT 0 COMMENT '内存使用率-sys' AFTER `sys_cpu_usage`; -ALTER TABLE `ne_state` ADD COLUMN `sys_disk_usage` float NULL DEFAULT 0 COMMENT '磁盘使用率-sys' AFTER `sys_mem_usage`; -ALTER TABLE `ne_state` ADD COLUMN `nf_cpu_usage` float NULL DEFAULT 0 COMMENT 'cpu使用率-nf' AFTER `sys_disk_usage`; -ALTER TABLE `ne_state` ADD COLUMN `nf_mem_used` bigint(20) NULL DEFAULT 0 COMMENT '内存使用KB-nf' AFTER `nf_cpu_usage`; -ALTER TABLE `ne_state` ADD COLUMN `create_time` bigint(20) NULL DEFAULT 0 COMMENT '创建时间' AFTER `nf_mem_used`; -ALTER TABLE `ne_state` ADD INDEX `idx_type_id_time`(`ne_type`, `ne_id`, `create_time`) USING BTREE COMMENT 'idx_state_ne_type_id_at'; -ALTER TABLE `ne_state` COMMENT = '网元_状态记录内存/CPU/磁盘'; - -SET FOREIGN_KEY_CHECKS=1; diff --git a/src/modules/crontask/processor/ne_alarm_state_check_cmd/ne_alarm_state_check_cmd.go b/src/modules/crontask/processor/ne_alarm_state_check_cmd/ne_alarm_state_check_cmd.go index c1de2070..ab65a793 100644 --- a/src/modules/crontask/processor/ne_alarm_state_check_cmd/ne_alarm_state_check_cmd.go +++ b/src/modules/crontask/processor/ne_alarm_state_check_cmd/ne_alarm_state_check_cmd.go @@ -4,8 +4,6 @@ import ( "encoding/json" "fmt" "runtime" - "sort" - "strconv" "strings" "sync" "time" @@ -17,8 +15,7 @@ import ( "be.ems/src/framework/database/redis" "be.ems/src/framework/logger" "be.ems/src/framework/utils/parse" - neDataModel "be.ems/src/modules/network_data/model" - neDataService "be.ems/src/modules/network_data/service" + neFetchlink "be.ems/src/modules/network_element/fetch_link" neModel "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" oamService "be.ems/src/modules/oam/service" @@ -27,7 +24,7 @@ import ( var NewProcessor = &NeAlarmStateCheckCMDProcessor{ neInfoService: neService.NewNeInfo, - neStateService: neDataService.NewNEState, + neStateService: neService.NewNEState, wsSendService: wsService.NewWSSend, count: 0, triggerMax: 3, @@ -36,12 +33,12 @@ var NewProcessor = &NeAlarmStateCheckCMDProcessor{ // NeAlarmStateCheckCMDProcessor 网元告警内存/CPU/磁盘检查 type NeAlarmStateCheckCMDProcessor struct { - neInfoService *neService.NeInfo // 网元信息服务 - neStateService *neDataService.NEState // 网元状态信息服务 - wsSendService *wsService.WSSend // ws发送服务 - count int // 执行次数 - triggerMax int64 // 阈值:连续触发次数大于该值才会产生告警 - triggerCount sync.Map // 阈值连续触发次数,存储每个事件的触发记录 + neInfoService *neService.NeInfo // 网元信息服务 + neStateService *neService.NEState // 网元状态信息服务 + wsSendService *wsService.WSSend // ws发送服务 + count int // 执行次数 + triggerMax int64 // 阈值:连续触发次数大于该值才会产生告警 + triggerCount sync.Map // 阈值连续触发次数,存储每个事件的触发记录 } // alarmParams 告警参数 @@ -95,20 +92,23 @@ func (s *NeAlarmStateCheckCMDProcessor) Execute(data any) (any, error) { return nil, fmt.Errorf("diskUseGt must be between 0 and 100") } - neList := s.neInfoService.Find(neModel.NeInfo{}, true, false) + neList := s.neInfoService.Find(neModel.NeInfo{}, false, false) for _, neInfo := range neList { if neInfo.CreateTime == 0 { continue } // 网元在线状态 - isOnline := parse.Boolean(neInfo.ServerState["online"]) - if !isOnline { + key := fmt.Sprintf("%s:%s:%s_status", constants.CACHE_NE_INFO, neInfo.NeType, neInfo.NeId) + state, stateErr := neFetchlink.NeState(neInfo) + if stateErr != nil { + redis.Del("", key) continue } + redis.Set("", key, neInfo.RmUID, 0) // 检查状态 - sysCpuUsage, sysMemUsage, sysDiskUsage := s.serverState(neInfo.ServerState) + sysCpuUsage, sysMemUsage, sysDiskUsage := s.serverState(state) // 检查CPU/Memory/Disk使用率 warnMsg := []string{} if int64(sysCpuUsage) >= params.CPUUseGt { @@ -193,68 +193,17 @@ func (s *NeAlarmStateCheckCMDProcessor) Execute(data any) (any, error) { // serverState 网元状态记录 func (s *NeAlarmStateCheckCMDProcessor) serverState(state map[string]any) (float64, float64, float64) { - // 网元CPU使用率 - var nfCpuUsage float64 = 0 - // CPU使用率 - var sysCpuUsage float64 = 0 - if state["cpu"] != nil { - cpu := state["cpu"].(map[string]any) - v := parse.Number(cpu["sysCpuUsage"]) - sysCpuUsage = float64(v) / 100 - nfv := parse.Number(cpu["nfCpuUsage"]) - nfCpuUsage = float64(nfv) / 100 + neState := s.neStateService.SaveState(state) + if neState.ID <= 0 { + return 0, 0, 0 } - // 网元内存使用KB - var nfMemUsed int64 = 0 - // 内存使用率 - var sysMemUsage float64 = 0 - if state["mem"] != nil { - mem := state["mem"].(map[string]any) - v := parse.Number(mem["sysMemUsage"]) - sysMemUsage = float64(v) / 100 - nfMemUsed = parse.Number(mem["nfUsedMem"]) - } - - // 磁盘使用率 - var sysDiskUsage float64 = 0 - if state["disk"] != nil { - mem := state["disk"].(map[string]any) - disks := mem["partitionInfo"].([]any) - sort.Slice(disks, func(i, j int) bool { - iUsed := parse.Number(disks[i].(map[string]any)["used"]) - jUsed := parse.Number(disks[j].(map[string]any)["used"]) - return iUsed > jUsed - }) - disk := disks[0].(map[string]any) - total := parse.Number(disk["total"]) - used := parse.Number(disk["used"]) - sysDiskUsage = (float64(used) / float64(total)) * 100 - sysDiskUsage, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", sysDiskUsage), 64) - } - - // 插入网元状态记录 - neState := neDataModel.NEState{ - NeType: fmt.Sprint(state["neType"]), - NeId: fmt.Sprint(state["neId"]), - Version: fmt.Sprint(state["version"]), - Capability: parse.Number(state["capability"]), - SerialNum: fmt.Sprint(state["sn"]), - ExpiryDate: fmt.Sprint(state["expire"]), - SysCpuUsage: sysCpuUsage, - SysMemUsage: sysMemUsage, - SysDiskUsage: sysDiskUsage, - NfCpuUsage: nfCpuUsage, - NfMemUsed: nfMemUsed, - CreateTime: parse.Number(state["refreshTime"]), - } - s.neStateService.Insert(neState) // 删除网元状态记录7天前 ltTime := time.Now().AddDate(0, 0, -7).UnixMilli() - s.neStateService.DeleteByTime(ltTime) + s.neStateService.DeleteByTime(neState.NeType, neState.NeId, ltTime) // 推送ws消息 groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_NE_STATE, neState.NeType, neState.NeId) s.wsSendService.ByGroupID(groupID, neState) - return sysCpuUsage, sysMemUsage, sysDiskUsage + return neState.SysCpuUsage, neState.SysMemUsage, neState.SysDiskUsage } diff --git a/src/modules/network_data/network_data.go b/src/modules/network_data/network_data.go index 72d83484..8e9738c8 100644 --- a/src/modules/network_data/network_data.go +++ b/src/modules/network_data/network_data.go @@ -137,15 +137,6 @@ func Setup(router *gin.Engine) { ) } - // 网元状态记录信息 - neStateGroup := neDataGroup.Group("/ne-state") - { - neStateGroup.GET("/list", - middleware.AuthorizeUser(nil), - controller.NewNEState.List, - ) - } - // 基站状态历史记录信息 含AMF/MME nbStateGroup := neDataGroup.Group("/nb-state") { diff --git a/src/modules/network_data/service/ne_state.go b/src/modules/network_data/service/ne_state.go deleted file mode 100644 index be467f18..00000000 --- a/src/modules/network_data/service/ne_state.go +++ /dev/null @@ -1,31 +0,0 @@ -package service - -import ( - "be.ems/src/modules/network_data/model" - "be.ems/src/modules/network_data/repository" -) - -// 实例化数据层 NEState 结构体 -var NewNEState = &NEState{ - neStateRepository: repository.NewNEState, -} - -// NEState 网元状态记录表 服务层处理 -type NEState struct { - neStateRepository *repository.NEState // 网元状态记录信息 -} - -// FindByPage 根据条件分页查询 -func (r NEState) FindByPage(query model.NEStateQuery) ([]model.NEState, int64) { - return r.neStateRepository.SelectByPage(query) -} - -// Insert 插入数据 -func (r NEState) Insert(item model.NEState) int64 { - return r.neStateRepository.Insert(item) -} - -// DeleteByTime 删除数据 -func (r NEState) DeleteByTime(ltTime int64) int64 { - return r.neStateRepository.DeleteByTime(ltTime) -} diff --git a/src/modules/network_element/controller/ne_info.go b/src/modules/network_element/controller/ne_info.go index 17526d25..b9d76f00 100644 --- a/src/modules/network_element/controller/ne_info.go +++ b/src/modules/network_element/controller/ne_info.go @@ -3,8 +3,9 @@ package controller import ( "fmt" "strings" - "sync" + "be.ems/src/framework/constants" + "be.ems/src/framework/database/redis" "be.ems/src/framework/i18n" "be.ems/src/framework/reqctx" "be.ems/src/framework/resp" @@ -21,6 +22,7 @@ var NewNeInfo = &NeInfoController{ neInfoService: neService.NewNeInfo, neLicenseService: neService.NewNeLicense, neVersionService: neService.NewNeVersion, + neStateService: neService.NewNEState, } // 网元信息请求 @@ -30,12 +32,9 @@ type NeInfoController struct { neInfoService *neService.NeInfo // 网元信息服务 neLicenseService *neService.NeLicense // 网元授权激活信息服务 neVersionService *neService.NeVersion // 网元版本信息服务 + neStateService *neService.NEState // 网元状态服务 } -// neStateCacheMap 网元状态缓存最后一次成功的信息 -var neStateCacheMap sync.Map -var mutex sync.Mutex - // 网元信息状态 // // GET /state @@ -67,37 +66,18 @@ func (s NeInfoController) State(c *gin.Context) { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } - neKey := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId) + state := s.neStateService.Last(neInfo.NeType, neInfo.NeId) + result := s.neStateService.ParseState(neInfo, state) - // 网元直连 - 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 + // 没状态标记,视为离线 + key := fmt.Sprintf("%s:%s:%s_status", constants.CACHE_NE_INFO, neInfo.NeType, neInfo.NeId) + keyNum, err := redis.Has("", key) + if keyNum == 0 || err != nil { + result["online"] = false + } else { + result["online"] = true } - - // 存入缓存 - resData["online"] = true - mutex.Lock() - neStateCacheMap.Store(neKey, resData) - mutex.Unlock() - c.JSON(200, resp.OkData(resData)) + c.JSON(200, resp.OkData(result)) } // 网元neType和neID查询 @@ -362,22 +342,6 @@ func (s NeInfoController) Add(c *gin.Context) { 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{ @@ -392,24 +356,34 @@ func (s NeInfoController) Add(c *gin.Context) { CreateBy: loginUserName, } - // 已有网元可获取的信息 - if body.ServerState != nil { - if v, ok := body.ServerState["version"]; ok && v != nil { - body.NeVersion = fmt.Sprint(v) - neVersion.Version = fmt.Sprint(v) + // 获取网元状态是否正常 + key := fmt.Sprintf("%s:%s:%s_status", constants.CACHE_NE_INFO, body.NeType, body.NeId) + state, err := neFetchlink.NeState(body) + if err != nil { + redis.Del("", key) + body.Status = 0 + } else { + redis.Set("", key, body.RmUID, 0) + // 网元状态设置为在线 + body.Status = 1 + if parse.Boolean(state["standby"]) { + body.Status = 3 } - if v, ok := body.ServerState["sn"]; ok && v != nil { - neLicense.SerialNum = fmt.Sprint(v) + // 下发网管配置信息给网元 + if _, err = neFetchlink.NeConfigOMC(body); err != nil { + body.Status = 2 } - if v, ok := body.ServerState["expire"]; ok && v != nil { - neLicense.ExpiryDate = fmt.Sprint(v) + // 网元状态记录 + neState := s.neStateService.SaveState(state) + body.ServerState = s.neStateService.ParseState(body, neState) + if neState.ID > 0 { + body.NeVersion = neState.NeVersion + neVersion.Version = neState.NeVersion + neLicense.SerialNum = neState.SerialNum + neLicense.ExpiryDate = neState.ExpiryDate neLicense.Status = "1" - } - if v, ok := body.ServerState["ueNumber"]; ok && v != nil { - neLicense.UeNumber = parse.Number(v) - } - if v, ok := body.ServerState["nbNumber"]; ok && v != nil { - neLicense.NbNumber = parse.Number(v) + neLicense.UeNumber = neState.UENumber + neLicense.NbNumber = neState.NbNumber } } @@ -475,62 +449,41 @@ func (s NeInfoController) Edit(c *gin.Context) { } } + loginUserName := reqctx.LoginUserToUserName(c) + neLicense := s.neLicenseService.FindByNeTypeAndNeID(neInfo.NeType, neInfo.NeId) + neVersion := s.neVersionService.FindByNeTypeAndNeID(neInfo.NeType, neInfo.NeId) + // 获取网元状态是否正常 - body.ServerState, err = neFetchlink.NeState(neInfo) + key := fmt.Sprintf("%s:%s:%s_status", constants.CACHE_NE_INFO, body.NeType, body.NeId) + state, err := neFetchlink.NeState(body) if err != nil { + redis.Del("", key) body.Status = 0 } else { + redis.Set("", key, body.RmUID, 0) // 网元状态设置为在线 body.Status = 1 - if parse.Boolean(body.ServerState["standby"]) { + if parse.Boolean(state["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 { - body.NeVersion = fmt.Sprint(v) - neVersion.Version = fmt.Sprint(v) - neVersion.UpdateBy = loginUserName - } - 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) + // 网元状态记录 + neState := s.neStateService.SaveState(state) + body.ServerState = s.neStateService.ParseState(body, neState) + if neState.ID > 0 { + body.NeVersion = neState.NeVersion + neVersion.Version = neState.NeVersion + s.neVersionService.Update(neVersion) + neLicense.SerialNum = neState.SerialNum + neLicense.ExpiryDate = neState.ExpiryDate neLicense.Status = "1" - neLicense.UpdateBy = loginUserName + neLicense.UeNumber = neState.UENumber + neLicense.NbNumber = neState.NbNumber + s.neLicenseService.Update(neLicense) } - if v, ok := body.ServerState["ueNumber"]; ok && v != nil { - neLicense.UeNumber = parse.Number(v) - } - if v, ok := body.ServerState["nbNumber"]; ok && v != nil { - neLicense.NbNumber = parse.Number(v) - } - } - - 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 diff --git a/src/modules/network_element/controller/ne_license.go b/src/modules/network_element/controller/ne_license.go index 8edfba42..90dc6c2e 100644 --- a/src/modules/network_element/controller/ne_license.go +++ b/src/modules/network_element/controller/ne_license.go @@ -6,11 +6,12 @@ import ( "github.com/gin-gonic/gin" + "be.ems/src/framework/constants" + "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/utils/parse" - neFetchlink "be.ems/src/modules/network_element/fetch_link" "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" ) @@ -19,6 +20,7 @@ import ( var NewNeLicense = &NeLicenseController{ neLicenseService: neService.NewNeLicense, neInfoService: neService.NewNeInfo, + neStateService: neService.NewNEState, } // 网元授权激活请求 @@ -27,6 +29,7 @@ var NewNeLicense = &NeLicenseController{ type NeLicenseController struct { neLicenseService *neService.NeLicense // 网元授权激活服务 neInfoService *neService.NeInfo // 网元信息服务 + neStateService *neService.NEState // 网元状态服务 } // 网元授权激活列表 @@ -260,15 +263,21 @@ func (s *NeLicenseController) State(c *gin.Context) { 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.SerialNum = fmt.Sprint(neState["sn"]) - neLicense.ExpiryDate = fmt.Sprint(neState["expire"]) - neLicense.UeNumber = parse.Number(neState["ueNumber"]) - neLicense.NbNumber = parse.Number(neState["nbNumber"]) - } else { + + // 没状态标记,视为离线 + key := fmt.Sprintf("%s:%s:%s_status", constants.CACHE_NE_INFO, neInfo.NeType, neInfo.NeId) + keyNum, err := redis.Has("", key) + if keyNum == 0 || err != nil { neLicense.Status = "0" + } else { + state := s.neStateService.Last(neInfo.NeType, neInfo.NeId) + neLicense.Status = "1" + neLicense.SerialNum = state.SerialNum + neLicense.ExpiryDate = state.ExpiryDate + neLicense.UeNumber = state.UENumber + neLicense.NbNumber = state.NbNumber } + // 更新授权码 if neLicense.ActivationRequestCode == "" || strings.HasPrefix(neLicense.ActivationRequestCode, "SN") || neLicense.Status == "0" { code, licensePath := s.neLicenseService.ReadLicenseInfo(neLicense) diff --git a/src/modules/network_data/controller/all_ne_state.go b/src/modules/network_element/controller/ne_state.go similarity index 85% rename from src/modules/network_data/controller/all_ne_state.go rename to src/modules/network_element/controller/ne_state.go index 7173ef7c..f06ab9fe 100644 --- a/src/modules/network_data/controller/all_ne_state.go +++ b/src/modules/network_element/controller/ne_state.go @@ -6,23 +6,22 @@ import ( "github.com/gin-gonic/gin" "be.ems/src/framework/resp" - "be.ems/src/modules/network_data/model" - neDataService "be.ems/src/modules/network_data/service" + "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" ) // 实例化控制层 NEStateController 结构体 var NewNEState = &NEStateController{ neInfoService: neService.NewNeInfo, - neStateService: neDataService.NewNEState, + neStateService: neService.NewNEState, } // 网元状态记录 // -// PATH /ne-state +// PATH /ne/state type NEStateController struct { - neInfoService *neService.NeInfo // 网元信息服务 - neStateService *neDataService.NEState // 网元状态服务 + neInfoService *neService.NeInfo // 网元信息服务 + neStateService *neService.NEState // 网元状态服务 } // 网元状态记录-内存/CPU/磁盘列表 @@ -44,7 +43,7 @@ type NEStateController struct { // @Security TokenAuth // @Summary NE Status Record - Memory/CPU/Disk List // @Description NE Status Record - Memory/CPU/Disk List -// @Router /ne-state/list [get] +// @Router /ne/state/list [get] func (s NEStateController) List(c *gin.Context) { var query model.NEStateQuery if err := c.ShouldBindQuery(&query); err != nil { diff --git a/src/modules/network_data/model/ne_state.go b/src/modules/network_element/model/ne_state.go similarity index 65% rename from src/modules/network_data/model/ne_state.go rename to src/modules/network_element/model/ne_state.go index b875f58f..fcacb010 100644 --- a/src/modules/network_data/model/ne_state.go +++ b/src/modules/network_element/model/ne_state.go @@ -3,18 +3,22 @@ package model // NEState 网元状态记录表 ne_state type NEState 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"` - Version string `json:"version" gorm:"column:version"` // 版本 - Capability int64 `json:"capability" gorm:"column:capability"` // 用户容量 + NeType string `json:"neType" gorm:"column:ne_type"` // 网元类型 + NeId string `json:"neId" gorm:"column:ne_id"` // 网元ID + NeVersion string `json:"neVersion" gorm:"column:ne_version"` // 网元版本 + Standby int64 `json:"standby" gorm:"column:standby"` // 主备状态 0-主 1-备 + NbNumber int64 `json:"nbNumber" gorm:"column:nb_number"` // 基站容量 + UENumber int64 `json:"ueNumber" gorm:"column:ue_number"` // 用户容量 SerialNum string `json:"serialNum" gorm:"column:serial_num"` // 序列号 ExpiryDate string `json:"expiryDate" gorm:"column:expiry_date"` // 许可证到期日期 + HostName string `json:"hostname" gorm:"column:hostname"` // 主机名 hostname + OS string `json:"os" gorm:"column:os"` // 操作系统 uname SysCpuUsage float64 `json:"sysCpuUsage" gorm:"column:sys_cpu_usage"` // cpu使用率-sys SysMemUsage float64 `json:"sysMemUsage" gorm:"column:sys_mem_usage"` // 内存使用率-sys SysDiskUsage float64 `json:"sysDiskUsage" gorm:"column:sys_disk_usage"` // 磁盘使用率-sys NfCpuUsage float64 `json:"nfCpuUsage" gorm:"column:nf_cpu_usage"` // cpu使用率-nf NfMemUsed int64 `json:"nfMemUsed" gorm:"column:nf_mem_used"` // 内存使用KB-nf - CreateTime int64 `json:"createTime" gorm:"column:create_time"` // 创建时间 + RefreshTime int64 `json:"refreshTime" gorm:"column:refresh_time"` // 刷新时间 } // TableName 表名称 diff --git a/src/modules/network_element/network_element.go b/src/modules/network_element/network_element.go index 95f7685c..ba724592 100644 --- a/src/modules/network_element/network_element.go +++ b/src/modules/network_element/network_element.go @@ -48,6 +48,15 @@ func Setup(router *gin.Engine) { ) } + // 网元状态记录信息 + neStateGroup := router.Group("/ne/state") + { + neStateGroup.GET("/list", + middleware.AuthorizeUser(nil), + controller.NewNEState.List, + ) + } + // 网元信息 neInfoGroup := router.Group("/ne/info") { diff --git a/src/modules/network_data/repository/ne_state.go b/src/modules/network_element/repository/ne_state.go similarity index 70% rename from src/modules/network_data/repository/ne_state.go rename to src/modules/network_element/repository/ne_state.go index 05f48a8f..b7226dd7 100644 --- a/src/modules/network_data/repository/ne_state.go +++ b/src/modules/network_element/repository/ne_state.go @@ -5,7 +5,7 @@ import ( "be.ems/src/framework/database/db" "be.ems/src/framework/logger" - "be.ems/src/modules/network_data/model" + "be.ems/src/modules/network_element/model" ) // 实例化数据层 NEState 结构体 @@ -25,18 +25,10 @@ func (r NEState) SelectByPage(query model.NEStateQuery) ([]model.NEState, int64) tx = tx.Where("ne_id = ?", query.NeID) } if query.BeginTime != "" { - startTime := query.BeginTime - if len(startTime) == 10 { - startTime = startTime + "000" - } - tx = tx.Where("create_time >= ?", startTime) + tx = tx.Where("refresh_time >= ?", query.BeginTime) } if query.EndTime != "" { - endTime := query.EndTime - if len(endTime) == 10 { - endTime = endTime + "999" - } - tx = tx.Where("create_time <= ?", endTime) + tx = tx.Where("refresh_time <= ?", query.EndTime) } // 查询结果 @@ -85,12 +77,30 @@ func (r NEState) SelectByIds(ids []string) []model.NEState { return rows } +// SelectByLast 查询最新状态 +func (r NEState) SelectByLast(neType, neId string) model.NEState { + item := model.NEState{} + if neType == "" || neId == "" { + return item + } + tx := db.DB("").Model(item) + // 构建查询条件 + tx = tx.Where("ne_type = ? and ne_id = ?", neType, neId) + tx = tx.Order("refresh_time desc") + // 查询数据 + if err := tx.Limit(1).Find(&item).Error; err != nil { + logger.Errorf("query find err => %v", err.Error()) + return item + } + return item +} + // DeleteByTime 删除信息 -func (r NEState) DeleteByTime(ltTime int64) int64 { +func (r NEState) DeleteByTime(neType, neId string, ltTime int64) int64 { if ltTime <= 0 { return 0 } - tx := db.DB("").Where("create_time < ?", ltTime) + tx := db.DB("").Where("ne_type = ? and ne_id = ? and refresh_time < ?", neType, neId, ltTime) if err := tx.Delete(&model.NEState{}).Error; err != nil { logger.Errorf("delete err => %v", err.Error()) return 0 @@ -100,7 +110,9 @@ func (r NEState) DeleteByTime(ltTime int64) int64 { // Insert 新增信息 func (r NEState) Insert(param model.NEState) int64 { - param.CreateTime = time.Now().UnixMilli() + if param.RefreshTime <= 0 { + param.RefreshTime = time.Now().UnixMilli() + } // 执行插入 if err := db.DB("").Create(¶m).Error; err != nil { logger.Errorf("insert err => %v", err.Error()) diff --git a/src/modules/network_element/repository/ne_version.go b/src/modules/network_element/repository/ne_version.go index 668d8cd2..73b49ed0 100644 --- a/src/modules/network_element/repository/ne_version.go +++ b/src/modules/network_element/repository/ne_version.go @@ -147,3 +147,23 @@ func (r NeVersion) DeleteByIds(ids []int64) int64 { } return tx.RowsAffected } + +// UpdateVersion 修改网元版本 +func (r NeVersion) UpdateVersion(id int64, neVersion string) int64 { + if id <= 0 { + return 0 + } + tx := db.DB("").Model(&model.NeVersion{}) + // 构建查询条件 + tx = tx.Where("id = ?", id) + tx.Updates(map[string]any{ + "version": neVersion, + "update_time": time.Now().UnixMilli(), + }) + // 执行更新 + if err := tx.Error; err != nil { + logger.Errorf("update err => %v", err.Error()) + return 0 + } + return tx.RowsAffected +} diff --git a/src/modules/network_element/service/ne_info.go b/src/modules/network_element/service/ne_info.go index e216cfcb..70a5312f 100644 --- a/src/modules/network_element/service/ne_info.go +++ b/src/modules/network_element/service/ne_info.go @@ -24,6 +24,7 @@ import ( var NewNeInfo = &NeInfo{ neInfoRepository: repository.NewNeInfo, neHostService: NewNeHost, + neStateService: NewNEState, Para5GData: map[string]string{}, } @@ -31,6 +32,7 @@ var NewNeInfo = &NeInfo{ type NeInfo struct { neInfoRepository *repository.NeInfo // 网元信息数据信息 neHostService *NeHost // 网元主机连接服务 + neStateService *NEState // 网元状态服务 Para5GData map[string]string } @@ -127,10 +129,22 @@ func (r NeInfo) FindByRmuid(rmUid string) model.NeInfo { } else { neInfos := r.Find(neInfo, false, false) for _, v := range neInfos { - key := fmt.Sprintf("%s:%s:%s", constants.CACHE_NE_INFO, strings.ToUpper(v.NeType), v.NeId) + neType := strings.ToUpper(v.NeType) + // 网元信息 + key := fmt.Sprintf("%s:%s:%s", constants.CACHE_NE_INFO, neType, v.NeId) redis.Del("", key) values, _ := json.Marshal(v) redis.Set("", key, string(values), 0) + // 网元在线状态 + stateKey := fmt.Sprintf("%s:%s:%s_status", constants.CACHE_NE_INFO, neType, v.NeId) + state, stateErr := neFetchlink.NeState(v) + if stateErr != nil { + redis.Del("", stateKey) + } else { + redis.Set("", stateKey, neInfo.RmUID, 0) + r.neStateService.SaveState(state) + } + if v.RmUID == rmUid { neInfo = v } @@ -177,11 +191,15 @@ func (r NeInfo) Find(ne model.NeInfo, bandStatus bool, bandHost bool) []model.Ne func (r NeInfo) bandNeStatus(arr *[]model.NeInfo) { for i := range *arr { v := (*arr)[i] - result, err := neFetchlink.NeState(v) - if err != nil { - (*arr)[i].ServerState = map[string]any{ - "online": false, - } + state := r.neStateService.Last(v.NeType, v.NeId) + result := r.neStateService.ParseState(v, state) + + // 没状态标记,视为离线 + key := fmt.Sprintf("%s:%s:%s_status", constants.CACHE_NE_INFO, v.NeType, v.NeId) + keyNum, err := redis.Has("", key) + if keyNum == 0 || err != nil { + result["online"] = false + (*arr)[i].ServerState = result // 网元状态设置为离线 if v.Status != 0 { v.Status = 0 @@ -190,17 +208,23 @@ func (r NeInfo) bandNeStatus(arr *[]model.NeInfo) { } continue } + result["online"] = true (*arr)[i].ServerState = result - // 网元状态设置为在线 - var status int64 = 1 + status := v.Status + if status == 0 || status == 2 { + // 下发网管配置信息给网元 + _, err := neFetchlink.NeConfigOMC(v) + if err != nil { + status = 2 + } else { + // 网元状态设置为在线 + status = 1 + } + } if parse.Boolean(result["standby"]) { status = 3 } - // 下发网管配置信息给网元 - if _, err = neFetchlink.NeConfigOMC(v); err != nil { - status = 2 - } (*arr)[i].Status = status if v.Status != status { r.neInfoRepository.UpdateState(v.ID, status) diff --git a/src/modules/network_element/service/ne_state.go b/src/modules/network_element/service/ne_state.go new file mode 100644 index 00000000..0f5ce235 --- /dev/null +++ b/src/modules/network_element/service/ne_state.go @@ -0,0 +1,137 @@ +package service + +import ( + "fmt" + "sort" + "strconv" + + "be.ems/src/modules/network_element/model" + "be.ems/src/modules/network_element/repository" + "github.com/tsmask/go-oam/framework/utils/parse" +) + +// 实例化数据层 NEState 结构体 +var NewNEState = &NEState{ + neStateRepository: repository.NewNEState, +} + +// NEState 网元状态记录表 服务层处理 +type NEState struct { + neStateRepository *repository.NEState // 网元状态记录信息 +} + +// FindByPage 根据条件分页查询 +func (r NEState) FindByPage(query model.NEStateQuery) ([]model.NEState, int64) { + return r.neStateRepository.SelectByPage(query) +} + +// Insert 插入数据 +func (r NEState) Insert(item model.NEState) int64 { + return r.neStateRepository.Insert(item) +} + +// DeleteByTime 删除数据 +func (r NEState) DeleteByTime(neType, neId string, ltTime int64) int64 { + return r.neStateRepository.DeleteByTime(neType, neId, ltTime) +} + +// Last 查询最新状态 +func (r NEState) Last(neType, neId string) model.NEState { + return r.neStateRepository.SelectByLast(neType, neId) +} + +// ParseState 解析状态数据 +func (r NEState) ParseState(neInfo model.NeInfo, state model.NEState) map[string]any { + if state.ID == 0 { + return map[string]any{} + } + return map[string]any{ + "neId": neInfo.NeId, + "neName": neInfo.NeName, + "neType": neInfo.NeType, + "neIP": neInfo.IP, + "standby": state.Standby, + "version": state.NeVersion, + "sn": state.SerialNum, + "expire": state.ExpiryDate, + "refreshTime": state.RefreshTime, + "ueNumber": state.UENumber, + "nbNumber": state.NbNumber, + "hostname": state.HostName, + "os": state.OS, + "sysCpuUsage": state.SysCpuUsage, + "sysMemUsage": state.SysMemUsage, + "sysDiskUsage": state.SysDiskUsage, + "nfCpuUsage": state.NfCpuUsage, + "nfMemUsed": state.NfMemUsed, + } +} + +// SaveState 网元直连返回的状态数据保存 +func (r NEState) SaveState(state map[string]any) model.NEState { + // 网元CPU使用率 + var nfCpuUsage float64 = 0 + // CPU使用率 + var sysCpuUsage float64 = 0 + if state["cpu"] != nil { + cpu := state["cpu"].(map[string]any) + v := parse.Number(cpu["sysCpuUsage"]) + sysCpuUsage = float64(v) / 100 + nfv := parse.Number(cpu["nfCpuUsage"]) + nfCpuUsage = float64(nfv) / 100 + } + + // 网元内存使用KB + var nfMemUsed int64 = 0 + // 内存使用率 + var sysMemUsage float64 = 0 + if state["mem"] != nil { + mem := state["mem"].(map[string]any) + v := parse.Number(mem["sysMemUsage"]) + sysMemUsage = float64(v) / 100 + nfMemUsed = parse.Number(mem["nfUsedMem"]) + } + + // 磁盘使用率 + var sysDiskUsage float64 = 0 + if state["disk"] != nil { + mem := state["disk"].(map[string]any) + disks := mem["partitionInfo"].([]any) + sort.Slice(disks, func(i, j int) bool { + iUsed := parse.Number(disks[i].(map[string]any)["used"]) + jUsed := parse.Number(disks[j].(map[string]any)["used"]) + return iUsed > jUsed + }) + disk := disks[0].(map[string]any) + total := parse.Number(disk["total"]) + used := parse.Number(disk["used"]) + sysDiskUsage = (float64(used) / float64(total)) * 100 + sysDiskUsage, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", sysDiskUsage), 64) + } + + // 插入网元状态记录 + neState := model.NEState{ + NeType: fmt.Sprint(state["neType"]), + NeId: fmt.Sprint(state["neId"]), + NeVersion: fmt.Sprint(state["version"]), + Standby: parse.Number(state["standby"]), + UENumber: parse.Number(state["ueNumber"]), + NbNumber: parse.Number(state["nbNumber"]), + SerialNum: fmt.Sprint(state["sn"]), + ExpiryDate: fmt.Sprint(state["expire"]), + HostName: fmt.Sprint(state["hostname"]), + OS: fmt.Sprint(state["os"]), + SysCpuUsage: sysCpuUsage, + SysMemUsage: sysMemUsage, + SysDiskUsage: sysDiskUsage, + NfCpuUsage: nfCpuUsage, + NfMemUsed: nfMemUsed, + RefreshTime: parse.Number(state["refreshTime"]), + } + + insertId := r.neStateRepository.Insert(neState) + if insertId > 0 { + neState.ID = insertId + } + return neState +} diff --git a/src/modules/network_element/service/ne_version.go b/src/modules/network_element/service/ne_version.go index f3d862a5..98f23570 100644 --- a/src/modules/network_element/service/ne_version.go +++ b/src/modules/network_element/service/ne_version.go @@ -9,7 +9,6 @@ import ( "be.ems/src/framework/ssh" "be.ems/src/framework/utils/file" - neFetchlink "be.ems/src/modules/network_element/fetch_link" "be.ems/src/modules/network_element/model" "be.ems/src/modules/network_element/repository" ) @@ -18,12 +17,14 @@ import ( var NewNeVersion = &NeVersion{ neVersionRepository: repository.NewNeVersion, neInfoService: NewNeInfo, + neStateService: NewNEState, } // NeVersion 网元版本信息 服务层处理 type NeVersion struct { neVersionRepository *repository.NeVersion // 网元版本信息表 neInfoService *NeInfo // 网元信息数据信息 + neStateService *NEState // 网元状态服务 } // FindByPage 分页查询列表数据 @@ -54,29 +55,15 @@ func (r NeVersion) Find(neVersion model.NeVersion, checkVersion bool) []model.Ne 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 == "" { + state := r.neStateService.Last(item.NeType, item.NeId) + if state.RefreshTime <= 0 { continue } - result, err := neFetchlink.NeState(neInfo) - if err != nil { + if state.NeVersion == item.Version { continue } - if v, ok := result["version"]; ok && v != nil { - ver := fmt.Sprint(v) - 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) + item.Version = state.NeVersion + r.neVersionRepository.UpdateVersion(item.ID, item.Version) (*arr)[i] = item } } diff --git a/src/modules/ws/processor/ne_state.go b/src/modules/ws/processor/ne_state.go index fc606b33..955a1561 100644 --- a/src/modules/ws/processor/ne_state.go +++ b/src/modules/ws/processor/ne_state.go @@ -4,9 +4,10 @@ import ( "encoding/json" "fmt" + "be.ems/src/framework/constants" + "be.ems/src/framework/database/redis" "be.ems/src/framework/logger" "be.ems/src/framework/resp" - neFetchlink "be.ems/src/modules/network_element/fetch_link" neService "be.ems/src/modules/network_element/service" ) @@ -33,26 +34,21 @@ func GetNeState(requestID string, data any) ([]byte, error) { return nil, fmt.Errorf("no matching network element information found") } - // 网元直连 - resData, err := neFetchlink.NeState(neInfo) - if err != nil { - resultByte, err := json.Marshal(resp.Ok(map[string]any{ - "requestId": requestID, - "data": map[string]any{ - "online": false, - "neId": neInfo.NeId, - "neName": neInfo.NeName, - "neType": neInfo.NeType, - "neIP": neInfo.IP, - }, - })) - return resultByte, err + state := neService.NewNEState.Last(neInfo.NeType, neInfo.NeId) + result := neService.NewNEState.ParseState(neInfo, state) + + // 没状态标记,视为离线 + key := fmt.Sprintf("%s:%s:%s_status", constants.CACHE_NE_INFO, neInfo.NeType, neInfo.NeId) + keyNum, err := redis.Has("", key) + if keyNum == 0 || err != nil { + result["online"] = false + } else { + result["online"] = true } - resData["online"] = true resultByte, err := json.Marshal(resp.Ok(map[string]any{ "requestId": requestID, - "data": resData, + "data": result, })) return resultByte, err }