Files
be.ems/src/modules/trace/service/trace_task.go
T

346 lines
9.4 KiB
Go

package service
import (
"encoding/base64"
"fmt"
"net"
"strings"
"be.ems/src/framework/config"
"be.ems/src/framework/logger"
"be.ems/src/framework/socket"
"be.ems/src/framework/utils/date"
"be.ems/src/framework/utils/parse"
neFetchlink "be.ems/src/modules/network_element/fetch_link"
neModel "be.ems/src/modules/network_element/model"
neService "be.ems/src/modules/network_element/service"
"be.ems/src/modules/trace/model"
"be.ems/src/modules/trace/repository"
wsService "be.ems/src/modules/ws/service"
)
// 实例化数据层 TraceTask 结构体
var NewTraceTask = &TraceTask{
udpService: socket.SocketUDP{},
tcpService: socket.SocketTCP{},
traceTaskRepository: repository.NewTraceTask,
traceDataRepository: repository.NewTraceData,
}
// TraceTask 跟踪任务 服务层处理
type TraceTask struct {
udpService socket.SocketUDP // UDP服务对象
tcpService socket.SocketTCP // 测试用,后续调整TODO
traceTaskRepository *repository.TraceTask // 跟踪_任务数据信息
traceDataRepository *repository.TraceData // 跟踪_数据信息
}
// CreateUDP 创建UDP数据通道
func (r *TraceTask) CreateUDP(reload bool) error {
if reload {
r.CloseUDP() // 关闭之前的UDP服务
}
// 跟踪配置是否开启
host, port, err := r.traceNotify()
if err != nil {
return err
}
// 初始化UDP服务
r.udpService = socket.SocketUDP{Addr: host, Port: port}
if _, err := r.udpService.New(); err != nil {
return err
}
// 接收处理UDP数据
go r.udpService.Resolve(func(conn *net.UDPConn, err error) {
if err != nil {
logger.Errorf("UDP Resolve %s", err.Error())
return
}
// 读取数据
buf := make([]byte, 10*1048)
n, addr, err := conn.ReadFromUDPAddrPort(buf)
if err != nil {
logger.Errorf("UDP Resolve ReadFromUDPAddrPort Error: %s", err.Error())
return
}
// logger.Infof("socket UDP: %s", string(buf[:n]))
logger.Infof("socket UDP Base64 Encode: %s", base64.StdEncoding.EncodeToString(buf[:n]))
// 解析数据
if err := r.pasreUDPData(buf[:n]); err != nil {
logger.Errorf("UDP Resolve UDPData Error: %s", err.Error())
return
}
// 发送响应
if _, err := conn.WriteToUDPAddrPort([]byte("udp>"), addr); err != nil {
logger.Errorf("UDP Resolve WriteToUDPAddrPort Error: %s", err.Error())
}
buf = nil
})
// ============ 本地测试接收网元UDP发过来的数据 后续调整TODO
if config.Env() == "local" {
// 初始化TCP服务
r.tcpService = socket.SocketTCP{Addr: host, Port: port + 1}
if _, err := r.tcpService.New(); err != nil {
return err
}
// 接收处理TCP数据
go r.tcpService.Resolve(func(conn *net.Conn, err error) {
if err != nil {
logger.Errorf("TCP Resolve %s", err.Error())
return
}
c := (*conn)
// 读取数据
buf := make([]byte, 2048)
n, err := c.Read(buf)
if err != nil {
logger.Errorf("TCP Resolve Read Error: %s", err.Error())
return
}
// logger.Infof("socket TCP: %s", string(buf[:n]))
deData, _ := base64.StdEncoding.DecodeString(string(buf[:n]))
// logger.Infof("socket TCP Base64 Decode: %s", deData)
if err := r.pasreUDPData(deData); err != nil {
logger.Errorf("TCP Resolve UDPData Error: %s", err.Error())
return
}
// 发送响应
if _, err = c.Write([]byte("tcp>")); err != nil {
logger.Errorf("TCP Resolve Write Error: %s", err.Error())
}
buf = nil
})
}
return nil
}
// pasreUDPData 解析数据
func (r *TraceTask) pasreUDPData(buf []byte) error {
data, err := traceHandler(buf)
if err != nil {
logger.Errorf("UDP Resolve UDPDataHandler Error: %s", err.Error())
return err
}
taskId := parse.Number(data.NfTraceMsg.TraceId)
// 插入数据库做记录
item := model.TraceData{
TraceId: taskId,
IMSI: data.NfTraceMsg.IMSI,
SrcAddr: data.NfTraceMsg.SrcIpStr,
DstAddr: data.NfTraceMsg.DstIpStr,
IfType: data.NfTraceMsg.IfType,
MsgType: data.NfTraceMsg.MsgType,
MsgDirect: data.NfTraceMsg.MsgDirect,
MsgNe: data.NfTraceMsg.NfName,
MsgEvent: data.NfTraceMsg.MsgEvent,
Length: int64(data.TracePayloadLen),
RawMsg: base64.StdEncoding.EncodeToString(data.TracePayload),
Timestamp: data.NfTraceMsg.Timestamp,
}
item.ID = r.traceDataRepository.Insert(item)
// 推送到ws订阅组
item.RawMsg = "" // 不推送原始数据
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s_%d", wsService.GROUP_TRACE_NE, taskId), item)
return err
}
// CloseUDP 关闭UDP数据通道
func (r *TraceTask) CloseUDP() {
r.udpService.Close()
r.tcpService.Close()
}
// FindByPage 根据条件分页查询
func (r TraceTask) FindByPage(query map[string]string) ([]model.TraceTask, int64) {
return r.traceTaskRepository.SelectByPage(query)
}
// FindById 通过ID查询
func (r TraceTask) FindById(id int64) model.TraceTask {
tasks := r.traceTaskRepository.SelectByIds([]int64{id})
if len(tasks) > 0 {
return tasks[0]
}
return model.TraceTask{}
}
// Insert 新增信息
func (r TraceTask) Insert(task model.TraceTask) error {
if err := r.createTaskToNe(&task, false); err != nil {
return err
}
// 插入数据库
insertId := r.traceTaskRepository.Insert(task)
if insertId <= 0 {
return fmt.Errorf("insert task error")
}
return nil
}
// CreateTaskToNe 创建任务到网元
func (r TraceTask) createTaskToNe(task *model.TraceTask, ignoreErr bool) error {
// 跟踪配置是否开启
host, port, err := r.traceNotify()
if err != nil {
return err
}
task.NotifyUrl = fmt.Sprintf("udp:%s:%d", host, port)
// 网元列表
neList := strings.Split(task.NeList, ",")
if len(neList) <= 0 {
return fmt.Errorf("ne list is empty")
}
// 生成任务ID
if task.TraceId == "" {
task.TraceId = fmt.Sprint(r.traceTaskRepository.LastID() + 1) // 生成任务ID < 65535
}
// 发送任务给网元
errNe := []string{}
for _, neTypeID := range neList {
neTypeIDArr := strings.Split(neTypeID, "_")
if len(neTypeIDArr) != 2 {
logger.Warnf("ne type id is error")
continue
}
neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neTypeIDArr[0], neTypeIDArr[1])
if neInfo.NeType != neTypeIDArr[0] || neInfo.IP == "" {
logger.Warnf("ne type id is not exist")
continue
}
if err := r.traceNeTask(neInfo, *task); err != nil {
logger.Errorf("ne type id is %s to %s error: %s", task.TraceId, neTypeID, err.Error())
errNe = append(errNe, neTypeID)
continue
}
}
if len(errNe) <= 0 && !ignoreErr {
return nil
}
// 移除任务
for _, neTypeID := range neList {
neTypeIDArr := strings.Split(neTypeID, "_")
if len(neTypeIDArr) != 2 {
continue
}
neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neTypeIDArr[0], neTypeIDArr[1])
if neInfo.NeType != neTypeIDArr[0] || neInfo.IP == "" {
continue
}
neFetchlink.NeTraceDelete(neInfo, task.TraceId)
}
return fmt.Errorf("task to ne error: %s", strings.Join(errNe, ","))
}
// traceNotify 网元通知地址
func (r TraceTask) traceNotify() (string, int64, error) {
if v := config.Get("trace.enabled"); !parse.Boolean(v) {
return "", 0, fmt.Errorf("trace is not enabled")
}
host := "127.0.0.1"
if v := config.Get("trace.host"); v != nil {
host = v.(string)
}
var port int64 = 33033
if v := config.Get("trace.port"); v != nil {
port = parse.Number(v)
}
return host, port, nil
}
// traceNeTask 网元创建任务
func (r TraceTask) traceNeTask(neInfo neModel.NeInfo, task model.TraceTask) error {
data := model.TraceReq{
TraceId: parse.Number(task.TraceId),
NotifyUrl: task.NotifyUrl,
StartTime: date.ParseDateToStr(task.StartTime, date.YYYY_MM_DD_HH_MM_SS),
EndTime: date.ParseDateToStr(task.EndTime, date.YYYY_MM_DD_HH_MM_SS),
}
switch task.TraceType {
case "1": // Interface
data.TraceType = "Interface"
data.Interfaces = strings.Split(task.Interfaces, ",")
case "2": // Device
data.TraceType = "Device"
data.SrcIp = task.SrcIp
data.DstIp = task.DstIp
case "3": // UE
data.TraceType = "UE"
data.IMSI = fmt.Sprintf("imsi-%s", task.IMSI)
default:
return fmt.Errorf("trace type is not support")
}
msg, err := neFetchlink.NeTraceAdd(neInfo, data)
if err != nil {
return err
}
if v, ok := msg["cause"]; ok {
return fmt.Errorf("trace task add failed, %v", v)
}
return nil
}
// DeleteByIds 批量删除信息
func (r TraceTask) DeleteByIds(ids []int64) (int64, error) {
// 检查是否存在
rows := r.traceTaskRepository.SelectByIds(ids)
if len(rows) <= 0 {
return 0, fmt.Errorf("not data")
}
if len(rows) == len(ids) {
// 删除数据同时给网元发送停止任务
for _, v := range rows {
// 删除数据
r.traceDataRepository.DeleteByTraceId(v.TraceId)
// 网元列表
neList := strings.Split(v.NeList, ",")
if len(neList) <= 0 {
continue
}
// 停止任务
for _, neTypeID := range neList {
neTypeIDArr := strings.Split(neTypeID, "_")
if len(neTypeIDArr) != 2 {
continue
}
neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neTypeIDArr[0], neTypeIDArr[1])
if neInfo.NeType != neTypeIDArr[0] || neInfo.IP == "" {
continue
}
neFetchlink.NeTraceDelete(neInfo, v.TraceId)
}
}
num := r.traceTaskRepository.DeleteByIds(ids)
return num, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}
// RunUnstopped 启动跟踪未停止的任务
func (r TraceTask) RunUnstopped(neType string, neId string) {
neStr := fmt.Sprintf("%s_%s", neType, neId)
tasks := r.traceTaskRepository.SelectByUnstopped(neStr)
for _, task := range tasks {
r.createTaskToNe(&task, true)
}
}