feat: UDM-Voip/volte-ims功能接口

This commit is contained in:
TsMask
2025-05-09 18:34:40 +08:00
parent 2f27466408
commit f4741a1e07
8 changed files with 1837 additions and 0 deletions

View File

@@ -0,0 +1,561 @@
package controller
import (
"fmt"
"path/filepath"
"strings"
"time"
"be.ems/src/framework/constants"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/telnet"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/network_data/model"
neDataService "be.ems/src/modules/network_data/service"
neService "be.ems/src/modules/network_element/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 UDMVOIPController 结构体
var NewUDMVOIP = &UDMVOIPController{
udmVOIPService: neDataService.NewUDMVOIPUser,
neInfoService: neService.NewNeInfo,
}
// UDMVOIP用户
//
// PATH /udm/voip
type UDMVOIPController struct {
udmVOIPService *neDataService.UDMVOIPUser // UDMVOIP信息服务
neInfoService *neService.NeInfo // 网元信息服务
}
// UDMVOIP用户重载数据
//
// PUT /resetData/:neId
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VOIP User Data Refresh
// @Description UDM VOIP User Data List Refresh Synchronization Latest
// @Router /neData/udm/voip/resetData/{neId} [put]
func (s *UDMVOIPController) ResetData(c *gin.Context) {
neId := c.Param("neId")
if neId == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId is empty"))
return
}
data := s.udmVOIPService.ResetData(neId)
c.JSON(200, resp.OkData(data))
}
// UDMVOIP用户列表
//
// GET /list
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param neId query string true "NE ID" default(001)
// @Param username query string false "User Name"
// @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 UDM VOIP User List
// @Description UDM VOIP User List
// @Router /neData/udm/voip/list [get]
func (s *UDMVOIPController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
total, rows := s.udmVOIPService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// UDMVOIP用户信息
//
// GET /:neId/:username
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param value path string true "User Name"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VOIP User Information
// @Description UDM VOIP User Information
// @Router /neData/udm/voip/{neId}/{value} [get]
func (s *UDMVOIPController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
username := c.Param("username")
if neId == "" || username == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId or username is empty"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
cmd := fmt.Sprintf("dsp voip:username=%s", username)
data, err := telnet.ConvertToMap(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
if len(data) == 0 {
c.JSON(200, resp.ErrMsg("No VOIP Data"))
return
}
// 解析返回的数据
u := s.udmVOIPService.ParseInfo(neId, data)
if u.ID != "" {
s.udmVOIPService.Insert(neId, u.UserName)
c.JSON(200, resp.OkData(u))
return
}
c.JSON(200, resp.ErrMsg("No VOIP Data"))
}
// UDMVOIP用户新增
//
// POST /:neId
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VOIP User Added
// @Description UDM VOIP User Added
// @Router /neData/udm/voip/{neId} [post]
func (s *UDMVOIPController) Add(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
if neId == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId is empty"))
return
}
var body model.UDMVOIPUser
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(422001, errMsgs))
return
}
if body.UserName == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: username is empty"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
cmd := fmt.Sprintf("add voip:username=%s,password=%s", body.UserName, body.Password)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVOIPService.Insert(neId, body.UserName)
}
c.JSON(200, resp.OkData(data))
}
// UDMVOIP用户批量新增
//
// POST /:neId/:num
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param value path number true "Number of releases, value includes start username"
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VOIP User Batch Add
// @Description UDM VOIP User Batch Add
// @Router /neData/udm/voip/{neId}/{value} [post]
func (s *UDMVOIPController) Adds(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
num := c.Param("num")
if neId == "" || num == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId or num is empty"))
return
}
var body model.UDMVOIPUser
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(422001, errMsgs))
return
}
if body.UserName == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: username is empty"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
cmd := fmt.Sprintf("baa voip:sub_num=%s,start_username=%s,password=%s", num, body.UserName, body.Password)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVOIPService.LoadData(neId, body.UserName, num)
}
c.JSON(200, resp.OkData(data))
}
// UDMVOIP用户删除
//
// DELETE /:neId/:username
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param value path string true "User Name, multiple separated by a , sign"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VOIP User Deletion
// @Description UDM VOIP User Deletion
// @Router /neData/udm/voip/{neId}/{value} [delete]
func (s *UDMVOIPController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
username := c.Param("username")
if neId == "" || username == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId or username is empty"))
return
}
// 处理字符转id数组后去重
usernameArr := strings.Split(username, ",")
uniqueIDs := parse.RemoveDuplicates(usernameArr)
if len(uniqueIDs) <= 0 {
c.JSON(200, resp.Err(nil))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
resultData := map[string]string{}
for _, v := range uniqueIDs {
// 发送MML
cmd := fmt.Sprintf("del voip:username=%s", v)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
resultData[v] = err.Error()
continue
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVOIPService.Delete(v, neId)
}
resultData[v] = data
}
c.JSON(200, resp.OkData(resultData))
}
// UDMVOIP用户批量删除
//
// DELETE /:neId/:username/:num
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param username path string true "User Name"
// @Param num path number true "Number of releases, value includes start username"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VOIP User Batch Deletion
// @Description UDM VOIP User Batch Deletion
// @Router /neData/udm/voip/{neId}/{username}/{num} [delete]
func (s *UDMVOIPController) Removes(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
username := c.Param("username")
num := c.Param("num")
if neId == "" || username == "" || num == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId/username/num is empty"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
cmd := fmt.Sprintf("bde voip:start_username=%s,sub_num=%s", username, num)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVOIPService.LoadData(neId, username, num)
}
c.JSON(200, resp.OkData(data))
}
// UDMVOIP用户导出
//
// GET /export
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param neId query string true "NE ID" default(001)
// @Param type query string true "File Type" Enums(csv,txt) default(txt)
// @Param username query string false "User Name"
// @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 UDM VOIP User Export
// @Description UDM VOIP User Export
// @Router /neData/udm/voip/export [get]
func (s *UDMVOIPController) Export(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
neId := c.Query("neId")
fileType := c.Query("type")
if neId == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId is empty"))
return
}
if !(fileType == "csv" || fileType == "txt") {
c.JSON(200, resp.ErrMsg("file type error, only support csv,txt"))
return
}
query := reqctx.QueryMap(c)
total, rows := s.udmVOIPService.FindByPage(query)
if total == 0 {
// 导出数据记录为空
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
// rows := s.udmVOIPService.SelectList(model.UDMVOIPUser{NeId: neId})
if len(rows) <= 0 {
// 导出数据记录为空
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
// 文件名
fileName := fmt.Sprintf("udm_voip_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), fileType)
filePath := filepath.Join(file.ParseUploadFileDir(constants.UPLOAD_EXPORT), fileName)
if fileType == "csv" {
// 转换数据
data := [][]string{}
data = append(data, []string{"username", "password"})
for _, v := range rows {
data = append(data, []string{v.UserName, v.Password})
}
// 输出到文件
if err := file.WriterFileCSV(data, filePath); err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
}
if fileType == "txt" {
// 转换数据
data := [][]string{}
for _, v := range rows {
data = append(data, []string{v.UserName, v.Password})
}
// 输出到文件
if err := file.WriterFileTXT(data, ",", filePath); err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
}
c.FileAttachment(filePath, fileName)
}
// UDMVOIP用户导入
//
// POST /import
//
// @Tags network_data/udm/voip
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VOIP User Import
// @Description UDM VOIP User Import
// @Router /neData/udm/voip/import [post]
func (s *UDMVOIPController) Import(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeId string `json:"neId" binding:"required"` // 网元ID
UploadPath string `json:"uploadPath" binding:"required"` // 上传文件路径
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(422001, errMsgs))
return
}
// 判断文件名
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserAuthFileFormat")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
// 本地文件
localFilePath := file.ParseUploadFilePath(body.UploadPath)
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
// 复制到远程
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
c.JSON(200, resp.ErrMsg("error uploading file"))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 结果信息
var resultMsg string
var resultErr error
// 发送MML
cmd := fmt.Sprintf("import voip:path=%s", neFilePath)
resultMsg, resultErr = telnet.ConvertToStr(telnetClient, cmd)
if resultErr != nil {
c.JSON(200, resp.ErrMsg(resultErr.Error()))
return
}
// 命令ok时
if strings.Contains(resultMsg, "ok") {
if strings.HasSuffix(body.UploadPath, ".csv") {
data := file.ReadFileCSV(localFilePath)
go s.udmVOIPService.InsertData(neInfo.NeId, "csv", data)
}
if strings.HasSuffix(body.UploadPath, ".txt") {
data := file.ReadFileTXT(",", localFilePath)
go s.udmVOIPService.InsertData(neInfo.NeId, "txt", data)
}
}
c.JSON(200, resp.OkMsg(resultMsg))
}

View File

@@ -0,0 +1,590 @@
package controller
import (
"fmt"
"path/filepath"
"strings"
"time"
"be.ems/src/framework/constants"
"be.ems/src/framework/i18n"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/telnet"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/network_data/model"
neDataService "be.ems/src/modules/network_data/service"
neService "be.ems/src/modules/network_element/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 UDMVolteIMSController 结构体
var NewUDMVolteIMS = &UDMVolteIMSController{
udmVolteIMSService: neDataService.NewUDMVolteIMSUser,
neInfoService: neService.NewNeInfo,
}
// UDMVolteIMS用户
//
// PATH /udm/volte-ims
type UDMVolteIMSController struct {
udmVolteIMSService *neDataService.UDMVolteIMSUser // UDMVolteIMS信息服务
neInfoService *neService.NeInfo // 网元信息服务
}
// UDMVolteIMS用户重载数据
//
// PUT /resetData/:neId
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VolteIMS User Data Refresh
// @Description UDM Authenticated User Data List Refresh Synchronization Latest
// @Router /neData/udm/volte-ims/resetData/{neId} [put]
func (s *UDMVolteIMSController) ResetData(c *gin.Context) {
neId := c.Param("neId")
if neId == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId is empty"))
return
}
data := s.udmVolteIMSService.ResetData(neId)
c.JSON(200, resp.OkData(data))
}
// UDMVolteIMS用户列表
//
// GET /list
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param neId query string true "NE ID" default(001)
// @Param imsi query string false "IMSI"
// @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 UDM VolteIMS User List
// @Description UDM VolteIMS User List
// @Router /neData/udm/volte-ims/list [get]
func (s *UDMVolteIMSController) List(c *gin.Context) {
query := reqctx.QueryMap(c)
total, rows := s.udmVolteIMSService.FindByPage(query)
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
}
// UDMVolteIMS用户信息
//
// GET /:neId/:imsi
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param value path string true "IMSI"
// @Param msisdn query string true "MSISDN"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VolteIMS User Information
// @Description UDM VolteIMS User Information
// @Router /neData/udm/volte-ims/{neId}/{value} [get]
func (s *UDMVolteIMSController) Info(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
imsi := c.Param("imsi")
msisdn := c.Query("msisdn")
if neId == "" || imsi == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId or imsi is empty"))
return
}
if msisdn == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: msisdn is required"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
cmd := fmt.Sprintf("dsp imsuser:imsi=%s,msisdn=%s", imsi, msisdn)
data, err := telnet.ConvertToMap(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
if len(data) == 0 {
c.JSON(200, resp.ErrMsg("No Volte IMS Data"))
return
}
// 解析返回的数据
u := s.udmVolteIMSService.ParseInfo(neId, data)
if u.ID != "" {
s.udmVolteIMSService.InsertByIMSI(imsi, neId)
c.JSON(200, resp.OkData(u))
return
}
c.JSON(200, resp.ErrMsg("No Volte IMS Data"))
}
// UDMVolteIMS用户新增
//
// POST /:neId
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VolteIMS User Added
// @Description UDM VolteIMS User Added If VoIP tag=0, then MSISDN and IMSI need to be the same.
// @Router /neData/udm/volte-ims/{neId} [post]
func (s *UDMVolteIMSController) Add(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
if neId == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId is empty"))
return
}
var body model.UDMVolteIMSUser
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(422001, errMsgs))
return
}
if body.IMSI == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: imsi is empty"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 检查同IMSI下msisdn是否存在
hasMsisdns := s.udmVolteIMSService.Find(model.UDMVolteIMSUser{IMSI: body.IMSI, MSISDN: body.MSISDN, NeId: neId})
if len(hasMsisdns) > 0 {
c.JSON(200, resp.ErrMsg("IMSI and MSISDN already exist"))
return
}
// 发送MML
cmd := fmt.Sprintf("add imsuser:imsi=%s,msisdn=%s,volte=%s,vni=%s", body.IMSI, body.MSISDN, body.Tag, body.VNI)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVolteIMSService.InsertByIMSI(body.IMSI, neId)
}
c.JSON(200, resp.OkData(data))
}
// UDMVolteIMS用户批量新增
//
// POST /:neId/:num
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param value path number true "Number of releases, value includes start imsi"
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VolteIMS User Batch Add
// @Description UDM VolteIMS User Batch Add
// @Router /neData/udm/volte-ims/{neId}/{value} [post]
func (s *UDMVolteIMSController) Adds(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
num := c.Param("num")
if neId == "" || num == "" {
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
var body model.UDMVolteIMSUser
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(422001, errMsgs))
return
}
if body.IMSI == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: imsi is empty"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
cmd := fmt.Sprintf("baa imsuser:sub_num=%s,start_imsi=%s,start_msisdn=%s,volte=%s,vni=%s", num, body.IMSI, body.MSISDN, body.Tag, body.VNI)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVolteIMSService.LoadData(neId, body.IMSI, num)
}
c.JSON(200, resp.OkData(data))
}
// UDMVolteIMS用户删除
//
// DELETE /:neId/:imsi
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param value path string true "IMSI, multiple separated by a , sign"
// @Param msisdn query string false "MSISDN"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM Authenticated User Deletion
// @Description UDM Authenticated User Deletion
// @Router /neData/udm/volte-ims/{neId}/{value} [delete]
func (s *UDMVolteIMSController) Remove(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
imsi := c.Param("imsi")
msisdn := c.Query("msisdn")
if neId == "" || imsi == "" {
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
imsiArr := strings.Split(imsi, ",")
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 精确msisdn删除
if msisdn != "" {
// 发送MML
cmd := fmt.Sprintf("del imsuser:imsi=%s,msisdn=%s", imsiArr[0], msisdn)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVolteIMSService.Delete(imsi, neId)
}
c.JSON(200, resp.OkData(data))
return
} else {
// 处理字符转id数组后去重
uniqueIDs := parse.RemoveDuplicates(imsiArr)
if len(uniqueIDs) <= 0 {
c.JSON(200, resp.Err(nil))
return
}
resultData := map[string]string{}
for _, imsi := range uniqueIDs {
// 发送MML
cmd := fmt.Sprintf("del imsuser:imsi=%s", imsi)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
resultData[imsi] = err.Error()
continue
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVolteIMSService.Delete(imsi, neId)
}
resultData[imsi] = data
}
c.JSON(200, resp.OkData(resultData))
return
}
}
// UDMVolteIMS用户批量删除
//
// DELETE /:neId/:imsi/:num
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param neId path string true "NE ID" default(001)
// @Param imsi path string true "IMSI"
// @Param num path number true "Number of releases, value includes start imsi"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM VolteIMS User Batch Deletion
// @Description UDM VolteIMS User Batch Deletion
// @Router /neData/udm/volte-ims/{neId}/{imsi}/{num} [delete]
func (s *UDMVolteIMSController) Removes(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
neId := c.Param("neId")
imsi := c.Param("imsi")
num := c.Param("num")
if neId == "" || imsi == "" || num == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId/imsi/num is empty"))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
if neInfo.NeId != neId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 发送MML
cmd := fmt.Sprintf("bde imsuser:start_imsi=%s,sub_num=%s", imsi, num)
data, err := telnet.ConvertToStr(telnetClient, cmd)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 命令ok时
if strings.Contains(data, "ok") {
s.udmVolteIMSService.LoadData(neId, imsi, num)
}
c.JSON(200, resp.OkData(data))
}
// UDMVolteIMS用户导出
//
// GET /export
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param neId query string true "NE ID" default(001)
// @Param type query string true "File Type" Enums(csv,txt) default(txt)
// @Param imsi query string false "IMSI"
// @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 UDM Authenticated User Export
// @Description UDM Authenticated User Export
// @Router /neData/udm/volte-ims/export [get]
func (s *UDMVolteIMSController) Export(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
// 查询结果,根据查询条件结果,单页最大值限制
neId := c.Query("neId")
fileType := c.Query("type")
if neId == "" {
c.JSON(422, resp.CodeMsg(422002, "bind err: neId is empty"))
return
}
if !(fileType == "csv" || fileType == "txt") {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
return
}
query := reqctx.QueryMap(c)
total, rows := s.udmVolteIMSService.FindByPage(query)
if total == 0 {
// 导出数据记录为空
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
if len(rows) <= 0 {
// 导出数据记录为空
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
return
}
// 文件名
fileName := fmt.Sprintf("udm_volte_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), fileType)
filePath := filepath.Join(file.ParseUploadFileDir(constants.UPLOAD_EXPORT), fileName)
if fileType == "csv" {
// 转换数据
data := [][]string{}
data = append(data, []string{"IMSI", "MSISDN", "TAG", "VNI"})
for _, v := range rows {
data = append(data, []string{v.IMSI, v.MSISDN, v.Tag, v.VNI})
}
// 输出到文件
if err := file.WriterFileCSV(data, filePath); err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
}
if fileType == "txt" {
// 转换数据
data := [][]string{}
for _, v := range rows {
data = append(data, []string{v.IMSI, v.MSISDN, v.Tag, v.VNI})
}
// 输出到文件
if err := file.WriterFileTXT(data, ",", filePath); err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
}
c.FileAttachment(filePath, fileName)
}
// UDMVolteIMS用户导入
//
// POST /import
//
// @Tags network_data/udm/volte-ims
// @Accept json
// @Produce json
// @Param data body object true "Request Param"
// @Success 200 {object} object "Response Results"
// @Security TokenAuth
// @Summary UDM Authenticated User Import
// @Description UDM Authenticated User Import
// @Router /neData/udm/volte-ims/import [post]
func (s *UDMVolteIMSController) Import(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body struct {
NeId string `json:"neId" binding:"required"` // 网元ID
UploadPath string `json:"uploadPath" binding:"required"` // 上传文件路径
}
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(422001, errMsgs))
return
}
// 判断文件名
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserAuthFileFormat")))
return
}
// 查询网元获取IP
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
if neInfo.NeId != body.NeId || neInfo.IP == "" {
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元主机的SSH客户端
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sftpClient.Close()
// 本地文件
localFilePath := file.ParseUploadFilePath(body.UploadPath)
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
// 复制到远程
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
c.JSON(200, resp.ErrMsg("error uploading file"))
return
}
// 网元主机的Telnet客户端
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer telnetClient.Close()
// 结果信息
var resultMsg string
var resultErr error
// 发送MML
cmd := fmt.Sprintf("import imsuser:path=%s", neFilePath)
resultMsg, resultErr = telnet.ConvertToStr(telnetClient, cmd)
if resultErr != nil {
c.JSON(200, resp.ErrMsg(resultErr.Error()))
return
}
// 命令ok时
if strings.Contains(resultMsg, "ok") {
if strings.HasSuffix(body.UploadPath, ".csv") {
data := file.ReadFileCSV(localFilePath)
go s.udmVolteIMSService.InsertData(neInfo.NeId, "csv", data)
}
if strings.HasSuffix(body.UploadPath, ".txt") {
data := file.ReadFileTXT(",", localFilePath)
go s.udmVolteIMSService.InsertData(neInfo.NeId, "txt", data)
}
}
c.JSON(200, resp.OkMsg(resultMsg))
}

View File

@@ -0,0 +1,15 @@
package model
// UDMVOIPUser UDMVOIP用户 udm_voip
type UDMVOIPUser struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识
UserName string `json:"username" gorm:"column:user_name"` // 用户名
Password string `json:"password" gorm:"column:password"` // 密码
}
// TableName 表名称
func (*UDMVOIPUser) TableName() string {
return "udm_voip"
}

View File

@@ -0,0 +1,17 @@
package model
// UDMVolteIMSUser UDMVolteIMS用户 u_ims_user
type UDMVolteIMSUser struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识
Tag string `json:"tag" gorm:"column:tag"` // 0=VoIP, 1=VoLTE
VNI string `json:"vni" gorm:"column:vni"` // VNI
}
// TableName 表名称
func (*UDMVolteIMSUser) TableName() string {
return "u_ims_user"
}

View File

@@ -0,0 +1,138 @@
package repository
import (
"fmt"
"strings"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/network_data/model"
)
// 实例化数据层 UDMVOIPUser 结构体
var NewUDMVOIPUser = &UDMVOIPUser{}
// UDMVOIPUser UDMVOIP用户信息表 数据层处理
type UDMVOIPUser struct{}
// ClearAndInsert 清空ne_id后新增实体
func (r UDMVOIPUser) ClearAndInsert(neId string, uArr []model.UDMVOIPUser) int64 {
// 不指定neID时用 TRUNCATE 清空表快
// _, err := datasource.ExecDB("", "TRUNCATE TABLE udm_voip", nil)
result := db.DB("").Where("ne_id = ?", neId).Unscoped().Delete(&model.UDMVOIPUser{})
if result.Error != nil {
logger.Errorf("Delete err => %v", result.Error)
}
return r.Inserts(uArr)
}
// SelectPage 根据条件分页查询
func (r UDMVOIPUser) SelectPage(query map[string]string) (int64, []model.UDMVOIPUser) {
tx := db.DB("").Model(&model.UDMVOIPUser{})
// 查询条件拼接
if v, ok := query["username"]; ok && v != "" {
tx = tx.Where("user_name like ?", fmt.Sprintf("%%%s%%", v))
}
if v, ok := query["neId"]; ok && v != "" {
tx = tx.Where("ne_id = ?", v)
}
if v, ok := query["usernames"]; ok && v != "" {
arr := strings.Split(v, ",")
tx = tx.Where("user_name in ?", arr)
// 勾选时pageSize为勾选的数量
query["pageSize"] = fmt.Sprint(len(arr))
}
var total int64 = 0
rows := []model.UDMVOIPUser{}
// 查询数量 长度为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return total, rows
}
// 分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Offset(int(pageNum * pageSize)).Limit(int(pageSize))
// 排序
if v, ok := query["sortField"]; ok && v != "" {
sortSql := v
if o, ok := query["sortOrder"]; ok && o != "" {
if o == "desc" {
sortSql += " desc "
} else {
sortSql += " asc "
}
}
tx = tx.Order(sortSql)
} else {
tx = tx.Order("username asc")
}
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query err => %v", err)
}
return total, rows
}
// SelectList 根据实体查询
func (r UDMVOIPUser) SelectList(u model.UDMVOIPUser) []model.UDMVOIPUser {
tx := db.DB("").Model(&model.UDMVOIPUser{})
// 查询条件拼接
if u.UserName != "" {
tx = tx.Where("username = ?", u.UserName)
}
if u.NeId != "" {
tx = tx.Where("ne_id = ?", u.NeId)
}
// 查询数据
arr := []model.UDMVOIPUser{}
if err := tx.Order("username asc").Find(&arr).Error; err != nil {
logger.Errorf("query err => %v", err)
}
return arr
}
// SelectByUserNameAndNeID 通过username和ne_id查询
func (r UDMVOIPUser) SelectByUserNameAndNeID(username, neId string) model.UDMVOIPUser {
tx := db.DB("").Model(&model.UDMVOIPUser{})
item := model.UDMVOIPUser{}
// 查询条件拼接
tx = tx.Where("username = ? and ne_id = ?", username, neId)
// 查询数据
if err := tx.Order("username asc").Limit(1).Find(&item).Error; err != nil {
logger.Errorf("query err => %v", err)
}
return item
}
// Insert 批量添加
func (r UDMVOIPUser) Inserts(uArr []model.UDMVOIPUser) int64 {
tx := db.DB("").CreateInBatches(uArr, 500)
if err := tx.Error; err != nil {
logger.Errorf("CreateInBatches err => %v", err)
}
return tx.RowsAffected
}
// Delete 删除实体
func (r UDMVOIPUser) Delete(username, neId string) int64 {
tx := db.DB("").Where("username = ? and ne_id = ?", username, neId).Delete(&model.UDMVOIPUser{})
if err := tx.Error; err != nil {
logger.Errorf("Delete err => %v", err)
}
return tx.RowsAffected
}
// DeletePrefixByUserName 删除前缀匹配的实体
func (r UDMVOIPUser) DeletePrefixByUserName(username, neId string) int64 {
tx := db.DB("").Where("username like ? and ne_id = ?", fmt.Sprintf("%s%%", username), neId).Delete(&model.UDMVOIPUser{})
if err := tx.Error; err != nil {
logger.Errorf("DeletePrefixByUserName err => %v", err)
}
return tx.RowsAffected
}

View File

@@ -0,0 +1,150 @@
package repository
import (
"fmt"
"strings"
"be.ems/src/framework/database/db"
"be.ems/src/framework/logger"
"be.ems/src/modules/network_data/model"
)
// 实例化数据层 UDMVolteIMSUser 结构体
var NewUDMVolteIMSUser = &UDMVolteIMSUser{}
// UDMVolteIMSUser UDMVOIP用户信息表 数据层处理
type UDMVolteIMSUser struct{}
// ClearAndInsert 清空ne_id后新增实体
func (r UDMVolteIMSUser) ClearAndInsert(neId string, uArr []model.UDMVolteIMSUser) int64 {
// 不指定neID时用 TRUNCATE 清空表快
// _, err := datasource.ExecDB("", "TRUNCATE TABLE udm_volte_ims", nil)
result := db.DB("").Where("ne_id = ?", neId).Unscoped().Delete(&model.UDMVolteIMSUser{})
if result.Error != nil {
logger.Errorf("Delete err => %v", result.Error)
}
return r.Inserts(uArr)
}
// SelectPage 根据条件分页查询
func (r UDMVolteIMSUser) SelectPage(query map[string]string) (int64, []model.UDMVolteIMSUser) {
tx := db.DB("").Model(&model.UDMVolteIMSUser{})
// 查询条件拼接
if v, ok := query["imsi"]; ok && v != "" {
tx = tx.Where("imsi like ?", fmt.Sprintf("%%%s%%", v))
}
if v, ok := query["msisdn"]; ok && v != "" {
tx = tx.Where("msisdn like ?", fmt.Sprintf("%%%s%%", v))
}
if v, ok := query["neId"]; ok && v != "" {
tx = tx.Where("ne_id = ?", v)
}
if v, ok := query["tag"]; ok && v != "" {
tx = tx.Where("tag = ?", v)
}
if v, ok := query["vni"]; ok && v != "" {
tx = tx.Where("vni like ?", fmt.Sprintf("%%%s%%", v))
}
if v, ok := query["imsis"]; ok && v != "" {
arr := strings.Split(v, ",")
tx = tx.Where("imsi in ?", arr)
// 勾选时pageSize为勾选的数量
query["pageSize"] = fmt.Sprint(len(arr))
}
var total int64 = 0
rows := []model.UDMVolteIMSUser{}
// 查询数量 长度为0直接返回
if err := tx.Count(&total).Error; err != nil || total <= 0 {
return total, rows
}
// 分页
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
tx = tx.Offset(int(pageNum * pageSize)).Limit(int(pageSize))
// 排序
if v, ok := query["sortField"]; ok && v != "" {
sortSql := v
if o, ok := query["sortOrder"]; ok && o != "" {
if o == "desc" {
sortSql += " desc "
} else {
sortSql += " asc "
}
}
tx = tx.Order(sortSql)
} else {
tx = tx.Order("imsi asc")
}
// 查询数据
if err := tx.Find(&rows).Error; err != nil {
logger.Errorf("query err => %v", err)
}
return total, rows
}
// SelectList 根据实体查询
func (r UDMVolteIMSUser) SelectList(u model.UDMVolteIMSUser) []model.UDMVolteIMSUser {
tx := db.DB("").Model(&model.UDMVolteIMSUser{})
// 查询条件拼接
if u.IMSI != "" {
tx = tx.Where("imsi = ?", u.IMSI)
}
if u.NeId != "" {
tx = tx.Where("ne_id = ?", u.NeId)
}
if u.Tag != "" {
tx = tx.Where("tag = ?", u.Tag)
}
// 查询数据
arr := []model.UDMVolteIMSUser{}
if err := tx.Order("imsi asc").Find(&arr).Error; err != nil {
logger.Errorf("query err => %v", err)
}
return arr
}
// SelectByIMSIAndMSISDNAndNeID 通过imsi,msisdn,ne_id查询
func (r UDMVolteIMSUser) SelectByIMSIAndMSISDNAndNeID(imsi, msisdn, neId string) model.UDMVolteIMSUser {
tx := db.DB("").Model(&model.UDMVolteIMSUser{})
item := model.UDMVolteIMSUser{}
// 查询条件拼接
tx = tx.Where("imsi = ? and msisdn = ? and ne_id = ?", imsi, msisdn, neId)
// 查询数据
if err := tx.Order("imsi asc").Limit(1).Find(&item).Error; err != nil {
logger.Errorf("query err => %v", err)
}
return item
}
// Insert 批量添加
func (r UDMVolteIMSUser) Inserts(uArr []model.UDMVolteIMSUser) int64 {
tx := db.DB("").CreateInBatches(uArr, 500)
if err := tx.Error; err != nil {
logger.Errorf("CreateInBatches err => %v", err)
}
return tx.RowsAffected
}
// Delete 删除实体
func (r UDMVolteIMSUser) Delete(imsi, neId string) int64 {
tx := db.DB("").Where("imsi = ? and ne_id = ?", imsi, neId).Delete(&model.UDMVolteIMSUser{})
if err := tx.Error; err != nil {
logger.Errorf("Delete err => %v", err)
}
return tx.RowsAffected
}
// DeletePrefixByIMSI 删除前缀匹配的实体
func (r UDMVolteIMSUser) DeletePrefixByIMSI(imsi, neId string) int64 {
tx := db.DB("").Where("imsi like ? and ne_id = ?", fmt.Sprintf("%s%%", imsi), neId).Delete(&model.UDMVolteIMSUser{})
if err := tx.Error; err != nil {
logger.Errorf("DeletePrefixByIMSI err => %v", err)
}
return tx.RowsAffected
}

View File

@@ -0,0 +1,172 @@
package service
import (
"fmt"
"strconv"
"strings"
"be.ems/src/framework/database/redis"
"be.ems/src/modules/network_data/model"
"be.ems/src/modules/network_data/repository"
neService "be.ems/src/modules/network_element/service"
)
// 实例化服务层 UDMVOIPUser 结构体
var NewUDMVOIPUser = &UDMVOIPUser{
udmVOIPRepository: repository.NewUDMVOIPUser,
}
// UDMVOIP信息 服务层处理
type UDMVOIPUser struct {
// UDMVOIP信息数据信息
udmVOIPRepository *repository.UDMVOIPUser
}
// dataByRedis UDMVOIP用户 db:0 中 voip:*
func (r UDMVOIPUser) dataByRedis(username, neId string) []model.UDMVOIPUser {
arr := []model.UDMVOIPUser{}
key := fmt.Sprintf("voip:%s", username)
source := fmt.Sprintf("UDM_%s", neId)
// 网元主机的Redis客户端
redisClient, err := neService.NewNeInfo.NeRunRedisClient("UDM", neId)
if err != nil {
return arr
}
defer func() {
redisClient.Close()
redis.ConnectPush(source, nil)
}()
redis.ConnectPush(source, redisClient.Client)
voipArr, err := redis.GetKeys(source, key)
if err != nil {
return arr
}
mkv, err := redis.GetHashBatch(source, voipArr)
if err != nil {
return arr
}
for k, m := range mkv {
// 跳过-号数据 voip:360000100000130
username, hasPrefix := strings.CutPrefix(k, "voip:")
if strings.Contains(username, "-") || !hasPrefix {
continue
}
a := model.UDMVOIPUser{
NeId: neId,
UserName: username,
Password: m["password"],
}
arr = append(arr, a)
}
return arr
}
// ResetData 重置VOIP用户数据清空数据库重新同步Redis数据
func (r UDMVOIPUser) ResetData(neId string) int64 {
arr := r.dataByRedis("*", neId)
// 数据清空后添加
go r.udmVOIPRepository.ClearAndInsert(neId, arr)
return int64(len(arr))
}
// ParseInfo 解析单个用户userName信息 data从命令MML得到的结果
func (r UDMVOIPUser) ParseInfo(neId string, data map[string]string) model.UDMVOIPUser {
u := model.UDMVOIPUser{
NeId: neId,
UserName: data["username"],
Password: data["password"],
}
// 赋予ID
item := r.udmVOIPRepository.SelectByUserNameAndNeID(u.UserName, neId)
if item.ID != "" {
u.ID = item.ID
}
return u
}
// FindByPage 分页查询数据库
func (r UDMVOIPUser) FindByPage(query map[string]string) (int64, []model.UDMVOIPUser) {
return r.udmVOIPRepository.SelectPage(query)
}
// Find 查询数据库
func (r UDMVOIPUser) Find(u model.UDMVOIPUser) []model.UDMVOIPUser {
return r.udmVOIPRepository.SelectList(u)
}
// Insert 从数据中读取后删除username再存入数据库
func (r UDMVOIPUser) Insert(neId string, username string) int64 {
uArr := r.dataByRedis(username, neId)
if len(uArr) > 0 {
r.udmVOIPRepository.Delete(username, neId)
return r.udmVOIPRepository.Inserts(uArr)
}
return 0
}
// InsertData 导入文件数据 dataType目前两种txt/csv
func (r UDMVOIPUser) InsertData(neId, dataType string, data any) int64 {
// imsi截取前缀,重新获取部分数据
prefixes := make(map[string]struct{})
if dataType == "csv" {
for _, v := range data.([]map[string]string) {
username := v["username"]
if len(username) < 4 {
continue
}
prefix := username[:len(username)-3]
prefixes[prefix] = struct{}{}
}
}
if dataType == "txt" {
for _, v := range data.([][]string) {
username := v[0]
if len(username) < 4 {
continue
}
prefix := username[:len(username)-3]
prefixes[prefix] = struct{}{}
}
}
// 根据前缀重新加载插入
var num int64 = 0
for prefix := range prefixes {
// 直接删除前缀的记录
r.udmVOIPRepository.DeletePrefixByUserName(prefix, neId)
// keys voip:4600001000004*
arr := r.dataByRedis(prefix+"*", neId)
if len(arr) > 0 {
num += r.udmVOIPRepository.Inserts(arr)
}
}
return num
}
// Delete 删除单个不重新加载
func (r UDMVOIPUser) Delete(username, neId string) int64 {
return r.udmVOIPRepository.Delete(username, neId)
}
// LoadData 重新加载从username开始num的数据
func (r UDMVOIPUser) LoadData(neId, username, num string) {
startUserName, _ := strconv.ParseInt(username, 10, 64)
subNum, _ := strconv.ParseInt(num, 10, 64)
var i int64
for i = 0; i < subNum; i++ {
keyUserName := fmt.Sprintf("%d", startUserName+i)
// 删除原数据
r.udmVOIPRepository.Delete(keyUserName, neId)
// 加载数据
arr := r.dataByRedis(keyUserName, neId)
if len(arr) < 1 {
continue
}
r.udmVOIPRepository.Inserts(arr)
}
}

View File

@@ -0,0 +1,194 @@
package service
import (
"fmt"
"strconv"
"strings"
"be.ems/src/framework/database/redis"
"be.ems/src/modules/network_data/model"
"be.ems/src/modules/network_data/repository"
neService "be.ems/src/modules/network_element/service"
)
// 实例化服务层 UDMVolteIMSUser 结构体
var NewUDMVolteIMSUser = &UDMVolteIMSUser{
udmVolteIMSRepository: repository.NewUDMVolteIMSUser,
}
// UDMVolteIMS信息 服务层处理
type UDMVolteIMSUser struct {
// UDMVolteIMS信息数据信息
udmVolteIMSRepository *repository.UDMVolteIMSUser
}
// dataByRedis UDMVolteIMS用户 db:0 中 volte:*
func (r UDMVolteIMSUser) dataByRedis(imsi, neId string) []model.UDMVolteIMSUser {
arr := []model.UDMVolteIMSUser{}
key := fmt.Sprintf("volte:%s", imsi)
source := fmt.Sprintf("UDM_%s", neId)
// 网元主机的Redis客户端
redisClient, err := neService.NewNeInfo.NeRunRedisClient("UDM", neId)
if err != nil {
return arr
}
defer func() {
redisClient.Close()
redis.ConnectPush(source, nil)
}()
redis.ConnectPush(source, redisClient.Client)
volteArr, err := redis.GetKeys(source, key)
if err != nil {
return arr
}
mkv, err := redis.GetHashBatch(source, volteArr)
if err != nil {
return arr
}
for k, m := range mkv {
// volte:360000100000130:8612300000130
keys := strings.Split(k, ":")
if len(keys) != 3 {
continue
}
// "110011200004217@ims.mnc001.mcc110.3gppnetwork.org"
vni := ""
impiParts := strings.Split(m["impi"], "@")
if len(impiParts) > 1 {
vni = impiParts[1]
}
a := model.UDMVolteIMSUser{
NeId: neId,
IMSI: keys[1],
MSISDN: keys[2],
Tag: m["tag"], // volte = tag
VNI: vni,
}
arr = append(arr, a)
}
return arr
}
// ResetData 重置VolteIMS用户数据清空数据库重新同步Redis数据
func (r UDMVolteIMSUser) ResetData(neId string) int64 {
authArr := r.dataByRedis("*", neId)
// 数据清空后添加
go r.udmVolteIMSRepository.ClearAndInsert(neId, authArr)
return int64(len(authArr))
}
// ParseInfo 解析单个用户imsi信息 data从命令MML得到的结果
func (r UDMVolteIMSUser) ParseInfo(neId string, data map[string]string) model.UDMVolteIMSUser {
// "110011200004217@ims.mnc001.mcc110.3gppnetwork.org"
vni := ""
impiParts := strings.Split(data["impi"], "@")
if len(impiParts) > 1 {
vni = impiParts[1]
}
if vni == "" {
return model.UDMVolteIMSUser{}
}
u := model.UDMVolteIMSUser{
NeId: neId,
IMSI: data["imsi"],
MSISDN: data["msisdn"],
Tag: data["volte_tag"],
VNI: vni,
}
// 赋予ID
item := r.udmVolteIMSRepository.SelectByIMSIAndMSISDNAndNeID(u.IMSI, u.MSISDN, neId)
if item.ID != "" {
u.ID = item.ID
}
return u
}
// FindByPage 分页查询数据库
func (r UDMVolteIMSUser) FindByPage(query map[string]string) (int64, []model.UDMVolteIMSUser) {
return r.udmVolteIMSRepository.SelectPage(query)
}
// Find 查询数据库
func (r UDMVolteIMSUser) Find(u model.UDMVolteIMSUser) []model.UDMVolteIMSUser {
return r.udmVolteIMSRepository.SelectList(u)
}
// InsertByIMSI 从数据中读取后删除imsi再存入数据库
// imsi长度15
func (r UDMVolteIMSUser) InsertByIMSI(imsi, neId string) int64 {
uArr := r.dataByRedis(imsi+":*", neId)
if len(uArr) > 0 {
r.udmVolteIMSRepository.Delete(imsi, neId)
return r.udmVolteIMSRepository.Inserts(uArr)
}
return 0
}
// InsertData 导入文件数据 dataType目前两种txt/csv
func (r UDMVolteIMSUser) InsertData(neId, dataType string, data any) int64 {
// imsi截取前缀,重新获取部分数据
prefixes := make(map[string]struct{})
if dataType == "csv" {
for _, v := range data.([]map[string]string) {
imsi := v["imsi"]
if len(imsi) < 6 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
}
if dataType == "txt" {
for _, v := range data.([][]string) {
imsi := v[0]
if len(imsi) < 6 {
continue
}
prefix := imsi[:len(imsi)-4]
prefixes[prefix] = struct{}{}
}
}
// 根据前缀重新加载插入
var num int64 = 0
for prefix := range prefixes {
// 直接删除前缀的记录
r.udmVolteIMSRepository.DeletePrefixByIMSI(prefix, neId)
// keys voip:4600001000004*
arr := r.dataByRedis(prefix+"*", neId)
if len(arr) > 0 {
num += r.udmVolteIMSRepository.Inserts(arr)
}
}
return num
}
// Delete 删除单个不重新加载
func (r UDMVolteIMSUser) Delete(imsi, neId string) int64 {
return r.udmVolteIMSRepository.Delete(imsi, neId)
}
// LoadData 重新加载从imsi开始num的数据
func (r UDMVolteIMSUser) LoadData(neId, imsiOrMsisdn, num string) {
startIMSIOrMsisdn, _ := strconv.ParseInt(imsiOrMsisdn, 10, 64)
subNum, _ := strconv.ParseInt(num, 10, 64)
var i int64
for i = 0; i < subNum; i++ {
keyIMSI := fmt.Sprintf("%d", startIMSIOrMsisdn+i)
// 删除原数据
r.udmVolteIMSRepository.Delete(keyIMSI, neId)
// 加载数据
arr := r.dataByRedis(keyIMSI+":*", neId)
if len(arr) < 1 {
continue
}
r.udmVolteIMSRepository.Inserts(arr)
}
}