package controller import ( "fmt" "strings" "ems.agt/src/framework/cmd" "ems.agt/src/framework/config" "ems.agt/src/framework/i18n" "ems.agt/src/framework/utils/ctx" "ems.agt/src/framework/utils/ssh" "ems.agt/src/framework/vo/result" netElementService "ems.agt/src/modules/network_element/service" traceService "ems.agt/src/modules/trace/service" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" ) // 实例化控制层 TcpdumpController 结构体 var NewTcpdump = &TcpdumpController{ NeInfoService: netElementService.NewNeInfoImpl, TcpdumpService: traceService.NewTcpdumpImpl, } // 信令抓包请求 // // PATH /tcpdump type TcpdumpController struct { // 网元信息服务 NeInfoService netElementService.INeInfo // 信令抓包服务 TcpdumpService traceService.ITcpdump } // 网元发送执行 pcap // // POST /ne func (s *TcpdumpController) NeTask(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` // 网元类型 NeId string `json:"neId" binding:"required"` // 网元ID Timeout int `json:"timeout" binding:"required"` // 超时时间 Cmd string `json:"cmd" binding:"required"` // 命令 Timestamp string `json:"timestamp" binding:"required"` // 时间戳 } err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 检查网元信息 neInfo := s.NeInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeId) if neInfo.NeId != body.NeId { // 找不到 %s %s 对应网元信息 msg := i18n.TTemplate(language, "trace.tcpdump.noData", map[string]any{"type": body.NeType, "id": body.NeId}) c.JSON(200, result.ErrMsg(msg)) return } filePcapName := fmt.Sprintf("%s_%s_%s.pcap", body.Timestamp, body.NeType, body.NeId) fileLogName := fmt.Sprintf("%s_%s_%s.log", body.Timestamp, body.NeType, body.NeId) 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 := config.Get("ne.user").(string) // 网元统一用户 sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.IP) msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr+writeLog) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } if strings.Contains(msg, "command not found") { c.JSON(200, result.ErrMsg("Command [tcpdump] Not Found")) return } c.JSON(200, result.OkData(map[string]any{ "cmd": cmdStr, "msg": msg, "fileName": filePcapName, })) } // 网元抓包pcap文件下载 // // POST /download func (s *TcpdumpController) Download(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` // 网元类型 NeId string `json:"neId" binding:"required"` // 网元ID FileName string `form:"fileName" ` // 文件名 } err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 检查网元信息 neInfo := s.NeInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeId) if neInfo.NeId != body.NeId { // 找不到 %s %s 对应网元信息 msg := i18n.TTemplate(language, "trace.tcpdump.noData", map[string]any{"type": body.NeType, "id": body.NeId}) c.JSON(200, result.ErrMsg(msg)) return } nePath := fmt.Sprintf("/tmp/%s", body.FileName) localPath := fmt.Sprintf("/tmp/omc/tcpdump/%s", body.FileName) err = ssh.FileSCPNeToLocal(neInfo.IP, nePath, localPath) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } c.FileAttachment(localPath, body.FileName) } // 网元发送执行 pcap // // POST /neUPF func (s *TcpdumpController) NeUPFTask(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` // 网元类型 NeId string `json:"neId" binding:"required"` // 网元ID RunType string `json:"runType" binding:"required"` // 执行开始start还是停止stop Cmd string `json:"cmd" binding:"required"` // 命令 Timestamp string `json:"timestamp" binding:"required"` // 时间戳 } err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 检查网元信息 neInfo := s.NeInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeId) if neInfo.NeId != body.NeId { msg := i18n.TTemplate(language, "trace.tcpdump.noData", map[string]any{"type": body.NeType, "id": body.NeId}) c.JSON(200, result.ErrMsg(msg)) return } // 开始telnet if body.RunType == "start_telnet" { filePcapName := fmt.Sprintf("%s_%s_%s.pcap", body.Timestamp, body.NeType, body.NeId) cmdStr := fmt.Sprintf("%s file %s", body.Cmd, filePcapName) // 进行连接telnet resultStr, err := s.TcpdumpService.UPFTelnet(neInfo.IP, cmdStr) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } // 处理结果 s := strings.Index(resultStr, "pcap dispatch trace:") if s == -1 { s = strings.Index(resultStr, "Write ") } if s != -1 { e := strings.Index(resultStr, "\r\nupfd1#") resultStr = resultStr[s:e] } else { resultStr = "No stoppable found" } c.JSON(200, result.OkData(map[string]any{ "cmd": cmdStr, "msg": resultStr, "fileName": filePcapName, })) return } // 停止telnet if body.RunType == "stop_telnet" { filePcapName := fmt.Sprintf("%s_%s_%s.pcap", body.Timestamp, body.NeType, body.NeId) cmdStr := "pcap dispatch trace off" // 进行连接telnet resultStr, err := s.TcpdumpService.UPFTelnet(neInfo.IP, cmdStr) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } // 处理结果 s := strings.Index(resultStr, "pcap dispatch trace:") if s != -1 { e := strings.Index(resultStr, "\r\nupfd1#") resultStr = resultStr[s:e] } else { resultStr = "Executed, please stop before proceeding" } c.JSON(200, result.OkData(map[string]any{ "cmd": cmdStr, "msg": resultStr, "fileName": filePcapName, })) return } // 开始-脚本字符串 if body.RunType == "start_str" { fileLogName := fmt.Sprintf("%s_%s_%s.log", body.Timestamp, body.NeType, body.NeId) filePcapName := fmt.Sprintf("%s_%s_%s.pcap", body.Timestamp, 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 := config.Get("ne.user").(string) // 网元统一用户 sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.IP) msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } if strings.Contains(msg, "command not found") { c.JSON(200, result.ErrMsg("Command [expect] Not Found")) return } if strings.Contains(msg, "Unable to connect to remote host") { c.JSON(200, result.ErrMsg("Connection Refused")) return } 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" } c.JSON(200, result.OkData(map[string]any{ "cmd": capCmdStr, "msg": msg, "fileName": filePcapName, })) return } // 停止-脚本字符串 if body.RunType == "stop_str" { fileLogName := fmt.Sprintf("%s_%s_%s.log", body.Timestamp, body.NeType, body.NeId) filePcapName := fmt.Sprintf("%s_%s_%s.pcap", body.Timestamp, 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 := config.Get("ne.user").(string) // 网元统一用户 sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.IP) msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } if strings.Contains(msg, "command not found") { c.JSON(200, result.ErrMsg("Command [expect] Not Found")) return } if strings.Contains(msg, "Unable to connect to remote host") { c.JSON(200, result.ErrMsg("Connection Refused")) return } s := strings.Index(msg, "pcap dispatch trace:") if s == -1 { s = strings.Index(msg, "Write ") // 停止写入的文件名 startIndex := strings.LastIndex(msg, "/") + 1 endIndex := strings.LastIndex(msg, ",") filePcapName = msg[startIndex:endIndex] } if s != -1 { e := strings.Index(msg, "\r\nupfd1#") msg = msg[s:e] } else { msg = "No stoppable found" } c.JSON(200, result.OkData(map[string]any{ "cmd": capCmdStr, "msg": msg, "fileName": filePcapName, })) return } c.JSON(200, result.ErrMsg("Please select RunType to execute: start_telnet/stop_telnet/start_str/stop_str")) }