add: parameter config support alarm forward config

This commit is contained in:
2024-09-06 10:49:22 +08:00
parent 86ae0779ef
commit 388729bf09
13 changed files with 497 additions and 77 deletions

View File

@@ -0,0 +1,100 @@
omc:
alarmEmailForward:
display: "Alarm Email Forward Interface"
sort: 3
list:
- name: "enable"
type: "bool"
value: "true"
access: "rw"
filter: "true;false"
display: "Enable"
comment: "Is it enabled forward alarm with Email interface"
- name: "emailList"
type: "string"
value: ""
access: "rw"
filter: ""
display: "Email List"
comment: ""
- name: "smtp"
type: "string"
value: ""
access: "rw"
filter: ""
display: "SMTP Server"
comment: "Email SMTP server"
- name: "port"
type: "int"
value: ""
access: "rw"
filter: "0~65535"
display: "Port"
comment: ""
- name: "user"
type: "string"
value: ""
access: "rw"
filter: ""
display: "User"
comment: ""
- name: "password"
type: "string"
value: ""
access: "rw"
filter: ""
display: "Password"
comment: ""
- name: "tlsSkipVerify"
type: "bool"
value: "true"
access: "rw"
filter: "true;false"
display: "TLS Skip Verify"
comment: "If skip TLS verify (true/false)"
alarmSMSForward:
display: "Alarm SMS Forward Interface"
sort: 4
list:
- name: "enable"
type: "bool"
value: "true"
access: "rw"
filter: "true;false"
display: "Enable"
comment: "Is it enabled forward alarm with SMS interface"
- name: "mobileList"
type: "string"
value: ""
access: "rw"
filter: ""
display: "Mobile List"
comment: ""
- name: "smscAddr"
type: "string"
value: ""
access: "rw"
filter: ""
display: "SMSC Address"
comment: "The SMSC SMPP Address"
- name: "systemID"
type: "string"
value: ""
access: "rw"
filter: ""
display: "System ID"
comment: ""
- name: "password"
type: "string"
value: ""
access: "rw"
filter: ""
display: "Password"
comment: ""
- name: "systemType"
type: "string"
value: ""
access: "rw"
filter: ""
display: "System Type"
comment: ""

View File

@@ -0,0 +1,46 @@
package cm_omc
import (
"fmt"
"net/http"
"be.ems/lib/services"
"github.com/gin-gonic/gin"
)
func (o *ConfigOMC) Get(c *gin.Context) {
paramName := c.Param("paramName")
results, err := o.Query(paramName)
if err != nil {
c.JSON(http.StatusInternalServerError, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusOK, services.DataResp(results))
}
func (o *ConfigOMC) Post(c *gin.Context) {
err := fmt.Errorf("method not allowed")
c.JSON(http.StatusMethodNotAllowed, services.ErrResp(err.Error()))
}
func (o *ConfigOMC) Put(c *gin.Context) {
paramName := c.Param("paramName")
var paramData map[string]any
if err := c.ShouldBindJSON(&paramData); err != nil {
c.JSON(http.StatusBadRequest, services.ErrResp(err.Error()))
return
}
result, err := o.Modify(paramName, paramData)
if err != nil {
c.JSON(http.StatusInternalServerError, services.ErrResp(err.Error()))
return
}
c.JSON(http.StatusOK, services.DataResp(result))
}
func (o *ConfigOMC) Delete(c *gin.Context) {
err := fmt.Errorf("method not allowed")
c.JSON(http.StatusMethodNotAllowed, services.ErrResp(err.Error()))
}

View File

@@ -0,0 +1,69 @@
package cm_omc
import (
"fmt"
"be.ems/restagent/config"
)
const (
PASSWORD_MASK = "********"
)
func (o *ConfigOMC) Query(paramName string) (any, error) {
var results []any
switch paramName {
case "alarmEmailForward":
result := config.GetYamlConfig().Alarm.EmailForward
result.Password = PASSWORD_MASK
results = append(results, result)
case "alarmSMSForward":
result := config.GetYamlConfig().Alarm.SMSCForward
result.Password = PASSWORD_MASK
results = append(results, result)
default:
return nil, fmt.Errorf("invalid source parameter")
}
return results, nil
}
func (o *ConfigOMC) Add() {
}
func (o *ConfigOMC) Modify(paramName string, paramData map[string]any) (any, error) {
var results []any
switch paramName {
case "alarmEmailForward":
param := &(config.GetYamlConfig().Alarm.EmailForward)
config.UpdateStructFromMap(param, paramData)
result := *param
results = append(results, result)
err := config.WriteOrignalConfig(config.YamlConfigInfo.FilePath, paramName, paramData)
if err != nil {
fmt.Println("failed to write config yaml file:", err)
return results, err
}
case "alarmSMSForward":
param := &(config.GetYamlConfig().Alarm.SMSCForward)
config.UpdateStructFromMap(param, paramData)
result := *param
results = append(results, result)
err := config.WriteOrignalConfig(config.YamlConfigInfo.FilePath, paramName, paramData)
if err != nil {
fmt.Println("failed to write config yaml file:", err)
return results, err
}
default:
return nil, fmt.Errorf("invalid source parameter")
}
return results, nil
}
func (o *ConfigOMC) Remove() {
}

26
features/cm/omc/model.go Normal file
View File

@@ -0,0 +1,26 @@
package cm_omc
type ConfigOMC struct{}
type SystemConfig struct {
ForwardFlag bool `json:"forwardFlag"`
}
type AlarmEmailForward struct {
Enable bool `json:"enable"`
EmailList string `json:"emailList"`
SMTP string `json:"smtp"`
Port uint16 `json:"port"`
User string `json:"user"`
Password string `json:"password"`
TLSSkipVerify bool `json:"tlsSkipVerify"`
}
type AlarmSMSForward struct {
Enable bool `json:"enable"`
MobileList string `json:"mobileList"`
SMSCAddr string `json:"smscAddr"`
SystemID string `json:"systemID"`
Password string `json:"password"`
SystemType string `json:"systemType"`
}

30
features/cm/omc/route.go Normal file
View File

@@ -0,0 +1,30 @@
package cm_omc
import (
"be.ems/src/framework/middleware"
"github.com/gin-gonic/gin"
)
// Register Routes for file_export
func Register(r *gin.RouterGroup) {
cmOMC := r.Group("/omc")
{
var o *ConfigOMC
cmOMC.GET("/config/:paramName",
middleware.PreAuthorize(nil),
o.Get,
)
cmOMC.POST("/config/:paramName",
middleware.PreAuthorize(nil),
o.Post,
)
cmOMC.PUT("/config/:paramName",
middleware.PreAuthorize(nil),
o.Put,
)
cmOMC.DELETE("/config/:paramName",
middleware.PreAuthorize(nil),
o.Delete,
)
}
}

17
features/cm/service.go Normal file
View File

@@ -0,0 +1,17 @@
package cm
import (
cm_omc "be.ems/features/cm/omc"
"be.ems/lib/log"
"github.com/gin-gonic/gin"
)
func InitSubServiceRoute(r *gin.Engine) {
log.Info("======init PM group gin.Engine")
cmGroup := r.Group("/cm")
// register sub modules routes
cm_omc.Register(cmGroup)
// return featuresGroup
}

View File

@@ -1,6 +1,7 @@
package features
import (
"be.ems/features/cm"
"be.ems/features/lm"
"be.ems/features/pm"
"be.ems/lib/log"
@@ -14,6 +15,7 @@ func InitServiceEngine(r *gin.Engine) {
// 注册 各个features 模块的路由
pm.InitSubServiceRoute(r)
lm.InitSubServiceRoute(r)
cm.InitSubServiceRoute(r)
// return featuresGroup
}

View File

@@ -466,10 +466,12 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
}
session.Commit()
}
if config.GetYamlConfig().Alarm.ForwardAlarm {
if config.GetYamlConfig().Alarm.EmailForward.Enable {
if err = AlarmEmailForward(&alarmData); err != nil {
log.Error("Failed to AlarmEmailForward:", err)
}
}
if config.GetYamlConfig().Alarm.SMSCForward.Enable {
if err = AlarmSMSForward(&alarmData); err != nil {
log.Error("Failed to AlarmSMSForward:", err)
}
@@ -776,10 +778,12 @@ func GetAlarmFromNF(w http.ResponseWriter, r *http.Request) {
continue
}
session.Commit()
if config.GetYamlConfig().Alarm.ForwardAlarm {
if config.GetYamlConfig().Alarm.EmailForward.Enable {
if err = AlarmEmailForward(&alarmData); err != nil {
log.Error("Failed to AlarmEmailForward:", err)
}
}
if config.GetYamlConfig().Alarm.SMSCForward.Enable {
if err = AlarmSMSForward(&alarmData); err != nil {
log.Error("Failed to AlarmSMSForward:", err)
}

View File

@@ -2,7 +2,6 @@ package fm
import (
"crypto/tls"
"errors"
"fmt"
"strings"
@@ -48,25 +47,25 @@ func AlarmEmailForward(alarmData *Alarm) error {
// userName := "smtpext@agrandtech.com"
// password := "1000smtp@omc!"
host := config.GetYamlConfig().Alarm.Email.Smtp
port := int(config.GetYamlConfig().Alarm.Email.Port)
userName := config.GetYamlConfig().Alarm.Email.User
password := config.GetYamlConfig().Alarm.Email.Password
host := config.GetYamlConfig().Alarm.EmailForward.SMTP
port := int(config.GetYamlConfig().Alarm.EmailForward.Port)
userName := config.GetYamlConfig().Alarm.EmailForward.User
password := config.GetYamlConfig().Alarm.EmailForward.Password
m := gomail.NewMessage()
m.SetHeader("From", userName) // 发件人
//m.SetHeader("From", "alias"+"<"+"aliastest"+">") // 增加发件人别名
emails, err := dborm.XormGetAlarmForward("Email")
if err != nil {
log.Error("Failed to XormGetAlarmForward:", err)
return err
} else if emails == nil || len(*emails) == 0 {
err := errors.New("not found forward email list")
log.Error(err)
return err
}
// emails, err := dborm.XormGetAlarmForward("Email")
// if err != nil {
// log.Error("Failed to XormGetAlarmForward:", err)
// return err
// } else if emails == nil || len(*emails) == 0 {
// err := errors.New("not found forward email list")
// log.Error(err)
// return err
// }
emails := strings.Split(config.GetYamlConfig().Alarm.EmailForward.EmailList, ",")
forwardLog := &dborm.AlarmForwardLog{
NeType: alarmData.NeType,
NeID: alarmData.NeId,
@@ -74,10 +73,10 @@ func AlarmEmailForward(alarmData *Alarm) error {
AlarmTitle: alarmData.AlarmTitle,
AlarmSeq: alarmData.AlarmSeq,
EventTime: alarmData.EventTime,
ToUser: strings.Join(*emails, ","),
ToUser: config.GetYamlConfig().Alarm.EmailForward.EmailList,
}
m.SetHeader("To", *emails...) // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接
m.SetHeader("To", emails...) // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接
//m.SetHeader("To", strings.Join(*emails, " ")) // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接
//m.SetHeader("To", "zhangshuzhong@agrandtech.com", "simonzhangsz@outlook.com") // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接
//m.SetHeader("Cc", "******@qq.com") // 抄送,可以多个
@@ -103,7 +102,7 @@ func AlarmEmailForward(alarmData *Alarm) error {
)
// 关闭SSL协议认证
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if !config.GetYamlConfig().Alarm.Email.TlsSkipVerify {
if !config.GetYamlConfig().Alarm.EmailForward.TLSSkipVerify {
// 打开SSL协议认证
d.TLSConfig = &tls.Config{InsecureSkipVerify: false}
}

View File

@@ -99,22 +99,23 @@ func AlarmForwardBySMS(alarmData *Alarm) (string, error) {
func AlarmForwardBySMPP(alarmData *Alarm) (string, error) {
log.Info("AlarmForwardBySMPP processing... ")
toUsers, err := dborm.XormGetAlarmForward("SMS")
if err != nil {
log.Error("Failed to XormGetAlarmForward:", err)
return "", err
} else if toUsers == nil {
err := errors.New("not found forward phone number")
log.Error(err)
return "", err
}
userList := strings.Join(*toUsers, ",")
// toUsers, err := dborm.XormGetAlarmForward("SMS")
// if err != nil {
// log.Error("Failed to XormGetAlarmForward:", err)
// return "", err
// } else if toUsers == nil {
// err := errors.New("not found forward phone number")
// log.Error(err)
// return "", err
// }
// userList := strings.Join(*toUsers, ",")
userList := config.GetYamlConfig().Alarm.SMSCForward.MobileList
auth := gosmpp.Auth{
SMSC: config.GetYamlConfig().Alarm.SMSC.Addr,
SystemID: config.GetYamlConfig().Alarm.SMSC.SystemID,
Password: config.GetYamlConfig().Alarm.SMSC.Password,
SystemType: config.GetYamlConfig().Alarm.SMSC.SystemType,
SMSC: config.GetYamlConfig().Alarm.SMSCForward.SMSCAddr,
SystemID: config.GetYamlConfig().Alarm.SMSCForward.SystemID,
Password: config.GetYamlConfig().Alarm.SMSCForward.Password,
SystemType: config.GetYamlConfig().Alarm.SMSCForward.SystemType,
}
// conn, err := gosmpp.NonTLSDialer(auth.SMSC)

View File

@@ -1,14 +1,18 @@
package config
import (
"bufio"
"fmt"
"os"
"reflect"
"strings"
"be.ems/lib/global"
"be.ems/lib/log"
"gopkg.in/yaml.v3"
//"github.com/go-yaml-comment/yaml"
//"github.com/goccy/go-yaml"
)
// Yaml struct of config
@@ -147,29 +151,34 @@ type DbConfig struct {
}
type AlarmConfig struct {
SplitEventAlarm bool `yaml:"splitEventAlarm"`
ForwardAlarm bool `yaml:"forwardAlarm"`
SMProxy string `yaml:"smProxy"`
Email struct {
Smtp string `yaml:"smtp"`
Port uint16 `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"password"`
TlsSkipVerify bool `yaml:"tlsSkipVerify"`
} `yaml:"email"`
SplitEventAlarm bool `yaml:"splitEventAlarm"`
//ForwardAlarm bool `yaml:"forwardAlarm"`
EmailForward struct {
Enable bool `yaml:"enable" json:"enable"`
EmailList string `yaml:"emailList" json:"emailList"`
SMTP string `yaml:"smtp" json:"smtp"`
Port uint16 `yaml:"port" json:"port"`
User string `yaml:"user" json:"user"`
Password string `yaml:"password" json:"password"`
TLSSkipVerify bool `yaml:"tlsSkipVerify" json:"tlsSkipVerify"`
} `yaml:"alarmEmailForward"`
SMSCForward struct {
Enable bool `yaml:"enable" json:"enable"`
MobileList string `yaml:"mobileList" json:"mobileList"`
SMSCAddr string `yaml:"smscAddr" json:"smscAddr"`
SystemID string `yaml:"systemID" json:"systemID"`
Password string `yaml:"password" json:"password"`
SystemType string `yaml:"systemType" json:"systemType"`
} `yaml:"alarmSMSForward"`
SMS struct {
ApiURL string `yaml:"apiURL"`
AccessKeyID string `yaml:"AccessKeyID"`
AccessKeySecret string `yaml:"accessKeySecret"`
SignName string `yaml:"signName"`
TemplateCode string `yaml:"templateCode"`
} `yaml:"sms"`
SMSC struct {
Addr string `yaml:"addr"`
SystemID string `yaml:"systemID"`
Password string `yaml:"password"`
SystemType string `yaml:"systemType"`
} `yaml:"smsc"`
} `yaml:"smsForward"`
SMProxy string `yaml:"smProxy"`
}
type MMLParam struct {
@@ -218,6 +227,16 @@ type TestDataMap struct {
var yamlConfig YamlConfig = NewYamlConfig()
type YamlConfigFile struct {
FilePath string `json:"filePath"`
ConfigLines YamlConfig `json:"configLines"`
OrignalLines []string `json:"orignalLines"`
}
var YamlConfigInfo YamlConfigFile = YamlConfigFile{
ConfigLines: NewYamlConfig(),
}
// set default value for yaml config
func NewYamlConfig() YamlConfig {
return YamlConfig{
@@ -237,6 +256,8 @@ func NewYamlConfig() YamlConfig {
}
func ReadConfig(configFile string) {
YamlConfigInfo.FilePath = configFile
yamlFile, err := os.ReadFile(configFile)
if err != nil {
fmt.Println("Read yaml config file error:", err)
@@ -244,25 +265,85 @@ func ReadConfig(configFile string) {
}
// fmt.Println("yamlfile:", string(yamlFile))
err = yaml.Unmarshal(yamlFile, &yamlConfig)
err = yaml.Unmarshal(yamlFile, &YamlConfigInfo.ConfigLines)
if err != nil {
fmt.Println("Unmarshal error:", err)
os.Exit(3)
}
yamlConfig = YamlConfigInfo.ConfigLines
ReadOriginalConfig(configFile)
}
func WriteYamlConfig(newConfigData YamlConfig, configFile string) {
func ReadOriginalConfig(configFile string) {
// 读取原始YAML文件
inputFile, err := os.Open(configFile)
if err != nil {
fmt.Println("failed to open:", err)
os.Exit(3)
}
defer inputFile.Close()
scanner := bufio.NewScanner(inputFile)
for scanner.Scan() {
YamlConfigInfo.OrignalLines = append(YamlConfigInfo.OrignalLines, scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Println("failed to scanner:", err)
os.Exit(3)
}
}
func WriteOrignalConfig(configFile string, paramName string, paramData map[string]any) error {
lines := YamlConfigInfo.OrignalLines
for i, line := range lines {
if strings.Contains(line, paramName) {
for k, v := range paramData {
// find the first line nearby the paramName
for j := i + 1; j < len(lines); j++ {
if strings.Contains(lines[j], k+":") {
index := strings.Index(lines[j], k)
lines[j] = lines[j][:index] + fmt.Sprintf("%s: %v", k, v)
break
}
}
}
break
}
}
// write back to yaml file
outputFile, err := os.Create(configFile)
if err != nil {
fmt.Println(err)
return err
}
defer outputFile.Close()
writer := bufio.NewWriter(outputFile)
for _, line := range YamlConfigInfo.OrignalLines {
writer.WriteString(line + "\n")
}
writer.Flush()
return nil
}
func WriteYamlConfig(newConfigData YamlConfig, configFile string) error {
// 将配置转换回YAML数据
newYamlData, err := yaml.Marshal(&newConfigData)
if err != nil {
log.Errorf("Failed to marshal YAML: %v", err)
return err
}
// 将新的YAML数据写入文件
err = os.WriteFile(configFile, newYamlData, 0644)
if err != nil {
log.Errorf("Failed to write YAML file: %v", err)
return err
}
return nil
}
var mapYaml map[string]interface{}
@@ -284,8 +365,28 @@ func ReadParamConfig(fileName string) *map[string]interface{} {
return &mapYaml
}
func UpdateStructFromMap(s any, updates map[string]any) {
v := reflect.ValueOf(s).Elem()
t := v.Type()
for key, value := range updates {
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.Tag.Get("json") == key {
structField := v.FieldByName(field.Name)
if structField.IsValid() && structField.CanSet() {
if structField.Type() == reflect.TypeOf(value) {
structField.Set(reflect.ValueOf(value))
}
}
break
}
}
}
}
func GetYamlConfig() *YamlConfig {
return &yamlConfig
return &YamlConfigInfo.ConfigLines
}
func GetAuthFromConfig() interface{} {

View File

@@ -51,13 +51,13 @@ redis:
# OMC系统使用库
default:
port: 6379 # Redis port
host: "192.168.8.58" # Redis host
host: "127.0.0.1" # Redis host
password: "helloearth"
db: 10 # Redis db_num
# UDM网元用户库
udmuser:
port: 6379 # Redis port
host: "192.168.8.58"
host: "127.0.0.1"
password: "helloearth"
db: 0 # Redis db_num
# 多个数据源时可以用这个指定默认的数据源
@@ -123,29 +123,32 @@ omc:
# Alarm module setting
# Forward interface:
# TLS Skip verify: true/false
# email/sms
# smProxy: sms(Short Message Service)/smsc(SMS Centre)
alarm:
forwardAlarm: false
email:
alarmEmailForward:
enable: true
emailList:
smtp: mail.agrandtech.com
port: 25
user: smtpext@agrandtech.com
password: "1000smtp@omc!"
# TLS skip verify: true/false
tlsSkipVerify: true
smProxy: smsc
alarmSMSForward:
enable: true
mobileList:
smscAddr: "192.168.13.114:2775"
systemID: "omc"
password: "omc123"
systemType: "UTRAN"
sms:
apiURL: http://smsc.xxx.com/
accessKeyID: xxxx
accessKeySecret: xxxx
signName: xxx SMSC
templateCode: 1000
smsc:
addr: "192.168.13.114:2775"
systemID: "omc"
password: "omc123"
systemType: "UTRAN"
smProxy: smsc
#User authorized information
# crypt: mysql/md5/bcrypt

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"strings"
cm_omc "be.ems/features/cm/omc"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
"be.ems/src/framework/utils/parse"
@@ -191,14 +192,25 @@ func (s *NeConfigController) DataInfo(c *gin.Context) {
return
}
// 网元直连
resData, err := neFetchlink.NeConfigInfo(neInfo, query.ParamName)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
if query.NeType == "OMC" {
var o *cm_omc.ConfigOMC
resData, err := o.Query(query.ParamName)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(resData))
return
}
} else {
// 网元直连
resData, err := neFetchlink.NeConfigInfo(neInfo, query.ParamName)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.Ok(resData))
c.JSON(200, result.Ok(resData))
}
}
// 网元参数配置数据修改
@@ -223,14 +235,24 @@ func (s *NeConfigController) DataEdit(c *gin.Context) {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
resData, err := neFetchlink.NeConfigUpdate(neInfo, body.ParamName, body.Loc, body.ParamData)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
if body.NeType == "OMC" {
var o *cm_omc.ConfigOMC
resData, err := o.Modify(body.ParamName, body.ParamData)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(resData))
return
} else {
// 网元直连
resData, err := neFetchlink.NeConfigUpdate(neInfo, body.ParamName, body.Loc, body.ParamData)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(resData))
}
c.JSON(200, result.OkData(resData))
}
// 网元参数配置数据新增array