Files
be.ems/src/modules/network_element/service/ne_software.impl.go

307 lines
9.3 KiB
Go

package service
import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
"be.ems/src/framework/utils/file"
"be.ems/src/modules/network_element/model"
"be.ems/src/modules/network_element/repository"
)
// 实例化服务层 NeSoftwareImpl 结构体
var NewNeSoftwareImpl = &NeSoftwareImpl{
neSoftwareRepository: repository.NewNeSoftwareImpl,
}
// NeSoftwareImpl 网元软件包信息 服务层处理
type NeSoftwareImpl struct {
// 网元软件包信息
neSoftwareRepository repository.INeSoftware
}
// SelectNeHostPage 分页查询列表数据
func (r *NeSoftwareImpl) SelectPage(query map[string]any) map[string]any {
return r.neSoftwareRepository.SelectPage(query)
}
// SelectConfigList 查询列表
func (r *NeSoftwareImpl) SelectList(neSoftware model.NeSoftware) []model.NeSoftware {
return r.neSoftwareRepository.SelectList(neSoftware)
}
// SelectByIds 通过ID查询
func (r *NeSoftwareImpl) SelectById(id string) model.NeSoftware {
if id == "" {
return model.NeSoftware{}
}
neHosts := r.neSoftwareRepository.SelectByIds([]string{id})
if len(neHosts) > 0 {
return neHosts[0]
}
return model.NeSoftware{}
}
// Insert 新增信息
func (r *NeSoftwareImpl) Insert(neSoftware model.NeSoftware) string {
inserId := r.neSoftwareRepository.Insert(neSoftware)
if inserId != "" {
// 更新同类型的新包版本
neVersions := NewNeVersionImpl.SelectList(model.NeVersion{NeType: neSoftware.NeType})
if len(neVersions) > 0 {
for _, neVersion := range neVersions {
neVersion.NewName = neSoftware.Name
neVersion.NewVersion = neSoftware.Version
neVersion.NewPath = neSoftware.Path
neVersion.Status = "3"
neVersion.UpdateBy = neSoftware.CreateBy
NewNeVersionImpl.Update(neVersion)
}
}
}
return inserId
}
// Update 修改信息
func (r *NeSoftwareImpl) Update(neSoftware model.NeSoftware) int64 {
rows := r.neSoftwareRepository.Update(neSoftware)
if rows > 0 {
// 更新同类型的新包版本
neVersions := NewNeVersionImpl.SelectList(model.NeVersion{
NeType: neSoftware.NeType,
Status: "3",
})
if len(neVersions) > 0 {
for _, neVersion := range neVersions {
neVersion.NewName = neSoftware.Name
neVersion.NewVersion = neSoftware.Version
neVersion.NewPath = neSoftware.Path
neVersion.Status = "3"
neVersion.UpdateBy = neSoftware.UpdateBy
NewNeVersionImpl.Update(neVersion)
}
}
}
return rows
}
// DeleteByIds 批量删除信息
func (r *NeSoftwareImpl) DeleteByIds(ids []string) (int64, error) {
// 检查是否存在
rows := r.neSoftwareRepository.SelectByIds(ids)
if len(rows) <= 0 {
return 0, fmt.Errorf("neSoftware.noData")
}
if len(rows) == len(ids) {
// 遍历软件包列表进行文件删除
for _, row := range rows {
// 检查文件是否存在
filePath := file.ParseUploadFilePath(row.Path)
if _, err := os.Stat(filePath); err != nil {
continue
}
os.Remove(filePath)
}
rows := r.neSoftwareRepository.DeleteByIds(ids)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一
func (r *NeSoftwareImpl) CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool {
uniqueId := r.neSoftwareRepository.CheckUniqueTypeAndNameAndVersion(model.NeSoftware{
NeType: neType,
Name: name,
Version: version,
})
if uniqueId == id {
return true
}
return uniqueId == ""
}
// UpdateVersions 更新软件包对应网元的新版本
func (r *NeSoftwareImpl) UpdateVersions(neSoftware model.NeSoftware, neVersion model.NeVersion) int64 {
var rows int64 = 0
// 更新同类型的新包版本
neVersions := NewNeVersionImpl.SelectList(neVersion)
if len(neVersions) > 0 {
for _, v := range neVersions {
v.NewName = neSoftware.Name
v.NewVersion = neSoftware.Version
v.NewPath = neSoftware.Path
v.Status = "3"
v.UpdateBy = neVersion.UpdateBy
rows += NewNeVersionImpl.Update(v)
}
}
return rows
}
// InstallToNeHost 安装包上传到网元主机执行安装命令
func (r *NeSoftwareImpl) InstallToNeHost(neSoftware model.NeSoftware, preinput map[string]string) (string, error) {
// 检查文件是否存在
localFilePath := file.ParseUploadFilePath(neSoftware.Path)
if _, err := os.Stat(localFilePath); err != nil {
return "", fmt.Errorf("file read failure")
}
fileName := filepath.Base(neSoftware.Path)
if strings.Contains(fileName, "*") {
fileName = strings.ReplaceAll(fileName, "*", "_")
}
nePath := "/tmp"
neFilePath := fmt.Sprintf("%s/%s", nePath, fileName)
// 网元主机的SSH客户端
sshClient, err := NewNeInfoImpl.NeRunSSHclient(neSoftware.NeType, neSoftware.NeId)
if err != nil {
return "", err
}
defer sshClient.Close()
// 网元主机的SSH客户端进行文件传输
sftpClient, err := sshClient.NewClientSFTP()
if err != nil {
return "", err
}
defer sftpClient.Close()
// 上传软件包到 /tmp
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
return "", fmt.Errorf("error uploading package")
}
// ========= 安装命令 start =========
// 命令终止结束标记
okFlagStr := fmt.Sprintf("%s software install successful!", neSoftware.NeType)
// 安装软件包
pkgCmdStr := fmt.Sprintf("sudo dpkg -i %s \n", neFilePath)
fileExt := filepath.Ext(strings.ToLower(fileName))
if strings.HasSuffix(fileExt, "rpm") {
pkgCmdStr = fmt.Sprintf("sudo rpm -Uvh %s \n", neFilePath)
}
// 预先参数
cmdStrArr := []string{pkgCmdStr}
if neSoftware.NeType == "IMS" {
if !strings.Contains(strings.ToLower(fileName), "ims") {
return "", fmt.Errorf("error file package not ims")
}
// P/I/S-CSCF Config 配置覆盖
if pisCSCF, ok := preinput["pisCSCF"]; ok && pisCSCF != "" {
cmdStrArr = append(cmdStrArr, fmt.Sprintf("%s \n", pisCSCF))
}
// 公网 PLMN地址
pubIP, pubIPOk := preinput["pubIP"]
mcc, mccOk := preinput["mcc"]
mnc, mncOk := preinput["mnc"]
if pubIPOk && pubIP != "" && mccOk && mcc != "" && mncOk && mnc != "" {
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo /usr/local/etc/ims/default/tools/modipplmn.sh %s %s %s \n", pubIP, mcc, mnc))
}
// 内网 服务地址
if priIP, ok := preinput["priIP"]; ok && priIP != "" {
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo /usr/local/etc/ims/default/tools/modintraip.sh %s \n", priIP))
}
cmdStrArr = append(cmdStrArr, "sudo ims-start")
// 10s后停止服务
cmdStrArr = append(cmdStrArr, "nohup sh -c \"sleep 15s && sudo ims-stop\" > /dev/null 2>&1 & \n")
} else if neSoftware.NeType == "OMC" {
cmdStrArr = append(cmdStrArr, "sudo /usr/local/omc/bin/omcsvc.sh restart \n")
// 10s后停止服务
cmdStrArr = append(cmdStrArr, "nohup sh -c \"sleep 15s && sudo /usr/local/omc/bin/omcsvc.sh stop\" > /dev/null 2>&1 & \n")
} else {
neTypeLower := strings.ToLower(neSoftware.NeType)
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo service %s restart \n", neTypeLower))
// 10s后停止服务
cmdStrArr = append(cmdStrArr, fmt.Sprintf("nohup sh -c \"sleep 15s && sudo service %s stop\" > /dev/null 2>&1 & \n", neTypeLower))
}
// 删除软件包
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo rm %s \n", neFilePath))
// 结束
cmdStrArr = append(cmdStrArr, fmt.Sprintf("echo '%s' \n", okFlagStr))
// ========= 安装命令 end =========
// ssh连接会话
clientSession, err := sshClient.NewClientSession(80, 24)
if err != nil {
return "", fmt.Errorf("neinfo ssh client session new err")
}
defer clientSession.Close()
firstRead := true // 首次命令进行记录日志信息
logMsg := "" // 日志信息
done := make(chan bool) // 完成信号
// 超时退出 30s
timeoutTicker := time.NewTicker(30 * time.Second)
defer timeoutTicker.Stop()
// 实时读取SSH消息直接输出
msTicker := time.NewTicker(100 * time.Millisecond)
defer msTicker.Stop()
go func() {
for {
select {
case <-timeoutTicker.C:
done <- true
return
case <-msTicker.C:
outputByte := clientSession.Read()
if len(outputByte) > 0 {
outputStr := string(outputByte)
// 非首次进行记录命令
if !firstRead {
logMsg += outputStr
}
// IMS预输入
if neSoftware.NeType == "IMS" && strings.Contains(outputStr, "(P/I/S-CSCF Config)? <y/n>") {
shiftElement := cmdStrArr[0] // 获取第一个元素
cmdStrArr = cmdStrArr[1:] // 将第一个元素从切片中移除
clientSession.Write(shiftElement)
continue
}
// 命令终止符后继续执行命令
if len(cmdStrArr) > 0 && strings.LastIndex(outputStr, "~$ ") > 2 {
if firstRead {
firstRead = false
}
shiftElement := cmdStrArr[0] // 获取第一个元素
cmdStrArr = cmdStrArr[1:] // 将第一个元素从切片中移除
clientSession.Write(shiftElement)
continue
}
// 最后输出的退出标记
if strings.LastIndex(outputStr, okFlagStr) > 5 {
done <- true
break
}
}
}
}
}()
// 等待写入协程完成
<-done
// 执行到最后语句的更新Version
if strings.LastIndex(logMsg, okFlagStr) > 5 {
verInfo := NewNeVersionImpl.SelectByNeTypeAndNeID(neSoftware.NeType, neSoftware.NeId)
if verInfo.NeId == neSoftware.NeId {
verInfo.Name = neSoftware.Name
verInfo.Version = neSoftware.Version
verInfo.Path = neSoftware.Path
verInfo.NewName = "-"
verInfo.NewVersion = "-"
verInfo.NewPath = "-"
verInfo.Status = "1"
NewNeVersionImpl.Update(verInfo)
}
}
return logMsg, nil
}