From 715cf8ab188ee2adbdeb0f5aeae2a1d85254bef3 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 1 Apr 2024 16:57:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BD=91=E5=85=83=E8=BD=AF=E4=BB=B6?= =?UTF-8?q?=E5=8C=85=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network_element/controller/ne_software.go | 56 +++++++------ .../network_element/model/ne_software.go | 25 +++--- .../network_element/repository/ne_software.go | 4 +- .../repository/ne_software.impl.go | 71 +++++++--------- .../network_element/service/ne_software.go | 12 ++- .../service/ne_software.impl.go | 80 ++++++++++++++----- 6 files changed, 142 insertions(+), 106 deletions(-) diff --git a/src/modules/network_element/controller/ne_software.go b/src/modules/network_element/controller/ne_software.go index 1001392f..03d1614c 100644 --- a/src/modules/network_element/controller/ne_software.go +++ b/src/modules/network_element/controller/ne_software.go @@ -49,7 +49,7 @@ func (s *NeSoftwareController) Info(c *gin.Context) { neSoftware := s.neSoftwareService.SelectById(softwareId) if neSoftware.ID != softwareId { - // 没有可访问网元版本数据! + // 没有可访问网元包信息数据! c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData"))) return } @@ -64,20 +64,21 @@ func (s *NeSoftwareController) Add(c *gin.Context) { language := ctx.AcceptLanguage(c) var body model.NeSoftware err := c.ShouldBindBodyWith(&body, binding.JSON) - if err != nil || body.ID != "" { + if err != nil || body.Path == "" || body.ID != "" { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 检查属性值唯一 - uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndFileNameAndVersion(body.NeType, body.FileName, body.Version, "") + uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndNameAndVersion(body.NeType, body.Name, body.Version, "") if !uniqueSoftware { // 网元软件包操作【%s】失败,网元类型与文件名版本已存在 - msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.FileName}) + msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.Name}) c.JSON(200, result.ErrMsg(msg)) return } + body.CreateBy = ctx.LoginUserToUserName(c) insertId := s.neSoftwareService.Insert(body) if insertId != "" { c.JSON(200, result.Ok(nil)) @@ -93,16 +94,16 @@ func (s *NeSoftwareController) Edit(c *gin.Context) { language := ctx.AcceptLanguage(c) var body model.NeSoftware err := c.ShouldBindBodyWith(&body, binding.JSON) - if err != nil || body.ID == "" { + if err != nil || body.Path == "" || body.ID == "" { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 检查属性值唯一 - uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndFileNameAndVersion(body.NeType, body.FileName, body.Version, body.ID) + uniqueSoftware := s.neSoftwareService.CheckUniqueTypeAndNameAndVersion(body.NeType, body.Name, body.Version, body.ID) if !uniqueSoftware { // 网元软件包操作【%s】失败,网元类型与文件名版本已存在 - msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.FileName}) + msg := i18n.TTemplate(language, "neSoftware.errKeyExists", map[string]any{"name": body.Name}) c.JSON(200, result.ErrMsg(msg)) return } @@ -110,11 +111,12 @@ func (s *NeSoftwareController) Edit(c *gin.Context) { // 检查是否存在 neSoftware := s.neSoftwareService.SelectById(body.ID) if neSoftware.ID != body.ID { - // 没有可访问网元版本数据! + // 没有可访问网元包信息数据! c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData"))) return } + body.UpdateBy = ctx.LoginUserToUserName(c) rows := s.neSoftwareService.Update(body) if rows > 0 { c.JSON(200, result.Ok(nil)) @@ -149,32 +151,40 @@ func (s *NeSoftwareController) Remove(c *gin.Context) { c.JSON(200, result.OkMsg(msg)) } -// 网元软件包安装 +// 网元软件包安装检查 // -// POST /install -func (s *NeSoftwareController) Install(c *gin.Context) { +// POST /checkInstall +func (s *NeSoftwareController) CheckInstall(c *gin.Context) { language := ctx.AcceptLanguage(c) var body model.NeSoftware err := c.ShouldBindBodyWith(&body, binding.JSON) - if err != nil { + if err != nil || body.HostId == "" { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } - // 检查是否存在 - neSoftwares := s.neSoftwareService.SelectList(body) - if len(neSoftwares) == 0 { - // 没有可访问网元版本数据! - c.JSON(200, result.ErrMsg(i18n.TKey(language, "neSoftware.noData"))) - return + // 检查是否存在软件包记录 + neSoftwares := s.neSoftwareService.SelectList(model.NeSoftware{ + NeType: body.NeType, + Name: body.Name, + Version: body.Version, + }) + if len(neSoftwares) <= 0 { + body.CreateBy = ctx.LoginUserToUserName(c) + body.ID = s.neSoftwareService.Insert(body) + } else { + neSoftware := neSoftwares[0] + neSoftware.Path = body.Path + neSoftware.Description = body.Description + neSoftware.UpdateBy = ctx.LoginUserToUserName(c) + s.neSoftwareService.Update(neSoftware) } - neSoftware := neSoftwares[0] - // 进行安装 - output, err := s.neSoftwareService.Install(neSoftware) + // 进行安装检查 + cmdStrArr, err := s.neSoftwareService.UploadToNeHost(body) if err != nil { - c.JSON(200, result.OkData(output)) + c.JSON(200, result.ErrMsg(err.Error())) return } - c.JSON(200, result.Err(nil)) + c.JSON(200, result.OkData(cmdStrArr)) } diff --git a/src/modules/network_element/model/ne_software.go b/src/modules/network_element/model/ne_software.go index afb6dff6..d0166163 100644 --- a/src/modules/network_element/model/ne_software.go +++ b/src/modules/network_element/model/ne_software.go @@ -1,18 +1,21 @@ package model -import "time" - // NeSoftware 网元软件包 ne_software type NeSoftware struct { - ID string `json:"id" gorm:"id"` - NeType string `json:"neType" gorm:"ne_type" binding:"required"` // 网元类型 - FileName string `json:"fileName" gorm:"file_name" binding:"required"` // 包名称 - Path string `json:"path" gorm:"path"` // 包路径 - Version string `json:"version" gorm:"version" binding:"required"` // 包版本 - Md5Sum string `json:"md5Sum" gorm:"md5_sum"` // --无使用 md5签名 - Status string `json:"status" gorm:"status"` // --无使用 - Comment string `json:"comment" gorm:"comment"` // 包说明 - UpdateTime time.Time `json:"updateTime" gorm:"update_time"` // 上传时间 + ID string `json:"id" gorm:"id"` + NeType string `json:"neType" gorm:"ne_type" binding:"required"` // 网元类型 + Name string `json:"name" gorm:"name" binding:"required"` // 包名称 + Path string `json:"path" gorm:"path"` // 包路径 + Version string `json:"version" gorm:"version" binding:"required"` // 包版本 + Description string `json:"description" gorm:"description"` // 包说明 + CreateBy string `json:"createBy" gorm:"column:create_by"` // 创建者 + CreateTime int64 `json:"createTime" gorm:"column:create_time"` // 创建时间 + UpdateBy string `json:"updateBy" gorm:"column:update_by"` // 更新者 + UpdateTime int64 `json:"updateTime" gorm:"column:update_time"` // 更新时间 + + // ====== 非数据库字段属性 ====== + + HostId string `json:"hostId,omitempty" gorm:"-"` // 已记录的主机ID } // TableName 表名称 diff --git a/src/modules/network_element/repository/ne_software.go b/src/modules/network_element/repository/ne_software.go index 98947d20..f6d0f23e 100644 --- a/src/modules/network_element/repository/ne_software.go +++ b/src/modules/network_element/repository/ne_software.go @@ -22,6 +22,6 @@ type INeSoftware interface { // DeleteByIds 批量删除信息 DeleteByIds(ids []string) int64 - // CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一 - CheckUniqueTypeAndFileNameAndVersion(neSoftware model.NeSoftware) string + // CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一 + CheckUniqueTypeAndNameAndVersion(neSoftware model.NeSoftware) string } diff --git a/src/modules/network_element/repository/ne_software.impl.go b/src/modules/network_element/repository/ne_software.impl.go index 3116b52e..133dd420 100644 --- a/src/modules/network_element/repository/ne_software.impl.go +++ b/src/modules/network_element/repository/ne_software.impl.go @@ -15,18 +15,19 @@ import ( // 实例化数据层 NewNeSoftware 结构体 var NewNeSoftwareImpl = &NeSoftwareImpl{ selectSql: `select - id, ne_type, file_name, path, version, md5_sum, status, comment, update_time + id, ne_type, name, path, version, description, create_by, create_time, update_by, update_time from ne_software`, resultMap: map[string]string{ "id": "ID", "ne_type": "NeType", - "file_name": "FileName", + "name": "Name", "path": "Path", "version": "Version", - "md5_sum": "Md5Sum", - "status": "Status", - "comment": "Comment", + "description": "Description", + "create_by": "CreateBy", + "create_time": "CreateTime", + "update_by": "UpdateBy", "update_time": "UpdateTime", }, } @@ -63,8 +64,8 @@ func (r *NeSoftwareImpl) SelectPage(query map[string]any) map[string]any { conditions = append(conditions, "ne_type = ?") params = append(params, strings.Trim(v.(string), " ")) } - if v, ok := query["fileName"]; ok && v != "" { - conditions = append(conditions, "file_name like concat(?, '%')") + if v, ok := query["name"]; ok && v != "" { + conditions = append(conditions, "name like concat(?, '%')") params = append(params, strings.Trim(v.(string), " ")) } if v, ok := query["version"]; ok && v != "" { @@ -133,9 +134,9 @@ func (r *NeSoftwareImpl) SelectList(neSoftware model.NeSoftware) []model.NeSoftw conditions = append(conditions, "version = ?") params = append(params, neSoftware.Version) } - if neSoftware.FileName != "" { - conditions = append(conditions, "file_name like concat(?, '%')") - params = append(params, neSoftware.FileName) + if neSoftware.Name != "" { + conditions = append(conditions, "name like concat(?, '%')") + params = append(params, neSoftware.Name) } // 构建查询条件语句 @@ -169,8 +170,8 @@ func (r *NeSoftwareImpl) SelectByIds(cmdIds []string) []model.NeSoftware { return r.convertResultRows(results) } -// CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一 -func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neSoftware model.NeSoftware) string { +// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一 +func (r *NeSoftwareImpl) CheckUniqueTypeAndNameAndVersion(neSoftware model.NeSoftware) string { // 查询条件拼接 var conditions []string var params []any @@ -182,9 +183,9 @@ func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neSoftware model.N conditions = append(conditions, "version = ?") params = append(params, neSoftware.Version) } - if neSoftware.FileName != "" { - conditions = append(conditions, "file_name = ?") - params = append(params, neSoftware.FileName) + if neSoftware.Name != "" { + conditions = append(conditions, "name = ?") + params = append(params, neSoftware.Name) } // 构建查询条件语句 @@ -215,8 +216,8 @@ func (r *NeSoftwareImpl) Insert(neSoftware model.NeSoftware) string { if neSoftware.NeType != "" { params["ne_type"] = neSoftware.NeType } - if neSoftware.FileName != "" { - params["file_name"] = neSoftware.FileName + if neSoftware.Name != "" { + params["name"] = neSoftware.Name } if neSoftware.Path != "" { params["path"] = neSoftware.Path @@ -224,19 +225,11 @@ func (r *NeSoftwareImpl) Insert(neSoftware model.NeSoftware) string { if neSoftware.Version != "" { params["version"] = neSoftware.Version } - if neSoftware.Md5Sum != "" { - params["md5_sum"] = neSoftware.Md5Sum + params["description"] = neSoftware.Description + if neSoftware.CreateBy != "" { + params["create_by"] = neSoftware.CreateBy + params["create_time"] = time.Now().UnixMilli() } - if neSoftware.Status != "" { - params["status"] = neSoftware.Status - } - if neSoftware.Comment != "" { - params["comment"] = neSoftware.Comment - } - if neSoftware.Status != "" { - params["status"] = neSoftware.Status - } - params["update_time"] = time.Now() // 构建执行语句 keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params) @@ -272,8 +265,8 @@ func (r *NeSoftwareImpl) Update(neSoftware model.NeSoftware) int64 { if neSoftware.NeType != "" { params["ne_type"] = neSoftware.NeType } - if neSoftware.FileName != "" { - params["file_name"] = neSoftware.FileName + if neSoftware.Name != "" { + params["name"] = neSoftware.Name } if neSoftware.Path != "" { params["path"] = neSoftware.Path @@ -281,19 +274,11 @@ func (r *NeSoftwareImpl) Update(neSoftware model.NeSoftware) int64 { if neSoftware.Version != "" { params["version"] = neSoftware.Version } - if neSoftware.Md5Sum != "" { - params["md5_sum"] = neSoftware.Md5Sum + params["description"] = neSoftware.Description + if neSoftware.UpdateBy != "" { + params["update_by"] = neSoftware.UpdateBy + params["update_time"] = time.Now().UnixMilli() } - if neSoftware.Status != "" { - params["status"] = neSoftware.Status - } - if neSoftware.Comment != "" { - params["comment"] = neSoftware.Comment - } - if neSoftware.Status != "" { - params["status"] = neSoftware.Status - } - params["update_time"] = time.Now() // 构建执行语句 keys, values := repo.KeyValueByUpdate(params) diff --git a/src/modules/network_element/service/ne_software.go b/src/modules/network_element/service/ne_software.go index c4936ac2..5f5e10f2 100644 --- a/src/modules/network_element/service/ne_software.go +++ b/src/modules/network_element/service/ne_software.go @@ -22,12 +22,10 @@ type INeSoftware interface { // DeleteByIds 批量删除信息 DeleteByIds(ids []string) (int64, error) - // SelectByVersionAndPath 通过文件版本和路径查询 - SelectByVersionAndPath(version, path string) model.NeSoftware + // CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一 + CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool - // CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一 - CheckUniqueTypeAndFileNameAndVersion(neType, fileName, version, id string) bool - - // Install 安装软件包 - Install(neSoftware model.NeSoftware) (string, error) + // UploadToNeHost 安装包上传到网元主机 + // 返回执行命令步骤 + UploadToNeHost(neSoftware model.NeSoftware) ([]string, error) } diff --git a/src/modules/network_element/service/ne_software.impl.go b/src/modules/network_element/service/ne_software.impl.go index 9978f4bf..77783a33 100644 --- a/src/modules/network_element/service/ne_software.impl.go +++ b/src/modules/network_element/service/ne_software.impl.go @@ -2,7 +2,12 @@ package service import ( "fmt" + "os" + "path/filepath" + "strings" + "be.ems/src/framework/utils/file" + "be.ems/src/framework/utils/ssh" "be.ems/src/modules/network_element/model" "be.ems/src/modules/network_element/repository" ) @@ -66,24 +71,12 @@ func (r *NeSoftwareImpl) DeleteByIds(ids []string) (int64, error) { return 0, fmt.Errorf("delete fail") } -// SelectByVersionAndPath 通过文件版本和路径查询 -func (r *NeSoftwareImpl) SelectByVersionAndPath(version, path string) model.NeSoftware { - neSoftwares := r.neSoftwareRepository.SelectList(model.NeSoftware{ +// CheckUniqueTypeAndNameAndVersion 校验网元类型和文件名版本是否唯一 +func (r *NeSoftwareImpl) CheckUniqueTypeAndNameAndVersion(neType, name, version, id string) bool { + uniqueId := r.neSoftwareRepository.CheckUniqueTypeAndNameAndVersion(model.NeSoftware{ + NeType: neType, + Name: name, Version: version, - Path: path, - }) - if len(neSoftwares) > 0 { - return neSoftwares[0] - } - return model.NeSoftware{} -} - -// CheckUniqueTypeAndFileNameAndVersion 校验网元类型和文件名版本是否唯一 -func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neType, fileName, version, id string) bool { - uniqueId := r.neSoftwareRepository.CheckUniqueTypeAndFileNameAndVersion(model.NeSoftware{ - NeType: neType, - FileName: fileName, - Version: version, }) if uniqueId == id { return true @@ -91,7 +84,54 @@ func (r *NeSoftwareImpl) CheckUniqueTypeAndFileNameAndVersion(neType, fileName, return uniqueId == "" } -// Install 安装软件包 -func (r *NeSoftwareImpl) Install(neSoftware model.NeSoftware) (string, error) { - return "", nil +// UploadToNeHost 安装包上传到网元主机 +// 返回执行命令步骤 +func (r *NeSoftwareImpl) UploadToNeHost(neSoftware model.NeSoftware) ([]string, error) { + cmdStrArr := []string{} + // 检查文件是否存在 + filePath := file.ParseUploadFilePath(neSoftware.Path) + if _, err := os.Stat(filePath); err != nil { + return cmdStrArr, 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) + + // 检查网元主机 + neHostInfo := NewNeHostImpl.SelectById(neSoftware.HostId) + if neHostInfo.HostType != "ssh" || neHostInfo.HostID != neSoftware.HostId { + return cmdStrArr, fmt.Errorf("no found host info") + } + + // 上传软件包到 /tmp + if err := ssh.FileSCPLocalToNe(neHostInfo.Addr, filePath, neFilePath); err != nil { + return cmdStrArr, fmt.Errorf("error uploading package") + } + + // 安装软件包 + cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo dpkg -i %s", neFilePath)) + + if neSoftware.NeType == "IMS" { + // 公网 PLMN地址 + cmdStrArr = append(cmdStrArr, "sudo /usr/local/etc/ims/default/tools/modipplmn.sh {PUBIP} {MCC} {MNC}") + // 内网 服务地址 + cmdStrArr = append(cmdStrArr, "sudo /usr/local/etc/ims/default/tools/modintraip.sh {PRIIP}") + // 10s后停止服务 + cmdStrArr = append(cmdStrArr, "sudo ims-start") + cmdStrArr = append(cmdStrArr, `nohup sh -c "sleep 10s && sudo ims-stop" > /dev/null 2>&1 &`) + } else { + // 10s后停止服务 + cmdStrArr = append(cmdStrArr, fmt.Sprintf("sudo service %s restart", strings.ToLower(neSoftware.NeType))) + 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, fmt.Sprintf("sudo rm %s", neFilePath)) + + // 结束 + cmdStrArr = append(cmdStrArr, fmt.Sprintf("echo '%s software install successful!'", neSoftware.NeType)) + return cmdStrArr, nil }