1
0
Files
omc_api/features/trace/tcpdump.go
2023-10-27 09:40:53 +08:00

340 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package trace
import (
"fmt"
"net"
"net/http"
"strings"
"time"
"ems.agt/lib/core/conf"
"ems.agt/lib/core/utils/ctx"
"ems.agt/lib/core/vo/result"
"ems.agt/lib/dborm"
"ems.agt/lib/log"
"ems.agt/restagent/config"
"ems.agt/src/framework/cmd"
"ems.agt/src/framework/utils/ssh"
)
var (
UriTcpdumpTask = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeTask"
CustomUriTcpdumpTask = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeTask" // decode message api
UriTcpdumpPcapDownload = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpPcapDownload"
CustomUriTcpdumpPcapDownload = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpPcapDownload" // decode message api
UriTcpdumpNeUPFTask = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeUPFTask"
CustomUriTcpdumpNeUPFTask = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeUPFTask" // decode message api
)
// NeInfo 网元信息
func NeInfo(neType, neId string) (*dborm.NeInfo, error) {
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Error("dborm.XormGetNeInfo is failed:", err)
return nil, err
}
if neInfo == nil || neInfo.Ip == "" {
return nil, fmt.Errorf("not ne_info or not IP")
}
return neInfo, nil
}
// TcpdumpNeTask 网元发送执行 pcap
func TcpdumpNeTask(w http.ResponseWriter, r *http.Request) {
var body struct {
NeType string `json:"neType"` // 网元类型
NeId string `json:"neId"` // 网元ID
Timeout int `json:"timeout"` // 超时时间
Cmd string `json:"cmd"` // 命令
}
err := ctx.ShouldBindJSON(r, &body)
if err != nil || body.NeType == "" || body.NeId == "" || body.Timeout < 5 || body.Cmd == "" {
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
return
}
neInfo, err := NeInfo(body.NeType, body.NeId)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
filePcapName := fmt.Sprintf("tmp_%s_%s_%d.pcap", body.NeType, body.NeId, time.Now().UnixMilli())
fileLogName := fmt.Sprintf("tmp_%s_%s_%d.log", body.NeType, body.NeId, time.Now().UnixMilli())
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件放置弹出code 127
cmdStr := fmt.Sprintf("cd /tmp \nsudo timeout %d tcpdump -i any %s -s0 -w %s", body.Timeout, body.Cmd, filePcapName)
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr+writeLog)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
ctx.JSON(w, 200, result.OkData(map[string]any{
"cmd": cmdStr,
"msg": msg,
"fileName": filePcapName,
}))
}
// TcpdumpPcapDownload 网元抓包pcap文件下载
func TcpdumpPcapDownload(w http.ResponseWriter, r *http.Request) {
var body struct {
NeType string `json:"neType"` // 网元类型
NeId string `json:"neId"` // 网元ID
FileName string `json:"fileName"` // 文件名
}
err := ctx.ShouldBindJSON(r, &body)
if err != nil || body.NeType == "" || body.NeId == "" || body.FileName == "" {
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
return
}
neInfo, err := NeInfo(body.NeType, body.NeId)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
nePath := fmt.Sprintf("/tmp/%s", body.FileName)
localPath := fmt.Sprintf("%s/tcpdump/pcap/%s", conf.Get("ne.omcdir"), body.FileName)
err = ssh.FileSCPNeToLocal(neInfo.Ip, nePath, localPath)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
ctx.FileAttachment(w, r, localPath, body.FileName)
}
// TcpdumpNeUPFTask 网元UPF发送执行 pcap
func TcpdumpNeUPFTask(w http.ResponseWriter, r *http.Request) {
var body struct {
NeType string `json:"neType"` // 网元类型
NeId string `json:"neId"` // 网元ID
Cmd string `json:"cmd"` // 命令
RunType string `json:"runType"` // 执行开始start还是停止stop
}
err := ctx.ShouldBindJSON(r, &body)
if err != nil || body.NeType != "UPF" || body.NeId == "" || body.Cmd == "" {
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
return
}
neInfo, err := NeInfo(body.NeType, body.NeId)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
// 开始telnet
if body.RunType == "start_telnet" {
// 创建TCP连接
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", neInfo.Ip, 5002))
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
defer conn.Close()
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
cmdStr := fmt.Sprintf("pcap dispatch trace on max 100000 file %s", filePcapName)
fmt.Fprintln(conn, cmdStr)
// 读取内容
time.Sleep(time.Duration(200) * time.Millisecond)
buf := make([]byte, 1024*8)
n, err := conn.Read(buf)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
} else {
str := string(buf[0:n])
s := strings.Index(str, "pcap dispatch trace:")
if s != -1 {
e := strings.Index(str, "\r\nupfd1#")
str = str[s:e]
} else {
str = fmt.Sprintf("Executed, please stop before proceeding %d", n)
}
ctx.JSON(w, 200, result.OkData(map[string]any{
"cmd": cmdStr,
"msg": str,
"fileName": filePcapName,
}))
}
conn.Close()
return
}
// 停止telnet
if body.RunType == "stop_telnet" {
// 创建TCP连接
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", neInfo.Ip, 5002))
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
defer conn.Close()
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
cmdStr := "pcap dispatch trace off"
fmt.Fprintln(conn, cmdStr)
// 读取内容
time.Sleep(time.Duration(200) * time.Millisecond)
buf := make([]byte, 1024*8)
n, err := conn.Read(buf)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
} else {
str := string(buf[0:n])
s := strings.Index(str, "pcap dispatch trace:")
if s == -1 {
s = strings.Index(str, "Write ")
}
if s != -1 {
e := strings.Index(str, "\r\nupfd1#")
str = str[s:e]
} else {
str = "No stoppable found"
}
ctx.JSON(w, 200, result.OkData(map[string]any{
"cmd": cmdStr,
"msg": str,
"fileName": filePcapName,
}))
}
conn.Close()
return
}
// 开始 -脚本
if body.RunType == "start2" {
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
// 复制文件到网元上
err := ssh.FileSCPLocalToNe(neInfo.Ip, "C:\\AMP\\Probject\\ems_backend\\restagent\\backup\\upf_pcap", "/tmp")
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件放置弹出code 127
cmdStr := fmt.Sprintf("cd /tmp \nchmod +x upf_pcap\n./upf_pcap '192.168.4.139' 'root' 'Admin123@pl' 'pcap dispatch trace on max 100000 file %s' %s ", fileLogName, writeLog)
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
} else {
ctx.JSON(w, 200, result.OkData(map[string]any{
"cmd": cmdStr,
"msg": msg,
"fileName": filePcapName,
}))
}
return
}
// 停止 -脚本
if body.RunType == "stop2" {
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
// cmdStr := "cd /tmp \nexpect /tmp/cat.sh "
err := ssh.FileSCPLocalToNe(neInfo.Ip, "C:\\AMP\\Probject\\ems_backend\\restagent\\backup\\upf_pcap", "/tmp")
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件放置弹出code 127
cmdStr := fmt.Sprintf("cd /tmp \nchmod +x upf_pcap\n./upf_pcap '192.168.4.139' 'root' 'Admin123@pl' 'pcap dispatch trace off' %s ", writeLog)
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
} else {
ctx.JSON(w, 200, result.OkData(map[string]any{
"cmd": cmdStr,
"msg": msg,
"fileName": filePcapName,
}))
}
return
}
// 开始-脚本字符串
if body.RunType == "start_str" {
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
scriptStr := "set capcmd [lindex $argv 0]\nspawn telnet localhost 5002\nexpect \"upfd1# \"\nsend \"$capcmd\\n\"\nexpect \"upfd1# \"\nsend \"quit\\n\"\nexpect \"eof\""
writeLog := fmt.Sprintf(" > %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件输出避免弹出code 127
capCmdStr := fmt.Sprintf("%s file %s", body.Cmd, filePcapName)
cmdStr := fmt.Sprintf("cd /tmp\n\necho '%s' > cap.sh\n\nchmod +x cap.sh\n\nexpect ./cap.sh '%s'%s", scriptStr, capCmdStr, writeLog)
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
} else {
s := strings.Index(msg, "pcap dispatch trace:")
if s != -1 {
e := strings.Index(msg, "\r\nupfd1#")
msg = msg[s:e]
} else {
msg = "Executed, please stop before proceeding"
}
ctx.JSON(w, 200, result.OkData(map[string]any{
"cmd": capCmdStr,
"msg": msg,
"fileName": filePcapName,
}))
}
return
}
// 停止-脚本字符串
if body.RunType == "stop_str" {
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
scriptStr := "set capcmd [lindex $argv 0]\nspawn telnet localhost 5002\nexpect \"upfd1# \"\nsend \"$capcmd\\n\"\nexpect \"upfd1# \"\nsend \"quit\\n\"\nexpect \"eof\""
writeLog := fmt.Sprintf(" > %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件输出避免弹出code 127
capCmdStr := body.Cmd
cmdStr := fmt.Sprintf("cd /tmp\n\necho '%s' > cap.sh\n\nchmod +x cap.sh\n\nexpect ./cap.sh '%s'%s", scriptStr, capCmdStr, writeLog)
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
} else {
s := strings.Index(msg, "pcap dispatch trace:")
if s == -1 {
s = strings.Index(msg, "Write ")
}
if s != -1 {
e := strings.Index(msg, "\r\nupfd1#")
msg = msg[s:e]
} else {
msg = "No stoppable found"
}
ctx.JSON(w, 200, result.OkData(map[string]any{
"cmd": capCmdStr,
"msg": msg,
"fileName": filePcapName,
}))
}
return
}
ctx.JSON(w, 200, result.ErrMsg("runType is start or stop"))
}