feat: 新增网元端文件列表获取和下载
This commit is contained in:
83
src/framework/utils/ssh/files.go
Normal file
83
src/framework/utils/ssh/files.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"ems.agt/src/framework/cmd"
|
||||
"ems.agt/src/framework/config"
|
||||
"ems.agt/src/framework/utils/parse"
|
||||
)
|
||||
|
||||
// FileListRow 文件列表行数据
|
||||
type FileListRow struct {
|
||||
FileMode string `json:"fileMode"` // 文件的权限
|
||||
LinkCount int64 `json:"linkCount"` // 硬链接数目
|
||||
Owner string `json:"owner"` // 所属用户
|
||||
Group string `json:"group"` // 所属组
|
||||
Size string `json:"size"` // 文件的大小
|
||||
ModifiedTime int64 `json:"modifiedTime"` // 最后修改时间,单位为秒
|
||||
FileName string `json:"fileName"` // 文件的名称
|
||||
}
|
||||
|
||||
// 文件列表
|
||||
// neIp 网元IP空字符串为本地
|
||||
// search 文件名后模糊*
|
||||
//
|
||||
// return 目录大小,行记录,异常
|
||||
func FileList(path, neIp, search string) (string, []FileListRow, error) {
|
||||
total := ""
|
||||
var rows []FileListRow
|
||||
rowStr := ""
|
||||
|
||||
// 发送命令
|
||||
searchStr := ""
|
||||
if search != "" {
|
||||
searchStr = search + "*"
|
||||
}
|
||||
pathStr := fmt.Sprintf("cd %s \n", path)
|
||||
cmdStr := fmt.Sprintf("ls -lht --time-style=+%%s %s \n", searchStr)
|
||||
|
||||
// 是否远程读取
|
||||
if neIp != "" {
|
||||
usernameNe := config.Get("ne.user").(string) // 网元统一用户
|
||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neIp)
|
||||
resultStr, err := cmd.ExecWithCheck("ssh", sshHost, pathStr, cmdStr)
|
||||
if err != nil {
|
||||
return total, rows, err
|
||||
}
|
||||
rowStr = resultStr
|
||||
} else {
|
||||
resultStr, err := cmd.Execf(pathStr, cmdStr)
|
||||
if err != nil {
|
||||
return total, rows, err
|
||||
}
|
||||
rowStr = resultStr
|
||||
}
|
||||
|
||||
// 遍历组装
|
||||
rowStrList := strings.Split(rowStr, "\n")
|
||||
for i, rowStr := range rowStrList {
|
||||
if rowStr == "" {
|
||||
continue
|
||||
}
|
||||
// 使用空格对字符串进行切割
|
||||
fields := strings.Fields(rowStr)
|
||||
|
||||
if i == 0 {
|
||||
total = fields[1]
|
||||
continue
|
||||
}
|
||||
// 提取各个字段的值
|
||||
rows = append(rows, FileListRow{
|
||||
FileMode: fields[0],
|
||||
LinkCount: parse.Number(fields[1]),
|
||||
Owner: fields[2],
|
||||
Group: fields[3],
|
||||
Size: fields[4],
|
||||
ModifiedTime: parse.Number(fields[5]),
|
||||
FileName: fields[6],
|
||||
})
|
||||
}
|
||||
return total, rows, nil
|
||||
}
|
||||
@@ -6,44 +6,39 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"ems.agt/lib/core/conf"
|
||||
"ems.agt/lib/log"
|
||||
"ems.agt/src/framework/config"
|
||||
"ems.agt/src/framework/logger"
|
||||
)
|
||||
|
||||
// 网元NE 文件复制到远程文件
|
||||
func FileSCPLocalToNe(neIp, localPath, nePath string) error {
|
||||
usernameNe := conf.Get("ne.user").(string)
|
||||
usernameNe := config.Get("ne.user").(string)
|
||||
// scp /path/to/local/file.txt user@remote-server:/path/to/remote/directory/
|
||||
neDir := fmt.Sprintf("%s@%s:%s", usernameNe, neIp, nePath)
|
||||
cmd := exec.Command("scp", "-r", localPath, neDir)
|
||||
out, err := cmd.CombinedOutput()
|
||||
_, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Errorf("FileSCPLocalToNe %s", err.Error())
|
||||
return err
|
||||
}
|
||||
log.Infof("FileSCPLocalToNe %s", string(out))
|
||||
return nil
|
||||
}
|
||||
|
||||
// 网元NE 远程文件复制到本地文件
|
||||
func FileSCPNeToLocal(neIp, nePath, localPath string) error {
|
||||
// 获取文件所在的目录路径
|
||||
dirPath := filepath.Dir(localPath)
|
||||
|
||||
// 确保文件夹路径存在
|
||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Errorf("FileSCPNeToLocal MkdirAll err %v", err)
|
||||
if err := os.MkdirAll(filepath.Dir(localPath), 0750); err != nil {
|
||||
logger.Errorf("FileSCPNeToLocal MkdirAll err %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
usernameNe := conf.Get("ne.user").(string)
|
||||
usernameNe := config.Get("ne.user").(string)
|
||||
// scp user@remote-server:/path/to/remote/directory/ /path/to/local/file.txt
|
||||
neDir := fmt.Sprintf("%s@%s:%s", usernameNe, neIp, nePath)
|
||||
cmd := exec.Command("scp", "-r", neDir, localPath)
|
||||
out, err := cmd.CombinedOutput()
|
||||
_, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Errorf("FileSCPNeToLocal %s", err.Error())
|
||||
return err
|
||||
}
|
||||
log.Infof("FileSCPNeToLocal %s", string(out))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -66,3 +66,73 @@ func (s *NeActionController) PushFile(c *gin.Context) {
|
||||
neFilePath := fmt.Sprintf("%s/%s", nePath, fileName)
|
||||
c.JSON(200, result.OkData(filepath.ToSlash(neFilePath)))
|
||||
}
|
||||
|
||||
// 从网元端获取文件
|
||||
//
|
||||
// GET /pullFile
|
||||
func (s *NeActionController) PullFile(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys struct {
|
||||
NeType string `form:"neType" binding:"required"`
|
||||
NeID string `form:"neId" binding:"required"`
|
||||
Path string `form:"path" binding:"required"`
|
||||
FileName string `form:"fileName" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
nePath := fmt.Sprintf("%s/%s", querys.Path, querys.FileName)
|
||||
localPath := fmt.Sprintf("/tmp/omc/pullFile/%s", querys.FileName)
|
||||
err := ssh.FileSCPNeToLocal(neInfo.IP, nePath, localPath)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
c.FileAttachment(localPath, querys.FileName)
|
||||
}
|
||||
|
||||
// 网元端文件列表
|
||||
//
|
||||
// GET /files
|
||||
func (s *NeActionController) Files(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys struct {
|
||||
NeType string `form:"neType" binding:"required"`
|
||||
NeID string `form:"neId" binding:"required"`
|
||||
Path string `form:"path" binding:"required"`
|
||||
PageNum int64 `form:"pageNum" binding:"required"`
|
||||
PageSize int64 `form:"pageSize" binding:"required"`
|
||||
Search string `form:"search"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
total, rows, err := ssh.FileList(querys.Path, neInfo.IP, querys.Search)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
c.JSON(200, result.OkData(map[string]any{
|
||||
"path": querys.Path,
|
||||
"total": total,
|
||||
"rows": rows,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -25,7 +25,14 @@ func Setup(router *gin.Engine) {
|
||||
// 网元处理
|
||||
neActionGroup := neGroup.Group("/action")
|
||||
{
|
||||
// 发送文件到网元服务器
|
||||
neActionGroup.GET("/files",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewNeAction.Files,
|
||||
)
|
||||
neActionGroup.GET("/pullFile",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewNeAction.PullFile,
|
||||
)
|
||||
neActionGroup.POST("/pushFile",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neAction", collectlogs.BUSINESS_TYPE_IMPORT)),
|
||||
|
||||
Reference in New Issue
Block a user