package controller import ( "fmt" "strings" "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" "github.com/gin-gonic/gin" ) // 实例化控制层 NeInfoController 结构体 var NewNeInfo = &NeInfoController{ neInfoService: neService.NewNeInfo, neLicenseService: neService.NewNeLicense, neVersionService: neService.NewNeVersion, neStateService: neService.NewNEState, } // 网元信息请求 // // PATH /info type NeInfoController struct { neInfoService *neService.NeInfo // 网元信息服务 neLicenseService *neService.NeLicense // 网元授权激活信息服务 neVersionService *neService.NeVersion // 网元版本信息服务 neStateService *neService.NEState // 网元状态服务 } // 网元信息状态 // // GET /state // // @Tags network_element/info // @Accept json // @Produce json // @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC) // @Param neId query string true "NE ID" default(001) // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Network element information state // @Description Network element information state // @Router /ne/info/state [get] func (s NeInfoController) State(c *gin.Context) { language := reqctx.AcceptLanguage(c) var querys struct { NeType string `form:"neType" binding:"required"` NeId string `form:"neId" binding:"required"` } if err := c.ShouldBindQuery(&querys); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) return } neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeId) if neInfo.NeId != querys.NeId || neInfo.IP == "" { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } state := s.neStateService.Last(neInfo.NeType, neInfo.NeId) result := s.neStateService.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 } c.JSON(200, resp.OkData(result)) } // 网元neType和neID查询 // // GET /byTypeAndID // // @Tags network_element/info // @Accept json // @Produce json // @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC) // @Param neId query string true "NE ID" default(001) // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Network element neType and neID queries // @Description Network element neType and neID queries // @Router /ne/info/byTypeAndID [get] func (s NeInfoController) NeTypeAndID(c *gin.Context) { language := reqctx.AcceptLanguage(c) var querys struct { NeType string `form:"neType" binding:"required"` NeID string `form:"neId" binding:"required"` } if err := c.ShouldBindQuery(&querys); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) return } neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID) if neInfo.NeId != querys.NeID || neInfo.IP == "" { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } c.JSON(200, resp.OkData(neInfo)) } // 网元信息列表全部无分页 // // GET /listAll // // @Tags network_element/info // @Accept json // @Produce json // @Param neType query string true "NE Type" // @Param neId query string true "NE ID" default(001) // @Param bandStatus query boolean true "With status information" // @Param bandHost query boolean true "With host information" // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary The list of network element information is all unpaginated // @Description The list of network element information is all unpaginated // @Router /ne/info/listAll [get] func (s NeInfoController) ListAll(c *gin.Context) { language := reqctx.AcceptLanguage(c) var querys struct { NeType string `form:"neType"` NeId string `form:"neId"` BandStatus bool `form:"bandStatus"` BandHost bool `form:"bandHost"` } if err := c.ShouldBindQuery(&querys); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) return } // 查询实体参数 ne := model.NeInfo{} if querys.NeType != "" { ne.NeType = querys.NeType } if querys.NeId != "" { ne.NeId = querys.NeId } neList := s.neInfoService.Find(ne, querys.BandStatus, querys.BandHost) if len(neList) == 0 { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } c.JSON(200, resp.OkData(neList)) } // 网元端Para5G配置文件读取 // // GET /para5GFile func (s NeInfoController) Para5GFileRead(c *gin.Context) { data, err := s.neInfoService.NeConfPara5GRead() if err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return } c.JSON(200, resp.OkData(data)) } // 网元端Para5G配置文件写入 // // PUT /para5GFile func (s NeInfoController) Para5GFileWrite(c *gin.Context) { var body struct { Content map[string]any `json:"content" binding:"required"` // 内容 SyncNE []string `json:"syncNe"` // 同步到网元 } if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) return } err := s.neInfoService.NeConfPara5GWirte(body.Content, body.SyncNE) if err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return } c.JSON(200, resp.Ok(nil)) } // 网元端OAM配置文件读取 // // GET /oamFile func (s NeInfoController) OAMFileRead(c *gin.Context) { var querys struct { NeType string `form:"neType" binding:"required"` NeID string `form:"neId" binding:"required"` } if err := c.ShouldBindQuery(&querys); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) return } data, err := s.neInfoService.NeConfOAMReadSync(querys.NeType, querys.NeID) if err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return } c.JSON(200, resp.OkData(data)) } // 网元端OAM配置文件写入 // // PUT /oamFile func (s NeInfoController) OAMFileWrite(c *gin.Context) { language := reqctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` NeID string `json:"neId" binding:"required"` Content map[string]any `json:"content" binding:"required"` // 内容 Sync bool `json:"sync"` // 同步到网元 } if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) return } // 查询网元获取IP neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeID) if neInfo.NeId != body.NeID || neInfo.IP == "" { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } err := s.neInfoService.NeConfOAMWirteSync(neInfo, body.Content, body.Sync) if err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return } c.JSON(200, resp.Ok(nil)) } // 网元信息列表 // // GET /list // // @Tags network_element/info // @Accept json // @Produce json // @Param bandStatus query boolean false "The result carries the state of the network element" // @Param neId query string false "NE ID" // @Param neType query string false "Ne Type" // @Param pageNum query number true "pageNum" default(1) // @Param pageSize query number true "pageSize" default(10) // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Network element information list // @Description Network element information list // @Router /ne/info/list [get] func (s NeInfoController) List(c *gin.Context) { query := reqctx.QueryMap(c) bandStatus := false if v, ok := query["bandStatus"]; ok { bandStatus = parse.Boolean(v) } rows, total := s.neInfoService.FindByPage(query, bandStatus) c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total})) } // 网元信息 // // GET /:id // // @Tags network_element/info // @Accept json // @Produce json // @Param value path string true "Row ID" // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Network element information // @Description Network element information // @Router /ne/info/{value} [get] func (s NeInfoController) Info(c *gin.Context) { language := reqctx.AcceptLanguage(c) id := parse.Number(c.Param("id")) if id <= 0 { c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty")) return } neHost := s.neInfoService.FindById(id, true) if neHost.ID != id { // 没有可访问网元信息数据! c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neInfo.noData"))) return } c.JSON(200, resp.OkData(neHost)) } // 网元信息新增 // // POST / // // @Tags network_element/info // @Accept json // @Produce json // @Param data body object true "Request Param" // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Network element information addition // @Description Network element information addition // @Router /ne/info [post] func (s NeInfoController) Add(c *gin.Context) { language := reqctx.AcceptLanguage(c) var body model.NeInfo err := c.ShouldBindBodyWithJSON(&body) if err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) return } if body.ID != 0 { c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id not is empty")) return } // 检查属性值唯一 uniqueInfo := s.neInfoService.CheckUniqueNeTypeAndNeId(body.NeType, body.NeId, 0) if !uniqueInfo { // 网元信息操作【%s】失败,同类型下标识已存在 msg := i18n.TTemplate(language, "neInfo.errKeyExists", map[string]any{"key": body.NeId}) c.JSON(200, resp.ErrMsg(msg)) return } loginUserName := reqctx.LoginUserToUserName(c) // 新增Version信息 neVersion := model.NeVersion{ NeType: body.NeType, NeId: body.NeId, CreateBy: loginUserName, } // 新增License信息 neLicense := model.NeLicense{ NeType: body.NeType, NeId: body.NeId, CreateBy: loginUserName, } // 获取网元状态是否正常 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 _, err = neFetchlink.NeConfigOMC(body); err != nil { body.Status = 2 } // 网元状态记录 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" neLicense.UeNumber = neState.UENumber neLicense.NbNumber = neState.NbNumber } } s.neVersionService.Insert(neVersion) s.neLicenseService.Insert(neLicense) body.CreateBy = loginUserName insertId := s.neInfoService.Insert(body) if insertId > 0 { c.JSON(200, resp.OkData(insertId)) return } c.JSON(200, resp.Err(nil)) } // 网元信息修改 // // PUT / // // @Tags network_element/info // @Accept json // @Produce json // @Param data body object true "Request Param" // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Network element information modification // @Description Network element information modification // @Router /ne/info [put] func (s NeInfoController) Edit(c *gin.Context) { language := reqctx.AcceptLanguage(c) var body model.NeInfo err := c.ShouldBindBodyWithJSON(&body) if err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) return } if body.ID <= 0 { c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty")) return } // 检查属性值唯一 uniqueInfo := s.neInfoService.CheckUniqueNeTypeAndNeId(body.NeType, body.NeId, body.ID) if !uniqueInfo { // 网元信息操作【%s】失败,同类型下标识已存在 msg := i18n.TTemplate(language, "neInfo.errKeyExists", map[string]any{"key": body.NeId}) c.JSON(200, resp.ErrMsg(msg)) return } // 检查是否存在 neInfo := s.neInfoService.FindById(body.ID, false) if neInfo.ID != body.ID { // 没有可访问网元信息数据! c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neInfo.noData"))) return } // 赋予主机ID if neInfo.HostIDs != "" && len(body.Hosts) > 0 { hostIDs := strings.Split(neInfo.HostIDs, ",") for index, id := range hostIDs { body.Hosts[index].ID = parse.Number(id) } } loginUserName := reqctx.LoginUserToUserName(c) neLicense := s.neLicenseService.FindByNeTypeAndNeID(neInfo.NeType, neInfo.NeId) neVersion := s.neVersionService.FindByNeTypeAndNeID(neInfo.NeType, neInfo.NeId) // 获取网元状态是否正常 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 _, err = neFetchlink.NeConfigOMC(body); err != nil { body.Status = 2 } // 网元状态记录 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.UeNumber = neState.UENumber neLicense.NbNumber = neState.NbNumber s.neLicenseService.Update(neLicense) } } body.UpdateBy = loginUserName rows := s.neInfoService.Update(body) if rows > 0 { c.JSON(200, resp.Ok(nil)) return } c.JSON(200, resp.Err(nil)) } // 网元信息删除 // // DELETE /:id // // @Tags network_element/info // @Accept json // @Produce json // @Param value path string true "Row ID" // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Network element information deletion // @Description Network element information deletion // @Router /ne/info [delete] func (s NeInfoController) Remove(c *gin.Context) { language := reqctx.AcceptLanguage(c) id := c.Param("id") if id == "" { c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty")) return } // 处理字符转id数组后去重 uniqueIDs := parse.RemoveDuplicatesToArray(id, ",") // 转换成int64数组类型 ids := make([]int64, 0) for _, v := range uniqueIDs { ids = append(ids, parse.Number(v)) } rows, err := s.neInfoService.DeleteByIds(ids) if err != nil { c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows}) c.JSON(200, resp.OkMsg(msg)) }