feat: 安装包上传到网元主机执行安装命令
This commit is contained in:
@@ -151,40 +151,44 @@ func (s *NeSoftwareController) Remove(c *gin.Context) {
|
|||||||
c.JSON(200, result.OkMsg(msg))
|
c.JSON(200, result.OkMsg(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网元软件包安装检查
|
// 网元软件包安装
|
||||||
//
|
//
|
||||||
// POST /checkInstall
|
// POST /install
|
||||||
func (s *NeSoftwareController) CheckInstall(c *gin.Context) {
|
func (s *NeSoftwareController) Install(c *gin.Context) {
|
||||||
language := ctx.AcceptLanguage(c)
|
language := ctx.AcceptLanguage(c)
|
||||||
var body model.NeSoftware
|
var body struct {
|
||||||
|
Action string `json:"action" binding:"required,oneof=install upgrade"` // 安装行为
|
||||||
|
Software model.NeSoftware `json:"software" binding:"required"` // 软件包信息
|
||||||
|
Preinput map[string]string `json:"preinput" binding:"required"` // 预先输入参数
|
||||||
|
}
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||||
if err != nil || body.HostId == "" {
|
if err != nil || body.Software.HostId == "" {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否存在软件包记录
|
// 检查是否存在软件包记录
|
||||||
neSoftwares := s.neSoftwareService.SelectList(model.NeSoftware{
|
neSoftwares := s.neSoftwareService.SelectList(model.NeSoftware{
|
||||||
NeType: body.NeType,
|
NeType: body.Software.NeType,
|
||||||
Name: body.Name,
|
Name: body.Software.Name,
|
||||||
Version: body.Version,
|
Version: body.Software.Version,
|
||||||
})
|
})
|
||||||
if len(neSoftwares) <= 0 {
|
if len(neSoftwares) <= 0 {
|
||||||
body.CreateBy = ctx.LoginUserToUserName(c)
|
body.Software.CreateBy = ctx.LoginUserToUserName(c)
|
||||||
body.ID = s.neSoftwareService.Insert(body)
|
body.Software.ID = s.neSoftwareService.Insert(body.Software)
|
||||||
} else {
|
} else {
|
||||||
neSoftware := neSoftwares[0]
|
neSoftware := neSoftwares[0]
|
||||||
neSoftware.Path = body.Path
|
neSoftware.Path = body.Software.Path
|
||||||
neSoftware.Description = body.Description
|
neSoftware.Description = body.Software.Description
|
||||||
neSoftware.UpdateBy = ctx.LoginUserToUserName(c)
|
neSoftware.UpdateBy = ctx.LoginUserToUserName(c)
|
||||||
s.neSoftwareService.Update(neSoftware)
|
s.neSoftwareService.Update(neSoftware)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 进行安装检查
|
// 进行安装检查
|
||||||
cmdStrArr, err := s.neSoftwareService.UploadToNeHost(body)
|
output, err := s.neSoftwareService.InstallToNeHost(body.Action, body.Software, body.Preinput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(cmdStrArr))
|
c.JSON(200, result.OkData(output))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ type INeSoftware interface {
|
|||||||
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一
|
// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一
|
||||||
CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool
|
CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool
|
||||||
|
|
||||||
// UploadToNeHost 安装包上传到网元主机
|
// InstallToNeHost 安装包上传到网元主机执行安装命令
|
||||||
// 返回执行命令步骤
|
//
|
||||||
UploadToNeHost(neSoftware model.NeSoftware) ([]string, error)
|
// action 安装行为:install upgrade
|
||||||
|
InstallToNeHost(action string, neSoftware model.NeSoftware, preinput map[string]string) (string, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"be.ems/src/framework/utils/file"
|
"be.ems/src/framework/utils/file"
|
||||||
"be.ems/src/framework/utils/ssh"
|
"be.ems/src/framework/utils/ssh"
|
||||||
@@ -47,26 +48,66 @@ func (r *NeSoftwareImpl) SelectById(id string) model.NeSoftware {
|
|||||||
|
|
||||||
// Insert 新增信息
|
// Insert 新增信息
|
||||||
func (r *NeSoftwareImpl) Insert(neSoftware model.NeSoftware) string {
|
func (r *NeSoftwareImpl) Insert(neSoftware model.NeSoftware) string {
|
||||||
return r.neSoftwareRepository.Insert(neSoftware)
|
inserId := r.neSoftwareRepository.Insert(neSoftware)
|
||||||
|
if inserId != "" {
|
||||||
|
// 更新同类型的新包版本
|
||||||
|
neVersions := NewNeVersionImpl.SelectList(model.NeVersion{NeType: neSoftware.NeType})
|
||||||
|
if len(neVersions) > 0 {
|
||||||
|
for _, neVersion := range neVersions {
|
||||||
|
neVersion.NewVersion = neSoftware.Version
|
||||||
|
neVersion.NewPath = neSoftware.Path
|
||||||
|
neVersion.Status = "3"
|
||||||
|
neVersion.UpdateBy = neSoftware.CreateBy
|
||||||
|
NewNeVersionImpl.Update(neVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inserId
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update 修改信息
|
// Update 修改信息
|
||||||
func (r *NeSoftwareImpl) Update(neSoftware model.NeSoftware) int64 {
|
func (r *NeSoftwareImpl) Update(neSoftware model.NeSoftware) int64 {
|
||||||
return r.neSoftwareRepository.Update(neSoftware)
|
rows := r.neSoftwareRepository.Update(neSoftware)
|
||||||
|
if rows > 0 {
|
||||||
|
// 更新同类型的新包版本
|
||||||
|
neVersions := NewNeVersionImpl.SelectList(model.NeVersion{
|
||||||
|
NeType: neSoftware.NeType,
|
||||||
|
NewPath: neSoftware.Path,
|
||||||
|
Status: "3",
|
||||||
|
})
|
||||||
|
if len(neVersions) > 0 {
|
||||||
|
for _, neVersion := range neVersions {
|
||||||
|
neVersion.NewVersion = neSoftware.Version
|
||||||
|
neVersion.UpdateBy = neSoftware.UpdateBy
|
||||||
|
NewNeVersionImpl.Update(neVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rows
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteByIds 批量删除信息
|
// DeleteByIds 批量删除信息
|
||||||
func (r *NeSoftwareImpl) DeleteByIds(ids []string) (int64, error) {
|
func (r *NeSoftwareImpl) DeleteByIds(ids []string) (int64, error) {
|
||||||
// 检查是否存在
|
// 检查是否存在
|
||||||
rowIds := r.neSoftwareRepository.SelectByIds(ids)
|
rows := r.neSoftwareRepository.SelectByIds(ids)
|
||||||
if len(rowIds) <= 0 {
|
if len(rows) <= 0 {
|
||||||
return 0, fmt.Errorf("neSoftware.noData")
|
return 0, fmt.Errorf("neSoftware.noData")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rowIds) == len(ids) {
|
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)
|
rows := r.neSoftwareRepository.DeleteByIds(ids)
|
||||||
return rows, nil
|
return rows, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除信息失败!
|
// 删除信息失败!
|
||||||
return 0, fmt.Errorf("delete fail")
|
return 0, fmt.Errorf("delete fail")
|
||||||
}
|
}
|
||||||
@@ -84,14 +125,14 @@ func (r *NeSoftwareImpl) CheckUniqueTypeAndNameAndVersion(neType, name, version,
|
|||||||
return uniqueId == ""
|
return uniqueId == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadToNeHost 安装包上传到网元主机
|
// InstallToNeHost 安装包上传到网元主机执行安装命令
|
||||||
// 返回执行命令步骤
|
//
|
||||||
func (r *NeSoftwareImpl) UploadToNeHost(neSoftware model.NeSoftware) ([]string, error) {
|
// action 安装行为:install upgrade
|
||||||
cmdStrArr := []string{}
|
func (r *NeSoftwareImpl) InstallToNeHost(action string, neSoftware model.NeSoftware, preinput map[string]string) (string, error) {
|
||||||
// 检查文件是否存在
|
// 检查文件是否存在
|
||||||
filePath := file.ParseUploadFilePath(neSoftware.Path)
|
filePath := file.ParseUploadFilePath(neSoftware.Path)
|
||||||
if _, err := os.Stat(filePath); err != nil {
|
if _, err := os.Stat(filePath); err != nil {
|
||||||
return cmdStrArr, fmt.Errorf("file read failure")
|
return "", fmt.Errorf("file read failure")
|
||||||
}
|
}
|
||||||
fileName := filepath.Base(neSoftware.Path)
|
fileName := filepath.Base(neSoftware.Path)
|
||||||
if strings.Contains(fileName, "*") {
|
if strings.Contains(fileName, "*") {
|
||||||
@@ -103,35 +144,132 @@ func (r *NeSoftwareImpl) UploadToNeHost(neSoftware model.NeSoftware) ([]string,
|
|||||||
// 检查网元主机
|
// 检查网元主机
|
||||||
neHostInfo := NewNeHostImpl.SelectById(neSoftware.HostId)
|
neHostInfo := NewNeHostImpl.SelectById(neSoftware.HostId)
|
||||||
if neHostInfo.HostType != "ssh" || neHostInfo.HostID != neSoftware.HostId {
|
if neHostInfo.HostType != "ssh" || neHostInfo.HostID != neSoftware.HostId {
|
||||||
return cmdStrArr, fmt.Errorf("no found host info")
|
return "", fmt.Errorf("no found host info")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传软件包到 /tmp
|
// 上传软件包到 /tmp
|
||||||
if err := ssh.FileSCPLocalToNe(neHostInfo.Addr, filePath, neFilePath); err != nil {
|
if err := ssh.FileSCPLocalToNe(neHostInfo.Addr, filePath, neFilePath); err != nil {
|
||||||
return cmdStrArr, fmt.Errorf("error uploading package")
|
return "", fmt.Errorf("error uploading package")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========= 安装命令 start =========
|
||||||
|
cmdStrArr := []string{}
|
||||||
|
// 命令终止结束标记
|
||||||
|
okFlagStr := fmt.Sprintf("%s software %s successful!", neSoftware.NeType, action)
|
||||||
// 安装软件包
|
// 安装软件包
|
||||||
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo dpkg -i %s", neFilePath))
|
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo dpkg -i %s \n", neFilePath))
|
||||||
|
|
||||||
|
// 预先参数
|
||||||
if neSoftware.NeType == "IMS" {
|
if neSoftware.NeType == "IMS" {
|
||||||
|
if !strings.Contains(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地址
|
// 公网 PLMN地址
|
||||||
cmdStrArr = append(cmdStrArr, "sudo /usr/local/etc/ims/default/tools/modipplmn.sh {PUBIP} {MCC} {MNC}")
|
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))
|
||||||
|
}
|
||||||
// 内网 服务地址
|
// 内网 服务地址
|
||||||
cmdStrArr = append(cmdStrArr, "sudo /usr/local/etc/ims/default/tools/modintraip.sh {PRIIP}")
|
if priIP, ok := preinput["priIP"]; ok && priIP != "" {
|
||||||
// 10s后停止服务
|
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo /usr/local/etc/ims/default/tools/modintraip.sh %s \n", priIP))
|
||||||
|
}
|
||||||
cmdStrArr = append(cmdStrArr, "sudo ims-start")
|
cmdStrArr = append(cmdStrArr, "sudo ims-start")
|
||||||
cmdStrArr = append(cmdStrArr, `nohup sh -c "sleep 10s && sudo ims-stop" > /dev/null 2>&1 &`)
|
|
||||||
} else {
|
|
||||||
// 10s后停止服务
|
// 10s后停止服务
|
||||||
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo service %s restart", strings.ToLower(neSoftware.NeType)))
|
if action == "install" {
|
||||||
cmdStrArr = append(cmdStrArr, fmt.Sprintf(`nohup sh -c "sleep 10s && sudo service %s stop" > /dev/null 2>&1 &`, strings.ToLower(neSoftware.NeType)))
|
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后停止服务
|
||||||
|
if action == "install" {
|
||||||
|
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后停止服务
|
||||||
|
if action == "install" {
|
||||||
|
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", neFilePath))
|
cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo rm %s \n", neFilePath))
|
||||||
|
|
||||||
// 结束
|
// 结束
|
||||||
cmdStrArr = append(cmdStrArr, fmt.Sprintf("echo '%s software install successful!'", neSoftware.NeType))
|
cmdStrArr = append(cmdStrArr, fmt.Sprintf("echo '%s' \n", okFlagStr))
|
||||||
return cmdStrArr, nil
|
// ========= 安装命令 end =========
|
||||||
|
|
||||||
|
// ssh连接客户端
|
||||||
|
var connSSH ssh.ConnSSH
|
||||||
|
neHostInfo.CopyTo(&connSSH)
|
||||||
|
client, err := connSSH.NewClient()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("neinfo ssh client new err")
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
// ssh连接会话
|
||||||
|
clientSession, err := client.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) // 完成信号
|
||||||
|
// 实时读取SSH消息直接输出
|
||||||
|
msTicker := time.NewTicker(100 * time.Millisecond)
|
||||||
|
defer msTicker.Stop()
|
||||||
|
// 超时退出
|
||||||
|
timeoutTicker := time.NewTicker(30 * time.Second)
|
||||||
|
defer timeoutTicker.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
|
||||||
|
return logMsg, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user