style: 去除Impl接口声明层聚焦服务函数

This commit is contained in:
TsMask
2024-10-12 19:06:12 +08:00
parent 94bba0c910
commit 1f0c932be8
102 changed files with 5624 additions and 6320 deletions

View File

@@ -1,72 +1,918 @@
package service
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"be.ems/src/framework/constants/cachekey"
"be.ems/src/framework/logger"
"be.ems/src/framework/redis"
"be.ems/src/framework/telnet"
"be.ems/src/framework/utils/parse"
"be.ems/src/framework/utils/ssh"
neFetchlink "be.ems/src/modules/network_element/fetch_link"
"be.ems/src/modules/network_element/model"
"be.ems/src/modules/network_element/repository"
)
// 网元信息 服务层接口
type INeInfo interface {
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo
// RefreshByNeTypeAndNeID 通过ne_type和ne_id刷新redis中的缓存
RefreshByNeTypeAndNeID(neType, neID string) model.NeInfo
// ClearNeCacheByNeType 清除网元类型缓存
ClearNeCacheByNeType(neType string) bool
// SelectNeInfoByRmuid 通过rmUID查询网元信息
SelectNeInfoByRmuid(rmUid string) model.NeInfo
// SelectPage 根据条件分页查询
//
// bandStatus 带状态信息
SelectPage(query map[string]any, bandStatus bool) map[string]any
// SelectList 查询列表
//
// bandStatus 带状态信息
// bandHost 带主机信息
SelectList(ne model.NeInfo, bandStatus bool, bandHost bool) []model.NeInfo
// SelectByIds 通过ID查询
//
// bandStatus 带主机信息
SelectById(infoId string, bandHost bool) model.NeInfo
// Insert 新增信息
Insert(neInfo model.NeInfo) string
// Update 修改信息
Update(neInfo model.NeInfo) int64
// DeleteByIds 批量删除信息
DeleteByIds(infoIds []string) (int64, error)
// CheckUniqueNeTypeAndNeId 校验同类型下标识是否唯一
CheckUniqueNeTypeAndNeId(neType, neId, id string) bool
// NeRunSSHClient 网元主机的SSH客户端-为创建相关连接,注意结束后 Close()
NeRunSSHClient(neType, neId string) (*ssh.ConnSSH, error)
// NeRunSSHCmd 网元主机的SSH客户端发送cmd命令
NeRunSSHCmd(neType, neId, cmd string) (string, error)
// NeRunTelnetClient 网元主机的Telnet客户端-为创建相关连接,注意结束后 Close()
// num 是网元主机telnet 14100 25200
NeRunTelnetClient(neType, neId string, num int) (*telnet.ConnTelnet, error)
// NeConfOAMReadSync 网元OAM配置文件读取
NeConfOAMReadSync(neType, neId string) (map[string]any, error)
// NeConfOAMWirteSync 网元OAM配置文件生成并同步
NeConfOAMWirteSync(neInfo model.NeInfo, content map[string]any, sync bool) error
// NeConfPara5GRead 网元公共配置文件读取
NeConfPara5GRead() (map[string]any, error)
// NeConfPara5GWirte 网元公共配置文件写入 content内容 syncNE同步到网元端NeType@NeId
NeConfPara5GWirte(content map[string]any, syncNE []string) error
// 实例化服务层 NeInfo 结构体
var NewNeInfo = &NeInfo{
neInfoRepository: repository.NewNeInfo,
Para5GData: map[string]string{},
}
// 网元信息 服务层处理
type NeInfo struct {
// 网元信息数据信息
neInfoRepository *repository.NeInfo
Para5GData map[string]string
}
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
func (r *NeInfo) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo {
var neInfo model.NeInfo
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, strings.ToUpper(neType), neID)
jsonStr, _ := redis.Get("", key)
if len(jsonStr) > 7 {
err := json.Unmarshal([]byte(jsonStr), &neInfo)
if err != nil {
neInfo = model.NeInfo{}
}
} else {
neInfo = r.neInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID)
if neInfo.ID != "" && neInfo.NeId == neID {
redis.Del("", key)
values, _ := json.Marshal(neInfo)
redis.Set("", key, string(values))
}
}
return neInfo
}
// RefreshByNeTypeAndNeID 通过ne_type和ne_id刷新redis中的缓存
func (r *NeInfo) RefreshByNeTypeAndNeID(neType, neID string) model.NeInfo {
var neInfo model.NeInfo
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, strings.ToUpper(neType), neID)
redis.Del("", key)
neInfo = r.neInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID)
if neInfo.ID != "" && neInfo.NeId == neID {
values, _ := json.Marshal(neInfo)
redis.Set("", key, string(values))
}
return neInfo
}
// ClearNeCacheByNeType 清除网元类型缓存
func (r *NeInfo) ClearNeCacheByNeType(neType string) bool {
key := fmt.Sprintf("%s*", cachekey.NE_KEY)
if neType != "*" {
key = fmt.Sprintf("%s%s*", cachekey.NE_KEY, neType)
}
keys, err := redis.GetKeys("", key)
if err != nil {
return false
}
delOk, _ := redis.DelKeys("", keys)
return delOk
}
// SelectNeInfoByRmuid 通过rmUID查询网元信息
func (r *NeInfo) SelectNeInfoByRmuid(rmUid string) model.NeInfo {
var neInfo model.NeInfo
cacheKeys, _ := redis.GetKeys("", cachekey.NE_KEY+"*")
if len(cacheKeys) > 0 {
for _, key := range cacheKeys {
var v model.NeInfo
jsonStr, _ := redis.Get("", key)
if len(jsonStr) > 7 {
json.Unmarshal([]byte(jsonStr), &v)
}
if v.RmUID == rmUid {
neInfo = v
break
}
}
} else {
neInfos := r.SelectList(neInfo, false, false)
for _, v := range neInfos {
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, strings.ToUpper(v.NeType), v.NeId)
redis.Del("", key)
values, _ := json.Marshal(v)
redis.Set("", key, string(values))
if v.RmUID == rmUid {
neInfo = v
}
}
}
return neInfo
}
// SelectPage 根据条件分页查询
//
// bandStatus 带状态信息
func (r *NeInfo) SelectPage(query map[string]any, bandStatus bool) map[string]any {
data := r.neInfoRepository.SelectPage(query)
// 网元直连读取网元服务状态
if bandStatus {
rows := data["rows"].([]model.NeInfo)
r.bandNeStatus(&rows)
}
return data
}
// SelectList 查询列表
//
// bandStatus 带状态信息
// bandHost 带主机信息
func (r *NeInfo) SelectList(ne model.NeInfo, bandStatus bool, bandHost bool) []model.NeInfo {
list := r.neInfoRepository.SelectList(ne)
// 网元直连读取网元服务状态
if bandStatus {
r.bandNeStatus(&list)
}
// 网元主机信息
if bandHost {
r.bandNeHosts(&list)
}
return list
}
// bandNeStatus 网元列表项数据带网元服务状态
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,
}
// 网元状态设置为离线
if v.Status != "0" {
v.Status = "0"
(*arr)[i].Status = v.Status
r.neInfoRepository.Update(v)
}
continue
}
result["online"] = true
(*arr)[i].ServerState = result
// 网元状态设置为在线
if v.Status != "1" {
// 下发网管配置信息给网元
_, err = neFetchlink.NeConfigOMC(v)
if err == nil {
v.Status = "1"
} else {
v.Status = "2"
}
(*arr)[i].Status = v.Status
r.neInfoRepository.Update(v)
}
}
}
// bandNeHosts 网元列表项数据带网元主机信息
func (r *NeInfo) bandNeHosts(arr *[]model.NeInfo) {
for i := range *arr {
v := (*arr)[i]
if v.HostIDs != "" {
hostIds := strings.Split(v.HostIDs, ",")
if len(hostIds) <= 1 {
continue
}
for _, hostId := range hostIds {
neHost := NewNeHost.SelectById(hostId)
if neHost.HostID == "" || neHost.HostID != hostId {
continue
}
(*arr)[i].Hosts = append((*arr)[i].Hosts, neHost)
}
}
}
}
// SelectByIds 通过ID查询
//
// bandHost 带主机信息
func (r *NeInfo) SelectById(infoId string, bandHost bool) model.NeInfo {
if infoId == "" {
return model.NeInfo{}
}
neInfos := r.neInfoRepository.SelectByIds([]string{infoId})
if len(neInfos) > 0 {
// 带主机信息
if neInfos[0].HostIDs != "" && bandHost {
r.bandNeHosts(&neInfos)
}
return neInfos[0]
}
return model.NeInfo{}
}
// Insert 新增信息
func (r *NeInfo) Insert(neInfo model.NeInfo) string {
// 主机信息新增
if neInfo.Hosts != nil {
var hostIDs []string
for _, host := range neInfo.Hosts {
host.Title = fmt.Sprintf("%s_%s_%d", strings.ToUpper(neInfo.NeType), neInfo.NeId, host.Port)
host.GroupID = "1"
hostId := NewNeHost.Insert(host)
if hostId != "" {
hostIDs = append(hostIDs, hostId)
}
}
neInfo.HostIDs = strings.Join(hostIDs, ",")
}
insertId := r.neInfoRepository.Insert(neInfo)
if insertId != "" {
// 刷新缓存
r.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
}
return insertId
}
// Update 修改信息
func (r *NeInfo) Update(neInfo model.NeInfo) int64 {
// 主机信息更新
if neInfo.Hosts != nil {
for _, host := range neInfo.Hosts {
if host.HostID != "" {
host.Title = fmt.Sprintf("%s_%s_%d", strings.ToUpper(neInfo.NeType), neInfo.NeId, host.Port)
host.GroupID = "1"
NewNeHost.Update(host)
}
}
}
num := r.neInfoRepository.Update(neInfo)
if num > 0 {
// 刷新缓存
r.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
}
return num
}
// DeleteByIds 批量删除信息
func (r *NeInfo) DeleteByIds(infoIds []string) (int64, error) {
// 检查是否存在
infos := r.neInfoRepository.SelectByIds(infoIds)
if len(infos) <= 0 {
return 0, fmt.Errorf("neHostCmd.noData")
}
if len(infos) == len(infoIds) {
for _, v := range infos {
// 主机信息删除
if v.HostIDs != "" {
NewNeHost.DeleteByIds(strings.Split(v.HostIDs, ","))
}
// 删除License
neLicense := NewNeLicense.SelectByNeTypeAndNeID(v.NeType, v.NeId)
if neLicense.NeId == v.NeId {
NewNeLicense.DeleteByIds([]string{neLicense.ID})
}
// 删除Version
neVersion := NewNeVersion.SelectByNeTypeAndNeID(v.NeType, v.NeId)
if neVersion.NeId == v.NeId {
NewNeVersion.DeleteByIds([]string{neVersion.ID})
}
// 缓存信息删除
redis.Del("", fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, v.NeType, v.NeId))
}
rows := r.neInfoRepository.DeleteByIds(infoIds)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// CheckUniqueNeTypeAndNeId 校验同类型下标识是否唯一
func (r *NeInfo) CheckUniqueNeTypeAndNeId(neType, neId, id string) bool {
uniqueId := r.neInfoRepository.CheckUniqueNeTypeAndNeId(model.NeInfo{
NeType: neType,
NeId: neId,
})
if uniqueId == id {
return true
}
return uniqueId == ""
}
// NeRunSSHClient 网元主机的SSH客户端-为创建相关连接,注意结束后 Close()
func (r *NeInfo) NeRunSSHClient(neType, neId string) (*ssh.ConnSSH, error) {
neInfo := r.SelectNeInfoByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId {
logger.Errorf("NeRunSSHClient NeType:%s NeID:%s not found", neType, neId)
return nil, fmt.Errorf("neinfo not found")
}
// 取主机信息
if neInfo.HostIDs == "" {
logger.Errorf("NeRunSSHClient NeType:%s NeID:%s hostId not found", neType, neId)
return nil, fmt.Errorf("neinfo hostId not found")
}
hostIds := strings.Split(neInfo.HostIDs, ",")
if len(hostIds) <= 1 {
logger.Errorf("NeRunTelnetClient hosts id %s not found", neInfo.HostIDs)
return nil, fmt.Errorf("neinfo host id not found")
}
hostId := hostIds[0] // 网元主机ssh 022
neHost := NewNeHost.SelectById(hostId)
if neHost.HostID == "" || neHost.HostID != hostId {
logger.Errorf("NeRunTelnetClient Hosts %s not found", neInfo.HostIDs)
return nil, fmt.Errorf("neinfo host not found")
}
if neHost.HostType != "ssh" {
logger.Errorf("NeRunSSHClient Hosts first HostType %s not ssh", neHost.HostType)
return nil, fmt.Errorf("neinfo host type not ssh")
}
var connSSH ssh.ConnSSH
neHost.CopyTo(&connSSH)
var client *ssh.ConnSSH
var err error
if neHost.AuthMode == "2" {
client, err = connSSH.NewClientByLocalPrivate()
} else {
client, err = connSSH.NewClient()
}
if err != nil {
logger.Errorf("NeRunSSHClient NewClient err => %s", err.Error())
return nil, fmt.Errorf("neinfo ssh client new err")
}
return client, nil
}
// NeRunSSHCmd 网元主机的SSH客户端发送cmd命令
func (r *NeInfo) NeRunSSHCmd(neType, neId, cmd string) (string, error) {
sshClient, err := r.NeRunSSHClient(neType, neId)
if err != nil {
return "", err
}
defer sshClient.Close()
// 执行命令
output, err := sshClient.RunCMD(cmd)
if err != nil {
logger.Errorf("NeRunSSHCmd RunCMD %s err => %s", output, err.Error())
return "", fmt.Errorf("neinfo ssh run cmd err")
}
return output, nil
}
// NeRunTelnetClient 网元主机的Telnet客户端-为创建相关连接,注意结束后 Close()
// num 是网元主机telnet 14100 25200
func (r *NeInfo) NeRunTelnetClient(neType, neId string, num int) (*telnet.ConnTelnet, error) {
neInfo := r.SelectNeInfoByNeTypeAndNeID(neType, neId)
if neInfo.NeId != neId {
logger.Errorf("NeRunTelnetClient NeType:%s NeID:%s not found", neType, neId)
return nil, fmt.Errorf("neinfo not found")
}
// 取主机信息
if neInfo.HostIDs == "" {
logger.Errorf("NeRunTelnetClient NeType:%s NeID:%s hostId not found", neType, neId)
return nil, fmt.Errorf("neinfo hostId not found")
}
hostIds := strings.Split(neInfo.HostIDs, ",")
if len(hostIds) <= 1 {
logger.Errorf("NeRunTelnetClient hosts id %s not found", neInfo.HostIDs)
return nil, fmt.Errorf("neinfo host id not found")
}
hostId := hostIds[num] // 网元主机telnet 14100 25200
neHost := NewNeHost.SelectById(hostId)
if neHost.HostID == "" || neHost.HostID != hostId {
logger.Errorf("NeRunTelnetClient Hosts %s not found", neInfo.HostIDs)
return nil, fmt.Errorf("neinfo host not found")
}
// 创建链接Telnet客户端
var connTelnet telnet.ConnTelnet
neHost.CopyTo(&connTelnet)
telnetClient, err := connTelnet.NewClient()
if err != nil {
logger.Errorf("NeRunTelnetClient NewClient err => %s", err.Error())
return nil, fmt.Errorf("neinfo telnet client new err")
}
return telnetClient, nil
}
// NeConfOAMReadSync 网元OAM配置文件读取
func (r *NeInfo) NeConfOAMReadSync(neType, neId string) (map[string]any, error) {
oamData, err := r.neConfOAMRead(neType, neId, true)
if err != nil {
return nil, err
}
// UPF和SMF 全小写的key
if _, ok := oamData["httpmanagecfg"]; ok {
content := map[string]any{}
// 网元HTTP服务
// if v, ok := oamData["httpmanagecfg"]; ok {
// item := v.(map[string]any)
// }
// 对网管HTTP配置
if v, ok := oamData["oamconfig"]; ok {
item := v.(map[string]any)
if v, ok := item["iptype"]; ok && v != "" && v != nil {
ipType := v.(string)
if ipType == "ipv6" {
content["omcIP"] = item["ipv6"]
}
if ipType == "ipv4" {
content["omcIP"] = item["ipv4"]
}
}
content["oamEnable"] = item["enable"]
content["oamPort"] = item["port"]
}
// 对网管SNMP配置
if v, ok := oamData["snmpconfig"]; ok {
item := v.(map[string]any)
content["snmpEnable"] = item["enable"]
content["snmpPort"] = item["port"]
}
// 对网管KPI上报配置
if v, ok := oamData["kpiconfig"]; ok {
item := v.(map[string]any)
content["kpiEnable"] = item["enable"]
content["kpiTimer"] = item["timer"]
}
oamData := r.neConfOAMData()
r.neConfOAMWirte(neType, neId, oamData, false)
r.NeConfOAMWirteSync(model.NeInfo{
NeType: neType,
NeId: neId,
}, content, false)
return r.neConfOAMRead(neType, neId, false)
}
// NSSF和MME 配置KPIconfig名不一致时
if v, ok := oamData["KPIconfig"]; ok && v != nil {
item := v.(map[string]any)
oamData["kpiConfig"] = item
delete(oamData, "KPIconfig")
r.neConfOAMWirte(neType, neId, oamData, false)
}
return oamData, nil
}
// neConfOAMData 网元OAM配置文件默认格式数据
func (r *NeInfo) neConfOAMData() map[string]any {
return map[string]any{
"httpManageCfg": map[string]any{
"ipType": "ipv4",
"ipv4": "172.16.5.1", // 必改
"ipv6": "",
"port": 33030,
"scheme": "http",
},
"oamConfig": map[string]any{
"enable": true,
"ipType": "ipv4",
"ipv4": "172.16.5.100", // 必改
"ipv6": "",
"port": 33030,
"scheme": "http",
// 必改
"neConfig": map[string]any{
"neId": "001",
"rmUid": "4400HX1XXX001",
"neName": "XXX_001",
"dn": "-",
"vendorName": "GD",
"province": "-",
"pvFlag": "PNF",
},
},
"snmpConfig": map[string]any{
"enable": false,
"ipType": "ipv4",
"ipv4": "172.16.5.1", // 必改
"ipv6": "",
"port": 4957,
},
"kpiConfig": map[string]any{
"enable": true,
"timer": 60, // 必改
},
// "pubConfigPath": "/usr/local/etc/conf/para5G.yaml", // 网元只会读一次后续会置空,建议不放
}
}
// neConfOAMRead 网元OAM配置文件读取 sync从网元端同步到本地
func (r *NeInfo) neConfOAMRead(neType, neId string, sync bool) (map[string]any, error) {
neTypeLower := strings.ToLower(neType)
fileName := "oam_manager.yaml"
// 网管本地路径
localFilePath := fmt.Sprintf("/usr/local/etc/omc/ne_config/%s/%s/%s", neTypeLower, neId, fileName)
if runtime.GOOS == "windows" {
localFilePath = fmt.Sprintf("C:%s", localFilePath)
}
// 从网元端同步到本地
if sync {
// 网元主机的SSH客户端
sshClient, err := r.NeRunSSHClient(neType, neId)
if err != nil {
return nil, fmt.Errorf("ne info ssh client err")
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return nil, fmt.Errorf("ne info sftp client err")
}
defer sftpClient.Close()
// 网元端文件路径
neFilePath := fmt.Sprintf("/usr/local/etc/%s/%s", neTypeLower, fileName)
// 修改网元文件权限
sshClient.RunCMD(fmt.Sprintf("sudo touch %s && sudo chmod o+rw %s", neFilePath, neFilePath))
// 网元端复制到本地
if err = sftpClient.CopyFileRemoteToLocal(neFilePath, localFilePath); err != nil {
return nil, fmt.Errorf("copy oam config err")
}
}
// 读取文件内容
bytes, err := os.ReadFile(localFilePath)
if err != nil {
// logger.Warnf("NeConfOAMRead ReadFile => %s", err.Error())
// return nil, fmt.Errorf("read file error")
// 无保留文件时返回默认文件数据
oamData := r.neConfOAMData()
r.neConfOAMWirte(neType, neId, oamData, false)
return oamData, nil
}
content := string(bytes)
// 序列化Map
mapData, err := parse.ConvertConfigToMap("yaml", content)
if err != nil {
logger.Warnf("NeConfOAMRead ConvertConfigToMap => %s", err.Error())
return nil, fmt.Errorf("content convert type error")
}
return mapData, nil
}
// neConfOAMWirte 网元OAM配置文件写入 content内容 sync同步到网元端
func (r *NeInfo) neConfOAMWirte(neType, neId string, content any, sync bool) error {
neTypeLower := strings.ToLower(neType)
fileName := "oam_manager.yaml"
// 网管本地路径
omcPath := "/usr/local/etc/omc/ne_config"
if runtime.GOOS == "windows" {
omcPath = fmt.Sprintf("C:%s", omcPath)
}
localFilePath := fmt.Sprintf("%s/%s/%s/%s", omcPath, neTypeLower, neId, fileName)
// 写入文件
if err := parse.ConvertConfigToFile("yaml", localFilePath, content); err != nil {
return fmt.Errorf("please check if the file exists or write permissions")
}
// 同步到网元端
if sync {
// 网元主机的SSH客户端
sshClient, err := r.NeRunSSHClient(neType, neId)
if err != nil {
return err
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return err
}
defer sftpClient.Close()
// 网元端配置路径
neFilePath := fmt.Sprintf("/usr/local/etc/%s/%s", neTypeLower, fileName)
neFileDir := filepath.ToSlash(filepath.Dir(neFilePath))
// 修改网元文件权限
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p %s && sudo chmod 775 %s && sudo touch %s && sudo chmod o+rw %s", neFileDir, neFileDir, neFilePath, neFilePath))
// 复制到网元进行覆盖
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
return fmt.Errorf("please check if scp remote copy is allowed")
}
}
return nil
}
// NeConfOAMWirteSync 网元OAM配置文件生成并同步
func (r *NeInfo) NeConfOAMWirteSync(neInfo model.NeInfo, content map[string]any, sync bool) error {
oamData, err := r.neConfOAMRead(neInfo.NeType, neInfo.NeId, false)
if oamData == nil || err != nil {
return fmt.Errorf("error read OAM file info")
}
// 网元HTTP服务
if v, ok := oamData["httpManageCfg"]; ok {
item := v.(map[string]any)
item["port"] = neInfo.Port
if strings.Contains(neInfo.IP, ":") {
item["ipType"] = "ipv6"
item["ipv6"] = neInfo.IP
}
if strings.Contains(neInfo.IP, ".") {
item["ipType"] = "ipv4"
item["ipv4"] = neInfo.IP
}
oamData["httpManageCfg"] = item
}
// 对网管HTTP配置
if v, ok := oamData["oamConfig"]; ok {
item := v.(map[string]any)
item["neConfig"] = map[string]string{
"neId": neInfo.NeId,
"rmUid": neInfo.RmUID,
"neName": neInfo.NeName,
"dn": neInfo.Dn,
"vendorName": neInfo.VendorName,
"province": neInfo.Province,
"pvFlag": neInfo.PvFlag,
}
// 公共参数指定的OMC
if omcIP, ok := r.Para5GData["OMC_IP"]; ok && omcIP != "" {
if strings.Contains(omcIP, ":") {
item["ipType"] = "ipv6"
item["ipv6"] = omcIP
}
if strings.Contains(omcIP, ".") {
item["ipType"] = "ipv4"
item["ipv4"] = omcIP
}
}
if v, ok := content["omcIP"]; ok && v != "" && v != nil {
omcIP := v.(string)
if strings.Contains(omcIP, ":") {
item["ipType"] = "ipv6"
item["ipv6"] = omcIP
}
if strings.Contains(omcIP, ".") {
item["ipType"] = "ipv4"
item["ipv4"] = omcIP
}
}
if oamEnable, ok := content["oamEnable"]; ok && oamEnable != nil {
item["enable"] = parse.Boolean(oamEnable)
}
if oamPort, ok := content["oamPort"]; ok && oamPort != nil {
item["port"] = parse.Number(oamPort)
}
oamData["oamConfig"] = item
}
// 对网管SNMP配置
if v, ok := oamData["snmpConfig"]; ok {
item := v.(map[string]any)
if strings.Contains(neInfo.IP, ":") {
item["ipType"] = "ipv6"
item["ipv6"] = neInfo.IP
}
if strings.Contains(neInfo.IP, ".") {
item["ipType"] = "ipv4"
item["ipv4"] = neInfo.IP
}
if snmpEnable, ok := content["snmpEnable"]; ok && snmpEnable != nil {
item["enable"] = parse.Boolean(snmpEnable)
}
if snmpPort, ok := content["snmpPort"]; ok && snmpPort != nil {
item["port"] = parse.Number(snmpPort)
}
oamData["snmpConfig"] = item
}
// 对网管KPI上报配置
if v, ok := oamData["kpiConfig"]; ok {
item := v.(map[string]any)
if neInfo.NeType == "UPF" {
item["timer"] = 5
} else {
item["timer"] = 60
}
if kpiEnable, ok := content["kpiEnable"]; ok && kpiEnable != nil {
item["enable"] = parse.Boolean(kpiEnable)
}
if kpiTimer, ok := content["kpiTimer"]; ok && kpiTimer != nil {
item["timer"] = parse.Number(kpiTimer)
}
oamData["kpiConfig"] = item
}
if err := r.neConfOAMWirte(neInfo.NeType, neInfo.NeId, oamData, sync); err != nil {
return fmt.Errorf("error wirte OAM file info")
}
return nil
}
// NeConfPara5GRead 网元公共配置文件读取
func (r *NeInfo) NeConfPara5GRead() (map[string]any, error) {
// 网管本地路径
omcFilePath := "/usr/local/etc/omc/para5G.yaml"
if runtime.GOOS == "windows" {
omcFilePath = fmt.Sprintf("C:%s", omcFilePath)
}
// 读取文件内容
bytes, err := os.ReadFile(omcFilePath)
if err != nil {
logger.Warnf("NeConfPara5GRead ReadFile => %s", err.Error())
return nil, fmt.Errorf("read file error")
}
content := string(bytes)
// 序列化Map
mapData, err := parse.ConvertConfigToMap("yaml", content)
if err != nil {
logger.Warnf("NeConfPara5GRead ConvertConfigToMap => %s", err.Error())
return nil, fmt.Errorf("content convert type error")
}
return mapData, nil
}
// NeConfPara5GWirte 网元公共配置文件写入 content内容 syncNE同步到网元端NeType@NeId
func (r *NeInfo) NeConfPara5GWirte(content map[string]any, syncNE []string) error {
// 网管本地路径
omcFilePath := "/usr/local/etc/omc/para5G.yaml"
if runtime.GOOS == "windows" {
omcFilePath = fmt.Sprintf("C:%s", omcFilePath)
}
if err := parse.ConvertConfigToFile("yaml", omcFilePath, content); err != nil {
return fmt.Errorf("please check if the file exists or write permissions")
}
// 同步到网元端
if len(syncNE) > 0 {
errMsg := []string{}
for _, neTI := range syncNE {
ti := strings.SplitN(neTI, "@", 2)
// 网元主机的SSH客户端
sshClient, err := r.NeRunSSHClient(ti[0], ti[1])
if err != nil {
errMsg = append(errMsg, fmt.Sprintf("%s : %s", ti, err.Error()))
continue
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
errMsg = append(errMsg, fmt.Sprintf("%s : %s", ti, err.Error()))
continue
}
defer sftpClient.Close()
// 网元端配置路径
neFilePath := "/usr/local/etc/conf/para5G.yaml"
neFileDir := filepath.ToSlash(filepath.Dir(neFilePath))
// 修改网元文件权限
sshClient.RunCMD(fmt.Sprintf("sudo mkdir -p %s && sudo chmod 775 %s && sudo touch %s && sudo chmod o+rw %s", neFileDir, neFileDir, neFilePath, neFilePath))
// 复制到网元进行覆盖
if err = sftpClient.CopyFileLocalToRemote(omcFilePath, neFilePath); err != nil {
errMsg = append(errMsg, fmt.Sprintf("%s : please check if scp remote copy is allowed", ti))
continue
}
}
if len(errMsg) > 0 {
return fmt.Errorf("%s", strings.Join(errMsg, "\r\n"))
}
}
// 转换一份数据到全局
r.Para5GData = r.neConfPara5GDataConvert(content)
return nil
}
// NeConfPara5GConvert 网元公共配置数据转化 content网元公共配置文件读取内容
func (r *NeInfo) neConfPara5GDataConvert(content map[string]any) map[string]string {
defer func() {
if err := recover(); err != nil {
logger.Errorf("NeConfPara5GDataConvert panic: %v", err)
// 文件异常就删除配置
omcFilePath := "/usr/local/etc/omc/para5G.yaml"
if runtime.GOOS == "windows" {
omcFilePath = fmt.Sprintf("C:%s", omcFilePath)
}
os.Remove(omcFilePath)
}
}()
basic := content["basic"].(map[string]any)
external := content["external"].(map[string]any)
sbi := content["sbi"].(map[string]any)
mcc := "460"
mnc := "01"
mncDomain := "001"
if plmnId, plmnIdOk := basic["plmnId"].(map[string]any); plmnIdOk {
mcc = plmnId["mcc"].(string)
mnc = plmnId["mnc"].(string)
// If a user input two digit MNC, add a leading zero
if len(mnc) == 2 {
mncDomain = fmt.Sprintf("0%s", mnc)
} else {
mncDomain = mnc
}
}
sst := "1"
sd := "000001"
if plmnId, plmnIdOk := basic["snssai"].(map[string]any); plmnIdOk {
sst = plmnId["sst"].(string)
sd = plmnId["sd"].(string)
}
n3IPAmdMask := external["upfn3_ip"].(string)
n3Arr := strings.SplitN(n3IPAmdMask, "/", 2)
n3IP := n3Arr[0]
n3Mask := "255.255.255.0"
if len(n3Arr) > 1 {
n3Mask = parse.ConvertIPMask(parse.Number(n3Arr[1]))
}
n6IPAmdMask := external["upfn6_ip"].(string)
n6Arr := strings.SplitN(n6IPAmdMask, "/", 2)
n6IP := n6Arr[0]
n6Mask := "255.255.255.0"
if len(n6Arr) > 1 {
n6Mask = parse.ConvertIPMask(parse.Number(n6Arr[1]))
}
ueIPAmdMask := external["ue_pool"].(string)
ueArr := strings.SplitN(ueIPAmdMask, "/", 2)
ueIP := ueArr[0]
ueCicr := "24"
ueMask := "255.255.255.0"
if len(ueArr) > 1 {
ueCicr = ueArr[1]
ueMask = parse.ConvertIPMask(parse.Number(ueArr[1]))
}
return map[string]string{
// basic
"TAC": basic["tac"].(string),
"MCC": mcc,
"MNC": mnc,
"MNC_DOMAIN": mncDomain,
"SST": sst,
"SD": sd,
"DNN_DATA": basic["dnn_data"].(string),
"DNN_IMS": basic["dnn_ims"].(string),
// external
"N2_IP": external["amfn2_ip"].(string),
"UE_POOL": external["ue_pool"].(string),
"UE_IP": ueIP,
"UE_MASK": ueMask,
"UE_CIDR": ueCicr,
"UPF_TYPE": external["upf_type"].(string), // StandardUPF LightUPF
"N3_IP": n3IP,
"N3_MASK": n3Mask,
"N3_GW": external["upfn3_gw"].(string),
"N3_PCI": external["upfn3_pci"].(string),
"N3_MAC": external["upfn3_mac"].(string),
"N6_IP": n6IP,
"N6_MASK": n6Mask,
"N6_GW": external["upfn6_gw"].(string),
"N6_PCI": external["upfn6_pci"].(string),
"N6_MAC": external["upfn6_mac"].(string),
"SIP_IP": external["ims_sip_ip"].(string),
"S1_MMEIP": external["mmes1_ip"].(string),
"S11_MMEIP": external["mmes11_ip"].(string),
"S10_MMEIP": external["mmes10_ip"].(string),
// sbi
"OMC_IP": sbi["omc_ip"].(string),
"IMS_IP": sbi["ims_ip"].(string),
"AMF_IP": sbi["amf_ip"].(string),
"AUSF_IP": sbi["ausf_ip"].(string),
"UDM_IP": sbi["udm_ip"].(string),
"SMF_IP": sbi["smf_ip"].(string),
"PCF_IP": sbi["pcf_ip"].(string),
"NSSF_IP": sbi["nssf_ip"].(string),
"NRF_IP": sbi["nrf_ip"].(string),
"UPF_IP": sbi["upf_ip"].(string),
"LMF_IP": sbi["lmf_ip"].(string),
"NEF_IP": sbi["nef_ip"].(string),
"MME_IP": sbi["mme_ip"].(string),
"N3IWF_IP": sbi["n3iwf_ip"].(string),
"SMSC_IP": sbi["smsc_ip"].(string),
"DB_IP": sbi["db_ip"].(string),
}
}