Compare commits
73
Commits
2d4cf580ee
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33cbaeb1cd | ||
|
|
6b4633fa5e | ||
|
|
9f34b4bdac | ||
|
|
da42adef91 | ||
|
|
62bfc47a0a | ||
|
|
1fa9442c1f | ||
|
|
aedea2ce2d | ||
|
|
1db5713183 | ||
|
|
d41ea50bd0 | ||
|
|
a892dce6ca | ||
|
|
9d1bee99ab | ||
|
|
eac9b2b4e9 | ||
|
|
07b78e1138 | ||
|
|
17f57175c7 | ||
|
|
49860c2f28 | ||
|
|
3b50e2f3f8 | ||
|
|
3cc193f57d | ||
|
|
78bd110b03 | ||
|
|
df904f5328 | ||
|
|
d5f7a2077e | ||
|
|
6d9123314c | ||
|
|
269b578d77 | ||
|
|
7edad64f93 | ||
|
|
c75a300d4c | ||
|
|
94392e13fd | ||
|
|
3cec6077d3 | ||
|
|
2118daa165 | ||
|
|
83c63819a7 | ||
|
|
3f70705c7a | ||
|
|
fd56dda836 | ||
|
|
bb6a929720 | ||
|
|
02a45da0be | ||
|
|
7264cf6d57 | ||
|
|
e94ca04f16 | ||
|
|
3c5c77b881 | ||
|
|
615ab2eb2e | ||
|
|
56310cc3c9 | ||
|
|
6fe7464779 | ||
|
|
3c56f1ae36 | ||
|
|
3df3b5b5f7 | ||
|
|
5050f4f113 | ||
|
|
d5d3feb5fc | ||
|
|
f490d9af0f | ||
|
|
aa3b792a6f | ||
|
|
2f463b772c | ||
|
|
21a5e210eb | ||
|
|
6caf373ab5 | ||
|
|
13a9b7007b | ||
|
|
970167c76c | ||
|
|
f8bf36f94b | ||
|
|
05559e2c16 | ||
|
|
955aba902b | ||
|
|
08a908c3f4 | ||
|
|
d63db9dd6c | ||
|
|
bbdced9633 | ||
|
|
e24f619ef9 | ||
|
|
5c44f044d7 | ||
|
|
4652a124ca | ||
|
|
f1393c2dd9 | ||
|
|
bf1f06fa6c | ||
|
|
cedc90d1f0 | ||
|
|
710e49e2e1 | ||
|
|
e2d17640ef | ||
|
|
5f5a2e2e9e | ||
|
|
05c7e9b9e8 | ||
|
|
55fe1d534d | ||
|
|
3220f9d138 | ||
|
|
fadc3560b6 | ||
|
|
e179731fa8 | ||
|
|
039ad74561 | ||
|
|
d03ff60eee | ||
|
|
d173205528 | ||
|
|
ce7c3cae68 |
No files matched your search
+23
@@ -0,0 +1,23 @@
|
||||
# ---> VisualStudioCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
.idea/
|
||||
|
||||
# Run temp file and dir
|
||||
restagent/backup/
|
||||
restagent/log/
|
||||
restagent/upload/
|
||||
restagent/software/
|
||||
restagent/database/
|
||||
restagent/license/
|
||||
restagent/restagent
|
||||
|
||||
__debug_bin*.exe
|
||||
docker/tar/*.tar
|
||||
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "调试模式",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "./restagent/restagent.go",
|
||||
"console": "integratedTerminal",
|
||||
"args": ["--env", "local"] // 走开发配置
|
||||
},
|
||||
{
|
||||
"name": "DEBUG restagent",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "d:/omc.git/be.ems/restagent/",
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "debug sshsvc",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "d:/omc.git/be.ems/sshsvc/sshsvc.go",
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "debug crontask",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "d:/omc.git/be.ems/crontask",
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "debug encyaml",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "d:/omc.git/be.ems/tools/encode",
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,73 @@
|
||||
# omc_api
|
||||
|
||||
OMC åŽç«¯
|
||||
OMC 后端
|
||||
|
||||
## 简单运行
|
||||
|
||||
```bash
|
||||
cd /home/manager/omc_api
|
||||
|
||||
go env -w CGO_ENABLED='1'
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go mod download
|
||||
|
||||
cd restagent/
|
||||
# 打包命名 omcDevApp
|
||||
go build -ldflags="-s -w" -o omcDevApp
|
||||
|
||||
# 启动
|
||||
./omcDevApp -c ./etc/restconf.yaml --env local
|
||||
|
||||
nohup ./omcDevApp -c ./etc/restconf.yaml > ./dev.log 2>&1 &
|
||||
|
||||
# 查找进程并杀死
|
||||
kill -9 $(ps aux | grep "omcDevApp" | grep -v grep | awk '{print $2}')
|
||||
ps aux | grep omcDevApp
|
||||
```
|
||||
|
||||
## 脚本
|
||||
|
||||
```bash
|
||||
ps aux | grep "omcDevApp"
|
||||
|
||||
process_id=$(ps aux | grep "omcDevApp" | grep -v grep | awk '{print $2}')
|
||||
if [ -n "$process_id" ]; then
|
||||
kill -9 "$process_id"
|
||||
else
|
||||
echo "未找到匹配的进程"
|
||||
fi
|
||||
|
||||
go version
|
||||
go mod download
|
||||
|
||||
cd restagent/
|
||||
go build -ldflags="-s -w" -o omcDevApp
|
||||
|
||||
BUILD_ID=dontKillMe
|
||||
nohup ./omcDevApp -c ./dev.yaml > ./dev.log 2>&1 &
|
||||
echo ok
|
||||
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
```bash
|
||||
docker build --build-arg VERSION=241101 -t omc:2.241101 .
|
||||
|
||||
docker run -it omc:2.241101 sh
|
||||
|
||||
-v /var/log/omc
|
||||
-v /etc/nginx
|
||||
-v /usr/local/omc/etc
|
||||
-v /usr/local/omc/static
|
||||
-v /usr/local/omc/upload
|
||||
-p 33022:22 \
|
||||
|
||||
docker run -d \
|
||||
--privileged=true \
|
||||
--restart=always \
|
||||
-e TZ="Asia/Shanghai" \
|
||||
-m 512M \
|
||||
--name omc_001 \
|
||||
omc:2.241101
|
||||
```
|
||||
@@ -0,0 +1,95 @@
|
||||
## 第一阶段 ====> Nodejs打包编译输出前端资源
|
||||
FROM node:20-alpine AS build-node
|
||||
|
||||
# 前端程序
|
||||
COPY ./omc_web /web
|
||||
RUN npm config set registry https://registry.npmmirror.com
|
||||
RUN cd /web && npm install && npm run build
|
||||
RUN touch /web/dist/config.js && echo '/*use nginx*/' | tee /web/dist/config.js
|
||||
|
||||
# 后端程序
|
||||
# COPY ./omc_api /api
|
||||
COPY ./omc_api/restagent/config /api/restagent/config
|
||||
COPY ./omc_api/restagent/etc/restconf.yaml /api/restagent/etc/restconf.yaml
|
||||
COPY ./omc_api/restagent/restagent.go /api/restagent/restagent.go
|
||||
COPY ./omc_api/features /api/features
|
||||
COPY ./omc_api/lib /api/lib
|
||||
COPY ./omc_api/src /api/src
|
||||
COPY ./omc_api/go.sum /api/go.sum
|
||||
COPY ./omc_api/go.mod /api/go.mod
|
||||
|
||||
# Docker文件
|
||||
COPY ./omc_api/docker/omc /docker
|
||||
|
||||
|
||||
## 第二阶段 ====> Go打包编译输出后端程序
|
||||
FROM ubuntu:22.04 AS build-golang
|
||||
|
||||
# 从上个阶段复制过来的文件
|
||||
COPY --from=build-node /web/dist /frontend
|
||||
COPY --from=build-node /api /backend
|
||||
COPY --from=build-node /docker /docker
|
||||
|
||||
# 安装 Go 和其他依赖
|
||||
RUN apt-get update && \
|
||||
apt-get install -y build-essential libpcap-dev curl \
|
||||
&& curl -OL https://dl.google.com/go/go1.22.5.linux-amd64.tar.gz \
|
||||
&& tar -C /usr/local -xzf go1.22.5.linux-amd64.tar.gz \
|
||||
&& rm go1.22.5.linux-amd64.tar.gz \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 设置 Go 环境变量
|
||||
ENV PATH="/usr/local/go/bin:${PATH}"
|
||||
ENV CGO_ENABLED 1
|
||||
ENV GOOS linux
|
||||
ENV GOPROXY https://goproxy.cn,direct
|
||||
|
||||
ARG VERSION
|
||||
RUN cd /backend && go mod download
|
||||
RUN cd /backend/restagent && go build -o omc -v -ldflags "-s -w \
|
||||
-X 'be.ems/lib/global.Version=${VERSION}' \
|
||||
-X 'be.ems/lib/global.BuildTime=`date`' \
|
||||
-X 'be.ems/lib/global.GoVer=`go version`'"
|
||||
|
||||
## 第三阶段 ====> 构建前后端融合镜像
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# 安装必要的软件包
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata \
|
||||
iputils-ping libpcap-dev \
|
||||
nginx openssh-server \
|
||||
&& ssh-keygen -A \
|
||||
&& adduser --disabled-password --gecos "" omcuser \
|
||||
&& echo 'omcuser:a9tU53r' | chpasswd \
|
||||
&& mkdir -p /home/omcuser/.ssh \
|
||||
&& chmod 700 /home/omcuser/.ssh \
|
||||
&& touch /home/omcuser/.ssh/authorized_keys \
|
||||
&& chmod 600 /home/omcuser/.ssh/authorized_keys \
|
||||
&& chown -R omcuser:omcuser /home/omcuser/.ssh \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 设置时区和语言环境
|
||||
ENV TZ="Asia/Shanghai"
|
||||
ENV LANG="en_US.UTF-8"
|
||||
ENV APPENV="prod"
|
||||
|
||||
WORKDIR /usr/local/etc/omc
|
||||
COPY --from=build-golang /frontend /usr/local/bin/web
|
||||
COPY --from=build-golang /backend/restagent/omc /usr/local/bin/omc
|
||||
COPY --from=build-golang /docker/omc.yaml ./omc.yaml
|
||||
COPY --from=build-golang /docker/static ./static
|
||||
COPY --from=build-golang /docker/logs /var/log/omc
|
||||
COPY --from=build-golang /docker/nginx/cert /etc/nginx/cert
|
||||
COPY --from=build-golang /docker/nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
EXPOSE 22 80 443 33030 33443 33033 33060
|
||||
|
||||
CMD ["/bin/sh", "-c", "service ssh start && service nginx start && /usr/local/bin/omc --env ${APPENV} -c /usr/local/etc/omc/omc.yaml"]
|
||||
|
||||
# 构建
|
||||
# docker build --build-arg VERSION=241211 -t omc:2.2412.1 .
|
||||
# docker run -it omc:2.241211 sh
|
||||
# service ssh start && service nginx start && /usr/local/bin/omc --env prod -c /usr/local/etc/omc/omc.yaml
|
||||
@@ -0,0 +1,46 @@
|
||||
FROM golang:1.22-alpine AS buildGo
|
||||
|
||||
ARG VERSION
|
||||
|
||||
ENV CGO_ENABLED 1
|
||||
ENV GOOS linux
|
||||
ENV GOPROXY https://goproxy.cn,direct
|
||||
|
||||
## 安装时区工具
|
||||
RUN apk add --no-cache gcc musl-dev libpcap-dev tzdata openssh \
|
||||
&& ssh-keygen -A \
|
||||
&& adduser -D omcuser \
|
||||
&& echo 'omcuser:password' | chpasswd \
|
||||
&& mkdir /home/omcuser/.ssh \
|
||||
&& chmod 700 /home/omcuser/.ssh
|
||||
|
||||
# 设置时区和语言环境
|
||||
ENV TZ="Asia/Shanghai"
|
||||
ENV LANG="en_US.UTF-8"
|
||||
|
||||
WORKDIR /backend
|
||||
|
||||
## 复制实际需要的文件到工作目录
|
||||
COPY ./restagent/config ./restagent/config
|
||||
COPY ./restagent/etc ./restagent/etc
|
||||
COPY ./restagent/restagent.go ./restagent/restagent.go
|
||||
COPY ./features ./features
|
||||
COPY ./lib ./lib
|
||||
COPY ./src ./src
|
||||
COPY ./go.sum ./
|
||||
COPY ./go.mod ./
|
||||
|
||||
RUN cd /backend && go mod download
|
||||
RUN cd /backend/restagent && go build -o omc_api -v -ldflags "-s -w \
|
||||
-X 'be.ems/lib/global.Version=${VERSION}' \
|
||||
-X 'be.ems/lib/global.BuildTime=`date`' \
|
||||
-X 'be.ems/lib/global.GoVer=`go version`'"
|
||||
|
||||
EXPOSE 33030 33033 33040 80 22
|
||||
|
||||
CMD [ "/backend/restagent/omc_api", "--env", "prod", "-c", "/backend/restagent/etc/restconf.yaml"]
|
||||
|
||||
# 构建
|
||||
# docker build --build-arg VERSION=241031 -t omc:2.241031 .
|
||||
# docker run -it omc:2.241031 sh
|
||||
# /backend/restagent/omc_api --env prod -c /backend/restagent/etc/restconf.yaml
|
||||
@@ -0,0 +1,109 @@
|
||||
# Docker 编译
|
||||
|
||||
编译目录内含 `omc_web` 和 `omc_api` 两个项目代码
|
||||
|
||||
将后端项目代码中的 `docker/Dockerfile` 文件移动到最外层目录下,`docker/omc`是内部文件挂载的文件资源。
|
||||
|
||||
编译目录结构
|
||||
|
||||
```text
|
||||
probject
|
||||
├── omc_web 目录-前端项目代码
|
||||
├── omc_api 目录-后端项目代码
|
||||
└── Dockerfile 文件-Docker编译需要
|
||||
```
|
||||
|
||||
内部文件资源
|
||||
|
||||
| 路径 | 说明 |
|
||||
| --------------------------- | -------------------------- |
|
||||
| /usr/local/etc/omc/static | 网管静态资源文件路径 |
|
||||
| /usr/local/etc/omc/upload | 网管上传文件资源路径 |
|
||||
| /usr/local/etc/omc/omc.yaml | 网管配置文件 |
|
||||
| /usr/local/etc/omc | 网管与网元之间相关文件 |
|
||||
| /etc/nginx/cert | 网管前端 nginx 代理证书 |
|
||||
| /etc/nginx/nginx.conf | 网管前端 nginx 代理配置 |
|
||||
| /var/log | 网管相关日志输出 |
|
||||
| /tmp/omc | 存放从网元拉取到本地的文件 |
|
||||
|
||||
端口声明
|
||||
|
||||
| 端口 | 说明 |
|
||||
| ----- | ----------------------------- |
|
||||
| 22 | 网管 容器内部 SSH 服务 |
|
||||
| 80 | 网管 Nginx HTTP 服务 |
|
||||
| 443 | 网管 Nginx HTTP2 服务 |
|
||||
| 33030 | 网管后台 API HTTP 服务 |
|
||||
| 33443 | 网管后台 API HTTP2 服务 |
|
||||
| 33033 | 网管信令跟踪 UDP 协议接收服务 |
|
||||
| 33060 | 网管性能分析监控 metrics 服务 |
|
||||
|
||||
## 编译
|
||||
|
||||
- `VERSION` 变量是后端程序打包版本号注入
|
||||
|
||||
```sh
|
||||
|
||||
docker build --build-arg VERSION="241212" -t omc:2.2412.1 .
|
||||
|
||||
```
|
||||
|
||||
## 部署
|
||||
|
||||
- `APPENV` 程序启动环境变量 local、prod (-e APPENV="local")
|
||||
|
||||
```sh
|
||||
|
||||
docker run -d \
|
||||
--privileged=true \
|
||||
--restart=always \
|
||||
-p 8822:22 \
|
||||
-p 8880:80 \
|
||||
-p 8884:443 \
|
||||
-p 8830:33030 \
|
||||
-p 8833:33033 \
|
||||
-p 8860:33060 \
|
||||
-v /home/manager/probject/omc_api/docker/omc:/usr/local/etc/omc \
|
||||
-v /home/manager/probject/omc_api/docker/omc/logs:/var/log \
|
||||
-v /home/manager/probject/omc_api/docker/omc/tmp:/tmp/omc \
|
||||
-v /home/manager/probject/omc_api/docker/omc/nginx/cert:/etc/nginx/cert \
|
||||
-v /home/manager/probject/omc_api/docker/omc/nginx/nginx.conf:/etc/nginx/nginx.conf \
|
||||
-e TZ="Asia/Shanghai" \
|
||||
-e APPENV="prod" \
|
||||
-m 512M \
|
||||
--name omc \
|
||||
omc:2.2412.1
|
||||
|
||||
```
|
||||
|
||||
## 调试
|
||||
|
||||
```sh
|
||||
|
||||
docker run -it omc:xxx sh
|
||||
|
||||
docker exec -it omc:xxx sh
|
||||
|
||||
service ssh start && service nginx start && /usr/local/bin/omc --env prod -c /usr/local/etc/omc/omc.yaml
|
||||
|
||||
```
|
||||
|
||||
## 镜像导出导入
|
||||
|
||||
```sh
|
||||
docker save redis:7.2.5 -o redis_7.2.5.tar
|
||||
docker save mysql:8.0.39 -o mysql_8.0.39.tar
|
||||
docker save omc:2.2412.1 -o omc_2.2412.1.tar
|
||||
|
||||
docker load -i redis_7.2.5.tar
|
||||
docker load -i mysql_8.0.39.tar
|
||||
docker load -i omc_2.2412.1.tar
|
||||
|
||||
sudo bash omc-docker.sh install
|
||||
|
||||
mkdir omc-r2.2412.1-ub22-cloud
|
||||
tar -czvf omc-r2.2412.1-ub22-cloud.tgz omc-r2.2412.1-ub22-cloud/
|
||||
tar -xzvf omc-r2.2412.1-ub22-cloud.tgz
|
||||
|
||||
scp omc_2.2412.1.tar manager@192.168.9.59:/home/manager/omc-r2.2412.1-ub22-cloud/tar/
|
||||
```
|
||||
@@ -0,0 +1,158 @@
|
||||
#!/bin/bash
|
||||
|
||||
OMC_CONTAINER_NAME="omc"
|
||||
MYSQL_CONTAINER_NAME="omc_mysql"
|
||||
REDIS_CONTAINER_NAME="omc_redis"
|
||||
|
||||
# usage
|
||||
usage() {
|
||||
echo "Usage: bash omc-docker.sh [install|uninstall|restart|start|stop]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# install
|
||||
install(){
|
||||
echo "====================== Install container omc service ====================="
|
||||
echo "Install mysql and redis service program, default N (Y/N):"
|
||||
read DB_SERVICE
|
||||
DB_SERVICE=${DB_SERVICE:-"N"}
|
||||
echo "Select the image in the tar directory (omc_2.2412.1.tar):"
|
||||
read OMC_FILE
|
||||
OMC_FILE=${OMC_FILE:-"omc_2.2412.1.tar"}
|
||||
echo "Container time zone (Asia/Shanghai):"
|
||||
read OMC_TZ
|
||||
OMC_TZ=${OMC_TZ:-"Asia/Shanghai"}
|
||||
echo "Container service http port (80):"
|
||||
read OMC_HTTP_PORT
|
||||
OMC_HTTP_PORT=${OMC_HTTP_PORT:-"80"}
|
||||
echo "Container service https port (443):"
|
||||
read OMC_HTTPS_PORT
|
||||
OMC_HTTPS_PORT=${OMC_HTTPS_PORT:-"443"}
|
||||
echo "Container name ($OMC_CONTAINER_NAME):"
|
||||
read OMC_CONTAINER_NAME
|
||||
OMC_CONTAINER_NAME=${OMC_CONTAINER_NAME:-"omc"}
|
||||
echo "==> Checking Docker version $OMC_CONTAINER_NAME"
|
||||
sed -i "s/^OMC_CONTAINER_NAME=.*/OMC_CONTAINER_NAME=\"$OMC_CONTAINER_NAME\"/" ./omc-docker.sh
|
||||
echo "===================== Install container omc service ====================="
|
||||
|
||||
echo "==> Checking Docker version"
|
||||
if sudo docker -v > /dev/null 2>&1; then
|
||||
sudo docker -v
|
||||
else
|
||||
echo "Docker is not available or sudo privileges are not granted."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> Created service network"
|
||||
NETWORK="omcnet"
|
||||
if ! docker network ls --filter name=$NETWORK -q | grep -q .; then
|
||||
docker network create $NETWORK
|
||||
echo "Network '$NETWORK' created."
|
||||
else
|
||||
echo "Network '$NETWORK' already exists."
|
||||
fi
|
||||
|
||||
echo "==> Install service mysql and redis container"
|
||||
MYSQL_CONTAINER_NAME="omc_mysql"
|
||||
REDIS_CONTAINER_NAME="omc_redis"
|
||||
if [[ "$DB_SERVICE" =~ ^[Yy]$ ]]; then
|
||||
# MySQL Config
|
||||
mysql_container=$(docker ps --filter "name=$MYSQL_CONTAINER_NAME" --format "{{.Names}}")
|
||||
if [[ -z "$mysql_container" ]]; then
|
||||
echo "MySQL container is not running. Installing MySQL container..."
|
||||
|
||||
docker load --input $(pwd)/tar/mysql_8.0.39.tar
|
||||
MYSQL_IMAGE="mysql:8.0.39"
|
||||
MYSQL_ROOT_PASSWORD="1000omc@kp!"
|
||||
SQL_FILE_PATH="$(pwd)/sql/install/omc_db.sql"
|
||||
MYSQL_DATA=/usr/local/etc/$MYSQL_CONTAINER_NAME/data
|
||||
mkdir -p $MYSQL_DATA
|
||||
docker run --privileged=true --restart=always -e TZ="$OMC_TZ" \
|
||||
-e MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD \
|
||||
-v $SQL_FILE_PATH:/docker-entrypoint-initdb.d/database.sql \
|
||||
-v $MYSQL_DATA:/var/lib/mysql \
|
||||
--network $NETWORK \
|
||||
--name $MYSQL_CONTAINER_NAME \
|
||||
-d $MYSQL_IMAGE
|
||||
else
|
||||
echo "MySQL container is already running: $mysql_container"
|
||||
fi
|
||||
|
||||
# Redis Config
|
||||
redis_container=$(docker ps --filter "name=$REDIS_CONTAINER_NAME" --format "{{.Names}}")
|
||||
if [[ -z "$redis_container" ]]; then
|
||||
echo "Redis container is not running. Installing Redis container..."
|
||||
docker load --input $(pwd)/tar/redis_7.2.5.tar
|
||||
REDIS_IMAGE="redis:7.2.5"
|
||||
REDIS_PASSWORD="helloearth"
|
||||
REDIS_DATA=/usr/local/etc/$REDIS_CONTAINER_NAME/data
|
||||
mkdir -p $REDIS_DATA
|
||||
docker run --privileged=true --restart=always -e TZ="$OMC_TZ" \
|
||||
-e REDIS_PASSWORD=$REDIS_PASSWORD \
|
||||
-v $REDIS_DATA:/data \
|
||||
--network $NETWORK \
|
||||
--name $REDIS_CONTAINER_NAME \
|
||||
-d $REDIS_IMAGE
|
||||
else
|
||||
echo "Redis container is already running: $redis_container"
|
||||
fi
|
||||
else
|
||||
echo "You chose not to install MySQL and Redis containers."
|
||||
fi
|
||||
|
||||
echo "==> Loading service omc container"
|
||||
docker load --input $(pwd)/tar/$OMC_FILE
|
||||
|
||||
if [ ! -d /usr/local/etc/omc ]; then
|
||||
mkdir -p /usr/local/etc/omc
|
||||
cp -rf ./omc/* /usr/local/etc/omc
|
||||
fi
|
||||
|
||||
OMC_IMAGE=$(echo "$OMC_FILE" | sed -e 's/_/:/' -e 's/\.tar$//')
|
||||
docker run --privileged=true --restart=always -m 512M \
|
||||
-v /usr/local/etc/omc:/usr/local/etc/omc \
|
||||
-v /usr/local/etc/omc/logs:/var/log \
|
||||
-v /usr/local/etc/omc/tmp:/tmp/omc \
|
||||
-v /usr/local/etc/omc/nginx/cert:/etc/nginx/cert \
|
||||
-v /usr/local/etc/omc/nginx/nginx.conf:/etc/nginx/nginx.conf \
|
||||
-e TZ=$OMC_TZ \
|
||||
-p $OMC_HTTP_PORT:80 \
|
||||
-p $OMC_HTTPS_PORT:443 \
|
||||
--network $NETWORK \
|
||||
--name $OMC_CONTAINER_NAME \
|
||||
-d $OMC_IMAGE
|
||||
|
||||
echo "Running service $OMC_CONTAINER_NAME container http port $OMC_HTTP_PORT / https port $OMC_HTTPS_PORT"
|
||||
}
|
||||
|
||||
# uninstall
|
||||
uninstall(){
|
||||
docker stop $OMC_CONTAINER_NAME && docker rm $OMC_CONTAINER_NAME
|
||||
docker stop $REDIS_CONTAINER_NAME && docker rm $REDIS_CONTAINER_NAME
|
||||
docker stop $MYSQL_CONTAINER_NAME && docker rm $MYSQL_CONTAINER_NAME
|
||||
}
|
||||
|
||||
# According to the input parameters, the corresponding method will be selected for execution, and the instructions will be executed without input.
|
||||
case "$1" in
|
||||
"install")
|
||||
install
|
||||
;;
|
||||
"uninstall")
|
||||
uninstall
|
||||
;;
|
||||
"restart")
|
||||
echo "restart container $OMC_CONTAINER_NAME"
|
||||
docker restart $OMC_CONTAINER_NAME
|
||||
;;
|
||||
"start")
|
||||
echo "start container $OMC_CONTAINER_NAME"
|
||||
docker start $OMC_CONTAINER_NAME
|
||||
;;
|
||||
"stop")
|
||||
echo "stop container $OMC_CONTAINER_NAME"
|
||||
docker stop $OMC_CONTAINER_NAME
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1 @@
|
||||
# unique
|
||||
@@ -0,0 +1,13 @@
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MIICCAKCAgEAlgLQ4jKKVmeAuZG3w7+QNXh/hJIba+/eHV3PA0zGBCyN63lqOED/
|
||||
87/WzUKQxLuzJeSiQ3EGPUit/aVRS8guAajFXLx81Lj5BaID8GWhJziQUk97GX6E
|
||||
UyAvHqZdtJNNp30ds3A5KL/p09Wo6HGvCYwYCFdJwkR26PGFitjDR2KYkuCzAnbx
|
||||
iiMAb67pP0KtGBkShgvJUTnSs1Klpofh9ylf20QuR9oZ9+NtOMhGa3ttNIcIwxem
|
||||
Uqk8n5OP9PM5DX2TqL4fD4o43+UNKPdSbyv2dOCyLTGD6nmz/Jwx7vd1s+DKeWIq
|
||||
y/Sce8+DybCuto+tJACsWRh9W6JL/O4vBuZeU+wp8V4/kGutcsVisAaKKGgJEMSi
|
||||
FEMu5FQRKdi2vP4wbZcG5usmgRlXQN9rJXuJ3yigmj8ffrdyCCDAMniTflta02n+
|
||||
RJv0329h4OYzdMkb1+IMwr+0go0KfiahDfaCeO/8OYlA5dzeVAbGE8dHTG2j9Lpr
|
||||
M/SoAcObUEHnMDS0FCrnyMVimUKOZoPhpo/xUdVFYoM73okFN0qG76b/Vj6Je1SN
|
||||
xOV8e0riVJnB4j07CnXpNuUDBgxqaVWpoZa2NU/94KwCukuPZppzk3d3QrfV01lq
|
||||
XKlIcvLVW1rrq1Ty0f9YMqim7K6LE4/kUBurA4nGUyFx/p+KfxkcysMCAQI=
|
||||
-----END DH PARAMETERS-----
|
||||
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID4TCCAcmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAQMQ4wDAYDVQQKEwVHbyBD
|
||||
QTAeFw0yNDAxMDkwNzEyNTVaFw0zNDAxMDYwNzEyNTVaMBQxEjAQBgNVBAoTCUdv
|
||||
IE9NQyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPidCkI9UhWg
|
||||
7EOKoS/JGH95Q3ekfU+rK0EULJbJfeszJkYZ2u2gQ5gbBcyWUQvFhOuFpgcchsGA
|
||||
Vy3QfudO0Jxysf67rBFFjyB2NQXc68B3zJS5L+N9P0XEwgz9hr9rijDrNT8RvY+z
|
||||
L8Blrbl4oBEssOEyFOBYkHIMlvUEIMZYaA1NPA+Wwk8x3ENS1YVGml5u7JBk2oe2
|
||||
gHDktHe98hU0Nd88K3ZxGte3pwmeynMslTw9Oct6Wy2fu0zcZlnJZPmoY2LXYyhx
|
||||
mj9oO3n5KgXxHlfGxPl5N2lqu/tmAr/1fAwUKVHUZzpmIbEyqMTDow8qTvjYa4o/
|
||||
41Bvg1JOrDsCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMB
|
||||
Af8wHQYDVR0OBBYEFJ2woDwnDKwmU3bU8cA+EAG0MVMwMA0GCSqGSIb3DQEBCwUA
|
||||
A4ICAQAuT4aMkcJWZeAJXGjSxSCoLclnrQw4SAVjNvIUNS83+0flHLTFzj1fAU4M
|
||||
/RZjZE22mdF+wgAhMfC+zoJq7plHELSkG9HY1dmscK7MVRrVdnooYD+HXS8rjOaD
|
||||
oUapFmEK5ivXF6Cx1gQoPeo/Q0FRDd9Ky5rjB0vWFxsnU/BZkfOLCC2zQoZcL+UN
|
||||
rmSq+iPkUMvFDVWSR/XY+xtXaW9GboqaqtoNvR24RSquI5xe1Co7JuDuu+j83lv/
|
||||
5YpOG14pNA3IF6TNFChR63l/VkaT15QDSnKxSgIQdcaPuv9yvA7OPIiaTOAqcDKi
|
||||
4RSTqRezh6TnbWIFSJI03EY8gFa7PkelcWqurCXgc4vevC3bLAHuys4QIVboq0yw
|
||||
CmCMVmJtgyXT15yc4x+ivwHyDT25wI2ynPnoXgKqzudFav0ZhoR7l2YmH2by7wrN
|
||||
5AnNbyer72NJhKRleLyboPtqWwTLfvtOW2Aqbg+cWKwTq9NNAqJ47tZ1ZrCuWI/H
|
||||
oOehNKM5QpW5k6shWuOmhYD9kROE/D1U9huzGEzijUZkT4yUF0udCNoFofz6wl4t
|
||||
Czk1+Pjd3tecIj9/NitBiDzjCPJVXeAOphvCO0Z0R5fKA+Y/4kd+HmiuNiW1tnGG
|
||||
D7z+beF+SsnagRquwdfZTpICfu/2+ogHwfxpsm8cHhx8DzMslA==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,18 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC2jCCAcKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQKEwlHbyBP
|
||||
TUMgQ0EwHhcNMjQwMTA5MDcxMjU1WhcNMzQwMTA2MDcxMjU1WjAVMRMwEQYDVQQK
|
||||
EwpPTUMgU2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApSTG
|
||||
HNOWScYVHHiGw9z8q2u3ZMUaOFBm6+F4p4PrpM1h3FtHmYv5IWr5kqoMgCU/FmPG
|
||||
HrSqDzrm+J4QMdguq40Jd4QOadiDg5oyLIM6Su32sjtG/y5an3abtY9hNCoWDdpy
|
||||
kNRb1i9NQ2uTSBHm1lTVWutZWgm7D9jES8JB2byDwAOONwGlqAw6buxUlIP2vCtn
|
||||
SpMF8Mqdypnw8K17DLXpP+D8Exw4mjOmJEVOGnw/pinjDCHm9SEiFtagdXIWliwl
|
||||
DgbyVeSE70JhaGV2bGlmldV2sN2qPvG/W99pCeObxNcCko9JdJqsDVQTiOTY6uaH
|
||||
o/GdDnzZh4TbbDutDQIDAQABozYwNDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAww
|
||||
CgYIKwYBBQUHAwEwDQYDVR0OBAYEBAECAwQwDQYJKoZIhvcNAQELBQADggEBAJY6
|
||||
eI54wSn+kNteFEdoFS2jVM+GAMS0x4blX2wzNro6HqhlYC6oJ8TxRS6V22ugWLFX
|
||||
M/pcqV5FA1XCSibYdwscdaoUSUYc6inlkHxrbfSryiQqXAkEv8Ote3dqtOu7Z0BY
|
||||
PkykdMrCUXn5ksYgoTa7G1CdAiaKMeuTz801l1g8AIOpNV1+Xhi29TKA134VDW9S
|
||||
2aDcD6jEs63rqKx/knStli0F58N0kOKjmmt45stP90o5NsshAMumzP0xhfwC94Gg
|
||||
eBXg6ThM3nuOBQyzPEtUZioRKKV4XmgZF/F4ePCnS4ST9ft09kx7UcR9MVzGIHov
|
||||
whwVw6o5O7h1xQr6Pjw=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEApSTGHNOWScYVHHiGw9z8q2u3ZMUaOFBm6+F4p4PrpM1h3FtH
|
||||
mYv5IWr5kqoMgCU/FmPGHrSqDzrm+J4QMdguq40Jd4QOadiDg5oyLIM6Su32sjtG
|
||||
/y5an3abtY9hNCoWDdpykNRb1i9NQ2uTSBHm1lTVWutZWgm7D9jES8JB2byDwAOO
|
||||
NwGlqAw6buxUlIP2vCtnSpMF8Mqdypnw8K17DLXpP+D8Exw4mjOmJEVOGnw/pinj
|
||||
DCHm9SEiFtagdXIWliwlDgbyVeSE70JhaGV2bGlmldV2sN2qPvG/W99pCeObxNcC
|
||||
ko9JdJqsDVQTiOTY6uaHo/GdDnzZh4TbbDutDQIDAQABAoIBAHxE49+lSJ5TNGes
|
||||
Op0AmhHUiLiHqWde+VPe4xALMTNeaZmMBqEAt4PyH8PBuo5jeMm8YsWQZbf4Nv42
|
||||
0zDu4I+vHcSV1tLHXo+VZNQiG6du0gjkmlRD6WW9twY00oySbu4Vx8g8RK80AQwO
|
||||
01GURwRZ6gL0vtQGJoGSOIRZtXvGLltVR52OfkgNMjNepwtJvMV7PW5xYwEcnx+i
|
||||
sZD/6hl49Qv5g4dCCGrnr8Garx9+cUkVP/ipkBnjyKACfzYQhoauo03Rv4iuNdy6
|
||||
QD9KB95ALHq66vYXF72YW75JQhQ3C1qGcghNn68RIlufSnA7D7J9VCG5VSXfVrk2
|
||||
a5Xw2HECgYEAzaXU75hl87fmf88X+8M6+OuaMnnLAwIadbcecakkO4bgzNF1SYwv
|
||||
dbZ608LvdUt+BYVU43CCX3//a/MI+Ncp5sk85TLsXUxXGWonO1zXpa3+BAEXJe1n
|
||||
xnWVdytWMeoyzhBZ/Vkx7/NAu5WSViXgQ3trB0Wr3OGw3Nksb4Son8cCgYEAzZQc
|
||||
SlglEiU+Z+BsCV07FEkU6xgsmxQQuptPuGcm713Ik8c8a5KAyjbhpp+oBvn8v69i
|
||||
hVGHcFmZYeazBL39dC4/6E/wDOVEwN2fY8oYBnrPvoz7FUTvObRjZakrgVj+XAjS
|
||||
lg9RuMm1tYPFR52V5BTngJ9Rkj/AewxWnGMDtIsCgYEAng1i/5ZQXSUs+XPwCeY9
|
||||
b8yb4Ulr9u7p6SkJM+/8UefS5HfjPdiJLV5HPnOm2K5ht9qGqJrzCHT2mT/b2Gx9
|
||||
3ssxizI9KWOf2X+VkXFEqCh2fxtbcCHrTUNX0ZQ0Ff7adzdoAmhIEhQR31oQczd/
|
||||
Cj5Tvu4ULZoj9UjQdxEtDEcCgYAYrW3T8s7IZdYe7A6r9RgRcFBlhCpel0MG03v3
|
||||
W9KNq0lXi/QRya1SGNJviPzHkZyoeeourMHAV9EUsnfM2u2g06hyP55GPgNJz5DB
|
||||
jtHhfT6Q1iWRwQuidqfz3SHOzhsCe0CkKMSblQMN/fphhWYn0eaURwuoraRyYOHI
|
||||
tg4MzwKBgGImdyBx/l6bkWa4GywZ9iw5RDe7KYN9UclnBcHDkIELXskp8bTbwpBy
|
||||
m/IyLC5eLOzdK7c2Odtd3LP/AG5fYPAzQ5S6YmSDPp1JEKODbg51wcMJpLSvG2Q/
|
||||
P5paV/ZAKbxgXpilBrjSejM/QLYqD8756z5lgo5biR7bGkBA+nkj
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -0,0 +1,189 @@
|
||||
user www-data;
|
||||
worker_processes auto;
|
||||
pid /run/nginx.pid;
|
||||
include /etc/nginx/modules-enabled/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
# multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
##
|
||||
# Basic Settings
|
||||
##
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
types_hash_max_size 2048;
|
||||
server_tokens off;
|
||||
|
||||
# server_names_hash_bucket_size 64;
|
||||
# server_name_in_redirect off;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
##
|
||||
# SSL Settings
|
||||
##
|
||||
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_dhparam /etc/nginx/cert/dhparams.pem;
|
||||
|
||||
##
|
||||
# Logging Settings
|
||||
##
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
access_log /var/log/nginx/access.log main;
|
||||
error_log /var/log/nginx/error.log;
|
||||
|
||||
##
|
||||
# Gzip Settings
|
||||
##
|
||||
|
||||
gzip on;
|
||||
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
##
|
||||
# Virtual Host Configs
|
||||
##
|
||||
keepalive_timeout 65;
|
||||
client_max_body_size 1024m;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name localhost;
|
||||
#if ($scheme = "http") {
|
||||
# return 301 https://$host$request_uri;
|
||||
#}
|
||||
|
||||
client_max_body_size 100M;
|
||||
keepalive_timeout 180s;
|
||||
|
||||
# OMC
|
||||
location / {
|
||||
root /usr/local/bin/web;
|
||||
#root /usr/local/etc/omc/frontend;
|
||||
|
||||
try_files $uri $uri/ /index.html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
location /omc-api/ {
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
proxy_connect_timeout 180s;
|
||||
proxy_send_timeout 180s;
|
||||
proxy_read_timeout 180s;
|
||||
|
||||
proxy_pass http://127.0.0.1:33030/;
|
||||
}
|
||||
|
||||
location /api/rest/ {
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
proxy_pass http://127.0.0.1:33030/api/rest/;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
return 301 http://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name localhost;
|
||||
|
||||
client_max_body_size 100M;
|
||||
keepalive_timeout 180s;
|
||||
|
||||
ssl_certificate /etc/nginx/cert/omc-server.crt;
|
||||
ssl_certificate_key /etc/nginx/cert/omc-server.key;
|
||||
|
||||
ssl_session_timeout 5m;
|
||||
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
|
||||
|
||||
# OMC
|
||||
location / {
|
||||
root /usr/local/bin/web;
|
||||
#root /usr/local/etc/omc/frontend;
|
||||
|
||||
try_files $uri $uri/ /index.html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
location /omc-api/ {
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
proxy_connect_timeout 180s;
|
||||
proxy_send_timeout 180s;
|
||||
proxy_read_timeout 180s;
|
||||
|
||||
proxy_pass https://127.0.0.1:33443/;
|
||||
}
|
||||
|
||||
location /api/rest/ {
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
proxy_pass https://127.0.0.1:33443/api/rest/;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
# file: log file name
|
||||
# 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
|
||||
logger:
|
||||
file: "/var/log/restagent.log"
|
||||
level: debug
|
||||
duration: 24
|
||||
count: 2
|
||||
|
||||
# rest agent listen ipv4/v6 and port, support multiple routines
|
||||
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
||||
# clientAuthType: 0:NoClientCert (default), 1:RequestClientCert, 2:RequireAnyClientCert,
|
||||
# 3:VerifyClientCertIfGiven, 4:RequireAndVerifyClientCerts
|
||||
rest:
|
||||
- ipv4: 0.0.0.0
|
||||
ipv6:
|
||||
port: 33030
|
||||
scheme: http
|
||||
- ipv4: 0.0.0.0
|
||||
ipv6:
|
||||
port: 33443
|
||||
scheme: https
|
||||
clientAuthType: 0
|
||||
caFile: /etc/nginx/cert/omc-ca.crt
|
||||
certFile: /etc/nginx/cert/omc-server.crt
|
||||
keyFile: /etc/nginx/cert/omc-server.key
|
||||
|
||||
webServer:
|
||||
enabled: false
|
||||
|
||||
database:
|
||||
type: mysql
|
||||
user: root
|
||||
password: "1000omc@kp!"
|
||||
host: "omc_mysql"
|
||||
port: 3306
|
||||
name: "omc_db"
|
||||
connParam: charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True
|
||||
backup: "/usr/local/etc/omc/database"
|
||||
|
||||
# Redis data cache
|
||||
redis:
|
||||
dataSource:
|
||||
# OMC system db
|
||||
default:
|
||||
port: 6379 # Redis port
|
||||
host: "omc_redis" # Redis host
|
||||
password: "helloearth"
|
||||
db: 10 # Redis db_num
|
||||
# used to specify the default data source for multiple data resourece
|
||||
defaultDataSourceName: "default"
|
||||
|
||||
# sleep: time delay for after write buffer (millisecond)
|
||||
# deadLine: timeout for io read and write (second)
|
||||
mml:
|
||||
sleep: 200
|
||||
deadLine: 10
|
||||
sizeRow: 600
|
||||
sizeCol: 128
|
||||
bufferSize: 65535
|
||||
|
||||
# Tracking configuration
|
||||
trace:
|
||||
enabled: true
|
||||
host: "0.0.0.0" # Fill in the specific IP address
|
||||
port: 33033
|
||||
|
||||
# NE config
|
||||
ne:
|
||||
user: omcuser
|
||||
etcdir: /usr/local/etc
|
||||
bindir: /usr/local/bin
|
||||
omcdir: /usr/local/omc
|
||||
scpdir: /tmp
|
||||
licensedir: /usr/local/etc/{neType}/license
|
||||
# backup etc list of IMS,no space
|
||||
etcListIMS: "{*.yaml,mmtel,vars.cfg}"
|
||||
etcListDefault: "{*.yaml,*.conf,*.cfg}"
|
||||
# true/false to overwrite config file when dpkg ne software
|
||||
dpkgOverwrite: false
|
||||
# dpkg timeout (second)
|
||||
dpkgTimeout: 180
|
||||
|
||||
# chk2ne: true/false, if put OmcNeConfig parameters to NE
|
||||
omc:
|
||||
uriPrefix: "/omc/rest"
|
||||
neType: OMC
|
||||
neId: 001
|
||||
rmUID: 4400HX101
|
||||
neName: OMC
|
||||
province: GD
|
||||
vendor: ""
|
||||
dn: 4600
|
||||
chk2ne: false
|
||||
sn: "-"
|
||||
checksign: false
|
||||
rootDir: ./
|
||||
binDir: ./bin
|
||||
backup: /usr/local/omc/backup
|
||||
upload: /usr/local/omc/upload
|
||||
frontUpload: /usr/local/omc/upload
|
||||
frontTraceDir: /usr/local/omc/trace
|
||||
software: /usr/local/omc/software
|
||||
license: /usr/local/omc/license
|
||||
gtpUri: gtp:192.168.2.219:2152
|
||||
checkContentType: false
|
||||
testMode: false
|
||||
rbacMode: true
|
||||
runDir:
|
||||
cmdTimeout: 120
|
||||
|
||||
# Alarm module setting
|
||||
# Forward interface:
|
||||
# TLS Skip verify: true/false
|
||||
# email/sms
|
||||
# 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:
|
||||
alarmEmailForward:
|
||||
enable: true
|
||||
emailList:
|
||||
smtp: mail.smtp.com
|
||||
port: 25
|
||||
user: smtpext@smtp.com
|
||||
password: "1000smtp@omc!"
|
||||
tlsSkipVerify: true
|
||||
alarmSMSForward:
|
||||
enable: true
|
||||
mobileList: "1006,1008"
|
||||
smscAddr: "192.168.14.212:2775"
|
||||
systemID: "123456"
|
||||
password: "123456"
|
||||
systemType: "UTRAN"
|
||||
dataCoding: 0
|
||||
serviceNumber: "OMC"
|
||||
sms:
|
||||
apiURL: http://smsc.xxx.com/
|
||||
accessKeyID: xxxx
|
||||
accessKeySecret: xxxx
|
||||
signName: xxx SMSC
|
||||
templateCode: 1000
|
||||
smProxy: smsc
|
||||
|
||||
#User authorized information
|
||||
# crypt: mysql/md5/bcrypt
|
||||
# token: true/false to check accessToken
|
||||
# expires for session, unit: second
|
||||
# Support single/multiple session of user
|
||||
#
|
||||
auth:
|
||||
crypt: bcrypt
|
||||
token: true
|
||||
expires: 1800
|
||||
session: multiple
|
||||
publicKey: /usr/local/omc/certs/omc_pub.key
|
||||
privateKey: /usr/local/omc/omc_pri.key
|
||||
|
||||
# Parameter for limit number
|
||||
# rmuid_maxnum: the max number of rmUID, default: 50
|
||||
# alarmid_maxnum: the max number of AlarmID, default: 50
|
||||
# pmid_maxnum: the max number of pmID, default: 50
|
||||
# subid_maxnum: the max number of subscription ID, default: 20
|
||||
# uri_maxlen: the max length of uri, default: 8192
|
||||
# rmuid_regexp: regexp pattern of rmUID
|
||||
params:
|
||||
rmuidmaxnum: 50
|
||||
alarmidmaxnum: 50
|
||||
pmidmaxnum: 50
|
||||
subidmaxnum: 20
|
||||
urimaxlen: 2100000
|
||||
rmuidregexp: "[0-9]{4}[A-Z]{2}[A-Z]{2}[0-9A-Z]{1}[0-9A-Z]{3}[0-9A-Z]{1,16}"
|
||||
|
||||
# Static file configuration, relative to the project root path or fill in the absolute path
|
||||
staticFile:
|
||||
# Default resources, dir directories need to be pre-created
|
||||
default:
|
||||
prefix: "/static"
|
||||
dir: "/usr/local/etc/omc/static"
|
||||
# File upload resource directory mapping, same level as project directory
|
||||
upload:
|
||||
prefix: "/upload"
|
||||
dir: "/usr/local/etc/omc/upload"
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -0,0 +1 @@
|
||||
# OMC tmp Dir
|
||||
@@ -0,0 +1 @@
|
||||
# OMC Upload Dir
|
||||
File diff suppressed because it is too large.
Load diff
Whitespace-only changes.
@@ -0,0 +1,5 @@
|
||||
# Docker Image
|
||||
|
||||
- mysql:8.0.39 => mysql_8.0.39.tar
|
||||
- redis:7.2.5 => redis_7.2.5.tar
|
||||
- omc:2.2412.1 => omc_2.2412.1.tar
|
||||
@@ -0,0 +1,142 @@
|
||||
package aaaa
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/oauth"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
)
|
||||
|
||||
var (
|
||||
UriAAAASSO = config.DefaultUriPrefix + "/aaaa/{apiVersion}/security/sso" // for 4A external
|
||||
|
||||
CustomUriAAAASSO = config.UriPrefix + "/aaaa/{apiVersion}/security/sso" // for 4A external
|
||||
)
|
||||
|
||||
var client = resty.New()
|
||||
|
||||
func init() {
|
||||
/*
|
||||
client.
|
||||
SetTimeout(10 * time.Second).
|
||||
SetRetryCount(1).
|
||||
SetRetryWaitTime(1 * time.Second).
|
||||
SetRetryMaxWaitTime(2 * time.Second).
|
||||
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
|
||||
return 0, errors.New("quota exceeded")
|
||||
})
|
||||
*/
|
||||
client.SetTimeout(3 * time.Second)
|
||||
}
|
||||
|
||||
type AAAATicket struct {
|
||||
Ticket string `json:"ticket"`
|
||||
}
|
||||
|
||||
type SSOResult struct {
|
||||
SSO struct {
|
||||
Result string `json:"result"`
|
||||
ResultMsg string `json:"result_msg"`
|
||||
Ticket string `json:"ticket"`
|
||||
ResultMsgcode string `json:"result_msgcode"`
|
||||
Account []struct {
|
||||
Accid string `json:"accid"`
|
||||
} `json:"account"`
|
||||
} `json:"sso"`
|
||||
}
|
||||
|
||||
// Get system state from NF/NFs
|
||||
func GetSSOFromAAAA(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetSSOFromAAAA processing... ")
|
||||
|
||||
vars := r.URL.Query()
|
||||
ticket := vars["ticket"]
|
||||
if len(ticket) == 0 {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Debug("ticket:", ticket)
|
||||
|
||||
log.Debugf("r.RemoteAddr:%s r.Host: %s", r.RemoteAddr, r.Host)
|
||||
|
||||
aaaaIp := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
|
||||
omcIp := r.Host[:strings.Index(r.Host, ":")]
|
||||
|
||||
log.Debugf("aaaaIp=%s omcIp=%s", aaaaIp, omcIp)
|
||||
requestURI2NF := fmt.Sprintf("http://%s:8080/qryUserByTicket", aaaaIp)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
aaaaTicket := &AAAATicket{
|
||||
Ticket: ticket[0],
|
||||
}
|
||||
|
||||
body, err := json.Marshal(aaaaTicket)
|
||||
if err != nil {
|
||||
log.Error("Failed to json.Marshal:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Post(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Post:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("response:", response)
|
||||
|
||||
switch response.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
ssoResult := new(SSOResult)
|
||||
json.Unmarshal(response.Body(), ssoResult)
|
||||
var accid string
|
||||
if len(ssoResult.SSO.Account) != 0 {
|
||||
accid = ssoResult.SSO.Account[0].Accid
|
||||
}
|
||||
|
||||
log.Debug("accid:", accid)
|
||||
exist, err := dborm.XormIsExistUser(accid)
|
||||
if err != nil {
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
token := oauth.GenRandToken("aaaa") // Generate new token to session ID
|
||||
affected, err := dborm.XormInsertSession(accid, r.RemoteAddr, token,
|
||||
config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormInsertSession:", err)
|
||||
if affected == -1 {
|
||||
services.ResponseForbidden403MultiLoginNotAllowed(w)
|
||||
} else {
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
}
|
||||
return
|
||||
}
|
||||
if exist == true {
|
||||
redirectUrl := fmt.Sprintf("http://%s:8888/home.html?user=%s&token=%s", omcIp, accid, token)
|
||||
services.ResponseRedirect(w, redirectUrl, accid, token)
|
||||
return
|
||||
} else {
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
return
|
||||
}
|
||||
default:
|
||||
services.ResponseForbidden403NotPermission(w)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package cdr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
wsService "be.ems/src/modules/ws/service"
|
||||
)
|
||||
|
||||
var (
|
||||
UriCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrEvent"
|
||||
UriCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile"
|
||||
|
||||
CustomUriCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrEvent"
|
||||
CustomUriCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile"
|
||||
)
|
||||
|
||||
// CDREvent CDR数据表格结构体
|
||||
type CDREvent struct {
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeName string `json:"neName" xorm:"ne_name"`
|
||||
RmUID string `json:"rmUID" xorm:"rm_uid"`
|
||||
Timestamp int `json:"timestamp" xorm:"timestamp"`
|
||||
CDR map[string]any `json:"CDR" xorm:"cdr_json"`
|
||||
}
|
||||
|
||||
// PostCDREventFrom 接收CDR数据请求
|
||||
func PostCDREventFrom(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostCDREventFrom processing... ")
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
var cdrEvent CDREvent
|
||||
if err := ctx.ShouldBindJSON(r, &cdrEvent); err != nil {
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
neTypeLower := strings.ToLower(cdrEvent.NeType)
|
||||
if neType == "" || neType != neTypeLower {
|
||||
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element types"))
|
||||
return
|
||||
}
|
||||
|
||||
tableName := fmt.Sprintf("cdr_event_%s", neTypeLower)
|
||||
affected, err := dborm.XormInsertTableOne(tableName, cdrEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert "+tableName, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 发送到匹配的网元
|
||||
neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(cdrEvent.RmUID)
|
||||
if neInfo.RmUID == cdrEvent.RmUID {
|
||||
// 推送到ws订阅组
|
||||
switch neInfo.NeType {
|
||||
case "IMS":
|
||||
if v, ok := cdrEvent.CDR["recordType"]; ok && (v == "MOC" || v == "MTSM") {
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_IMS_CDR+neInfo.NeId, cdrEvent)
|
||||
}
|
||||
case "SMF":
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_SMF_CDR+neInfo.NeId, cdrEvent)
|
||||
case "SMSC":
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_SMSC_CDR+neInfo.NeId, cdrEvent)
|
||||
case "SGWC":
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_SGWC_CDR+neInfo.NeId, cdrEvent)
|
||||
}
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package cm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/log"
|
||||
)
|
||||
|
||||
func ExecCmd(command string) error {
|
||||
log.Debug("Exec command:", command)
|
||||
|
||||
cmd := exec.Command("/bin/bash", "-c", command)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Tracef("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("exe cmd error: ", err)
|
||||
return err
|
||||
}
|
||||
/*
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Error("Start error: ", err)
|
||||
return err
|
||||
}
|
||||
if err := cmd.Wait(); err != nil {
|
||||
log.Error("Wait error: ", err)
|
||||
return err
|
||||
}
|
||||
*/
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExecShell(command string) error {
|
||||
in := bytes.NewBuffer(nil)
|
||||
cmd := exec.Command("sh")
|
||||
cmd.Stdin = in
|
||||
in.WriteString(command)
|
||||
in.WriteString("exit\n")
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExecOsCmd(command, os string) error {
|
||||
log.Debugf("Exec %s command:%s", os, command)
|
||||
|
||||
var cmd *exec.Cmd
|
||||
switch os {
|
||||
case "Linux":
|
||||
cmd = exec.Command(command)
|
||||
case "Windows":
|
||||
cmd = exec.Command("cmd", "/C", command)
|
||||
}
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Tracef("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("exe cmd error: ", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartSSHCmdWithTimeout(duration int, sshHost, cmdStr string) error {
|
||||
timeout := time.Duration(duration) * time.Second
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout) // 设置超时
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(ctx, "ssh", sshHost, cmdStr)
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunSSHCmd(sshHost, cmdStr string) error {
|
||||
cmd := exec.Command("ssh", sshHost, cmdStr)
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package cm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/log"
|
||||
)
|
||||
|
||||
func ExecCmd(command string) error {
|
||||
log.Debug("Exec command:", command)
|
||||
|
||||
cmd := exec.Command("cmd", "/C", command)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Tracef("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("exe cmd error: ", err)
|
||||
return err
|
||||
}
|
||||
/*
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Error("Start error: ", err)
|
||||
return err
|
||||
}
|
||||
if err := cmd.Wait(); err != nil {
|
||||
log.Error("Wait error: ", err)
|
||||
return err
|
||||
}
|
||||
*/
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExecOsCmd(command, os string) error {
|
||||
log.Debugf("Exec %s command:%s", os, command)
|
||||
|
||||
var cmd *exec.Cmd
|
||||
switch os {
|
||||
case "Linux":
|
||||
cmd = exec.Command(command)
|
||||
case "Windows":
|
||||
cmd = exec.Command("cmd", "/C", command)
|
||||
}
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Tracef("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("exe cmd error: ", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartSSHCmdWithTimeout(duration int, sshHost, cmdStr string) error {
|
||||
timeout := time.Duration(duration) * time.Second
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout) // 设置超时
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(ctx, "ssh", sshHost, cmdStr)
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunSSHCmd(sshHost, cmdStr string) error {
|
||||
cmd := exec.Command("ssh", sshHost, cmdStr)
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,990 @@
|
||||
package cm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
tokenConst "be.ems/src/framework/constants/token"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var (
|
||||
// NE CM export/import
|
||||
NeCmUri = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/cm"
|
||||
// NE info
|
||||
UriNeInfo = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/neInfo"
|
||||
// NE backup file
|
||||
UriNeCmFile = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{neType}/neBackup/{fileName}"
|
||||
// service action uri, action: start/stop/restart
|
||||
UriNeService = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/service/{action}"
|
||||
// nf instance action uri, action: start/stop/restart
|
||||
UriNeInstance = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/instance/{action}"
|
||||
|
||||
CustomNeCmUri = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/cm"
|
||||
CustomUriNeInfo = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/neInfo"
|
||||
CustomUriNeCmFile = config.UriPrefix + "/systemManagement/{apiVersion}/{neType}/neBackup/{fileName}"
|
||||
// service action uri, action: start/stop/restart
|
||||
CustomUriNeService = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/service/{action}"
|
||||
// nf instance action uri, action: start/stop/restart
|
||||
CustomUriNeInstance = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/instance/{action}"
|
||||
)
|
||||
|
||||
const (
|
||||
NEStatusActive = 0
|
||||
NEStatusOffline = 1
|
||||
NEStatusStandby = 2
|
||||
NEStatusMaintain = 3
|
||||
)
|
||||
|
||||
var client = resty.New()
|
||||
|
||||
func init() {
|
||||
/*
|
||||
client.
|
||||
SetTimeout(10 * time.Second).
|
||||
SetRetryCount(1).
|
||||
SetRetryWaitTime(1 * time.Second).
|
||||
SetRetryMaxWaitTime(2 * time.Second).
|
||||
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
|
||||
return 0, errors.New("quota exceeded")
|
||||
})
|
||||
*/
|
||||
client.
|
||||
SetTimeout(time.Duration(1 * time.Second))
|
||||
}
|
||||
|
||||
func GetNeInfo(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetNeInfo processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
|
||||
|
||||
// no, _ := strconv.ParseInt(neId, 10, 64)
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("dborm.XormGetNeInfo is failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var response services.DataResponse
|
||||
response.Data = neInfo
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
type OmcNeConfig struct {
|
||||
NeId string `json:"neId" xorm:"ne_id"` // 网元标识(内部),
|
||||
RmUID string `json:"rmUID" xorm:"rm_uid"` // rmUID 网元唯一标识
|
||||
NeName string `json:"neName" xorm:"ne_name"` // 网元名称(内部)/友好名称(北向资源/性能等使用)
|
||||
PvFlag string `json:"pvFlag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理
|
||||
Province string `json:"province" xorm:"province"` // 网元所在省份
|
||||
VendorName string `json:"vendorName" xorm:"vendor_name"` // 厂商名称
|
||||
// ManagedBy string `json:"managedBy" xorm:"managed_by"` // 管理ManagedElement的ManagementNode对象类的DN值
|
||||
Dn string `json:"dn" xorm:"dn"` // 资源里边的ManagedBy,性能的Dn,网络唯一标识
|
||||
}
|
||||
|
||||
func PostNeInfo(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostNeInfo processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
neTypeUpper := strings.ToUpper(neType)
|
||||
syncFlag := services.GetUriParamString(r, "sync2ne", ",", false, false)
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("Failed to o.ReadAll:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Trace("Body:", string(body))
|
||||
|
||||
neInfo := new(dborm.NeInfo)
|
||||
err = json.Unmarshal(body, neInfo)
|
||||
if err != nil {
|
||||
log.Error("Failed to json.Unmarshal:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
//neInfo.UpdateTime = time.Now().Format(time.DateTime)
|
||||
neInfo.UpdateTime = time.Now()
|
||||
log.Debug("NE info:", neInfo)
|
||||
|
||||
//if !config.GetYamlConfig().OMC.Chk2Ne {
|
||||
if syncFlag == "false" || neTypeUpper == config.GetYamlConfig().OMC.NeType {
|
||||
neInfo.Status = NEStatusMaintain
|
||||
affected, err := dborm.XormInsertNeInfo(neInfo)
|
||||
if err != nil {
|
||||
log.Error("Failed to insert Ne info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 刷新缓存,不存在结构体网元Id空字符串
|
||||
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
|
||||
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow["data"] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
return
|
||||
} else {
|
||||
hostUri := global.CombineHostUri(neInfo.Ip, neInfo.Port)
|
||||
//hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
apiUri := fmt.Sprintf("%s/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig?ne_id=%s", config.DefaultUriPrefix, strings.ToLower(neInfo.NeType), neInfo.NeId)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, apiUri)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
omcNeConfig := &OmcNeConfig{
|
||||
NeId: neInfo.NeId,
|
||||
RmUID: neInfo.RmUID,
|
||||
NeName: neInfo.NeName,
|
||||
PvFlag: neInfo.PvFlag,
|
||||
Province: neInfo.Province,
|
||||
VendorName: neInfo.VendorName,
|
||||
Dn: neInfo.Dn,
|
||||
}
|
||||
body, _ = json.Marshal(omcNeConfig)
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Put(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Put:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Info("StatusCode: ", response.StatusCode())
|
||||
|
||||
respMsg := make(map[string]interface{})
|
||||
switch response.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
neInfo.Status = NEStatusActive
|
||||
affected, err := dborm.XormInsertNeInfo(neInfo)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormInsertNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if affected <= 0 {
|
||||
log.Infof("Not record affected to insert ne_info")
|
||||
}
|
||||
|
||||
// 刷新缓存,不存在结构体网元Id空字符串
|
||||
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
return
|
||||
default:
|
||||
log.Info("response body:", string(response.Body()))
|
||||
body := new(map[string]interface{})
|
||||
_ = json.Unmarshal(response.Body(), &body)
|
||||
respMsg["error"] = body
|
||||
}
|
||||
|
||||
services.ResponseWithJson(w, response.StatusCode(), respMsg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func PutNeInfo(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PutNeInfo processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
neTypeLower := strings.ToLower(neType)
|
||||
neTypeUpper := strings.ToUpper(neType)
|
||||
syncFlag := services.GetUriParamString(r, "sync2ne", ",", false, false)
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("Failed to io.ReadAll:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
neInfo := new(dborm.NeInfo)
|
||||
_ = json.Unmarshal(body, neInfo)
|
||||
neInfo.NeType = strings.ToUpper(neType)
|
||||
neInfo.UpdateTime = time.Now()
|
||||
log.Debug("NE info:", neInfo)
|
||||
|
||||
//if !config.GetYamlConfig().OMC.Chk2Ne {
|
||||
if syncFlag == "false" || neTypeUpper == config.GetYamlConfig().OMC.NeType {
|
||||
neInfo.Status = NEStatusMaintain
|
||||
affected, err := dborm.XormUpdateNeInfo(neInfo)
|
||||
if err != nil {
|
||||
log.Error("Failed to update Ne info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 刷新缓存,不存在结构体网元Id空字符串
|
||||
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
|
||||
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow["data"] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
return
|
||||
} else {
|
||||
hostUri := global.CombineHostUri(neInfo.Ip, neInfo.Port)
|
||||
//hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
apiUri := fmt.Sprintf("%s/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig?ne_id=%s", config.DefaultUriPrefix, neTypeLower, neInfo.NeId)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, apiUri)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
omcNeConfig := &OmcNeConfig{
|
||||
NeId: neInfo.NeId,
|
||||
RmUID: neInfo.RmUID,
|
||||
NeName: neInfo.NeName,
|
||||
PvFlag: neInfo.PvFlag,
|
||||
Province: neInfo.Province,
|
||||
VendorName: neInfo.VendorName,
|
||||
Dn: neInfo.Dn,
|
||||
}
|
||||
body, _ = json.Marshal(omcNeConfig)
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Put(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Put:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Info("StatusCode: ", response.StatusCode())
|
||||
|
||||
respMsg := make(map[string]interface{})
|
||||
switch response.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
neInfo.Status = NEStatusActive
|
||||
affected, err := dborm.XormUpdateNeInfo(neInfo)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormUpdateNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if affected <= 0 {
|
||||
log.Infof("Not record affected to insert ne_info")
|
||||
}
|
||||
|
||||
// 刷新缓存,不存在结构体网元Id空字符串
|
||||
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
return
|
||||
default:
|
||||
log.Info("response body:", string(response.Body()))
|
||||
body := new(map[string]interface{})
|
||||
_ = json.Unmarshal(response.Body(), &body)
|
||||
respMsg["error"] = body
|
||||
}
|
||||
|
||||
services.ResponseWithJson(w, response.StatusCode(), respMsg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteNeInfo(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DeleteNeInfo processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
neInfo := new(dborm.NeInfo)
|
||||
_ = json.Unmarshal(body, neInfo)
|
||||
neInfo.NeType = strings.ToUpper(neType)
|
||||
neInfo.NeId = services.GetUriParamString(r, "ne_id", ",", false, false)
|
||||
neInfo, err = dborm.XormGetNeInfo(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil || neInfo == nil {
|
||||
log.Error("Failed to delete Ne info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("NE info:", neInfo)
|
||||
|
||||
// if NE in active status, can't delete NE
|
||||
if !IsActiveNF(neInfo) {
|
||||
affected, err := dborm.XormDeleteNeInfo(neInfo)
|
||||
if err != nil {
|
||||
log.Error("Failed to delete Ne info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 刷新缓存,不存在结构体网元Id空字符串
|
||||
neService.NewNeInfo.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
|
||||
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow["data"] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
return
|
||||
}
|
||||
err = global.ErrCMCannotDeleteActiveNE
|
||||
log.Error(err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
}
|
||||
|
||||
func IsActiveNF(neInfo *dborm.NeInfo) bool {
|
||||
log.Debug("IsActiveNF processing... ")
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI := fmt.Sprintf(config.UriPrefix+"/systemManagement/v1/elementType/%s/objectType/systemState",
|
||||
strings.ToLower(neInfo.NeType))
|
||||
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(hostUri + requestURI)
|
||||
if err != nil {
|
||||
log.Error("Failed to Get:", err)
|
||||
return false
|
||||
}
|
||||
|
||||
switch response.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ExportCmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExportCmFromNF processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
neTypeUpper := strings.ToUpper(neType)
|
||||
neTypeLower := strings.ToLower(neType)
|
||||
|
||||
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
|
||||
|
||||
// neInfo := new(dborm.NeInfo)
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get ne_info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("neInfo:", neInfo)
|
||||
nePath := fmt.Sprintf("%s/etc/%s", config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
isExist, err := global.PathExists(nePath)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to stat:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
if isExist {
|
||||
err = os.RemoveAll(nePath)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to RemoveAll:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
err = os.MkdirAll(nePath, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to MkdirAll:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var scpCmd string
|
||||
ipType := global.ParseIPAddr(neInfo.Ip)
|
||||
omcNetypeLower := strings.ToLower(config.GetYamlConfig().OMC.NeType)
|
||||
etcListIMS := "{*.yaml,mmtel,vars.cfg}"
|
||||
if config.GetYamlConfig().NE.EtcListIMS != "" {
|
||||
etcListIMS = config.GetYamlConfig().NE.EtcListIMS
|
||||
}
|
||||
switch neTypeLower {
|
||||
case omcNetypeLower:
|
||||
if ipType == global.IsIPv4 {
|
||||
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/etc/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.OmcDir, config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
} else {
|
||||
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/etc/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.OmcDir, config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
}
|
||||
|
||||
case "ims":
|
||||
if ipType == global.IsIPv4 {
|
||||
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/%s/%s %s/etc/%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.EtcDir, neTypeLower,
|
||||
etcListIMS, config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
} else {
|
||||
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/%s/%s %s/etc/%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.EtcDir, neTypeLower,
|
||||
etcListIMS, config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
}
|
||||
|
||||
case "mme":
|
||||
if ipType == global.IsIPv4 {
|
||||
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/%s/*.conf %s/etc/%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
|
||||
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
} else {
|
||||
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/%s/*.conf %s/etc/%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
|
||||
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
}
|
||||
|
||||
default:
|
||||
if ipType == global.IsIPv4 {
|
||||
scpCmd = fmt.Sprintf("scp -r %s@%s:%s/%s/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
|
||||
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
} else {
|
||||
scpCmd = fmt.Sprintf("scp -r %s@[%s]:%s/%s/*.yaml %s/etc/%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.EtcDir,
|
||||
neTypeLower, config.GetYamlConfig().OMC.Backup, neTypeLower)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
zipFile := fmt.Sprintf("%s-%s-etc-%s.zip", neTypeLower, strings.ToLower(neInfo.NeId), time.Now().Format(global.DateData))
|
||||
zipFilePath := config.GetYamlConfig().OMC.Backup + "/" + zipFile
|
||||
zipCmd := fmt.Sprintf("cd %s/etc && zip -r %s %s/*", config.GetYamlConfig().OMC.Backup, zipFilePath, neTypeLower)
|
||||
|
||||
command := fmt.Sprintf("%s&&%s", scpCmd, zipCmd)
|
||||
|
||||
log.Debug("command:", command)
|
||||
err = ExecCmd(command)
|
||||
if err != nil {
|
||||
log.Error("Faile to exec command:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
md5Sum, err := global.GetFileMD5Sum(zipFilePath)
|
||||
if err != nil {
|
||||
log.Error("Faile to md5sum:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
//log.Debug("md5Str:", md5Sum)
|
||||
path := config.GetYamlConfig().OMC.Backup
|
||||
neBackup := dborm.NeBackup{NeType: neTypeUpper, NeId: neId, FileName: zipFile, Path: path, Md5Sum: md5Sum}
|
||||
_, err = dborm.XormInsertTableOne("ne_backup", neBackup)
|
||||
if err != nil {
|
||||
log.Error("Faile to XormInsertTableOne:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
//services.ResponseFileWithNameAndMD5(w, http.StatusOK, zipFile, path, md5Sum)
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
type ImportCMJson struct {
|
||||
FileName string `json:"fileName"`
|
||||
}
|
||||
|
||||
func ImportCmToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ImportCmToNF processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
neTypeUpper := strings.ToUpper(neType)
|
||||
neTypeLower := strings.ToLower(neType)
|
||||
|
||||
neId := services.GetUriParamString(r, "ne_id", ",", false, false)
|
||||
|
||||
var fileName, path string
|
||||
if services.IsJsonContentType(r) {
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Debug("Body:", string(body))
|
||||
|
||||
importCMJson := new(ImportCMJson)
|
||||
_ = json.Unmarshal(body, importCMJson)
|
||||
fileName = importCMJson.FileName
|
||||
path = config.GetYamlConfig().OMC.Backup
|
||||
} else {
|
||||
path = config.GetYamlConfig().OMC.Upload
|
||||
fileNamePath, err := services.HandleUploadFile(r, path, "")
|
||||
if err != nil {
|
||||
log.Error("Faile to HandleUploadFile:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
fileName = fileNamePath
|
||||
}
|
||||
filePath := fmt.Sprintf("%s/%s", path, fileName)
|
||||
|
||||
// neInfo := new(dborm.NeInfo)
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get ne_info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("neInfo:", neInfo)
|
||||
|
||||
md5Sum, err := global.GetFileMD5Sum(filePath)
|
||||
if err != nil {
|
||||
log.Error("Faile to GetFileMD5Sum:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
//neBackup := dborm.NeBackup{NeType: neType, NeId: neId, Md5Sum: md5Sum}
|
||||
//log.Debug("neBackup:", neBackup)
|
||||
where := fmt.Sprintf("ne_type='%s' and ne_id='%s' and md5_sum='%s'", neTypeUpper, neId, md5Sum)
|
||||
has, err := dborm.XormExistTableOne("ne_backup", where)
|
||||
if err != nil {
|
||||
log.Error("Faile to XormInsertTableOne:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if !has {
|
||||
err = global.ErrCMInvalidBackupFile
|
||||
log.Error(err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// nePath := fmt.Sprintf("%s/etc/%s", config.GetYamlConfig().OMC.Upload, neTypeLower)
|
||||
// isExist, err := global.PathExists(nePath)
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to stat:", err)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// }
|
||||
// if isExist {
|
||||
// err = os.RemoveAll(nePath)
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to remove:", err)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// unzipCmd := fmt.Sprintf("unzip -o %s -d %s", filePath, config.GetYamlConfig().OMC.Upload)
|
||||
|
||||
// var scpCmd string
|
||||
// ipType := global.ParseIPAddr(neInfo.Ip)
|
||||
// if ipType == global.IsIPv4 {
|
||||
// scpCmd = fmt.Sprintf("scp -r %s/etc/%s %s@%s:%s", config.GetYamlConfig().OMC.Upload,
|
||||
// neTypeLower, config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.EtcDir)
|
||||
// } else {
|
||||
// scpCmd = fmt.Sprintf("scp -r %s/etc/%s %s@[%s]:%s", config.GetYamlConfig().OMC.Upload,
|
||||
// neTypeLower, config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.EtcDir)
|
||||
// }
|
||||
|
||||
// err = ExecCmd(fmt.Sprintf("%s && %s", unzipCmd, scpCmd))
|
||||
// if err != nil {
|
||||
// log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// }
|
||||
|
||||
// nePath := fmt.Sprintf("%s/etc/%s", config.GetYamlConfig().OMC.Upload, neTypeLower)
|
||||
// isExist, err := global.PathExists(nePath)
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to stat:", err)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// }
|
||||
// if isExist {
|
||||
// err = os.RemoveAll(nePath)
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to remove:", err)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
var scpZipCmd string
|
||||
ipType := global.ParseIPAddr(neInfo.Ip)
|
||||
if ipType == global.IsIPv4 {
|
||||
scpZipCmd = fmt.Sprintf("scp -r %s %s@%s:%s", filePath,
|
||||
config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.ScpDir)
|
||||
} else {
|
||||
scpZipCmd = fmt.Sprintf("scp -r %s %s@[%s]:%s", filePath,
|
||||
config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.ScpDir)
|
||||
}
|
||||
err = ExecCmd(scpZipCmd)
|
||||
if err != nil {
|
||||
log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
neFilePath := config.GetYamlConfig().NE.ScpDir + "/" + fileName
|
||||
var unzipCmd string
|
||||
if neTypeLower != "omc" {
|
||||
unzipCmd = fmt.Sprintf("sudo unzip -o %s -d %s", neFilePath, config.GetYamlConfig().NE.EtcDir)
|
||||
} else {
|
||||
unzipCmd = fmt.Sprintf("sudo unzip -oj %s -d %s/etc", neFilePath, config.GetYamlConfig().NE.OmcDir)
|
||||
}
|
||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||
cmd := exec.Command("ssh", sshHost, unzipCmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Tracef("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("Faile to execute command:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
func DownloadNeBackupFile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DownloadNeBackupFile processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["neType"]
|
||||
if neType == "" {
|
||||
log.Error("neType is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
neTypeUpper := strings.ToUpper(neType)
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
|
||||
fileName := vars["fileName"]
|
||||
if fileName == "" {
|
||||
log.Error("fileName is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
sql := fmt.Sprintf("select * from ne_backup where ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
|
||||
neBackup, err := dborm.XormGetDataBySQL(sql)
|
||||
if err != nil {
|
||||
log.Error("Faile to XormGetDataBySQL:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if len(*neBackup) == 0 {
|
||||
err := global.ErrCMNotFoundTargetBackupFile
|
||||
log.Error(err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
path := (*neBackup)[0]["path"]
|
||||
md5Sum := (*neBackup)[0]["md5_sum"]
|
||||
|
||||
services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, md5Sum)
|
||||
}
|
||||
|
||||
func DeleteNeBackupFile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DeleteNeBackupFile processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["neType"]
|
||||
if neType == "" {
|
||||
log.Error("neType is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
neTypeUpper := strings.ToUpper(neType)
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
|
||||
fileName := vars["fileName"]
|
||||
if fileName == "" {
|
||||
log.Error("fileName is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
sql := fmt.Sprintf("select * from ne_backup where ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
|
||||
neBackup, err := dborm.XormGetDataBySQL(sql)
|
||||
if err != nil {
|
||||
log.Error("Faile to XormGetDataBySQL:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if len(*neBackup) == 0 {
|
||||
err := global.ErrCMNotFoundTargetBackupFile
|
||||
log.Error(err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
where := fmt.Sprintf("ne_type='%s' and file_name='%s'", neTypeUpper, fileName)
|
||||
affected, err := dborm.XormDeleteDataByWhere(where, "ne_backup")
|
||||
if err != nil || affected == 0 {
|
||||
log.Error("Faile to XormGetDataBySQL:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
path := (*neBackup)[0]["path"]
|
||||
filePath := fmt.Sprintf("%s/%s", path, fileName)
|
||||
err = os.Remove(filePath)
|
||||
if err != nil {
|
||||
log.Error("Faile to Remove:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
func PostNeServiceAction(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostNeServiceAction processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeUpper := strings.ToUpper(neType)
|
||||
neTypeLower := strings.ToLower(neType)
|
||||
action := vars["action"]
|
||||
|
||||
neId := services.GetUriParamString(r, "neId", ",", false, false)
|
||||
|
||||
// neInfo := new(dborm.NeInfo)
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to get ne_info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("neInfo:", neInfo)
|
||||
|
||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||
switch neTypeLower {
|
||||
case "omc":
|
||||
// send 204 to fe firstly
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
//actionCmd := fmt.Sprintf("sudo %s/bin/omcsvc.sh %s", config.GetYamlConfig().NE.OmcDir, action)
|
||||
actionCmd := fmt.Sprintf("sudo systemctl %s restagent", action)
|
||||
go RunSSHCmd(sshHost, actionCmd)
|
||||
return
|
||||
// cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
// out, err := cmd.CombinedOutput()
|
||||
// log.Debugf("Exec output: %v", string(out))
|
||||
// if err != nil {
|
||||
// log.Errorf("Faile to execute ssh %s omc:%v", action, err)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// }
|
||||
case "ims":
|
||||
switch action {
|
||||
case "start", "stop":
|
||||
actionCmd := fmt.Sprintf("sudo ims-%s", action)
|
||||
cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Errorf("Faile to execute %s command:%v", actionCmd, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
case "restart":
|
||||
actionCmd := "sudo ims-stop && sudo ims-start"
|
||||
cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Errorf("Faile to execute %s command:%v", actionCmd, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = global.ErrCMUnknownServiceAction
|
||||
log.Errorf("%v, action:%s", err, action)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
actionCmd := fmt.Sprintf("sudo systemctl %s %s.service", action, neTypeLower)
|
||||
cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("Faile to execute command:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
func PostNeInstanceAction(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostNeInstanceAction processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeUpper := strings.ToUpper(neType)
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
action := vars["action"]
|
||||
|
||||
neId := services.GetUriParamString(r, "neId", ",", false, false)
|
||||
|
||||
// neInfo := new(dborm.NeInfo)
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get ne_info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("neInfo:", neInfo)
|
||||
|
||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||
switch action {
|
||||
case "poweron":
|
||||
actionCmd := "sudo poweron"
|
||||
cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("Faile to execute ssh %s omc:", action, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
case "poweroff":
|
||||
actionCmd := "sudo poweroff"
|
||||
cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("Faile to execute ssh sudo poweroff:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
case "reboot":
|
||||
actionCmd := "sudo reboot"
|
||||
cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("Faile to execute ssh sudo reboot:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = global.ErrCMUnknownInstanceAction
|
||||
log.Errorf("%v, action:%s", err, action)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
@@ -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(¶mData); 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()))
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package cm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var (
|
||||
// parameter config management
|
||||
ParamConfigUri = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/config/{paraName}"
|
||||
|
||||
CustomParamConfigUri = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/config/{paraName}"
|
||||
)
|
||||
|
||||
func GetParamConfigFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetParamConfigFromNF processing... ")
|
||||
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" || neId == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
var response services.DataResponse
|
||||
if neInfo.NeId == neId && neInfo.NeId != "" {
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Get from NF:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
}
|
||||
log.Debug("response:", response)
|
||||
}
|
||||
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func PostParamConfigToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostParamConfigToNF processing... ")
|
||||
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" || neId == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
if neInfo.NeId != neId || neInfo.NeId == "" {
|
||||
log.Error("neId is empty")
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF: POST ", requestURI2NF)
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
client := resty.New()
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Post(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to POST to NF:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
services.ResponseWithJson(w, http.StatusNoContent, response)
|
||||
}
|
||||
|
||||
func PutParamConfigToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PutParamConfigToNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// OMC配置接口 /api/rest/systemManagement/v1/elementType/omc/objectType/config/omcNeConfig
|
||||
if v, ok := vars["paraName"]; ok && v == "omcNeConfig" && strings.ToLower(neType) == "omc" {
|
||||
PutOMCNeConfig(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
if neInfo.NeId != neId || neInfo.NeId == "" {
|
||||
log.Error("neId is empty")
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF: PUT ", requestURI2NF)
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
client := resty.New()
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Put(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Put to NF:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
services.ResponseWithJson(w, http.StatusNoContent, response)
|
||||
}
|
||||
|
||||
// PutOMCNeConfig 网元OMC配置
|
||||
//
|
||||
// 目前没配置,返回204
|
||||
func PutOMCNeConfig(w http.ResponseWriter, r *http.Request) {
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
func DeleteParamConfigToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DeleteParamConfigToNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
log.Error("elementTypeValue is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
if neInfo.NeId != neId || neInfo.NeId == "" {
|
||||
log.Error("neId is empty")
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF: DELETE ", requestURI2NF)
|
||||
|
||||
client := resty.New()
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Delete(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to delete parameter:", err)
|
||||
services.ResponseInternalServerError500NFConnectRefused(w)
|
||||
return
|
||||
}
|
||||
|
||||
services.ResponseWithJson(w, http.StatusNoContent, response)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,134 @@
|
||||
package dbrest
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/conf"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
var (
|
||||
// 系统备份-数据库备份
|
||||
UriDbBackup = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/dbBackup"
|
||||
CustomUriDbBackup = config.UriPrefix + "/dataManagement/{apiVersion}/dbBackup" // for external
|
||||
|
||||
// 系统备份-文件备份
|
||||
UriConfBackup = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/confBackup"
|
||||
CustomUriConfBackup = config.UriPrefix + "/dataManagement/{apiVersion}/confBackup" // for external
|
||||
|
||||
)
|
||||
|
||||
// DbBackup 系统备份-数据库备份1
|
||||
func DbBackup(w http.ResponseWriter, r *http.Request) {
|
||||
dbConfigHost := conf.Get("database.host").(string)
|
||||
dbConfigUser := conf.Get("database.user").(string)
|
||||
dbConfigPassword := conf.Get("database.password").(string)
|
||||
dbConfigBackup := conf.Get("database.backup").(string)
|
||||
|
||||
// 备份SQL文件路径
|
||||
fileName := "database_backup_" + time.Now().Format("20060102150405") + ".sql"
|
||||
backupFile := dbConfigBackup + "/" + fileName
|
||||
|
||||
// 执行mysqldump命令进行备份
|
||||
cmd := exec.Command("mysqldump", "-u", dbConfigUser, "-p"+dbConfigPassword, "-h", dbConfigHost, "--all-databases", ">", backupFile)
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 备份结果
|
||||
res, err := dborm.DbClient.XEngine.Exec("INSERT INTO `sys_backup`(`id`, `created_at`, `updated_at`, `backup_type`, `backup_way`, `name`, `path`) VALUES (null, ?, ?, '1', '0', ?, ?);", time.Now(), time.Now(), fileName, backupFile)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
services.ResponseWithJson(w, 200, res)
|
||||
log.Info("Backup completed successfully.")
|
||||
}
|
||||
|
||||
// 系统备份-文件备份0
|
||||
func ConfBackup(w http.ResponseWriter, r *http.Request) {
|
||||
dbConfigBackup := conf.Get("database.backup").(string)
|
||||
etcDir := conf.Get("ne.omcdir").(string)
|
||||
|
||||
// 文件名
|
||||
fileName := "conf_backup_" + time.Now().Format("20060102150405") + ".tar.gz"
|
||||
backupFile := dbConfigBackup + "/" + fileName
|
||||
|
||||
err := createTarGz(etcDir, backupFile)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 备份结果
|
||||
res, err := dborm.DbClient.XEngine.Exec("INSERT INTO `sys_backup`(`id`, `created_at`, `updated_at`, `backup_type`, `backup_way`, `name`, `path`) VALUES (null, ?, ?, '1', '0', ?, ?);", time.Now(), time.Now(), fileName, backupFile)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
services.ResponseWithJson(w, 200, res)
|
||||
log.Info("Backup completed successfully.")
|
||||
}
|
||||
|
||||
// 打压缩
|
||||
func createTarGz(source, target string) error {
|
||||
tarFile, err := os.Create(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tarFile.Close()
|
||||
|
||||
gw := gzip.NewWriter(tarFile)
|
||||
defer gw.Close()
|
||||
|
||||
tw := tar.NewWriter(gw)
|
||||
defer tw.Close()
|
||||
|
||||
return filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := tar.FileInfoHeader(info, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relPath, err := filepath.Rel(source, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name = relPath
|
||||
|
||||
if err := tw.WriteHeader(header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.Mode().IsRegular() {
|
||||
return nil
|
||||
}
|
||||
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(tw, file)
|
||||
return err
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,919 @@
|
||||
package dbrest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type XormResponse struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type XormInsertResponse struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
var (
|
||||
// database management rest pattern, discard
|
||||
XormGetDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
|
||||
XormSelectDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/select/{elementTypeValue}/{objectTypeValue}"
|
||||
XormInsertDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/insert/{elementTypeValue}/{objectTypeValue}"
|
||||
XormUpdateDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/update/{elementTypeValue}/{objectTypeValue}"
|
||||
XormDeleteDataUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/delete/{elementTypeValue}/{objectTypeValue}"
|
||||
|
||||
CustomXormGetDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
|
||||
CustomXormSelectDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/select/{elementTypeValue}/{objectTypeValue}"
|
||||
CustomXormInsertDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/insert/{elementTypeValue}/{objectTypeValue}"
|
||||
CustomXormUpdateDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/update/{elementTypeValue}/{objectTypeValue}"
|
||||
CustomXormDeleteDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/delete/{elementTypeValue}/{objectTypeValue}"
|
||||
|
||||
XormCommonUri = config.DefaultUriPrefix + "/databaseManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for internal
|
||||
XormDatabaseUri = config.DefaultUriPrefix + "/database/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for crontask
|
||||
XormDataRestUri = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
|
||||
XormExtDataUri = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for external
|
||||
XormDataSQLUri = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for external
|
||||
|
||||
CustomXormCommonUri = config.UriPrefix + "/databaseManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for internal
|
||||
CustomXormExtDataUri = config.UriPrefix + "/dataManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for external
|
||||
CustomXormDataSQLUri = config.UriPrefix + "/dataManagement/{apiVersion}/{elementTypeValue}/{objectTypeValue}" // for external
|
||||
|
||||
// 查询数据库连接情况
|
||||
UriDbConnection = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/dbConnection"
|
||||
CustomUriDbConnection = config.UriPrefix + "/dataManagement/{apiVersion}/dbConnection" // for external
|
||||
|
||||
// 终结非法的数据库连接
|
||||
UriDbStop = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/dbStop"
|
||||
CustomUriDbStop = config.UriPrefix + "/dataManagement/{apiVersion}/dbStop" // for external
|
||||
|
||||
)
|
||||
|
||||
var XEngine *xorm.Engine
|
||||
|
||||
type DatabaseClient struct {
|
||||
dbType string
|
||||
dbUrl string
|
||||
dbConnMaxLifetime time.Duration
|
||||
dbMaxIdleConns int
|
||||
dbMaxOpenConns int
|
||||
IsShowSQL bool
|
||||
|
||||
XEngine *xorm.Engine
|
||||
}
|
||||
|
||||
var DbClient DatabaseClient
|
||||
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
|
||||
// DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
// dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
|
||||
DbClient.dbType = dbType
|
||||
DbClient.dbConnMaxLifetime = 0
|
||||
DbClient.dbMaxIdleConns = 0
|
||||
DbClient.dbMaxOpenConns = 0
|
||||
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
DbClient.IsShowSQL = true
|
||||
}
|
||||
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
|
||||
|
||||
var err error
|
||||
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
|
||||
if err != nil {
|
||||
log.Error("Failed to connet database:", err)
|
||||
return err
|
||||
}
|
||||
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
|
||||
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
|
||||
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
|
||||
DbClient.XEngine.DatabaseTZ = time.Local // 必须
|
||||
DbClient.XEngine.TZLocation = time.Local // 必须
|
||||
if DbClient.IsShowSQL {
|
||||
//DbClient.XEngine.SetLogger(&log.Elogger)
|
||||
DbClient.XEngine.ShowSQL(true)
|
||||
}
|
||||
XEngine = DbClient.XEngine
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetUriSQLArray(r *http.Request) []string {
|
||||
var sa []string
|
||||
vars := r.URL.Query()
|
||||
|
||||
// 默认SQL
|
||||
if s, ok := vars["SQL"]; ok {
|
||||
for _, r := range s {
|
||||
if r != "" {
|
||||
sa = append(sa, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查询总数
|
||||
if totalSQL, ok := vars["totalSQL"]; ok {
|
||||
if totalSQL[0] != "" {
|
||||
sa = append(sa, totalSQL[0])
|
||||
}
|
||||
}
|
||||
// 查询列表
|
||||
if rowsSQL, ok := vars["rowsSQL"]; ok {
|
||||
if rowsSQL[0] != "" {
|
||||
sa = append(sa, rowsSQL[0])
|
||||
}
|
||||
}
|
||||
|
||||
if len(sa) == 0 {
|
||||
log.Info("SQL is not exist")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debug("SQL array:", sa)
|
||||
return sa
|
||||
}
|
||||
|
||||
// Get table name from SQL
|
||||
func GetTableNameFromSQL(s string) string {
|
||||
ls := strings.ToLower(s)
|
||||
i1 := strings.Index(ls, "from")
|
||||
i2 := strings.Index(ls, "where")
|
||||
|
||||
var ts string
|
||||
if i1 > 0 {
|
||||
if i2 > 0 && i2 > i1 {
|
||||
ts = ls[i1+4 : i2]
|
||||
}
|
||||
if i2 < 0 {
|
||||
ts = ls[i1+4:]
|
||||
}
|
||||
}
|
||||
|
||||
tn := strings.Trim(ts, " ")
|
||||
log.Debug("i1:", i1, "i2:", i2, "tn:", tn)
|
||||
return tn
|
||||
}
|
||||
|
||||
func GetTableName(sql string) string {
|
||||
ls := strings.ToLower(sql)
|
||||
|
||||
re := regexp.MustCompile(`from\s+(\S+)`)
|
||||
matches := re.FindStringSubmatch(ls)
|
||||
if len(matches) < 2 {
|
||||
return ""
|
||||
}
|
||||
return matches[1]
|
||||
}
|
||||
|
||||
func IsQuerySQL(s string) bool {
|
||||
ts := strings.Trim(strings.ToLower(s), " ")
|
||||
if strings.Index(ts, "select") != 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// xorm Get data from database
|
||||
func ExtDatabaseExecSQL(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseExecSQL processing... ")
|
||||
|
||||
var sql []string
|
||||
// var err error
|
||||
|
||||
// _, err = services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
//vars := mux.Vars(r)
|
||||
//tblName := vars["objectTypeValue"]
|
||||
sql = GetUriSQLArray(r)
|
||||
// select as must, todo ...
|
||||
|
||||
ls := services.ExtGetUriPageLimitString(r)
|
||||
|
||||
// data := make([]map[string]interface{}, 0)
|
||||
// xormResponse := make([]map[string]interface{}, len(sql))
|
||||
var xormResponse XormResponse
|
||||
data := make([]map[string]interface{}, 0)
|
||||
for i, s := range sql {
|
||||
log.Tracef("SQL[%d]: %s", i, sql[i])
|
||||
|
||||
//rows := make([]map[string]interface{}, 0)
|
||||
mapRows := make(map[string]interface{})
|
||||
|
||||
if s != "" {
|
||||
// err = XEngine.SQL(s).Find(&rows)
|
||||
// if IsQuerySQL(s) == false {
|
||||
// services.ResponseNotAcceptable406QuerySQLError(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
querySQL := s
|
||||
if i == (len(sql) - 1) {
|
||||
querySQL = querySQL + " " + ls
|
||||
}
|
||||
log.Debug("querySQL:", querySQL)
|
||||
rows, err := DbClient.XEngine.Exec(querySQL)
|
||||
if err != nil {
|
||||
log.Error("SQL failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
tableName := GetTableName(s)
|
||||
log.Debugf("s:%s tableName:%s", s, tableName)
|
||||
mapRows[tableName] = rows
|
||||
data = append(data, mapRows)
|
||||
log.Trace("data:", data)
|
||||
}
|
||||
i++
|
||||
}
|
||||
xormResponse.Data = data
|
||||
|
||||
services.ResponseWithJson(w, http.StatusOK, xormResponse)
|
||||
}
|
||||
|
||||
// xorm Get data from database
|
||||
func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseGetData processing... ")
|
||||
|
||||
var sql []string
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
pack := "dbrest"
|
||||
vars := mux.Vars(r)
|
||||
module := ""
|
||||
dbname := vars["elementTypeValue"]
|
||||
tbname := vars["objectTypeValue"]
|
||||
|
||||
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to get permission:", err)
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
// if !exist {
|
||||
// log.Error("Not permission!")
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
sql = GetUriSQLArray(r)
|
||||
// select as must, todo ...
|
||||
if sql == nil {
|
||||
wc := services.GetUriLocString(r)
|
||||
if wc == "" {
|
||||
sql = append(sql, fmt.Sprintf("select * from %s", tbname))
|
||||
} else {
|
||||
sql = append(sql, fmt.Sprintf("select * from %s where %s", tbname, wc))
|
||||
}
|
||||
}
|
||||
|
||||
ls := services.ExtGetUriPageLimitString(r)
|
||||
|
||||
// data := make([]map[string]interface{}, 0)
|
||||
// xormResponse := make([]map[string]interface{}, len(sql))
|
||||
var xormResponse XormResponse
|
||||
data := make([]map[string]interface{}, 0)
|
||||
for i, s := range sql {
|
||||
log.Tracef("SQL[%d]: %s", i, sql[i])
|
||||
|
||||
mapRows := make(map[string]interface{})
|
||||
|
||||
if s != "" {
|
||||
// err = XEngine.SQL(s).Find(&rows)
|
||||
if !IsQuerySQL(s) {
|
||||
services.ResponseNotAcceptable406QuerySQLError(w)
|
||||
return
|
||||
}
|
||||
|
||||
querySQL := s
|
||||
if i == (len(sql) - 1) {
|
||||
querySQL = querySQL + " " + ls
|
||||
}
|
||||
log.Debug("querySQL:", querySQL)
|
||||
rows, err := DbClient.XEngine.QueryInterface(querySQL)
|
||||
if err != nil {
|
||||
log.Error("SQL failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
tableName := GetTableName(s)
|
||||
log.Debugf("s:%s tableName:%s", s, tableName)
|
||||
mapRows[tableName] = rows
|
||||
data = append(data, mapRows)
|
||||
log.Trace("data:", data)
|
||||
}
|
||||
i++
|
||||
}
|
||||
xormResponse.Data = data
|
||||
|
||||
services.ResponseWithJson(w, http.StatusOK, xormResponse)
|
||||
}
|
||||
|
||||
func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseInsertData processing... ")
|
||||
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
module := ""
|
||||
dbname := vars["elementTypeValue"]
|
||||
tbname := vars["objectTypeValue"]
|
||||
pack := "dbrest"
|
||||
|
||||
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to get permission:", err)
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
// if !exist {
|
||||
// log.Error("permission deny!")
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
log.Debug("Request body:", string(body), "dataObject:", tbname)
|
||||
insertData := make(map[string]interface{})
|
||||
_ = json.Unmarshal(body, &insertData)
|
||||
|
||||
tn, sql := dborm.ConstructInsertSQL(tbname, insertData)
|
||||
log.Tracef("tn: %s sql :%s", tn, sql)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
var affected int64
|
||||
for _, s := range sql {
|
||||
res, err := xSession.Exec(s)
|
||||
if err != nil {
|
||||
log.Error("Insert failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
n, _ := res.RowsAffected()
|
||||
affected = affected + n
|
||||
}
|
||||
xSession.Commit()
|
||||
// affected, err := InsertDataWithJson(insertData)
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow[tn] = row
|
||||
// xormResponse.Data = mapRow
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
|
||||
func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseUpdateData processing... ")
|
||||
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
module := ""
|
||||
dbname := vars["elementTypeValue"]
|
||||
tbname := vars["objectTypeValue"]
|
||||
pack := "dbrest"
|
||||
|
||||
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to get permission:", err)
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
// if !exist {
|
||||
// log.Error("Not permission!")
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
wc := services.GetUriLocString(r)
|
||||
|
||||
log.Debug("Request body:", string(body), "Tablename:", tbname, "wc:", wc)
|
||||
updateData := make(map[string]interface{})
|
||||
_ = json.Unmarshal(body, &updateData)
|
||||
|
||||
tn, sql := dborm.ConstructUpdateSQL(tbname, updateData, wc)
|
||||
log.Tracef("tn: %s sql :%s", tn, sql)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
var affected int64
|
||||
for _, s := range sql {
|
||||
res, err := xSession.Exec(s)
|
||||
if err != nil {
|
||||
log.Error("Update failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
n, _ := res.RowsAffected()
|
||||
affected = affected + n
|
||||
}
|
||||
xSession.Commit()
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow[tn] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
|
||||
func ExtDatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseDeleteData processing... ")
|
||||
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
module := ""
|
||||
dbname := vars["elementTypeValue"]
|
||||
tbname := vars["objectTypeValue"]
|
||||
pack := "dbreset"
|
||||
|
||||
log.Debugf("method:%s, module:%, dbname:%s, tbname:%s pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to get permission:", err)
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
// if !exist {
|
||||
// log.Error("Not permission!")
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
wc := services.GetUriLocString(r)
|
||||
|
||||
log.Debug("Table name:", tbname, "wc:", wc)
|
||||
|
||||
sql := dborm.ConstructDeleteSQL(tbname, wc)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
res, err := xSession.Exec(sql)
|
||||
if err != nil {
|
||||
log.Error("Update failed, err:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
affected, _ := res.RowsAffected()
|
||||
xSession.Commit()
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow["data"] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
|
||||
// xorm Get data from database
|
||||
func DatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DatabaseGetData processing... ")
|
||||
|
||||
var sql []string
|
||||
var err error
|
||||
|
||||
// _, err = services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
tblName := vars["objectTypeValue"]
|
||||
sql = GetUriSQLArray(r)
|
||||
// select as must, todo ...
|
||||
|
||||
if sql == nil {
|
||||
wc := services.GetUriWhereString(r)
|
||||
if wc == "" {
|
||||
sql = append(sql, fmt.Sprintf("select * from %s", tblName))
|
||||
} else {
|
||||
sql = append(sql, fmt.Sprintf("select * from %s where %s", tblName, wc))
|
||||
}
|
||||
}
|
||||
|
||||
ls := services.GetUriPageLimitString(r)
|
||||
|
||||
// data := make([]map[string]interface{}, 0)
|
||||
// xormResponse := make([]map[string]interface{}, len(sql))
|
||||
var xormResponse XormResponse
|
||||
data := make([]map[string]interface{}, 0)
|
||||
for i, s := range sql {
|
||||
log.Tracef("SQL[%d]: %s", i, sql[i])
|
||||
|
||||
rows := make([]map[string]interface{}, 0)
|
||||
mapRows := make(map[string]interface{})
|
||||
|
||||
if s != "" {
|
||||
// err = XEngine.SQL(s).Find(&rows)
|
||||
if !IsQuerySQL(s) {
|
||||
services.ResponseNotAcceptable406QuerySQLError(w)
|
||||
return
|
||||
}
|
||||
|
||||
querySQL := s
|
||||
if i == (len(sql) - 1) {
|
||||
querySQL = querySQL + " " + ls
|
||||
}
|
||||
log.Debug("querySQL:", querySQL)
|
||||
rows, err = DbClient.XEngine.QueryInterface(querySQL)
|
||||
if err != nil {
|
||||
log.Error("QueryInterface failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
tableName := GetTableName(s)
|
||||
log.Debugf("s:%s tableName:%s", s, tableName)
|
||||
mapRows[tableName] = rows
|
||||
data = append(data, mapRows)
|
||||
log.Trace("data:", data)
|
||||
}
|
||||
i++
|
||||
}
|
||||
xormResponse.Data = data
|
||||
|
||||
services.ResponseWithJson(w, http.StatusOK, xormResponse)
|
||||
}
|
||||
|
||||
func DatabaseInsertData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DatabaseInsertData processing... ")
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
tableName := vars["objectTypeValue"]
|
||||
log.Debug("Request body:", string(body), "tableName:", tableName)
|
||||
insertData := make(map[string]interface{})
|
||||
_ = json.Unmarshal(body, &insertData)
|
||||
|
||||
// 操作日志的IP
|
||||
if tableName == "operation_log" || tableName == "security_log" {
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
s := insertData["data"].([]any)
|
||||
a := s[0].(map[string]any)
|
||||
a["op_ip"] = ipAddr
|
||||
} else if tableName == "mml_log" {
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
s := insertData["data"].([]any)
|
||||
a := s[0].(map[string]any)
|
||||
a["ip"] = ipAddr
|
||||
}
|
||||
|
||||
tn, sql := dborm.ConstructInsertSQL(tableName, insertData)
|
||||
log.Tracef("tn: %s sql :%s", tn, sql)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
var affected int64
|
||||
for _, s := range sql {
|
||||
res, err := xSession.Exec(s)
|
||||
if err != nil {
|
||||
log.Error("Insert failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
n, _ := res.RowsAffected()
|
||||
affected = affected + n
|
||||
}
|
||||
xSession.Commit()
|
||||
// affected, err := InsertDataWithJson(insertData)
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow[tn] = row
|
||||
// xormResponse.Data = mapRow
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
|
||||
func DatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DatabaseUpdateData processing... ")
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
tblName := vars["objectTypeValue"]
|
||||
wc := services.GetUriWhereString(r)
|
||||
|
||||
log.Debug("Request body:", string(body), "Table name:", tblName, "wc:", wc)
|
||||
updateData := make(map[string]interface{})
|
||||
_ = json.Unmarshal(body, &updateData)
|
||||
|
||||
tn, sql := dborm.ConstructUpdateSQL(tblName, updateData, wc)
|
||||
log.Tracef("tn: %s sql :%s", tn, sql)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
var affected int64
|
||||
for _, s := range sql {
|
||||
res, err := xSession.Exec(s)
|
||||
if err != nil {
|
||||
log.Error("Update failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
n, _ := res.RowsAffected()
|
||||
affected = affected + n
|
||||
}
|
||||
xSession.Commit()
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow[tn] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
|
||||
func DatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DatabaseDeleteData processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
tblName := vars["objectTypeValue"]
|
||||
wc := services.GetUriWhereString(r)
|
||||
|
||||
log.Debug("Table name:", tblName, "wc:", wc)
|
||||
|
||||
sql := dborm.ConstructDeleteSQL(tblName, wc)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
res, err := xSession.Exec(sql)
|
||||
if err != nil {
|
||||
log.Error("Update failed, err:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
affected, _ := res.RowsAffected()
|
||||
xSession.Commit()
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow["data"] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
|
||||
// 连接用户实例
|
||||
func DbConnection(w http.ResponseWriter, r *http.Request) {
|
||||
if dborm.DbClient.XEngine == nil {
|
||||
services.ResponseErrorWithJson(w, 400, "无连接")
|
||||
}
|
||||
// 查询实例
|
||||
result, err := dborm.DbClient.XEngine.QueryString("SHOW PROCESSLIST;")
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 500, err.Error())
|
||||
}
|
||||
filterData := []map[string]string{}
|
||||
for _, r := range result {
|
||||
if r["User"] != "system user" {
|
||||
filterData = append(filterData, r)
|
||||
}
|
||||
}
|
||||
// Sleep:连接处于空闲状态,没有执行任何操作。
|
||||
// Query:连接正在执行一个查询语句。
|
||||
// Execute:连接正在执行一个准备好的 SQL 语句。
|
||||
// Connect:连接正在建立但尚未完成。
|
||||
services.ResponseWithJson(w, 200, filterData)
|
||||
}
|
||||
|
||||
// 关闭数据库连接
|
||||
func DbStop(w http.ResponseWriter, r *http.Request) {
|
||||
if dborm.DbClient.XEngine == nil {
|
||||
services.ResponseErrorWithJson(w, 400, "无连接")
|
||||
}
|
||||
|
||||
// json 請求參數獲取
|
||||
var bodyArgs struct {
|
||||
ID string `json:"ID" validate:"required"`
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 关闭
|
||||
rse, err := dborm.DbClient.XEngine.Exec("KILL ?;", bodyArgs.ID)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
services.ResponseWithJson(w, 200, rse)
|
||||
}
|
||||
|
||||
// xorm Get data from database
|
||||
func TaskDatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DatabaseGetData processing... ")
|
||||
|
||||
var sql []string
|
||||
var err error
|
||||
|
||||
vars := mux.Vars(r)
|
||||
tblName := vars["objectTypeValue"]
|
||||
sql = GetUriSQLArray(r)
|
||||
// select as must, todo ...
|
||||
|
||||
if sql == nil {
|
||||
wc := services.GetUriWhereString(r)
|
||||
if wc == "" {
|
||||
sql = append(sql, fmt.Sprintf("select * from %s", tblName))
|
||||
} else {
|
||||
sql = append(sql, fmt.Sprintf("select * from %s where %s", tblName, wc))
|
||||
}
|
||||
}
|
||||
|
||||
ls := services.GetUriPageLimitString(r)
|
||||
|
||||
// data := make([]map[string]interface{}, 0)
|
||||
// xormResponse := make([]map[string]interface{}, len(sql))
|
||||
var xormResponse XormResponse
|
||||
data := make([]map[string]interface{}, 0)
|
||||
for i, s := range sql {
|
||||
log.Tracef("SQL[%d]: %s", i, sql[i])
|
||||
|
||||
rows := make([]map[string]interface{}, 0)
|
||||
mapRows := make(map[string]interface{})
|
||||
|
||||
if s != "" {
|
||||
// err = XEngine.SQL(s).Find(&rows)
|
||||
if IsQuerySQL(s) == false {
|
||||
services.ResponseNotAcceptable406QuerySQLError(w)
|
||||
return
|
||||
}
|
||||
|
||||
querySQL := s
|
||||
if i == (len(sql) - 1) {
|
||||
querySQL = querySQL + " " + ls
|
||||
}
|
||||
log.Debug("querySQL:", querySQL)
|
||||
rows, err = DbClient.XEngine.QueryInterface(querySQL)
|
||||
if err != nil {
|
||||
log.Error("SQL failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
tableName := GetTableName(s)
|
||||
log.Debugf("s:%s tableName:%s", s, tableName)
|
||||
mapRows[tableName] = rows
|
||||
data = append(data, mapRows)
|
||||
log.Trace("data:", data)
|
||||
}
|
||||
i++
|
||||
}
|
||||
xormResponse.Data = data
|
||||
|
||||
services.ResponseWithJson(w, http.StatusOK, xormResponse)
|
||||
}
|
||||
|
||||
func TaskDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DatabaseInsertData processing... ")
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
tableName := vars["objectTypeValue"]
|
||||
log.Debug("Request body:", string(body), "tableName:", tableName)
|
||||
insertData := make(map[string]interface{})
|
||||
_ = json.Unmarshal(body, &insertData)
|
||||
|
||||
tn, sql := dborm.ConstructInsertSQL(tableName, insertData)
|
||||
log.Tracef("tn: %s sql :%s", tn, sql)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
var affected int64
|
||||
for _, s := range sql {
|
||||
res, err := xSession.Exec(s)
|
||||
if err != nil {
|
||||
log.Error("Insert failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
n, _ := res.RowsAffected()
|
||||
affected = affected + n
|
||||
}
|
||||
xSession.Commit()
|
||||
// affected, err := InsertDataWithJson(insertData)
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow[tn] = row
|
||||
// xormResponse.Data = mapRow
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
|
||||
func TaskDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DatabaseUpdateData processing... ")
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
tblName := vars["objectTypeValue"]
|
||||
wc := services.GetUriWhereString(r)
|
||||
|
||||
log.Debug("Request body:", string(body), "Table name:", tblName, "wc:", wc)
|
||||
updateData := make(map[string]interface{})
|
||||
_ = json.Unmarshal(body, &updateData)
|
||||
|
||||
tn, sql := dborm.ConstructUpdateSQL(tblName, updateData, wc)
|
||||
log.Tracef("tn: %s sql :%s", tn, sql)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
var affected int64
|
||||
for _, s := range sql {
|
||||
res, err := xSession.Exec(s)
|
||||
if err != nil {
|
||||
log.Error("Update failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
n, _ := res.RowsAffected()
|
||||
affected = affected + n
|
||||
}
|
||||
xSession.Commit()
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow[tn] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
|
||||
func TaskDatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DatabaseDeleteData processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
tblName := vars["objectTypeValue"]
|
||||
wc := services.GetUriWhereString(r)
|
||||
|
||||
log.Debug("Table name:", tblName, "wc:", wc)
|
||||
|
||||
sql := dborm.ConstructDeleteSQL(tblName, wc)
|
||||
xSession := DbClient.XEngine.NewSession()
|
||||
defer xSession.Close()
|
||||
res, err := xSession.Exec(sql)
|
||||
if err != nil {
|
||||
log.Error("Update failed, err:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
affected, _ := res.RowsAffected()
|
||||
xSession.Commit()
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow["data"] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
wsService "be.ems/src/modules/ws/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
// 走Gin
|
||||
UriUEEventAMF = "/upload-ue/v1/:eventType"
|
||||
// 走Mux
|
||||
UriUEEvent = config.DefaultUriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
|
||||
CustomUriUEEvent = config.UriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
|
||||
)
|
||||
|
||||
type UEEvent struct {
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeName string `json:"neName" xorm:"ne_name"`
|
||||
RmUID string `json:"rmUID" xorm:"rm_uid"`
|
||||
Timestamp int64 `json:"timestamp" xorm:"timestamp"`
|
||||
EventType string `json:"eventType" xorm:"event_type"`
|
||||
EventJson map[string]any `json:"eventJSON" xorm:"event_json"`
|
||||
}
|
||||
|
||||
// 旧AMF上报处理
|
||||
func PostUEEventFromAMF(c *gin.Context) {
|
||||
log.Info("PostUEEventFromAMF processing... ")
|
||||
|
||||
eventType, ok := c.Params.Get("eventType")
|
||||
if !ok || eventType == "" {
|
||||
log.Error("eventType is empty")
|
||||
services.ResponseNotFound404UriNotExist(c.Writer, c.Request)
|
||||
return
|
||||
}
|
||||
var body map[string]any
|
||||
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
|
||||
log.Error("Failed to Unmarshal ueEvent:", err)
|
||||
services.ResponseInternalServerError500ProcessError(c.Writer, err)
|
||||
return
|
||||
}
|
||||
|
||||
ueEvent := UEEvent{
|
||||
NeType: "AMF",
|
||||
Timestamp: time.Now().Unix(),
|
||||
EventType: eventType,
|
||||
}
|
||||
// 从eventJson中获取rmUID
|
||||
if v, ok := body["rmUID"]; ok {
|
||||
ueEvent.RmUID = fmt.Sprint(v)
|
||||
} else {
|
||||
ueEvent.RmUID = "4400HXAMF001"
|
||||
}
|
||||
if v, ok := body["neName"]; ok {
|
||||
ueEvent.NeName = fmt.Sprint(v)
|
||||
} else {
|
||||
ueEvent.NeName = "AMF_001"
|
||||
}
|
||||
|
||||
// 统一格式
|
||||
eventJson := map[string]any{"cellID": 0, "gNBID": "", "imsi": "", "onlineNumber": 0, "result": "", "tacID": 0, "timestamp": 0, "time": 0, "type": eventType}
|
||||
switch eventType {
|
||||
case "auth-result":
|
||||
// {"authCode":"200","authMessage":"成功","authTime":"2024-12-07 16:48:37","cellID":"3","gNBID":"1","imsi":"460002082100000","onlineNumber":1,"tacID":"81"}
|
||||
if v, ok := body["imsi"]; ok {
|
||||
eventJson["imsi"] = fmt.Sprint(v)
|
||||
}
|
||||
if v, ok := body["cellID"]; ok {
|
||||
eventJson["cellID"] = fmt.Sprint(v)
|
||||
}
|
||||
if v, ok := body["gNBID"]; ok {
|
||||
eventJson["gNBID"] = fmt.Sprint(v)
|
||||
}
|
||||
if v, ok := body["tacID"]; ok {
|
||||
eventJson["tacID"] = fmt.Sprint(v)
|
||||
}
|
||||
if v, ok := body["onlineNumber"]; ok {
|
||||
eventJson["onlineNumber"] = parse.Number(v)
|
||||
}
|
||||
if v, ok := body["authCode"]; ok {
|
||||
eventJson["result"] = fmt.Sprint(v)
|
||||
}
|
||||
if v, ok := body["authTime"]; ok {
|
||||
eventJson["timestamp"] = ueEvent.Timestamp
|
||||
eventJson["time"] = fmt.Sprint(v)
|
||||
}
|
||||
case "detach":
|
||||
// {"detachResult":0,"detachTime":"2024-12-07 18:00:47","imsi":"460002082100000"}
|
||||
if v, ok := body["imsi"]; ok {
|
||||
eventJson["imsi"] = fmt.Sprint(v)
|
||||
}
|
||||
if v, ok := body["detachResult"]; ok {
|
||||
if fmt.Sprint(v) == "0" {
|
||||
eventJson["result"] = "200"
|
||||
} else {
|
||||
eventJson["result"] = "500"
|
||||
}
|
||||
}
|
||||
if v, ok := body["detachTime"]; ok {
|
||||
eventJson["timestamp"] = ueEvent.Timestamp
|
||||
eventJson["time"] = fmt.Sprint(v)
|
||||
}
|
||||
case "cm-state":
|
||||
// {"changeTime":"2024-12-07 17:07:52","imsi":"460002082100000","onlineNumber":1,"status":2}
|
||||
if v, ok := body["imsi"]; ok {
|
||||
eventJson["imsi"] = fmt.Sprint(v)
|
||||
}
|
||||
if v, ok := body["onlineNumber"]; ok {
|
||||
eventJson["onlineNumber"] = parse.Number(v)
|
||||
}
|
||||
if v, ok := body["status"]; ok {
|
||||
eventJson["result"] = fmt.Sprint(v)
|
||||
}
|
||||
if v, ok := body["changeTime"]; ok {
|
||||
eventJson["timestamp"] = ueEvent.Timestamp
|
||||
eventJson["time"] = fmt.Sprint(v)
|
||||
}
|
||||
}
|
||||
ueEvent.EventJson = eventJson
|
||||
|
||||
affected, err := dborm.XormInsertTableOne("ue_event_amf", ueEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert ue_event_amf:", err)
|
||||
services.ResponseInternalServerError500ProcessError(c.Writer, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 发送到匹配的网元
|
||||
neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(ueEvent.RmUID)
|
||||
if neInfo.RmUID == ueEvent.RmUID {
|
||||
// 推送到ws订阅组
|
||||
if ueEvent.NeType == "AMF" {
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, ueEvent)
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, ueEvent)
|
||||
}
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(c.Writer)
|
||||
}
|
||||
|
||||
// UE上报处理
|
||||
func PostUEEvent(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostUEEvent processing... ")
|
||||
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
var ueEvent UEEvent
|
||||
if err := ctx.ShouldBindJSON(r, &ueEvent); err != nil {
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
ueEvent.NeType = strings.ToUpper(neType)
|
||||
tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(neType))
|
||||
affected, err := dborm.XormInsertTableOne(tableName, ueEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert "+tableName, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 发送到匹配的网元
|
||||
neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(ueEvent.RmUID)
|
||||
if neInfo.RmUID == ueEvent.RmUID {
|
||||
// 推送到ws订阅组
|
||||
if ueEvent.NeType == "MME" {
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE, ueEvent)
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE+"_"+neInfo.NeId, ueEvent)
|
||||
}
|
||||
if ueEvent.NeType == "AMF" {
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, ueEvent)
|
||||
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, ueEvent)
|
||||
}
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package features
|
||||
|
||||
import (
|
||||
"be.ems/features/cm"
|
||||
"be.ems/features/lm"
|
||||
"be.ems/features/nbi"
|
||||
"be.ems/features/pm"
|
||||
"be.ems/lib/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitServiceEngine(r *gin.Engine) {
|
||||
log.Info("======init feature group gin.Engine")
|
||||
|
||||
// featuresGroup := r.Group("/")
|
||||
// register features routers
|
||||
pm.InitSubServiceRoute(r)
|
||||
lm.InitSubServiceRoute(r)
|
||||
cm.InitSubServiceRoute(r)
|
||||
nbi.InitSubServiceRoute(r)
|
||||
// return featuresGroup
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var (
|
||||
// parameter config management
|
||||
UriFile = config.DefaultUriPrefix + "/fileManagement/{apiVersion}/{location}/file"
|
||||
CustomUriFile = config.UriPrefix + "/fileManagement/{apiVersion}/{location}/file"
|
||||
)
|
||||
|
||||
// func init() {
|
||||
// routes.Register("POST", UriFile, UploadFile, nil)
|
||||
// routes.Register("GET", UriFile, DownloadFile, nil)
|
||||
// routes.Register("DELETE", UriFile, DeleteFile, nil)
|
||||
// }
|
||||
|
||||
func UploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("UploadFile processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Http request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
location := vars["location"]
|
||||
if location == "" {
|
||||
log.Error("location is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
params := r.URL.Query()
|
||||
rename, ok := params["rename"]
|
||||
if !ok {
|
||||
log.Info("rename parameter is not exist")
|
||||
}
|
||||
log.Debug("rename:", rename)
|
||||
|
||||
var path, fileName string
|
||||
if len(rename) > 0 {
|
||||
fileName = rename[0]
|
||||
}
|
||||
if location == "upload" {
|
||||
path = config.GetYamlConfig().OMC.Upload
|
||||
fileNamePath, err := services.HandleUploadFile(r, path, fileName)
|
||||
if err != nil {
|
||||
log.Error("Faile to HandleUploadFile:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
fileName = fileNamePath
|
||||
} else {
|
||||
path = config.GetYamlConfig().OMC.FrontUpload
|
||||
fileNamePath, err := services.HandleUploadFile(r, path, fileName)
|
||||
if err != nil {
|
||||
log.Error("Faile to HandleUploadFile:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
fileName = fileNamePath
|
||||
}
|
||||
log.Debugf("upload file=%s to path=%s", fileName, path)
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
return
|
||||
}
|
||||
|
||||
func DownloadFile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DownloadFile processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
location := vars["location"]
|
||||
if location == "" {
|
||||
log.Error("location is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 全路径文件下载
|
||||
filePath := r.URL.Query().Get("path")
|
||||
if location == "path" && filePath != "" {
|
||||
// 截取文件路径
|
||||
dir := filepath.Dir(filePath)
|
||||
// 截取文件名
|
||||
fileName := filepath.Base(filePath)
|
||||
services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, dir, "")
|
||||
return
|
||||
}
|
||||
|
||||
params := r.URL.Query()
|
||||
fileNames, ok := params["loc"]
|
||||
if !ok {
|
||||
log.Info("loc parameter is not exist")
|
||||
}
|
||||
var path string
|
||||
if location == "upload" {
|
||||
path = config.GetYamlConfig().OMC.Upload
|
||||
} else {
|
||||
path = config.GetYamlConfig().OMC.FrontUpload
|
||||
}
|
||||
for _, fileName := range fileNames {
|
||||
services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, "")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteFile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DeleteFile processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["neType"]
|
||||
if neType == "" {
|
||||
log.Error("neType is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,797 @@
|
||||
package fm
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
"xorm.io/xorm"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const (
|
||||
AlarmStatusClear = 0
|
||||
AlarmStatusActive = 1
|
||||
AlarmStatusClearString = "0"
|
||||
AlarmStatusActiveString = "1"
|
||||
)
|
||||
|
||||
const (
|
||||
ClearTypeUnclear = 0
|
||||
ClearTypeAutoClear = 1
|
||||
ClearTypeManualClear = 2
|
||||
)
|
||||
|
||||
const (
|
||||
AckStateUnacked = 0
|
||||
AckStateAcked = 1
|
||||
)
|
||||
|
||||
const (
|
||||
AlarmTypeCommunicationAlarm = 1
|
||||
AlarmTypeEquipmentAlarm = 2
|
||||
AlarmTypeProcessingFailure = 3
|
||||
AlarmTypeEnvironmentalAlarm = 4
|
||||
AlarmTypeQualityOfServiceAlarm = 5
|
||||
)
|
||||
|
||||
const (
|
||||
AlarmPerceivedSeverityCritical = 1
|
||||
AlarmPerceivedSeverityMajor = 2
|
||||
AlarmPerceivedSeverityMinor = 3
|
||||
AlarmPerceivedSeverityWarning = 4
|
||||
AlarmPerceivedSeverityEvent = 5
|
||||
)
|
||||
|
||||
const (
|
||||
AlarmSeqBeginNumber = 1
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type Alarm struct {
|
||||
AlarmSeq int `json:"alarmSeq"`
|
||||
AlarmId string `json:"alarmId" xorm:"alarm_id"`
|
||||
NeId string `json:"neId"`
|
||||
AlarmCode int `json:"alarmCode"`
|
||||
AlarmTitle string `json:"alarmTitle"`
|
||||
EventTime string `json:"eventTime"`
|
||||
AlarmType string `json:"alarmType"`
|
||||
OrigSeverity string `json:"origSeverity"`
|
||||
PerceivedSeverity string `json:"perceivedSeverity"`
|
||||
PVFlag string `json:"pvFlag" xorm:"pv_flag"`
|
||||
NeName string `json:"neName"`
|
||||
NeType string `json:"neType"`
|
||||
ObjectUid string `json:"objectUid" xorm:"object_uid"`
|
||||
ObjectName string `json:"objectName" xorm:"object_name"`
|
||||
ObjectType string `json:"objectType" xorm:"object_type"`
|
||||
LocationInfo string `json:"locationInfo"`
|
||||
Province string `json:"province"`
|
||||
AlarmStatus int `json:"alarmStatus"`
|
||||
SpecificProblem string `json:"specificProblem"`
|
||||
SpecificProblemID string `json:"specificProblemID" xorm:"specific_problem_id"`
|
||||
AddInfo string `json:"addInfo"`
|
||||
|
||||
AckState int `json:"ackState"`
|
||||
AckTime sql.NullTime `json:"ackTime"`
|
||||
AckUser string `json:"ackUser"`
|
||||
ClearType int `json:"clearType"` // 0: Unclear, 1: Auto clear, 2: Manual clear
|
||||
ClearTime sql.NullTime `json:"clearTime"`
|
||||
}
|
||||
|
||||
type AlarmLog struct {
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeId string `json:"neId" xorm:"ne_id"`
|
||||
AlarmSeq int `json:"alarmSeq" xorm:"alarm_seq"`
|
||||
AlarmId string `json:"alarmId" xorm:"alarm_id"`
|
||||
AlarmCode int `json:"alarmCode" xorm:"alarm_code"`
|
||||
AlarmStatus int `json:"alarmStatus" xorm:"alarm_status"`
|
||||
EventTime string `json:"eventTime" xorm:"event_time"`
|
||||
// ClearTime sql.NullTime `json:"clearTime" xorm:"clear_time"`
|
||||
LogTime string `json:"logTime" xorm:"-"`
|
||||
}
|
||||
|
||||
var (
|
||||
// alarm management
|
||||
UriAlarms = config.DefaultUriPrefix + "/faultManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/alarms"
|
||||
UriAlarmsFmt = config.DefaultUriPrefix + "/faultManagement/v1/elementType/%s/objectType/alarms"
|
||||
|
||||
CustomUriAlarms = config.UriPrefix + "/faultManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/alarms"
|
||||
CustomUriAlarmsFmt = config.UriPrefix + "/faultManagement/v1/elementType/%s/objectType/alarms"
|
||||
)
|
||||
|
||||
var client = resty.New()
|
||||
|
||||
func init() {
|
||||
/*
|
||||
client.
|
||||
SetTimeout(10 * time.Second).
|
||||
SetRetryCount(1).
|
||||
SetRetryWaitTime(1 * time.Second).
|
||||
SetRetryMaxWaitTime(2 * time.Second).
|
||||
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
|
||||
return 0, errors.New("quota exceeded")
|
||||
})
|
||||
*/
|
||||
client.
|
||||
SetTimeout(time.Duration(500 * time.Millisecond))
|
||||
// SetRetryCount(1).
|
||||
// SetRetryWaitTime(time.Duration(1 * time.Second)).
|
||||
// SetRetryMaxWaitTime(time.Duration(2 * time.Second))
|
||||
//client.SetTimeout(2 * time.Second)
|
||||
}
|
||||
|
||||
var xEngine *xorm.Engine
|
||||
|
||||
type DatabaseClient struct {
|
||||
dbType string
|
||||
dbUrl string
|
||||
dbConnMaxLifetime time.Duration
|
||||
dbMaxIdleConns int
|
||||
dbMaxOpenConns int
|
||||
IsShowSQL bool
|
||||
|
||||
XEngine *xorm.Engine
|
||||
}
|
||||
|
||||
var DbClient DatabaseClient
|
||||
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
|
||||
DbClient.dbType = dbType
|
||||
DbClient.dbConnMaxLifetime = 0
|
||||
DbClient.dbMaxIdleConns = 0
|
||||
DbClient.dbMaxOpenConns = 0
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
DbClient.IsShowSQL = true
|
||||
}
|
||||
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
|
||||
|
||||
var err error
|
||||
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
|
||||
if err != nil {
|
||||
log.Error("Failed to connet database:", err)
|
||||
return err
|
||||
}
|
||||
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
|
||||
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
|
||||
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
|
||||
DbClient.XEngine.DatabaseTZ = time.Local // 必须
|
||||
DbClient.XEngine.TZLocation = time.Local // 必须
|
||||
if DbClient.IsShowSQL {
|
||||
DbClient.XEngine.ShowSQL(true)
|
||||
}
|
||||
xEngine = DbClient.XEngine
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func XormConnectDatabase(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) (*xorm.Engine, error) {
|
||||
sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
log.Debugf("dbType:%s Connect to:%s:******@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbType, dbUser, dbHost, dbPort, dbName)
|
||||
var err error
|
||||
xEngine, err = xorm.NewEngine(dbType, sqlStr) //1、Create xorm engine
|
||||
if err != nil {
|
||||
log.Error("Failed to connect database:", err)
|
||||
return nil, err
|
||||
}
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
xEngine.ShowSQL(true)
|
||||
}
|
||||
return xEngine, nil
|
||||
}
|
||||
|
||||
func IsNeedToAckAlarm(valueJson *dborm.ValueJson, alarm *Alarm) bool {
|
||||
log.Info("IsNeedToAckAlarm processing... ")
|
||||
if valueJson != nil {
|
||||
status, _ := strconv.Atoi(valueJson.AlarmStatus)
|
||||
log.Tracef("alarm.AlarmStatus=%d, alarm.AlarmType=%s, alarm.OrigSeverity=%s", alarm.AlarmStatus, alarm.AlarmType, alarm.OrigSeverity)
|
||||
log.Tracef("status=%d, valueJson.AlarmType=%s, valueJson.OrigSeverity=%s", status, valueJson.AlarmType, valueJson.OrigSeverity)
|
||||
|
||||
if alarm.AlarmStatus == status &&
|
||||
alarm.AlarmType == valueJson.AlarmType &&
|
||||
alarm.OrigSeverity == valueJson.OrigSeverity {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func SetAlarmAckInfo(valueJson *dborm.ValueJson, alarm *Alarm) {
|
||||
log.Info("SetAlarmAckInfo processing... ")
|
||||
alarm.AckState = AckStateAcked
|
||||
alarm.AckTime.Valid = true
|
||||
alarm.AckTime.Time = time.Now()
|
||||
alarm.AckUser = valueJson.AckUser
|
||||
}
|
||||
|
||||
// process alarm post message from NFs
|
||||
func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostAlarmFromNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != global.ApiVersionV1 {
|
||||
log.Error("Uri api version is invalid. apiVersion:", apiVer)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("Request body:", string(body))
|
||||
alarmArray := new([]Alarm)
|
||||
|
||||
err = json.Unmarshal(body, &alarmArray)
|
||||
if err != nil {
|
||||
log.Error("Failed to Unmarshal:", err)
|
||||
services.ResponseBadRequest400InvalidJson(w)
|
||||
return
|
||||
}
|
||||
|
||||
valueJson, err := dborm.XormGetAAConfig()
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetAAConfig:", err)
|
||||
//services.ResponseInternalServerError500ProcessError(w, err)
|
||||
//return
|
||||
}
|
||||
log.Trace("valueJson:", valueJson)
|
||||
// session := xEngine.NewSession()
|
||||
// defer session.Close()
|
||||
var activeAlarmNum int = 0
|
||||
for _, alarmData := range *alarmArray {
|
||||
log.Debug("alarmData:", alarmData)
|
||||
|
||||
session := xEngine.NewSession()
|
||||
defer session.Close()
|
||||
if alarmData.AlarmStatus == AlarmStatusClear {
|
||||
alarmData.ClearType = ClearTypeAutoClear
|
||||
alarmData.ClearTime.Valid = true
|
||||
tm, _ := time.Parse(time.RFC3339, alarmData.EventTime)
|
||||
log.Debugf("EventTime:%s tm:%d tm-datetime:%s", alarmData.EventTime, tm, tm.Local().Format(time.DateTime))
|
||||
alarmData.ClearTime.Time = tm
|
||||
if IsNeedToAckAlarm(valueJson, &alarmData) {
|
||||
SetAlarmAckInfo(valueJson, &alarmData)
|
||||
affected, err := session.Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId).
|
||||
Cols("alarm_status", "clear_type", "clear_time", "ack_state", "ack_time", "ack_user").
|
||||
Update(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to update alarm data:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
affected, err := session.Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId).
|
||||
Cols("alarm_status", "clear_type", "clear_time").
|
||||
Update(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to update alarm data:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
}
|
||||
log.Trace("alarmData:", alarmData)
|
||||
var currentSeq string
|
||||
var seq int
|
||||
has, err := xEngine.Table("alarm").
|
||||
Where("ne_type=? and ne_id=?", alarmData.NeType, alarmData.NeId).
|
||||
Desc("alarm_seq").
|
||||
Cols("alarm_seq").
|
||||
Limit(1).
|
||||
Get(¤tSeq)
|
||||
if err != nil {
|
||||
log.Error("Failed to get alarm:", err)
|
||||
continue
|
||||
}
|
||||
if has {
|
||||
seq, _ = strconv.Atoi(currentSeq)
|
||||
}
|
||||
|
||||
eventTime := global.GetFmtTimeString(time.RFC3339, alarmData.EventTime, time.DateTime)
|
||||
alarmLog := new(AlarmLog)
|
||||
alarmLog.NeType = alarmData.NeType
|
||||
alarmLog.NeId = alarmData.NeId
|
||||
alarmLog.AlarmSeq = seq
|
||||
alarmLog.AlarmId = alarmData.AlarmId
|
||||
alarmLog.AlarmCode = alarmData.AlarmCode
|
||||
alarmLog.AlarmStatus = alarmData.AlarmStatus
|
||||
alarmLog.EventTime = eventTime
|
||||
log.Trace("alarmLog:", alarmLog)
|
||||
|
||||
affected, err := session.Insert(alarmLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm_log:", err)
|
||||
}
|
||||
|
||||
// todo: PerceivedSeverity set color
|
||||
var severity string
|
||||
has, err = xEngine.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime).
|
||||
//OrderBy("FIELD(orig_severity, 'Critical', 'Major', 'Minor', 'Warning', 'Event') ASC").
|
||||
Asc("orig_severity").
|
||||
Cols("orig_severity").
|
||||
Limit(1).
|
||||
Get(&severity)
|
||||
if err != nil {
|
||||
log.Error("Failed to get alarm:", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("neType=%s, neId=%s, eventTime=%s, severity=%s", alarmData.NeType, alarmData.NeId, alarmData.EventTime, severity)
|
||||
|
||||
if has && severity > alarmData.OrigSeverity {
|
||||
// update exist record
|
||||
_, err := session.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime).
|
||||
Update(&Alarm{PerceivedSeverity: severity})
|
||||
if err != nil {
|
||||
log.Error("Failed to update alarm:", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
session.Commit()
|
||||
// for alarm forward time format
|
||||
alarmData.EventTime = eventTime
|
||||
} else {
|
||||
activeAlarmNum++
|
||||
has, err := xEngine.Table("alarm").
|
||||
Where("alarm_id=? and ne_type=? and ne_id=? and alarm_status=1",
|
||||
alarmData.AlarmId, alarmData.NeType, alarmData.NeId).
|
||||
Exist()
|
||||
if err == nil && has {
|
||||
log.Warn("Exist the same alarm")
|
||||
continue
|
||||
}
|
||||
|
||||
var currentSeq string
|
||||
has, err = xEngine.Table("alarm").
|
||||
Where("ne_type=? and ne_id=?", alarmData.NeType, alarmData.NeId).
|
||||
Desc("alarm_seq").
|
||||
//Desc("event_time").
|
||||
Cols("alarm_seq").
|
||||
Limit(1).
|
||||
Get(¤tSeq)
|
||||
if err != nil {
|
||||
log.Error("Failed to get alarm:", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("neType=%s, neId=%s, currentSeq=%s activeAlarmNum=%d",
|
||||
alarmData.NeType, alarmData.NeId, currentSeq, activeAlarmNum)
|
||||
|
||||
if has {
|
||||
seq, _ := strconv.Atoi(currentSeq)
|
||||
alarmData.AlarmSeq = seq + 1
|
||||
if alarmData.AlarmSeq > global.MaxInt32Number {
|
||||
alarmData.AlarmSeq = AlarmSeqBeginNumber
|
||||
}
|
||||
} else {
|
||||
alarmData.AlarmSeq = AlarmSeqBeginNumber
|
||||
}
|
||||
|
||||
// todo: PerceivedSeverity set color
|
||||
var severity string
|
||||
has, err = xEngine.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime).
|
||||
//OrderBy("FIELD(orig_severity, 'Critical', 'Major', 'Minor', 'Warning', 'Event') ASC").
|
||||
Asc("orig_severity").
|
||||
Cols("orig_severity").
|
||||
Limit(1).
|
||||
Get(&severity)
|
||||
if err != nil {
|
||||
log.Error("Failed to get alarm:", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("neType=%s, neId=%s, eventTime=%s, severity=%s", alarmData.NeType, alarmData.NeId, alarmData.EventTime, severity)
|
||||
|
||||
if !has || severity == alarmData.OrigSeverity {
|
||||
alarmData.PerceivedSeverity = alarmData.OrigSeverity
|
||||
} else if severity > alarmData.OrigSeverity {
|
||||
alarmData.PerceivedSeverity = alarmData.OrigSeverity
|
||||
} else {
|
||||
alarmData.PerceivedSeverity = severity
|
||||
// update exist record
|
||||
_, err := session.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime).
|
||||
Update(&Alarm{PerceivedSeverity: alarmData.PerceivedSeverity})
|
||||
if err != nil {
|
||||
log.Error("Failed to update alarm:", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
eventTime := global.GetFmtTimeString(time.RFC3339, alarmData.EventTime, time.DateTime)
|
||||
alarmData.ObjectUid = alarmData.NeId
|
||||
alarmData.ObjectType = "VNFM"
|
||||
alarmData.EventTime = eventTime
|
||||
if alarmData.LocationInfo == "" {
|
||||
alarmData.LocationInfo = fmt.Sprintf("Host:%s", r.RemoteAddr)
|
||||
}
|
||||
if alarmData.AddInfo == "" {
|
||||
alarmData.AddInfo = fmt.Sprintf("subNeInfo:%s", alarmData.NeType)
|
||||
}
|
||||
if IsNeedToAckAlarm(valueJson, &alarmData) {
|
||||
SetAlarmAckInfo(valueJson, &alarmData)
|
||||
}
|
||||
log.Trace("alarmData:", alarmData)
|
||||
if (alarmData.OrigSeverity == "Event" || alarmData.OrigSeverity == "5") && config.GetYamlConfig().Alarm.SplitEventAlarm {
|
||||
affected, err := xEngine.Table("alarm_event").InsertOne(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm_event:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
affected, err := session.Insert(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm data:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
}
|
||||
alarmLog := new(AlarmLog)
|
||||
alarmLog.NeType = alarmData.NeType
|
||||
alarmLog.NeId = alarmData.NeId
|
||||
alarmLog.AlarmSeq = alarmData.AlarmSeq
|
||||
alarmLog.AlarmId = alarmData.AlarmId
|
||||
alarmLog.AlarmCode = alarmData.AlarmCode
|
||||
alarmLog.AlarmStatus = alarmData.AlarmStatus
|
||||
alarmLog.EventTime = eventTime
|
||||
log.Trace("alarmLog:", alarmLog)
|
||||
|
||||
affected, err := session.Insert(alarmLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm_log:", err)
|
||||
}
|
||||
session.Commit()
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
type AlarmEvent struct {
|
||||
AlarmSeq int `json:"alarmSeq"`
|
||||
AlarmId string `json:"alarmId" xorm:"alarm_id"`
|
||||
NeId string `json:"neId"`
|
||||
AlarmCode int `json:"alarmCode"`
|
||||
AlarmTitle string `json:"alarmTitle"`
|
||||
EventTime string `json:"eventTime"`
|
||||
AlarmType string `json:"alarmType"`
|
||||
OrigSeverity string `json:"origSeverity"`
|
||||
PVFlag string `json:"pvFlag" xorm:"pv_flag"`
|
||||
NeName string `json:"neName"`
|
||||
NeType string `json:"neType"`
|
||||
ObjectUid string `json:"objectUid" xorm:"object_uid"`
|
||||
ObjectName string `json:"objectName" xorm:"object_name"`
|
||||
ObjectType string `json:"objectType" xorm:"object_type"`
|
||||
LocationInfo string `json:"locationInfo"`
|
||||
Province string `json:"province"`
|
||||
SpecificProblem string `json:"specificProblem"`
|
||||
SpecificProblemID string `json:"specificProblemID" xorm:"specific_problem_id"`
|
||||
AddInfo string `json:"addInfo"`
|
||||
}
|
||||
|
||||
// process alarm get from NFs
|
||||
func GetAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetAlarmFromNF processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
neTypeLower := strings.ToLower(neType)
|
||||
|
||||
// Get alarms from OMC return 204
|
||||
if neTypeLower == strings.ToLower(config.GetYamlConfig().OMC.NeType) {
|
||||
log.Infof("Return no content alarms from %s", neType)
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
return
|
||||
}
|
||||
|
||||
//var neInfo *dborm.NeInfo
|
||||
var nes []dborm.NeInfo
|
||||
_, err := dborm.XormGetAllNeInfo(&nes)
|
||||
if err != nil {
|
||||
log.Error("Failed to get all ne info:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, ne := range nes {
|
||||
hostUri := fmt.Sprintf("http://%s:%v", ne.Ip, ne.Port)
|
||||
apiUri := fmt.Sprintf(UriAlarmsFmt, strings.ToLower(ne.NeType))
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, apiUri)
|
||||
log.Debug("requestURI2NF: Get ", requestURI2NF)
|
||||
// client := resty.New()
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Get:", err)
|
||||
//services.ResponseInternalServerError500ProcessError(w, err)
|
||||
continue
|
||||
}
|
||||
|
||||
alarmArray := new([]Alarm)
|
||||
switch response.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
body := response.Body()
|
||||
if len(body) == 0 || body == nil {
|
||||
log.Infof("Empty alarm body from neType=%s, neId=%s", ne.NeType, ne.NeId)
|
||||
//services.ResponseInternalServerError500ProcessError(w, err)
|
||||
continue
|
||||
}
|
||||
//log.Debug("Request body:", string(body))
|
||||
|
||||
err = json.Unmarshal(body, &alarmArray)
|
||||
if err != nil {
|
||||
log.Error("Failed to Unmarshal:", err)
|
||||
//services.ResponseInternalServerError500ProcessError(w, err)
|
||||
continue
|
||||
}
|
||||
default:
|
||||
log.Error("Failed to get alarms:", response.Status)
|
||||
continue
|
||||
}
|
||||
|
||||
valueJson, err := dborm.XormGetAAConfig()
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetAAConfig:", err)
|
||||
//services.ResponseInternalServerError500ProcessError(w, err)
|
||||
continue
|
||||
}
|
||||
if alarmArray == nil {
|
||||
log.Infof("Not found sync alarms, neType=%s, neId=%s", ne.NeType, ne.NeId)
|
||||
//services.ResponseInternalServerError500ProcessError(w, err)
|
||||
continue
|
||||
}
|
||||
// session := xEngine.NewSession()
|
||||
// defer session.Close()
|
||||
var activeAlarmNum int = 0
|
||||
for _, alarmData := range *alarmArray {
|
||||
log.Debug("alarmData:", alarmData)
|
||||
|
||||
session := xEngine.NewSession()
|
||||
defer session.Close()
|
||||
// todo: clear alarm ....
|
||||
if alarmData.AlarmStatus == AlarmStatusClear {
|
||||
exist, err := session.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId).
|
||||
Exist()
|
||||
if err != nil || !exist {
|
||||
log.Infof("Not found active alarm: ne_id=%s, alarm_id=%s", alarmData.NeId, alarmData.AlarmId)
|
||||
continue
|
||||
}
|
||||
alarmData.ClearType = ClearTypeAutoClear
|
||||
alarmData.ClearTime.Valid = true
|
||||
tm, _ := time.Parse(time.RFC3339, alarmData.EventTime)
|
||||
log.Debugf("EventTime:%s tm:%d tm-datetime:%s", alarmData.EventTime, tm, tm.Local().Format(time.DateTime))
|
||||
alarmData.ClearTime.Time = tm
|
||||
if IsNeedToAckAlarm(valueJson, &alarmData) {
|
||||
SetAlarmAckInfo(valueJson, &alarmData)
|
||||
log.Debug("alarmData:", alarmData)
|
||||
affected, err := session.
|
||||
Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId).
|
||||
Cols("alarm_status", "clear_type", "clear_time", "ack_state", "ack_time", "ack_user").
|
||||
Update(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to update alarm data:", err)
|
||||
//services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
affected, err := session.
|
||||
Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId).
|
||||
Cols("alarm_status", "clear_type", "clear_time").
|
||||
Update(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to update alarm data:", err)
|
||||
//services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
eventTime := global.GetFmtTimeString(time.RFC3339, alarmData.EventTime, time.DateTime)
|
||||
alarmLog := new(AlarmLog)
|
||||
alarmLog.NeType = alarmData.NeType
|
||||
alarmLog.NeId = alarmData.NeId
|
||||
alarmLog.AlarmSeq = alarmData.AlarmSeq
|
||||
alarmLog.AlarmId = alarmData.AlarmId
|
||||
alarmLog.AlarmCode = alarmData.AlarmCode
|
||||
alarmLog.AlarmStatus = alarmData.AlarmStatus
|
||||
alarmLog.EventTime = eventTime
|
||||
log.Debug("alarmLog:", alarmLog)
|
||||
|
||||
affected, err := session.Insert(alarmLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm_log:", err)
|
||||
}
|
||||
|
||||
// todo: PerceivedSeverity set color
|
||||
var severity string
|
||||
has, err := xEngine.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime).
|
||||
//OrderBy("FIELD(orig_severity, 'Critical', 'Major', 'Minor', 'Warning', 'Event') ASC").
|
||||
Asc("orig_severity").
|
||||
Cols("orig_severity").
|
||||
Limit(1).
|
||||
Get(&severity)
|
||||
if err != nil {
|
||||
log.Error("Failed to get alarm:", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("neType=%s, neId=%s, eventTime=%s, severity=%s", alarmData.NeType, alarmData.NeId, alarmData.EventTime, severity)
|
||||
|
||||
if has && severity > alarmData.OrigSeverity {
|
||||
// update exist record
|
||||
_, err := session.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and event_time=?", alarmData.NeType, alarmData.NeId, alarmData.EventTime).
|
||||
Update(&Alarm{PerceivedSeverity: severity})
|
||||
if err != nil {
|
||||
log.Error("Failed to update alarm:", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
session.Commit()
|
||||
// for alarm forward time format
|
||||
alarmData.EventTime = eventTime
|
||||
} else {
|
||||
activeAlarmNum++
|
||||
has, err := xEngine.Table("alarm").
|
||||
Where("alarm_id=? and ne_type=? and ne_id=? and alarm_status=1",
|
||||
alarmData.AlarmId, alarmData.NeType, alarmData.NeId).
|
||||
Exist()
|
||||
if err == nil && has {
|
||||
log.Warn("Exist the same alarm")
|
||||
continue
|
||||
}
|
||||
|
||||
var currentSeq string
|
||||
has, err = xEngine.Table("alarm").
|
||||
Where("ne_type=? and ne_id=?", alarmData.NeType, alarmData.NeId).
|
||||
Desc("alarm_seq").
|
||||
//Desc("event_time").
|
||||
Cols("alarm_seq").
|
||||
Limit(1).
|
||||
Get(¤tSeq)
|
||||
if err != nil {
|
||||
log.Error("Failed to get alarm:", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("neType=%s, neId=%s, currentSeq=%s, activeAlarmNum=%d",
|
||||
alarmData.NeType, alarmData.NeId, currentSeq, activeAlarmNum)
|
||||
|
||||
if has {
|
||||
seq, _ := strconv.Atoi(currentSeq)
|
||||
alarmData.AlarmSeq = seq + 1
|
||||
if alarmData.AlarmSeq > global.MaxInt32Number {
|
||||
alarmData.AlarmSeq = AlarmSeqBeginNumber
|
||||
}
|
||||
} else {
|
||||
alarmData.AlarmSeq = AlarmSeqBeginNumber
|
||||
}
|
||||
|
||||
// todo: PerceivedSeverity set color
|
||||
var severity string
|
||||
has, err = xEngine.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime).
|
||||
//OrderBy("FIELD(orig_severity, 'Critical', 'Major', 'Minor', 'Warning', 'Event') ASC").
|
||||
Asc("orig_severity").
|
||||
Cols("orig_severity").
|
||||
Limit(1).
|
||||
Get(&severity)
|
||||
if err != nil {
|
||||
log.Error("Failed to get alarm:", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("neType=%s, neId=%s, eventTime=%s, severity=%s", alarmData.NeType, alarmData.NeId, alarmData.EventTime, severity)
|
||||
|
||||
if !has || severity == alarmData.OrigSeverity {
|
||||
alarmData.PerceivedSeverity = alarmData.OrigSeverity
|
||||
} else if severity > alarmData.OrigSeverity {
|
||||
alarmData.PerceivedSeverity = alarmData.OrigSeverity
|
||||
} else {
|
||||
alarmData.PerceivedSeverity = severity
|
||||
// update exist record
|
||||
_, err := session.Table("alarm").
|
||||
Where("ne_type=? and ne_id=? and event_time=?", alarmData.NeType, alarmData.NeId, alarmData.EventTime).
|
||||
Update(&Alarm{PerceivedSeverity: alarmData.PerceivedSeverity})
|
||||
if err != nil {
|
||||
log.Error("Failed to update alarm:", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
evenTime := global.GetFmtTimeString(time.RFC3339, alarmData.EventTime, time.DateTime)
|
||||
alarmData.ObjectUid = alarmData.NeId
|
||||
alarmData.ObjectType = "VNFM"
|
||||
alarmData.EventTime = evenTime
|
||||
if IsNeedToAckAlarm(valueJson, &alarmData) {
|
||||
SetAlarmAckInfo(valueJson, &alarmData)
|
||||
}
|
||||
log.Trace("alarmData:", alarmData)
|
||||
var affected int64
|
||||
if (alarmData.OrigSeverity == "Event" || alarmData.OrigSeverity == "5") && config.GetYamlConfig().Alarm.SplitEventAlarm {
|
||||
affected, err = session.Table("alarm_event").InsertOne(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm_event:", err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
affected, err = session.Table("alarm").Insert(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm:", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if err == nil && affected > 0 {
|
||||
alarmLog := new(AlarmLog)
|
||||
alarmLog.NeType = alarmData.NeType
|
||||
alarmLog.NeId = alarmData.NeId
|
||||
alarmLog.AlarmSeq = alarmData.AlarmSeq
|
||||
alarmLog.AlarmId = alarmData.AlarmId
|
||||
alarmLog.AlarmCode = alarmData.AlarmCode
|
||||
alarmLog.AlarmStatus = alarmData.AlarmStatus
|
||||
alarmLog.EventTime = evenTime
|
||||
log.Trace("alarmLog:", alarmLog)
|
||||
affected, err = session.Insert(alarmLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert data:", err)
|
||||
//services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
session.Commit()
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Warn("Failed to insert alarm data:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package fm
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/restagent/config"
|
||||
|
||||
"gopkg.in/gomail.v2"
|
||||
)
|
||||
|
||||
func AlarmEmailForward(alarmData *Alarm) error {
|
||||
log.Info("AlarmEmailForward processing... ")
|
||||
|
||||
message := fmt.Sprintf(`
|
||||
<p>Alarm information</p>
|
||||
<p style="text-indent:2.5em">Sequence: %d</p>
|
||||
<p style="text-indent:3em">NE name: %s</p>
|
||||
<p style="text-indent:4em">Title: %s</p>
|
||||
<p style="text-indent:2.5em">Severity: %s</p>
|
||||
<p style="text-indent:1.5em">Event Time: %s</p>
|
||||
<p style="text-indent:0.5em">Alarm Status: %d</p>
|
||||
<p>Automatic sent by OMC, please do not reply!</p>
|
||||
`, alarmData.AlarmSeq, alarmData.NeName, alarmData.AlarmTitle, alarmData.OrigSeverity, alarmData.EventTime, alarmData.AlarmStatus)
|
||||
|
||||
// message := fmt.Sprintf(`
|
||||
// Alarm information
|
||||
|
||||
// Sequence: %d
|
||||
// NE name: %s
|
||||
// Title: %s
|
||||
// Severity: %s
|
||||
// Event Time: %s
|
||||
|
||||
// Automatic send by OMC, don't reply!
|
||||
// `, alarmData.AlarmSeq, alarmData.NeName, alarmData.AlarmTitle, alarmData.OrigSeverity, alarmData.EventTime)
|
||||
|
||||
// QQ 邮箱:
|
||||
// SMTP 服务器地址:smtp.qq.com(SSL协议端口:465/994 | 非SSL协议端口:25)
|
||||
// 163 邮箱:
|
||||
// SMTP 服务器地址:smtp.163.com(端口:25)
|
||||
// host := "mail.agrandtech.com"
|
||||
// port := 25
|
||||
// userName := "smtpext@agrandtech.com"
|
||||
// password := "1000smtp@omc!"
|
||||
|
||||
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 := strings.Split(config.GetYamlConfig().Alarm.EmailForward.EmailList, ",")
|
||||
forwardLog := &dborm.AlarmForwardLog{
|
||||
NeType: alarmData.NeType,
|
||||
NeID: alarmData.NeId,
|
||||
AlarmID: alarmData.AlarmId,
|
||||
AlarmTitle: alarmData.AlarmTitle,
|
||||
AlarmSeq: alarmData.AlarmSeq,
|
||||
EventTime: alarmData.EventTime,
|
||||
ToUser: config.GetYamlConfig().Alarm.EmailForward.EmailList,
|
||||
}
|
||||
|
||||
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") // 抄送,可以多个
|
||||
//m.SetHeader("Bcc", "******@qq.com") // 暗送,可以多个
|
||||
m.SetHeader("Subject", "Alarm from OMC!") // 邮件主题
|
||||
|
||||
// text/html 的意思是将文件的 content-type 设置为 text/html 的形式,浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。
|
||||
// 可以通过 text/html 处理文本格式进行特殊处理,如换行、缩进、加粗等等
|
||||
//m.SetBody("text/html", fmt.Sprintf(message, *alarm))
|
||||
m.SetBody("text/html", message)
|
||||
|
||||
// text/plain的意思是将文件设置为纯文本的形式,浏览器在获取到这种文件时并不会对其进行处理
|
||||
//m.SetBody("text/plain", message)
|
||||
// m.Attach("test.sh") // 附件文件,可以是文件,照片,视频等等
|
||||
// m.Attach("lolcatVideo.mp4") // 视频
|
||||
// m.Attach("lolcat.jpg") // 照片
|
||||
|
||||
d := gomail.NewDialer(
|
||||
host,
|
||||
port,
|
||||
userName,
|
||||
password,
|
||||
)
|
||||
// 关闭SSL协议认证
|
||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
if !config.GetYamlConfig().Alarm.EmailForward.TLSSkipVerify {
|
||||
// 打开SSL协议认证
|
||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: false}
|
||||
}
|
||||
|
||||
if err := d.DialAndSend(m); err != nil {
|
||||
operResult := fmt.Sprintf("Failed to DialAndSend:%v", err)
|
||||
log.Error(operResult)
|
||||
forwardLog.OperResult = operResult
|
||||
affected, err := dborm.XormInsertAlarmForwardLog(forwardLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert data:", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
forwardLog.OperResult = "Email sent successfully!"
|
||||
affected, err := dborm.XormInsertAlarmForwardLog(forwardLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert data:", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
package fm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/restagent/config"
|
||||
"github.com/linxGnu/gosmpp"
|
||||
"github.com/linxGnu/gosmpp/data"
|
||||
"github.com/linxGnu/gosmpp/pdu"
|
||||
)
|
||||
|
||||
func AlarmSMSForward(alarmData *Alarm) error {
|
||||
switch config.GetYamlConfig().Alarm.SMProxy {
|
||||
case "sms":
|
||||
users, err := AlarmForwardBySMS(alarmData)
|
||||
writeLog(alarmData, users, "SMS", err)
|
||||
return err
|
||||
case "smsc":
|
||||
users, err := AlarmForwardBySMPP(alarmData)
|
||||
writeLog(alarmData, users, "SMS", err)
|
||||
return err
|
||||
default:
|
||||
users, err := AlarmForwardBySMPP(alarmData)
|
||||
writeLog(alarmData, users, "SMS", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func AlarmForwardBySMS(alarmData *Alarm) (string, error) {
|
||||
log.Info("AlarmForwardBySMS processing... ")
|
||||
|
||||
SMSFforwardconfig := config.GetYamlConfig().Alarm.SMS
|
||||
// 阿里云短信API的请求地址
|
||||
apiURL := SMSFforwardconfig.ApiURL
|
||||
|
||||
// 阿里云短信API的AccessKey ID和AccessKey Secret
|
||||
//accessKeyID := SMSFforwardconfig.AccessKeyID
|
||||
accessKeySecret := SMSFforwardconfig.AccessKeySecret
|
||||
|
||||
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, ",")
|
||||
|
||||
// 短信相关参数
|
||||
params := url.Values{}
|
||||
params.Set("PhoneNumbers", userList)
|
||||
params.Set("SignName", SMSFforwardconfig.SignName)
|
||||
params.Set("TemplateCode", SMSFforwardconfig.TemplateCode)
|
||||
params.Set("TemplateParam", `{"message":"alarm"}`)
|
||||
|
||||
// 构建请求URL
|
||||
reqURL := apiURL + "?Action=SendSms&" + params.Encode()
|
||||
|
||||
// 创建HTTP请求
|
||||
req, err := http.NewRequest("GET", reqURL, nil)
|
||||
if err != nil {
|
||||
log.Error("Failed to create request:", err)
|
||||
return userList, err
|
||||
}
|
||||
|
||||
// 添加请求头部
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Authorization", "APPCODE "+accessKeySecret)
|
||||
|
||||
// 发送请求
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Error("Failed to send request:%v", err)
|
||||
return userList, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 解析响应
|
||||
switch resp.StatusCode {
|
||||
case http.StatusOK, http.StatusAccepted, http.StatusNoContent, http.StatusCreated:
|
||||
return userList, nil
|
||||
default:
|
||||
log.Error(fmt.Errorf("failed to send SMS: %s(Code=%d)", resp.Status, resp.StatusCode))
|
||||
return userList, err
|
||||
}
|
||||
}
|
||||
|
||||
var smsForward = &(config.GetYamlConfig().Alarm.SMSCForward)
|
||||
|
||||
func AlarmForwardBySMPP(alarmData *Alarm) (string, error) {
|
||||
log.Info("AlarmForwardBySMPP processing... ")
|
||||
|
||||
if smsForward == nil {
|
||||
err := errors.New("smsForward configuration is nil")
|
||||
log.Error(err)
|
||||
return "", err
|
||||
}
|
||||
userList := smsForward.MobileList
|
||||
auth := gosmpp.Auth{
|
||||
SMSC: smsForward.SMSCAddr,
|
||||
SystemID: smsForward.SystemID,
|
||||
Password: smsForward.Password,
|
||||
SystemType: smsForward.SystemType,
|
||||
}
|
||||
|
||||
trans, err := gosmpp.NewSession(
|
||||
gosmpp.TXConnector(gosmpp.NonTLSDialer, auth),
|
||||
gosmpp.Settings{
|
||||
ReadTimeout: 2 * time.Second,
|
||||
|
||||
OnPDU: func(p pdu.PDU, _ bool) {
|
||||
log.Debug("%+v", p)
|
||||
},
|
||||
|
||||
OnSubmitError: func(_ pdu.PDU, err error) {
|
||||
log.Error(err)
|
||||
},
|
||||
|
||||
OnRebindingError: func(err error) {
|
||||
log.Error(err)
|
||||
},
|
||||
|
||||
OnClosed: func(state gosmpp.State) {
|
||||
log.Error(state)
|
||||
},
|
||||
}, -1)
|
||||
if err != nil {
|
||||
log.Error("Failed to create SMPP new session:", err)
|
||||
return userList, err
|
||||
}
|
||||
// defer func() {
|
||||
// if err := trans.Close(); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// }()
|
||||
|
||||
message := "Alarm Notification: " + alarmData.AlarmTitle +
|
||||
" from " + alarmData.NeType + "_" + alarmData.NeId +
|
||||
" at " + alarmData.EventTime
|
||||
users := strings.Split(userList, ",")
|
||||
for _, user := range users {
|
||||
sm, err := newSubmitSM(user, message)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to newSubmitSM %s short message: %v", user, err)
|
||||
writeLog(alarmData, user, "SMS", err)
|
||||
continue
|
||||
}
|
||||
if err = trans.Transceiver().Submit(sm); err != nil {
|
||||
log.Errorf("Failed to Submit %s short message: %v", user, err)
|
||||
writeLog(alarmData, user, "SMS", err)
|
||||
continue
|
||||
}
|
||||
writeLog(alarmData, user, "SMS", nil)
|
||||
}
|
||||
|
||||
return userList, nil
|
||||
}
|
||||
|
||||
func writeLog(alarmData *Alarm, toUser, forwardBy string, err error) error {
|
||||
var result string
|
||||
if err == nil {
|
||||
result = "SMS sent successfully"
|
||||
} else {
|
||||
result = err.Error()
|
||||
}
|
||||
forwardLog := &dborm.AlarmForwardLog{
|
||||
NeType: alarmData.NeType,
|
||||
NeID: alarmData.NeId,
|
||||
AlarmID: alarmData.AlarmId,
|
||||
AlarmTitle: alarmData.AlarmTitle,
|
||||
AlarmSeq: alarmData.AlarmSeq,
|
||||
EventTime: alarmData.EventTime,
|
||||
Interface: forwardBy,
|
||||
ToUser: toUser,
|
||||
OperResult: result,
|
||||
}
|
||||
|
||||
affected, err := dborm.XormInsertAlarmForwardLog(forwardLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert data:", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newSubmitSM(phoneNumber string, message string) (*pdu.SubmitSM, error) {
|
||||
// build up submitSM
|
||||
srcAddr := pdu.NewAddress()
|
||||
srcAddr.SetTon(5)
|
||||
srcAddr.SetNpi(0)
|
||||
err := srcAddr.SetAddress(smsForward.ServiceNumber)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
destAddr := pdu.NewAddress()
|
||||
destAddr.SetTon(1)
|
||||
destAddr.SetNpi(1)
|
||||
err = destAddr.SetAddress(phoneNumber)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
submitSM := pdu.NewSubmitSM().(*pdu.SubmitSM)
|
||||
submitSM.SourceAddr = srcAddr
|
||||
submitSM.DestAddr = destAddr
|
||||
dataCoding := data.FromDataCoding(smsForward.DataCoding)
|
||||
err = submitSM.Message.SetMessageWithEncoding(message, dataCoding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
submitSM.ProtocolID = 0
|
||||
submitSM.RegisteredDelivery = 1
|
||||
submitSM.ReplaceIfPresentFlag = 0
|
||||
submitSM.EsmClass = 0
|
||||
|
||||
return submitSM, nil
|
||||
}
|
||||
|
||||
// const (
|
||||
// // Short message data coding type
|
||||
// SMS_CODING_GSM7BIT byte = iota
|
||||
// SMS_CODING_ASCII
|
||||
// SMS_CODING_BINARY8BIT1
|
||||
// SMS_CODING_LATIN1
|
||||
// SMS_CODING_BINARY8BIT2
|
||||
// SMS_CODING_NODEF
|
||||
// SMS_CODING_CYRILLIC
|
||||
// SMS_CODING_HEBREW
|
||||
// SMS_CODING_UCS2
|
||||
// )
|
||||
|
||||
// var codingMap = map[byte]data.Encoding{
|
||||
// SMS_CODING_GSM7BIT: data.GSM7BIT,
|
||||
// SMS_CODING_ASCII: data.ASCII,
|
||||
// SMS_CODING_BINARY8BIT1: data.BINARY8BIT1,
|
||||
// SMS_CODING_LATIN1: data.LATIN1,
|
||||
// SMS_CODING_BINARY8BIT2: data.BINARY8BIT2,
|
||||
// SMS_CODING_CYRILLIC: data.CYRILLIC,
|
||||
// SMS_CODING_HEBREW: data.HEBREW,
|
||||
// SMS_CODING_UCS2: data.UCS2,
|
||||
// }
|
||||
@@ -0,0 +1,586 @@
|
||||
package handle
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
g "github.com/gosnmp/gosnmp"
|
||||
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/oauth"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/lib/session"
|
||||
"be.ems/restagent/config"
|
||||
)
|
||||
|
||||
var TodoList []stTodo
|
||||
|
||||
type stTodo struct {
|
||||
No string
|
||||
Item string
|
||||
Value string
|
||||
}
|
||||
|
||||
type ErrorOAuthResponse struct {
|
||||
Error map[string]interface{}
|
||||
}
|
||||
|
||||
type FailOAuthResponse struct {
|
||||
Error struct {
|
||||
ErrorCode string
|
||||
ErrorInfo string
|
||||
}
|
||||
}
|
||||
|
||||
type ApiResponse struct {
|
||||
ResultCode string
|
||||
ResultMessage interface{}
|
||||
}
|
||||
|
||||
var globalSession = session.NewSessManager("restagent")
|
||||
|
||||
func init() {
|
||||
conf := config.GetYamlConfig()
|
||||
// Default is a pointer to a GoSNMP struct that contains sensible defaults
|
||||
// eg port 161, community public, etc
|
||||
g.Default.Target = conf.NE.Addr
|
||||
g.Default.Port = conf.NE.Port
|
||||
err := g.Default.Connect()
|
||||
if err != nil {
|
||||
log.Fatalf("Connect() err: %v", err)
|
||||
}
|
||||
//defer g.Default.Conn.Close()
|
||||
}
|
||||
|
||||
/*
|
||||
func IsValidOAuthInfo(oAuthBody OAuthBody) bool {
|
||||
log.Debug("IsValidOAuthInfo processing... ")
|
||||
|
||||
conf := config.GetYamlConfig()
|
||||
for _, o := range conf.Auth {
|
||||
if oAuthBody.GrantType == o.Type && oAuthBody.UserName == o.User && oAuthBody.Value == o.Password {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func IsWrongOAuthInfo(oAuthBody OAuthBody) bool {
|
||||
log.Debug("IsWrongOAuthInfo processing... ")
|
||||
|
||||
if oAuthBody.GrantType == "" || strings.ToLower(oAuthBody.GrantType) != "password" || oAuthBody.UserName == "" || oAuthBody.Value == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
*/
|
||||
|
||||
func IsValidOAuthUri(r *http.Request) bool {
|
||||
vars := mux.Vars(r)
|
||||
Uri := vars["apiCategory"] + "/" + vars["apiVersion"] // 获取Uri
|
||||
if Uri != "securityManagement/v1" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func IsVallidContentType(r *http.Request) bool {
|
||||
log.Debug("IsVallidContentType processing ...")
|
||||
|
||||
ctype := r.Header["Content-Type"]
|
||||
if len(ctype) != 0 && !strings.Contains(ctype[0], "application/json") {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("LoginFromOMC processing... ")
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Debug(err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
/* if !IsVallidContentType(r) {
|
||||
log.Debug("Invalid Content-Type")
|
||||
services.ResponseUnsupportedMediaType415(w)
|
||||
return
|
||||
}
|
||||
|
||||
// check extend uri, response 404
|
||||
if !IsValidOAuthUri(r) {
|
||||
log.Debug("Uri is invalid")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
*/
|
||||
// Error process ....
|
||||
// response 400-7
|
||||
if !json.Valid([]byte(body)) {
|
||||
log.Debug("Invalid Json Format")
|
||||
services.ResponseBadRequest400InvalidJson(w)
|
||||
return
|
||||
}
|
||||
|
||||
var oAuthBody oauth.OAuthBody
|
||||
_ = json.Unmarshal(body, &oAuthBody) //转为json
|
||||
log.Debug("body:", string(body), "oAuthBody:", oAuthBody)
|
||||
|
||||
defer r.Body.Close()
|
||||
// response 400-5
|
||||
if oauth.IsWrongOAuthInfo(oAuthBody) {
|
||||
log.Debug("Wrong parameter value")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
/*
|
||||
if oauth.IsValidOAuthInfo(oAuthBody) {
|
||||
plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType)
|
||||
log.Debug("Permission list:", plist)
|
||||
|
||||
token := globalSession.NewSession(w, r, plist)
|
||||
services.ResponseStatusOK200Login(w, token)
|
||||
} else {
|
||||
// response 400-4
|
||||
log.Debug("Authentication failed, mismatch user or password")
|
||||
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
}
|
||||
*/
|
||||
validUser, changePassword, _ := dborm.XormCheckLoginUser(oAuthBody.UserName,
|
||||
oAuthBody.Value, config.GetYamlConfig().Auth.Crypt)
|
||||
if validUser {
|
||||
// plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType)
|
||||
plist := []bool{true, true, true, true}
|
||||
log.Debug("Permission list:", plist)
|
||||
|
||||
token := globalSession.NewSession(w, r, plist)
|
||||
services.ResponseStatusOK200Login(w, token, changePassword)
|
||||
} else {
|
||||
// response 400-4
|
||||
log.Error("Authentication failed, mismatch user or password")
|
||||
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func LogoutFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("LogoutFromOMC processing... ")
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
if !IsVallidContentType(r) {
|
||||
log.Debug("Invalid Content-Type")
|
||||
services.ResponseUnsupportedMediaType415(w)
|
||||
return
|
||||
}
|
||||
|
||||
// check extend uri, response 404
|
||||
if !IsValidOAuthUri(r) {
|
||||
log.Debug("Uri is invalid")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
token, ret := globalSession.IsCarriedToken(r)
|
||||
if ret == false {
|
||||
log.Debug("AccessToken is not carried")
|
||||
services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return
|
||||
}
|
||||
|
||||
// 401-2 response
|
||||
if globalSession.IsValidToken(token) == false {
|
||||
log.Debug("AccessToken fails or does not exist")
|
||||
services.ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return
|
||||
}
|
||||
|
||||
globalSession.EndSession(w, r)
|
||||
services.ResponseStatusOK200Null(w)
|
||||
return
|
||||
}
|
||||
|
||||
func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("HandshakeFromOMC processing... ")
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
if !IsVallidContentType(r) {
|
||||
log.Debug("Invalid Content-Type")
|
||||
services.ResponseUnsupportedMediaType415(w)
|
||||
return
|
||||
}
|
||||
|
||||
// check extend uri, response 404
|
||||
if !IsValidOAuthUri(r) {
|
||||
log.Debug("Uri is invalid")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
token, ret := globalSession.IsCarriedToken(r)
|
||||
if ret == false {
|
||||
log.Debug("AccessToken is not carried")
|
||||
services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return
|
||||
}
|
||||
|
||||
if !globalSession.ShakeSession(token) {
|
||||
// 401-2 response
|
||||
log.Debug("AccessToken fails or does not exist")
|
||||
services.ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return
|
||||
}
|
||||
|
||||
// 200 response
|
||||
services.ResponseStatusOK200Null(w)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
MAX_RMUID_NUM = config.GetRmUIDMaxNumFromConfig()
|
||||
MAX_ALARMID_NUM = config.GetAlarmIDMaxNumFromConfig()
|
||||
MAX_PMUID_NUM = config.GetPmIDMaxNumFromConfig()
|
||||
MAX_SUBID_NUM = config.GetSubIDMaxNumFromConfig()
|
||||
MAX_URI_LEN = config.GetUriMaxLenFromConfig()
|
||||
RMUID_REGEXP = config.GetRmUIDRegexpFromConfig()
|
||||
)
|
||||
|
||||
func CheckParameterName(r *http.Request) []string {
|
||||
var errorParams []string
|
||||
vars := r.URL.Query()
|
||||
for k, v := range vars {
|
||||
log.Debug("vars:", k, v)
|
||||
if k != "rmUIDs" && k != "fields" {
|
||||
errorParams = append(errorParams, k)
|
||||
}
|
||||
}
|
||||
|
||||
return errorParams
|
||||
}
|
||||
|
||||
func GetRmUIDArr(r *http.Request) []string {
|
||||
vars := r.URL.Query()
|
||||
rmUIDs, ok := vars["rmUIDs"]
|
||||
if !ok {
|
||||
log.Debug("rmUIDs is not exist")
|
||||
return nil
|
||||
}
|
||||
|
||||
var rmUIDValues []string
|
||||
for _, r := range rmUIDs {
|
||||
if r != "" {
|
||||
rmUIDValues = global.MergeStringArr(rmUIDValues, strings.Split(r, `,`))
|
||||
}
|
||||
}
|
||||
|
||||
return rmUIDValues
|
||||
}
|
||||
|
||||
func GetAttrNameArr(r *http.Request) []string {
|
||||
vars := r.URL.Query()
|
||||
fields, ok := vars["fields"]
|
||||
if !ok {
|
||||
log.Debug("attributeNames does not exist")
|
||||
return nil
|
||||
}
|
||||
var attrNames []string
|
||||
for _, a := range fields {
|
||||
if a != "" {
|
||||
attrNames = global.MergeStringArr(attrNames, strings.Split(a, `,`))
|
||||
}
|
||||
}
|
||||
|
||||
return attrNames
|
||||
}
|
||||
|
||||
func CheckValidRmUID(rmUIDs []string) []string {
|
||||
log.Debug("GetLocalRmUID processing... ")
|
||||
|
||||
var invalidRmUIDs []string
|
||||
for _, r := range rmUIDs {
|
||||
if !global.MatchRmUID(RMUID_REGEXP, r) {
|
||||
invalidRmUIDs = append(invalidRmUIDs, r)
|
||||
}
|
||||
}
|
||||
|
||||
return invalidRmUIDs
|
||||
}
|
||||
|
||||
func CheckLocalRmUID(rmUIDs []string) string {
|
||||
log.Debug("GetLocalRmUID processing... ")
|
||||
|
||||
rmUID := config.GetRmUIDFromConfig()
|
||||
for _, r := range rmUIDs {
|
||||
if r == rmUID {
|
||||
return rmUID
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetNRMByUri(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetNRMByUri processing... ")
|
||||
|
||||
// response 414-4 uri too long ? (optional)
|
||||
// todo ... ?
|
||||
if bytes.Count([]byte(r.RequestURI), nil) > MAX_URI_LEN {
|
||||
log.Debug("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil))
|
||||
services.ResponseRequestURITooLong414UriTooLong(w)
|
||||
return
|
||||
}
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
// response 415-1
|
||||
if !IsVallidContentType(r) {
|
||||
log.Debug("Invalid Content-Type")
|
||||
services.ResponseUnsupportedMediaType415(w)
|
||||
return
|
||||
}
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
token, ret := globalSession.IsCarriedToken(r)
|
||||
if ret == false {
|
||||
log.Debug("AccessToken is not carried")
|
||||
services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return
|
||||
}
|
||||
|
||||
// 401-2 response
|
||||
if globalSession.IsValidToken(token) == false {
|
||||
log.Debug("AccessToken fails or does not exist")
|
||||
services.ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return
|
||||
}
|
||||
// response 403 Forbidden, permissions deny
|
||||
// todo...
|
||||
plist := globalSession.GetPermissionFromSession(token)
|
||||
log.Debug("permission list:", plist)
|
||||
if len(plist) == 0 || plist[0] == false {
|
||||
log.Debug("User permission deny")
|
||||
services.ResponseForbidden403NotPermission(w)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
qeuryUri := vars["apiCategory"] + "/" + vars["elementTypeValue"] + "/" + vars["objectTypeValue"]
|
||||
log.Debug("Get by Uri: ", qeuryUri)
|
||||
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != "v1" {
|
||||
log.Debug("Uri is invalid")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// response 406-1
|
||||
rmUIDValues := GetRmUIDArr(r)
|
||||
if rmUIDValues == nil {
|
||||
log.Debug("missing parameter: rmUIDs")
|
||||
services.ResponseNotAcceptable406MissingParam(w)
|
||||
return
|
||||
}
|
||||
|
||||
// response 406-2
|
||||
errorParams := CheckParameterName(r)
|
||||
if errorParams != nil {
|
||||
log.Debug("parameter name error: ", errorParams)
|
||||
services.ResponseNotAcceptable406ParamError(w, errorParams)
|
||||
return
|
||||
}
|
||||
|
||||
// response 400-5
|
||||
if len(rmUIDValues) == 0 {
|
||||
log.Debug("rmUIDs is wrong or NULL")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
|
||||
// response 414-1
|
||||
if len(rmUIDValues) > MAX_RMUID_NUM {
|
||||
log.Debug("rmUID greater than", MAX_RMUID_NUM)
|
||||
services.ResponseRequestURITooLong414NRMNumExceed(w, MAX_RMUID_NUM)
|
||||
return
|
||||
}
|
||||
|
||||
// response 400-1
|
||||
// check rmUID is valid
|
||||
// todo ...
|
||||
invalidRmUIDs := CheckValidRmUID(rmUIDValues)
|
||||
if len(invalidRmUIDs) != 0 {
|
||||
log.Debug("rmUID is invalid")
|
||||
services.ResponseBadRequest400RmUIDsIsInvalid(w, invalidRmUIDs)
|
||||
return
|
||||
}
|
||||
|
||||
// response 404-2
|
||||
rmUID := CheckLocalRmUID(rmUIDValues)
|
||||
if rmUID == "" {
|
||||
log.Debug("rmUID does not exist")
|
||||
services.ResponseNotFound404NRMNotExist(w, rmUIDValues)
|
||||
return
|
||||
}
|
||||
|
||||
// response 404-1, uri is not exist in map
|
||||
attrNames := GetAttrNameArr(r)
|
||||
var Oids []string
|
||||
Oids = *config.GetOidByFileds(qeuryUri, attrNames, &Oids)
|
||||
if len(Oids) == 0 {
|
||||
log.Debug("Nothing of config map")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// response 404-1, uri is not exist in map
|
||||
var nameOids []config.NameOid
|
||||
nameOids = *config.GetDataOidByFields(qeuryUri, attrNames, &nameOids)
|
||||
if len(nameOids) == 0 {
|
||||
log.Debug("Nothing of config map")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
result, err2 := g.Default.Get(Oids) // Get() accepts up to g.MAX_OIDS
|
||||
if err2 != nil {
|
||||
log.Fatalf("Get() err: %v", err2)
|
||||
|
||||
}
|
||||
|
||||
// var nameValues []config.NameValue
|
||||
var nameValue config.NameValue
|
||||
|
||||
nameValues := make(map[string]interface{})
|
||||
nameValues["rmUID"] = rmUID
|
||||
for i, variable := range result.Variables {
|
||||
nameValue.Name = nameOids[i].Name
|
||||
log.Debugf("%d: oid: %s name: %s\n", i, variable.Name, nameValue.Name)
|
||||
// if nameOids[i].Oid == variable.Name && global.IsContain(attributeNames, nameValue.Name) {
|
||||
if nameOids[i].Oid == variable.Name {
|
||||
// the Value of each variable returned by Get() implements
|
||||
// interface{}. You could do a type switch...
|
||||
switch variable.Type {
|
||||
case g.OctetString:
|
||||
bytes := variable.Value.([]byte)
|
||||
log.Debugf("string: %s\n", string(bytes))
|
||||
nameValue.Value = string(bytes)
|
||||
nameValues[nameValue.Name] = nameValue.Value
|
||||
case g.Integer:
|
||||
value := variable.Value.(int)
|
||||
log.Debugf("integer: %d\n", value)
|
||||
nameValue.Value = strconv.Itoa(value)
|
||||
nameValues[nameValue.Name] = nameValue.Value
|
||||
case g.IPAddress:
|
||||
value := variable.Value.(string)
|
||||
log.Debugf("IPAddress: %s\n", variable.Value)
|
||||
nameValue.Value = value
|
||||
nameValues[nameValue.Name] = nameValue.Value
|
||||
default:
|
||||
// ... or often you're just interested in numeric values.
|
||||
// ToBigInt() will return the Value as a BigInt, for plugging
|
||||
// into your calculations.
|
||||
log.Debugf("number: %d\n", g.ToBigInt(variable.Value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getResponse := services.DataResponse{nameValues}
|
||||
services.ResponseWithJson(w, http.StatusOK, getResponse)
|
||||
}
|
||||
|
||||
func RestfulPut(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
queryNo := vars["no"]
|
||||
var targetTodo stTodo
|
||||
for _, Todo := range TodoList {
|
||||
if Todo.No == queryNo {
|
||||
targetTodo = Todo
|
||||
}
|
||||
}
|
||||
response := ApiResponse{"200", targetTodo}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func RestfulHead(w http.ResponseWriter, r *http.Request) {
|
||||
var targetTodo stTodo
|
||||
|
||||
response := ApiResponse{"200", targetTodo}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
|
||||
}
|
||||
|
||||
func RemoveElement(TodoList []stTodo, No string) stTodo {
|
||||
// var targetTodo stTodo
|
||||
j := 0
|
||||
if len(TodoList) == 0 {
|
||||
return TodoList[j]
|
||||
}
|
||||
|
||||
for i := 0; i < len(TodoList); i++ {
|
||||
if TodoList[i].No != No {
|
||||
if i != j {
|
||||
TodoList[i], TodoList[j] = TodoList[j], TodoList[i]
|
||||
}
|
||||
j++
|
||||
}
|
||||
}
|
||||
log.Debug(TodoList[j].No, TodoList[j].Item)
|
||||
return TodoList[j]
|
||||
}
|
||||
|
||||
func RestfulDelete(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
queryNo := vars["no"] //获取No
|
||||
|
||||
log.Debug("RestfulDelete processing... ")
|
||||
|
||||
targetTodo := RemoveElement(TodoList, queryNo)
|
||||
response := ApiResponse{"200", targetTodo}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func RestfulOptions(w http.ResponseWriter, r *http.Request) {
|
||||
var targetTodo stTodo
|
||||
|
||||
response := ApiResponse{"200", targetTodo}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
|
||||
}
|
||||
|
||||
func RestfulTrace(w http.ResponseWriter, r *http.Request) {
|
||||
var targetTodo stTodo
|
||||
|
||||
response := ApiResponse{"200", targetTodo}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
|
||||
}
|
||||
|
||||
func RestfulPatch(w http.ResponseWriter, r *http.Request) {
|
||||
var targetTodo stTodo
|
||||
|
||||
response := ApiResponse{"200", targetTodo}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package file_export
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"be.ems/lib/file"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type SysJobResponse struct {
|
||||
SysJob
|
||||
TableName string `json:"tableName"`
|
||||
TableDisplay string `json:"tableDisplay"`
|
||||
FilePath string `json:"filePath"`
|
||||
}
|
||||
|
||||
type TargetParams struct {
|
||||
Duration int `json:"duration"`
|
||||
TableName string `json:"tableName"`
|
||||
Columns string `json:"columns"` // exported column name of time string
|
||||
TimeCol string `json:"timeCol"` // time stamp of column name
|
||||
TimeUnit string `json:"timeUnit"` // timestamp unit: second/micro/milli
|
||||
Extras string `json:"extras"` // extras condition for where
|
||||
FilePath string `json:"filePath"` // file path
|
||||
}
|
||||
|
||||
func (m *SysJob) GetFileExportTable(c *gin.Context) {
|
||||
var results []SysJob
|
||||
|
||||
err := datasource.DefaultDB().Table(m.TableName()).Where("invoke_target=? and status=1", INVOKE_FILE_EXPORT).
|
||||
Find(&results).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var response []SysJobResponse
|
||||
for _, job := range results {
|
||||
var params TargetParams
|
||||
if err := json.Unmarshal([]byte(job.TargetParams), ¶ms); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
TableDisplay := i18n.TKey(language, "table."+params.TableName)
|
||||
if TableDisplay == "" {
|
||||
TableDisplay = params.TableName
|
||||
}
|
||||
response = append(response, SysJobResponse{
|
||||
SysJob: job,
|
||||
TableName: params.TableName,
|
||||
TableDisplay: TableDisplay,
|
||||
FilePath: params.FilePath,
|
||||
})
|
||||
}
|
||||
c.JSON(http.StatusOK, services.DataResp(response))
|
||||
}
|
||||
|
||||
func (m *FileExport) GetFileList(c *gin.Context) {
|
||||
var querys FileExportQuery
|
||||
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
files, err := file.GetFileInfo(querys.Path, querys.Suffix)
|
||||
if err != nil {
|
||||
log.Error("failed to GetFileInfo:", err)
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// split files list
|
||||
lenNum := int64(len(files))
|
||||
start := (querys.PageNum - 1) * querys.PageSize
|
||||
end := start + querys.PageSize
|
||||
var splitList []file.FileInfo
|
||||
if start >= lenNum {
|
||||
splitList = []file.FileInfo{}
|
||||
} else if end >= lenNum {
|
||||
splitList = files[start:]
|
||||
} else {
|
||||
splitList = files[start:end]
|
||||
}
|
||||
total := len(files)
|
||||
c.JSON(http.StatusOK, services.TotalDataResp(splitList, total))
|
||||
}
|
||||
|
||||
func (m *FileExport) Total(c *gin.Context) {
|
||||
dir := c.Query("path")
|
||||
|
||||
fileCount, dirCount, err := file.GetFileAndDirCount(dir)
|
||||
if err != nil {
|
||||
log.Error("failed to GetFileAndDirCount:", err)
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
total := fileCount + dirCount
|
||||
c.JSON(http.StatusOK, services.TotalResp(int64(total)))
|
||||
}
|
||||
|
||||
func (m *FileExport) DownloadHandler(c *gin.Context) {
|
||||
dir := c.Query("path")
|
||||
fileName := c.Param("fileName")
|
||||
filePath := filepath.Join(dir, fileName)
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Disposition", "attachment; filename="+fileName)
|
||||
c.Header("Content-Type", "application/octet-stream")
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
func (m *FileExport) Delete(c *gin.Context) {
|
||||
fileName := c.Param("fileName")
|
||||
dir := c.Query("path")
|
||||
filePath := filepath.Join(dir, fileName)
|
||||
|
||||
if err := os.Remove(filePath); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusNoContent, nil) // 204 No Content
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package file_export
|
||||
|
||||
import (
|
||||
"be.ems/lib/file"
|
||||
)
|
||||
|
||||
const (
|
||||
INVOKE_FILE_EXPORT = "exportTable"
|
||||
)
|
||||
|
||||
type SysJob struct {
|
||||
JobID int64 `gorm:"column:job_id;primary_key;auto_increment" json:"job_id"` //任务ID
|
||||
InvokeTarget string `gorm:"column:invoke_target" json:"invoke_target"` //调用目标字符串
|
||||
TargetParams string `gorm:"column:target_params;type:json" json:"target_params,omitempty"` //调用目标传入参数
|
||||
}
|
||||
|
||||
func (m *SysJob) TableName() string {
|
||||
return "sys_job"
|
||||
}
|
||||
|
||||
type FileExport struct {
|
||||
file.FileInfo
|
||||
}
|
||||
|
||||
type FileExportQuery struct {
|
||||
Path string `form:"path" binding:"required"`
|
||||
Suffix string `form:"suffix"`
|
||||
PageNum int64 `form:"pageNum" binding:"required"`
|
||||
PageSize int64 `form:"pageSize" binding:"required"`
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package file_export
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Register Routes for file_export
|
||||
func Register(r *gin.RouterGroup) {
|
||||
|
||||
lmTable := r.Group("/table")
|
||||
{
|
||||
var m *SysJob
|
||||
lmTable.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
m.GetFileExportTable,
|
||||
)
|
||||
|
||||
}
|
||||
lmFile := r.Group("/file")
|
||||
{
|
||||
var f *FileExport
|
||||
lmFile.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.GetFileList,
|
||||
)
|
||||
lmFile.GET("/total",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.Total,
|
||||
)
|
||||
lmFile.GET("/:fileName",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.DownloadHandler,
|
||||
)
|
||||
lmFile.DELETE("/:fileName",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.Delete,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package lm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type XormResponse struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type XormInsertResponse struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
var (
|
||||
ExtBackupDataUri = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/{dataStorage}/{dataObject}/backup" // for external
|
||||
|
||||
CustomExtBackupDataUri = config.UriPrefix + "/dataManagement/{apiVersion}/{dataStorage}/{dataObject}/backup" // for external
|
||||
)
|
||||
|
||||
var XEngine *xorm.Engine
|
||||
|
||||
type DatabaseClient struct {
|
||||
dbType string
|
||||
dbUrl string
|
||||
dbConnMaxLifetime time.Duration
|
||||
dbMaxIdleConns int
|
||||
dbMaxOpenConns int
|
||||
IsShowSQL bool
|
||||
|
||||
XEngine *xorm.Engine
|
||||
}
|
||||
|
||||
var DbClient DatabaseClient
|
||||
|
||||
// func init() {
|
||||
// conf := config.GetYamlConfig()
|
||||
// InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
||||
// conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||
// }
|
||||
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
|
||||
DbClient.dbType = dbType
|
||||
DbClient.dbConnMaxLifetime = 0
|
||||
DbClient.dbMaxIdleConns = 0
|
||||
DbClient.dbMaxOpenConns = 0
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
DbClient.IsShowSQL = true
|
||||
}
|
||||
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
|
||||
|
||||
var err error
|
||||
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
|
||||
if err != nil {
|
||||
log.Error("Failed to connet database:", err)
|
||||
return err
|
||||
}
|
||||
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
|
||||
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
|
||||
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
|
||||
DbClient.XEngine.DatabaseTZ = time.Local // 必须
|
||||
DbClient.XEngine.TZLocation = time.Local // 必须
|
||||
if DbClient.IsShowSQL {
|
||||
DbClient.XEngine.ShowSQL(true)
|
||||
}
|
||||
XEngine = DbClient.XEngine
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExtDatabaseBackupData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseBackupData processing... ")
|
||||
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
module := vars["managementModule"]
|
||||
dbname := vars["dataStorage"]
|
||||
tbname := vars["dataObject"]
|
||||
pack := "lm"
|
||||
log.Debugf("method:%s, module:%s dbname:%s, tbname:%s pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to get permission:", err)
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
// if !exist {
|
||||
// log.Error("permission deny!")
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
var sql string
|
||||
var filePath string
|
||||
switch tbname {
|
||||
case "operation_log":
|
||||
filePath = fmt.Sprintf("/tmp/%s-%s.csv", tbname, time.Now().Local().Format(global.DateData))
|
||||
sql = fmt.Sprintf("select * into outfile '%s' fields terminated by ',' escaped by '' optionally enclosed by '' lines terminated by '\n' from (select 'op_id','account_name','op_ip','subsys_tag','op_type','op_content','op_result','begin_time','end_time','vnf_flag','log_time' union select op_id,account_name,op_ip,subsys_tag,op_type,op_content,op_result,begin_time,end_time,vnf_flag,log_time from operation_log) b", filePath)
|
||||
case "security_log":
|
||||
filePath = fmt.Sprintf("/tmp/%s-%s.csv", tbname, time.Now().Local().Format(global.DateData))
|
||||
sql = fmt.Sprintf("select * into outfile '%s' fields terminated by ',' escaped by '' optionally enclosed by '' lines terminated by '\n' from (select 'id','account_name','account_type','op_ip','op_type','op_content','op_result','op_time' union select id,account_name,account_type,op_ip,op_type,op_content,op_result,op_time from security_log) b", filePath)
|
||||
case "alarm_log":
|
||||
filePath = fmt.Sprintf("/tmp/%s-%s.csv", tbname, time.Now().Local().Format(global.DateData))
|
||||
sql = fmt.Sprintf("select * into outfile '%s' fields terminated by ',' escaped by '' optionally enclosed by '' lines terminated by '\n' from (select 'id','ne_type','ne_id','alarm_seq','alarm_id','alarm_code','alarm_status','event_time','log_time' union select id,ne_type,ne_id,alarm_seq,alarm_id,alarm_code,alarm_status,event_time,log_time from alarm_log) b", filePath)
|
||||
default:
|
||||
log.Error("error target table")
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := DbClient.XEngine.Exec(sql)
|
||||
if err != nil {
|
||||
log.Error("Failed to exec SQL:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
affected, _ := res.RowsAffected()
|
||||
|
||||
log.Debugf("filePath:%s backup dir:%s", filePath, config.GetYamlConfig().Database.Backup)
|
||||
cmd := exec.Command("cp", "-rf", filePath, config.GetYamlConfig().Database.Backup)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("Faile to exec:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
mapRow := make(map[string]interface{})
|
||||
row := map[string]interface{}{"affectedRows": affected}
|
||||
mapRow[tbname] = row
|
||||
services.ResponseWithJson(w, http.StatusOK, mapRow)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// log management package
|
||||
|
||||
package lm
|
||||
|
||||
import (
|
||||
"be.ems/features/lm/file_export"
|
||||
"be.ems/lib/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitSubServiceRoute(r *gin.Engine) {
|
||||
log.Info("======init Log management group gin.Engine")
|
||||
|
||||
lmGroup := r.Group("/lm")
|
||||
// register sub modules routes
|
||||
file_export.Register(lmGroup)
|
||||
}
|
||||
@@ -0,0 +1,695 @@
|
||||
package mml
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/mmlp"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
tokenConst "be.ems/src/framework/constants/token"
|
||||
neModel "be.ems/src/modules/network_element/model"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
)
|
||||
|
||||
// const (
|
||||
// //经过测试,linux下,延时需要大于100ms
|
||||
// TIME_DELAY_AFTER_WRITE = 200
|
||||
// TIME_DEAD_LINE = 10
|
||||
// )
|
||||
|
||||
type Response struct {
|
||||
Data []string `json:"data"`
|
||||
}
|
||||
|
||||
type MMLRequest struct {
|
||||
MML []string `json:"mml"`
|
||||
}
|
||||
|
||||
var (
|
||||
// MML interface
|
||||
UriMML = config.DefaultUriPrefix + "/operationManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml"
|
||||
UriMML2 = config.DefaultUriPrefix + "/operationManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml2"
|
||||
UriMMLDiscard = config.DefaultUriPrefix + "/opeartionManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml"
|
||||
UriNeOmMml = config.DefaultUriPrefix + "/omManagement/{apiVersion}/mml/{netype}/{neid}"
|
||||
UriOmMmlExt = config.DefaultUriPrefix + "/{managedType}/{apiVersion}/elementType/OMC/objectType/mml"
|
||||
UriOmMmlInt = config.DefaultUriPrefix + "/omManagement/{apiVersion}/mml/{neType}/{neId}"
|
||||
|
||||
CustomUriMML = config.UriPrefix + "/operationManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml"
|
||||
CustomUriMML2 = config.UriPrefix + "/operationManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/mml2"
|
||||
CustomUriNeOmMml = config.UriPrefix + "/omManagement/{apiVersion}/mml/{netype}/{neid}"
|
||||
CustomUriOmMmlExt = config.UriPrefix + "/opeartionManagement/{apiVersion}/elementType/OMC/objectType/mml"
|
||||
CustomUriOmMmlInt = config.UriPrefix + "/omManagement/{apiVersion}/mml/{neType}/{neId}"
|
||||
)
|
||||
|
||||
var (
|
||||
TIME_DELAY_AFTER_WRITE time.Duration = 200
|
||||
TIME_DEAD_LINE time.Duration = 10
|
||||
WIN_ROW_SIZE int16 = 200
|
||||
WIN_COL_SIZE int16 = 120
|
||||
BUFFER_SIZE int = 65535
|
||||
)
|
||||
|
||||
func InitMML() {
|
||||
if config.GetYamlConfig().MML.Sleep != 0 {
|
||||
TIME_DELAY_AFTER_WRITE = time.Duration(config.GetYamlConfig().MML.Sleep)
|
||||
}
|
||||
if config.GetYamlConfig().MML.DeadLine != 0 {
|
||||
TIME_DEAD_LINE = time.Duration(config.GetYamlConfig().MML.DeadLine)
|
||||
}
|
||||
WIN_ROW_SIZE = config.GetYamlConfig().MML.SizeRow
|
||||
WIN_COL_SIZE = config.GetYamlConfig().MML.SizeCol
|
||||
BUFFER_SIZE = config.GetYamlConfig().MML.BufferSize
|
||||
}
|
||||
|
||||
func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostMML2ToNF processing... ")
|
||||
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
if neId == "" {
|
||||
log.Error("NOT FOUND ne_id")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
log.Debug("neType:", neType, "neId", neId)
|
||||
|
||||
neInfoArr := neService.NewNeInfo.SelectList(neModel.NeInfo{NeType: neType, NeId: neId}, false, true)
|
||||
if len(neInfoArr) < 1 {
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
neInfo := neInfoArr[0]
|
||||
if neInfo.NeId != neId || neInfo.IP == "" || len(neInfo.Hosts) < 2 {
|
||||
services.ResponseWithJson(w, 200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "neInfo not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
telnetHost := neInfo.Hosts[1]
|
||||
|
||||
buf := make([]byte, BUFFER_SIZE)
|
||||
var n int
|
||||
var mmlResult []string
|
||||
hostMML := fmt.Sprintf("%s:%d", telnetHost.Addr, telnetHost.Port)
|
||||
conn, err := net.Dial("tcp", hostMML)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err)
|
||||
log.Error(errMsg)
|
||||
mmlResult = append(mmlResult, errMsg)
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// localAddr := conn.LocalAddr()
|
||||
// remoteAddr := conn.RemoteAddr()
|
||||
// if localAddr == nil || remoteAddr == nil {
|
||||
// errMsg := fmt.Sprintf("connect invalid: localAddr=%v, remoteAddr=%v", localAddr, remoteAddr)
|
||||
// log.Error(errMsg)
|
||||
// mmlResult = append(mmlResult, errMsg)
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
|
||||
// 发送窗口大小设置命令
|
||||
conn.Write([]byte{255, 251, 31}) // 发送WILL WINDOW SIZE
|
||||
conn.Write([]byte{
|
||||
255, 250, 31,
|
||||
byte(WIN_COL_SIZE >> 8), byte(WIN_COL_SIZE & 0xFF),
|
||||
byte(WIN_ROW_SIZE >> 8), byte(WIN_ROW_SIZE & 0xFF),
|
||||
255, 240,
|
||||
}) // 发送设置 WINDOW SIZE
|
||||
|
||||
conn.SetDeadline(time.Now().Add(TIME_DEAD_LINE * time.Second))
|
||||
loginStr := fmt.Sprintf("%s\n%s\n", telnetHost.User, telnetHost.Password)
|
||||
_, err = conn.Write([]byte(loginStr))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
log.Trace(string(buf[0:n]))
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("Failed to ReadAll:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Trace("Body:", string(body))
|
||||
|
||||
mmlRequest := new(MMLRequest)
|
||||
_ = json.Unmarshal(body, mmlRequest)
|
||||
|
||||
for _, mml := range mmlRequest.MML {
|
||||
mmlCommand := fmt.Sprintf("%s\n", mml)
|
||||
_, err = conn.Write([]byte(mmlCommand))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
continue
|
||||
}
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
continue
|
||||
}
|
||||
log.Trace(string(buf[0 : n-len(neType)-2]))
|
||||
re1 := regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`) // 匹配包含␛的控制字符
|
||||
//re2 := regexp.MustCompile(`\x00`) // 匹配空字符
|
||||
re2 := regexp.MustCompile(`[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x1B]`) // 匹配空字符和包含␛的控制字符
|
||||
//re := regexp.MustCompile(`[\x00-\x1F\x7F]`)
|
||||
result := re1.ReplaceAllString(string(buf[0:n]), "")
|
||||
result = re2.ReplaceAllString(result, "")
|
||||
mmlResult = append(mmlResult, result)
|
||||
}
|
||||
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostMMLToNF processing... ")
|
||||
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// 经过测试,linux下,延时需要大于100ms
|
||||
// var TIME_DELAY_AFTER_WRITE time.Duration = 200
|
||||
// var TIME_DEAD_LINE time.Duration = 10
|
||||
// if config.GetYamlConfig().MML.Sleep != 0 {
|
||||
// TIME_DELAY_AFTER_WRITE = time.Duration(config.GetYamlConfig().MML.Sleep)
|
||||
// }
|
||||
// if config.GetYamlConfig().MML.DeadLine != 0 {
|
||||
// TIME_DEAD_LINE = time.Duration(config.GetYamlConfig().MML.DeadLine)
|
||||
// }
|
||||
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
if neId == "" {
|
||||
log.Error("NOT FOUND ne_id")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
log.Debug("neType:", neType, "neId", neId)
|
||||
|
||||
if strings.ToLower(neType) == "omc" {
|
||||
PostMMLToOMC(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
neInfoArr := neService.NewNeInfo.SelectList(neModel.NeInfo{NeType: neType, NeId: neId}, false, true)
|
||||
if len(neInfoArr) < 1 {
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
neInfo := neInfoArr[0]
|
||||
if neInfo.NeId != neId || neInfo.IP == "" || len(neInfo.Hosts) < 2 {
|
||||
services.ResponseWithJson(w, 200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "neInfo not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
telnetHost := neInfo.Hosts[1]
|
||||
|
||||
var buf [20 * 1024]byte
|
||||
//buf := make([]byte, 0)
|
||||
var n int
|
||||
var mmlResult []string
|
||||
switch strings.ToLower(neType) {
|
||||
case "xxx":
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Trace("Body:", string(body))
|
||||
|
||||
mmlRequest := new(MMLRequest)
|
||||
_ = json.Unmarshal(body, mmlRequest)
|
||||
|
||||
// n, err = conn.Read(buf[0:])
|
||||
// if err != nil {
|
||||
// log.Error("Failed to read:", err)
|
||||
// mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
// log.Debug(string(buf[0:n]))
|
||||
|
||||
// hostMML := fmt.Sprintf("%s:%d", neInfo.Ip, config.GetYamlConfig().MML.Port)
|
||||
// conn, err := net.Dial("tcp", hostMML)
|
||||
// if err != nil {
|
||||
// errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err)
|
||||
// log.Error(errMsg)
|
||||
// mmlResult = append(mmlResult, errMsg)
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
// defer conn.Close()
|
||||
|
||||
// conn.SetDeadline(time.Now().Add(10 * time.Second))
|
||||
// loginStr := fmt.Sprintf("%s\n%s\n", config.GetYamlConfig().MML.User, config.GetYamlConfig().MML.Password)
|
||||
// _, err = conn.Write([]byte(loginStr))
|
||||
// if err != nil {
|
||||
// log.Error("Failed to write:", err)
|
||||
// mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
// time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
// n, err = conn.Write([]byte(config.GetYamlConfig().MML.User + "\n"))
|
||||
// if err != nil {
|
||||
// log.Error("Failed to write:", err)
|
||||
// mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
// log.Debug(string(buf[0:n]))
|
||||
// time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
// n, err = conn.Read(buf[0:])
|
||||
// if err != nil {
|
||||
// log.Error("Failed to read:", err)
|
||||
// mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
// log.Debug(string(buf[0:n]))
|
||||
|
||||
// n, err = conn.Write([]byte(config.GetYamlConfig().MML.Password + "\n"))
|
||||
// if err != nil {
|
||||
// log.Error("Failed to write:", err)
|
||||
// mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
// log.Debug(string(buf[0:n]))
|
||||
|
||||
// time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
// n, err = conn.Read(buf[0:])
|
||||
// if err != nil {
|
||||
// log.Error("Failed to read:", err)
|
||||
// mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
// log.Debug(string(buf[0:n]))
|
||||
|
||||
for _, mml := range mmlRequest.MML {
|
||||
hostMML := fmt.Sprintf("%s:%d", telnetHost.Addr, telnetHost.Port)
|
||||
conn, err := net.Dial("tcp", hostMML)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err)
|
||||
log.Error(errMsg)
|
||||
mmlResult = append(mmlResult, errMsg)
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
conn.SetDeadline(time.Now().Add(TIME_DEAD_LINE * time.Second))
|
||||
|
||||
loginStr := fmt.Sprintf("%s\n%s\n", telnetHost.User, telnetHost.Password)
|
||||
_, err = conn.Write([]byte(loginStr))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
//response := Response{mmlResult}
|
||||
//services.ResponseWithJson(w, http.StatusOK, response)
|
||||
//return
|
||||
continue
|
||||
}
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
mmlCommand := fmt.Sprintf("%s\n", mml)
|
||||
log.Debug("mml command:", mmlCommand)
|
||||
_, err = conn.Write([]byte(mmlCommand))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
//response := Response{mmlResult}
|
||||
//services.ResponseWithJson(w, http.StatusOK, response)
|
||||
//return
|
||||
continue
|
||||
}
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
//response := Response{mmlResult}
|
||||
//services.ResponseWithJson(w, http.StatusOK, response)
|
||||
//return
|
||||
continue
|
||||
}
|
||||
log.Trace(string(buf[0 : n-len(neType)-2]))
|
||||
|
||||
re1 := regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`) // 匹配包含␛的控制字符
|
||||
//re2 := regexp.MustCompile(`\x00`) // 匹配空字符
|
||||
re2 := regexp.MustCompile(`[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x1B]`) // 匹配空字符和包含␛的控制字符
|
||||
//re := regexp.MustCompile(`[\x00-\x1F\x7F]`)
|
||||
// upf telnet buffer只能读取一次,需要去掉前面的多余字符
|
||||
//result := re1.ReplaceAllString(string(buf[config.GetYamlConfig().MML.UpfHeaderLength:n-len(neType)-2]), "")
|
||||
result := re1.ReplaceAllString(string(buf[0:n-len(neType)-2]), "")
|
||||
result = re2.ReplaceAllString(result, "")
|
||||
mmlResult = append(mmlResult, result)
|
||||
conn.Close()
|
||||
//mmlResult = append(mmlResult, string(buf[0:n-len(neType)-2]))
|
||||
|
||||
// can't read buffer from upf telnet server, so return ok always
|
||||
// mmlResult = append(mmlResult, "COMMAND OK\n")
|
||||
}
|
||||
case "ims":
|
||||
hostMML := fmt.Sprintf("%s:%d", telnetHost.Addr, telnetHost.Port)
|
||||
conn, err := net.Dial("tcp", hostMML)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err)
|
||||
log.Error(errMsg)
|
||||
mmlResult = append(mmlResult, errMsg)
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// localAddr := conn.LocalAddr()
|
||||
// remoteAddr := conn.RemoteAddr()
|
||||
// if localAddr == nil || remoteAddr == nil {
|
||||
// errMsg := fmt.Sprintf("connect invalid: localAddr=%v, remoteAddr=%v", localAddr, remoteAddr)
|
||||
// log.Error(errMsg)
|
||||
// mmlResult = append(mmlResult, errMsg)
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
conn.SetDeadline(time.Now().Add(TIME_DEAD_LINE * time.Second))
|
||||
|
||||
_, err = conn.Write([]byte(telnetHost.User + "\r\n"))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
log.Trace(string(buf[0:n]))
|
||||
|
||||
_, err = conn.Write([]byte(telnetHost.Password + "\r\n"))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
// loginStr := fmt.Sprintf("%s\r\n%s\r\n", config.GetYamlConfig().MML.User, config.GetYamlConfig().MML.Password)
|
||||
// _, err = conn.Write([]byte(loginStr))
|
||||
// if err != nil {
|
||||
// log.Error("Failed to write:", err)
|
||||
// mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
// time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
log.Trace(string(buf[0 : n-len(neType)-2]))
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Trace("Body:", string(body))
|
||||
|
||||
mmlRequest := new(MMLRequest)
|
||||
_ = json.Unmarshal(body, mmlRequest)
|
||||
|
||||
for _, mml := range mmlRequest.MML {
|
||||
mmlCommand := fmt.Sprintf("%s\r\n", mml)
|
||||
log.Debug("mml command:", mmlCommand)
|
||||
_, err = conn.Write([]byte(mmlCommand))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
continue
|
||||
}
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
continue
|
||||
}
|
||||
log.Trace(string(buf[0 : n-len(neType)-2]))
|
||||
|
||||
re1 := regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`) // 匹配包含␛的控制字符
|
||||
//re2 := regexp.MustCompile(`\x00`) // 匹配空字符
|
||||
re2 := regexp.MustCompile(`[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x1B]`) // 匹配空字符和包含␛的控制字符
|
||||
//re := regexp.MustCompile(`[\x00-\x1F\x7F]`)
|
||||
result := re1.ReplaceAllString(string(buf[0:n-len(neType)-2]), "")
|
||||
result = re2.ReplaceAllString(result, "")
|
||||
mmlResult = append(mmlResult, result)
|
||||
}
|
||||
default:
|
||||
hostMML := fmt.Sprintf("%s:%d", telnetHost.Addr, telnetHost.Port)
|
||||
conn, err := net.Dial("tcp", hostMML)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err)
|
||||
log.Error(errMsg)
|
||||
mmlResult = append(mmlResult, errMsg)
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// localAddr := conn.LocalAddr()
|
||||
// remoteAddr := conn.RemoteAddr()
|
||||
// if localAddr == nil || remoteAddr == nil {
|
||||
// errMsg := fmt.Sprintf("connect invalid: localAddr=%v, remoteAddr=%v", localAddr, remoteAddr)
|
||||
// log.Error(errMsg)
|
||||
// mmlResult = append(mmlResult, errMsg)
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
|
||||
conn.SetDeadline(time.Now().Add(TIME_DEAD_LINE * time.Second))
|
||||
loginStr := fmt.Sprintf("%s\n%s\n", telnetHost.User, telnetHost.Password)
|
||||
_, err = conn.Write([]byte(loginStr))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
log.Trace(string(buf[0:n]))
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("Failed to ReadAll:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Trace("Body:", string(body))
|
||||
|
||||
mmlRequest := new(MMLRequest)
|
||||
_ = json.Unmarshal(body, mmlRequest)
|
||||
|
||||
for _, mml := range mmlRequest.MML {
|
||||
mmlCommand := fmt.Sprintf("%s\n", mml)
|
||||
_, err = conn.Write([]byte(mmlCommand))
|
||||
if err != nil {
|
||||
log.Error("Failed to write:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
continue
|
||||
}
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read:", err)
|
||||
mmlResult = append(mmlResult, err.Error())
|
||||
// response := Response{mmlResult}
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
continue
|
||||
}
|
||||
log.Trace(string(buf[0 : n-len(neType)-2]))
|
||||
re1 := regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`) // 匹配包含␛的控制字符
|
||||
//re2 := regexp.MustCompile(`\x00`) // 匹配空字符
|
||||
re2 := regexp.MustCompile(`[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x1B]`) // 匹配空字符和包含␛的控制字符
|
||||
//re := regexp.MustCompile(`[\x00-\x1F\x7F]`)
|
||||
result := re1.ReplaceAllString(string(buf[0:n-len(neType)-2]), "")
|
||||
result = re2.ReplaceAllString(result, "")
|
||||
mmlResult = append(mmlResult, result)
|
||||
}
|
||||
}
|
||||
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func PostMMLToOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostMMLToOMC processing... ")
|
||||
|
||||
neType := "OMC" //ctx.GetParam(r, "elementTypeValue")
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
if neId == "" {
|
||||
log.Error("NOT FOUND ne_id")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
log.Debug("neType:", neType, "neId", neId)
|
||||
|
||||
neInfoArr := neService.NewNeInfo.SelectList(neModel.NeInfo{NeType: neType, NeId: neId}, false, false)
|
||||
if len(neInfoArr) < 1 {
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
neInfo := neInfoArr[0]
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
services.ResponseWithJson(w, 200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "neInfo not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Trace("Body:", string(body))
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%d", neInfo.IP, neInfo.Port)
|
||||
omcMmlVar := &mmlp.MmlVar{
|
||||
Version: global.Version,
|
||||
Output: mmlp.DefaultFormatType,
|
||||
MmlHome: config.GetYamlConfig().MML.MmlHome,
|
||||
Limit: 50,
|
||||
User: "",
|
||||
SessionToken: "", // 旧token
|
||||
Authorization: r.Header.Get(tokenConst.HEADER_KEY), // 请求Token
|
||||
HttpUri: hostUri,
|
||||
UserAgent: config.GetDefaultUserAgent(),
|
||||
}
|
||||
mmlRequest := new(MMLRequest)
|
||||
_ = json.Unmarshal(body, mmlRequest)
|
||||
|
||||
var mmlResult []string
|
||||
mmlLine := strings.Join(mmlRequest.MML, ";")
|
||||
|
||||
var mmlCmds []mmlp.MmlCommand
|
||||
if err = mmlp.ParseMMLCommand(mmlLine, &mmlCmds); err != nil {
|
||||
response := fmt.Sprintf("parse command error: %v\n", err)
|
||||
mmlResult = append(mmlResult, response)
|
||||
}
|
||||
|
||||
for _, mmlCmd := range mmlCmds {
|
||||
output, err := mmlp.TransMml2HttpReq(omcMmlVar, &mmlCmd)
|
||||
if err != nil {
|
||||
response := fmt.Sprintf("translate MML command error: %v]\n", err)
|
||||
mmlResult = append(mmlResult, response)
|
||||
}
|
||||
mmlResult = append(mmlResult, string(*output))
|
||||
}
|
||||
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
package nbi_file
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/file"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type SysJobResponse struct {
|
||||
SysJob
|
||||
TableName string `json:"tableName"`
|
||||
TableDisplay string `json:"tableDisplay"`
|
||||
FilePath string `json:"filePath"`
|
||||
}
|
||||
|
||||
type TargetParams struct {
|
||||
Duration int `json:"duration"`
|
||||
TableName string `json:"tableName"`
|
||||
Columns string `json:"columns"` // exported column name of time string
|
||||
TimeCol string `json:"timeCol"` // time stamp of column name
|
||||
TimeUnit string `json:"timeUnit"` // timestamp unit: second/micro/milli
|
||||
Extras string `json:"extras"` // extras condition for where
|
||||
FilePath string `json:"filePath"` // file path
|
||||
}
|
||||
|
||||
func (m *FileNBI) GetFileList(c *gin.Context) {
|
||||
var querys FileNBIQuery
|
||||
|
||||
querys.Category = c.Param("category")
|
||||
querys.Type = c.Param("type")
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if querys.Path == "" {
|
||||
tableName := ""
|
||||
ok := false
|
||||
switch querys.Category {
|
||||
case "cdr":
|
||||
tableName, ok = CDRTableMapper[querys.Type]
|
||||
if tableName == "" || !ok {
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type)))
|
||||
return
|
||||
}
|
||||
case "log":
|
||||
tableName, ok = LogTableMapper[querys.Type]
|
||||
if tableName == "" || !ok {
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type)))
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category)))
|
||||
return
|
||||
}
|
||||
|
||||
s := SysJob{}
|
||||
where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName)
|
||||
_, err := dborm.XEngDB().Table(s.TableName()).
|
||||
Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path").
|
||||
Where(where).
|
||||
Get(&querys.Path)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
files, err := file.GetFileInfo(querys.Path, querys.Suffix)
|
||||
if err != nil {
|
||||
log.Error("failed to GetFileInfo:", err)
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// split files list
|
||||
lenNum := int64(len(files))
|
||||
start := (querys.PageNum - 1) * querys.PageSize
|
||||
end := start + querys.PageSize
|
||||
var splitList []file.FileInfo
|
||||
if start >= lenNum {
|
||||
splitList = []file.FileInfo{}
|
||||
} else if end >= lenNum {
|
||||
splitList = files[start:]
|
||||
} else {
|
||||
splitList = files[start:end]
|
||||
}
|
||||
total := len(files)
|
||||
c.JSON(http.StatusOK, services.TotalDataResp(splitList, total))
|
||||
}
|
||||
|
||||
func (m *FileNBI) Total(c *gin.Context) {
|
||||
dir := c.Query("path")
|
||||
|
||||
fileCount, dirCount, err := file.GetFileAndDirCount(dir)
|
||||
if err != nil {
|
||||
log.Error("failed to GetFileAndDirCount:", err)
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
total := fileCount + dirCount
|
||||
c.JSON(http.StatusOK, services.TotalResp(int64(total)))
|
||||
}
|
||||
|
||||
func (m *FileNBI) GetSingleFileHandler(c *gin.Context) {
|
||||
var querys FileNBIQuery
|
||||
|
||||
querys.Category = c.Param("category")
|
||||
querys.Type = c.Param("type")
|
||||
querys.DateIndex = c.Param("dateIndex")
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
tableName := ""
|
||||
if querys.Path == "" {
|
||||
ok := false
|
||||
switch querys.Category {
|
||||
case "cdr":
|
||||
tableName, ok = CDRTableMapper[querys.Type]
|
||||
if tableName == "" || !ok {
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type)))
|
||||
return
|
||||
}
|
||||
case "log":
|
||||
tableName, ok = LogTableMapper[querys.Type]
|
||||
if tableName == "" || !ok {
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type)))
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category)))
|
||||
return
|
||||
}
|
||||
|
||||
s := SysJob{}
|
||||
where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName)
|
||||
_, err := dborm.XEngDB().Table(s.TableName()).
|
||||
Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path").
|
||||
Where(where).
|
||||
Get(&querys.Path)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fileName := tableName + "_export_" + querys.DateIndex + "0000" + ".csv"
|
||||
filePath := filepath.Join(querys.Path, fileName)
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Disposition", "attachment; filename="+fileName)
|
||||
c.Header("Content-Type", "application/octet-stream")
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
func (m *FileNBI) GetMultiFileHandler(c *gin.Context) {
|
||||
var querys FileNBIQuery
|
||||
|
||||
querys.Category = c.Param("category")
|
||||
querys.Type = c.Param("type")
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
tableName := ""
|
||||
if querys.Path == "" {
|
||||
ok := false
|
||||
switch querys.Category {
|
||||
case "cdr":
|
||||
tableName, ok = CDRTableMapper[querys.Type]
|
||||
if tableName == "" || !ok {
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid CDR file type: %s", querys.Type)))
|
||||
return
|
||||
}
|
||||
case "log":
|
||||
tableName, ok = LogTableMapper[querys.Type]
|
||||
if tableName == "" || !ok {
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file type: %s", querys.Type)))
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.JSON(http.StatusOK, services.ErrResp(fmt.Sprintf("invalid log file category: %s", querys.Category)))
|
||||
return
|
||||
}
|
||||
|
||||
s := SysJob{}
|
||||
where := fmt.Sprintf("invoke_target='%s' and status=1 and JSON_UNQUOTE(JSON_EXTRACT(target_params,'$.tableName'))='%s'", INVOKE_FILE_EXPORT, tableName)
|
||||
_, err := dborm.XEngDB().Table(s.TableName()).
|
||||
Select("JSON_UNQUOTE(JSON_EXTRACT(target_params, '$.filePath')) as file_path").
|
||||
Where(where).
|
||||
Get(&querys.Path)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
zipWriter := zip.NewWriter(c.Writer)
|
||||
defer zipWriter.Close()
|
||||
|
||||
for _, fileName := range querys.FileNames {
|
||||
filePath := filepath.Join(querys.Path, fileName)
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
writer, err := zipWriter.Create(filepath.Base(fileName))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := io.Copy(writer, file); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
zipFile := tableName + "_export_" + time.Now().Local().Format(global.DateData) + ".zip"
|
||||
c.Header("Content-Disposition", "attachment; filename="+zipFile)
|
||||
c.Header("Content-Type", "application/zip")
|
||||
//c.File(filePath)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package nbi_file
|
||||
|
||||
import (
|
||||
"be.ems/lib/file"
|
||||
)
|
||||
|
||||
const (
|
||||
INVOKE_FILE_EXPORT = "exportTable"
|
||||
)
|
||||
|
||||
var CDRTableMapper map[string]string = map[string]string{
|
||||
"ims": "cdr_event_ims",
|
||||
"smf": "cdr_event_smf",
|
||||
"smsc": "cdr_event_smsc",
|
||||
"sms": "cdr_event_smsc",
|
||||
}
|
||||
|
||||
var LogTableMapper map[string]string = map[string]string{
|
||||
"operate": "sys_log_operate",
|
||||
"security": "sys_log_login",
|
||||
"alarm": "alarm_log",
|
||||
}
|
||||
|
||||
type SysJob struct {
|
||||
JobID int64 `gorm:"column:job_id;primary_key;auto_increment" json:"job_id"` //任务ID
|
||||
InvokeTarget string `gorm:"column:invoke_target" json:"invoke_target"` //调用目标字符串
|
||||
TargetParams string `gorm:"column:target_params;type:json" json:"target_params,omitempty"` //调用目标传入参数
|
||||
}
|
||||
|
||||
func (s *SysJob) TableName() string {
|
||||
return "sys_job"
|
||||
}
|
||||
|
||||
type FileNBI struct {
|
||||
file.FileInfo
|
||||
}
|
||||
|
||||
type FileNBIQuery struct {
|
||||
Category string `form:"category" binding:"required"`
|
||||
Type string `form:"type" binding:"required"`
|
||||
DateIndex string `form:"dateIndex"`
|
||||
Path string `json:"path" form:"path"`
|
||||
FileNames []string `json:"fileName" form:"fileName"`
|
||||
Suffix string `form:"suffix"`
|
||||
PageNum int64 `form:"pageNum"`
|
||||
PageSize int64 `form:"pageSize"`
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package nbi_file
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Register Routes for file_export
|
||||
func Register(r *gin.RouterGroup) {
|
||||
fileNBI := r.Group("/file")
|
||||
{
|
||||
var f *FileNBI
|
||||
fileNBI.GET("/:category/:type/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.GetFileList,
|
||||
)
|
||||
fileNBI.GET("/:category/:type/:dateIndex",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.GetSingleFileHandler,
|
||||
)
|
||||
fileNBI.GET("/:category/:type",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.GetMultiFileHandler,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
package nbi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/oauth"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
)
|
||||
|
||||
type ErrorOAuthResponse struct {
|
||||
Error map[string]interface{}
|
||||
}
|
||||
|
||||
type FailOAuthResponse struct {
|
||||
Error struct {
|
||||
ErrorCode string
|
||||
ErrorInfo string
|
||||
}
|
||||
}
|
||||
|
||||
type ApiResponse struct {
|
||||
ResultCode string
|
||||
ResultMessage interface{}
|
||||
}
|
||||
|
||||
//var globalSession = session.NewSessManager("restagent")
|
||||
|
||||
var (
|
||||
MAX_RMUID_NUM int
|
||||
MAX_ALARMID_NUM int
|
||||
MAX_PMUID_NUM int
|
||||
MAX_SUBID_NUM int
|
||||
MAX_URI_LEN int
|
||||
RMUID_REGEXP string
|
||||
)
|
||||
|
||||
var (
|
||||
// Northbound interface
|
||||
GetNRMUri = config.DefaultUriPrefix + "/resourceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
|
||||
NorthboundGetAlarmUri = config.DefaultUriPrefix + "/faultManagement/{apiVersion}/alarms" // ?alarmIds={alarmIdValues}
|
||||
|
||||
CustomGetNRMUri = config.UriPrefix + "/resourceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
|
||||
)
|
||||
|
||||
func CheckParameterName(r *http.Request) []string {
|
||||
var errorParams []string
|
||||
vars := r.URL.Query()
|
||||
for k, v := range vars {
|
||||
log.Debug("vars:", k, v)
|
||||
if k != "rmUIDs" && k != "fields" {
|
||||
errorParams = append(errorParams, k)
|
||||
}
|
||||
}
|
||||
|
||||
return errorParams
|
||||
}
|
||||
|
||||
func GetRmUIDArr(r *http.Request) []string {
|
||||
vars := r.URL.Query()
|
||||
rmUIDs, ok := vars["rmUIDs"]
|
||||
if !ok {
|
||||
log.Debug("rmUIDs is not exist")
|
||||
return nil
|
||||
}
|
||||
|
||||
var rmUIDValues []string
|
||||
for _, r := range rmUIDs {
|
||||
if r != "" {
|
||||
rmUIDValues = global.MergeStringArr(rmUIDValues, strings.Split(r, `,`))
|
||||
}
|
||||
}
|
||||
|
||||
return rmUIDValues
|
||||
}
|
||||
|
||||
func GetAttrNameArr(r *http.Request) []string {
|
||||
vars := r.URL.Query()
|
||||
fields, ok := vars["fields"]
|
||||
if !ok {
|
||||
log.Debug("attributeNames does not exist")
|
||||
return nil
|
||||
}
|
||||
var attrNames []string
|
||||
for _, a := range fields {
|
||||
if a != "" {
|
||||
attrNames = global.MergeStringArr(attrNames, strings.Split(a, `,`))
|
||||
}
|
||||
}
|
||||
|
||||
return attrNames
|
||||
}
|
||||
|
||||
func CheckValidRmUID(rmUIDs []string) []string {
|
||||
log.Debug("CheckValidRmUID processing... ")
|
||||
|
||||
var invalidRmUIDs []string
|
||||
for _, r := range rmUIDs {
|
||||
if !global.MatchRmUID(RMUID_REGEXP, r) {
|
||||
invalidRmUIDs = append(invalidRmUIDs, r)
|
||||
}
|
||||
}
|
||||
|
||||
return invalidRmUIDs
|
||||
}
|
||||
|
||||
func CheckLocalRmUID(rmUIDs []string) string {
|
||||
log.Debug("GetLocalRmUID processing... ")
|
||||
|
||||
rmUID := config.GetRmUIDFromConfig()
|
||||
for _, r := range rmUIDs {
|
||||
if r == rmUID {
|
||||
return rmUID
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func NBIGetNRMFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("NBIGetNRMFromNF processing... ")
|
||||
|
||||
// response 414-4 uri too long ? (optional)
|
||||
// todo ... ?
|
||||
if bytes.Count([]byte(r.RequestURI), nil) > config.GetUriMaxLenFromConfig() {
|
||||
log.Error("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil), config.GetUriMaxLenFromConfig())
|
||||
services.ResponseRequestURITooLong414UriTooLong(w)
|
||||
return
|
||||
}
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
// response 415-1
|
||||
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
|
||||
log.Debug("Invalid Content-Type")
|
||||
services.ResponseUnsupportedMediaType415(w)
|
||||
return
|
||||
}
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
token, ret := oauth.IsCarriedToken(r)
|
||||
if ret == false {
|
||||
log.Error("AccessToken is not carried")
|
||||
services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return
|
||||
}
|
||||
|
||||
// 401-2 response
|
||||
if dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) == false {
|
||||
log.Error("AccessToken fails or does not exist")
|
||||
services.ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return
|
||||
}
|
||||
|
||||
_, err := dborm.XormUpdateSessionShakeTime(token)
|
||||
if err != nil {
|
||||
log.Error("Failed to update session table:", err)
|
||||
services.ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
// response 403 Forbidden, permissions deny
|
||||
// todo...
|
||||
plist := globalSession.GetPermissionFromSession(token)
|
||||
log.Debug("permission list:", plist)
|
||||
if len(plist) == 0 || plist[0] == false {
|
||||
log.Debug("User permission deny")
|
||||
services.ResponseForbidden403NotPermission(w)
|
||||
return
|
||||
}
|
||||
*/
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != "v1" {
|
||||
log.Error("Uri is invalid")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// response 406-1
|
||||
rmUIDValues := GetRmUIDArr(r)
|
||||
if rmUIDValues == nil {
|
||||
log.Error("missing parameter: rmUIDs")
|
||||
services.ResponseNotAcceptable406MissingParam(w)
|
||||
return
|
||||
}
|
||||
|
||||
// response 406-2
|
||||
errorParams := CheckParameterName(r)
|
||||
if errorParams != nil {
|
||||
log.Error("parameter name error: ", errorParams)
|
||||
services.ResponseNotAcceptable406ParamError(w, errorParams)
|
||||
return
|
||||
}
|
||||
|
||||
// response 400-5
|
||||
if len(rmUIDValues) == 0 {
|
||||
log.Error("rmUIDs is wrong or NULL")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
|
||||
// response 414-1
|
||||
if len(rmUIDValues) > config.GetYamlConfig().Params.RmUIDMaxNum {
|
||||
log.Error("rmUID greater than", config.GetYamlConfig().Params.RmUIDMaxNum)
|
||||
services.ResponseRequestURITooLong414NRMNumExceed(w, config.GetYamlConfig().Params.RmUIDMaxNum)
|
||||
return
|
||||
}
|
||||
|
||||
var response *resty.Response
|
||||
respMsg := make(map[string]interface{})
|
||||
for _, rmUID := range rmUIDValues {
|
||||
neInfo, err := dborm.XormGetNeInfoByRmUID(neType, rmUID)
|
||||
if err != nil {
|
||||
log.Error("dborm.XormGetNeInfo is failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.Ip, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF: GET ", requestURI2NF)
|
||||
|
||||
client := resty.New()
|
||||
response, err = client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Get from NF:", err)
|
||||
services.ResponseInternalServerError500NFConnectRefused(w)
|
||||
return
|
||||
}
|
||||
switch response.StatusCode() {
|
||||
case http.StatusOK, http.StatusAccepted, http.StatusNoContent, http.StatusCreated:
|
||||
respMsg["data"] = response
|
||||
default:
|
||||
if response != nil {
|
||||
services.TransportResponse(w, response.StatusCode(), response.Body())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
services.TransportResponse(w, response.StatusCode(), response.Body())
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// log management package
|
||||
|
||||
package nbi
|
||||
|
||||
import (
|
||||
nbi_file "be.ems/features/nbi/file"
|
||||
"be.ems/lib/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitSubServiceRoute(r *gin.Engine) {
|
||||
log.Info("======init North-Bound Interface group gin.Engine")
|
||||
|
||||
nbiGroup := r.Group("/nbi")
|
||||
nbi_file.Register(nbiGroup)
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package nbi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
g "github.com/gosnmp/gosnmp"
|
||||
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
conf := config.GetYamlConfig()
|
||||
// Default is a pointer to a GoSNMP struct that contains sensible defaults
|
||||
// eg port 161, community public, etc
|
||||
g.Default.Target = conf.NE.Addr
|
||||
g.Default.Port = conf.NE.Port
|
||||
err := g.Default.Connect()
|
||||
if err != nil {
|
||||
fmt.Printf("Connect() err: %v", err)
|
||||
}
|
||||
//defer g.Default.Conn.Close()
|
||||
MAX_RMUID_NUM = config.GetRmUIDMaxNumFromConfig()
|
||||
MAX_ALARMID_NUM = config.GetAlarmIDMaxNumFromConfig()
|
||||
MAX_PMUID_NUM = config.GetPmIDMaxNumFromConfig()
|
||||
MAX_SUBID_NUM = config.GetSubIDMaxNumFromConfig()
|
||||
MAX_URI_LEN = config.GetUriMaxLenFromConfig()
|
||||
RMUID_REGEXP = config.GetRmUIDRegexpFromConfig()
|
||||
}
|
||||
|
||||
func GetNRMByUri(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetNRMByUri processing... ")
|
||||
|
||||
// response 414-4 uri too long ? (optional)
|
||||
// todo ... ?
|
||||
if bytes.Count([]byte(r.RequestURI), nil) > MAX_URI_LEN {
|
||||
log.Error("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil))
|
||||
services.ResponseRequestURITooLong414UriTooLong(w)
|
||||
return
|
||||
}
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
// response 415-1
|
||||
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
|
||||
log.Debug("Invalid Content-Type")
|
||||
services.ResponseUnsupportedMediaType415(w)
|
||||
return
|
||||
}
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
// token, ret := globalSession.IsCarriedToken(r)
|
||||
// if ret == false {
|
||||
// log.Error("AccessToken is not carried")
|
||||
// services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
// 401-2 response
|
||||
// if globalSession.IsValidToken(token) == false {
|
||||
// log.Error("AccessToken fails or does not exist")
|
||||
// services.ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
// return
|
||||
// }
|
||||
// response 403 Forbidden, permissions deny
|
||||
// todo...
|
||||
// plist := globalSession.GetPermissionFromSession(token)
|
||||
// log.Debug("permission list:", plist)
|
||||
// if len(plist) == 0 || plist[0] == false {
|
||||
// log.Error("User permission deny")
|
||||
// services.ResponseForbidden403NotPermission(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
qeuryUri := vars["apiCategory"] + "/" + vars["elementTypeValue"] + "/" + vars["objectTypeValue"]
|
||||
log.Debug("Get by Uri: ", qeuryUri)
|
||||
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != "v1" {
|
||||
log.Error("Uri is invalid")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// response 406-1
|
||||
rmUIDValues := GetRmUIDArr(r)
|
||||
if rmUIDValues == nil {
|
||||
log.Error("missing parameter: rmUIDs")
|
||||
services.ResponseNotAcceptable406MissingParam(w)
|
||||
return
|
||||
}
|
||||
|
||||
// response 406-2
|
||||
errorParams := CheckParameterName(r)
|
||||
if errorParams != nil {
|
||||
log.Error("parameter name error: ", errorParams)
|
||||
services.ResponseNotAcceptable406ParamError(w, errorParams)
|
||||
return
|
||||
}
|
||||
|
||||
// response 400-5
|
||||
if len(rmUIDValues) == 0 {
|
||||
log.Error("rmUIDs is wrong or NULL")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
|
||||
// response 414-1
|
||||
if len(rmUIDValues) > MAX_RMUID_NUM {
|
||||
log.Error("rmUID greater than", MAX_RMUID_NUM)
|
||||
services.ResponseRequestURITooLong414NRMNumExceed(w, MAX_RMUID_NUM)
|
||||
return
|
||||
}
|
||||
|
||||
// response 400-1
|
||||
// check rmUID is valid
|
||||
// todo ...
|
||||
invalidRmUIDs := CheckValidRmUID(rmUIDValues)
|
||||
if len(invalidRmUIDs) != 0 {
|
||||
log.Error("rmUID is invalid")
|
||||
services.ResponseBadRequest400RmUIDsIsInvalid(w, invalidRmUIDs)
|
||||
return
|
||||
}
|
||||
|
||||
// response 404-2
|
||||
rmUID := CheckLocalRmUID(rmUIDValues)
|
||||
if rmUID == "" {
|
||||
log.Error("rmUID does not exist")
|
||||
services.ResponseNotFound404NRMNotExist(w, rmUIDValues)
|
||||
return
|
||||
}
|
||||
|
||||
// response 404-1, uri is not exist in map
|
||||
attrNames := GetAttrNameArr(r)
|
||||
var Oids []string
|
||||
Oids = *config.GetOidByFileds(qeuryUri, attrNames, &Oids)
|
||||
if len(Oids) == 0 {
|
||||
log.Error("Nothing of config map")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// response 404-1, uri is not exist in map
|
||||
var nameOids []config.NameOid
|
||||
nameOids = *config.GetDataOidByFields(qeuryUri, attrNames, &nameOids)
|
||||
if len(nameOids) == 0 {
|
||||
log.Error("Nothing of config map")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
result, err2 := g.Default.Get(Oids) // Get() accepts up to g.MAX_OIDS
|
||||
if err2 != nil {
|
||||
log.Fatalf("Get() err: %v", err2)
|
||||
|
||||
}
|
||||
|
||||
// var nameValues []config.NameValue
|
||||
var nameValue config.NameValue
|
||||
|
||||
nameValues := make(map[string]interface{})
|
||||
nameValues["rmUID"] = rmUID
|
||||
for i, variable := range result.Variables {
|
||||
nameValue.Name = nameOids[i].Name
|
||||
log.Debugf("%d: oid: %s name: %s\n", i, variable.Name, nameValue.Name)
|
||||
// if nameOids[i].Oid == variable.Name && global.IsContain(attributeNames, nameValue.Name) {
|
||||
if nameOids[i].Oid == variable.Name {
|
||||
// the Value of each variable returned by Get() implements
|
||||
// interface{}. You could do a type switch...
|
||||
switch variable.Type {
|
||||
case g.OctetString:
|
||||
bytes := variable.Value.([]byte)
|
||||
log.Debugf("string: %s\n", string(bytes))
|
||||
nameValue.Value = string(bytes)
|
||||
nameValues[nameValue.Name] = nameValue.Value
|
||||
case g.Integer:
|
||||
value := variable.Value.(int)
|
||||
log.Debugf("integer: %d\n", value)
|
||||
nameValue.Value = strconv.Itoa(value)
|
||||
nameValues[nameValue.Name] = nameValue.Value
|
||||
case g.IPAddress:
|
||||
value := variable.Value.(string)
|
||||
log.Debugf("IPAddress: %s\n", variable.Value)
|
||||
nameValue.Value = value
|
||||
nameValues[nameValue.Name] = nameValue.Value
|
||||
default:
|
||||
// ... or often you're just interested in numeric values.
|
||||
// ToBigInt() will return the Value as a BigInt, for plugging
|
||||
// into your calculations.
|
||||
log.Debugf("number: %d\n", g.ToBigInt(variable.Value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getResponse := services.DataResponse{nameValues}
|
||||
services.ResponseWithJson(w, http.StatusOK, getResponse)
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
package kpi_c_report
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func (k *KpiCReport) Get(c *gin.Context) {
|
||||
var reports []KpiCReport
|
||||
var conditions []string
|
||||
var params []any
|
||||
|
||||
var querys KpiCReportQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusBadRequest, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// construct condition to get
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, strings.ToUpper(querys.NeType))
|
||||
} else {
|
||||
c.JSON(http.StatusBadRequest, services.ErrResp("Not found NE type"))
|
||||
return
|
||||
}
|
||||
tableName := TableName() + "_" + strings.ToLower(querys.NeType)
|
||||
dbg := dborm.DefaultDB().Table(tableName)
|
||||
|
||||
if querys.NeID != "" {
|
||||
conditions = append(conditions, "rm_uid = (select n.rm_uid from ne_info n where n.ne_type=? and n.ne_id=? and n.status=1)")
|
||||
params = append(params, strings.ToUpper(querys.NeType), querys.NeID)
|
||||
} else {
|
||||
c.JSON(http.StatusBadRequest, services.ErrResp("Not found required parameter NE ID"))
|
||||
return
|
||||
}
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
|
||||
params = append(params, querys.StartTime)
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
|
||||
params = append(params, querys.EndTime)
|
||||
}
|
||||
conditions = append(conditions, "kpi_values != 'null'")
|
||||
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += strings.Join(conditions, " and ")
|
||||
dbg = dbg.Where(whereSql, params...)
|
||||
}
|
||||
// page number and size
|
||||
if pageSize := querys.PageSize; pageSize > 0 {
|
||||
dbg = dbg.Limit(pageSize)
|
||||
if pageNum := querys.PageNum; pageNum > 0 {
|
||||
dbg = dbg.Offset((pageNum - 1) * pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
// order by
|
||||
if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
|
||||
orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
|
||||
dbg = dbg.Order(orderBy)
|
||||
}
|
||||
|
||||
//err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error
|
||||
err := dbg.Find(&reports).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, services.DataResp(reports))
|
||||
}
|
||||
|
||||
func (k *KpiCReport) GetReport2FE(c *gin.Context) {
|
||||
var results []KpiCReport
|
||||
var conditions []string
|
||||
var params []any
|
||||
|
||||
var querys KpiCReportQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// construct condition to get
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, strings.ToUpper(querys.NeType))
|
||||
} else {
|
||||
c.JSON(http.StatusOK, services.ErrResp("Not found required parameter NE type"))
|
||||
return
|
||||
}
|
||||
tableName := TableName() + "_" + strings.ToLower(querys.NeType)
|
||||
dbg := dborm.DefaultDB().Table(tableName)
|
||||
|
||||
if querys.NeID != "" {
|
||||
conditions = append(conditions, "rm_uid = (select n.rm_uid from ne_info n where n.ne_type=? and n.ne_id=? and n.status=1)")
|
||||
params = append(params, querys.NeType, querys.NeID)
|
||||
} else {
|
||||
c.JSON(http.StatusBadRequest, services.ErrResp("Not found required parameter NE ID"))
|
||||
return
|
||||
}
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
|
||||
params = append(params, querys.StartTime)
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
|
||||
params = append(params, querys.EndTime)
|
||||
}
|
||||
conditions = append(conditions, "kpi_values != 'null'")
|
||||
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += strings.Join(conditions, " and ")
|
||||
dbg = dbg.Where(whereSql, params...)
|
||||
}
|
||||
// page number and size
|
||||
if pageSize := querys.PageSize; pageSize > 0 {
|
||||
dbg = dbg.Limit(pageSize)
|
||||
if pageNum := querys.PageNum; pageNum > 0 {
|
||||
dbg = dbg.Offset((pageNum - 1) * pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
// order by
|
||||
if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
|
||||
orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
|
||||
dbg = dbg.Order(orderBy)
|
||||
}
|
||||
|
||||
//err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error
|
||||
err := dbg.Find(&results).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
reports := []map[string]any{}
|
||||
for _, r := range results {
|
||||
report := map[string]any{
|
||||
// kip_id ...
|
||||
"neType": *r.NeType,
|
||||
"neId": querys.NeID,
|
||||
"neName": *r.NeName,
|
||||
"rmUID": *r.RmUID,
|
||||
"startIndex": r.Index,
|
||||
"timeGroup": r.Date[:10] + " " + *r.EndTime,
|
||||
"createdAt": r.CreatedAt,
|
||||
"granularity": r.Granularity,
|
||||
}
|
||||
|
||||
for _, k := range r.KpiValues {
|
||||
report[k.KPIID] = k.Value
|
||||
}
|
||||
reports = append(reports, report)
|
||||
}
|
||||
c.JSON(http.StatusOK, services.DataResp(reports))
|
||||
}
|
||||
|
||||
func (k *KpiCReport) GetTotalList(c *gin.Context) {
|
||||
var reports []KpiCReport
|
||||
var conditions []string
|
||||
var params []any
|
||||
|
||||
var querys KpiCReportQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// construct condition to get
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, strings.ToUpper(querys.NeType))
|
||||
} else {
|
||||
c.JSON(http.StatusOK, services.ErrResp("Not found NE type"))
|
||||
return
|
||||
}
|
||||
tableName := TableName() + "_" + strings.ToLower(querys.NeType)
|
||||
dbg := dborm.DefaultDB().Table(tableName)
|
||||
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
|
||||
params = append(params, querys.StartTime)
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
|
||||
params = append(params, querys.EndTime)
|
||||
}
|
||||
conditions = append(conditions, "kpi_values != 'null'")
|
||||
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += strings.Join(conditions, " and ")
|
||||
dbg = dbg.Where(whereSql, params...)
|
||||
}
|
||||
|
||||
// get total number
|
||||
var total int64 = 0
|
||||
err := dbg.Count(&total).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// page number and size
|
||||
if pageSize := querys.PageSize; pageSize > 0 {
|
||||
dbg = dbg.Limit(pageSize)
|
||||
if pageNum := querys.PageNum; pageNum > 0 {
|
||||
dbg = dbg.Offset((pageNum - 1) * pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
// order by
|
||||
if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
|
||||
orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
|
||||
dbg = dbg.Order(orderBy)
|
||||
}
|
||||
|
||||
//err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error
|
||||
err = dbg.Find(&reports).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, services.TotalDataResp(reports, total))
|
||||
}
|
||||
|
||||
func (k *KpiCReport) Total(c *gin.Context) {
|
||||
var conditions []string
|
||||
var params []any
|
||||
|
||||
var querys KpiCReportQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// construct condition to get
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, strings.ToUpper(querys.NeType))
|
||||
} else {
|
||||
c.JSON(http.StatusOK, services.ErrResp("Not found NE type"))
|
||||
return
|
||||
}
|
||||
tableName := TableName() + "_" + strings.ToLower(querys.NeType)
|
||||
dbg := dborm.DefaultDB().Table(tableName)
|
||||
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
|
||||
params = append(params, querys.StartTime)
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
|
||||
params = append(params, querys.EndTime)
|
||||
}
|
||||
conditions = append(conditions, "kpi_values != 'null'")
|
||||
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += strings.Join(conditions, " and ")
|
||||
dbg = dbg.Where(whereSql, params...)
|
||||
}
|
||||
var total int64 = 0
|
||||
err := dbg.Count(&total).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, services.TotalResp(total))
|
||||
}
|
||||
|
||||
func (k *KpiCReport) Post(c *gin.Context) {
|
||||
var report KpiCReport
|
||||
|
||||
if err := c.ShouldBindJSON(&report); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
if err := dborm.DefaultDB().Create(&report).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, services.DataResp(report))
|
||||
}
|
||||
|
||||
func (k *KpiCReport) Put(c *gin.Context) {
|
||||
var report KpiCReport
|
||||
id := c.Param("id")
|
||||
|
||||
if err := dborm.DefaultDB().First(&report, id).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp("custom indicator report not found"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&report); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
dborm.DefaultDB().Save(&report)
|
||||
c.JSON(http.StatusOK, services.DataResp(report))
|
||||
}
|
||||
|
||||
func (k *KpiCReport) Delete(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
if err := dborm.DefaultDB().Delete(&KpiCReport{}, id).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp("custom indicator report not found"))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusNoContent, nil) // 204 No Content
|
||||
}
|
||||
|
||||
func InsertKpiCReport(neType string, report KpiCReport) {
|
||||
tableName := TableName() + "_" + strings.ToLower(neType)
|
||||
if err := dborm.DefaultDB().Table(tableName).Create(&report).Error; err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package kpi_c_report
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type KpiCVal struct {
|
||||
KPIID string `json:"kpi_id" gorm:"column:kpi_id"`
|
||||
Value float64 `json:"value" gorm:"column:value"`
|
||||
Err string `json:"err" gorm:"column:err"`
|
||||
}
|
||||
|
||||
type KpiCValues []KpiCVal
|
||||
|
||||
type KpiCReport struct {
|
||||
ID int `gorm:"column:id;primary_key;auto_increment" json:"id"`
|
||||
NeType *string `gorm:"column:ne_type;default:NULL" json:"neType,omitempty"`
|
||||
NeName *string `gorm:"column:ne_name;default:" json:"neName,omitempty"`
|
||||
RmUID *string `gorm:"column:rm_uid;default:NULL" json:"rmUid,omitempty"`
|
||||
Date string `gorm:"column:date" json:"date"` // time.Time `gorm:"column:date" json:"date"`
|
||||
StartTime *string `gorm:"column:start_time;default:NULL" json:"startTime,omitempty"`
|
||||
EndTime *string `gorm:"column:end_time;default:NULL" json:"endTime,omitempty"`
|
||||
Index int16 `gorm:"column:index" json:"index"`
|
||||
Granularity *int8 `gorm:"column:granularity;default:60" json:"granularity,omitempty"` //Time granualarity: 5/10/.../60/300 (second)
|
||||
KpiValues KpiCValues `gorm:"column:kpi_values;type:json" json:"kpiValues,omitempty"`
|
||||
CreatedAt *time.Time `gorm:"column:created_at;default:current_timestamp()" json:"createdAt,omitempty"`
|
||||
}
|
||||
|
||||
type KpiCReportQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required"`
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
StartTime string `json:"startTime" form:"startTime"`
|
||||
EndTime string `json:"endTime" form:"endTime"`
|
||||
UserName string `json:"userName" form:"userName"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=created_at"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int `json:"pageNum" form:"pageNum"`
|
||||
PageSize int `json:"pageSize" form:"pageSize"`
|
||||
}
|
||||
|
||||
type KpiCReport2FE struct {
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeId string `json:"neId"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUid" gorm:"column:rm_uid"`
|
||||
TimeGroup string `json:"timeGroup"`
|
||||
StartIndex int16 `json:"startIndex" gorm:"column:index"`
|
||||
Granularity int8 `json:"granularity" gorm:"column:granularity"`
|
||||
}
|
||||
|
||||
func TableName() string {
|
||||
return "kpi_c_report"
|
||||
}
|
||||
|
||||
// 将 KpiCValues 转换为 JSON 字节
|
||||
func (k KpiCValues) Value() (driver.Value, error) {
|
||||
return json.Marshal(k)
|
||||
}
|
||||
|
||||
// 从字节中扫描 KpiCValues
|
||||
func (k *KpiCValues) Scan(value interface{}) error {
|
||||
b, ok := value.([]byte)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to scan value: %v", value)
|
||||
}
|
||||
return json.Unmarshal(b, k)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package kpi_c_report
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Register Routes for kpi_c_report
|
||||
func Register(r *gin.RouterGroup) {
|
||||
|
||||
pmKPIC := r.Group("/kpiC")
|
||||
{
|
||||
var k *KpiCReport
|
||||
pmKPIC.GET("/report",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.GetReport2FE,
|
||||
)
|
||||
pmKPIC.GET("/report/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Get,
|
||||
)
|
||||
pmKPIC.GET("/report/totalList",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Total,
|
||||
)
|
||||
pmKPIC.GET("/report/total",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Total,
|
||||
)
|
||||
pmKPIC.POST("/report",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Post,
|
||||
)
|
||||
pmKPIC.PUT("/report/:id",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Put,
|
||||
)
|
||||
pmKPIC.DELETE("/report/:id",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Delete,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
package kpi_c_title
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// get customize kpi total and list
|
||||
func (k *KpiCTitle) GetToalList(c *gin.Context) {
|
||||
var titles []KpiCTitle
|
||||
var conditions []string
|
||||
var params []any
|
||||
i18n := ctx.AcceptLanguage(c)
|
||||
|
||||
var querys KpiCTitleQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
dbg := dborm.DefaultDB().Table(k.TableName())
|
||||
// construct condition to get
|
||||
if neType := querys.NeType; neType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, strings.ToUpper(neType))
|
||||
}
|
||||
if status := querys.Status; status != "" {
|
||||
conditions = append(conditions, "status = ?")
|
||||
params = append(params, status)
|
||||
} else {
|
||||
conditions = append(conditions, "status != 'Deleted'")
|
||||
}
|
||||
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += strings.Join(conditions, " and ")
|
||||
dbg = dbg.Where(whereSql, params...)
|
||||
}
|
||||
|
||||
// Get total number
|
||||
var total int64 = 0
|
||||
if err := dbg.Count(&total).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// page number and size
|
||||
if pageSize := querys.PageSize; pageSize > 0 {
|
||||
dbg = dbg.Limit(pageSize)
|
||||
if pageNum := querys.PageNum; pageNum > 0 {
|
||||
dbg = dbg.Offset((pageNum - 1) * pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
// order by
|
||||
if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
|
||||
orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
|
||||
dbg = dbg.Order(orderBy)
|
||||
}
|
||||
if err := dbg.Find(&titles).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
k.expressionAlias(titles, i18n)
|
||||
|
||||
c.JSON(http.StatusOK, services.TotalDataResp(titles, total))
|
||||
//c.JSON(http.StatusOK, titles)
|
||||
}
|
||||
|
||||
func (k *KpiCTitle) Get(c *gin.Context) {
|
||||
var titles []KpiCTitle
|
||||
var conditions []string
|
||||
var params []any
|
||||
i18n := ctx.AcceptLanguage(c)
|
||||
|
||||
// construct condition to get
|
||||
if neType := c.Query("neType"); neType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, strings.ToUpper(neType))
|
||||
}
|
||||
if status := c.Query("status"); status != "" {
|
||||
conditions = append(conditions, "status = ?")
|
||||
params = append(params, status)
|
||||
} else {
|
||||
conditions = append(conditions, "status != 'Deleted'")
|
||||
}
|
||||
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += strings.Join(conditions, " and ")
|
||||
}
|
||||
if err := dborm.DefaultDB().Where(whereSql, params...).Find(&titles).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
k.expressionAlias(titles, i18n)
|
||||
|
||||
c.JSON(http.StatusOK, services.DataResp(titles))
|
||||
//c.JSON(http.StatusOK, titles)
|
||||
}
|
||||
|
||||
// alias customized kpi expression with cn/en title
|
||||
func (k *KpiCTitle) expressionAlias(titles []KpiCTitle, i18n string) {
|
||||
var title *KpiCTitle
|
||||
for i := 0; i < len(titles); i++ {
|
||||
title = &titles[i]
|
||||
title.ExprAlias = *title.Expression
|
||||
re := regexp.MustCompile(`'([^']+)'`)
|
||||
matches := re.FindAllStringSubmatch(title.ExprAlias, -1)
|
||||
|
||||
for _, match := range matches {
|
||||
var alias, sql string
|
||||
if i18n == "zh" {
|
||||
sql = fmt.Sprintf("SELECT cn_title FROM kpi_title WHERE kpi_id='%s'", match[1])
|
||||
} else {
|
||||
sql = fmt.Sprintf("SELECT en_title FROM kpi_title WHERE kpi_id='%s'", match[1])
|
||||
}
|
||||
err := dborm.XCoreDB().QueryRow(sql).Scan(&alias)
|
||||
if err != nil {
|
||||
log.Warn("Failed to QueryRow:", err)
|
||||
continue
|
||||
}
|
||||
title.ExprAlias = regexp.MustCompile(match[1]).ReplaceAllString(title.ExprAlias, alias)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (k *KpiCTitle) Total(c *gin.Context) {
|
||||
var conditions []string
|
||||
var params []any
|
||||
|
||||
// construct condition to get
|
||||
if neType := c.Query("neType"); neType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, strings.ToUpper(neType))
|
||||
}
|
||||
if status := c.Query("status"); status != "" {
|
||||
conditions = append(conditions, "status = ?")
|
||||
params = append(params, status)
|
||||
} else {
|
||||
conditions = append(conditions, "status != 'Deleted'")
|
||||
}
|
||||
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += strings.Join(conditions, " and ")
|
||||
}
|
||||
var total int64 = 0
|
||||
if err := dborm.DefaultDB().Table(k.TableName()).Where(whereSql, params...).Count(&total).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, services.TotalResp(total))
|
||||
}
|
||||
|
||||
func (k *KpiCTitle) Post(c *gin.Context) {
|
||||
var title, res KpiCTitle
|
||||
|
||||
if err := c.ShouldBindJSON(&title); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
userName := ctx.LoginUserToUserName(c)
|
||||
title.CreatedBy = &userName
|
||||
result := dborm.DefaultDB().Where("ne_type=? and (kpi_id=? or title=?) and status!='Deleted'", title.NeType, title.KpiID, title.Title).First(&title)
|
||||
if result.RowsAffected > 0 {
|
||||
c.JSON(http.StatusOK, services.ErrResp("custom indicator already exist"))
|
||||
return
|
||||
}
|
||||
|
||||
// Regexp match like AMF.C.01
|
||||
kpiIDRegexp := "^" + *title.NeType + "\\.C\\.[0-9]{2}$"
|
||||
ret := dborm.DefaultDB().Table("kpi_c_title").
|
||||
Where("ne_type=? and kpi_id REGEXP ? ORDER BY kpi_id DESC LIMIT 1", title.NeType, kpiIDRegexp).Scan(&res)
|
||||
if err := ret.Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
newKpiID := *title.NeType + ".C" + ".01"
|
||||
if ret.RowsAffected != 0 {
|
||||
maxKpiID := *res.KpiID
|
||||
prefix := maxKpiID[:len(maxKpiID)-2]
|
||||
suffix := maxKpiID[len(maxKpiID)-2:]
|
||||
suffixInt, err := strconv.Atoi(suffix)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
if suffixInt >= MAX_KPI_C_ID {
|
||||
err := fmt.Errorf("exceed the max customized KPI ID")
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
suffixInt++
|
||||
newSuffix := fmt.Sprintf("%02d", suffixInt)
|
||||
newKpiID = prefix + newSuffix
|
||||
}
|
||||
title.KpiID = &newKpiID
|
||||
if err := dborm.DefaultDB().Create(&title).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
kpiCReportTable := "kpi_c_report_" + strings.ToLower(*title.NeType)
|
||||
if !dborm.DefaultDB().Migrator().HasTable(kpiCReportTable) {
|
||||
// clone table "kpi_c_report" to "kpi_c_report_{neType}"
|
||||
sql := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s AS SELECT * FROM %s WHERE 1=0", kpiCReportTable, "kpi_c_report")
|
||||
if _, err := dborm.ExecSQL(sql, nil); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
sql = fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,ADD PRIMARY KEY IF NOT EXISTS (`id`)", kpiCReportTable)
|
||||
if _, err := dborm.ExecSQL(sql, nil); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
sql = fmt.Sprintf("ALTER TABLE %s ADD INDEX IF NOT EXISTS `idx_timestamp`(`created_at`) USING BTREE, ADD INDEX IF NOT EXISTS `idx_uid_datetime`(`rm_uid`, `date`, `start_time`) USING BTREE", kpiCReportTable)
|
||||
if _, err := dborm.ExecSQL(sql, nil); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusCreated, services.DataResp(title))
|
||||
}
|
||||
|
||||
func (k *KpiCTitle) Put(c *gin.Context) {
|
||||
var title KpiCTitle
|
||||
id := c.Param("id")
|
||||
|
||||
if err := dborm.DefaultDB().First(&title, id).Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp("custom indicator not found"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&title); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
dborm.DefaultDB().Save(&title)
|
||||
|
||||
c.JSON(http.StatusOK, services.DataResp(title))
|
||||
}
|
||||
|
||||
func (k *KpiCTitle) Delete(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
if err := dborm.DefaultDB().Table(k.TableName()).Where("id=?", id).Update("status", "Deleted").Error; err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusNoContent, nil) // 204 No Content
|
||||
}
|
||||
|
||||
func GetActiveKPICList(neType string) []KpiCTitle {
|
||||
k := new([]KpiCTitle)
|
||||
|
||||
err := dborm.DefaultDB().Where("`ne_type` = ? and `status` = 'Active'", neType).Find(&k).Error
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return *k
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package kpi_c_title
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
MAX_KPI_C_ID = 99
|
||||
)
|
||||
|
||||
type KpiCTitle struct {
|
||||
ID int `gorm:"column:id;primary_key;auto_increment" json:"id"`
|
||||
NeType *string `gorm:"column:ne_type;default:NULL," json:"neType,omitempty"`
|
||||
KpiID *string `gorm:"column:kpi_id;default:NULL," json:"kpiId,omitempty"`
|
||||
Title *string `gorm:"column:title;default:NULL," json:"title,omitempty"`
|
||||
Expression *string `gorm:"column:expression;default:NULL," json:"expression,omitempty"`
|
||||
ExprAlias string `gorm:"-" json:"exprAlias"`
|
||||
Status string `gorm:"column:status;default:'Active'" json:"status"`
|
||||
Unit *string `gorm:"column:unit" json:"unit,omitempty"`
|
||||
Description *string `gorm:"column:description;default:NULL," json:"description,omitempty"`
|
||||
CreatedBy *string `gorm:"column:created_by;default:NULL," json:"createdBy,omitempty"`
|
||||
UpdatedAt *time.Time `gorm:"column:updated_at;default:current_timestamp()," json:"updatedAt,omitempty"`
|
||||
}
|
||||
|
||||
type KpiCTitleQuery struct {
|
||||
ID int `json:"id" form:"id"`
|
||||
NeType string `json:"neType" form:"neType"`
|
||||
Status string `json:"status" form:"status"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=created_at"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int `json:"pageNum" form:"pageNum"`
|
||||
PageSize int `json:"pageSize" form:"pageSize"`
|
||||
}
|
||||
|
||||
func (k *KpiCTitle) TableName() string {
|
||||
return "kpi_c_title"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package kpi_c_title
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Register Routes for kpi_c_title
|
||||
func Register(r *gin.RouterGroup) {
|
||||
|
||||
pmKPIC := r.Group("/kpiC")
|
||||
{
|
||||
var k *KpiCTitle
|
||||
pmKPIC.GET("/title",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Get,
|
||||
)
|
||||
pmKPIC.GET("/title/total",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Total,
|
||||
)
|
||||
pmKPIC.GET("/title/totalList",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.GetToalList,
|
||||
)
|
||||
pmKPIC.POST("/title",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Post,
|
||||
)
|
||||
pmKPIC.PUT("/title/:id",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Put,
|
||||
)
|
||||
pmKPIC.DELETE("/title/:id",
|
||||
middleware.PreAuthorize(nil),
|
||||
k.Delete,
|
||||
)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,19 @@
|
||||
package pm
|
||||
|
||||
import (
|
||||
"be.ems/features/pm/kpi_c_report"
|
||||
"be.ems/features/pm/kpi_c_title"
|
||||
"be.ems/lib/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitSubServiceRoute(r *gin.Engine) {
|
||||
log.Info("======init PM group gin.Engine")
|
||||
|
||||
pmGroup := r.Group("/pm")
|
||||
// register sub modules routes
|
||||
kpi_c_title.Register(pmGroup)
|
||||
kpi_c_report.Register(pmGroup)
|
||||
|
||||
// return featuresGroup
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/oauth"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
)
|
||||
|
||||
var (
|
||||
UriOauthToken = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
|
||||
UriOauthHandshake = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
|
||||
|
||||
CustomUriOauthToken = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
|
||||
CustomUriOauthHandshake = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
|
||||
)
|
||||
|
||||
func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("LoginFromOMC processing... ")
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Error("Failed to ReadAll:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
|
||||
log.Debug("Invalid Content-Type")
|
||||
services.ResponseUnsupportedMediaType415(w)
|
||||
return
|
||||
}
|
||||
|
||||
// // check extend uri, response 404
|
||||
// if !IsValidOAuthUri(r) {
|
||||
// log.Debug("Uri is invalid")
|
||||
// services.ResponseNotFound404UriNotExist(w, r)
|
||||
// return
|
||||
// }
|
||||
|
||||
// Error process ....
|
||||
// response 400-7
|
||||
if !json.Valid([]byte(body)) {
|
||||
log.Error("Invalid Json Format")
|
||||
services.ResponseBadRequest400InvalidJson(w)
|
||||
return
|
||||
}
|
||||
|
||||
var oAuthBody oauth.OAuthBody
|
||||
_ = json.Unmarshal(body, &oAuthBody) //转为json
|
||||
//log.Debug("body:", string(body), "oAuthBody:", oAuthBody)
|
||||
|
||||
defer r.Body.Close()
|
||||
// response 400-5
|
||||
if oauth.IsWrongOAuthInfo(oAuthBody) {
|
||||
log.Error("Wrong parameter value")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
/*
|
||||
if oauth.IsValidOAuthInfo(oAuthBody) {
|
||||
plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType)
|
||||
log.Debug("Permission list:", plist)
|
||||
|
||||
token := globalSession.NewSession(w, r, plist)
|
||||
services.ResponseStatusOK200Login(w, token)
|
||||
} else {
|
||||
// response 400-4
|
||||
log.Debug("Authentication failed, mismatch user or password")
|
||||
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
}
|
||||
*/
|
||||
validUser, user, err := dborm.XormCheckLoginUser(oAuthBody.UserName,
|
||||
oAuthBody.Value, config.GetYamlConfig().Auth.Crypt)
|
||||
if !validUser || err != nil {
|
||||
// response 400-4
|
||||
log.Error("Authentication failed, mismatch user or password")
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
token := oauth.GenRandToken("omc") // Generate new token to session ID
|
||||
sourceAddr := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
|
||||
affected, err := dborm.XormInsertSession(oAuthBody.UserName, sourceAddr, token,
|
||||
config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormInsertSession:", err)
|
||||
if affected == -1 {
|
||||
services.ResponseForbidden403MultiLoginNotAllowed(w)
|
||||
} else {
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
empty := []string{}
|
||||
services.ResponseStatusOK200LoginWhitRP(w, token, user, empty, empty)
|
||||
return
|
||||
}
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
}
|
||||
|
||||
func LogoutFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("LogoutFromOMC processing... ")
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// // check media type(content type) only support "application/json"
|
||||
// if services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) == false {
|
||||
// log.Error("Invalid Content-Type")
|
||||
// services.ResponseUnsupportedMediaType415(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
// // check extend uri, response 404
|
||||
// if !services.IsValidOAuthUri(r) {
|
||||
// log.Error("Uri is invalid")
|
||||
// services.ResponseNotFound404UriNotExist(w, r)
|
||||
// return
|
||||
// }
|
||||
|
||||
// // error processing ...
|
||||
// // 401-1 response
|
||||
// token, ret := oauth.IsCarriedToken(r)
|
||||
// if ret == false {
|
||||
// log.Error("AccessToken is not carried")
|
||||
// services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
// se, err := dborm.XormLogoutUpdateSession(token)
|
||||
// if err != nil {
|
||||
// log.Error("Uri is invalid")
|
||||
// services.ResponseNotFound404UriNotExist(w, r)
|
||||
// return
|
||||
// }
|
||||
// 清除缓存用户信息
|
||||
// account.ClearLoginUser(se.AccountId)
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("HandshakeFromOMC processing... ")
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
|
||||
log.Debug("Invalid Content-Type")
|
||||
services.ResponseUnsupportedMediaType415(w)
|
||||
return
|
||||
}
|
||||
|
||||
// check extend uri, response 404
|
||||
if !services.IsValidOAuthUri(r) {
|
||||
log.Error("Uri is invalid")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
token, ret := oauth.IsCarriedToken(r)
|
||||
if !ret {
|
||||
log.Error("AccessToken is not carried")
|
||||
services.ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return
|
||||
}
|
||||
|
||||
_, err := dborm.XormUpdateSessionShakeTime(token)
|
||||
if err != nil {
|
||||
log.Error("Uri is invalid")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package sm
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
var (
|
||||
// Get OMC local time
|
||||
UriOMCLocalTime = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/OMC/objectType/time"
|
||||
|
||||
CustomUriOMCLocalTime = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/OMC/objectType/time"
|
||||
)
|
||||
|
||||
type OMCLocalTime struct {
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳 (单位:毫秒)
|
||||
TimeZone int `json:"timeZone"` // 本地时区偏移(单位:秒)
|
||||
}
|
||||
|
||||
func GetOMCLocalTime(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetOMCLocalTime processing... ")
|
||||
|
||||
// _, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Http request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
t := time.Now()
|
||||
_, offset := t.Zone()
|
||||
|
||||
localTime := OMCLocalTime{
|
||||
Timestamp: t.UnixMilli(),
|
||||
TimeZone: offset,
|
||||
}
|
||||
response := services.DataResponse{
|
||||
Data: localTime,
|
||||
}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
var dbConfig = config.GetYamlConfig().Database
|
||||
|
||||
func DatabaseWhoreBackup() {
|
||||
// MySQL数据库连接信息
|
||||
sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Name)
|
||||
db, err := sql.Open("mysql", sqlStr)
|
||||
if err != nil {
|
||||
log.Error("Failed to connect to database:", err)
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// 备份SQL文件路径
|
||||
backupFile := dbConfig.Backup + "/" + "whore_backup_" + dbConfig.Name + ".sql"
|
||||
|
||||
// 执行mysqldump命令进行备份
|
||||
cmd := exec.Command("mysqldump", "-u", dbConfig.User, "-p"+dbConfig.Password, "-h", dbConfig.Host, dbConfig.Name)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
log.Error("Failed to execute mysqldump command:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 将备份结果写入SQL文件
|
||||
file, err := os.Create(backupFile)
|
||||
if err != nil {
|
||||
log.Error("Failed to create backup file:", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = file.Write(output)
|
||||
if err != nil {
|
||||
log.Error("Failed to write backup file:", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Backup completed successfully.")
|
||||
}
|
||||
|
||||
func DatabaseIncrementalBackup() {
|
||||
// MySQL数据库连接信息
|
||||
sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Name)
|
||||
db, err := sql.Open("mysql", sqlStr)
|
||||
if err != nil {
|
||||
log.Error("Failed to connect to database:", err)
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// 备份SQL文件路径
|
||||
backupFile := dbConfig.Backup + "/" + "incremental_backup_" + dbConfig.Name + ".sql"
|
||||
|
||||
// 上次备份的时间点
|
||||
lastBackupTime := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.Local)
|
||||
|
||||
// 构建增量备份SQL语句
|
||||
query := fmt.Sprintf("SELECT * FROM table WHERE modified_at > '%s'", lastBackupTime.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// 执行查询
|
||||
rows, err := db.Query(query)
|
||||
if err != nil {
|
||||
log.Error("Failed to execute query:", err)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
// 创建增量备份SQL文件
|
||||
file, err := os.Create(backupFile)
|
||||
if err != nil {
|
||||
log.Error("Failed to create backup file:", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 将查询结果写入SQL文件
|
||||
for rows.Next() {
|
||||
var data string
|
||||
err := rows.Scan(&data)
|
||||
if err != nil {
|
||||
log.Error("Failed to scan row:", err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = file.WriteString(data + "\n")
|
||||
if err != nil {
|
||||
log.Error("Failed to write backup file:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Incremental backup completed successfully.")
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,243 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package state
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/log"
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
"github.com/shirou/gopsutil/v4/process"
|
||||
)
|
||||
|
||||
type SysInfo struct {
|
||||
SysCpuPercent uint16 // x%
|
||||
MyCpuPercent uint16 // x%, CPU percent of current proccess
|
||||
|
||||
SysTotalRam uint32 // KB
|
||||
MyUsedRam uint32 // RAM usage of current proccess, KB
|
||||
SysRamUsedPercent uint16 // x%
|
||||
|
||||
PartitionNum byte
|
||||
PartitionInfo []PartitionInfo // usage of each partition
|
||||
}
|
||||
|
||||
const MAX_PARTITION_NUM byte = 32
|
||||
|
||||
func GetSysStat() ([]byte, int) {
|
||||
// Get sys info
|
||||
var sysInfo SysInfo
|
||||
err := GetSysInfo(&sysInfo)
|
||||
if err != nil {
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
//log.Tracef("current sys info: %v", sysInfo)
|
||||
|
||||
// build ems buffer
|
||||
var data []byte = make([]byte, 1024)
|
||||
var len int
|
||||
var i byte
|
||||
binary.BigEndian.PutUint16(data[0:], sysInfo.MyCpuPercent) //x% * 100
|
||||
binary.BigEndian.PutUint16(data[2:], sysInfo.SysCpuPercent) //x% * 100
|
||||
binary.BigEndian.PutUint32(data[4:], sysInfo.SysTotalRam) // KB
|
||||
binary.BigEndian.PutUint32(data[8:], sysInfo.MyUsedRam) // KB
|
||||
binary.BigEndian.PutUint16(data[12:], sysInfo.SysRamUsedPercent) //x% * 100
|
||||
data[14] = sysInfo.PartitionNum
|
||||
for i = 0; i < sysInfo.PartitionNum; i++ {
|
||||
binary.BigEndian.PutUint32(data[15+8*(i):], sysInfo.PartitionInfo[i].Total) // MB
|
||||
binary.BigEndian.PutUint32(data[15+8*(i)+4:], sysInfo.PartitionInfo[i].Used) // MB
|
||||
}
|
||||
len = int(15 + 8*sysInfo.PartitionNum)
|
||||
|
||||
//log.Tracef("current sys stat buf: %v, len: %d", data, len)
|
||||
|
||||
return data, len
|
||||
}
|
||||
|
||||
var pProc *process.Process = nil
|
||||
|
||||
func GetSYsCpuPercent() float64 {
|
||||
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
|
||||
if err != nil {
|
||||
return 0.0
|
||||
} else {
|
||||
return totalPercent[0]
|
||||
}
|
||||
}
|
||||
|
||||
func GetSysInfo(sysInfo *SysInfo) error {
|
||||
// sys cpu percent
|
||||
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
|
||||
if err != nil {
|
||||
sysInfo.SysCpuPercent = 0
|
||||
} else {
|
||||
sysInfo.SysCpuPercent = uint16(totalPercent[0] * 100)
|
||||
}
|
||||
|
||||
if pProc == nil {
|
||||
checkPid := os.Getpid()
|
||||
pProc, err = process.NewProcess(int32(checkPid))
|
||||
if err != nil {
|
||||
log.Tracef("get process info error %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// self cpu percent
|
||||
percent, err := pProc.Percent(0) //(2*time.Second)
|
||||
if err != nil {
|
||||
log.Tracef("get process cpu percent error %v", err)
|
||||
sysInfo.MyCpuPercent = 0
|
||||
} else {
|
||||
sysInfo.MyCpuPercent = uint16(percent * 100)
|
||||
}
|
||||
|
||||
// self RAM(KB)
|
||||
myRam, err := pProc.MemoryInfo()
|
||||
if err != nil {
|
||||
log.Tracef("get self memory info error %v", err)
|
||||
sysInfo.MyUsedRam = 0
|
||||
} else {
|
||||
sysInfo.MyUsedRam = uint32(myRam.RSS / 1024)
|
||||
}
|
||||
|
||||
// system RAM(KB)
|
||||
sysRam, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
log.Tracef("gett sys memory info error %v", err)
|
||||
sysInfo.SysTotalRam = 0
|
||||
sysInfo.SysRamUsedPercent = 0
|
||||
} else {
|
||||
sysInfo.SysTotalRam = uint32(sysRam.Total / 1024)
|
||||
sysInfo.SysRamUsedPercent = uint16(sysRam.UsedPercent * 100)
|
||||
}
|
||||
|
||||
// partition usage
|
||||
GetPartitions(sysInfo)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getProcess() process.Process {
|
||||
checkPid := os.Getpid()
|
||||
ret, _ := process.NewProcess(int32(checkPid))
|
||||
return *ret
|
||||
}
|
||||
|
||||
func GetSystemCpuInfo() {
|
||||
physicalCnt, _ := cpu.Counts(false)
|
||||
logicalCnt, _ := cpu.Counts(true)
|
||||
log.Tracef("physical count:%d logical count:%d", physicalCnt, logicalCnt)
|
||||
|
||||
totalPercent, _ := cpu.Percent(3*time.Second, false) // per cpu is false
|
||||
perPercents, _ := cpu.Percent(3*time.Second, true) // per cpu is true
|
||||
log.Tracef("total percent:%v per percents:%v", totalPercent, perPercents)
|
||||
}
|
||||
|
||||
func GetProcessCpuPercent() {
|
||||
p := getProcess()
|
||||
percent, err := p.Percent(0)
|
||||
if err != nil {
|
||||
log.Tracef("error %v", err)
|
||||
}
|
||||
|
||||
numcpu := runtime.NumCPU()
|
||||
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
|
||||
if percent < 0.0 {
|
||||
log.Tracef("Err CPU Percent of Process: %f, CPU num: %d", percent, numcpu)
|
||||
} else {
|
||||
log.Tracef("get process CPU percent: %f, CPU num: %d", percent, numcpu)
|
||||
}
|
||||
}
|
||||
|
||||
func GetProcessMemoryInfo() {
|
||||
p := getProcess()
|
||||
|
||||
v, err := p.MemoryInfo()
|
||||
if err != nil {
|
||||
log.Tracef("getting memory info error %v", err)
|
||||
}
|
||||
|
||||
log.Tracef("get process memory info %v", v)
|
||||
|
||||
info, _ := mem.VirtualMemory()
|
||||
fmt.Println(info)
|
||||
}
|
||||
|
||||
func GetPartitions(sysInfo *SysInfo) {
|
||||
sysInfo.PartitionNum = 0
|
||||
//sysInfo.PartitionInfo = make([]PartitionInfo, MAX_PARTITION_NUM, MAX_PARTITION_NUM)
|
||||
infos, _ := disk.Partitions(true)
|
||||
for _, info := range infos {
|
||||
GetOnePartitionUsage(info.Mountpoint, sysInfo)
|
||||
if sysInfo.PartitionNum >= MAX_PARTITION_NUM {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetOnePartitionUsage(path string, sysInfo *SysInfo) int {
|
||||
info, err := disk.Usage(path)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
if info.Total <= 0 { // info.Used/(1024 * 1024)MB
|
||||
return 0
|
||||
}
|
||||
var partition PartitionInfo
|
||||
partition.Total = uint32(info.Total / 1024 / 1024)
|
||||
partition.Used = uint32(info.Used / 1024 / 1024)
|
||||
sysInfo.PartitionInfo = append(sysInfo.PartitionInfo, partition)
|
||||
sysInfo.PartitionNum++
|
||||
|
||||
/*data, err := json.MarshalIndent(info, "", " ")
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
fmt.Println(string(data))*/
|
||||
return 1
|
||||
}
|
||||
|
||||
func getOS() string {
|
||||
var osname string
|
||||
if runtime.GOOS == "linux" {
|
||||
osname = "GNU/Linux"
|
||||
}
|
||||
return osname
|
||||
}
|
||||
|
||||
func utsnameToString(unameArray [65]int8) string {
|
||||
var byteString [65]byte
|
||||
var indexLength int
|
||||
for ; unameArray[indexLength] != 0 && indexLength < 65; indexLength++ {
|
||||
byteString[indexLength] = uint8(unameArray[indexLength])
|
||||
}
|
||||
return string(byteString[:indexLength])
|
||||
}
|
||||
|
||||
func getUnameStr() string {
|
||||
var utsname = syscall.Utsname{}
|
||||
err := syscall.Uname(&utsname)
|
||||
if err == nil {
|
||||
name := utsnameToString(utsname.Sysname)
|
||||
node := utsnameToString(utsname.Nodename)
|
||||
release := utsnameToString(utsname.Release)
|
||||
version := utsnameToString(utsname.Version)
|
||||
machine := utsnameToString(utsname.Machine)
|
||||
//domain:= utsnameToString(utsname.Domainname)
|
||||
osName := getOS()
|
||||
return fmt.Sprintf("%s %s %s %s %s %s", name, node,
|
||||
release, version, machine, osName)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package state
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
"github.com/shirou/gopsutil/v4/process"
|
||||
)
|
||||
|
||||
type SysInfo struct {
|
||||
SysCpuPercent uint16 // x%
|
||||
MyCpuPercent uint16 // x%, CPU percent of current proccess
|
||||
|
||||
SysTotalRam uint32 // KB
|
||||
MyUsedRam uint32 // RAM usage of current proccess, KB
|
||||
SysRamUsedPercent uint16 // x%
|
||||
|
||||
PartitionNum byte
|
||||
PartitionInfo []PartitionInfo // usage of each partition
|
||||
}
|
||||
|
||||
const MAX_PARTITION_NUM byte = 32
|
||||
|
||||
func GetSysStat() ([]byte, int) {
|
||||
// Get sys info
|
||||
var sysInfo SysInfo
|
||||
err := GetSysInfo(&sysInfo)
|
||||
if err != nil {
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
//fmt.Printf("current sys info: %v", sysInfo)
|
||||
|
||||
// build ems buffer
|
||||
var data []byte = make([]byte, 1024)
|
||||
var len int
|
||||
var i byte
|
||||
binary.BigEndian.PutUint16(data[0:], sysInfo.MyCpuPercent) //x% * 100
|
||||
binary.BigEndian.PutUint16(data[2:], sysInfo.SysCpuPercent) //x% * 100
|
||||
binary.BigEndian.PutUint32(data[4:], sysInfo.SysTotalRam) // KB
|
||||
binary.BigEndian.PutUint32(data[8:], sysInfo.MyUsedRam) // KB
|
||||
binary.BigEndian.PutUint16(data[12:], sysInfo.SysRamUsedPercent) //x% * 100
|
||||
data[14] = sysInfo.PartitionNum
|
||||
for i = 0; i < sysInfo.PartitionNum; i++ {
|
||||
binary.BigEndian.PutUint32(data[15+8*(i):], sysInfo.PartitionInfo[i].Total) // MB
|
||||
binary.BigEndian.PutUint32(data[15+8*(i)+4:], sysInfo.PartitionInfo[i].Used) // MB
|
||||
}
|
||||
len = int(15 + 8*sysInfo.PartitionNum)
|
||||
|
||||
//fmt.Printf("current sys stat buf: %v, len: %d", data, len)
|
||||
|
||||
return data, len
|
||||
}
|
||||
|
||||
var pProc *process.Process = nil
|
||||
|
||||
func GetSYsCpuPercent() float64 {
|
||||
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
|
||||
if err != nil {
|
||||
return 0.0
|
||||
} else {
|
||||
return totalPercent[0]
|
||||
}
|
||||
}
|
||||
|
||||
func GetSysInfo(sysInfo *SysInfo) error {
|
||||
// sys cpu percent
|
||||
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
|
||||
if err != nil {
|
||||
sysInfo.SysCpuPercent = 0
|
||||
} else {
|
||||
sysInfo.SysCpuPercent = uint16(totalPercent[0] * 100)
|
||||
}
|
||||
|
||||
if pProc == nil {
|
||||
checkPid := os.Getpid()
|
||||
pProc, err = process.NewProcess(int32(checkPid))
|
||||
if err != nil {
|
||||
fmt.Printf("get process info error %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// self cpu percent
|
||||
percent, err := pProc.Percent(0) //(2*time.Second)
|
||||
if err != nil {
|
||||
fmt.Printf("get process cpu percent error %v", err)
|
||||
sysInfo.MyCpuPercent = 0
|
||||
} else {
|
||||
sysInfo.MyCpuPercent = uint16(percent * 100)
|
||||
}
|
||||
|
||||
// self RAM(KB)
|
||||
myRam, err := pProc.MemoryInfo()
|
||||
if err != nil {
|
||||
fmt.Printf("get self memory info error %v", err)
|
||||
sysInfo.MyUsedRam = 0
|
||||
} else {
|
||||
sysInfo.MyUsedRam = uint32(myRam.RSS / 1024)
|
||||
}
|
||||
|
||||
// system RAM(KB)
|
||||
sysRam, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
fmt.Printf("gett sys memory info error %v", err)
|
||||
sysInfo.SysTotalRam = 0
|
||||
sysInfo.SysRamUsedPercent = 0
|
||||
} else {
|
||||
sysInfo.SysTotalRam = uint32(sysRam.Total / 1024)
|
||||
sysInfo.SysRamUsedPercent = uint16(sysRam.UsedPercent * 100)
|
||||
}
|
||||
|
||||
// partition usage
|
||||
GetPartitions(sysInfo)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getProcess() process.Process {
|
||||
checkPid := os.Getpid()
|
||||
ret, _ := process.NewProcess(int32(checkPid))
|
||||
return *ret
|
||||
}
|
||||
|
||||
func GetSystemCpuInfo() {
|
||||
physicalCnt, _ := cpu.Counts(false)
|
||||
logicalCnt, _ := cpu.Counts(true)
|
||||
fmt.Printf("physical count:%d logical count:%d\n", physicalCnt, logicalCnt)
|
||||
|
||||
totalPercent, _ := cpu.Percent(3*time.Second, false) // per cpu is false
|
||||
perPercents, _ := cpu.Percent(3*time.Second, true) // per cpu is true
|
||||
fmt.Printf("total percent:%v per percents:%v\n", totalPercent, perPercents)
|
||||
}
|
||||
|
||||
func GetProcessCpuPercent() {
|
||||
p := getProcess()
|
||||
percent, err := p.Percent(0)
|
||||
if err != nil {
|
||||
fmt.Printf("error %v", err)
|
||||
}
|
||||
|
||||
numcpu := runtime.NumCPU()
|
||||
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
|
||||
if percent < 0.0 {
|
||||
fmt.Printf("Err CPU Percent of Process: %f, CPU num: %d", percent, numcpu)
|
||||
} else {
|
||||
fmt.Printf("get process CPU percent: %f, CPU num: %d", percent, numcpu)
|
||||
}
|
||||
}
|
||||
|
||||
func GetProcessMemoryInfo() {
|
||||
p := getProcess()
|
||||
|
||||
v, err := p.MemoryInfo()
|
||||
if err != nil {
|
||||
fmt.Printf("getting memory info error %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("get process memory info %v\n", v)
|
||||
|
||||
info, _ := mem.VirtualMemory()
|
||||
fmt.Println(info)
|
||||
}
|
||||
|
||||
func GetPartitions(sysInfo *SysInfo) {
|
||||
sysInfo.PartitionNum = 0
|
||||
//sysInfo.PartitionInfo = make([]PartitionInfo, MAX_PARTITION_NUM, MAX_PARTITION_NUM)
|
||||
infos, _ := disk.Partitions(true)
|
||||
for _, info := range infos {
|
||||
GetOnePartitionUsage(info.Mountpoint, sysInfo)
|
||||
if sysInfo.PartitionNum >= MAX_PARTITION_NUM {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetOnePartitionUsage(path string, sysInfo *SysInfo) int {
|
||||
info, err := disk.Usage(path)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
if info.Total <= 0 { // info.Used/(1024 * 1024)MB
|
||||
return 0
|
||||
}
|
||||
var partition PartitionInfo
|
||||
partition.Total = uint32(info.Total / 1024 / 1024)
|
||||
partition.Used = uint32(info.Used / 1024 / 1024)
|
||||
sysInfo.PartitionInfo = append(sysInfo.PartitionInfo, partition)
|
||||
sysInfo.PartitionNum++
|
||||
|
||||
/*data, err := json.MarshalIndent(info, "", " ")
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
fmt.Println(string(data))*/
|
||||
return 1
|
||||
}
|
||||
|
||||
func getOS() string {
|
||||
var osname string
|
||||
if runtime.GOOS == "linux" {
|
||||
osname = "GNU/Linux"
|
||||
}
|
||||
return osname
|
||||
}
|
||||
|
||||
func utsnameToString(unameArray [65]int8) string {
|
||||
var byteString [65]byte
|
||||
var indexLength int
|
||||
for ; unameArray[indexLength] != 0 && indexLength < 65; indexLength++ {
|
||||
byteString[indexLength] = uint8(unameArray[indexLength])
|
||||
}
|
||||
return string(byteString[:indexLength])
|
||||
}
|
||||
|
||||
func getUnameStr() string {
|
||||
osInfo, _ := syscall.GetVersion()
|
||||
|
||||
return fmt.Sprintf("Widnows %d", osInfo)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"be.ems/lib/log"
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
)
|
||||
|
||||
func getCpuNumber() int {
|
||||
// 获取CPU信息
|
||||
cpuInfo, err := cpu.Info()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get CPU info: %v", err)
|
||||
return 0
|
||||
}
|
||||
log.Tracef("CPU info: %+v", cpuInfo)
|
||||
return len(cpuInfo)
|
||||
}
|
||||
|
||||
func getTotalMemory() int {
|
||||
// 获取内存信息
|
||||
memInfo, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get memory info: %v", err)
|
||||
return 0
|
||||
}
|
||||
log.Tracef("Memory info: %+v", memInfo)
|
||||
return int(memInfo.Total)
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
package trace
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/run"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
)
|
||||
|
||||
var (
|
||||
UriTraceTaskV1 = config.DefaultUriPrefix + "/traceManagement/v1/subscriptions"
|
||||
UriTraceTask = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/subscriptions"
|
||||
UriTraceRawMsg = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/rawMessage/{id}"
|
||||
UriTraceDecMsg = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/decMessage/{id}" // decode message api
|
||||
|
||||
CustomUriTraceTaskV1 = config.UriPrefix + "/traceManagement/v1/subscriptions"
|
||||
CustomUriTraceTask = config.UriPrefix + "/traceManagement/{apiVersion}/subscriptions"
|
||||
)
|
||||
|
||||
type TraceTask struct {
|
||||
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
||||
TraceType string `json:"traceType"`
|
||||
StartTime string `json:"startTime"`
|
||||
EndTime string `json:"endTime"`
|
||||
Imsi string `json:"imsi"`
|
||||
Msisdn string `json:"msisdn"`
|
||||
SrcIp string `json:"srcIp"`
|
||||
DstIp string `json:"dstIp"`
|
||||
SignalPort int16 `json:"signalPort"`
|
||||
NeType string `json:"neType"`
|
||||
NeId string `json:"neId"`
|
||||
UeIp string `json:"ueIp"`
|
||||
Interfaces []string `json:"interfaces"`
|
||||
NotifyUrl string `json:"notifyUrl" xorm:"-"`
|
||||
Status string `json:"-" xorm:"status"`
|
||||
SuccNEs []string `json:"-" xorm:"succ_nes"`
|
||||
FailNEs []string `json:"-" xorm:"fail_nes"`
|
||||
AccountID string `json:"accountId" xorm:"account_id"`
|
||||
Comment string `json:"comment" xorm:"comment"`
|
||||
UpdateTime string `json:"-" xorm:"-"`
|
||||
}
|
||||
|
||||
var client = resty.New()
|
||||
|
||||
/*
|
||||
func init() {
|
||||
client.SetTimeout(3 * time.Second)
|
||||
}
|
||||
*/
|
||||
|
||||
// Post trace task to NF/NFs
|
||||
func PostTraceTaskToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostTraceTaskToNF processing... ")
|
||||
|
||||
//vars := mux.Vars(r)
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("AccessToken:", token)
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, int64(config.GetYamlConfig().Params.UriMaxLen)))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Trace("body:", string(body))
|
||||
|
||||
traceTask := new(TraceTask)
|
||||
_ = json.Unmarshal(body, traceTask)
|
||||
log.Debug("traceTask:", traceTask)
|
||||
|
||||
var neTypes []string
|
||||
// do not set device
|
||||
if traceTask.NeType == "" {
|
||||
// query neType by interface
|
||||
if len(traceTask.Interfaces) > 0 {
|
||||
err := dborm.XormGetSingleColStringArrayByIn("trace_info", "ne_type", "interface", traceTask.Interfaces, &neTypes)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetSingleCol:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
neTypes = []string{"AMF", "SMF", "UDM", "AUSF", "UPF"}
|
||||
}
|
||||
} else {
|
||||
neTypes = append(neTypes, traceTask.NeType)
|
||||
}
|
||||
log.Debug("neTypes:", neTypes)
|
||||
|
||||
traceTask.Status = "Inactive"
|
||||
_, err = dborm.XormInsertTableOne("trace_task", traceTask)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormInsertTableOne:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
traceTask.NotifyUrl = config.GetYamlConfig().OMC.GtpUri
|
||||
log.Trace("traceTask:", traceTask)
|
||||
|
||||
for _, neType := range neTypes {
|
||||
var neInfos []dborm.NeInfo
|
||||
if traceTask.NeId == "" {
|
||||
err := dborm.XormGetNeInfoByNeType(neType, &neInfos)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetNeInfoByNeType:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, traceTask.NeId)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetNeInfoByNeType:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
neInfos = append(neInfos, *neInfo)
|
||||
}
|
||||
for _, neInfo := range neInfos {
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, UriTraceTaskV1)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
body, _ := json.Marshal(traceTask)
|
||||
log.Debug("body:", string(body))
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Post(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Post:", err)
|
||||
failNE := fmt.Sprintf("%s.%s", neInfo.NeType, neInfo.NeId)
|
||||
traceTask.FailNEs = append(traceTask.FailNEs, failNE)
|
||||
} else {
|
||||
switch resp.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
succNE := fmt.Sprintf("%s.%s", neInfo.NeType, neInfo.NeId)
|
||||
traceTask.SuccNEs = append(traceTask.SuccNEs, succNE)
|
||||
default:
|
||||
log.Warnf("Post return code:%d, message:%s", resp.StatusCode(), string(resp.Body()))
|
||||
failNE := fmt.Sprintf("%s.%s", neInfo.NeType, neInfo.NeId)
|
||||
traceTask.FailNEs = append(traceTask.FailNEs, failNE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(traceTask.SuccNEs) > 0 {
|
||||
traceTask.Status = "Active"
|
||||
_, err = dborm.XormUpdateTableById(traceTask.Id, "trace_task", traceTask)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormUpdateTableById:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
} else {
|
||||
traceTask.Status = "Failed"
|
||||
_, err = dborm.XormUpdateTableById(traceTask.Id, "trace_task", traceTask)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormUpdateTableById:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
err = global.ErrTraceFailedDistributeToNEs
|
||||
log.Error(err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func PutTraceTaskToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PutTraceTaskToNF processing... ")
|
||||
|
||||
//vars := mux.Vars(r)
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("AccessToken:", token)
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, int64(config.GetYamlConfig().Params.UriMaxLen)))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
traceTask := new(TraceTask)
|
||||
_ = json.Unmarshal(body, traceTask)
|
||||
|
||||
traceTask.NotifyUrl = config.GetYamlConfig().OMC.GtpUri
|
||||
log.Debug("traceTask:", traceTask)
|
||||
|
||||
var neTypes []string
|
||||
// do not set device
|
||||
if traceTask.NeType == "" {
|
||||
// query neType by interface
|
||||
if len(traceTask.Interfaces) > 0 {
|
||||
err := dborm.XormGetSingleColStringArrayByIn("trace_info", "ne_type", "interface", traceTask.Interfaces, &neTypes)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetSingleColStringArrayByIn:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
neTypes = []string{"AMF", "SMF", "UDM", "AUSF", "UPF"}
|
||||
}
|
||||
|
||||
} else {
|
||||
neTypes = append(neTypes, traceTask.NeType)
|
||||
}
|
||||
log.Debug("neTypes:", neTypes)
|
||||
|
||||
for _, neType := range neTypes {
|
||||
var neInfos []dborm.NeInfo
|
||||
if traceTask.NeId == "" {
|
||||
err := dborm.XormGetNeInfoByNeType(neType, &neInfos)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetNeInfoByNeType:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, traceTask.NeId)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetNeInfoByNeType:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
neInfos = append(neInfos, *neInfo)
|
||||
}
|
||||
for _, neInfo := range neInfos {
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, UriTraceTaskV1)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
body, _ := json.Marshal(traceTask)
|
||||
log.Debug("body:", string(body))
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Put(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Put:", err)
|
||||
failNE := fmt.Sprintf("%s.%s", neInfo.NeType, neInfo.NeId)
|
||||
traceTask.FailNEs = append(traceTask.FailNEs, failNE)
|
||||
} else {
|
||||
switch resp.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
succNE := fmt.Sprintf("%s.%s", neInfo.NeType, neInfo.NeId)
|
||||
traceTask.SuccNEs = append(traceTask.SuccNEs, succNE)
|
||||
default:
|
||||
log.Warn("Post return code:%d, message:%s", resp.StatusCode(), string(resp.Body()))
|
||||
failNE := fmt.Sprintf("%s.%s", neInfo.NeType, neInfo.NeId)
|
||||
traceTask.FailNEs = append(traceTask.FailNEs, failNE)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if len(traceTask.SuccNEs) > 0 {
|
||||
traceTask.Status = "Active"
|
||||
_, err = dborm.XormUpdateTableById(traceTask.Id, "trace_task", traceTask)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormUpdateTableById:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
} else {
|
||||
traceTask.Status = "Failed"
|
||||
_, err = dborm.XormUpdateTableById(traceTask.Id, "trace_task", traceTask)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormUpdateTableById:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
err = global.ErrTraceFailedDistributeToNEs
|
||||
log.Error(err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteTraceTaskToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("DeleteTraceTaskToNF processing... ")
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("AccessToken:", token)
|
||||
|
||||
vars := r.URL.Query()
|
||||
ids, ok := vars["id"]
|
||||
if !ok || len(ids) == 0 {
|
||||
err := global.ErrTraceNotCarriedTaskID
|
||||
log.Error(err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("ids:", ids)
|
||||
|
||||
for _, id := range ids {
|
||||
log.Debug("id:", id)
|
||||
|
||||
var succNes []string
|
||||
err := dborm.XormGetColStringArrayByWhere("trace_task", "succ_nes", fmt.Sprintf("id=%s", id), &succNes)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetSingleColStringArrayByWhere:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("succNes:", succNes)
|
||||
nes := new([]string)
|
||||
if len(succNes) > 0 {
|
||||
_ = json.Unmarshal([]byte(succNes[0]), nes)
|
||||
}
|
||||
log.Debug("nes:", nes)
|
||||
|
||||
for _, ne := range *nes {
|
||||
i := strings.Index(ne, ".")
|
||||
neType := ne[0:i]
|
||||
neId := ne[i+1:]
|
||||
log.Debugf("ne:%s neType:%s neId:%s", ne, neType, neId)
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s?id=%s", hostUri, UriTraceTaskV1, id)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
_, err = client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Delete(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Delete:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err = dborm.XormDeleteDataByWhere(fmt.Sprintf("id=%s", id), "trace_task")
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormDeleteDataByWhere:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
func GetRawMessage(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetRawMessage processing... ")
|
||||
|
||||
}
|
||||
|
||||
func ParseRawMsg2Html(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ParseRawMsg2Html processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
idStr := vars["id"]
|
||||
id, _ := strconv.Atoi(idStr)
|
||||
|
||||
traceData, err := dborm.XormGetTraceData(id)
|
||||
if err != nil {
|
||||
log.Error("Failed to dborm.XormGetTraceRawMsg:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("traceData:", traceData)
|
||||
filePath := traceData.DecMsg
|
||||
if traceData.DecMsg == "" {
|
||||
htmlFile := fmt.Sprintf("traceDecMessage-%d-%d.html", traceData.TaskID, traceData.ID)
|
||||
filePath = config.GetYamlConfig().OMC.FrontTraceDir + "/" + htmlFile
|
||||
command := fmt.Sprintf("/usr/local/omc/bin/data2html -f %s -t %d -i N%d -d %x", filePath, traceData.Timestamp, traceData.IfType, traceData.RawMsg)
|
||||
out, err := run.ExecCmd(command, "/")
|
||||
log.Tracef("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Errorf("Faile to ipdate2html:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
exist, err := global.FilePathExists(filePath)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to stat:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
if !exist {
|
||||
err = errors.New(string(strings.ReplaceAll(string(out), "\n", "")))
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
traceData.DecMsg = filePath
|
||||
_, err = dborm.XormUpdateTraceData(id, traceData)
|
||||
if err != nil {
|
||||
log.Errorf("Faile to XormUpdateTraceData:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
services.ResponseHtmlContent(w, http.StatusOK, filePath)
|
||||
}
|
||||
@@ -0,0 +1,763 @@
|
||||
package ue
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
tokenConst "be.ems/src/framework/constants/token"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// AmfNBInfo AMF的NodeB信息
|
||||
type AmfNBInfo struct {
|
||||
ID string `json:"id"` //NodeB ID
|
||||
Name string `json:"name"` // NodeB name
|
||||
Address string `json:"address"` // 基站地址
|
||||
UENum int `jons:"ueNum"` // UE数量
|
||||
}
|
||||
|
||||
// SmfUENum SMF在线用户数
|
||||
type SmfUENum struct {
|
||||
UENum int `json:"ueNum"` // 当前在线用户数
|
||||
}
|
||||
|
||||
// SmfUEInfo SMF在线用户信息
|
||||
type SmfUEInfo struct {
|
||||
IMSI string `json:"imsi"`
|
||||
MSISDN string `json:"msisdn"`
|
||||
RatType string `json:"ratType"`
|
||||
PduSessionInfo []struct {
|
||||
PduSessionID int `json:"pduSessionID"`
|
||||
IPv4 string `json:"ipv4"`
|
||||
IPv6 string `json:"ipv6"`
|
||||
Dnn string `json:"dnn"`
|
||||
Tai string `json:"tai"`
|
||||
SstSD string `json:"sstSD"`
|
||||
UpfN3IP string `json:"upfN3IP"`
|
||||
RanN3IP string `json:"ranN3IP"`
|
||||
Activetime string `json:"activeTime"`
|
||||
UpState string `json:"upState"`
|
||||
} `json:"pduSessionInfo"`
|
||||
}
|
||||
|
||||
// ImsUEInfo IMS在线用户信息
|
||||
type ImsUEInfo struct {
|
||||
IMSI string `json:"imsi"`
|
||||
MSISDN string `json:"msisdn"`
|
||||
IMPU string `json:"impu"`
|
||||
Barring int `json:"barring"`
|
||||
RegState int `json:"regState"`
|
||||
Activetime string `json:"activeTime"`
|
||||
}
|
||||
|
||||
// N3iwfUEInfo N3IWF在线用户信息
|
||||
type N3iwfUEInfo struct {
|
||||
IMSI string `json:"imsi"`
|
||||
|
||||
NAI string `json:"nai"`
|
||||
RegState int `json:"regState"`
|
||||
Activetime string `json:"activeTime"`
|
||||
}
|
||||
|
||||
type N3iwfUEData struct {
|
||||
Data []N3iwfUEInfo `json:"data"`
|
||||
}
|
||||
|
||||
var (
|
||||
UriNBInfo = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/nbInfo"
|
||||
UriUEInfo = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueInfo"
|
||||
UriUENum = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueNum"
|
||||
UriPCFUser = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo"
|
||||
UriPCFUserM = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/batch/{number}"
|
||||
UriPCFUserFileImport = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/file/import"
|
||||
UriPCFUserFileExport = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/file/export"
|
||||
UriNSSFAvailableAMFs = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/availableAMFs"
|
||||
UriNSSFSubscriptions = config.DefaultUriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/subscriptions"
|
||||
|
||||
CustomUriNBInfo = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/nbInfo"
|
||||
CustomUriUEInfo = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueInfo"
|
||||
CustomUriUENum = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/ueNum"
|
||||
CustomUriPCFUser = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo"
|
||||
CustomUriPCFUserM = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/batch/{number}"
|
||||
CustomUriPCFUserFileImport = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/file/import"
|
||||
CustomUriPCFUserFileExport = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/pcf/objectType/ueInfo/file/export"
|
||||
CustomUriNSSFAvailableAMFs = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/availableAMFs"
|
||||
CustomUriNSSFSubscriptions = config.UriPrefix + "/ueManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/subscriptions"
|
||||
)
|
||||
|
||||
var client = resty.New()
|
||||
|
||||
func init() {
|
||||
/*
|
||||
client.
|
||||
SetTimeout(10 * time.Second).
|
||||
SetRetryCount(1).
|
||||
SetRetryWaitTime(1 * time.Second).
|
||||
SetRetryMaxWaitTime(2 * time.Second).
|
||||
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
|
||||
return 0, errors.New("quota exceeded")
|
||||
})
|
||||
*/
|
||||
client.SetTimeout(500 * time.Millisecond)
|
||||
}
|
||||
|
||||
// Get AvailableAMFs from NSSF
|
||||
func GetAvailableAMFsFromNSSF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetAvailableAMFsFromNSSF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if strings.ToLower(neType) != "nssf" {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
// SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Get system state from NF is failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get Subscriptions from NSSF
|
||||
func GetSubscriptionsFromNSSF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetSubscriptionsFromNSSF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if strings.ToLower(neType) != "nssf" {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
// SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Get system state from NF is failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get UEInfo from NF/NFs
|
||||
func GetUEInfoFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetUEInfoFromNF processing... ")
|
||||
|
||||
neId := ctx.GetQuery(r, "neId")
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
if neType == "" || neId == "" {
|
||||
log.Error("elementTypeValue/neId is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
var response services.MapResponse
|
||||
if neInfo.NeId == neId && neInfo.NeId != "" {
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Get from NF:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
}
|
||||
log.Debug("response:", response)
|
||||
}
|
||||
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
// POST User Info from NF/NFs
|
||||
func PostPCFUserInfo(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostPCFUserInfo processing... ")
|
||||
|
||||
// vars := mux.Vars(r)
|
||||
// neType := vars["elementTypeValue"]
|
||||
// if neType == "" {
|
||||
// services.ResponseNotFound404UriNotExist(w, r)
|
||||
// return
|
||||
// }
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
neType := "PCF"
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
client.SetTimeout(1 * time.Minute)
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
//SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Post(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to post:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// PUT PCF User Info from NF/NFs
|
||||
func PutPCFUserInfo(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PutPCFUserInfo processing... ")
|
||||
|
||||
// vars := mux.Vars(r)
|
||||
// neType := vars["elementTypeValue"]
|
||||
// if neType == "" {
|
||||
// services.ResponseNotFound404UriNotExist(w, r)
|
||||
// return
|
||||
// }
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
neType := "PCF"
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
client.SetTimeout(1 * time.Minute)
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
//SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(body).
|
||||
Put(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to put:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get UEInfo from NF/NFs
|
||||
func DeletePCFUserInfo(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("DeletePCFUserInfo processing... ")
|
||||
|
||||
// vars := mux.Vars(r)
|
||||
// neType := vars["elementTypeValue"]
|
||||
// if neType == "" {
|
||||
// services.ResponseNotFound404UriNotExist(w, r)
|
||||
// return
|
||||
// }
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
neType := "PCF"
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
//SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Delete(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to delete:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
w.WriteHeader(resp.StatusCode())
|
||||
w.Write(resp.Body())
|
||||
// var response services.MapResponse
|
||||
// _ = json.Unmarshal(resp.Body(), &response)
|
||||
// services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get UEInfo from SMF
|
||||
func GetUENumFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetUENumFromNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
// SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Get system state from NF is failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get Radio Info from NF/NFs
|
||||
func GetNBInfoFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetNBInfoFromNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
// SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Get system state from NF is failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get Radio Info from NF/NFs
|
||||
func GetNBInfoAllFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetNBInfoAllFromNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
// var neID string
|
||||
neIDs := services.GetParamsArrByName("neId", r)
|
||||
// if len(neIDs) == 1 {
|
||||
// neID = neIDs[0]
|
||||
// } else {
|
||||
// services.ResponseNotFound404UriNotExist(w, r)
|
||||
// return
|
||||
// }
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
//var ret error
|
||||
var statusCode int = 500
|
||||
var dataResponse []services.MapResponse
|
||||
var neInfos []dborm.NeInfo
|
||||
dborm.XormGetNeInfo2(neType, neIDs, &neInfos)
|
||||
for _, neInfo := range neInfos {
|
||||
// neInfo, err := dborm.XormGetNeInfo(neType, neID)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to XormGetNeInfo:", err)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// } else if neInfo == nil {
|
||||
// err := global.ErrCMNotFoundTargetNE
|
||||
// log.Error(global.ErrCMNotFoundTargetNE)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// }
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
//SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to GET:", err)
|
||||
continue
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
} else {
|
||||
switch resp.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
dataResponse = append(dataResponse, response)
|
||||
statusCode = http.StatusOK
|
||||
}
|
||||
}
|
||||
}
|
||||
var response services.DataResponse
|
||||
response.Data = dataResponse
|
||||
services.ResponseWithJson(w, statusCode, response)
|
||||
}
|
||||
|
||||
// Get GetUEInfoFileExportNF from NF/NFs
|
||||
func GetUEInfoFileExportNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetUEInfoFromNF processing... ")
|
||||
|
||||
// vars := mux.Vars(r)
|
||||
// neType := vars["elementTypeValue"]
|
||||
// if neType == "" {
|
||||
// services.ResponseNotFound404UriNotExist(w, r)
|
||||
// return
|
||||
// }
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo("PCF", neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
client.SetTimeout(3 * time.Minute)
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
// SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Get system state from NF is failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
w.WriteHeader(resp.StatusCode())
|
||||
w.Write(resp.Body())
|
||||
// var response services.MapResponse
|
||||
// _ = json.Unmarshal(resp.Body(), &response)
|
||||
// services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
module be.ems
|
||||
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/dlclark/regexp2 v1.11.4
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-resty/resty/v2 v2.14.0
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/gopacket/gopacket v1.2.0
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/gosnmp/gosnmp v1.38.0
|
||||
github.com/jasonlvhit/gocron v0.0.1
|
||||
github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f
|
||||
github.com/linxGnu/gosmpp v0.3.0
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0
|
||||
github.com/metaleap/go-xsd v0.0.0-20180330193350-61f7638f502f
|
||||
github.com/mojocn/base64Captcha v1.3.6
|
||||
github.com/mssola/useragent v1.0.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pkg/sftp v1.13.6
|
||||
github.com/prometheus-community/pro-bing v0.4.1
|
||||
github.com/redis/go-redis/v9 v9.6.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/shirou/gopsutil/v4 v4.24.7
|
||||
github.com/slayercat/GoSNMPServer v0.5.2
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/xuri/excelize/v2 v2.8.1
|
||||
github.com/xuri/xgen v0.0.0-20240722131518-d0691b701898
|
||||
golang.org/x/crypto v0.26.0
|
||||
golang.org/x/net v0.28.0
|
||||
golang.org/x/term v0.23.0
|
||||
golang.org/x/text v0.17.0
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/mysql v1.5.7
|
||||
gorm.io/gorm v1.25.11
|
||||
xorm.io/xorm v1.3.9
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.12.1 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-forks/fsnotify v1.4.7 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.0 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect
|
||||
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/metaleap/go-util v0.0.0-20180330192724-a09253046f73 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/gomega v1.21.1 // indirect
|
||||
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/prometheus/client_golang v1.20.0
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.3 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.23.11 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/sirupsen/logrus v1.4.2 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
||||
github.com/tebeka/strftime v0.1.5 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||
github.com/tklauser/numcpus v0.8.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.9.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
|
||||
golang.org/x/image v0.19.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/tools/cmd/guru v0.1.1-deprecated // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
xorm.io/builder v0.3.13 // indirect
|
||||
)
|
||||
@@ -0,0 +1,590 @@
|
||||
cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4=
|
||||
cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk=
|
||||
cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8=
|
||||
cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s=
|
||||
cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
|
||||
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||
github.com/allegro/bigcache/v3 v3.1.0/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
|
||||
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bytedance/sonic v1.12.1 h1:jWl5Qz1fy7X1ioY74WqO0KjAMtAGQs4sYnjiEBiyX24=
|
||||
github.com/bytedance/sonic v1.12.1/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
|
||||
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a h1:yTfhjWYoPomJkHVArtNHpo36FuOa6Kc2ZjTLvyyQ5Lg=
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a/go.mod h1:lINNCb1ZH3c0uL/9ApaQ8muR4QILsi0STj8Ojt8ZmwU=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 h1:Ghm4eQYC0nEPnSJdVkTrXpu9KtoVCSo1hg7mtI7G9KU=
|
||||
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-forks/fsnotify v1.4.7 h1:lyiU2Wqd4fNGCQDn9dZ4UxSiSFgeU1rM6yIfahk8haY=
|
||||
github.com/go-forks/fsnotify v1.4.7/go.mod h1:AU8mot+GznW5+B4jRJHxKg/2EeO+jMORGRkKSxs0biw=
|
||||
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
|
||||
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-redis/redis v6.15.5+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-resty/resty/v2 v2.14.0 h1:/rhkzsAqGQkozwfKS5aFAbb6TyKd3zyFRWcdRXLPCAU=
|
||||
github.com/go-resty/resty/v2 v2.14.0/go.mod h1:IW6mekUOsElt9C7oWr0XRt9BNSD6D5rr9mhk6NjmNHg=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gopacket/gopacket v1.2.0 h1:eXbzFad7f73P1n2EJHQlsKuvIMJjVXK5tXoSca78I3A=
|
||||
github.com/gopacket/gopacket v1.2.0/go.mod h1:BrAKEy5EOGQ76LSqh7DMAr7z0NNPdczWm2GxCG7+I8M=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gosnmp/gosnmp v1.36.2-0.20231009064202-d306ed5aa998/go.mod h1:O938QjIS4vpSag1UTcnnBq9MfNmimuOGtvQsT1NbErc=
|
||||
github.com/gosnmp/gosnmp v1.38.0 h1:I5ZOMR8kb0DXAFg/88ACurnuwGwYkXWq3eLpJPHMEYc=
|
||||
github.com/gosnmp/gosnmp v1.38.0/go.mod h1:FE+PEZvKrFz9afP9ii1W3cprXuVZ17ypCcyyfYuu5LY=
|
||||
github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx/v4 v4.18.0/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
|
||||
github.com/jasonlvhit/gocron v0.0.1 h1:qTt5qF3b3srDjeOIR4Le1LfeyvoYzJlYpqvG7tJX5YU=
|
||||
github.com/jasonlvhit/gocron v0.0.1/go.mod h1:k9a3TV8VcU73XZxfVHCHWMWF9SOqgoku0/QlY2yvlA4=
|
||||
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
|
||||
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
|
||||
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 h1:0iQektZGS248WXmGIYOwRXSQhD4qn3icjMpuxwO7qlo=
|
||||
github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570/go.mod h1:BLt8L9ld7wVsvEWQbuLrUZnCMnUmLZ+CGDzKtclrTlE=
|
||||
github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f h1:sgUSP4zdTUZYZgAGGtN5Lxk92rK+JUFOwf+FT99EEI4=
|
||||
github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f/go.mod h1:UGmTpUd3rjbtfIpwAPrcfmGf/Z1HS95TATB+m57TPB8=
|
||||
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 h1:Bvq8AziQ5jFF4BHGAEDSqwPW1NJS3XshxbRCxtjFAZc=
|
||||
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042/go.mod h1:TPpsiPUEh0zFL1Snz4crhMlBe60PYxRHr5oFF3rRYg0=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/linxGnu/gosmpp v0.3.0 h1:LL+eY+zc9Ei/YY0po9A6L6SHf8nPyGvqsLddttr/y/4=
|
||||
github.com/linxGnu/gosmpp v0.3.0/go.mod h1:Ba6SULQql3IbF2A5Mtj3DqMKoFbx1pEz/8xyiOh8ZOs=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae h1:dIZY4ULFcto4tAFlj1FYZl8ztUZ13bdq+PLY+NOfbyI=
|
||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0 h1:P64+dmq21hhWdtvZfEAofnvJULaRR1Yib0+PnU669bE=
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0/go.mod h1:KlbGNQ+FhrUNIHUxZdL63t7tl4LaPkZNpUULS8H4uVM=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/metaleap/go-util v0.0.0-20180330192724-a09253046f73 h1:4vKVhAdype/dejZjdQZZXVTKLz8mD0oakKz128L+IFQ=
|
||||
github.com/metaleap/go-util v0.0.0-20180330192724-a09253046f73/go.mod h1:l71/5fppWP5A6nqhcxz6wQAYok6pr/vM2+KHIy50/LY=
|
||||
github.com/metaleap/go-xsd v0.0.0-20180330193350-61f7638f502f h1:eeJGcYszuvOpmuJxeq57LaOO8mJurfjpOHJJMfQSD0s=
|
||||
github.com/metaleap/go-xsd v0.0.0-20180330193350-61f7638f502f/go.mod h1:WK3zEKtwVd/v+NM3lh1ZE6MdDfHsdOFFOD5Ezi4Hutg=
|
||||
github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew03H+Tw=
|
||||
github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E=
|
||||
github.com/mssola/useragent v1.0.0 h1:WRlDpXyxHDNfvZaPEut5Biveq86Ze4o4EMffyMxmH5o=
|
||||
github.com/mssola/useragent v1.0.0/go.mod h1:hz9Cqz4RXusgg1EdI4Al0INR62kP7aPSRNHnpU+b85Y=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/nats.go v1.34.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.21.1 h1:OB/euWYIExnPBohllTicTHmGTrMaqJ67nIu80j0/uEM=
|
||||
github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||
github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c=
|
||||
github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus-community/pro-bing v0.4.1 h1:aMaJwyifHZO0y+h8+icUz0xbToHbia0wdmzdVZ+Kl3w=
|
||||
github.com/prometheus-community/pro-bing v0.4.1/go.mod h1:aLsw+zqCaDoa2RLVVSX3+UiCkBBXTMtZC3c7EkfWnAE=
|
||||
github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
|
||||
github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
|
||||
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
|
||||
github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/crypt v0.19.0/go.mod h1:c6vimRziqqERhtSe0MhIvzE1w54FrCHtrXb5NH/ja78=
|
||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ=
|
||||
github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
|
||||
github.com/shirou/gopsutil/v4 v4.24.7 h1:V9UGTK4gQ8HvcnPKf6Zt3XHyQq/peaekfxpJ2HSocJk=
|
||||
github.com/shirou/gopsutil/v4 v4.24.7/go.mod h1:0uW/073rP7FYLOkvxolUQM5rMOLTNmRXnFKafpb71rw=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/slayercat/GoSNMPServer v0.5.2 h1:IK2d3kz6JoiYHbAZT5H7hrQQRzAD7rxF0iJZxWrV7Ns=
|
||||
github.com/slayercat/GoSNMPServer v0.5.2/go.mod h1:6taMSIwudR+7pKRO6dz2U+xoNccZds8eiMVlEN66fXY=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tebeka/strftime v0.1.5 h1:1NQKN1NiQgkqd/2moD6ySP/5CoZQsKa1d3ZhJ44Jpmg=
|
||||
github.com/tebeka/strftime v0.1.5/go.mod h1:29/OidkoWHdEKZqzyDLUyC+LmgDgdHo4WAFCDT7D/Ig=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
||||
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
|
||||
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
|
||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
|
||||
github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE=
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
github.com/xuri/xgen v0.0.0-20240722131518-d0691b701898 h1:qqSByV3qojIVp1XbrFgD3nO38w1m6aePzmknorZQmRc=
|
||||
github.com/xuri/xgen v0.0.0-20240722131518-d0691b701898/go.mod h1:tBkmlRf8JH62H5fAW+BPFj0LNZWRmKglWTLFfpXhhbg=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
|
||||
go.etcd.io/etcd/client/v2 v2.305.12/go.mod h1:aQ/yhsxMu+Oht1FOupSr60oBvcS9cKXHrzBpDsPTf9E=
|
||||
go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
golang.org/x/arch v0.9.0 h1:ub9TgUInamJ8mrZIGlBG6/4TqWeMszd4N8lNorbrr6k=
|
||||
golang.org/x/arch v0.9.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
|
||||
golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ=
|
||||
golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/tools/cmd/guru v0.1.1-deprecated h1:WiL3pQGXG71u4N45C0eRkE2IcEMAiQdDZ2H5lGspNjM=
|
||||
golang.org/x/tools/cmd/guru v0.1.1-deprecated/go.mod h1:yFb7vixnH8+ByFZ63niwlvUUxyTE/6ULZ6AiEHZwlTk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
|
||||
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||
modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0=
|
||||
modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
|
||||
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.20.4 h1:J8+m2trkN+KKoE7jglyHYYYiaq5xmz2HoHJIiBlRzbE=
|
||||
modernc.org/sqlite v1.20.4/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
||||
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/xorm v1.3.9 h1:TUovzS0ko+IQ1XnNLfs5dqK1cJl1H5uHpWbWqAQ04nU=
|
||||
xorm.io/xorm v1.3.9/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
||||
@@ -0,0 +1,64 @@
|
||||
package aes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
func AesEncrypt(orig string, key string) string {
|
||||
// 转成字节数组
|
||||
origData := []byte(orig)
|
||||
k := []byte(key)
|
||||
|
||||
// 分组秘钥
|
||||
block, _ := aes.NewCipher(k)
|
||||
// 获取秘钥块的长度
|
||||
blockSize := block.BlockSize()
|
||||
// 补全码
|
||||
origData = PKCS7Padding(origData, blockSize)
|
||||
// 加密模式
|
||||
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
|
||||
// 创建数组
|
||||
cryted := make([]byte, len(origData))
|
||||
// 加密
|
||||
blockMode.CryptBlocks(cryted, origData)
|
||||
|
||||
return base64.StdEncoding.EncodeToString(cryted)
|
||||
|
||||
}
|
||||
|
||||
func AesDecrypt(cryted string, key string) string {
|
||||
// 转成字节数组
|
||||
crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
|
||||
k := []byte(key)
|
||||
|
||||
// 分组秘钥
|
||||
block, _ := aes.NewCipher(k)
|
||||
// 获取秘钥块的长度
|
||||
blockSize := block.BlockSize()
|
||||
// 加密模式
|
||||
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
|
||||
// 创建数组
|
||||
orig := make([]byte, len(crytedByte))
|
||||
// 解密
|
||||
blockMode.CryptBlocks(orig, crytedByte)
|
||||
// 去补全码
|
||||
orig = PKCS7UnPadding(orig)
|
||||
return string(orig)
|
||||
}
|
||||
|
||||
// 补码
|
||||
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
|
||||
padding := blocksize - len(ciphertext)%blocksize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
// 去码
|
||||
func PKCS7UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
Vendored
+56
@@ -0,0 +1,56 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
// 创建一个全局的不过期缓存对象
|
||||
var cNoExpiration = cache.New(cache.NoExpiration, cache.NoExpiration)
|
||||
|
||||
// 将数据放入缓存,并设置永不过期
|
||||
func SetLocal(key string, value any) {
|
||||
cNoExpiration.Set(key, value, cache.NoExpiration)
|
||||
}
|
||||
|
||||
// 从缓存中获取数据
|
||||
func GetLocal(key string) (any, bool) {
|
||||
return cNoExpiration.Get(key)
|
||||
}
|
||||
|
||||
// 从缓存中删除数据
|
||||
func DeleteLocal(key string) {
|
||||
cNoExpiration.Delete(key)
|
||||
}
|
||||
|
||||
// 获取指定前缀的所有键
|
||||
func GetLocalKeys(prefix string) []string {
|
||||
prefix = strings.TrimSuffix(prefix, "*")
|
||||
var keys []string
|
||||
for key := range cNoExpiration.Items() {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// 创建一个全局的过期缓存对象
|
||||
var cTTL = cache.New(6*time.Hour, 12*time.Hour)
|
||||
|
||||
// 设置具有过期时间的缓存项
|
||||
func SetLocalTTL(key string, value any, expiration time.Duration) {
|
||||
cTTL.Set(key, value, expiration)
|
||||
}
|
||||
|
||||
// 从缓存中获取数据
|
||||
func GetLocalTTL(key string) (any, bool) {
|
||||
return cTTL.Get(key)
|
||||
}
|
||||
|
||||
// 从缓存中删除数据
|
||||
func DeleteLocalTTL(key string) {
|
||||
cTTL.Delete(key)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var v *viper.Viper
|
||||
|
||||
// 配置文件读取
|
||||
func InitConfig(configFile string) {
|
||||
v = viper.New()
|
||||
|
||||
// 设置配置文件路径
|
||||
v.SetConfigFile(configFile)
|
||||
|
||||
// 读取配置文件
|
||||
err := v.ReadInConfig()
|
||||
if err != nil {
|
||||
fmt.Printf("failure to read configuration file: %v \n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get 获取配置信息
|
||||
//
|
||||
// Get("server.port")
|
||||
func Get(key string) any {
|
||||
return v.Get(key)
|
||||
}
|
||||
|
||||
// AllSettings 全部配置信息
|
||||
func AllSettings() map[string]interface{} {
|
||||
return v.AllSettings()
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package ctx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/constants/token"
|
||||
tokenUtils "be.ems/src/framework/utils/token"
|
||||
"be.ems/src/framework/vo"
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// GetParam 地址栏参数{id}
|
||||
func GetParam(r *http.Request, key string) string {
|
||||
vars := mux.Vars(r)
|
||||
v, ok := vars[key]
|
||||
if ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetQuery 查询参数
|
||||
func GetQuery(r *http.Request, key string) string {
|
||||
return r.URL.Query().Get(key)
|
||||
}
|
||||
|
||||
// GetHeader 请求头参数
|
||||
func GetHeader(r *http.Request, key string) string {
|
||||
return r.Header.Get(key)
|
||||
}
|
||||
|
||||
// QueryMap 查询参数转换Map
|
||||
func QueryMap(r *http.Request) map[string]any {
|
||||
queryValues := r.URL.Query()
|
||||
queryParams := make(map[string]any)
|
||||
for key, values := range queryValues {
|
||||
queryParams[key] = values[0]
|
||||
}
|
||||
return queryParams
|
||||
}
|
||||
|
||||
// ShouldBindQuery 查询参数读取json请求结构团体 &xxx
|
||||
func ShouldBindQuery(r *http.Request, args any) error {
|
||||
queryParams := QueryMap(r)
|
||||
body, err := json.Marshal(queryParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(body, args)
|
||||
}
|
||||
|
||||
// ShouldBindJSON 读取json请求结构团体 &xxx
|
||||
func ShouldBindJSON(r *http.Request, args any) error {
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) // 设置较大的长度,例如 1<<20 (1MB)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(body, args)
|
||||
return err
|
||||
}
|
||||
|
||||
// JSON 相应json数据
|
||||
func JSON(w http.ResponseWriter, code int, data any) {
|
||||
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||
|
||||
response, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
} else {
|
||||
w.WriteHeader(code)
|
||||
w.Write(response)
|
||||
}
|
||||
}
|
||||
|
||||
// 将文件导出到外部下载
|
||||
func FileAttachment(w http.ResponseWriter, r *http.Request, filepath, filename string) {
|
||||
w.Header().Set("Content-Disposition", `attachment; filename=`+url.QueryEscape(filename))
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
http.ServeFile(w, r, filepath)
|
||||
}
|
||||
|
||||
// 将文件上传保存到指定目录
|
||||
// file, handler, err := r.FormFile("file")
|
||||
// SaveUploadedFile uploads the form file to specific dst.
|
||||
func SaveUploadedFile(r *http.Request, dst string) error {
|
||||
// 解析请求中的文件
|
||||
_, handler, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
src, err := handler.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
if err = os.MkdirAll(filepath.Dir(dst), 0750); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, src)
|
||||
return err
|
||||
}
|
||||
|
||||
/// ==== 登录用户信息, 通过中间件后预置入
|
||||
|
||||
// Authorization 解析请求头
|
||||
func Authorization(r *http.Request) string {
|
||||
// Query请求查询
|
||||
if authQuery := r.URL.Query().Get(token.ACCESS_TOKEN); authQuery != "" {
|
||||
return authQuery
|
||||
}
|
||||
// Header请求头
|
||||
if authHeader := r.Header.Get(token.ACCESS_TOKEN); authHeader != "" {
|
||||
return authHeader
|
||||
}
|
||||
|
||||
// Query请求查询
|
||||
if authQuery := r.URL.Query().Get(token.RESPONSE_FIELD); authQuery != "" {
|
||||
return authQuery
|
||||
}
|
||||
// Header请求头
|
||||
authHeader := r.Header.Get(token.HEADER_KEY)
|
||||
if authHeader == "" {
|
||||
return ""
|
||||
}
|
||||
// 拆分 Authorization 请求头,提取 JWT 令牌部分
|
||||
arr := strings.Split(authHeader, token.HEADER_PREFIX)
|
||||
if len(arr) == 2 && arr[1] == "" {
|
||||
return ""
|
||||
}
|
||||
return arr[1]
|
||||
}
|
||||
|
||||
// AcceptLanguage 解析客户端接收语言 zh:中文 en: 英文
|
||||
func AcceptLanguage(r *http.Request) string {
|
||||
preferredLanguage := language.English
|
||||
|
||||
// Query请求查询
|
||||
if v := GetQuery(r, "language"); v != "" {
|
||||
tags, _, _ := language.ParseAcceptLanguage(v)
|
||||
if len(tags) > 0 {
|
||||
preferredLanguage = tags[0]
|
||||
}
|
||||
}
|
||||
// Header请求头
|
||||
if v := GetHeader(r, "Accept-Language"); v != "" {
|
||||
tags, _, _ := language.ParseAcceptLanguage(v)
|
||||
if len(tags) > 0 {
|
||||
preferredLanguage = tags[0]
|
||||
}
|
||||
}
|
||||
|
||||
// 只取前缀
|
||||
lang := preferredLanguage.String()
|
||||
arr := strings.Split(lang, "-")
|
||||
return arr[0]
|
||||
}
|
||||
|
||||
// ContextKey 定义自定义类型作为键
|
||||
type ContextKey string
|
||||
|
||||
// LoginUser 登录用户信息需要Authorize中间件
|
||||
func LoginUser(r *http.Request) (vo.LoginUser, error) {
|
||||
// 获取请求头标识信息
|
||||
tokenStr := Authorization(r)
|
||||
if tokenStr == "" {
|
||||
return vo.LoginUser{}, fmt.Errorf("not token info")
|
||||
}
|
||||
// 验证令牌
|
||||
claims, err := tokenUtils.Verify(tokenStr)
|
||||
if err != nil {
|
||||
return vo.LoginUser{}, fmt.Errorf("token verify fail")
|
||||
}
|
||||
|
||||
// 获取缓存的用户信息
|
||||
loginUser := tokenUtils.LoginUser(claims)
|
||||
if loginUser.UserID == "" {
|
||||
return vo.LoginUser{}, fmt.Errorf("not user info")
|
||||
}
|
||||
|
||||
return loginUser, nil
|
||||
}
|
||||
|
||||
// LoginUserToUserID 登录用户信息-用户ID
|
||||
func LoginUserToUserID(r *http.Request) string {
|
||||
loginUser, err := LoginUser(r)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return loginUser.UserID
|
||||
}
|
||||
|
||||
// LoginUserToUserName 登录用户信息-用户名称
|
||||
func LoginUserToUserName(r *http.Request) string {
|
||||
loginUser, err := LoginUser(r)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return loginUser.User.UserName
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package vo
|
||||
|
||||
import (
|
||||
"be.ems/lib/dborm"
|
||||
)
|
||||
|
||||
// LoginUser 登录用户身份权限信息对象
|
||||
type LoginUser struct {
|
||||
// UserID 用户ID
|
||||
UserID string `json:"userId"`
|
||||
|
||||
// UserName 用户名
|
||||
UserName string `json:"userName"`
|
||||
|
||||
// LoginTime 登录时间时间戳
|
||||
LoginTime int64 `json:"loginTime"`
|
||||
|
||||
// ExpireTime 过期时间时间戳
|
||||
ExpireTime int64 `json:"expireTime"`
|
||||
|
||||
// Permissions 权限列表
|
||||
Permissions []string `json:"permissions"`
|
||||
|
||||
// User 用户信息
|
||||
User dborm.User `json:"user"`
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package result
|
||||
|
||||
const CODE_ERROR = 0
|
||||
const MSG_ERROR = "error"
|
||||
const CODE_SUCCESS = 1
|
||||
const MSG_SUCCESS = "success"
|
||||
|
||||
// CodeMsg 响应结果
|
||||
func CodeMsg(code int, msg string) map[string]any {
|
||||
args := make(map[string]any)
|
||||
args["code"] = code
|
||||
args["msg"] = msg
|
||||
return args
|
||||
}
|
||||
|
||||
// 响应成功结果 map[string]any{}
|
||||
func Ok(v map[string]any) map[string]any {
|
||||
args := make(map[string]any)
|
||||
args["code"] = CODE_SUCCESS
|
||||
args["msg"] = MSG_SUCCESS
|
||||
// v合并到args
|
||||
for key, value := range v {
|
||||
args[key] = value
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
// 响应成功结果信息
|
||||
func OkMsg(msg string) map[string]any {
|
||||
args := make(map[string]any)
|
||||
args["code"] = CODE_SUCCESS
|
||||
args["msg"] = msg
|
||||
return args
|
||||
}
|
||||
|
||||
// 响应成功结果数据
|
||||
func OkData(data any) map[string]any {
|
||||
args := make(map[string]any)
|
||||
args["code"] = CODE_SUCCESS
|
||||
args["msg"] = MSG_SUCCESS
|
||||
args["data"] = data
|
||||
return args
|
||||
}
|
||||
|
||||
// 响应失败结果 map[string]any{}
|
||||
func Err(v map[string]any) map[string]any {
|
||||
args := make(map[string]any)
|
||||
args["code"] = CODE_ERROR
|
||||
args["msg"] = MSG_ERROR
|
||||
// v合并到args
|
||||
for key, value := range v {
|
||||
args[key] = value
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
// 响应失败结果信息
|
||||
func ErrMsg(msg string) map[string]any {
|
||||
args := make(map[string]any)
|
||||
args["code"] = CODE_ERROR
|
||||
args["msg"] = msg
|
||||
return args
|
||||
}
|
||||
|
||||
// 响应失败结果数据
|
||||
func ErrData(data any) map[string]any {
|
||||
args := make(map[string]any)
|
||||
args["code"] = CODE_ERROR
|
||||
args["msg"] = MSG_ERROR
|
||||
args["data"] = data
|
||||
return args
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package dborm
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
// 数据库连接实例
|
||||
var dbgEngine *gorm.DB
|
||||
|
||||
// 载入连接日志配置
|
||||
func loadLogger() logger.Interface {
|
||||
newLogger := logger.New(
|
||||
log.New(os.Stdout, "[GORM] ", log.LstdFlags), // 将日志输出到控制台
|
||||
logger.Config{
|
||||
SlowThreshold: time.Second, // Slow SQL 阈值
|
||||
LogLevel: logger.Info, // 日志级别 Silent不输出任何日志
|
||||
ParameterizedQueries: false, // 参数化查询SQL 用实际值带入?的执行语句
|
||||
Colorful: false, // 彩色日志输出
|
||||
},
|
||||
)
|
||||
return newLogger
|
||||
}
|
||||
|
||||
// 连接数据库实例
|
||||
func InitGormConnect(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam, dbLogging any) error {
|
||||
var dialector gorm.Dialector
|
||||
switch dbType {
|
||||
case "mysql":
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser,
|
||||
dbPassword,
|
||||
dbHost,
|
||||
dbPort,
|
||||
dbName,
|
||||
dbParam,
|
||||
)
|
||||
dialector = mysql.Open(dsn)
|
||||
default:
|
||||
err := fmt.Errorf("invalid type: %s", dbType)
|
||||
return err
|
||||
}
|
||||
opts := &gorm.Config{}
|
||||
// 是否需要日志输出
|
||||
if dbLogging.(bool) {
|
||||
opts.Logger = loadLogger()
|
||||
}
|
||||
// 创建连接
|
||||
db, err := gorm.Open(dialector, opts)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open: %s", err)
|
||||
return err
|
||||
}
|
||||
// 获取底层 SQL 数据库连接
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to connect DB pool: %v", err)
|
||||
return err
|
||||
}
|
||||
// 测试数据库连接
|
||||
err = sqlDB.Ping()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to ping database: %v", err)
|
||||
return err
|
||||
}
|
||||
dbgEngine = db
|
||||
return nil
|
||||
}
|
||||
|
||||
// 关闭数据库实例
|
||||
func Close() {
|
||||
sqlDB, err := dbgEngine.DB()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to connect pool: %s", err)
|
||||
}
|
||||
if err := sqlDB.Close(); err != nil {
|
||||
log.Fatalf("failed to close: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// default gorm DB
|
||||
func DefaultDB() *gorm.DB {
|
||||
return dbgEngine
|
||||
}
|
||||
|
||||
// get sql DB
|
||||
func GCoreDB() (*sql.DB, error) {
|
||||
return dbgEngine.DB()
|
||||
}
|
||||
|
||||
// RawSQL 原生查询语句
|
||||
func RawSQL(sql string, parameters []any) ([]map[string]any, error) {
|
||||
// 数据源
|
||||
db := DefaultDB()
|
||||
|
||||
// 使用正则表达式替换连续的空白字符为单个空格
|
||||
fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ")
|
||||
|
||||
// logger.Infof("sql=> %v", fmtSql)
|
||||
// logger.Infof("parameters=> %v", parameters)
|
||||
|
||||
// 查询结果
|
||||
var rows []map[string]any
|
||||
res := db.Raw(fmtSql, parameters...).Scan(&rows)
|
||||
if res.Error != nil {
|
||||
return nil, res.Error
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// ExecSQL 原生执行语句
|
||||
func ExecSQL(sql string, parameters []any) (int64, error) {
|
||||
// 数据源
|
||||
db := DefaultDB()
|
||||
|
||||
// 使用正则表达式替换连续的空白字符为单个空格
|
||||
fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ")
|
||||
// 执行结果
|
||||
res := db.Exec(fmtSql, parameters...)
|
||||
if res.Error != nil {
|
||||
return 0, res.Error
|
||||
}
|
||||
return res.RowsAffected, nil
|
||||
}
|
||||
|
||||
func CloneTable(srcTable, dstTable string) error {
|
||||
// 获取表 A 的结构信息
|
||||
var columns []gorm.ColumnType
|
||||
dbMigrator := dbgEngine.Migrator()
|
||||
columns, err := dbMigrator.ColumnTypes(srcTable)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to ColumnTypes, %v", err)
|
||||
}
|
||||
|
||||
// 创建表 destination table
|
||||
err = dbMigrator.CreateTable(dstTable)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to CreateTable, %v", err)
|
||||
}
|
||||
// 复制表 src 的字段到表 dst
|
||||
for _, column := range columns {
|
||||
err = dbMigrator.AddColumn(dstTable, column.Name())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to AddColumn, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 复制表 src 的主键和索引到表 dst
|
||||
err = dbMigrator.CreateConstraint(dstTable, "PRIMARY")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to AddColumn, %v", err)
|
||||
}
|
||||
|
||||
err = dbMigrator.CreateConstraint(dstTable, "INDEX")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to AddColumn, %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+1923
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,119 @@
|
||||
package evaluate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"math"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Parse and caculate expression
|
||||
func CalcExpr(expr string, paramValues map[string]any) (float64, error) {
|
||||
// match parameter with ''
|
||||
re := regexp.MustCompile(`'([^']+)'`)
|
||||
matches := re.FindAllStringSubmatch(expr, -1)
|
||||
|
||||
// replace to value
|
||||
for _, match := range matches {
|
||||
paramName := match[1]
|
||||
value, exists := paramValues[paramName]
|
||||
if !exists {
|
||||
return 0, fmt.Errorf("parameter '%s' not found", paramName)
|
||||
}
|
||||
|
||||
expr = strings.Replace(expr, match[0], fmt.Sprintf("%v", value), 1)
|
||||
}
|
||||
|
||||
// expression to evaluate
|
||||
result, err := evalExpr(expr)
|
||||
if math.IsNaN(result) {
|
||||
return 0.0, err
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// eval 解析和计算表达式
|
||||
func evalExpr(expr string) (float64, error) {
|
||||
//fset := token.NewFileSet()
|
||||
node, err := parser.ParseExpr(expr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return evalNode(node)
|
||||
}
|
||||
|
||||
// EvaluateExpr 解析并计算给定的表达式
|
||||
func EvalExpr(expr string, values map[string]any) (float64, error) {
|
||||
// 解析表达式
|
||||
node, err := parser.ParseExpr(expr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 遍历 AST 并替换变量
|
||||
ast.Inspect(node, func(n ast.Node) bool {
|
||||
if ident, ok := n.(*ast.Ident); ok {
|
||||
if val, ok := values[ident.Name]; ok {
|
||||
// 替换标识符为对应值
|
||||
ident.Name = fmt.Sprintf("%v", val)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// 计算表达式
|
||||
return evalNode(node)
|
||||
}
|
||||
|
||||
// eval 递归计算 AST 节点
|
||||
func evalNode(node ast.Node) (float64, error) {
|
||||
var result float64
|
||||
|
||||
switch n := node.(type) {
|
||||
case *ast.BinaryExpr:
|
||||
left, err := evalNode(n.X)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
right, err := evalNode(n.Y)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
switch n.Op {
|
||||
case token.ADD:
|
||||
result = left + right
|
||||
case token.SUB:
|
||||
result = left - right
|
||||
case token.MUL:
|
||||
result = left * right
|
||||
case token.QUO:
|
||||
if right == 0 {
|
||||
return math.NaN(), fmt.Errorf("divisor cannot be zero")
|
||||
}
|
||||
|
||||
result = left / right
|
||||
}
|
||||
case *ast.BasicLit:
|
||||
var err error
|
||||
result, err = strconv.ParseFloat(n.Value, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
case *ast.Ident:
|
||||
val, err := strconv.ParseFloat(n.Name, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("unsupported expression: %s", n.Name)
|
||||
}
|
||||
result = val
|
||||
case *ast.ParenExpr:
|
||||
return evalNode(n.X) // 递归评估括号中的表达式
|
||||
default:
|
||||
return 0, fmt.Errorf("unsupported expression: %T", n)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func GetFileAndDirCount(dir string) (int, int, error) {
|
||||
var fileCount, dirCount int
|
||||
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if path == dir {
|
||||
return nil // 跳过当前目录
|
||||
}
|
||||
if info.IsDir() {
|
||||
dirCount++
|
||||
} else {
|
||||
fileCount++
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return fileCount, dirCount, err
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
type FileInfo struct {
|
||||
FileType string `json:"fileType"` // 文件类型
|
||||
FileMode string `json:"fileMode"` // 文件的权限
|
||||
LinkCount int64 `json:"linkCount"` // 硬链接数目
|
||||
Owner string `json:"owner"` // 所属用户
|
||||
Group string `json:"group"` // 所属组
|
||||
Size string `json:"size"` // 文件的大小
|
||||
ModifiedTime int64 `json:"modifiedTime"` // 最后修改时间,单位为秒
|
||||
FileName string `json:"fileName"` // 文件的名称
|
||||
}
|
||||
|
||||
func GetFileInfo(dir, suffix string) ([]FileInfo, error) {
|
||||
var files []FileInfo
|
||||
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if path == dir {
|
||||
return nil // 跳过当前目录
|
||||
}
|
||||
|
||||
fileType := "file"
|
||||
if info.IsDir() {
|
||||
fileType = "directory"
|
||||
} else if info.Mode()&os.ModeSymlink != 0 {
|
||||
fileType = "symlink"
|
||||
}
|
||||
|
||||
// check if match suffix
|
||||
if (suffix != "" && filepath.Ext(path) == suffix) || suffix == "" {
|
||||
stat, ok := info.Sys().(*syscall.Stat_t)
|
||||
if !ok {
|
||||
return fmt.Errorf("not a syscall.Stat_t")
|
||||
}
|
||||
userInfo, err := user.LookupId(fmt.Sprint(stat.Uid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupInfo, err := user.LookupGroupId(fmt.Sprint(stat.Gid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
humanReadableSize := humanize.Bytes(uint64(info.Size()))
|
||||
fileInfo := FileInfo{
|
||||
FileType: fileType,
|
||||
FileMode: info.Mode().String(),
|
||||
LinkCount: int64(info.Sys().(*syscall.Stat_t).Nlink),
|
||||
Owner: userInfo.Username,
|
||||
Group: groupInfo.Name,
|
||||
Size: strings.ToUpper(humanReadableSize),
|
||||
ModifiedTime: info.ModTime().Unix(),
|
||||
FileName: info.Name(),
|
||||
}
|
||||
files = append(files, fileInfo)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type FileInfo struct {
|
||||
FileType string `json:"fileType"` // file type: file/directory
|
||||
FileMode string `json:"fileMode"` // file mode
|
||||
LinkCount int64 `json:"linkCount"` // link count
|
||||
Owner string `json:"owner"` // owner
|
||||
Group string `json:"group"` // group
|
||||
Size int64 `json:"size"` // size: xx byte
|
||||
ModifiedTime int64 `json:"modifiedTime"` // last modified time:seconds
|
||||
FilePath string `json:"filePath"` // file path
|
||||
FileName string `json:"fileName"` // file name
|
||||
}
|
||||
|
||||
func GetFileInfo(dir, suffix string) ([]FileInfo, error) {
|
||||
var files []FileInfo
|
||||
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if path == dir {
|
||||
return nil // 跳过当前目录
|
||||
}
|
||||
|
||||
fileType := "file"
|
||||
if info.IsDir() {
|
||||
fileType = "directory"
|
||||
} else if info.Mode()&os.ModeSymlink != 0 {
|
||||
fileType = "symlink"
|
||||
}
|
||||
|
||||
// check if match suffix
|
||||
if (suffix != "" && filepath.Ext(path) == suffix) || suffix == "" {
|
||||
fileInfo := FileInfo{
|
||||
FileType: fileType,
|
||||
FileMode: info.Mode().String(),
|
||||
LinkCount: 0,
|
||||
Owner: "-",
|
||||
Group: "-",
|
||||
Size: info.Size(),
|
||||
ModifiedTime: info.ModTime().Unix(),
|
||||
FilePath: dir,
|
||||
FileName: info.Name(),
|
||||
}
|
||||
files = append(files, fileInfo)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package global
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func ExecCmd(command string) ([]byte, error) {
|
||||
cmd := exec.Command("/bin/bash", "-c", command)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func ExecShell(command string) error {
|
||||
in := bytes.NewBuffer(nil)
|
||||
cmd := exec.Command("sh")
|
||||
cmd.Stdin = in
|
||||
in.WriteString(command)
|
||||
in.WriteString("exit\n")
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExecOsCmd(command, os string) ([]byte, error) {
|
||||
var cmd *exec.Cmd
|
||||
switch os {
|
||||
case "Linux":
|
||||
cmd = exec.Command(command)
|
||||
case "Windows":
|
||||
cmd = exec.Command("cmd", "/C", command)
|
||||
}
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package global
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func ExecCmd(command string) ([]byte, error) {
|
||||
cmd := exec.Command("cmd", "/C", command)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func ExecOsCmd(command, os string) ([]byte, error) {
|
||||
var cmd *exec.Cmd
|
||||
switch os {
|
||||
case "Linux":
|
||||
cmd = exec.Command(command)
|
||||
case "Windows":
|
||||
cmd = exec.Command("cmd", "/C", command)
|
||||
}
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package global
|
||||
|
||||
import "errors"
|
||||
|
||||
// 跨package引用的首字母大写
|
||||
const (
|
||||
RequestBodyMaxLen = 2000000
|
||||
ApiVersionV1 = "v1"
|
||||
ApiVersionV2 = "v2"
|
||||
LineBreak = "\n"
|
||||
)
|
||||
|
||||
const (
|
||||
DateTime = "2006-01-02 15:04:05"
|
||||
DateData = "20060102150405"
|
||||
DateHour = "2006010215"
|
||||
DateZone = "2006-01-02 15:04:05 +0000 UTC"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxInt32Number = 2147483647
|
||||
)
|
||||
|
||||
const (
|
||||
MaxLimitData = 1000
|
||||
)
|
||||
|
||||
var (
|
||||
Version string = "-"
|
||||
BuildTime string = "-"
|
||||
GoVer string = "-"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultUriPrefix = "/api/rest"
|
||||
)
|
||||
var (
|
||||
ErrParamsNotAdapted = errors.New("the number of params is not adapted")
|
||||
|
||||
// PM module error message
|
||||
ErrPMNotFoundData = errors.New("not found PM data")
|
||||
|
||||
// CM module error message
|
||||
ErrCMNotFoundTargetNE = errors.New("not found target NE")
|
||||
ErrCMCannotDeleteActiveNE = errors.New("can not delete an active NE")
|
||||
ErrCMInvalidBackupFile = errors.New("invalid backup file")
|
||||
ErrCMNotMatchMD5File = errors.New("md5 not match between file and url")
|
||||
ErrCMNotMatchSignFile = errors.New("digests signatures not match in the file")
|
||||
ErrCMExistSoftwareFile = errors.New("exist the same software package file")
|
||||
ErrCMNotFoundTargetSoftware = errors.New("not found the target software package")
|
||||
ErrCMNotFoundTargetNeVersion = errors.New("not found the target NE version")
|
||||
ErrCMNotFoundRollbackNeVersion = errors.New("not found the rollback NE version")
|
||||
ErrCMUnknownServiceAction = errors.New("unknown service action")
|
||||
ErrCMUnknownInstanceAction = errors.New("unknown instance action")
|
||||
|
||||
ErrCMNotFoundTargetBackupFile = errors.New("not found the target NE backup")
|
||||
ErrCMUnknownSoftwareFormat = errors.New("unknown software package format") // 未知软件包格式
|
||||
|
||||
// TRACE module error message
|
||||
ErrTraceFailedDistributeToNEs = errors.New("failed to distribute trace task to target NEs")
|
||||
ErrTraceNotCarriedTaskID = errors.New("not carried task id in request url")
|
||||
|
||||
// MML module error define
|
||||
ErrMmlInvalidCommandFormat = errors.New("invalid mml command format")
|
||||
)
|
||||
@@ -0,0 +1,728 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
IsIPv4 = "IPv4"
|
||||
IsIPv6 = "IPv6"
|
||||
NonIP = "NonIp"
|
||||
)
|
||||
|
||||
type em struct{}
|
||||
|
||||
func GetPkgName() string {
|
||||
return reflect.TypeOf(em{}).PkgPath()
|
||||
}
|
||||
|
||||
// interface{} change to map[string]interface{}
|
||||
// interface{} data is []interface{}
|
||||
func ListToMap(list interface{}, key string) map[string]interface{} {
|
||||
res := make(map[string]interface{})
|
||||
arr := ToSlice(list)
|
||||
for _, row := range arr {
|
||||
immutable := reflect.ValueOf(row)
|
||||
val := immutable.FieldByName(key).String()
|
||||
res[val] = row
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// interface{} change to []interface{}
|
||||
func ToSlice(arr interface{}) []interface{} {
|
||||
ret := make([]interface{}, 0)
|
||||
v := reflect.ValueOf(arr)
|
||||
if v.Kind() != reflect.Slice {
|
||||
ret = append(ret, arr)
|
||||
return ret
|
||||
}
|
||||
l := v.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
ret = append(ret, v.Index(i).Interface())
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var TodoList []Todo
|
||||
|
||||
type Todo struct {
|
||||
Id int64
|
||||
Item string
|
||||
}
|
||||
|
||||
// JSON序列化方式
|
||||
func jsonStructToMap(TodoList Todo) (map[string]interface{}, error) {
|
||||
// 结构体转json
|
||||
strRet, err := json.Marshal(TodoList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// json转map
|
||||
var mRet map[string]interface{}
|
||||
err1 := json.Unmarshal(strRet, &mRet)
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
return mRet, nil
|
||||
}
|
||||
|
||||
func IsContain(item string, items []string) bool {
|
||||
for _, e := range items {
|
||||
if e == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsContainP(item string, items *[]string, size int) bool {
|
||||
for i := 0; i < size; i++ {
|
||||
if (*items)[i] == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 将字符串 分割成 字符串数组
|
||||
// @s:分割符
|
||||
func SplitString(str string, s string) []string {
|
||||
sa := strings.Split(str, s)
|
||||
return sa
|
||||
}
|
||||
|
||||
// 合并字符串数组
|
||||
func MergeStringArr(a, b []string) []string {
|
||||
var arr []string
|
||||
for _, i := range a {
|
||||
arr = append(arr, i)
|
||||
}
|
||||
for _, j := range b {
|
||||
arr = append(arr, j)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
func UniqueStringArr(m []string) []string {
|
||||
d := make([]string, 0)
|
||||
tempMap := make(map[string]bool, len(m))
|
||||
for _, v := range m { // 以值作为键名
|
||||
if tempMap[v] == false {
|
||||
tempMap[v] = true
|
||||
d = append(d, v)
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// 合并整型数组
|
||||
func MergeArr(a, b []int) []int {
|
||||
var arr []int
|
||||
for _, i := range a {
|
||||
arr = append(arr, i)
|
||||
}
|
||||
for _, j := range b {
|
||||
arr = append(arr, j)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
func UniqueArr(m []int) []int {
|
||||
d := make([]int, 0)
|
||||
tempMap := make(map[int]bool, len(m))
|
||||
for _, v := range m { // 以值作为键名
|
||||
if tempMap[v] == false {
|
||||
tempMap[v] = true
|
||||
d = append(d, v)
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// 升序
|
||||
func AscArr(e []int) []int {
|
||||
sort.Ints(e[:])
|
||||
return e
|
||||
}
|
||||
|
||||
// 降序
|
||||
func DescArr(e []int) []int {
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(e)))
|
||||
return e
|
||||
}
|
||||
|
||||
func MatchRmUID(p string, s string) bool {
|
||||
match, _ := regexp.MatchString(p, s)
|
||||
return match
|
||||
}
|
||||
|
||||
type OrderedMap struct {
|
||||
Order []string
|
||||
Map map[string]interface{}
|
||||
}
|
||||
|
||||
func (om *OrderedMap) UnmarshalJson(b []byte) error {
|
||||
json.Unmarshal(b, &om.Map)
|
||||
|
||||
index := make(map[string]int)
|
||||
for key := range om.Map {
|
||||
om.Order = append(om.Order, key)
|
||||
esc, _ := json.Marshal(key) //Escape the key
|
||||
index[key] = bytes.Index(b, esc)
|
||||
}
|
||||
|
||||
sort.Slice(om.Order, func(i, j int) bool { return index[om.Order[i]] < index[om.Order[j]] })
|
||||
return nil
|
||||
}
|
||||
|
||||
func (om OrderedMap) MarshalJson() ([]byte, error) {
|
||||
var b []byte
|
||||
buf := bytes.NewBuffer(b)
|
||||
buf.WriteRune('{')
|
||||
l := len(om.Order)
|
||||
for i, key := range om.Order {
|
||||
km, err := json.Marshal(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.Write(km)
|
||||
buf.WriteRune(':')
|
||||
vm, err := json.Marshal(om.Map[key])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.Write(vm)
|
||||
if i != l-1 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
fmt.Println(buf.String())
|
||||
}
|
||||
buf.WriteRune('}')
|
||||
fmt.Println(buf.String())
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func GetBodyCopy(r *http.Request) (*bytes.Buffer, error) {
|
||||
// If r.bodyBuf present, return the copy
|
||||
// if r.bodyBuf != nil {
|
||||
// return bytes.NewBuffer(r.bodyBuf.Bytes()), nil
|
||||
// }
|
||||
|
||||
// Maybe body is `io.Reader`.
|
||||
// Note: Resty user have to watchout for large body size of `io.Reader`
|
||||
if r.Body != nil {
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Restore the Body
|
||||
// close(r.Body)
|
||||
r.Body = io.NopCloser(bytes.NewReader(b))
|
||||
|
||||
// Return the Body bytes
|
||||
return bytes.NewBuffer(b), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func UnmarshalBody(r *http.Request, v *interface{}, maxLen int64) error {
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, maxLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(body, v)
|
||||
}
|
||||
|
||||
func SetNotifyUrl(ip string, port uint16, uri string) string {
|
||||
return fmt.Sprintf("http://%s:%d%s", ip, port, uri)
|
||||
}
|
||||
|
||||
func GetIps() (ips []string, err error) {
|
||||
interfaceAddr, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return ips, err
|
||||
}
|
||||
|
||||
for _, address := range interfaceAddr {
|
||||
ipNet, isVailIpNet := address.(*net.IPNet)
|
||||
// 检查ip地址判断是否回环地址
|
||||
if isVailIpNet && !ipNet.IP.IsLoopback() {
|
||||
if ipNet.IP.To4() != nil {
|
||||
ips = append(ips, ipNet.IP.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func GetCurrentTimeSliceIndexByPeriod(t time.Time, period int) int {
|
||||
index := int((t.Hour()*60+t.Minute())/period) - 1
|
||||
if index < 0 {
|
||||
return int(24*60/period) - 1
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
var (
|
||||
cst *time.Location
|
||||
)
|
||||
|
||||
// RFC3339ToDateTime convert rfc3339 value to china standard time layout
|
||||
func RFC3339ToDateTime(value string) (string, error) {
|
||||
ts, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ts.In(cst).Format("2006-01-02 15:04:05"), nil
|
||||
}
|
||||
|
||||
// CreateTimeDir 根据当前时间格式来创建文件夹
|
||||
func CreateTimeDir(fmt string, path string) string {
|
||||
folderName := time.Now().Format(fmt)
|
||||
folderPath := filepath.Join(path, folderName)
|
||||
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
|
||||
// 必须分成两步:先创建文件夹、再修改权限
|
||||
os.Mkdir(folderPath, 0664) //0644也可以os.ModePerm
|
||||
os.Chmod(folderPath, 0664)
|
||||
}
|
||||
return folderPath
|
||||
}
|
||||
|
||||
// CreateDir 根据传入的目录名和路径来创建文件夹
|
||||
func CreateDir(folderName string, path string) string {
|
||||
folderPath := filepath.Join(path, folderName)
|
||||
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
|
||||
// 必须分成两步:先创建文件夹、再修改权限
|
||||
os.MkdirAll(folderPath, 0664) //0644也可以os.ModePerm
|
||||
os.Chmod(folderPath, 0664)
|
||||
}
|
||||
return folderPath
|
||||
}
|
||||
|
||||
func GetFmtTimeString(srcFmt string, timeString string, dstFmt string) string {
|
||||
t, _ := time.ParseInLocation(srcFmt, timeString, time.Local)
|
||||
return t.Format(dstFmt)
|
||||
}
|
||||
|
||||
func GetFileMD5Sum(filePath string) (string, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
md5 := md5.New()
|
||||
_, err = io.Copy(md5, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
md5str := hex.EncodeToString(md5.Sum(nil))
|
||||
|
||||
return md5str, nil
|
||||
}
|
||||
|
||||
// PathExists check path is exist or no
|
||||
func PathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil { //文件或者目录存在
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// PathExists check path is exist or no
|
||||
func FilePathExists(filePath string) (bool, error) {
|
||||
_, err := os.Stat(filePath)
|
||||
if err == nil { //文件或者目录存在
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func GetDayDuration(d1, d2 string) int64 {
|
||||
a, _ := time.Parse("2006-01-02", d1)
|
||||
b, _ := time.Parse("2006-01-02", d2)
|
||||
d := a.Sub(b)
|
||||
|
||||
return (int64)(d.Hours() / 24)
|
||||
}
|
||||
|
||||
func GetSecondsSinceDatetime(datetimeStr string) (int64, error) {
|
||||
loc1, _ := time.LoadLocation("Local")
|
||||
// 解析日期时间字符串为时间对象
|
||||
datetime, err := time.ParseInLocation(time.DateTime, datetimeStr, loc1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 计算时间差
|
||||
duration := time.Since(datetime)
|
||||
|
||||
// 获取时间差的秒数
|
||||
seconds := int64(duration.Seconds())
|
||||
|
||||
return seconds, nil
|
||||
}
|
||||
|
||||
func GetSecondDuration(time1, time2 string) (int64, error) {
|
||||
loc1, _ := time.LoadLocation("Local")
|
||||
// 解析日期时间字符串为时间对象
|
||||
t1, err := time.ParseInLocation(time.DateTime, time1, loc1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t2, err := time.ParseInLocation(time.DateTime, time2, loc1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 计算时间差
|
||||
duration := t2.Sub(t1)
|
||||
|
||||
// 获取时间差的秒数
|
||||
seconds := int64(duration.Seconds())
|
||||
|
||||
return seconds, nil
|
||||
}
|
||||
|
||||
// 0: invalid ip
|
||||
// 4: IPv4
|
||||
// 6: IPv6
|
||||
func ParseIP(s string) (net.IP, int) {
|
||||
ip := net.ParseIP(s)
|
||||
if ip == nil {
|
||||
return nil, 0
|
||||
}
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '.':
|
||||
return ip, 4
|
||||
case ':':
|
||||
return ip, 6
|
||||
}
|
||||
}
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
func BytesCombine1(pBytes ...[]byte) []byte {
|
||||
return bytes.Join(pBytes, []byte(""))
|
||||
}
|
||||
|
||||
func BytesCombine(pBytes ...[]byte) []byte {
|
||||
length := len(pBytes)
|
||||
s := make([][]byte, length)
|
||||
for index := 0; index < length; index++ {
|
||||
s[index] = pBytes[index]
|
||||
}
|
||||
sep := []byte("")
|
||||
return bytes.Join(s, sep)
|
||||
}
|
||||
|
||||
func ParseIPAddr(ip string) string {
|
||||
ipAddr := net.ParseIP(ip)
|
||||
|
||||
if ipAddr != nil {
|
||||
if ipAddr.To4() != nil {
|
||||
return IsIPv4
|
||||
} else {
|
||||
return IsIPv6
|
||||
}
|
||||
}
|
||||
|
||||
return NonIP
|
||||
}
|
||||
|
||||
func CombineHostUri(ip string, port string) string {
|
||||
var hostUri string = ""
|
||||
ipType := ParseIPAddr(ip)
|
||||
if ipType == IsIPv4 {
|
||||
hostUri = fmt.Sprintf("http://%s:%v", ip, port)
|
||||
} else {
|
||||
hostUri = fmt.Sprintf("http://[%s]:%v", ip, port)
|
||||
}
|
||||
|
||||
return hostUri
|
||||
}
|
||||
|
||||
func StructToMap(obj interface{}) map[string]interface{} {
|
||||
objValue := reflect.ValueOf(obj)
|
||||
objType := objValue.Type()
|
||||
|
||||
m := make(map[string]interface{})
|
||||
|
||||
for i := 0; i < objValue.NumField(); i++ {
|
||||
field := objValue.Field(i)
|
||||
fieldName := objType.Field(i).Name
|
||||
|
||||
m[fieldName] = field.Interface()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// ToMap 结构体转为Map[string]interface{}
|
||||
func ToMap(in interface{}, tagName string) (map[string]interface{}, error) {
|
||||
out := make(map[string]interface{})
|
||||
|
||||
v := reflect.ValueOf(in)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Struct { // 非结构体返回错误提示
|
||||
return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v)
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
// 遍历结构体字段
|
||||
// 指定tagName值为map中key;字段值为map中value
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
fi := t.Field(i)
|
||||
if tagValue := fi.Tag.Get(tagName); tagValue != "" {
|
||||
out[tagValue] = v.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func ZipOneFile(srcFile, dstZip string, pathFlag bool) error {
|
||||
zipFile, err := os.Create(dstZip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipFile.Close()
|
||||
|
||||
zipWriter := zip.NewWriter(zipFile)
|
||||
defer zipWriter.Close()
|
||||
|
||||
fileToCompress, err := os.Open(srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fileToCompress.Close()
|
||||
|
||||
var fileInZip io.Writer
|
||||
if pathFlag {
|
||||
fileInZip, err = zipWriter.Create(srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// 获取文件的基本名称
|
||||
fileName := filepath.Base(fileToCompress.Name())
|
||||
fileInZip, err = zipWriter.Create(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = io.Copy(fileInZip, fileToCompress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ZipDirectoryFile(srcDir, dstZip string) error {
|
||||
// Create a new zip file
|
||||
zipfileWriter, err := os.Create(dstZip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipfileWriter.Close()
|
||||
|
||||
// Create a new zip archive
|
||||
zipWriter := zip.NewWriter(zipfileWriter)
|
||||
defer zipWriter.Close()
|
||||
|
||||
// Walk through the directory and add files to the zip archive
|
||||
err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a new file header for the current file
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the name of the file within the zip archive
|
||||
header.Name = filepath.Join(filepath.Base(srcDir), path[len(srcDir):])
|
||||
|
||||
// If the current file is a directory, skip it
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a new file in the zip archive
|
||||
fileWriter, err := zipWriter.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Open the current file
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Copy the contents of the current file to the zip archive
|
||||
_, err = io.Copy(fileWriter, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 判断软件包是rpm或者deb, 1:rpm, 2:deb, 0:unknown format
|
||||
func JudgeRpmOrDebPackage(filePath string) (int, error) {
|
||||
var fileType int = 0
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return fileType, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Read the first 6 bytes of the file
|
||||
header := make([]byte, 6)
|
||||
_, err = file.Read(header)
|
||||
if err != nil {
|
||||
return fileType, err
|
||||
}
|
||||
|
||||
// Check the magic numbers to determine the package format
|
||||
if string(header) == "!<arch>" {
|
||||
fileType = 1
|
||||
} else if string(header) == "!<arch\n" || string(header) == "!<arch\r" {
|
||||
fileType = 2
|
||||
} else {
|
||||
fileType = 0
|
||||
}
|
||||
|
||||
return fileType, nil
|
||||
}
|
||||
|
||||
func isRpmPackage(file *os.File) bool {
|
||||
// RPM packages start with the magic number "EDABEEDB"
|
||||
magic := []byte{0xED, 0xAB, 0xEE, 0xDB}
|
||||
buffer := make([]byte, len(magic))
|
||||
|
||||
_, err := file.Read(buffer)
|
||||
if err != nil && err != io.EOF {
|
||||
return false
|
||||
}
|
||||
|
||||
return string(buffer) == string(magic)
|
||||
}
|
||||
|
||||
func isDebPackage(file *os.File) bool {
|
||||
// DEB packages start with the magic number "!<arch>\n"
|
||||
magic := []byte("!<arch>\n")
|
||||
buffer := make([]byte, len(magic))
|
||||
|
||||
_, err := file.Read(buffer)
|
||||
if err != nil && err != io.EOF {
|
||||
return false
|
||||
}
|
||||
|
||||
return string(buffer) == string(magic)
|
||||
}
|
||||
|
||||
func CheckRpmOrDebPackage(filePath string) (int, error) {
|
||||
var fileType int = 0
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return fileType, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
isRpm := isRpmPackage(file)
|
||||
isDeb := isDebPackage(file)
|
||||
|
||||
if isRpm {
|
||||
fileType = 1
|
||||
} else if isDeb {
|
||||
fileType = 2
|
||||
} else {
|
||||
fileType = 0
|
||||
}
|
||||
|
||||
return fileType, nil
|
||||
}
|
||||
|
||||
func IsRpmOrDebPackage(filePath string) int {
|
||||
var fileType int = 0
|
||||
|
||||
if strings.Contains(filePath, ".rpm") {
|
||||
fileType = 1
|
||||
} else if strings.Contains(filePath, ".deb") {
|
||||
fileType = 2
|
||||
} else {
|
||||
fileType = 0
|
||||
}
|
||||
|
||||
return fileType
|
||||
}
|
||||
|
||||
func RecurseStructToMap(obj any) map[string]any {
|
||||
out := make(map[string]any)
|
||||
v := reflect.ValueOf(obj)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
// 递归函数,用于处理嵌套结构体
|
||||
var recurse func(reflect.Value) any
|
||||
recurse = func(value reflect.Value) any {
|
||||
if value.Kind() == reflect.Struct {
|
||||
nestedOut := make(map[string]any)
|
||||
for i := 0; i < value.NumField(); i++ {
|
||||
nestedOut[value.Type().Field(i).Name] = recurse(value.Field(i))
|
||||
}
|
||||
return nestedOut
|
||||
} else if value.Kind() == reflect.Ptr {
|
||||
return recurse(value.Elem())
|
||||
}
|
||||
return value.Interface()
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
out[t.Field(i).Name] = recurse(f)
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
// logger for omc/ems
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
// LogLevel defines a log level
|
||||
type LogLevel int
|
||||
|
||||
// enum all LogLevels
|
||||
const (
|
||||
// following level also match syslog.Priority value
|
||||
LOG_TRACE LogLevel = iota
|
||||
LOG_DEBUG
|
||||
LOG_INFO
|
||||
LOG_WARN
|
||||
LOG_ERROR
|
||||
LOG_FATAL
|
||||
LOG_OFF
|
||||
LOG_NODEF
|
||||
)
|
||||
|
||||
// default log options
|
||||
const (
|
||||
DEFAULT_LOG_PREFIX = "omc"
|
||||
DEFAULT_LOG_FLAG = log.Lshortfile | log.Ldate | log.Lmicroseconds
|
||||
DEFAULT_LOG_LEVEL = LOG_DEBUG
|
||||
DEFAULT_CALL_DEPTH = 3
|
||||
)
|
||||
|
||||
// Logger is a logger interface
|
||||
type Logger interface {
|
||||
Fatal(v ...interface{})
|
||||
Fatalf(format string, v ...interface{})
|
||||
Error(v ...interface{})
|
||||
Errorf(format string, v ...interface{})
|
||||
Warn(v ...interface{})
|
||||
Warnf(format string, v ...interface{})
|
||||
Info(v ...interface{})
|
||||
Infof(format string, v ...interface{})
|
||||
Debug(v ...interface{})
|
||||
Debugf(format string, v ...interface{})
|
||||
Trace(v ...interface{})
|
||||
Tracef(format string, v ...interface{})
|
||||
|
||||
Level() LogLevel
|
||||
LevelString() string
|
||||
SetLevel(l LogLevel)
|
||||
}
|
||||
|
||||
var _ Logger = DiscardLogger{}
|
||||
|
||||
// DiscardLogger don't log implementation for ILogger
|
||||
type DiscardLogger struct{}
|
||||
|
||||
// Trace empty implementation
|
||||
func (DiscardLogger) Trace(v ...interface{}) {}
|
||||
|
||||
// Tracef empty implementation
|
||||
func (DiscardLogger) Tracef(format string, v ...interface{}) {}
|
||||
|
||||
// Debug empty implementation
|
||||
func (DiscardLogger) Debug(v ...interface{}) {}
|
||||
|
||||
// Debugf empty implementation
|
||||
func (DiscardLogger) Debugf(format string, v ...interface{}) {}
|
||||
|
||||
// Info empty implementation
|
||||
func (DiscardLogger) Info(v ...interface{}) {}
|
||||
|
||||
// Infof empty implementation
|
||||
func (DiscardLogger) Infof(format string, v ...interface{}) {}
|
||||
|
||||
// Warn empty implementation
|
||||
func (DiscardLogger) Warn(v ...interface{}) {}
|
||||
|
||||
// Warnf empty implementation
|
||||
func (DiscardLogger) Warnf(format string, v ...interface{}) {}
|
||||
|
||||
// Error empty implementation
|
||||
func (DiscardLogger) Error(v ...interface{}) {}
|
||||
|
||||
// Errorf empty implementation
|
||||
func (DiscardLogger) Errorf(format string, v ...interface{}) {}
|
||||
|
||||
// Fatal empty implementation
|
||||
func (DiscardLogger) Fatal(v ...interface{}) {}
|
||||
|
||||
// Fatalf empty implementation
|
||||
func (DiscardLogger) Fatalf(format string, v ...interface{}) {}
|
||||
|
||||
// Level empty implementation
|
||||
func (DiscardLogger) Level() LogLevel {
|
||||
return LOG_NODEF
|
||||
}
|
||||
|
||||
// Level empty implementation
|
||||
func (DiscardLogger) LevelString() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetLevel empty implementation
|
||||
func (DiscardLogger) SetLevel(l LogLevel) {}
|
||||
|
||||
// EmsLogger is the default implment of ILogger
|
||||
type EmsLogger struct {
|
||||
TRACE *log.Logger
|
||||
DEBUG *log.Logger
|
||||
INFO *log.Logger
|
||||
WARN *log.Logger
|
||||
ERROR *log.Logger
|
||||
FATAL *log.Logger
|
||||
level LogLevel
|
||||
levelString []string
|
||||
depth int
|
||||
}
|
||||
|
||||
var _ Logger = &EmsLogger{}
|
||||
|
||||
// NewEmsLogger use a special io.Writer as logger output
|
||||
func NewEmsLogger(out io.Writer) *EmsLogger {
|
||||
return NewEmsLogger2(out, DEFAULT_LOG_PREFIX, DEFAULT_LOG_FLAG)
|
||||
}
|
||||
|
||||
// NewEmsLogger2 let you customrize your logger prefix and flag
|
||||
func NewEmsLogger2(out io.Writer, prefix string, flag int) *EmsLogger {
|
||||
return NewEmsLogger3(out, prefix, flag, DEFAULT_LOG_LEVEL)
|
||||
}
|
||||
|
||||
// NewEmsLogger3 let you customrize your logger prefix and flag and logLevel
|
||||
func NewEmsLogger3(out io.Writer, prefix string, flag int, l LogLevel) *EmsLogger {
|
||||
return &EmsLogger{
|
||||
TRACE: log.New(out, fmt.Sprintf("[%s] [trace] ", prefix), flag),
|
||||
DEBUG: log.New(out, fmt.Sprintf("[%s] [debug] ", prefix), flag),
|
||||
INFO: log.New(out, fmt.Sprintf("[%s] [info ] ", prefix), flag),
|
||||
WARN: log.New(out, fmt.Sprintf("[%s] [warn ] ", prefix), flag),
|
||||
ERROR: log.New(out, fmt.Sprintf("[%s] [error] ", prefix), flag),
|
||||
FATAL: log.New(out, fmt.Sprintf("[%s] [fatal] ", prefix), flag),
|
||||
level: l,
|
||||
levelString: []string{"trace", "debug", "info", "warn", "error", "fatal"},
|
||||
depth: DEFAULT_CALL_DEPTH,
|
||||
}
|
||||
}
|
||||
|
||||
// Trace implement ILogger
|
||||
func (s *EmsLogger) Trace(v ...interface{}) {
|
||||
if s.level <= LOG_TRACE {
|
||||
_ = s.TRACE.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Tracef implement ILogger
|
||||
func (s *EmsLogger) Tracef(format string, v ...interface{}) {
|
||||
if s.level <= LOG_TRACE {
|
||||
_ = s.TRACE.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Debug implement ILogger
|
||||
func (s *EmsLogger) Debug(v ...interface{}) {
|
||||
if s.level <= LOG_DEBUG {
|
||||
_ = s.DEBUG.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Debugf implement ILogger
|
||||
func (s *EmsLogger) Debugf(format string, v ...interface{}) {
|
||||
if s.level <= LOG_DEBUG {
|
||||
_ = s.DEBUG.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Info implement ILogger
|
||||
func (s *EmsLogger) Info(v ...interface{}) {
|
||||
if s.level <= LOG_INFO {
|
||||
_ = s.INFO.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Infof implement ILogger
|
||||
func (s *EmsLogger) Infof(format string, v ...interface{}) {
|
||||
if s.level <= LOG_INFO {
|
||||
_ = s.INFO.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Warn implement ILogger
|
||||
func (s *EmsLogger) Warn(v ...interface{}) {
|
||||
if s.level <= LOG_WARN {
|
||||
_ = s.WARN.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Warnf implement ILogger
|
||||
func (s *EmsLogger) Warnf(format string, v ...interface{}) {
|
||||
if s.level <= LOG_WARN {
|
||||
_ = s.WARN.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Error implement ILogger
|
||||
func (s *EmsLogger) Error(v ...interface{}) {
|
||||
if s.level <= LOG_ERROR {
|
||||
_ = s.ERROR.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Errorf implement ILogger
|
||||
func (s *EmsLogger) Errorf(format string, v ...interface{}) {
|
||||
if s.level <= LOG_ERROR {
|
||||
_ = s.ERROR.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Warn implement ILogger
|
||||
func (s *EmsLogger) Fatal(v ...interface{}) {
|
||||
if s.level <= LOG_FATAL {
|
||||
_ = s.FATAL.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Warnf implement ILogger
|
||||
func (s *EmsLogger) Fatalf(format string, v ...interface{}) {
|
||||
if s.level <= LOG_FATAL {
|
||||
_ = s.FATAL.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Level implement ILogger
|
||||
func (s *EmsLogger) Level() LogLevel {
|
||||
return s.level
|
||||
}
|
||||
|
||||
// Level implement ILogger
|
||||
func (s *EmsLogger) LevelString() string {
|
||||
return s.levelString[s.level]
|
||||
}
|
||||
|
||||
// SetLevel implement ILogger
|
||||
func (s *EmsLogger) SetLevel(l LogLevel) {
|
||||
s.level = l
|
||||
}
|
||||
|
||||
var Elogger Logger
|
||||
|
||||
func InitLogger(logFile string, period int, count int, prefix string, logLevel LogLevel) io.Writer {
|
||||
|
||||
/*
|
||||
logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
|
||||
logWriter := getLogWriter(logFile, period, count)
|
||||
Elogger = NewEmsLogger3(logWriter, prefix, DEFAULT_LOG_FLAG, logLevel)
|
||||
fmt.Printf("logFile=%s, period=%d, count=%d, prefix=%s, logLevel=%s\n", logFile, period, count, prefix, GetLevelString())
|
||||
return logWriter
|
||||
}
|
||||
|
||||
// Trace implement ILogger
|
||||
func Trace(v ...interface{}) {
|
||||
Elogger.Trace(v...)
|
||||
}
|
||||
|
||||
// Tracef implement ILogger
|
||||
func Tracef(format string, v ...interface{}) {
|
||||
Elogger.Tracef(format, v...)
|
||||
}
|
||||
|
||||
// Debug implement ILogger
|
||||
func Debug(v ...interface{}) {
|
||||
Elogger.Debug(v...)
|
||||
}
|
||||
|
||||
// Debugf implement ILogger
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
Elogger.Debugf(format, v...)
|
||||
}
|
||||
|
||||
// Info implement ILogger
|
||||
func Info(v ...interface{}) {
|
||||
Elogger.Info(v...)
|
||||
}
|
||||
|
||||
// Infof implement ILogger
|
||||
func Infof(format string, v ...interface{}) {
|
||||
Elogger.Infof(format, v...)
|
||||
}
|
||||
|
||||
// Warn implement ILogger
|
||||
func Warn(v ...interface{}) {
|
||||
Elogger.Warn(v...)
|
||||
}
|
||||
|
||||
// Warnf implement ILogger
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
Elogger.Warnf(format, v...)
|
||||
}
|
||||
|
||||
// Error implement ILogger
|
||||
func Error(v ...interface{}) {
|
||||
Elogger.Error(v...)
|
||||
}
|
||||
|
||||
// Errorf implement ILogger
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
Elogger.Errorf(format, v...)
|
||||
}
|
||||
|
||||
// Warn implement ILogger
|
||||
func Fatal(v ...interface{}) {
|
||||
Elogger.Fatal(v...)
|
||||
}
|
||||
|
||||
// Warnf implement ILogger
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
Elogger.Fatalf(format, v...)
|
||||
}
|
||||
|
||||
// Level implement ILogger
|
||||
func GetLevel() LogLevel {
|
||||
return Elogger.Level()
|
||||
}
|
||||
|
||||
// Level implement ILogger
|
||||
func GetLevelString() string {
|
||||
return Elogger.LevelString()
|
||||
}
|
||||
|
||||
// SetLevel implement ILogger
|
||||
func SetLevel(l LogLevel) {
|
||||
Elogger.SetLevel(l)
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
rotatelogs "github.com/lestrrat/go-file-rotatelogs"
|
||||
)
|
||||
|
||||
type WriteSyncer interface {
|
||||
io.Writer
|
||||
Sync() error
|
||||
}
|
||||
|
||||
// 得到LogWriter
|
||||
func getLogWriter(filePath string, period, count int) WriteSyncer {
|
||||
warnIoWriter := getWriter(filePath, period, count)
|
||||
return addSync(warnIoWriter)
|
||||
}
|
||||
|
||||
// 日志文件切割
|
||||
func getWriter(filename string, period, count int) io.Writer {
|
||||
// 保存日志count天,每period小时分割一次日志
|
||||
duration := time.Hour * time.Duration(period)
|
||||
var logfile string
|
||||
if period >= 24 {
|
||||
logfile = filename + "-%Y%m%d"
|
||||
} else {
|
||||
logfile = filename + "-%Y%m%d%H"
|
||||
}
|
||||
hook, err := rotatelogs.New(
|
||||
|
||||
logfile,
|
||||
rotatelogs.WithLinkName(filename),
|
||||
// rotatelogs.WithMaxAge(duration),
|
||||
rotatelogs.WithRotationCount(count),
|
||||
rotatelogs.WithRotationTime(duration),
|
||||
rotatelogs.WithLocation(time.Local),
|
||||
)
|
||||
|
||||
//保存日志30天,每1分钟分割一次日志
|
||||
/*
|
||||
hook, err := rotatelogs.New(
|
||||
filename+"_%Y%m%d%H%M.log",
|
||||
rotatelogs.WithLinkName(filename),
|
||||
rotatelogs.WithMaxAge(time.Hour*24*30),
|
||||
rotatelogs.WithRotationTime(time.Minute*1),
|
||||
)
|
||||
*/
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hook
|
||||
}
|
||||
|
||||
func addSync(w io.Writer) WriteSyncer {
|
||||
switch w := w.(type) {
|
||||
case WriteSyncer:
|
||||
return w
|
||||
default:
|
||||
return writerWrapper{w}
|
||||
}
|
||||
}
|
||||
|
||||
type writerWrapper struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (w writerWrapper) Sync() error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
//go:build !windows && !nacl && !plan9
|
||||
// +build !windows,!nacl,!plan9
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
)
|
||||
|
||||
var _ Logger = &SyslogLogger{}
|
||||
|
||||
// SyslogLogger will be depricated
|
||||
type SyslogLogger struct {
|
||||
w *syslog.Writer
|
||||
}
|
||||
|
||||
// NewSyslogLogger implements Logger
|
||||
func NewSyslogLogger(w *syslog.Writer) *SyslogLogger {
|
||||
return &SyslogLogger{w: w}
|
||||
}
|
||||
|
||||
// Trace log content as Trace
|
||||
func (s *SyslogLogger) Trace(v ...interface{}) {
|
||||
_ = s.w.Trace(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Tracef log content as Trace and format
|
||||
func (s *SyslogLogger) Tracef(format string, v ...interface{}) {
|
||||
_ = s.w.Trace(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Debug log content as Debug
|
||||
func (s *SyslogLogger) Debug(v ...interface{}) {
|
||||
_ = s.w.Debug(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Debugf log content as Debug and format
|
||||
func (s *SyslogLogger) Debugf(format string, v ...interface{}) {
|
||||
_ = s.w.Debug(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Error log content as Error
|
||||
func (s *SyslogLogger) Error(v ...interface{}) {
|
||||
_ = s.w.Err(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Errorf log content as Errorf and format
|
||||
func (s *SyslogLogger) Errorf(format string, v ...interface{}) {
|
||||
_ = s.w.Err(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Info log content as Info
|
||||
func (s *SyslogLogger) Info(v ...interface{}) {
|
||||
_ = s.w.Info(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Infof log content as Infof and format
|
||||
func (s *SyslogLogger) Infof(format string, v ...interface{}) {
|
||||
_ = s.w.Info(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Warn log content as Warn
|
||||
func (s *SyslogLogger) Warn(v ...interface{}) {
|
||||
_ = s.w.Warn(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Warnf log content as Warnf and format
|
||||
func (s *SyslogLogger) Warnf(format string, v ...interface{}) {
|
||||
_ = s.w.Warn(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Fatal log content as Fatal
|
||||
func (s *SyslogLogger) Fatal(v ...interface{}) {
|
||||
_ = s.w.Fatal(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Fatalf log content as Fatalf and format
|
||||
func (s *SyslogLogger) Fatalf(format string, v ...interface{}) {
|
||||
_ = s.w.Fatal(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Level shows log level
|
||||
func (s *SyslogLogger) Level() LogLevel {
|
||||
return LOG_NODEF
|
||||
}
|
||||
|
||||
// SetLevel always return error, as current log/syslog package doesn't allow to set priority level after syslog.Writer created
|
||||
func (s *SyslogLogger) SetLevel(l LogLevel) {}
|
||||
@@ -0,0 +1,79 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
tokenConst "be.ems/src/framework/constants/token"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func LoggerTrace(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Do stuff here
|
||||
log.Trace("Http Trace Info:")
|
||||
log.Trace(" From Host:", r.RemoteAddr)
|
||||
log.Trace(" To Host:", r.Host)
|
||||
log.Debug(" RequestUri:", r.RequestURI)
|
||||
log.Trace(" Method:", r.Method)
|
||||
log.Trace(" Proto:", r.Proto)
|
||||
log.Trace(" ContentLength:", r.ContentLength)
|
||||
log.Trace(" User-Agent:", r.Header.Get("User-Agent"))
|
||||
log.Trace(" Content-Type:", r.Header.Get("Content-Type"))
|
||||
log.Trace(" AccessToken:", r.Header.Get("AccessToken"))
|
||||
log.Trace(" Authorization:", r.Header.Get(tokenConst.HEADER_KEY))
|
||||
log.Trace("Trace End=====")
|
||||
//body, _ := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
// nop-close to ready r.Body !!!
|
||||
//r.Body = ioutil.NopCloser(bytes.NewReader(body))
|
||||
//log.Trace("Body:", string(body))
|
||||
// Call the next handler, which can be another middleware in the chain, or the final handler.
|
||||
// if r.Method == "OPTIONS" {
|
||||
// services.ResponseStatusOK201Accepted(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// 已禁用
|
||||
func OptionProcess(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "OPTIONS" {
|
||||
services.ResponseStatusOK201Accepted(w)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// 已禁用
|
||||
func CheckPermission(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
token := r.Header.Get("AccessToken")
|
||||
vars := mux.Vars(r)
|
||||
management := vars["managedType"]
|
||||
element := vars["elementTypeValue"]
|
||||
object := vars["objectTypeValue"]
|
||||
pack := "*"
|
||||
if token != "" && element != "oauth" {
|
||||
log.Debugf("token:%s, method:%s, management:%s, element:%s, object:%s, pack:%s", token, r.Method, management, element, object, pack)
|
||||
exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), management, element, object, pack)
|
||||
if err != nil {
|
||||
log.Error("Failed to get permission:", err)
|
||||
services.ResponseForbidden403NotPermission(w)
|
||||
return
|
||||
}
|
||||
if !exist {
|
||||
log.Error("Not permission!")
|
||||
services.ResponseForbidden403NotPermission(w)
|
||||
return
|
||||
}
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/utils/date"
|
||||
)
|
||||
|
||||
// LogMML mml操作日志搜集
|
||||
func LogMML(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 读取请求体内容
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// 解析json内参数
|
||||
var bodyArgs map[string]any
|
||||
_ = json.Unmarshal(bytes.Clone(body), &bodyArgs)
|
||||
// 将请求体内容存储在临时缓冲区中
|
||||
buffer := bytes.NewBuffer(body)
|
||||
r.Body = io.NopCloser(buffer)
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
// 收尾存入数据库的参数
|
||||
mmlCmd := bodyArgs["mml"].([]any)[0]
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
timeStr := date.ParseDateToStr(time.Now(), date.YYYY_MM_DD_HH_MM_SS)
|
||||
|
||||
// 响应内容长度和状态码作为结果
|
||||
str := strings.TrimSuffix(fmt.Sprintf("%v", w), "}")
|
||||
strArr := strings.Split(str, " ")
|
||||
size := strArr[1]
|
||||
status := strArr[2]
|
||||
contentType := w.Header().Get("Content-Type")
|
||||
resultStr := fmt.Sprintf(`{"status":"%s","size":"%s","content-type":"%s"}`, status, size, contentType)
|
||||
|
||||
// 用户名
|
||||
username := ctx.LoginUserToUserName(r)
|
||||
// 执行插入
|
||||
sql := "insert into mml_log (user,ip,ne_type,ne_id,mml,result,log_time)values(?,?,?,?,?,?,?)"
|
||||
_, sqlerr := datasource.ExecDB("", sql, []any{username, ipAddr, neType, neId, mmlCmd, resultStr, timeStr})
|
||||
if sqlerr != nil {
|
||||
log.Errorf("insert row : %v", sqlerr.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
Loaded 100 of 494 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user