437 lines
12 KiB
Go
437 lines
12 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"be.ems/src/framework/constants/cachekey"
|
|
"be.ems/src/framework/logger"
|
|
"be.ems/src/framework/redis"
|
|
"be.ems/src/framework/utils/ssh"
|
|
"be.ems/src/modules/network_element/model"
|
|
"be.ems/src/modules/network_element/repository"
|
|
)
|
|
|
|
// 实例化服务层 NeInfoImpl 结构体
|
|
var NewNeInfoImpl = &NeInfoImpl{
|
|
neInfoRepository: repository.NewNeInfoImpl,
|
|
neHostRepository: repository.NewNeHostImpl,
|
|
}
|
|
|
|
// 网元信息 服务层处理
|
|
type NeInfoImpl struct {
|
|
// 网元信息数据信息
|
|
neInfoRepository repository.INeInfo
|
|
// 网元主机连接表
|
|
neHostRepository repository.INeHost
|
|
}
|
|
|
|
// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
|
|
func (r *NeInfoImpl) 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.NeId == neID {
|
|
redis.Del("", key)
|
|
values, _ := json.Marshal(neInfo)
|
|
redis.Set("", key, string(values))
|
|
}
|
|
}
|
|
return neInfo
|
|
}
|
|
|
|
// RefreshByNeTypeAndNeID 通过ne_type和ne_id刷新redis中的缓存
|
|
func (r *NeInfoImpl) 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.NeId == neID {
|
|
values, _ := json.Marshal(neInfo)
|
|
redis.Set("", key, string(values))
|
|
}
|
|
return neInfo
|
|
}
|
|
|
|
// ClearNeCacheByNeType 清除网元类型缓存
|
|
func (r *NeInfoImpl) 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 *NeInfoImpl) 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)
|
|
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 *NeInfoImpl) SelectPage(query map[string]any, bandStatus bool) map[string]any {
|
|
data := r.neInfoRepository.SelectPage(query)
|
|
|
|
// 网元直连读取网元服务状态
|
|
if bandStatus {
|
|
rows := data["rows"].([]model.NeInfo)
|
|
arr := &rows
|
|
for i := range *arr {
|
|
v := (*arr)[i]
|
|
result, err := NeState(v)
|
|
if err != nil {
|
|
(*arr)[i].ServerState = map[string]any{
|
|
"online": false,
|
|
}
|
|
// 网元状态设置为离线
|
|
if v.Status != "1" {
|
|
v.Status = "1"
|
|
(*arr)[i].Status = v.Status
|
|
r.neInfoRepository.Update(v)
|
|
}
|
|
continue
|
|
}
|
|
result["online"] = true
|
|
(*arr)[i].ServerState = result
|
|
// 网元状态设置为在线
|
|
if v.Status != "0" {
|
|
// 下发网管配置信息给网元
|
|
_, err = NeConfigOMC(v)
|
|
if err != nil {
|
|
v.Status = "3"
|
|
} else {
|
|
v.Status = "0"
|
|
}
|
|
(*arr)[i].Status = v.Status
|
|
r.neInfoRepository.Update(v)
|
|
}
|
|
}
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
// SelectList 查询列表
|
|
//
|
|
// bandStatus 带状态信息
|
|
func (r *NeInfoImpl) SelectList(ne model.NeInfo, bandStatus bool) []model.NeInfo {
|
|
list := r.neInfoRepository.SelectList(ne)
|
|
|
|
// 网元直连读取网元服务状态
|
|
if bandStatus {
|
|
neList := &list
|
|
for i := range *neList {
|
|
v := (*neList)[i]
|
|
result, err := NeState(v)
|
|
if err != nil {
|
|
(*neList)[i].ServerState = map[string]any{
|
|
"online": false,
|
|
}
|
|
// 网元状态设置为离线
|
|
if v.Status != "1" {
|
|
v.Status = "1"
|
|
(*neList)[i].Status = v.Status
|
|
r.neInfoRepository.Update(v)
|
|
}
|
|
continue
|
|
}
|
|
result["online"] = true
|
|
(*neList)[i].ServerState = result
|
|
// 网元状态设置为在线
|
|
if v.Status != "0" {
|
|
// 下发网管配置信息给网元
|
|
_, err = NeConfigOMC(v)
|
|
if err != nil {
|
|
v.Status = "3"
|
|
} else {
|
|
v.Status = "0"
|
|
}
|
|
(*neList)[i].Status = v.Status
|
|
r.neInfoRepository.Update(v)
|
|
}
|
|
}
|
|
}
|
|
|
|
return list
|
|
}
|
|
|
|
// SelectByIds 通过ID查询
|
|
//
|
|
// bandStatus 带主机信息
|
|
func (r *NeInfoImpl) SelectById(infoId string, bandHost bool) model.NeInfo {
|
|
if infoId == "" {
|
|
return model.NeInfo{}
|
|
}
|
|
neInfos := r.neInfoRepository.SelectByIds([]string{infoId})
|
|
if len(neInfos) > 0 {
|
|
neInfo := neInfos[0]
|
|
// 带主机信息
|
|
if neInfo.HostIDs != "" && bandHost {
|
|
neInfo.Hosts = r.neHostRepository.SelectByIds(strings.Split(neInfo.HostIDs, ","))
|
|
}
|
|
return neInfo
|
|
}
|
|
return model.NeInfo{}
|
|
}
|
|
|
|
// Insert 新增信息
|
|
func (r *NeInfoImpl) 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 := r.neHostRepository.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 *NeInfoImpl) 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"
|
|
r.neHostRepository.Update(host)
|
|
}
|
|
}
|
|
}
|
|
|
|
num := r.neInfoRepository.Update(neInfo)
|
|
if num > 0 {
|
|
// 刷新缓存
|
|
r.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
|
|
}
|
|
return num
|
|
}
|
|
|
|
// DeleteByIds 批量删除信息
|
|
func (r *NeInfoImpl) 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 != "" {
|
|
hostIds := strings.Split(v.HostIDs, ",")
|
|
r.neHostRepository.DeleteByIds(hostIds)
|
|
}
|
|
// 缓存信息删除
|
|
key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, v.NeType, v.NeId)
|
|
redis.Del("", key)
|
|
}
|
|
rows := r.neInfoRepository.DeleteByIds(infoIds)
|
|
return rows, nil
|
|
}
|
|
// 删除信息失败!
|
|
return 0, fmt.Errorf("delete fail")
|
|
}
|
|
|
|
// CheckUniqueNeTypeAndNeId 校验同类型下标识是否唯一
|
|
func (r *NeInfoImpl) CheckUniqueNeTypeAndNeId(neType, neId, infoId string) bool {
|
|
uniqueId := r.neInfoRepository.CheckUniqueNeTypeAndNeId(model.NeInfo{
|
|
NeType: neType,
|
|
NeId: neId,
|
|
})
|
|
if uniqueId == infoId {
|
|
return true
|
|
}
|
|
return uniqueId == ""
|
|
}
|
|
|
|
// NeRunCMD 向网元发送cmd命令
|
|
func (r *NeInfoImpl) NeRunCMD(neType, neId, cmd string) (string, error) {
|
|
neInfo := r.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
|
if neInfo.NeId != neId {
|
|
logger.Errorf("NeRunCMD NeType:%s NeID:%s not found", neType, neId)
|
|
return "", fmt.Errorf("neinfo not found")
|
|
}
|
|
// 带主机信息
|
|
if neInfo.HostIDs != "" {
|
|
neInfo.Hosts = r.neHostRepository.SelectByIds(strings.Split(neInfo.HostIDs, ","))
|
|
if len(neInfo.Hosts) <= 0 {
|
|
logger.Errorf("NeRunCMD Hosts %s not found", neInfo.HostIDs)
|
|
return "", fmt.Errorf("neinfo host not found")
|
|
}
|
|
}
|
|
|
|
neHost := neInfo.Hosts[0]
|
|
if neHost.HostType != "ssh" {
|
|
logger.Errorf("NeRunCMD Hosts first HostType %s not ssh", neHost.HostType)
|
|
return "", fmt.Errorf("neinfo host type not ssh")
|
|
}
|
|
var connSSH ssh.ConnSSH
|
|
neHost.CopyTo(&connSSH)
|
|
client, err := connSSH.NewClient()
|
|
if err != nil {
|
|
logger.Errorf("NeRunCMD NewClient err => %s", err.Error())
|
|
return "", fmt.Errorf("neinfo ssh client new err")
|
|
}
|
|
defer client.Close()
|
|
|
|
// 执行命令
|
|
output, err := client.RunCMD(cmd)
|
|
if err != nil {
|
|
logger.Errorf("NeRunCMD RunCMD %s err => %s", output, err.Error())
|
|
return "", fmt.Errorf("neinfo ssh run cmd err")
|
|
}
|
|
|
|
return output, nil
|
|
}
|
|
|
|
// NeConfigFileRead 网元配置文件读取 网元配置yaml文件复制到本地后通过filePath读取
|
|
func (r *NeInfoImpl) NeConfigFileRead(neInfo model.NeInfo, filePath string) []string {
|
|
files := []string{}
|
|
neTypeLower := strings.ToLower(neInfo.NeType)
|
|
|
|
// 网管本地路径
|
|
omcPath := "/usr/local/etc/omc/ne_config"
|
|
if runtime.GOOS == "windows" {
|
|
omcPath = fmt.Sprintf("C:%s", omcPath)
|
|
}
|
|
omcPath = fmt.Sprintf("%s/%s/%s", omcPath, neTypeLower, neInfo.NeId)
|
|
|
|
// 读取文件内容
|
|
if filePath != "" {
|
|
bytes, err := os.ReadFile(fmt.Sprintf("%s/%s", omcPath, filePath))
|
|
if err != nil {
|
|
logger.Warnf("NeConfigFile ReadFile => %s", err.Error())
|
|
return files
|
|
}
|
|
files = append(files, string(bytes))
|
|
return files
|
|
}
|
|
|
|
// 删除原有配置文件
|
|
// err := os.RemoveAll(omcPath)
|
|
// if err != nil {
|
|
// logger.Warnf("NeConfigFile Remove => %s", err.Error())
|
|
// return files
|
|
// }
|
|
|
|
// 网元端配置路径
|
|
nePath := "/usr/local/etc"
|
|
nePath = fmt.Sprintf("%s/%s", nePath, neTypeLower)
|
|
|
|
// 各个网元与网元间约定配置文件
|
|
err := ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/oam_manager.yaml", omcPath+"/oam_manager.yaml")
|
|
if err == nil {
|
|
files = append(files, "oam_manager.yaml")
|
|
}
|
|
|
|
// 根据情况复制网元特殊配置
|
|
switch neTypeLower {
|
|
case "ausf":
|
|
err = ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/ausfcfg.yaml", omcPath+"/ausfcfg.yaml")
|
|
if err == nil {
|
|
files = append(files, "ausfcfg.yaml")
|
|
}
|
|
case "smf":
|
|
ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/smf_conf.yaml", omcPath+"/smf_conf.yaml")
|
|
if err == nil {
|
|
files = append(files, "smf_conf.yaml")
|
|
}
|
|
ssh.FileSCPNeToLocal(neInfo.IP, nePath+"/smf_policy.yaml", omcPath+"/smf_policy.yaml")
|
|
if err == nil {
|
|
files = append(files, "smf_policy.yaml")
|
|
}
|
|
case "ims":
|
|
}
|
|
|
|
return files
|
|
}
|
|
|
|
// NeConfigFileWirte 网元配置文件写入 content内容 sync同步到网元端
|
|
func (r *NeInfoImpl) NeConfigFileWirte(neInfo model.NeInfo, filePath, content string, sync bool) error {
|
|
neTypeLower := strings.ToLower(neInfo.NeType)
|
|
|
|
// 网管本地路径
|
|
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, neInfo.NeId, filePath)
|
|
|
|
err := os.WriteFile(localFilePath, []byte(content), 0644)
|
|
if err != nil {
|
|
logger.Warnf("NeConfigFile WriteFile => %s", err.Error())
|
|
return fmt.Errorf("please check if the file exists or write permissions")
|
|
}
|
|
|
|
// 同步到网元端
|
|
if sync {
|
|
// 网元端配置路径
|
|
neFilePath := fmt.Sprintf("/usr/local/etc/%s/%s", neTypeLower, filePath)
|
|
// 修改网元文件权限
|
|
r.NeRunCMD(neInfo.NeType, neInfo.NeId, fmt.Sprintf("sudo chmod o+w %s", neFilePath))
|
|
// 复制到网元进行覆盖
|
|
err = ssh.FileSCPLocalToNe(neInfo.IP, localFilePath, neFilePath)
|
|
if err != nil {
|
|
logger.Warnf("NeConfigFile SyncFile => %s", err.Error())
|
|
return fmt.Errorf("please check if scp remote copy is allowed")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|