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

346 lines
9.4 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 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)
}
}