Merge remote-tracking branch 'origin/main' into multi-tenant

This commit is contained in:
TsMask
2025-01-11 12:00:19 +08:00
141 changed files with 1560 additions and 12496 deletions

View File

@@ -1,537 +0,0 @@
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
type YamlConfig struct {
Logger struct {
File string `yaml:"file"`
Level string `yaml:"level"`
Duration int `yaml:"duration"`
Count int `yaml:"count"`
} `yaml:"logger"`
Pprof struct {
Enabled bool `yaml:"enabled"`
Addr string `yaml:"addr"`
} `yaml:"pprof"`
// Rest []struct {
// IPv4 string `yaml:"ipv4"`
// IPv6 string `yaml:"ipv6"`
// Port uint16 `yaml:"port"`
// Scheme string `yaml:"scheme"`
// ClientAuthType int `yaml:"clientAuthType"`
// CaFile string `yaml:"caFile"`
// CertFile string `yaml:"certFile"`
// KeyFile string `yaml:"keyFile"`
// } `yaml:"rest"`
Rest []RestParam
WebServer struct {
Enabled bool `yaml:"enabled"`
RootDir string `yaml:"rootDir"`
Listen []struct {
Addr string `yaml:"addr"`
Scheme string `yaml:"scheme"`
ClientAuthType int `yaml:"clientAuthType"`
CaFile string `yaml:"caFile"`
CertFile string `yaml:"certFile"`
KeyFile string `yaml:"keyFile"`
} `yaml:"listen"`
} `yaml:"webServer"`
Database DbConfig `yaml:"database"`
OMC struct {
UriPrefix string `yaml:"uriPrefix"`
NeType string `yaml:"neType"`
NeId string `yaml:"neId"`
RmUID string `yaml:"rmUID"`
NeName string `yaml:"neName"`
Province string `yaml:"province"`
Vendor string `yaml:"vendor"`
Dn string `yaml:"dn"`
Chk2Ne bool `yaml:"chk2ne"`
Capability uint32 `yaml:"capability"`
Sn string `yaml:"sn"`
ExpiryDate string `yaml:"expiryDate"`
CheckSign bool `yaml:"checksign"`
RootDir string `yaml:"rootDir"`
BinDir string `yaml:"binDir"`
Backup string `yaml:"backup"`
Upload string `yaml:"upload"`
FrontUpload string `yaml:"frontUpload"`
FrontTraceDir string `yaml:"frontTraceDir"`
Software string `yaml:"software"`
License string `yaml:"license"`
GtpUri string `yaml:"gtpUri"`
CheckContentType bool `yaml:"checkContentType"`
TestMode bool `yaml:"testMode"`
RBACMode bool `yaml:"rbacMode"`
RunDir string `yaml:"runDir"`
CmdTimeout int `yaml:"cmdTimeout"`
} `yaml:"omc"`
Alarm AlarmConfig `yaml:"alarm"`
MML MMLParam `yaml:"mml"`
NE struct {
Addr string `yaml:"addr"`
Port uint16 `yaml:"port"`
User string `yaml:"user"`
EtcDir string `yaml:"etcdir"`
BinDir string `yaml:"bindir"`
OmcDir string `yaml:"omcdir"`
ScpDir string `yaml:"scpdir"`
LicenseDir string `yaml:"licensedir"`
EtcListIMS string `yaml:"etcListIMS"`
EtcListDefault string `yaml:"etcListDefault"`
DpkgOverwrite bool `yaml:"dpkgOverwrite"`
DpkgTimeout int `yaml:"dpkgTimeout"`
} `yaml:"ne"`
Auth struct {
Crypt string `yaml:"crypt"`
Token bool `yaml:"token"`
Expires uint32 `yaml:"expires"`
Session string `yaml:"session"`
PublicKey string `yaml:"publicKey"`
PrivateKey string `yaml:"privateKey"`
} `yaml:"auth"`
Params struct {
RmUIDMaxNum int `yaml:"rmuidmaxnum"`
AlarmIDMaxNum int `yaml:"alarmidmaxnum"`
PmIDMaxNum int `yaml:"pmidmaxnum"`
SubIDMaxNum int `yaml:"subidmaxnum"`
UriMaxLen int `yaml:"urimaxlen"`
RmUIDRegexp string `yaml:"rmuidregexp"`
} `yaml:"params"`
TestConfig struct {
Enabled bool `yaml:"enabled"`
File string `yaml:"file"`
} `yaml:"testConfig"`
}
type RestParam struct {
IPv4 string `yaml:"ipv4"`
IPv6 string `yaml:"ipv6"`
Port uint16 `yaml:"port"`
Scheme string `yaml:"scheme,omitempty" default:"http"`
ClientAuthType int `yaml:"clientAuthType"`
CaFile string `yaml:"caFile"`
CertFile string `yaml:"certFile"`
KeyFile string `yaml:"keyFile"`
}
type DbConfig struct {
Type string `yaml:"type"`
User string `yaml:"user"`
Password string `yaml:"password"`
Host string `yaml:"host"`
Port string `yaml:"port"`
Name string `yaml:"name"`
ConnParam string `yaml:"connParam,omitempty"`
Backup string `yaml:"backup"`
}
type AlarmConfig struct {
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"`
DataCoding byte `yaml:"dataCoding" json:"dataCoding"`
ServiceNumber string `yaml:"serviceNumber" json:"serviceNumber"`
} `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:"smsForward"`
SMProxy string `yaml:"smProxy"`
}
type MMLParam struct {
Sleep int64 `yaml:"sleep"`
DeadLine int64 `yaml:"deadLine"`
SizeRow int16 `yaml:"sizeRow"`
SizeCol int16 `yaml:"sizeCol"`
BufferSize int `yaml:"bufferSize"`
MmlHome string `yaml:"mmlHome"`
}
type TestDatas struct {
UDM struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"udm"`
AUSF struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"ausf"`
AMF struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"amf"`
SMF struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"smf"`
UPF struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
} `yaml:"upf"`
}
type NeTestData struct {
CapUsed uint32 `yaml:"capUsed"`
FeatureEnabled []string `yaml:"featureEnabled"`
}
type TestDataMap struct {
NeTestDatas []map[string]NeTestData
}
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{
Database: DbConfig{
Type: "mysql",
ConnParam: "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True",
},
MML: MMLParam{
SizeRow: 200,
SizeCol: 120,
BufferSize: 65535,
},
Alarm: AlarmConfig{
SplitEventAlarm: true,
},
}
}
func ReadConfig(configFile string) {
YamlConfigInfo.FilePath = configFile
yamlFile, err := os.ReadFile(configFile)
if err != nil {
fmt.Println("Read yaml config file error:", err)
os.Exit(2)
}
// fmt.Println("yamlfile:", string(yamlFile))
err = yaml.Unmarshal(yamlFile, &YamlConfigInfo.ConfigLines)
if err != nil {
fmt.Println("Unmarshal error:", err)
os.Exit(3)
}
yamlConfig = YamlConfigInfo.ConfigLines
ReadOriginalConfig(configFile)
}
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)
// Determine the type of v
switch v := v.(type) {
case string:
lines[j] = lines[j][:index] + fmt.Sprintf("%s: \"%s\"", k, v)
// case int:
// lines[j] = lines[j][:index] + fmt.Sprintf("%s: %d", k, v)
// case float64:
// lines[j] = lines[j][:index] + fmt.Sprintf("%s: %f", k, v)
case bool:
lines[j] = lines[j][:index] + fmt.Sprintf("%s: %t", k, v)
default:
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{}
func ReadParamConfig(fileName string) *map[string]interface{} {
file, err := os.ReadFile(fileName)
if err != nil {
fmt.Println("Read yaml file error:", err)
}
mapYaml = make(map[string]interface{})
err = yaml.Unmarshal(file, &mapYaml)
if err != nil {
fmt.Printf("yaml.Unmarshal: %v when to struct", err)
}
// fmt.Println("mapYaml:", mapYaml)
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() {
// Convert value to the appropriate type if necessary
convertedValue := reflect.ValueOf(value).Convert(structField.Type())
if structField.Type() == convertedValue.Type() {
structField.Set(convertedValue)
}
}
break
}
}
}
}
func GetYamlConfig() *YamlConfig {
return &YamlConfigInfo.ConfigLines
}
func GetAuthFromConfig() interface{} {
return yamlConfig.Auth
}
func GetExpiresFromConfig() uint32 {
return yamlConfig.Auth.Expires
}
func GetRmUIDFromConfig() string {
return yamlConfig.OMC.RmUID
}
func GetRmUIDRegexpFromConfig() string {
return yamlConfig.Params.RmUIDRegexp
}
func GetRmUIDMaxNumFromConfig() int {
return yamlConfig.Params.RmUIDMaxNum
}
func GetAlarmIDMaxNumFromConfig() int {
return yamlConfig.Params.AlarmIDMaxNum
}
func GetPmIDMaxNumFromConfig() int {
return yamlConfig.Params.PmIDMaxNum
}
func GetSubIDMaxNumFromConfig() int {
return yamlConfig.Params.SubIDMaxNum
}
func GetUriMaxLenFromConfig() int {
return yamlConfig.Params.UriMaxLen
}
func GetLogLevel() log.LogLevel {
var logLevel log.LogLevel
switch strings.ToLower(yamlConfig.Logger.Level) {
case "trace":
logLevel = log.LOG_TRACE
case "info":
logLevel = log.LOG_INFO
case "debug":
logLevel = log.LOG_DEBUG
case "warn":
logLevel = log.LOG_WARN
case "error":
logLevel = log.LOG_ERROR
case "fatal":
logLevel = log.LOG_FATAL
case "off":
logLevel = log.LOG_OFF
default:
logLevel = log.LOG_DEBUG
}
return logLevel
}
var (
DefaultUriPrefix string = "/api/rest"
UriPrefix string = "/omc/rest"
//TestDataUDM []map[string]interface{}
TDatas map[string]NeTestData
)
func ReadTestConfigYaml(pfile string) (ret error) {
file, err := os.ReadFile(pfile)
if err != nil {
return err
}
err = yaml.Unmarshal(file, &TDatas)
if err != nil {
fmt.Println("Failed to Unmarshal:", err)
return err
}
return nil
}
func GetDefaultUserAgent() string {
return "OMC-restagent/" + global.Version
}
func GetOMCHostUrl() string {
var omcip string = "127.0.0.1"
var rest RestParam = yamlConfig.Rest[0]
var port uint16 = rest.Port
if rest.IPv4 != "0.0.0.0" && rest.IPv4 != "" {
omcip = rest.IPv4
} else if rest.IPv6 != "::" && rest.IPv6 != "" {
omcip = "[" + rest.IPv6 + "]"
}
var scheme string = "http"
if rest.Scheme != "" {
scheme = rest.Scheme
}
return fmt.Sprintf("%s://%s:%d", scheme, omcip, port)
}
// const defaultConfigFile = "./etc/restconf.yaml"
// func init() {
// cfile := flag.String("c", defaultConfigFile, "config file")
// pv := flag.Bool("version", false, "print version")
// ph := flag.Bool("help", false, "print help")
// //global.BuildTime = "Wed May 31 18:24:04 CST 2023"
// //global.GoVer = "go version go1.15.7 linux/arm64"
// flag.Parse()
// if *pv {
// fmt.Printf("OMC restagent version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
// os.Exit(0)
// }
// if *ph {
// flag.Usage()
// os.Exit(0)
// }
// // 使用viper读取配置
// conf.InitConfig(*cfile)
// ReadConfig(*cfile)
// if GetYamlConfig().OMC.UriPrefix != "" {
// UriPrefix = GetYamlConfig().OMC.UriPrefix
// }
// if GetYamlConfig().TestConfig.Enabled {
// ReadTestConfigYaml(GetYamlConfig().TestConfig.File)
// }
// }

View File

@@ -1,111 +0,0 @@
package config
import (
"io/ioutil"
"log"
"gopkg.in/yaml.v3"
"be.ems/lib/global"
)
type Uri2Object struct {
Uri string `yaml:"uri"`
Object []Object `yaml:"object"`
}
type Object struct {
Name string `yaml:"name"`
Syntax string `yaml:"syntax"`
Oid string `yaml:"oid"`
}
var uri2Object []Uri2Object
func ReadMap(pfile string) (ret error) {
file, err := ioutil.ReadFile(pfile)
if err != nil {
log.Println(err)
return err
}
err = yaml.Unmarshal(file, &uri2Object)
if err != nil {
log.Println(err)
return err
}
/*
for _, v := range uri2Object {
log.Println(v)
}
*/
return nil
}
func GetOid(uri string, oids *[]string) *[]string {
for _, v := range uri2Object {
if uri == v.Uri {
for _, o := range v.Object {
*oids = append(*oids, o.Oid)
}
}
}
return oids
}
func GetOidByFileds(uri string, fields []string, oids *[]string) *[]string {
for _, v := range uri2Object {
if uri == v.Uri {
for _, o := range v.Object {
if global.IsContain(o.Name, fields) || len(fields) == 0 {
*oids = append(*oids, o.Oid)
}
}
}
}
return oids
}
type NameOid struct {
Name string
Oid string
}
type NameValue struct {
Name string
Value string
}
func GetDataOid(Uri string, nameOids *[]NameOid) *[]NameOid {
var nameOid NameOid
for _, v := range uri2Object {
if Uri == v.Uri {
for _, o := range v.Object {
nameOid.Name = o.Name
nameOid.Oid = o.Oid
*nameOids = append(*nameOids, nameOid)
}
}
}
return nameOids
}
func GetDataOidByFields(uri string, fields []string, nameOids *[]NameOid) *[]NameOid {
var nameOid NameOid
for _, v := range uri2Object {
if uri == v.Uri {
for _, o := range v.Object {
nameOid.Name = o.Name
nameOid.Oid = o.Oid
if len(fields) == 0 || global.IsContainP(nameOid.Name, &fields, len(fields)) {
*nameOids = append(*nameOids, nameOid)
}
}
}
}
return nameOids
}

View File

@@ -2,13 +2,13 @@
# level: /trace/debug/info/warn/error/fatal, default: debug
# duration: rotation time with xx hours, example: 1/12/24 hours
# count: rotation count of log, default is 30 rotation
# pprof: false(default)/true to disable/enable pprof
logger:
file: d:/omc.git/be.ems/restagent/log/restagent.log
file: ./log/restagent.log
level: trace
duration: 24
count: 2
# pprof: false(default)/true to disable/enable pprof
pprof:
enabled: true
addr: :33060
@@ -21,16 +21,24 @@ rest:
- ipv4: 0.0.0.0
ipv6:
port: 33030
- ipv4: 0.0.0.0
ipv6:
port: 33443
schema: https
clientAuthType: 0
caFile: ./etc/certs/omc-ca.crt
certFile: ./etc/certs/omc-server.crt
keyFile: ./etc/certs/omc-server.key
webServer:
enabled: true
rootDir: d:/omc.git/fe.ems.vue3/dist
rootDir: d:/omc.git/fe.ems.vue3/dist # front-end build dist directory
listen:
- addr: :80
schema: http
- addr: :443
scheme: https
clientAuthType: 0
schema: https
clientAuthType: 0
caFile: ./etc/certs/omc-ca.crt
certFile: ./etc/certs/omc-server.crt
keyFile: ./etc/certs/omc-server.key
@@ -38,12 +46,12 @@ webServer:
database:
type: mysql
user: root
password: "1000omc@kp!"
host: "127.0.0.1"
password: 1000omc@kp!
host: 127.0.0.1
port: 33066
name: "tenants_db"
connParam: charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True
backup: d:/omc.git/be.ems/restagent/database
backup: ./database
# Redis data cache
redis:
@@ -58,7 +66,7 @@ redis:
defaultDataSourceName: "default"
# sleep: time delay for after write buffer (millisecond)
# deadLine: timeout for io read and write (second)
# deadLine: timeout for io read and write (second)
mml:
sleep: 200
deadLine: 10
@@ -81,7 +89,7 @@ ne:
omcdir: /usr/local/omc
scpdir: /tmp
licensedir: /usr/local/etc/{neType}/license
# backup etc list of IMS,no space
# backup etc list of IMS, does not contain spaces
etcListIMS: '{*.yaml,mmtel,vars.cfg}'
etcListDefault: '{*.yaml,*.conf,*.cfg}'
# true/false to overwrite config file when dpkg ne software
@@ -96,27 +104,27 @@ omc:
neId: 001
rmUID: 4400HX101
neName: OMC
province: GD
province: ""
vendor: ""
dn: 4600
dn: ""
chk2ne: false
capability: 50
sn: "12345678"
expiryDate: "2099-12-31"
sn: "-"
expiryDate: "-"
checksign: false
rootDir: ./
binDir: ./bin
backup: C:/usr/local/omc/backup
upload: C:/usr/local/omc/upload
frontUpload: C:/usr/local/omc/upload
frontTraceDir: C:/usr/local/omc/trace
software: C:/usr/local/omc/software
license: C:/usr/local/omc/license
gtpUri: gtp:192.168.2.219:2152
rootDir: /usr/local/omc
binDir: /usr/local/omc/bin
backup: /usr/local/omc/backup
upload: /usr/local/omc/upload
frontUpload: /usr/local/omc/htdocs/front/upload
frontTraceDir: /usr/local/omc/htdocs/front/trace
software: /usr/local/omc/software
license: /usr/local/omc/license
gtpUri: gtp:192.168.2.119:32152
checkContentType: false
testMode: false
rbacMode: true
runDir:
runDir: /usr/local/omc/run
cmdTimeout: 120
# Alarm module setting
@@ -126,7 +134,7 @@ omc:
# smProxy: sms(Short Message Service)/smsc(SMS Centre)
# dataCoding: 0:GSM7BIT, 1:ASCII, 2:BINARY8BIT1, 3:LATIN1,
# 4:BINARY8BIT2, 6:CYRILLIC, 7:HEBREW, 8:UCS2
alarm:
alarm:
alarmEmailForward:
enable: true
emailList:
@@ -134,7 +142,7 @@ alarm:
port: 25
user: smtpext@smtp.com
password: "1000smtp@omc!"
tlsSkipVerify: true
tlsSkipVerify: true
alarmSMSForward:
enable: true
mobileList: "1006,1008"
@@ -151,8 +159,8 @@ alarm:
signName: xxx SMSC
templateCode: 1000
smProxy: smsc
#User authorized information
# User authorized information
# crypt: mysql/md5/bcrypt
# token: true/false to check accessToken
# expires for session, unit: second

View File

@@ -1,7 +1,7 @@
# Makefile for rest agent project
PROJECT = OMC
VERSION = 2.2501.1
VERSION = 2.2501.2
PLATFORM = amd64
ARMPLATFORM = aarch64
BUILDDIR = ../../build

View File

@@ -1,16 +1,19 @@
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"sync"
_ "net/http/pprof"
"github.com/chenjiandongx/ginprom"
"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus/promhttp"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"be.ems/features"
"be.ems/features/dbrest"
"be.ems/features/event"
@@ -18,191 +21,76 @@ import (
"be.ems/features/lm"
"be.ems/features/mml"
"be.ems/features/pm"
featuresCfg "be.ems/lib/config"
"be.ems/lib/dborm"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/routes"
"be.ems/restagent/config"
"be.ems/src"
"be.ems/src/framework/config"
"be.ems/src/framework/logger"
"be.ems/src/framework/middleware"
"github.com/gin-gonic/gin"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"be.ems/src/framework/utils/parse"
_ "be.ems/swagger2docs"
)
// const defaultConfigFile = "./etc/restconf.yaml"
// func init() {
// cfile := flag.String("c", defaultConfigFile, "config file")
// pv := flag.Bool("v", false, "print version")
// ph := flag.Bool("h", false, "print help")
// flag.Parse()
// if *pv {
// fmt.Printf("OMC restagent version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
// os.Exit(0)
// }
// if *ph {
// flag.Usage()
// os.Exit(0)
// }
// config.ReadConfig(*cfile)
// config.UriPrefix = config.GetYamlConfig().OMC.UriPrefix
// //fmt.Println(config.UriPrefix)
// }
// func listenIPv6(ipv6 string, port int) {
// //
// addr := &net.TCPAddr{
// IP: net.ParseIP(ipv6),
// Port: port,
// }
// listener, err := net.ListenTCP("tcp6", addr)
// if err != nil {
// fmt.Println("Failed to listen:", err)
// return
// }
// server := &http.Server{}
// err = server.Serve(listener)
// if err != nil {
// fmt.Println("Failed to serve:", err)
// }
// }
func HttpListen(addr string, router http.Handler) {
// 创建HTTP服务器
h2s := &http2.Server{
// ...
}
server := &http.Server{
Addr: addr,
Handler: h2c.NewHandler(router, h2s),
}
// // support http 2.0 server
// err := http2.ConfigureServer(server, &http2.Server{})
// if err != nil {
// fmt.Println("ConfigureServer err:", err)
// os.Exit(11)
// }
err := server.ListenAndServe()
if err != nil {
fmt.Println("ListenAndServe err:", err)
os.Exit(12)
}
}
func HttpListenTLS(addr, caFile, certFile, keyFile string, clientAuthType int, router http.Handler) {
// 加载根证书
caCert, err := os.ReadFile(caFile)
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 创建自定义的TLS配置
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS10,
MaxVersion: tls.VersionTLS13,
ClientCAs: caCertPool,
ClientAuth: tls.ClientAuthType(clientAuthType),
}
// 创建HTTP服务器
server := &http.Server{
Addr: addr,
Handler: router,
TLSConfig: tlsConfig,
}
// support http 2.0 server
http2.ConfigureServer(server, &http2.Server{})
if err != nil {
fmt.Println("ConfigureServer err:", err)
os.Exit(13)
}
err = server.ListenAndServeTLS(certFile, keyFile)
if err != nil {
fmt.Println("ListenAndServeTLS err:", err)
os.Exit(14)
}
}
func HttpListenWebServerTLS(addr, caFile, certFile, keyFile string, clientAuthType int) {
// 加载根证书
caCert, err := os.ReadFile(caFile)
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 创建自定义的TLS配置
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS10,
MaxVersion: tls.VersionTLS13,
ClientCAs: caCertPool,
ClientAuth: tls.ClientAuthType(clientAuthType),
}
// 创建HTTP服务器
server := &http.Server{
Addr: addr,
TLSConfig: tlsConfig,
}
// support http 2.0 server
http2.ConfigureServer(server, &http2.Server{})
if err != nil {
fmt.Println("ConfigureServer err:", err)
os.Exit(9)
}
err = server.ListenAndServeTLS(certFile, keyFile)
if err != nil {
fmt.Println("ListenAndServeTLS err:", err)
os.Exit(10)
}
}
func HttpListenWebServer(addr string) {
// 创建HTTP服务器
server := &http.Server{
Addr: addr,
}
// support http 2.0 server
err := http2.ConfigureServer(server, &http2.Server{})
if err != nil {
fmt.Println("ConfigureServer err:", err)
os.Exit(7)
}
err = server.ListenAndServe()
if err != nil {
fmt.Println("ListenAndServe err:", err)
os.Exit(8)
}
}
var wg sync.WaitGroup
// @title OMC Swagger API
// @version 1.0.5
// @description OMC Service Interface Info
//
// @tag.name chart
// @tag.description chart interface
// @tag.name common
// @tag.description common interface
// @tag.name monitor
// @tag.description monitor interface
// @tag.name network_data
// @tag.description network data interface
// @tag.name network_element
// @tag.description network element interface
// @tag.name system
// @tag.description system interface
// @tag.name tool
// @tag.description tool interface
// @tag.name trace
// @tag.description trace interface
// @tag.name ws
// @tag.description ws interface
//
// @host 127.0.0.1:33040
// @BasePath /
// @schemes http https
//
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
// @description Get the key through the login interface, fill in e.g. Bearer <access_token>
func main() {
// src 配置中心初始加载
// 初始配置加载
src.ConfigurationInit()
// 程序注册
app := src.AppEngine()
// Swagger 接口文档
app.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
conf := config.GetYamlConfig()
loadFeatures(app)
if conf.Pprof.Enabled {
// 启用pprof HTTP服务
go func() {
fmt.Println(http.ListenAndServe(conf.Pprof.Addr, nil))
}()
}
loadPprof(app)
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:restagent", config.GetLogLevel())
loadServer(app)
loadWebServer()
wg.Wait()
}
// loadFeatures mux路由模块
func loadFeatures(app *gin.Engine) {
conf := featuresCfg.GetYamlConfig()
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:restagent", featuresCfg.GetLogLevel())
fmt.Printf("OMC restagent version: %s\n", global.Version)
log.Infof("========================= OMC restagent startup =========================")
log.Infof("OMC restagent version: %s %s %s", global.Version, global.BuildTime, global.GoVer)
@@ -249,71 +137,138 @@ func main() {
// 将 mux.Router 注册到 gin.Engine
// 默认路由组
defaultUriGroup := app.Group(config.DefaultUriPrefix)
defaultUriGroup := app.Group(featuresCfg.DefaultUriPrefix)
defaultUriGroup.Use(middleware.PreAuthorize(nil))
defaultUriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
// 可配置前缀路由组
uriGroup := app.Group(config.UriPrefix)
uriGroup := app.Group(featuresCfg.UriPrefix)
uriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
// AMF上报的UE事件, 无前缀,暂时特殊处理
app.POST(event.UriUEEventAMF, event.PostUEEventFromAMF)
// register feature service gin.Engine
features.InitServiceEngine(app)
// var listenLocalhost bool = false
for _, rest := range conf.Rest {
// ipv4 goroutines
if rest.IPv4 != "" {
listen := rest.IPv4 + ":" + strconv.Itoa(int(rest.Port))
if strings.ToLower(rest.Scheme) == "https" {
go HttpListenTLS(listen, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
} else {
go HttpListen(listen, app)
}
}
// if rest.IPv4 != "0.0.0.0" && !listenLocalhost {
// listenLocalhost = true
// // 默认启动localhost侦听
// listenLocal := "127.0.0.1" + ":" + strconv.Itoa(int(rest.Port))
// if strings.ToLower(rest.Scheme) == "https" {
// go HttpListenTLS(listenLocal, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
// } else {
// go HttpListen(listenLocal, app)
// }
// }
// ipv6 goroutines
if rest.IPv6 != "" {
listenv6 := "[" + rest.IPv6 + "]" + ":" + strconv.Itoa(int(rest.Port))
if strings.ToLower(rest.Scheme) == "https" {
go HttpListenTLS(listenv6, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
} else {
go HttpListen(listenv6, app)
}
}
// if rest.IPv6 != "::" {
// // 默认启动localhost侦听
// listenv6Local := "[" + "::1" + "]" + ":" + strconv.Itoa(int(rest.Port))
// if strings.ToLower(rest.Scheme) == "https" {
// go HttpListenTLS(listenv6Local, rest.CaFile, rest.CertFile, rest.KeyFile, app)
// } else {
// go HttpListen(listenv6Local, app)
// }
// }
}
if conf.WebServer.Enabled {
fs := http.FileServer(http.Dir(conf.WebServer.RootDir))
http.Handle("/", fs)
for _, listen := range conf.WebServer.Listen {
if strings.ToLower(listen.Scheme) == "https" {
go HttpListenWebServerTLS(listen.Addr, listen.CaFile, listen.CertFile, listen.KeyFile, listen.ClientAuthType)
} else {
go HttpListenWebServer(listen.Addr)
}
}
}
select {}
}
// loadPprof 性能分析监控
func loadPprof(app *gin.Engine) {
pprofEnabled := config.Get("pprof.enabled")
if pprofEnabled != nil && pprofEnabled.(bool) {
app.Use(ginprom.PromMiddleware(nil))
app.GET("/metrics", ginprom.PromHandler(promhttp.Handler()))
pprofAddr := config.Get("pprof.addr").(string)
wg.Add(1)
// 启用pprof HTTP服务
go func(addr string) {
defer wg.Done()
fmt.Println(http.ListenAndServe(addr, nil))
}(pprofAddr)
}
}
// loadServer 多个HTTP服务启动
func loadServer(app *gin.Engine) {
httpArr := config.Get("rest")
if httpArr == nil {
logger.Errorf("rest config not found")
return
}
for _, v := range httpArr.([]any) {
rest := v.(map[string]any)
port := parse.Number(rest["port"])
ipv4 := fmt.Sprint(rest["ipv4"])
ipv6 := fmt.Sprint(rest["ipv6"])
schema := fmt.Sprint(rest["schema"])
if schema == "https" && schema != "<nil>" {
certFile := fmt.Sprint(rest["certfile"])
keyFile := fmt.Sprint(rest["keyfile"])
addr := ""
if ipv4 != "" && ipv4 != "<nil>" {
addr = fmt.Sprintf("%s:%d", ipv4, port)
}
if ipv6 != "" && ipv6 != "<nil>" {
addr = fmt.Sprintf("[%s]:%d", ipv6, port)
}
if addr == "" {
continue
}
// 启动HTTPS服务
wg.Add(1)
go func(addr string, certFile string, keyFile string) {
defer wg.Done()
err := app.RunTLS(addr, certFile, keyFile)
logger.Errorf("run tls err:%v", err)
}(addr, certFile, keyFile)
} else {
addr := ""
if ipv4 != "" && ipv4 != "<nil>" {
addr = fmt.Sprintf("%s:%d", ipv4, port)
}
if ipv6 != "" && ipv6 != "<nil>" {
addr = fmt.Sprintf("[%s]:%d", ipv6, port)
}
if addr == "" {
continue
}
// 启动HTTP服务
wg.Add(1)
go func(addr string) {
defer wg.Done()
err := app.Run(addr)
logger.Errorf("run err:%v", err)
}(addr)
}
}
}
// loadWebServer 前端静态资源服务
func loadWebServer() {
webEnabled := config.Get("webServer.enabled")
if webEnabled == nil {
logger.Errorf("webServer config not found")
return
}
if webEnabled.(bool) {
rootDir := config.Get("webServer.rootDir").(string)
if rootDir != "" {
var web *gin.Engine
gin.SetMode(gin.ReleaseMode)
web = gin.New()
web.Use(gin.Recovery())
gin.DisableConsoleColor()
web.StaticFS("/", http.Dir(rootDir))
// 多个HTTP服务启动
listenArr := config.Get("webServer.listen")
for _, v := range listenArr.([]any) {
listen := v.(map[string]any)
addr := fmt.Sprint(listen["addr"])
schema := fmt.Sprint(listen["schema"])
if schema == "https" && schema != "<nil>" {
certFile := fmt.Sprint(listen["certfile"])
keyFile := fmt.Sprint(listen["keyfile"])
if addr == "" || addr == "<nil>" {
continue
}
// 启动HTTPS服务
wg.Add(1)
go func(addr string, certFile string, keyFile string) {
defer wg.Done()
err := web.RunTLS(addr, certFile, keyFile)
logger.Errorf("web run tls err:%v", err)
}(addr, certFile, keyFile)
} else {
if addr == "" || addr == "<nil>" {
continue
}
// 启动HTTP服务
wg.Add(1)
go func(addr string) {
defer wg.Done()
err := web.Run(addr)
logger.Errorf("web run err:%v", err)
}(addr)
}
}
}
}
}