Procházet zdrojové kódy

1.将原来的 bnt 仓库更名为 bnt1, 原来的 devops 仓库更名为 bnt
2.使用 bnt1 的最新版本(3237867ca3)替换 bnt, bnt1 不再更新
3.旧瓶装新酒, 最大的变化是前端由 layui 更改为 bootstrap v3.4.1

reghao před 5 měsíci
rodič
revize
77746bcc59
100 změnil soubory, kde provedl 3066 přidání a 2259 odebrání
  1. 3 5
      .gitignore
  2. 26 108
      README.md
  3. 3 2
      agent/bin/devopsagent.json
  4. 0 24
      agent/bin/restart.sh
  5. 1 1
      agent/bin/shutdown.sh
  6. 1 1
      agent/bin/start.sh
  7. 15 4
      agent/pom.xml
  8. 114 0
      agent/src/main/java/cn/reghao/bnt/agent/AgentApp.java
  9. 53 0
      agent/src/main/java/cn/reghao/bnt/agent/config/ConfigFile.java
  10. 16 0
      agent/src/main/java/cn/reghao/bnt/agent/config/DagentConfig.java
  11. 41 0
      agent/src/main/java/cn/reghao/bnt/agent/task/ImageCleanTask.java
  12. 95 0
      agent/src/main/java/cn/reghao/bnt/agent/ws/WebSocketListenerImpl.java
  13. 118 0
      agent/src/main/java/cn/reghao/bnt/agent/ws/WsClient.java
  14. 57 0
      agent/src/main/java/cn/reghao/bnt/agent/ws/event/EventCenter.java
  15. 51 0
      agent/src/main/java/cn/reghao/bnt/agent/ws/event/handler/EvtAppDeployHandler.java
  16. 73 0
      agent/src/main/java/cn/reghao/bnt/agent/ws/event/handler/EvtAppStatHandler.java
  17. 0 114
      agent/src/main/java/cn/reghao/devops/agent/AgentApp.java
  18. 0 53
      agent/src/main/java/cn/reghao/devops/agent/config/ConfigFile.java
  19. 0 15
      agent/src/main/java/cn/reghao/devops/agent/config/DagentConfig.java
  20. 0 41
      agent/src/main/java/cn/reghao/devops/agent/task/ImageCleanTask.java
  21. 0 94
      agent/src/main/java/cn/reghao/devops/agent/ws/WebSocketListenerImpl.java
  22. 0 110
      agent/src/main/java/cn/reghao/devops/agent/ws/WsClient.java
  23. 0 57
      agent/src/main/java/cn/reghao/devops/agent/ws/event/EventCenter.java
  24. 0 51
      agent/src/main/java/cn/reghao/devops/agent/ws/event/handler/EvtAppDeployHandler.java
  25. 0 73
      agent/src/main/java/cn/reghao/devops/agent/ws/event/handler/EvtAppStatHandler.java
  26. 284 66
      agent/src/test/java/AgentTest.java
  27. 1 1
      agent/src/test/java/WebSocketClient.java
  28. 2 11
      agent/src/test/java/WebSocketClientHandler.java
  29. 8 2
      common/pom.xml
  30. 18 0
      common/src/main/java/cn/reghao/bnt/common/agent/app/dto/AppInfo.java
  31. 12 0
      common/src/main/java/cn/reghao/bnt/common/agent/app/iface/AppDeploy.java
  32. 20 0
      common/src/main/java/cn/reghao/bnt/common/agent/app/iface/AppStat.java
  33. 28 0
      common/src/main/java/cn/reghao/bnt/common/agent/app/iface/impl/AppDeployImpl.java
  34. 73 0
      common/src/main/java/cn/reghao/bnt/common/agent/app/iface/impl/AppStatImpl.java
  35. 122 0
      common/src/main/java/cn/reghao/bnt/common/agent/app/iface/impl/DockerApp.java
  36. 96 0
      common/src/main/java/cn/reghao/bnt/common/agent/machine/MachineEvent.java
  37. 34 0
      common/src/main/java/cn/reghao/bnt/common/docker/Docker.java
  38. 438 0
      common/src/main/java/cn/reghao/bnt/common/docker/DockerImpl.java
  39. 55 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/Config.java
  40. 20 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/DockerAuth.java
  41. 11 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/ExposedPorts.java
  42. 15 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/Healthcheck.java
  43. 24 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/HostConfig.java
  44. 14 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/Labels.java
  45. 11 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/NetworkingConfig.java
  46. 21 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/RestartPolicy.java
  47. 15 0
      common/src/main/java/cn/reghao/bnt/common/docker/model/Volumes.java
  48. 40 0
      common/src/main/java/cn/reghao/bnt/common/machine/CPU.java
  49. 158 0
      common/src/main/java/cn/reghao/bnt/common/machine/Disk.java
  50. 76 0
      common/src/main/java/cn/reghao/bnt/common/machine/Machine.java
  51. 76 0
      common/src/main/java/cn/reghao/bnt/common/machine/Memory.java
  52. 107 0
      common/src/main/java/cn/reghao/bnt/common/machine/Network.java
  53. 40 0
      common/src/main/java/cn/reghao/bnt/common/machine/OS.java
  54. 8 0
      common/src/main/java/cn/reghao/bnt/common/machine/model/CPUInfo.java
  55. 31 0
      common/src/main/java/cn/reghao/bnt/common/machine/model/DiskInfo.java
  56. 40 0
      common/src/main/java/cn/reghao/bnt/common/machine/model/DiskPartition.java
  57. 28 0
      common/src/main/java/cn/reghao/bnt/common/machine/model/MemoryInfo.java
  58. 27 0
      common/src/main/java/cn/reghao/bnt/common/machine/model/MemoryStat.java
  59. 20 0
      common/src/main/java/cn/reghao/bnt/common/machine/model/NetworkCard.java
  60. 17 0
      common/src/main/java/cn/reghao/bnt/common/msg/MessageSender.java
  61. 9 0
      common/src/main/java/cn/reghao/bnt/common/msg/constant/AppId.java
  62. 9 0
      common/src/main/java/cn/reghao/bnt/common/msg/constant/AppStatOps.java
  63. 21 0
      common/src/main/java/cn/reghao/bnt/common/msg/constant/NodeStatus.java
  64. 20 0
      common/src/main/java/cn/reghao/bnt/common/msg/constant/PackType.java
  65. 26 0
      common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAgentHeartbeat.java
  66. 33 0
      common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAgentStart.java
  67. 21 0
      common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAppDeploy.java
  68. 22 0
      common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAppStat.java
  69. 32 0
      common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAppStatResult.java
  70. 10 0
      common/src/main/java/cn/reghao/bnt/common/msg/event/EvtBuildApp.java
  71. 10 0
      common/src/main/java/cn/reghao/bnt/common/msg/event/EvtBuildAppResult.java
  72. 90 0
      common/src/main/java/cn/reghao/bnt/common/ws/WebSocketListenerImpl.java
  73. 106 0
      common/src/main/java/cn/reghao/bnt/common/ws/WsClient.java
  74. 0 18
      common/src/main/java/cn/reghao/devops/common/agent/app/dto/AppInfo.java
  75. 0 12
      common/src/main/java/cn/reghao/devops/common/agent/app/iface/AppDeploy.java
  76. 0 20
      common/src/main/java/cn/reghao/devops/common/agent/app/iface/AppStat.java
  77. 0 28
      common/src/main/java/cn/reghao/devops/common/agent/app/iface/impl/AppDeployImpl.java
  78. 0 73
      common/src/main/java/cn/reghao/devops/common/agent/app/iface/impl/AppStatImpl.java
  79. 0 122
      common/src/main/java/cn/reghao/devops/common/agent/app/iface/impl/DockerApp.java
  80. 0 96
      common/src/main/java/cn/reghao/devops/common/agent/machine/MachineEvent.java
  81. 0 34
      common/src/main/java/cn/reghao/devops/common/docker/Docker.java
  82. 0 438
      common/src/main/java/cn/reghao/devops/common/docker/DockerImpl.java
  83. 0 55
      common/src/main/java/cn/reghao/devops/common/docker/model/Config.java
  84. 0 20
      common/src/main/java/cn/reghao/devops/common/docker/model/DockerAuth.java
  85. 0 11
      common/src/main/java/cn/reghao/devops/common/docker/model/ExposedPorts.java
  86. 0 15
      common/src/main/java/cn/reghao/devops/common/docker/model/Healthcheck.java
  87. 0 24
      common/src/main/java/cn/reghao/devops/common/docker/model/HostConfig.java
  88. 0 14
      common/src/main/java/cn/reghao/devops/common/docker/model/Labels.java
  89. 0 11
      common/src/main/java/cn/reghao/devops/common/docker/model/NetworkingConfig.java
  90. 0 21
      common/src/main/java/cn/reghao/devops/common/docker/model/RestartPolicy.java
  91. 0 15
      common/src/main/java/cn/reghao/devops/common/docker/model/Volumes.java
  92. 0 33
      common/src/main/java/cn/reghao/devops/common/machine/Cpu.java
  93. 0 87
      common/src/main/java/cn/reghao/devops/common/machine/Disk.java
  94. 0 69
      common/src/main/java/cn/reghao/devops/common/machine/Machine.java
  95. 0 52
      common/src/main/java/cn/reghao/devops/common/machine/Memory.java
  96. 0 27
      common/src/main/java/cn/reghao/devops/common/machine/MemoryStat.java
  97. 0 75
      common/src/main/java/cn/reghao/devops/common/machine/Network.java
  98. 0 30
      common/src/main/java/cn/reghao/devops/common/machine/Os.java
  99. 0 17
      common/src/main/java/cn/reghao/devops/common/msg/MessageSender.java
  100. 0 9
      common/src/main/java/cn/reghao/devops/common/msg/constant/AppId.java

+ 3 - 5
.gitignore

@@ -1,10 +1,8 @@
-
 .idea/
 *.iml
 *target*/
 *logs/
 *.jar
-*.log*
-*git.properties*
-devops_data/
-dependency-reduced-pom.*
+*.log
+git.properties
+dependency-reduced-pom.xml

+ 26 - 108
README.md

@@ -1,5 +1,5 @@
-# devops
-后台使用的 layui 模板来自[这个项目](https://gitee.com/aun/Timo) master 分支的 a806fd0a 版本
+# bnt
+freemarker 模板来自[这个项目](https://github.com/langhsu/mblog) master 分支的 da0aec93 版本
 
 ## 依赖
 - os:Linux
@@ -8,137 +8,55 @@
 - mysql:5.7
 
 ## 模块
-devops 项目模块:
-- agent
-> 监听 127.0.0.1:60001 端口
-> > 监听这个端口的目的是防止系统中同时运行多个 agent 实例
-> 
-> 代理节点, 用于管理机器, 部署应用, 管理应用状态等
-- common
-> 公共依赖
-- deployer
-> 用来部署 mgr 和 agent 的工具
-- logstash
-> 日志收集器
-- mgr
-> 监听 4020 端口
-> > 通过这个端口对外提供 HTTP 服务
-> 
-> 管理节点, 用于管理 agent 节点, 构建部署应用等
-
-### mgr 和 agent
-devops-mgr 和 devops-agent 之间的关系如下图所示:
-![](https://blog.reghao.cn/file/e4fc2c65c2f44374a09dbb916499a5bf.png)
-> agent 和 mgr 之间使用 websocket 进行通信
-> 
-> 每台被管理的机器上都需要且只能一个部署 agent 实例
-> > 在 agent 的配置文件中指定 mgr 的地址
+bnt 项目模块:
+- web
+> 监听 4030 HTTP 端口和 14030 RPC 端口
 >
-> > agent 使用 Linux /etc/machine-id 文件中的字符串作为 machineId 在 mgr 中唯一地标识一台机器
-> > > 如果 VirtualBox 中使用的 vdisk 是通过 clonehd 得到, 那么多台 VM 中 /etc/machine-id 文件的内容是相同的, 此时需要在 VM 中执行 devops/zzz/reset_machine_id.sh 脚本来重置 machine-id
-> 
-> 只能部署一个 mgr 实例
-> > 可以在一个节点上同时部署 mgr 和 agent 实例
+> - console 模块
+> > 作为 [oss](https://git.reghao.cn/reghao/oss) 项目的 oss-console 模块
+> - blog 模块
+> > 一个独立的 blog 服务
+> - devops 模块
+> > 一个独立的 devops 服务
 
 ## 构建部署
 ### pull 项目源码
 ```
 cd ~/Downloads
-git clone https://git.reghao.cn/reghao/devops.git
+git clone https://git.reghao.cn/reghao/bnt.git
 ```
 
 ### 初始化 MySQL
 ```
-cd ~/Downloads/devops/zzz
+cd ~/Downloads/bnt/zzz
 bash db_init.sh
 ```
-> 执行 db_init.sh 会自动创建 devops 项目需要的数据库并初始化数据库表
+> 执行 db_init.sh 会自动创建 bnt 项目需要的数据库并初始化数据库表
 > > 需要自行指定 db_init.sh 脚本中的 host, username, password 等变量值
 
 ### 构建并运行
 ```
-cd ~/Downloads/devops/zzz
+cd ~/Downloads/bnt/zzz
 bash build_jar.sh
 ```
-> 执行 db_init.sh 会自动构建 devops 各应用 jar 包, 并运行 devops-mgr 应用
-> > build_jar.sh 脚本中的 proj_dir 变量默认是 ~/Downloads/devops
+> 执行 db_init.sh 会自动构建并运行 bntweb 应用 jar 包
+> > build_jar.sh 脚本中的 proj_dir 变量默认是 ~/Downloads/bnt
 >
 > mvn 构建默认使用 dev 环境, 所以需要修改 web 模块 resources/application-dev.yml 配置文件中的第三方服务配置
 >
-> 运行 devops-mgr 应用前需要根据环境修改 devops/mgr/bin/devopsmgr.yml 文件中的配置
+> 运行 bntweb 应用前需要根据环境修改 bnt/web/bin/bntweb.yml 文件中的配置
 > > mysql 配置
-> 
-> > app.baseDir 指定 mgr 产生的数据存放的位置
 >
-> 默认执行 devops/mgr/bin 目录中的 start.sh 脚本, 此时使用 devopsmgr.yml 配置文件
-> > 如果要使用 resources/application-dev.yml 配置文件, 则执行 start1.sh 脚本
+> 运行应用
+> > 执行 bnt/web/bin/start.sh 脚本
+> > > 使用 bntweb.yml 外部配置文件
+> >
+> > 执行 bnt/web/bin/start1.sh 脚本
+> > > 根据 mvn 打包选择的 profile, 使用 resources/application-dev.yml 或 resources/application-test.yml 内部配置文件
 
 ### 停止应用
 ```
-cd ~/Downloads/devops/web/bin
+cd ~/Downloads/bnt/web/bin
 bash shutdown.sh
 ```
-> 执行 shutdown.sh 会结束 devops-mgr 应用
-
-## 部署 devops-agent
-- 1.修改 devops/agent/bin/devopsagent.json 文件中的配置
-> mgrAddress 可以是 IP 地址, 也可以是域名
-> > 如果使用域名, 那么 mgrPort 应使用 Nginx 中的配置
-- 2.使用 cd 命令切换到 devops/agent/bin 目录
-- 3.执行 start.sh 脚本
-
-### 部署多节点
-如果要将 devops-mgr 和 devops-agent 部署到多个节点(注意, devops-mgr 只能部署到多个节点中的某个节点), 可以使用 devops-deployer 工具, 它本质上是一个 SFTP/SSH 客户端, 在和节点建立 SSH 连接后, 执行相应的 Shell 命令.
-- 1.使用 devops/zzz/servers2.csv 模板文件
-> 在该文件中填写节点的相应信息, 必须指定密码或私钥文件绝对路径
-- 2.然后根据需要执行 devops/zzz/deploy_mgr.sh 或 devops/zzz/deploy_agent.sh 脚本
-> 首先要设置脚本中 proj_dir, remote_dir 和 server_file 这三个变量的值
-
-## Nginx 配置
-devops-mgr 应用通常是经由 Nginx 反向带来来访问, 并且 Nginx 还需要提供对 websocket 的支持. 
-
-### 支持 websocket
-nginx.conf 文件中配置 websocket:
-```
-map $http_connection $connection_upgrade {
-        "~*Upgrade" $http_connection;
-        default keep-alive;
-    }
-```
-
-### 代理配置
-Nginx 代理配置示例:
-```
-server {
-   listen 80;
-   server_name devops.reghao.cn;
-   access_log off;
-
-   location / {
-      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_pass http://127.0.0.1:4020;
-   }
-   location /ws {
-      proxy_set_header Upgrade $http_upgrade;
-      proxy_set_header Connection $connection_upgrade;
-      proxy_cache off;
-      proxy_http_version 1.1;
-      proxy_buffering off;
-      proxy_read_timeout 100s;
-      proxy_set_header Host $host;
-      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-      proxy_set_header X-Forwarded-Proto $scheme;
-
-      proxy_pass http://127.0.0.1:4020;
-   }
-}
-```
-
-## 使用
-至此, devops 系统已部署并处于运行状态, 你可通过自己域名或直接通过 IP:PORT 访问系统.
-> devops-mgr 中默认只有一个 admin 用户, 帐号和密码分别为 admin 和 123456
-> > 强烈建议首次登录后修改 admin 用户密码
+> 执行 shutdown.sh 会结束 bntweb 应用

+ 3 - 2
agent/bin/devopsagent.json

@@ -1,4 +1,5 @@
 {
-  "mgrAddress": "localhost",
-  "mgrPort": 4020
+  "protocol": "ws",
+  "host": "127.0.0.1",
+  "port": 4030
 }

+ 0 - 24
agent/bin/restart.sh

@@ -1,24 +0,0 @@
-#!/bin/bash
-
-app_dir=`pwd`
-app_name='devops-agent.jar'
-
-pid=`ps aux | grep ${app_name} | grep -v 'grep' | tr -s ' '| cut -d ' ' -f 2`
-echo "process id: "${pid}
-if [[ -z ${pid} ]];
-then
-  echo "process killed"
-else
-  kill -15 ${pid}
-fi
-
-echo "sleep 10s and wait process killed"
-sleep 10
-pid=`ps aux | grep ${app_name} | grep -v 'grep' | tr -s ' '| cut -d ' ' -f 2`
-if [[ -z ${pid} ]];
-then
-  echo "${app_name} has killed, restart now"
-  nohup java -jar ${app_dir}"/"${app_name} ${app_dir}/agent.json > console.log 2>&1 &
-else
-  echo "process ${pid} not killed"
-fi

+ 1 - 1
agent/bin/shutdown.sh

@@ -8,4 +8,4 @@ then
 else
   echo "kill "${app_name}" with pid "${pid}
   kill -15 ${pid}
-fi
+fi

+ 1 - 1
agent/bin/start.sh

@@ -2,4 +2,4 @@
 
 app_dir=`pwd`
 app_name='devops-agent.jar'
-java -jar ${app_dir}"/"${app_name} ${app_dir}/devopsagent.json > console.log 2>&1 &
+java -jar ${app_dir}"/"${app_name} ${app_dir}/devopsagent.json > console.log 2>&1 &

+ 15 - 4
agent/pom.xml

@@ -3,8 +3,8 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>devops</artifactId>
-        <groupId>cn.reghao.devops</groupId>
+        <artifactId>bnt</artifactId>
+        <groupId>cn.reghao.bnt</groupId>
         <version>1.0.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
@@ -22,10 +22,21 @@
 
     <dependencies>
         <dependency>
-            <groupId>cn.reghao.devops</groupId>
+            <groupId>cn.reghao.bnt</groupId>
             <artifactId>common</artifactId>
             <version>1.0.0-SNAPSHOT</version>
         </dependency>
+
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>1.2.3</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.2.3</version>
+        </dependency>
     </dependencies>
 
     <build>
@@ -49,7 +60,7 @@
                 <configuration>
                     <archive>
                         <manifest>
-                            <mainClass>cn.reghao.devops.agent.AgentApp</mainClass>
+                            <mainClass>cn.reghao.bnt.agent.AgentApp</mainClass>
                         </manifest>
                     </archive>
                     <descriptorRefs>

+ 114 - 0
agent/src/main/java/cn/reghao/bnt/agent/AgentApp.java

@@ -0,0 +1,114 @@
+package cn.reghao.bnt.agent;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import cn.reghao.bnt.agent.config.ConfigFile;
+import cn.reghao.bnt.agent.config.DagentConfig;
+import cn.reghao.bnt.agent.task.ImageCleanTask;
+import cn.reghao.bnt.agent.ws.WsClient;
+import cn.reghao.bnt.common.agent.app.iface.AppDeploy;
+import cn.reghao.bnt.common.agent.app.iface.AppStat;
+import cn.reghao.bnt.common.agent.app.iface.impl.AppDeployImpl;
+import cn.reghao.bnt.common.agent.app.iface.impl.AppStatImpl;
+import cn.reghao.bnt.common.agent.app.iface.impl.DockerApp;
+import cn.reghao.bnt.common.docker.Docker;
+import cn.reghao.bnt.common.docker.DockerImpl;
+import cn.reghao.bnt.common.msg.MessageSender;
+import cn.reghao.jutil.jdk.serializer.JsonConverter;
+import cn.reghao.jutil.jdk.string.StringRegexp;
+import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
+import cn.reghao.jutil.jdk.util.SingleInstance;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+public class AgentApp {
+	static MessageSender messageSender;
+	static ScheduledExecutorService scheduler = ThreadPoolWrapper.scheduledThreadPool("heartbeat", 5);
+	static Docker docker = new DockerImpl();
+
+	static void setLogLevel() {
+		LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
+		Logger rootLogger = loggerContext.getLogger("ROOT");
+		rootLogger.setLevel(Level.INFO);
+		//LoggerConfig.initLogger(Appenders.fileAppender());
+	}
+	
+	static boolean tryConnect(String host, int port) {
+		try {
+			boolean isAddress = StringRegexp.matchIPv4Address(host);
+			InetAddress inetAddress;
+			if (isAddress) {
+				inetAddress = InetAddress.getByAddress(host.getBytes(StandardCharsets.UTF_8));
+			} else {
+				inetAddress = InetAddress.getByName(host);
+			}
+
+			InetSocketAddress socketAddress = new InetSocketAddress(inetAddress, port);
+			Socket socket = new Socket();
+			socket.connect(socketAddress);
+			return true;
+		} catch (IOException e) {
+			log.error("尝试建立到 {}:{} 的 Socket 连接失败", host, port);
+		}
+		return false;
+	}
+
+	static MessageSender getMessageSender(DagentConfig dagentConfig) {
+		DockerApp dockerApp = new DockerApp(docker);
+		AppDeploy appDeploy = new AppDeployImpl(dockerApp);
+		AppStat appStat = new AppStatImpl(dockerApp);
+
+		if (tryConnect(dagentConfig.getHost(), dagentConfig.getPort())) {
+			messageSender = new WsClient(dagentConfig, scheduler, appDeploy, appStat);
+			return messageSender;
+		}
+
+		return null;
+	}
+
+	static void shutdownGracefully() {
+		Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook(), "main-shutdown-hook"));
+	}
+
+	static class ShutdownHook implements Runnable {
+		@Override
+		public void run() {
+			messageSender.close();
+			log.info("资源清理完成,结束 devops-agent...");
+		}
+	}
+
+	public static void main(String[] args) {
+		setLogLevel();
+		if (args.length != 1) {
+			log.error("必须指定配置文件...");
+			return;
+		}
+
+		String configFilePath = ConfigFile.configFilePath(args[0], AgentApp.class);
+		DagentConfig dagentConfig = JsonConverter.jsonFileToObject(new File(configFilePath), DagentConfig.class);
+		messageSender = getMessageSender(dagentConfig);
+		if (messageSender == null) {
+			log.error("没有可用的 MessageSender, Agent 结束运行, 具体信息请查看日志");
+			System.exit(-1);
+		} else {
+			messageSender.connect();
+		}
+
+		ImageCleanTask cleanTask = new ImageCleanTask(docker);
+		scheduler.scheduleAtFixedRate(cleanTask, 1, 12, TimeUnit.HOURS);
+		shutdownGracefully();
+		SingleInstance.onlyOne(60001);
+	}
+}

+ 53 - 0
agent/src/main/java/cn/reghao/bnt/agent/config/ConfigFile.java

@@ -0,0 +1,53 @@
+package cn.reghao.bnt.agent.config;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author reghao
+ * @date 2021-03-03 18:47:01
+ */
+@Slf4j
+public class ConfigFile {
+    public static String configFilePath(String arg, Class<?> clazz) {
+        String configFilePath = null;
+        File configFile = new File(arg);
+        if (!configFile.exists()) {
+            if (arg.startsWith("./")) {
+                String filename = arg.replace(".", "")
+                        .replace("/", "");
+                configFilePath = runningHome(clazz) + "/" + filename;
+            } else if (!arg.contains("/")) {
+                configFilePath = runningHome(clazz) + "/" + arg;
+            } else {
+                log.error("相对路径的配置文件必须以 ./configFile 或 configFile 形式指定...");
+            }
+        } else {
+            // 绝对路径
+            configFilePath = arg;
+        }
+        return configFilePath;
+    }
+    
+    /**
+     * jar 文件运行目录
+     *
+     * @param
+     * @return
+     * @date 2021-03-03 下午6:33
+     */
+    public static String runningHome(Class<?> clazz) {
+        URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
+        String jarFilePath = URLDecoder.decode(url.getPath(), StandardCharsets.UTF_8);
+        if (jarFilePath.endsWith(".jar")) {
+            jarFilePath = jarFilePath.substring(0, jarFilePath.lastIndexOf("/") + 1);
+        }
+
+        File file = new File(jarFilePath);
+        return file.getAbsolutePath();
+    }
+}

+ 16 - 0
agent/src/main/java/cn/reghao/bnt/agent/config/DagentConfig.java

@@ -0,0 +1,16 @@
+package cn.reghao.bnt.agent.config;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author reghao
+ * @date 2023-02-23 11:37:32
+ */
+@AllArgsConstructor
+@Getter
+public class DagentConfig {
+    private String protocol;
+    private String host;
+    private int port;
+}

+ 41 - 0
agent/src/main/java/cn/reghao/bnt/agent/task/ImageCleanTask.java

@@ -0,0 +1,41 @@
+package cn.reghao.bnt.agent.task;
+
+import cn.reghao.bnt.common.docker.Docker;
+import com.github.dockerjava.api.command.InspectContainerResponse;
+import com.github.dockerjava.api.model.Image;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author reghao
+ * @date 2024-07-29 16:17:47
+ */
+@Slf4j
+public class ImageCleanTask implements Runnable {
+    private final Docker docker;
+
+    public ImageCleanTask(Docker docker) {
+        this.docker = docker;
+    }
+
+    @Override
+    public void run() {
+        Map<String, Image> map = docker.images().stream()
+                .collect(Collectors.toMap(Image::getId, image -> image));
+
+        List<InspectContainerResponse> list = docker.psAll();
+        for (InspectContainerResponse response : list) {
+            String imageId = response.getImageId();
+            Boolean running = response.getState().getRunning();
+            if (running != null && running) {
+                Image image = map.remove(imageId);
+            }
+        }
+
+        //map.keySet().forEach(docker::imageRm);
+        log.info("定时扫描 docker 镜像和容器");
+    }
+}

+ 95 - 0
agent/src/main/java/cn/reghao/bnt/agent/ws/WebSocketListenerImpl.java

@@ -0,0 +1,95 @@
+package cn.reghao.bnt.agent.ws;
+
+import cn.reghao.bnt.agent.ws.event.EventCenter;
+import cn.reghao.bnt.common.agent.machine.MachineEvent;
+import cn.reghao.jutil.jdk.event.message.EventMessage;
+import cn.reghao.jutil.jdk.serializer.JdkSerializer;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.Response;
+import okhttp3.WebSocket;
+import okhttp3.WebSocketListener;
+import okio.ByteString;
+
+/**
+ * @author reghao
+ * @date 2023-02-23 09:26:50
+ */
+@Slf4j
+public class WebSocketListenerImpl extends WebSocketListener {
+    private final EventCenter eventCenter;
+    private final WsClient wsClient;
+    private final MachineEvent machineEvent;
+
+    public WebSocketListenerImpl(WsClient wsClient, EventCenter eventCenter, MachineEvent machineEvent) {
+        this.eventCenter = eventCenter;
+        this.wsClient = wsClient;
+        this.machineEvent = machineEvent;
+    }
+
+    @Override
+    public void onOpen(WebSocket webSocket, Response response) {
+        log.info("WebSocket 连接成功");
+        wsClient.setConnected(true);
+        wsClient.resetRetryCount();
+
+        machineEvent.agentStart();
+    }
+
+    @Override
+    public void onClosing(WebSocket webSocket, int code, String reason) {
+        log.error("WebSocket 连接被动断开 -> {} - {}", code, reason);
+        wsClient.setConnected(false);
+
+        machineEvent.pauseHeartbeat();
+        if (wsClient.isRetry()) {
+            reconnect();
+        }
+    }
+
+    @Override
+    public void onClosed(WebSocket webSocket, int code, String reason) {
+        log.error("WebSocket 连接主动断开 -> {} - {}", code, reason);
+        wsClient.setConnected(false);
+    }
+
+    @Override
+    public void onFailure(WebSocket webSocket, Throwable throwable, Response response) {
+        log.info("WebSocket 异常事件: {}", throwable.getMessage());
+        wsClient.setConnected(false);
+        if (wsClient.isRetry()) {
+            reconnect();
+        }
+    }
+
+    private void reconnect() {
+        log.info("WebSocket 重连");
+        try {
+            if (wsClient.getRetryCount() > 10) {
+                log.info("WebSocket 重连超过 10 次, 休眠 1 分钟后再尝试");
+                Thread.sleep(60_000);
+                wsClient.resetRetryCount();
+            } else {
+                log.info("休眠 10s 后再尝试重连");
+                Thread.sleep(10_000);
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        wsClient.close0();
+        wsClient.retryCountIncr();
+        wsClient.connect();
+    }
+
+    @Override
+    public void onMessage(WebSocket webSocket, String text) {
+    }
+
+    @Override
+    public void onMessage(WebSocket webSocket, ByteString bytes) {
+        Object object = JdkSerializer.deserialize(bytes.toByteArray());
+        if (object instanceof EventMessage) {
+            EventMessage eventMessage = (EventMessage) object;
+            eventCenter.dispatch(eventMessage);
+        }
+    }
+}

+ 118 - 0
agent/src/main/java/cn/reghao/bnt/agent/ws/WsClient.java

@@ -0,0 +1,118 @@
+package cn.reghao.bnt.agent.ws;
+
+import cn.reghao.bnt.agent.config.DagentConfig;
+import cn.reghao.bnt.agent.ws.event.EventCenter;
+import cn.reghao.bnt.common.agent.app.iface.AppDeploy;
+import cn.reghao.bnt.common.agent.app.iface.AppStat;
+import cn.reghao.bnt.common.agent.machine.MachineEvent;
+import cn.reghao.bnt.common.machine.Machine;
+import cn.reghao.bnt.common.msg.MessageSender;
+import cn.reghao.jutil.jdk.serializer.JdkSerializer;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.WebSocket;
+import okhttp3.WebSocketListener;
+import okio.ByteString;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author reghao
+ * @date 2023-02-23 09:26:50
+ */
+public class WsClient implements MessageSender {
+    private final String url;
+    private WebSocket webSocket;
+    private boolean connected;
+    private final WebSocketListener webSocketListener;
+    private boolean retry;
+    private int retryCount;
+
+    public WsClient(DagentConfig dagentConfig, ScheduledExecutorService scheduler, AppDeploy appDeploy, AppStat appStat) {
+        String protocol = dagentConfig.getProtocol();
+        String host = dagentConfig.getHost();
+        int port = dagentConfig.getPort();
+        this.url = String.format("%s://%s:%s/bgws/agent?token=%s", protocol, host, port, Machine.ID);
+
+        EventCenter eventCenter = new EventCenter(this, appDeploy, appStat);
+        // 每 60s 发送一次心跳
+        int heartbeatInterval = 60;
+        MachineEvent machineEvent = new MachineEvent(this, new Machine(), appStat, scheduler, heartbeatInterval);
+        this.webSocketListener = new WebSocketListenerImpl(this, eventCenter, machineEvent);
+        this.retry = true;
+        this.retryCount = 0;
+        Logger.getLogger(OkHttpClient.class.getName()).setLevel(Level.FINE);
+    }
+
+    public void setRetry(boolean retry) {
+        this.retry = retry;
+    }
+
+    public boolean isRetry() {
+        return retry;
+    }
+
+    public void retryCountIncr() {
+        this.retryCount += 1;
+    }
+
+    public void resetRetryCount() {
+        this.retryCount = 0;
+    }
+
+    public int getRetryCount() {
+        return retryCount;
+    }
+
+    @Override
+    public void connect() {
+        Request request = new Request.Builder()
+                .url(url)
+                .header("Authorization", "Bearer " + Machine.ID)
+                .build();
+
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                //.pingInterval(30, TimeUnit.SECONDS)
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .build();
+
+        if (this.webSocket != null) {
+            this.webSocket.cancel();
+        }
+
+
+        this.webSocket = okHttpClient.newWebSocket(request, webSocketListener);
+    }
+
+    @Override
+    public void setConnected(boolean status) {
+        this.connected = status;
+    }
+
+    @Override
+    public boolean isConnected() {
+        return connected;
+    }
+
+    @Override
+    public void send(String dest, Object message) {
+        if (isConnected()) {
+            byte[] bytes = JdkSerializer.serialize(message);
+            webSocket.send(ByteString.of(bytes));
+        }
+    }
+
+    public void close() {
+        setRetry(false);
+        webSocket.close(1000, "Client Close Connection");
+    }
+
+    public void close0() {
+        webSocket.close(1000, "Client Close Connection");
+    }
+}

+ 57 - 0
agent/src/main/java/cn/reghao/bnt/agent/ws/event/EventCenter.java

@@ -0,0 +1,57 @@
+package cn.reghao.bnt.agent.ws.event;
+
+import cn.reghao.bnt.agent.ws.event.handler.EvtAppDeployHandler;
+import cn.reghao.bnt.agent.ws.event.handler.EvtAppStatHandler;
+import cn.reghao.bnt.common.agent.app.iface.AppDeploy;
+import cn.reghao.bnt.common.agent.app.iface.AppStat;
+import cn.reghao.bnt.common.msg.MessageSender;
+import cn.reghao.bnt.common.msg.event.EvtAppDeploy;
+import cn.reghao.bnt.common.msg.event.EvtAppStat;
+import cn.reghao.jutil.jdk.event.message.Event;
+import cn.reghao.jutil.jdk.event.message.EventMessage;
+import cn.reghao.jutil.jdk.event.router.EventDispatcher;
+import cn.reghao.jutil.jdk.exception.ExceptionUtil;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.management.ManagementFactory;
+
+/**
+ * @author reghao
+ * @date 2023-02-23 09:18:11
+ */
+@Slf4j
+public class EventCenter {
+    private final long startTime;
+    private final EventDispatcher dispatcher;
+
+    public EventCenter(MessageSender messageSender, AppDeploy appDeploy, AppStat appStat) {
+        this.startTime = ManagementFactory.getRuntimeMXBean().getStartTime();
+        this.dispatcher = new EventDispatcher();
+        initDispatcher(messageSender, appDeploy, appStat);
+    }
+
+    private void initDispatcher(MessageSender messageSender, AppDeploy appDeploy, AppStat appStat) {
+        dispatcher.register(EvtAppDeploy.class, new EvtAppDeployHandler(messageSender, appDeploy));
+        dispatcher.register(EvtAppStat.class, new EvtAppStatHandler(messageSender, appStat));
+    }
+
+    public void dispatch(EventMessage eventMessage) {
+        try {
+            long sendTime = eventMessage.getSendTime();
+            if (sendTime < startTime) {
+                log.info("忽略 agent 启动前 mgr 发送的事件...");
+                return;
+            }
+
+            Event event = eventMessage.getEvent();
+            dispatcher.dispatch(event);
+        } catch (Exception e) {
+            String errMsg = e.getMessage();
+            if (e instanceof NullPointerException) {
+                errMsg = ExceptionUtil.stackTrace(e);
+            }
+
+            log.error("处理消息发生异常: {}", errMsg);
+        }
+    }
+}

+ 51 - 0
agent/src/main/java/cn/reghao/bnt/agent/ws/event/handler/EvtAppDeployHandler.java

@@ -0,0 +1,51 @@
+package cn.reghao.bnt.agent.ws.event.handler;
+
+import cn.reghao.bnt.common.agent.app.iface.AppDeploy;
+import cn.reghao.bnt.common.machine.Machine;
+import cn.reghao.bnt.common.msg.MessageSender;
+import cn.reghao.bnt.common.msg.event.EvtAppDeploy;
+import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
+import cn.reghao.jutil.jdk.event.handler.Handler;
+import cn.reghao.jutil.jdk.event.message.Event;
+import cn.reghao.jutil.jdk.event.message.EventMessage;
+import cn.reghao.jutil.jdk.exception.ExceptionUtil;
+import cn.reghao.jutil.jdk.result.Result;
+import cn.reghao.jutil.jdk.result.ResultStatus;
+
+import java.io.IOException;
+
+/**
+ * @author reghao
+ * @date 2023-03-01 10:52:04
+ */
+public class EvtAppDeployHandler extends Handler {
+    private final MessageSender messageSender;
+    private final AppDeploy appDeploy;
+
+    public EvtAppDeployHandler(MessageSender messageSender, AppDeploy appDeploy) {
+        this.messageSender = messageSender;
+        this.appDeploy = appDeploy;
+    }
+
+    @Override
+    public void handle(Event evt) {
+        EvtAppDeploy deployParam = (EvtAppDeploy) evt;
+        String appId = deployParam.getAppId();
+        EvtAppStatResult statResult;
+        try {
+            statResult = appDeploy.deploy(deployParam);
+            statResult.setResult(Result.result(ResultStatus.SUCCESS));
+        } catch (Exception e) {
+            statResult = new EvtAppStatResult(appId, Machine.ID);
+            statResult.setResult(Result.result(ResultStatus.FAIL, ExceptionUtil.errorMsg(e)));
+        }
+
+        statResult.setDeploy(true);
+        EventMessage evtMsg = EventMessage.evt(statResult);
+        try {
+            messageSender.send("", evtMsg);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 73 - 0
agent/src/main/java/cn/reghao/bnt/agent/ws/event/handler/EvtAppStatHandler.java

@@ -0,0 +1,73 @@
+package cn.reghao.bnt.agent.ws.event.handler;
+
+import cn.reghao.bnt.common.agent.app.iface.AppStat;
+import cn.reghao.bnt.common.machine.Machine;
+import cn.reghao.bnt.common.msg.MessageSender;
+import cn.reghao.bnt.common.msg.constant.AppStatOps;
+import cn.reghao.bnt.common.msg.event.EvtAppStat;
+import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
+import cn.reghao.jutil.jdk.event.handler.Handler;
+import cn.reghao.jutil.jdk.event.message.Event;
+import cn.reghao.jutil.jdk.event.message.EventMessage;
+import cn.reghao.jutil.jdk.exception.ExceptionUtil;
+import cn.reghao.jutil.jdk.result.Result;
+import cn.reghao.jutil.jdk.result.ResultStatus;
+
+import java.io.IOException;
+
+/**
+ * @author reghao
+ * @date 2023-03-01 10:21:40
+ */
+public class EvtAppStatHandler extends Handler {
+    private final MessageSender messageSender;
+    private final AppStat appStat;
+
+    public EvtAppStatHandler(MessageSender messageSender, AppStat appStat) {
+        this.messageSender = messageSender;
+        this.appStat = appStat;
+    }
+
+    @Override
+    public void handle(Event evt) {
+        EvtAppStat evtAppStat = (EvtAppStat) evt;
+        String appId = evtAppStat.getAppId();
+        String ops = evtAppStat.getOps();
+
+        EvtAppStatResult statResult;
+        try {
+            switch (AppStatOps.valueOf(ops)) {
+                case start:
+                    statResult = appStat.start(evtAppStat);
+                    statResult.setResult(Result.result(ResultStatus.SUCCESS));
+                    break;
+                case stop:
+                    statResult = appStat.stop(evtAppStat);
+                    statResult.setResult(Result.result(ResultStatus.SUCCESS));
+                    break;
+                case restart:
+                    statResult = appStat.restart(evtAppStat);
+                    statResult.setResult(Result.result(ResultStatus.SUCCESS));
+                    break;
+                case stat:
+                    statResult = appStat.stat(evtAppStat);
+                    statResult.setResult(Result.result(ResultStatus.SUCCESS));
+                    break;
+                default:
+                    statResult = new EvtAppStatResult(appId, Machine.ID);
+                    String msg = String.format("应用状态操作类型 %s 不存在", ops);
+                    statResult.setResult(Result.result(ResultStatus.ERROR, msg));
+            }
+        } catch (Exception e) {
+            statResult = new EvtAppStatResult(appId, Machine.ID);
+            statResult.setResult(Result.result(ResultStatus.FAIL, ExceptionUtil.errorMsg(e)));
+        }
+
+        EventMessage evtMsg = EventMessage.evt(statResult);
+        try {
+            messageSender.send(Machine.ID, evtMsg);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 0 - 114
agent/src/main/java/cn/reghao/devops/agent/AgentApp.java

@@ -1,114 +0,0 @@
-package cn.reghao.devops.agent;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.LoggerContext;
-import cn.reghao.devops.agent.ws.WsClient;
-import cn.reghao.devops.agent.config.ConfigFile;
-import cn.reghao.devops.agent.config.DagentConfig;
-import cn.reghao.devops.agent.task.ImageCleanTask;
-import cn.reghao.devops.common.agent.app.iface.AppDeploy;
-import cn.reghao.devops.common.agent.app.iface.AppStat;
-import cn.reghao.devops.common.agent.app.iface.impl.AppDeployImpl;
-import cn.reghao.devops.common.agent.app.iface.impl.AppStatImpl;
-import cn.reghao.devops.common.agent.app.iface.impl.DockerApp;
-import cn.reghao.devops.common.docker.Docker;
-import cn.reghao.devops.common.docker.DockerImpl;
-import cn.reghao.devops.common.msg.MessageSender;
-import cn.reghao.jutil.jdk.serializer.JsonConverter;
-import cn.reghao.jutil.jdk.string.StringRegexp;
-import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
-import cn.reghao.jutil.jdk.util.SingleInstance;
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.nio.charset.StandardCharsets;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-@Slf4j
-public class AgentApp {
-	static MessageSender messageSender;
-	static ScheduledExecutorService scheduler = ThreadPoolWrapper.scheduledThreadPool("heartbeat", 5);
-	static Docker docker = new DockerImpl();
-
-	static void setLogLevel() {
-		LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
-		Logger rootLogger = loggerContext.getLogger("ROOT");
-		rootLogger.setLevel(Level.INFO);
-		//LoggerConfig.initLogger(Appenders.fileAppender());
-	}
-	
-	static boolean tryConnect(String host, int port) {
-		try {
-			boolean isAddress = StringRegexp.matchIPv4Address(host);
-			InetAddress inetAddress;
-			if (isAddress) {
-				inetAddress = InetAddress.getByAddress(host.getBytes(StandardCharsets.UTF_8));
-			} else {
-				inetAddress = InetAddress.getByName(host);
-			}
-
-			InetSocketAddress socketAddress = new InetSocketAddress(inetAddress, port);
-			Socket socket = new Socket();
-			socket.connect(socketAddress);
-			return true;
-		} catch (IOException e) {
-			log.error("尝试建立到 {}:{} 的 Socket 连接失败", host, port);
-		}
-		return false;
-	}
-
-	static MessageSender getMessageSender(DagentConfig dagentConfig) {
-		DockerApp dockerApp = new DockerApp(docker);
-		AppDeploy appDeploy = new AppDeployImpl(dockerApp);
-		AppStat appStat = new AppStatImpl(dockerApp);
-
-		if (tryConnect(dagentConfig.getMgrAddress(), dagentConfig.getMgrPort())) {
-			messageSender = new WsClient(dagentConfig, scheduler, appDeploy, appStat);
-			return messageSender;
-		}
-
-		return null;
-	}
-
-	static void shutdownGracefully() {
-		Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook(), "main-shutdown-hook"));
-	}
-
-	static class ShutdownHook implements Runnable {
-		@Override
-		public void run() {
-			messageSender.close();
-			log.info("资源清理完成,结束 devops-agent...");
-		}
-	}
-
-	public static void main(String[] args) {
-		setLogLevel();
-		if (args.length != 1) {
-			log.error("必须指定配置文件...");
-			return;
-		}
-
-		String configFilePath = ConfigFile.configFilePath(args[0], AgentApp.class);
-		DagentConfig dagentConfig = JsonConverter.jsonFileToObject(new File(configFilePath), DagentConfig.class);
-		messageSender = getMessageSender(dagentConfig);
-		if (messageSender == null) {
-			log.error("没有可用的 MessageSender, Agent 结束运行, 具体信息请查看日志");
-			System.exit(-1);
-		} else {
-			messageSender.connect();
-		}
-
-		ImageCleanTask cleanTask = new ImageCleanTask(docker);
-		scheduler.scheduleAtFixedRate(cleanTask, 1, 12, TimeUnit.HOURS);
-		shutdownGracefully();
-		SingleInstance.onlyOne(60001);
-	}
-}

+ 0 - 53
agent/src/main/java/cn/reghao/devops/agent/config/ConfigFile.java

@@ -1,53 +0,0 @@
-package cn.reghao.devops.agent.config;
-
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.File;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-
-/**
- * @author reghao
- * @date 2021-03-03 18:47:01
- */
-@Slf4j
-public class ConfigFile {
-    public static String configFilePath(String arg, Class<?> clazz) {
-        String configFilePath = null;
-        File configFile = new File(arg);
-        if (!configFile.exists()) {
-            if (arg.startsWith("./")) {
-                String filename = arg.replace(".", "")
-                        .replace("/", "");
-                configFilePath = runningHome(clazz) + "/" + filename;
-            } else if (!arg.contains("/")) {
-                configFilePath = runningHome(clazz) + "/" + arg;
-            } else {
-                log.error("相对路径的配置文件必须以 ./configFile 或 configFile 形式指定...");
-            }
-        } else {
-            // 绝对路径
-            configFilePath = arg;
-        }
-        return configFilePath;
-    }
-    
-    /**
-     * jar 文件运行目录
-     *
-     * @param
-     * @return
-     * @date 2021-03-03 下午6:33
-     */
-    public static String runningHome(Class<?> clazz) {
-        URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
-        String jarFilePath = URLDecoder.decode(url.getPath(), StandardCharsets.UTF_8);
-        if (jarFilePath.endsWith(".jar")) {
-            jarFilePath = jarFilePath.substring(0, jarFilePath.lastIndexOf("/") + 1);
-        }
-
-        File file = new File(jarFilePath);
-        return file.getAbsolutePath();
-    }
-}

+ 0 - 15
agent/src/main/java/cn/reghao/devops/agent/config/DagentConfig.java

@@ -1,15 +0,0 @@
-package cn.reghao.devops.agent.config;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * @author reghao
- * @date 2023-02-23 11:37:32
- */
-@AllArgsConstructor
-@Getter
-public class DagentConfig {
-    private String mgrAddress;
-    private int mgrPort;
-}

+ 0 - 41
agent/src/main/java/cn/reghao/devops/agent/task/ImageCleanTask.java

@@ -1,41 +0,0 @@
-package cn.reghao.devops.agent.task;
-
-import cn.reghao.devops.common.docker.Docker;
-import com.github.dockerjava.api.command.InspectContainerResponse;
-import com.github.dockerjava.api.model.Image;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * @author reghao
- * @date 2024-07-29 16:17:47
- */
-@Slf4j
-public class ImageCleanTask implements Runnable {
-    private final Docker docker;
-
-    public ImageCleanTask(Docker docker) {
-        this.docker = docker;
-    }
-
-    @Override
-    public void run() {
-        Map<String, Image> map = docker.images().stream()
-                .collect(Collectors.toMap(Image::getId, image -> image));
-
-        List<InspectContainerResponse> list = docker.psAll();
-        for (InspectContainerResponse response : list) {
-            String imageId = response.getImageId();
-            Boolean running = response.getState().getRunning();
-            if (running != null && running) {
-                Image image = map.remove(imageId);
-            }
-        }
-
-        //map.keySet().forEach(docker::imageRm);
-        log.info("定时扫描 docker 镜像和容器");
-    }
-}

+ 0 - 94
agent/src/main/java/cn/reghao/devops/agent/ws/WebSocketListenerImpl.java

@@ -1,94 +0,0 @@
-package cn.reghao.devops.agent.ws;
-
-import cn.reghao.devops.agent.ws.event.EventCenter;
-import cn.reghao.devops.common.agent.machine.MachineEvent;
-import cn.reghao.jutil.jdk.serializer.JdkSerializer;
-import cn.reghao.jutil.jdk.event.message.EventMessage;
-import lombok.extern.slf4j.Slf4j;
-import okhttp3.Response;
-import okhttp3.WebSocket;
-import okhttp3.WebSocketListener;
-import okio.ByteString;
-
-/**
- * @author reghao
- * @date 2023-02-23 09:26:50
- */
-@Slf4j
-public class WebSocketListenerImpl extends WebSocketListener {
-    private final EventCenter eventCenter;
-    private final WsClient wsClient;
-    private final MachineEvent machineEvent;
-
-    public WebSocketListenerImpl(WsClient wsClient, EventCenter eventCenter, MachineEvent machineEvent) {
-        this.eventCenter = eventCenter;
-        this.wsClient = wsClient;
-        this.machineEvent = machineEvent;
-    }
-
-    @Override
-    public void onOpen(WebSocket webSocket, Response response) {
-        log.info("WebSocket 连接成功");
-        wsClient.setConnected(true);
-        wsClient.resetRetryCount();
-
-        machineEvent.agentStart();
-    }
-
-    @Override
-    public void onClosing(WebSocket webSocket, int code, String reason) {
-        log.error("WebSocket 连接被动断开 -> {} - {}", code, reason);
-        wsClient.setConnected(false);
-
-        machineEvent.pauseHeartbeat();
-        if (wsClient.isRetry()) {
-            reconnect();
-        }
-    }
-
-    @Override
-    public void onClosed(WebSocket webSocket, int code, String reason) {
-        log.error("WebSocket 连接主动断开 -> {} - {}", code, reason);
-        wsClient.setConnected(false);
-    }
-
-    @Override
-    public void onFailure(WebSocket webSocket, Throwable throwable, Response response) {
-        log.info("WebSocket 异常事件: {}", throwable.getMessage());
-        wsClient.setConnected(false);
-        if (wsClient.isRetry()) {
-            reconnect();
-        }
-    }
-
-    private void reconnect() {
-        log.info("WebSocket 重连");
-        try {
-            if (wsClient.getRetryCount() > 10) {
-                log.info("WebSocket 重连超过 10 次, 休眠 1 分钟后再尝试");
-                Thread.sleep(60_000);
-                wsClient.resetRetryCount();
-            } else {
-                log.info("休眠 10s 后再尝试重连");
-                Thread.sleep(10_000);
-            }
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        wsClient.retryCountIncr();
-        wsClient.connect();
-    }
-
-    @Override
-    public void onMessage(WebSocket webSocket, String text) {
-    }
-
-    @Override
-    public void onMessage(WebSocket webSocket, ByteString bytes) {
-        Object object = JdkSerializer.deserialize(bytes.toByteArray());
-        if (object instanceof EventMessage) {
-            EventMessage eventMessage = (EventMessage) object;
-            eventCenter.dispatch(eventMessage);
-        }
-    }
-}

+ 0 - 110
agent/src/main/java/cn/reghao/devops/agent/ws/WsClient.java

@@ -1,110 +0,0 @@
-package cn.reghao.devops.agent.ws;
-
-import cn.reghao.devops.agent.config.DagentConfig;
-import cn.reghao.devops.agent.ws.event.EventCenter;
-import cn.reghao.devops.common.agent.app.iface.AppDeploy;
-import cn.reghao.devops.common.agent.app.iface.AppStat;
-import cn.reghao.devops.common.agent.machine.MachineEvent;
-import cn.reghao.devops.common.machine.Machine;
-import cn.reghao.devops.common.msg.MessageSender;
-import cn.reghao.jutil.jdk.serializer.JdkSerializer;
-import okhttp3.*;
-import okio.ByteString;
-
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * @author reghao
- * @date 2023-02-23 09:26:50
- */
-public class WsClient implements MessageSender {
-    private final String url;
-    private WebSocket webSocket;
-    private boolean connected;
-    private final WebSocketListener webSocketListener;
-    private boolean retry;
-    private int retryCount;
-
-    public WsClient(DagentConfig dagentConfig, ScheduledExecutorService scheduler, AppDeploy appDeploy, AppStat appStat) {
-        String host = dagentConfig.getMgrAddress();
-        int port = dagentConfig.getMgrPort();
-        this.url = String.format("ws://%s:%s/ws/agent?token=%s", host, port, Machine.ID);
-
-        EventCenter eventCenter = new EventCenter(this, appDeploy, appStat);
-        // 每 60s 发送一次心跳
-        int heartbeatInterval = 60;
-        MachineEvent machineEvent = new MachineEvent(this, new Machine(), appStat, scheduler, heartbeatInterval);
-        this.webSocketListener = new WebSocketListenerImpl(this, eventCenter, machineEvent);
-        this.retry = true;
-        this.retryCount = 0;
-        Logger.getLogger(OkHttpClient.class.getName()).setLevel(Level.FINE);
-    }
-
-    public void setRetry(boolean retry) {
-        this.retry = retry;
-    }
-
-    public boolean isRetry() {
-        return retry;
-    }
-
-    public void retryCountIncr() {
-        this.retryCount += 1;
-    }
-
-    public void resetRetryCount() {
-        this.retryCount = 0;
-    }
-
-    public int getRetryCount() {
-        return retryCount;
-    }
-
-    @Override
-    public void connect() {
-        Request request = new Request.Builder()
-                .url(url)
-                .header("Authorization", "Bearer " + Machine.ID)
-                .build();
-
-        OkHttpClient okHttpClient = new OkHttpClient.Builder()
-                //.pingInterval(30, TimeUnit.SECONDS)
-                .connectTimeout(60, TimeUnit.SECONDS)
-                .readTimeout(60, TimeUnit.SECONDS)
-                .writeTimeout(60, TimeUnit.SECONDS)
-                .build();
-
-        if (this.webSocket != null) {
-            this.webSocket.cancel();
-        }
-
-
-        this.webSocket = okHttpClient.newWebSocket(request, webSocketListener);
-    }
-
-    @Override
-    public void setConnected(boolean status) {
-        this.connected = status;
-    }
-
-    @Override
-    public boolean isConnected() {
-        return connected;
-    }
-
-    @Override
-    public void send(String dest, Object message) {
-        if (isConnected()) {
-            byte[] bytes = JdkSerializer.serialize(message);
-            webSocket.send(ByteString.of(bytes));
-        }
-    }
-
-    public void close() {
-        setRetry(false);
-        webSocket.close(1000, "Client Close Connection");
-    }
-}

+ 0 - 57
agent/src/main/java/cn/reghao/devops/agent/ws/event/EventCenter.java

@@ -1,57 +0,0 @@
-package cn.reghao.devops.agent.ws.event;
-
-import cn.reghao.devops.agent.ws.event.handler.EvtAppDeployHandler;
-import cn.reghao.devops.agent.ws.event.handler.EvtAppStatHandler;
-import cn.reghao.devops.common.agent.app.iface.AppDeploy;
-import cn.reghao.devops.common.agent.app.iface.AppStat;
-import cn.reghao.devops.common.msg.MessageSender;
-import cn.reghao.devops.common.msg.event.EvtAppDeploy;
-import cn.reghao.devops.common.msg.event.EvtAppStat;
-import cn.reghao.jutil.jdk.event.message.Event;
-import cn.reghao.jutil.jdk.event.router.EventDispatcher;
-import cn.reghao.jutil.jdk.event.message.EventMessage;
-import cn.reghao.jutil.jdk.exception.ExceptionUtil;
-import lombok.extern.slf4j.Slf4j;
-
-import java.lang.management.ManagementFactory;
-
-/**
- * @author reghao
- * @date 2023-02-23 09:18:11
- */
-@Slf4j
-public class EventCenter {
-    private final long startTime;
-    private final EventDispatcher dispatcher;
-
-    public EventCenter(MessageSender messageSender, AppDeploy appDeploy, AppStat appStat) {
-        this.startTime = ManagementFactory.getRuntimeMXBean().getStartTime();
-        this.dispatcher = new EventDispatcher();
-        initDispatcher(messageSender, appDeploy, appStat);
-    }
-
-    private void initDispatcher(MessageSender messageSender, AppDeploy appDeploy, AppStat appStat) {
-        dispatcher.register(EvtAppDeploy.class, new EvtAppDeployHandler(messageSender, appDeploy));
-        dispatcher.register(EvtAppStat.class, new EvtAppStatHandler(messageSender, appStat));
-    }
-
-    public void dispatch(EventMessage eventMessage) {
-        try {
-            long sendTime = eventMessage.getSendTime();
-            if (sendTime < startTime) {
-                log.info("忽略 agent 启动前 mgr 发送的事件...");
-                return;
-            }
-
-            Event event = eventMessage.getEvent();
-            dispatcher.dispatch(event);
-        } catch (Exception e) {
-            String errMsg = e.getMessage();
-            if (e instanceof NullPointerException) {
-                errMsg = ExceptionUtil.stackTrace(e);
-            }
-
-            log.error("处理消息发生异常: {}", errMsg);
-        }
-    }
-}

+ 0 - 51
agent/src/main/java/cn/reghao/devops/agent/ws/event/handler/EvtAppDeployHandler.java

@@ -1,51 +0,0 @@
-package cn.reghao.devops.agent.ws.event.handler;
-
-import cn.reghao.devops.common.agent.app.iface.AppDeploy;
-import cn.reghao.devops.common.machine.Machine;
-import cn.reghao.devops.common.msg.MessageSender;
-import cn.reghao.devops.common.msg.event.EvtAppStatResult;
-import cn.reghao.jutil.jdk.event.message.Event;
-import cn.reghao.jutil.jdk.event.message.EventMessage;
-import cn.reghao.jutil.jdk.event.handler.Handler;
-import cn.reghao.devops.common.msg.event.EvtAppDeploy;
-import cn.reghao.jutil.jdk.exception.ExceptionUtil;
-import cn.reghao.jutil.jdk.result.Result;
-import cn.reghao.jutil.jdk.result.ResultStatus;
-
-import java.io.IOException;
-
-/**
- * @author reghao
- * @date 2023-03-01 10:52:04
- */
-public class EvtAppDeployHandler extends Handler {
-    private final MessageSender messageSender;
-    private final AppDeploy appDeploy;
-
-    public EvtAppDeployHandler(MessageSender messageSender, AppDeploy appDeploy) {
-        this.messageSender = messageSender;
-        this.appDeploy = appDeploy;
-    }
-
-    @Override
-    public void handle(Event evt) {
-        EvtAppDeploy deployParam = (EvtAppDeploy) evt;
-        String appId = deployParam.getAppId();
-        EvtAppStatResult statResult;
-        try {
-            statResult = appDeploy.deploy(deployParam);
-            statResult.setResult(Result.result(ResultStatus.SUCCESS));
-        } catch (Exception e) {
-            statResult = new EvtAppStatResult(appId, Machine.ID);
-            statResult.setResult(Result.result(ResultStatus.FAIL, ExceptionUtil.errorMsg(e)));
-        }
-
-        statResult.setDeploy(true);
-        EventMessage evtMsg = EventMessage.evt(statResult);
-        try {
-            messageSender.send("", evtMsg);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-}

+ 0 - 73
agent/src/main/java/cn/reghao/devops/agent/ws/event/handler/EvtAppStatHandler.java

@@ -1,73 +0,0 @@
-package cn.reghao.devops.agent.ws.event.handler;
-
-import cn.reghao.devops.common.agent.app.iface.AppStat;
-import cn.reghao.devops.common.machine.Machine;
-import cn.reghao.devops.common.msg.MessageSender;
-import cn.reghao.devops.common.msg.constant.AppStatOps;
-import cn.reghao.devops.common.msg.event.EvtAppStat;
-import cn.reghao.devops.common.msg.event.EvtAppStatResult;
-import cn.reghao.jutil.jdk.event.handler.Handler;
-import cn.reghao.jutil.jdk.event.message.Event;
-import cn.reghao.jutil.jdk.event.message.EventMessage;
-import cn.reghao.jutil.jdk.exception.ExceptionUtil;
-import cn.reghao.jutil.jdk.result.Result;
-import cn.reghao.jutil.jdk.result.ResultStatus;
-
-import java.io.IOException;
-
-/**
- * @author reghao
- * @date 2023-03-01 10:21:40
- */
-public class EvtAppStatHandler extends Handler {
-    private final MessageSender messageSender;
-    private final AppStat appStat;
-
-    public EvtAppStatHandler(MessageSender messageSender, AppStat appStat) {
-        this.messageSender = messageSender;
-        this.appStat = appStat;
-    }
-
-    @Override
-    public void handle(Event evt) {
-        EvtAppStat evtAppStat = (EvtAppStat) evt;
-        String appId = evtAppStat.getAppId();
-        String ops = evtAppStat.getOps();
-
-        EvtAppStatResult statResult;
-        try {
-            switch (AppStatOps.valueOf(ops)) {
-                case start:
-                    statResult = appStat.start(evtAppStat);
-                    statResult.setResult(Result.result(ResultStatus.SUCCESS));
-                    break;
-                case stop:
-                    statResult = appStat.stop(evtAppStat);
-                    statResult.setResult(Result.result(ResultStatus.SUCCESS));
-                    break;
-                case restart:
-                    statResult = appStat.restart(evtAppStat);
-                    statResult.setResult(Result.result(ResultStatus.SUCCESS));
-                    break;
-                case stat:
-                    statResult = appStat.stat(evtAppStat);
-                    statResult.setResult(Result.result(ResultStatus.SUCCESS));
-                    break;
-                default:
-                    statResult = new EvtAppStatResult(appId, Machine.ID);
-                    String msg = String.format("应用状态操作类型 %s 不存在", ops);
-                    statResult.setResult(Result.result(ResultStatus.ERROR, msg));
-            }
-        } catch (Exception e) {
-            statResult = new EvtAppStatResult(appId, Machine.ID);
-            statResult.setResult(Result.result(ResultStatus.FAIL, ExceptionUtil.errorMsg(e)));
-        }
-
-        EventMessage evtMsg = EventMessage.evt(statResult);
-        try {
-            messageSender.send(Machine.ID, evtMsg);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-}

+ 284 - 66
agent/src/test/java/AgentTest.java

@@ -1,8 +1,16 @@
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
+import cn.reghao.bnt.common.docker.DockerImpl;
+import cn.reghao.bnt.common.machine.model.NetworkCard;
+import cn.reghao.jutil.jdk.converter.ByteConverter;
+import cn.reghao.jutil.jdk.converter.DateTimeConverter;
 import cn.reghao.jutil.jdk.converter.IpAddressConverter;
 import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
+import com.github.dockerjava.api.command.InspectContainerResponse;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
 import org.slf4j.LoggerFactory;
 import oshi.SystemInfo;
 import oshi.hardware.*;
@@ -10,12 +18,11 @@ import oshi.software.os.*;
 import oshi.util.FormatUtil;
 import oshi.util.Util;
 
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
+import java.util.*;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -23,7 +30,6 @@ import java.util.function.Predicate;
  */
 public class AgentTest {
     private static void printComputerSystem(final ComputerSystem computerSystem) {
-
         System.out.println("manufacturer: " + computerSystem.getManufacturer());
         System.out.println("model: " + computerSystem.getModel());
         System.out.println("serialnumber: " + computerSystem.getSerialNumber());
@@ -52,26 +58,21 @@ public class AgentTest {
         System.out.println("ProcessorID: " + processor.getProcessorIdentifier().getProcessorID());
     }
 
-    private static void printMemory(GlobalMemory memory) {
-        System.out.println("Memory: " + FormatUtil.formatBytes(memory.getAvailable()) + "/"
-                + FormatUtil.formatBytes(memory.getTotal()));
-        System.out.println("Swap used: " + FormatUtil.formatBytes(memory.getVirtualMemory().getSwapUsed()) + "/"
-                + FormatUtil.formatBytes(memory.getVirtualMemory().getSwapTotal()));
-    }
-
     private static void printCpu(CentralProcessor processor) {
-        System.out.println(
-                "Context Switches/Interrupts: " + processor.getContextSwitches() + " / " + processor.getInterrupts());
+        String cs = String.format("Context Switches/Interrupts: %s/%s\n",
+                processor.getContextSwitches(), processor.getInterrupts());
+        System.out.println(cs);
+        long sleep = 1000;
 
         long[] prevTicks = processor.getSystemCpuLoadTicks();
         System.out.println("CPU, IOWait, and IRQ ticks @ 0 sec:" + Arrays.toString(prevTicks));
-        // Wait a second...
-        Util.sleep(1000);
+        Util.sleep(sleep);
         long[] ticks = processor.getSystemCpuLoadTicks();
         System.out.println("CPU, IOWait, and IRQ ticks @ 1 sec:" + Arrays.toString(ticks));
+
         long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
-        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
         long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
+        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
         long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
         long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
         long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
@@ -79,16 +80,30 @@ public class AgentTest {
         long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
         long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal;
 
-        System.out.format(
+        String load = String.format("%.1f us, %.1f sy, %.1f ni, %.1f id, %.1f wa, %.1f hi, %.1f si, %.1f st\n",
+                100d * user / totalCpu, 100d * sys / totalCpu, 100d * nice / totalCpu, 100d * idle / totalCpu,
+                100d * iowait / totalCpu, 100d * irq / totalCpu, 100d * softirq / totalCpu, 100d * steal / totalCpu);
+        System.out.println(load);
+        /*System.out.format(
                 "User: %.1f%% Nice: %.1f%% System: %.1f%% Idle: %.1f%% IOwait: %.1f%% IRQ: %.1f%% SoftIRQ: %.1f%% Steal: %.1f%%%n",
                 100d * user / totalCpu, 100d * nice / totalCpu, 100d * sys / totalCpu, 100d * idle / totalCpu,
-                100d * iowait / totalCpu, 100d * irq / totalCpu, 100d * softirq / totalCpu, 100d * steal / totalCpu);
+                100d * iowait / totalCpu, 100d * irq / totalCpu, 100d * softirq / totalCpu, 100d * steal / totalCpu);*/
         System.out.format("CPU load: %.1f%% (counting ticks)%n", processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100);
-        //System.out.format("CPU load: %.1f%% (OS MXBean)%n", processor.getSystemCpuLoad() * 100);
+        System.out.format("CPU load: %.1f%% (OS MXBean)%n", processor.getSystemCpuLoad(1) * 100);
+
         double[] loadAverage = processor.getSystemLoadAverage(3);
-        System.out.println("CPU load averages:" + (loadAverage[0] < 0 ? " N/A" : String.format(" %.2f", loadAverage[0]))
-                + (loadAverage[1] < 0 ? " N/A" : String.format(" %.2f", loadAverage[1]))
-                + (loadAverage[2] < 0 ? " N/A" : String.format(" %.2f", loadAverage[2])));
+        /*System.out.println("CPU load averages:" +
+                (loadAverage[0] < 0 ? " N/A" : String.format(" %.2f", loadAverage[0])) +
+                (loadAverage[1] < 0 ? " N/A" : String.format(" %.2f", loadAverage[1])) +
+                (loadAverage[2] < 0 ? " N/A" : String.format(" %.2f", loadAverage[2]))
+        );*/
+        String loadAvg = String.format("%s %s %s\n",
+                (loadAverage[0] < 0 ? " N/A" : String.format(" %.2f", loadAverage[0])),
+                (loadAverage[1] < 0 ? " N/A" : String.format(" %.2f", loadAverage[1])),
+                (loadAverage[2] < 0 ? " N/A" : String.format(" %.2f", loadAverage[2]))
+        );
+        System.out.println(loadAvg);
+
         // per core CPU
 //      StringBuilder procCpu = new StringBuilder("CPU load per processor:");
 //      double[] load = processor.getProcessorCpuLoadBetweenTicks();
@@ -98,6 +113,17 @@ public class AgentTest {
 //      System.out.println(procCpu.toString());
     }
 
+    private static void printMemory(GlobalMemory memory) {
+        long total = memory.getTotal();
+        long avail = memory.getAvailable();
+        VirtualMemory virtualMemory = memory.getVirtualMemory();
+
+        System.out.println("Memory: " + FormatUtil.formatBytes(memory.getAvailable()) + "/"
+                + FormatUtil.formatBytes(memory.getTotal()));
+        System.out.println("Swap used: " + FormatUtil.formatBytes(memory.getVirtualMemory().getSwapUsed()) + "/"
+                + FormatUtil.formatBytes(memory.getVirtualMemory().getSwapTotal()));
+    }
+
     private static void printProcesses(OperatingSystem os, GlobalMemory memory) {
         System.out.println("Processes: " + os.getProcessCount() + ", Threads: " + os.getThreadCount());
         // Sort by highest CPU
@@ -189,6 +215,15 @@ public class AgentTest {
     private static void printNetworkInterfaces(List<NetworkIF> list) {
         System.out.println("Network interfaces:");
         for (NetworkIF net : list) {
+            String iface = net.getName();
+            String mac = net.getMacaddr();
+            String ipv4 = Arrays.toString(net.getIPv4addr());
+            String ipv6 = Arrays.toString(net.getIPv6addr());
+            long mtu = net.getMTU();
+            long speed = net.getSpeed();
+            String speedStr = byteConverter.convert(speed);
+            NetworkCard networkCard = new NetworkCard(iface, mac, ipv4, ipv6, mtu, speed, speedStr);
+
             System.out.format(" Name: %s (%s)%n", net.getName(), net.getDisplayName());
             System.out.format("   MAC Address: %s %n", net.getMacaddr());
             System.out.format("   MTU: %s, Speed: %s %n", net.getMTU(), FormatUtil.formatValue(net.getSpeed(), "bps"));
@@ -238,34 +273,188 @@ public class AgentTest {
         rootLogger.setLevel(Level.INFO);
     }
 
-    static class StatTask implements Runnable {
-        private final OperatingSystem os;
+    static List<ListenProcess> getListenProcesses() {
+        IpAddressConverter ipAddressConverter = new IpAddressConverter();
+        List<SysProcess> sysProcessList = new ArrayList<>();
+        os.getProcesses().forEach(osProcess -> {
+            int pid = osProcess.getProcessID();
+            String name = osProcess.getName();
+            int ppid = osProcess.getParentProcessID();
+            String state = osProcess.getState().name();
+            List<OSThread> osThreadList = osProcess.getThreadDetails();
+            sysProcessList.add(new SysProcess(pid, name, ppid));
+        });
 
-        public StatTask(OperatingSystem os) {
-            this.os = os;
-        }
+        String state = InternetProtocolStats.TcpState.LISTEN.name();
+        List<ListenProcess> list = new ArrayList<>();
+        os.getInternetProtocolStats().getConnections().forEach(ipConnection -> {
+            if (!ipConnection.getState().name().equals(state)) {
+                return;
+            }
 
-        public void run() {
-            os.getProcesses().forEach(osProcess -> {
-                int pid = osProcess.getProcessID();
+            String type = ipConnection.getType();
+            int pid = ipConnection.getowningProcessId();
+            byte[] localAddress = ipConnection.getLocalAddress();
+            int localPort = ipConnection.getLocalPort();
+            byte[] remoteAddress = ipConnection.getForeignAddress();
+            int remotePort = ipConnection.getForeignPort();
+            System.out.printf("%s %s %s %s\n", pid, type, state, localPort);
+            list.add(new ListenProcess(pid, type, localPort));
+        });
+
+        Map<Integer, List<ListenProcess>> groupMap = list.stream().collect(Collectors.groupingBy(ListenProcess::getPid));
+        os.getProcesses().forEach(osProcess -> {
+            int pid = osProcess.getProcessID();
+            List<ListenProcess> list1 = groupMap.get(pid);
+            if (list1 != null && !list1.isEmpty()) {
                 String name = osProcess.getName();
-                System.out.printf("%s -> %s\n", pid, name);
-            });
+                list1.get(0).setName(name);
+            }
+        });
+
+        return list;
+    }
+
+    static OSProcess getProcess(int pid) {
+        List<OSProcess> list = os.getProcesses().stream()
+                .filter(osProcess -> osProcess.getProcessID() == pid)
+                .collect(Collectors.toList());
+        return list.isEmpty() ? null : list.get(0);
+    }
+
+    static List<InternetProtocolStats.IPConnection> getProcessConnections(int pid, InternetProtocolStats.TcpState tcpState) {
+        return os.getInternetProtocolStats().getConnections().stream()
+                .filter(ipConnection -> ipConnection.getowningProcessId() == pid
+                        && ipConnection.getState().name().equals(tcpState.name()))
+                .collect(Collectors.toList());
+    }
+
+    static List<InternetProtocolStats.IPConnection> getProcessConnections(int pid, boolean containListen) {
+        String state = InternetProtocolStats.TcpState.LISTEN.name();
+        return os.getInternetProtocolStats().getConnections().stream()
+                .filter(ipConnection -> ipConnection.getowningProcessId() == pid
+                        && (containListen == ipConnection.getState().name().equals(state)))
+                .collect(Collectors.toList());
+    }
+
+    static void dockerListTest() {
+        List<ListenProcess> listenProcessList = getListenProcesses();
+        Map<Integer, List<ListenProcess>> groupMap = listenProcessList.stream().collect(Collectors.groupingBy(ListenProcess::getPid));
+
+        DockerImpl docker = new DockerImpl();
+        List<InspectContainerResponse> list = docker.psAll();
+        List<DockerProcess> dockerProcessList = new ArrayList<>();
+        for (InspectContainerResponse response : list) {
+            String imageId = response.getImageId();
+            Boolean running = response.getState().getRunning();
+            if (running != null && running) {
+                Integer pid = response.getState().getPid();
+                if (pid == null) {
+                    pid = -1;
+                }
+
+                String containerId = response.getId();
+                String appId = response.getName().replace("/", "");
+                System.out.printf("%s: %s -> %s\n", pid, containerId, appId);
+                dockerProcessList.add(new DockerProcess(pid, containerId, appId));
+            }
         }
+
+        System.out.println();
     }
 
-    public static void main(String[] args) throws IOException, InterruptedException {
-        //setLogLevel();
-        ScheduledExecutorService scheduler = ThreadPoolWrapper.scheduledThreadPool("heartbeat", 5);
+    @Setter
+    @Getter
+    static class ListenProcess {
+        private int pid;
+        private String name;
+        private String type;
+        private int port;
+
+        public ListenProcess(int pid, String type, int port) {
+            this.pid = pid;
+            this.type = type;
+            this.port = port;
+        }
+    }
+
+    @AllArgsConstructor
+    @Getter
+    static class DockerProcess {
+        private int pid;
+        private String containerId;
+        private String appId;
+    }
+
+    @AllArgsConstructor
+    @Getter
+    static class SysProcess {
+        private int pid;
+        private String name;
+        private int ppid;
+    }
 
-        SystemInfo si = new SystemInfo();
-        HardwareAbstractionLayer hal = si.getHardware();
-        OperatingSystem os = si.getOperatingSystem();
+    static SystemInfo si = new SystemInfo();
+    static HardwareAbstractionLayer hal = si.getHardware();
+    static OperatingSystem os = si.getOperatingSystem();
+    static ByteConverter byteConverter = new ByteConverter();
+    static ScheduledExecutorService scheduler = ThreadPoolWrapper.scheduledThreadPool("heartbeat", 5);
 
-        StatTask statTask = new StatTask(os);
-        scheduler.scheduleAtFixedRate(statTask, 0, 1, TimeUnit.SECONDS);
+    static void getProcessInfo(int pid) throws InterruptedException {
+        OSProcess osProcess = getProcess(pid);
+        if (osProcess == null) {
+            return;
+        }
+
+        long startTime = osProcess.getStartTime();
+        String groupId = osProcess.getGroupID();
+        String group = osProcess.getGroup();
+        String userId = osProcess.getUserID();
+        String user = osProcess.getUser();
+        String commandLine = osProcess.getCommandLine();
+        String path = osProcess.getPath();
+
+        StatTask statTask = new StatTask(pid);
+        scheduler.scheduleAtFixedRate(statTask, 0, 3, TimeUnit.SECONDS);
+        System.out.println("main-thread goto sleep");
         Thread.sleep(3600_000);
+    }
+
+    public static void main(String[] args) throws Exception {
+        //setLogLevel();
+        int pid = 1483161;
+        getProcessInfo(pid);
+        //List<InternetProtocolStats.IPConnection> processConnections = getProcessConnections(pid, tcpState);
+
+        /*getListenProcesses();
+        CentralProcessor centralProcessor = hal.getProcessor();
+        printProcessor(centralProcessor);
+        System.out.println("--------------------------------------------------");
+        printCpu(centralProcessor);*/
+
+        /*long bootTime = os.getSystemBootTime();
+        String bootAt = DateTimeConverter.format(bootTime*1000);
+        long uptime = os.getSystemUptime();
+        List<OSSession> osSessionList = os.getSessions();
+        int sessionCount = osSessionList.size();
+        String loadAvg = "";
+        int processCount = os.getProcessCount();*/
+        /*Map<String, List<OSProcess>> groupMap = os.getProcesses().stream()
+                .collect(Collectors.groupingBy(osProcess -> osProcess.getState().name()));
+        System.out.println();*/
+
+        /*System.out.println("--------------------------------------------------");
+        System.out.println("Checking Memory...");
+        printMemory(hal.getMemory());*/
 
+        /*System.out.println("--------------------------------------------------");
+        System.out.println("Checking Network interfaces...");
+        printNetworkInterfaces(hal.getNetworkIFs());*/
+
+        //System.out.println("Checking Network parameterss...");
+        //printNetworkParameters(os.getNetworkParams());
+
+        /*
         os.getProcesses().forEach(osProcess -> {
             int pid = osProcess.getProcessID();
             String name = osProcess.getName();
@@ -286,7 +475,7 @@ public class AgentTest {
                 return;
             }
             System.out.printf("%s %s %s %s\n", pid, type, state, localPort);
-        });
+        });*/
 
         /*Predicate<OSProcess> chromeProcessFilter = p -> p.getName().equalsIgnoreCase("Chrome");
         List<OSProcess> procs = os.getProcesses(chromeProcessFilter, OperatingSystem.ProcessSorting.CPU_DESC, 10);
@@ -295,15 +484,6 @@ public class AgentTest {
         System.out.println("Checking computer system...");
         printComputerSystem(hal.getComputerSystem());
 
-        System.out.println("Checking Processor...");
-        printProcessor(hal.getProcessor());
-
-        System.out.println("Checking Memory...");
-        printMemory(hal.getMemory());
-
-        System.out.println("Checking CPU...");
-        printCpu(hal.getProcessor());
-
         System.out.println("Checking Processes...");
         printProcesses(os, hal.getMemory());*/
 
@@ -317,28 +497,66 @@ public class AgentTest {
             }
         }*/
 
-        //System.out.println("Checking Sensors...");
-        //printSensors(hal.getSensors());
-/*
-        System.out.println("Checking Power sources...");
-        printPowerSources(hal.getPowerSources());
-
-        System.out.println("Checking Disks...");
-        printDisks(hal.getDiskStores());
-
-        System.out.println("Checking File System...");
-        printFileSystem(os.getFileSystem());
-
-        System.out.println("Checking Network interfaces...");
-        printNetworkInterfaces(hal.getNetworkIFs());
+        /*System.out.println("Checking Sensors...");
+        printSensors(hal.getSensors());*/
 
-        System.out.println("Checking Network parameterss...");
-        printNetworkParameters(os.getNetworkParams());
+        /*System.out.println("Checking Power sources...");
+        printPowerSources(hal.getPowerSources());*/
 
+        /*
         System.out.println("Checking Displays...");
         printDisplays(hal.getDisplays());
 
         System.out.println("Checking USB Devices...");
         printUsbDevices(hal.getUsbDevices(true));*/
     }
+
+    static class StatTask implements Runnable {
+        private final int pid;
+
+        public StatTask(int pid) {
+            this.pid = pid;
+        }
+
+        public void run() {
+            OSProcess osProcess = getProcess(pid);
+            if (osProcess == null) {
+                return;
+            }
+
+            List<OSThread> osThreadList = osProcess.getThreadDetails();
+            List<InternetProtocolStats.IPConnection> processConnections = getProcessConnections(pid, false);
+            long contextSwitches = osProcess.getContextSwitches();
+            double cpuLoadCumulative = osProcess.getProcessCpuLoadCumulative();
+
+            long uptime = osProcess.getUpTime();
+            long kernelTime = osProcess.getKernelTime();
+            long userTime = osProcess.getUserTime();
+
+            String state = osProcess.getState().name();
+            int priority = osProcess.getPriority();
+            long affinityMask = osProcess.getAffinityMask();
+
+            long residentSetSize= osProcess.getResidentSetSize();
+            long virtualSize = osProcess.getVirtualSize();
+
+            long openFiles = osProcess.getOpenFiles();
+            long bytesRead = osProcess.getBytesRead();
+            long bytesWritten = osProcess.getBytesWritten();
+
+            System.out.printf("%s -> threads: %s, connections: %s, " +
+                            "contextSwitches: %s, cpuLoadCumulative: %s, " +
+                            "uptime: %s, kernelTime: %s, userTime: %s, " +
+                            "state: %s, priority: %s, affinityMask: %s, " +
+                            "residentSetSize: %s, virtualSize: %s, " +
+                            "openFiles: %s, bytesRead: %s, bytesWritten: %s, " +
+                            "\n",
+                    DateTimeConverter.format(System.currentTimeMillis()), osThreadList.size(), processConnections.size(),
+                    contextSwitches, cpuLoadCumulative,
+                    uptime, kernelTime, userTime,
+                    state, priority, affinityMask,
+                    residentSetSize, virtualSize,
+                    openFiles, bytesRead, bytesWritten);
+        }
+    }
 }

+ 1 - 1
agent/src/test/java/WebSocketClient.java

@@ -1,4 +1,4 @@
-import cn.reghao.devops.common.machine.Machine;
+import cn.reghao.bnt.common.machine.Machine;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;

+ 2 - 11
agent/src/test/java/WebSocketClientHandler.java

@@ -1,15 +1,6 @@
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelPromise;
-import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.*;
 import io.netty.handler.codec.http.FullHttpResponse;
-import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
-import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
-import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
-import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
-import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
-import io.netty.handler.codec.http.websocketx.WebSocketFrame;
+import io.netty.handler.codec.http.websocketx.*;
 import io.netty.util.CharsetUtil;
 import lombok.extern.slf4j.Slf4j;
 

+ 8 - 2
common/pom.xml

@@ -3,8 +3,8 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>devops</artifactId>
-        <groupId>cn.reghao.devops</groupId>
+        <artifactId>bnt</artifactId>
+        <groupId>cn.reghao.bnt</groupId>
         <version>1.0.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
@@ -20,6 +20,12 @@
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>cn.reghao.jutil</groupId>
+            <artifactId>jdk</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+        </dependency>
+
         <dependency>
             <groupId>com.github.docker-java</groupId>
             <artifactId>docker-java</artifactId>

+ 18 - 0
common/src/main/java/cn/reghao/bnt/common/agent/app/dto/AppInfo.java

@@ -0,0 +1,18 @@
+package cn.reghao.bnt.common.agent.app.dto;
+
+import lombok.Getter;
+
+/**
+ * @author reghao
+ * @date 2023-03-08 10:01:20
+ */
+@Getter
+public class AppInfo {
+    private final String packType;
+    private final String appId;
+
+    public AppInfo(String packType, String appId) {
+        this.packType = packType;
+        this.appId = appId;
+    }
+}

+ 12 - 0
common/src/main/java/cn/reghao/bnt/common/agent/app/iface/AppDeploy.java

@@ -0,0 +1,12 @@
+package cn.reghao.bnt.common.agent.app.iface;
+
+import cn.reghao.bnt.common.msg.event.EvtAppDeploy;
+import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
+
+/**
+ * @author reghao
+ * @date 2023-03-06 16:21:07
+ */
+public interface AppDeploy {
+    EvtAppStatResult deploy(EvtAppDeploy deployParam) throws Exception;
+}

+ 20 - 0
common/src/main/java/cn/reghao/bnt/common/agent/app/iface/AppStat.java

@@ -0,0 +1,20 @@
+package cn.reghao.bnt.common.agent.app.iface;
+
+import cn.reghao.bnt.common.msg.event.EvtAppStat;
+import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
+
+import java.util.List;
+
+/**
+ * 应用状态管理
+ *
+ * @author reghao
+ * @date 2023-03-06 15:22:48
+ */
+public interface AppStat {
+    EvtAppStatResult start(EvtAppStat evtAppStat) throws Exception;
+    EvtAppStatResult stop(EvtAppStat evtAppStat) throws Exception;
+    EvtAppStatResult restart(EvtAppStat evtAppStat) throws Exception;
+    EvtAppStatResult stat(EvtAppStat evtAppStat) throws Exception;
+    List<EvtAppStatResult> stat() throws Exception;
+}

+ 28 - 0
common/src/main/java/cn/reghao/bnt/common/agent/app/iface/impl/AppDeployImpl.java

@@ -0,0 +1,28 @@
+package cn.reghao.bnt.common.agent.app.iface.impl;
+
+import cn.reghao.bnt.common.agent.app.iface.AppDeploy;
+import cn.reghao.bnt.common.msg.constant.PackType;
+import cn.reghao.bnt.common.msg.event.EvtAppDeploy;
+import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
+
+/**
+ * @author reghao
+ * @date 2023-03-06 16:21:30
+ */
+public class AppDeployImpl implements AppDeploy {
+    private final DockerApp dockerApp;
+
+    public AppDeployImpl(DockerApp dockerApp) {
+        this.dockerApp = dockerApp;
+    }
+
+    @Override
+    public EvtAppStatResult deploy(EvtAppDeploy deployParam) throws Exception {
+        String packType = deployParam.getPackType();
+        if (packType.equals(PackType.docker.name())) {
+            return dockerApp.deploy(deployParam);
+        } else {
+            throw new Exception("zip 打包没有实现");
+        }
+    }
+}

+ 73 - 0
common/src/main/java/cn/reghao/bnt/common/agent/app/iface/impl/AppStatImpl.java

@@ -0,0 +1,73 @@
+package cn.reghao.bnt.common.agent.app.iface.impl;
+
+import cn.reghao.bnt.common.agent.app.iface.AppStat;
+import cn.reghao.bnt.common.msg.constant.PackType;
+import cn.reghao.bnt.common.msg.event.EvtAppStat;
+import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2023-03-06 16:19:24
+ */
+public class AppStatImpl implements AppStat {
+    private final DockerApp dockerApp;
+
+    public AppStatImpl(DockerApp dockerApp) {
+        this.dockerApp = dockerApp;
+    }
+
+    @Override
+    public EvtAppStatResult start(EvtAppStat evtAppStat) throws Exception {
+        String packType = evtAppStat.getPackType();
+        String appId = evtAppStat.getAppId();
+
+        if (packType.equals(PackType.docker.name())) {
+            return dockerApp.start(appId);
+        } else {
+            throw new Exception("zip 打包没有实现");
+        }
+    }
+
+    @Override
+    public EvtAppStatResult stop(EvtAppStat evtAppStat) throws Exception {
+        String packType = evtAppStat.getPackType();
+        String appId = evtAppStat.getAppId();
+
+        if (packType.equals(PackType.docker.name())) {
+            return dockerApp.stop(appId);
+        } else {
+            throw new Exception("zip 打包没有实现");
+        }
+    }
+
+    @Override
+    public EvtAppStatResult restart(EvtAppStat evtAppStat) throws Exception {
+        String packType = evtAppStat.getPackType();
+        String appId = evtAppStat.getAppId();
+
+        if (packType.equals(PackType.docker.name())) {
+            return dockerApp.restart(appId);
+        } else {
+            throw new Exception("zip 打包没有实现");
+        }
+    }
+
+    @Override
+    public EvtAppStatResult stat(EvtAppStat evtAppStat) throws Exception {
+        String packType = evtAppStat.getPackType();
+        String appId = evtAppStat.getAppId();
+
+        if (packType.equals(PackType.docker.name())) {
+            return dockerApp.stat(appId);
+        } else {
+            throw new Exception("zip 打包没有实现");
+        }
+    }
+
+    @Override
+    public List<EvtAppStatResult> stat() throws Exception {
+        return dockerApp.stat();
+    }
+}

+ 122 - 0
common/src/main/java/cn/reghao/bnt/common/agent/app/iface/impl/DockerApp.java

@@ -0,0 +1,122 @@
+package cn.reghao.bnt.common.agent.app.iface.impl;
+
+import cn.reghao.bnt.common.docker.Docker;
+import cn.reghao.bnt.common.docker.DockerImpl;
+import cn.reghao.bnt.common.docker.model.Config;
+import cn.reghao.bnt.common.docker.model.DockerAuth;
+import cn.reghao.bnt.common.docker.model.HostConfig;
+import cn.reghao.bnt.common.machine.Machine;
+import cn.reghao.bnt.common.msg.constant.NodeStatus;
+import cn.reghao.bnt.common.msg.event.EvtAppDeploy;
+import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
+import cn.reghao.jutil.jdk.result.NotAvailable;
+import cn.reghao.jutil.jdk.converter.DateTimeConverter;
+import cn.reghao.jutil.jdk.serializer.JsonConverter;
+import com.github.dockerjava.api.command.InspectContainerResponse;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author reghao
+ * @date 2023-03-06 15:26:22
+ */
+public class DockerApp {
+    private Map<String, Docker> map = new HashMap<>();
+
+    public DockerApp(Docker docker) {
+        this.map.put("noAuth", docker);
+    }
+
+    public EvtAppStatResult deploy(EvtAppDeploy deployParam) throws Exception {
+        String appId = deployParam.getAppId();
+        String packagePath = deployParam.getPackagePath();
+        Config containerConfig = JsonConverter.jsonToObject(deployParam.getStartScript(), Config.class);
+        if (containerConfig == null) {
+            containerConfig = new Config(packagePath);
+        } else {
+            containerConfig.setImage(packagePath);
+            if (containerConfig.getHostConfig() == null) {
+                containerConfig.setHostConfig(new HostConfig());
+            }
+        }
+
+        Docker docker;
+        DockerAuth dockerAuth = deployParam.getDockerAuth();
+        if (dockerAuth != null) {
+            String registryUrl = dockerAuth.getRegistryUrl();
+            docker = map.get(registryUrl);
+            if (docker == null) {
+                // TODO DockerAuth 修改后 map 中的 Docker 实例无效
+                docker = new DockerImpl(dockerAuth);
+                map.put(registryUrl, docker);
+            }
+        } else {
+            docker = map.get("noAuth");
+        }
+        docker.pull(packagePath);
+        InspectContainerResponse containerInfo = docker.createAndRun(appId, containerConfig);
+        return getStat(appId, containerInfo);
+    }
+
+    public EvtAppStatResult start(String appId) throws Exception {
+        Docker docker = map.get("noAuth");
+        InspectContainerResponse containerInfo = docker.start(appId);
+        return getStat(appId, containerInfo);
+    }
+
+    public EvtAppStatResult stop(String appId) throws Exception {
+        Docker docker = map.get("noAuth");
+        InspectContainerResponse containerInfo = docker.stop(appId);
+        return getStat(appId, containerInfo);
+    }
+
+    public EvtAppStatResult restart(String appId) throws Exception {
+        Docker docker = map.get("noAuth");
+        InspectContainerResponse containerInfo = docker.restart(appId);
+        return getStat(appId, containerInfo);
+    }
+
+    public EvtAppStatResult stat(String appId) throws Exception {
+        Docker docker = map.get("noAuth");
+        InspectContainerResponse containerInfo = docker.inspectContainer(appId);
+        return getStat(appId, containerInfo);
+    }
+
+    public List<EvtAppStatResult> stat() throws Exception {
+        Docker docker = map.get("noAuth");
+        List<InspectContainerResponse> list = docker.psAll();
+        return list.stream().map(response -> {
+            String containerName = response.getName();
+            String appId = containerName.replace("/", "");
+            return getStat(appId, response);
+        }).collect(Collectors.toList());
+    }
+
+    private EvtAppStatResult getStat(String appId, InspectContainerResponse containerInfo) {
+        EvtAppStatResult appStatResult = new EvtAppStatResult(appId, Machine.ID);
+        String image = containerInfo.getConfig().getImage();
+        if (image != null && image.contains(":")) {
+            appStatResult.setCommitId(image.split(":")[1]);
+        } else {
+            appStatResult.setCommitId(NotAvailable.na.getDesc());
+        }
+
+        InspectContainerResponse.ContainerState state = containerInfo.getState();
+        if (state == null || Boolean.FALSE.equals(state.getRunning())) {
+            //appStatResult.setStatus(NodeStatus.Offline.name());
+            appStatResult.setStartTime(null);
+            appStatResult.setPid(-1);
+        } else {
+            String startedAt = state.getStartedAt();
+            //appStatResult.setStatus(NodeStatus.Online.name());
+            appStatResult.setRunning(true);
+            appStatResult.setStartTime(DateTimeConverter.localDateTime(startedAt));
+            appStatResult.setPid(state.getPidLong().intValue());
+        }
+
+        return appStatResult;
+    }
+}

+ 96 - 0
common/src/main/java/cn/reghao/bnt/common/agent/machine/MachineEvent.java

@@ -0,0 +1,96 @@
+package cn.reghao.bnt.common.agent.machine;
+
+import cn.reghao.bnt.common.agent.app.iface.AppStat;
+import cn.reghao.bnt.common.machine.Machine;
+import cn.reghao.bnt.common.msg.MessageSender;
+import cn.reghao.bnt.common.msg.event.EvtAgentHeartbeat;
+import cn.reghao.bnt.common.msg.event.EvtAgentStart;
+import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
+import cn.reghao.jutil.jdk.event.message.EventMessage;
+import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author reghao
+ * @date 2021-09-03 09:22:42
+ */
+@Slf4j
+public class MachineEvent {
+    private final ScheduledExecutorService scheduler;
+    private ScheduledFuture<?> heartbeatFuture;
+    private final Machine machine;
+    private final AppStat appStat;
+    private final MessageSender messageSender;
+    private final int heartbeatInterval;
+    
+    public MachineEvent(MessageSender messageSender, Machine machine, AppStat appStat,
+                        ScheduledExecutorService scheduler, int heartbeatInterval) {
+        this.messageSender = messageSender;
+        this.machine = machine;
+        this.appStat = appStat;
+        this.scheduler = scheduler;
+        this.heartbeatInterval = heartbeatInterval;
+    }
+
+    public void agentStart() {
+        EvtAgentStart evtAgentStart = machine.detail();
+        EventMessage eventMessage = EventMessage.evt(evtAgentStart);
+        pub(eventMessage);
+
+        try {
+            List<EvtAppStatResult> list = appStat.stat();
+            list.forEach(evtAppStatResult -> {
+                EventMessage eventMessage1 = EventMessage.evt(evtAppStatResult);
+                pub(eventMessage1);
+            });
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        agentHeartbeat();
+    }
+
+    public void agentShutdown() {
+        ThreadPoolWrapper.shutdownScheduler(scheduler);
+        EvtAgentHeartbeat machineStat = machine.stat();
+        EventMessage eventMessage = EventMessage.evt(machineStat);
+        pub(eventMessage);
+    }
+
+    public void agentHeartbeat() {
+        heartbeatFuture = scheduler.scheduleAtFixedRate(new Heartbeat(), 5, heartbeatInterval, TimeUnit.SECONDS);
+    }
+
+    public void pauseHeartbeat() {
+        if (!heartbeatFuture.isCancelled()) {
+            heartbeatFuture.cancel(true);
+        }
+    }
+
+    private void pub(EventMessage eventMessage) {
+        if (messageSender.isConnected()) {
+            try {
+                messageSender.send("", eventMessage);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        } else {
+            log.error("连接断开");
+        }
+    }
+
+    class Heartbeat implements Runnable {
+        @Override
+        public void run() {
+            EvtAgentHeartbeat machineStat = machine.stat();
+            EventMessage eventMessage = EventMessage.evt(machineStat);
+            pub(eventMessage);
+        }
+    }
+}

+ 34 - 0
common/src/main/java/cn/reghao/bnt/common/docker/Docker.java

@@ -0,0 +1,34 @@
+package cn.reghao.bnt.common.docker;
+
+import cn.reghao.bnt.common.docker.model.Config;
+import com.github.dockerjava.api.command.InspectContainerResponse;
+import com.github.dockerjava.api.model.Image;
+import com.github.dockerjava.api.model.Version;
+
+import java.util.List;
+
+/**
+ * Docker 客户端
+ *
+ * @author reghao
+ * @date 2021-10-27 04:17:38
+ */
+public interface Docker {
+    void auth();
+    Version version();
+    void build(String repoTag, String compileHome, String dockerfileContent) throws Exception;
+    void push(String image) throws Exception;
+    void pull(String repoTag) throws Exception;
+    void stopAndDelete(String containerName) throws Exception;
+    InspectContainerResponse createAndRun(String containerName, Config containerConfig) throws Exception;
+    void runAndRm(Config containerConfig) throws Exception;
+    InspectContainerResponse start(String containerName);
+    InspectContainerResponse stop(String containerName);
+    InspectContainerResponse restart(String containerName);
+    InspectContainerResponse inspectContainer(String containerName);
+    List<Image> images();
+    void imageRm(String imageId);
+    void rm(String containerId);
+    List<InspectContainerResponse> psAll();
+    InspectContainerResponse ps(String containerName);
+}

+ 438 - 0
common/src/main/java/cn/reghao/bnt/common/docker/DockerImpl.java

@@ -0,0 +1,438 @@
+package cn.reghao.bnt.common.docker;
+
+import cn.reghao.bnt.common.docker.model.DockerAuth;
+import cn.reghao.jutil.jdk.exception.ExceptionUtil;
+import cn.reghao.jutil.jdk.text.TextFile;
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.async.ResultCallback;
+import com.github.dockerjava.api.command.*;
+import com.github.dockerjava.api.model.*;
+import com.github.dockerjava.core.DefaultDockerClientConfig;
+import com.github.dockerjava.core.DockerClientConfig;
+import com.github.dockerjava.core.DockerClientImpl;
+import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
+import com.github.dockerjava.transport.DockerHttpClient;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.time.Duration;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * Docker 客户端
+ *
+ * @author reghao
+ * @date 2021-10-27 03:41:38
+ */
+@Slf4j
+public class DockerImpl implements Docker {
+    private DockerClient dockerClient;
+    private final TextFile textFile = new TextFile();
+    private final String unixSock = "/var/run/docker.sock";
+
+    public DockerImpl() {
+        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
+                .withDockerHost("unix://" + unixSock)
+                .withDockerTlsVerify(false)
+                //.withDockerCertPath(String.format("%s/.docker", System.getProperty("user.home")))
+                //.withRegistryUsername("username")
+                //.withRegistryPassword("password")
+                //.withRegistryEmail(registryMail)
+                //.withRegistryUrl(registryUrl)
+                .build();
+        init(config);
+    }
+
+    public DockerImpl(DockerAuth dockerAuth) {
+        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
+                .withDockerHost("unix://" + unixSock)
+                .withDockerTlsVerify(false)
+                //.withDockerCertPath(String.format("%s/.docker", System.getProperty("user.home")))
+                .withRegistryUrl(dockerAuth.getRegistryUrl())
+                .withRegistryUsername(dockerAuth.getUsername())
+                .withRegistryPassword(dockerAuth.getPassword())
+                //.withRegistryEmail(registryMail)
+                .build();
+        init(config);
+    }
+
+    private void init(DockerClientConfig config) {
+        DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
+                .dockerHost(config.getDockerHost())
+                .sslConfig(config.getSSLConfig())
+                .maxConnections(100)
+                .connectionTimeout(Duration.ofSeconds(60))
+                .responseTimeout(Duration.ofSeconds(60))
+                .build();
+        this.dockerClient = DockerClientImpl.getInstance(config, httpClient);
+    }
+
+    @Override
+    public void auth() {
+        dockerClient.authCmd().exec();
+    }
+
+    @Override
+    public Version version() {
+        return dockerClient.versionCmd().exec();
+    }
+
+    @Override
+    public void build(String repoTag, String compileHome, String dockerfileContent) throws Exception {
+        File dockerfile = new File(compileHome + "/Dockerfile.tmp");
+        try {
+            textFile.write(dockerfile, dockerfileContent);
+            String imageId = dockerClient.buildImageCmd()
+                    .withDockerfile(dockerfile)
+                    // repoTag 格式为 docker.reghao.cn/devops:12345678
+                    .withTags(Set.of(repoTag))
+                    .start()
+                    .awaitImageId(300, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            throw new Exception(ExceptionUtil.errorMsg(e));
+        }
+    }
+
+    public void build(String repoTag, String compileHome) throws Exception {
+        String dockerfilePath = compileHome + "/Dockerfile";
+        dockerClient.buildImageCmd()
+                .withDockerfile(new File(dockerfilePath))
+                .withTags(Set.of(repoTag))
+                .start()
+                .awaitImageId(300, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public void push(String image) throws Exception {
+        try {
+            ResultCallback.Adapter<PushResponseItem> callback = new PushCallback();
+            dockerClient.pushImageCmd(image)
+                    //.exec(new ResultCallback.Adapter<>())
+                    .exec(callback)
+                    .awaitCompletion(300, TimeUnit.SECONDS);
+            PushCallback pushCallback = (PushCallback) callback;
+            int code = pushCallback.getCode();
+            if (code != 0) {
+                throw new Exception(pushCallback.getMsg());
+            }
+        } catch (InterruptedException e) {
+            throw new Exception(ExceptionUtil.errorMsg(e));
+        }
+    }
+
+    @Override
+    public void pull(String image) throws Exception {
+        try {
+            dockerClient.pullImageCmd(image).exec(new PullImageResultCallback()).awaitCompletion();
+        } catch (InterruptedException e) {
+            throw new Exception(ExceptionUtil.errorMsg(e));
+        }
+        /*dockerClient.pullImageCmd(image).exec(new ResultCallback<PullResponseItem>() {
+            public void onStart(Closeable closeable) {
+                System.out.println("开始下载!");
+            }
+
+            public void onNext(PullResponseItem object) {
+                // 实时显示出下载信息
+                System.out.println(object.getStatus());
+            }
+
+            public void onError(Throwable throwable) {
+                throwable.printStackTrace();
+            }
+
+            public void onComplete() {
+                System.out.println("下载完毕!");
+            }
+
+            public void close() throws IOException {
+                System.out.println("下载完毕...");
+            }
+        }).onComplete();*/
+    }
+
+    private String getContainerIdByName(String containerName) {
+        List<Container> list = dockerClient.listContainersCmd()
+                .withShowAll(true)
+                .withNameFilter(List.of(containerName))
+                .exec();
+
+        for (Container container : list) {
+            Set<String> set = new HashSet<>(Arrays.asList(container.getNames()));
+            if (set.contains("/" + containerName)) {
+                return container.getId();
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void stopAndDelete(String containerName) {
+        String containerId = getContainerIdByName(containerName);
+        if (containerId != null) {
+            InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(containerId).exec();
+            InspectContainerResponse.ContainerState state = containerInfo.getState();
+            boolean isRunning = state.getRunning() != null ? state.getRunning() : false;
+            if (isRunning) {
+                dockerClient.stopContainerCmd(containerId).exec();
+            }
+            dockerClient.removeContainerCmd(containerId).exec();
+        }
+    }
+
+    @Override
+    public InspectContainerResponse createAndRun(String containerName, cn.reghao.bnt.common.docker.model.Config containerConfig) throws Exception {
+        stopAndDelete(containerName);
+
+        String image = containerConfig.getImage();
+        CreateContainerCmd createContainerCmd = dockerClient.createContainerCmd(image)
+                .withName(containerName);
+
+        List<String> env = containerConfig.getEnv();
+        if (env != null) {
+            createContainerCmd.withEnv(env);
+        }
+
+        RestartPolicy restartPolicy = RestartPolicy.onFailureRestart(3);
+        HostConfig hostConfig = HostConfig.newHostConfig()
+                // --init 参数
+                //.withInit(true)
+                .withNetworkMode("host")
+                .withRestartPolicy(restartPolicy);
+        if (containerConfig.getVolumes() != null) {
+            Map<String, String> map = containerConfig.getVolumes().getMap();
+            List<Bind> list = new ArrayList<>();
+            for (Map.Entry<String, String> entry : map.entrySet()) {
+                String key = entry.getKey();
+                String value = entry.getValue();
+                Volume volume2 = new Volume(value);
+                Bind bind = new Bind(key, volume2);
+                list.add(bind);
+            }
+            hostConfig.withBinds(list);
+        }
+
+        if (containerConfig.getHostConfig().getInit() != null) {
+            hostConfig.withInit(containerConfig.getHostConfig().getInit());
+        }
+
+        createContainerCmd.withHostConfig(hostConfig);
+        CreateContainerResponse response = createContainerCmd.exec();
+        String containerId = response.getId();
+        dockerClient.startContainerCmd(containerId).exec();
+        return dockerClient.inspectContainerCmd(containerId).exec();
+    }
+
+    public void runAndRm(cn.reghao.bnt.common.docker.model.Config containerConfig) throws Exception {
+        String image = containerConfig.getImage();
+        CreateContainerCmd createContainerCmd = dockerClient.createContainerCmd(image).withCmd("rm");
+
+        List<String> env = containerConfig.getEnv();
+        if (env != null) {
+            createContainerCmd.withEnv(env);
+        }
+
+        HostConfig hostConfig = HostConfig.newHostConfig()
+                .withNetworkMode("host")
+                .withRestartPolicy(RestartPolicy.noRestart());
+        if (containerConfig.getVolumes() != null) {
+            Map<String, String> map = containerConfig.getVolumes().getMap();
+            List<Bind> list = new ArrayList<>();
+            for (Map.Entry<String, String> entry : map.entrySet()) {
+                String hostPath = entry.getValue();
+                String containerPath = entry.getKey();
+
+                Volume volume2 = new Volume(containerPath);
+                Bind bind = new Bind(hostPath, volume2);
+                list.add(bind);
+            }
+            hostConfig.withBinds(list);
+        }
+
+        if (containerConfig.getCmd() != null) {
+            createContainerCmd.withCmd(containerConfig.getCmd());
+        }
+
+        createContainerCmd.withHostConfig(hostConfig);
+        CreateContainerResponse response = createContainerCmd.exec();
+        String containerId = response.getId();
+        dockerClient.startContainerCmd(containerId).exec();
+
+        List<String> list = new ArrayList<>();
+        LogContainerCmd logContainerCmd = dockerClient.logContainerCmd(containerId);
+        logContainerCmd.withStdOut(true).withStdErr(true).withFollowStream(true);
+        logContainerCmd.exec(new ResultCallback<Frame>() {
+            @Override
+            public void onStart(Closeable closeable) {
+            }
+
+            @Override
+            public void onNext(Frame object) {
+                if (object.getStreamType().equals(StreamType.STDERR)) {
+                    list.add(object.toString());
+                }
+            }
+
+            @Override
+            public void onError(Throwable throwable) {
+                log.info(throwable.toString());
+            }
+
+            @Override
+            public void onComplete() {
+            }
+
+            @Override
+            public void close() throws IOException {
+            }
+        });
+
+        dockerClient.waitContainerCmd(containerId).exec(new ResultCallback.Adapter<>())
+                .awaitCompletion(300, TimeUnit.SECONDS);
+
+        InspectContainerResponse response1 = dockerClient.inspectContainerCmd(containerId).exec();
+        InspectContainerResponse.ContainerState state = response1.getState();
+        Long exitCode = state.getExitCodeLong();
+        if (Boolean.TRUE.equals(state.getRunning())) {
+            dockerClient.stopContainerCmd(containerId).exec();
+            dockerClient.removeContainerCmd(containerId).exec();
+            throw new Exception("docker build timeout after 300 seconds");
+        } else if (exitCode != null && exitCode == 0) {
+            dockerClient.removeContainerCmd(containerId).exec();
+        } else {
+            dockerClient.removeContainerCmd(containerId).exec();
+            StringBuilder sb = new StringBuilder();
+            list.forEach(line -> {
+                sb.append(line).append(System.lineSeparator());
+            });
+            throw new Exception("docker build failed:\n" + sb.toString());
+        }
+    }
+
+    @Override
+    public InspectContainerResponse start(String containerName) {
+        String containerId = getContainerIdByName(containerName);
+        dockerClient.startContainerCmd(containerId).exec();
+        return dockerClient.inspectContainerCmd(containerId).exec();
+    }
+
+    @Override
+    public InspectContainerResponse stop(String containerName) {
+        String containerId = getContainerIdByName(containerName);
+        dockerClient.stopContainerCmd(containerId).exec();
+        return dockerClient.inspectContainerCmd(containerId).exec();
+    }
+
+    @Override
+    public InspectContainerResponse restart(String containerName) {
+        String containerId = getContainerIdByName(containerName);
+        dockerClient.restartContainerCmd(containerId).exec();
+        return dockerClient.inspectContainerCmd(containerId).exec();
+    }
+
+    @Override
+    public InspectContainerResponse inspectContainer(String containerName) {
+        String containerId = getContainerIdByName(containerName);
+        return dockerClient.inspectContainerCmd(containerId).exec();
+    }
+
+    @Override
+    public List<Image> images() {
+        List<Image> images = dockerClient.listImagesCmd().exec();
+        return images;
+        /*return images.stream().map(image -> {
+            long created = image.getCreated();
+            String[] repoTags = image.getRepoTags();
+            if (repoTags.length == 0) {
+                return null;
+            }
+
+            String imageId = image.getId();
+            String[] repoTag = repoTags[0].split(":");
+            String repo = repoTag[0];
+            String tag = repoTag[1];
+            LocalDateTime created1 = DateTimeConverter.localDateTime(created*1000);
+            return new ImageInfo(repo, tag, imageId, created1);
+        }).filter(Objects::nonNull).collect(Collectors.toList());*/
+    }
+
+    @Override
+    public void imageRm(String imageId) {
+        dockerClient.removeImageCmd(imageId).exec();
+    }
+
+    @Override
+    public void rm(String containerId) {
+        dockerClient.removeContainerCmd(containerId).exec();
+    }
+
+    @Override
+    public List<InspectContainerResponse> psAll() {
+        List<Container> list = dockerClient.listContainersCmd()
+                .withShowAll(true)
+                .exec();
+        return list.stream().map(container -> {
+            String containerId = container.getId();
+            return dockerClient.inspectContainerCmd(containerId).exec();
+        }).collect(Collectors.toList());
+    }
+
+    @Override
+    public InspectContainerResponse ps(String appId) {
+        List<Container> list = dockerClient.listContainersCmd()
+                .withNameFilter(List.of(appId))
+                .exec();
+
+        if (list.isEmpty()) {
+            return null;
+        }
+
+        Container container = list.get(0);
+        String containerId = container.getId();
+        return dockerClient.inspectContainerCmd(containerId).exec();
+    }
+
+    static class PushCallback extends ResultCallback.Adapter<PushResponseItem> {
+        private int code;
+        private String msg;
+
+        public PushCallback() {
+            this.code = 0;
+        }
+
+        public int getCode() {
+            return code;
+        }
+
+        public String getMsg() {
+            return msg;
+        }
+
+        @Override
+        public void onNext(PushResponseItem object) {
+            PushResponseItem.ErrorDetail errorDetail = object.getErrorDetail();
+            if (errorDetail != null) {
+                //log.info("error: {} {}", errorDetail.getCode(), errorDetail.getMessage());
+                code = 1;
+                msg = errorDetail.getMessage();
+            } else {
+                //log.info("info: {} {} {}", object.getStatus(), object.getId(), object.getProgressDetail());
+            }
+        }
+
+        @Override
+        public void onComplete() {
+            super.onComplete();
+        }
+
+        @Override
+        public void onError(Throwable throwable) {
+            throwable.printStackTrace();
+        }
+    }
+}

+ 55 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/Config.java

@@ -0,0 +1,55 @@
+package cn.reghao.bnt.common.docker.model;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * docker 容器创建时的配置
+ *
+ * @author reghao
+ * @date 2020-01-14 23:11:21
+ */
+@Data
+public class Config implements Cloneable {
+    @SerializedName("AttachStderr") private boolean attachStderr;
+    @SerializedName("AttachStdin") private boolean attachStdin;
+    @SerializedName("AttachStdout") private boolean attachStdout;
+    @SerializedName("Cmd") private List<String> cmd;
+    @SerializedName("Domainname") private String domainname;
+    @SerializedName("Env") private List<String> env;
+    @SerializedName("Healthcheck") private Healthcheck healthcheck;
+    @SerializedName("Hostname") private String hostname;
+    @SerializedName("Image") private String image;
+    @SerializedName("Labels") private Labels labels;
+    @SerializedName("MacAddress") private String macAddress;
+    @SerializedName("NetworkDisabled") private boolean networkDisabled;
+    @SerializedName("OpenStdin") private boolean openStdin;
+    @SerializedName("StdinOnce") private boolean stdinOnce;
+    @SerializedName("Tty") private boolean tty;
+    @SerializedName("User") private String user;
+    @SerializedName("Volumes") private Volumes volumes;
+    @SerializedName("WorkingDir") private String workingDir;
+    @SerializedName("StopSignal") private String stopSignal;
+    @SerializedName("StopTimeout") private int stopTimeout;
+
+    @SerializedName("Entrypoint") private String entrypoint;
+    @SerializedName("ExposedPorts") private ExposedPorts exposedPorts;
+    @SerializedName("HostConfig") private HostConfig hostConfig;
+    @SerializedName("NetworkingConfig") private NetworkingConfig networkingConfig;
+
+    public Config() {
+        this.hostConfig = new HostConfig();
+    }
+
+    public Config(String image) {
+        this.image = image;
+        this.hostConfig = new HostConfig();
+    }
+
+    @Override
+    public Object clone() throws CloneNotSupportedException {
+        return super.clone();
+    }
+}

+ 20 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/DockerAuth.java

@@ -0,0 +1,20 @@
+package cn.reghao.bnt.common.docker.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.io.Serializable;
+
+/**
+ * @author reghao
+ * @date 2024-07-26 17:29:56
+ */
+@AllArgsConstructor
+@Getter
+public class DockerAuth implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String registryUrl;
+    private String username;
+    private String password;
+}

+ 11 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/ExposedPorts.java

@@ -0,0 +1,11 @@
+package cn.reghao.bnt.common.docker.model;
+
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2021-02-10 01:30:17
+ */
+@Data
+public class ExposedPorts {
+}

+ 15 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/Healthcheck.java

@@ -0,0 +1,15 @@
+package cn.reghao.bnt.common.docker.model;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2021-02-25 10:02:59
+ */
+@Data
+public class Healthcheck {
+    @SerializedName("Test") private List<String> test;
+}

+ 24 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/HostConfig.java

@@ -0,0 +1,24 @@
+package cn.reghao.bnt.common.docker.model;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * TODO 部分
+ *
+ * @author reghao
+ * @date 2020-01-14 23:16:52
+ */
+@AllArgsConstructor
+@Data
+public class HostConfig {
+    @SerializedName("NetworkMode") private String networkMode;
+    @SerializedName("RestartPolicy") private RestartPolicy restartPolicy;
+    @SerializedName("Init") private Boolean init;
+
+    public HostConfig() {
+        this.networkMode = "host";
+        this.restartPolicy = new RestartPolicy();
+    }
+}

+ 14 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/Labels.java

@@ -0,0 +1,14 @@
+package cn.reghao.bnt.common.docker.model;
+
+import lombok.Data;
+
+import java.util.Map;
+
+/**
+ * @author reghao
+ * @date 2021-02-10 01:28:38
+ */
+@Data
+public class Labels {
+    private Map<String, String> map;
+}

+ 11 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/NetworkingConfig.java

@@ -0,0 +1,11 @@
+package cn.reghao.bnt.common.docker.model;
+
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2021-02-10 01:33:05
+ */
+@Data
+public class NetworkingConfig {
+}

+ 21 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/RestartPolicy.java

@@ -0,0 +1,21 @@
+package cn.reghao.bnt.common.docker.model;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2020-05-19 15:00:50
+ */
+@AllArgsConstructor
+@Data
+public class RestartPolicy {
+    @SerializedName("Name") private String name;
+    @SerializedName("MaximumRetryCount") private int maximumRetryCount;
+
+    public RestartPolicy() {
+        this.name = "on-failure";
+        this.maximumRetryCount = 3;
+    }
+}

+ 15 - 0
common/src/main/java/cn/reghao/bnt/common/docker/model/Volumes.java

@@ -0,0 +1,15 @@
+package cn.reghao.bnt.common.docker.model;
+
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author reghao
+ * @date 2021-02-10 01:29:10
+ */
+@Data
+public class Volumes {
+    private Map<String, String> map = new HashMap<>();
+}

+ 40 - 0
common/src/main/java/cn/reghao/bnt/common/machine/CPU.java

@@ -0,0 +1,40 @@
+package cn.reghao.bnt.common.machine;
+
+import cn.reghao.bnt.common.machine.model.CPUInfo;
+import cn.reghao.jutil.jdk.machine.data.MachineData;
+import cn.reghao.jutil.jdk.machine.data.detail.CpuDetail;
+import cn.reghao.jutil.jdk.machine.data.stat.CpuStat;
+import oshi.SystemInfo;
+import oshi.hardware.CentralProcessor;
+import oshi.hardware.HardwareAbstractionLayer;
+
+/**
+ * @author reghao
+ * @date 2019-10-25 13:12:36
+ */
+public class CPU implements MachineData<CpuDetail, CpuStat> {
+    private final CentralProcessor processor;
+
+    public CPU(SystemInfo si) {
+        this.processor = si.getHardware().getProcessor();
+    }
+
+    @Override
+    public CpuDetail detail() {
+        CentralProcessor.ProcessorIdentifier processorIdentifier = processor.getProcessorIdentifier();
+        String vendor = processorIdentifier.getVendor();
+        String name = processorIdentifier.getName();
+        int physicalCore = processor.getPhysicalProcessorCount();
+        int logicalCore = processor.getLogicalProcessorCount();
+        return new CpuDetail(vendor, name, physicalCore, logicalCore);
+    }
+
+    @Override
+    public CpuStat stat() {
+        return null;
+    }
+
+    public CPUInfo getCPUInfo() {
+        return null;
+    }
+}

+ 158 - 0
common/src/main/java/cn/reghao/bnt/common/machine/Disk.java

@@ -0,0 +1,158 @@
+package cn.reghao.bnt.common.machine;
+
+import cn.reghao.bnt.common.machine.model.DiskInfo;
+import cn.reghao.bnt.common.machine.model.DiskPartition;
+import cn.reghao.jutil.jdk.converter.ByteConverter;
+import cn.reghao.jutil.jdk.machine.data.MachineData;
+import cn.reghao.jutil.jdk.machine.data.detail.DiskDetail;
+import cn.reghao.jutil.jdk.machine.data.stat.DiskStat;
+import cn.reghao.jutil.jdk.math.Calculator;
+import oshi.SystemInfo;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.OperatingSystem;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author reghao
+ * @date 2019-10-25 13:21:25
+ */
+public class Disk implements MachineData<List<DiskDetail>, List<DiskStat>> {
+    private final HardwareAbstractionLayer hal;
+    private final OperatingSystem os;
+    private final ByteConverter byteConverter;
+
+    public Disk(SystemInfo si, ByteConverter byteConverter) {
+        this.hal = si.getHardware();
+        this.os = si.getOperatingSystem();
+        this.byteConverter = byteConverter;
+    }
+
+    @Override
+    public List<DiskDetail> detail() {
+        return os.getFileSystem().getFileStores().stream()
+                .filter(osFileStore -> osFileStore.getVolume().startsWith("/dev/"))
+                .map(osFileStore -> {
+                    String vol = osFileStore.getVolume();
+                    String mount = osFileStore.getMount();
+                    String fsType = osFileStore.getType();
+
+                    long total = osFileStore.getTotalSpace();
+                    // non-root 用户可用的磁盘空间
+                    long userAvail = osFileStore.getUsableSpace();
+                    // root 用户可用的磁盘空间
+                    long rootAvail = osFileStore.getFreeSpace();
+
+                    long inodeTotal = osFileStore.getTotalInodes();
+                    long inodeFree = osFileStore.getFreeInodes();
+
+                    return new DiskDetail(vol, mount, fsType, total, userAvail, total-userAvail, inodeTotal, inodeFree);
+                })
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<DiskStat> stat() {
+        return null;
+    }
+
+    /**
+     * 根据一个路径确定它所在的分区
+     *
+     * @param
+     * @return
+     * @date 2021-02-06 下午11:25
+     */
+    public DiskDetail diskDetail(String path) {
+        List<DiskDetail> diskInfos = detail();
+        // 根据挂载路径的长度降序
+        diskInfos.sort((o1, o2) -> o2.getMountedOn().length() - o1.getMountedOn().length());
+
+        List<DiskDetail> candidates = new ArrayList<>();
+        for (DiskDetail diskInfo : diskInfos) {
+            String mountedOn = diskInfo.getMountedOn();
+            String[] array = path.split(mountedOn);
+            if (array.length == 0) {
+                return diskInfo;
+            } else if (array.length == 2) {
+                if (array[1].startsWith("/") || "/".equals(mountedOn)) {
+                    candidates.add(diskInfo);
+                }
+            } else if (array.length > 2) {
+                candidates.add(diskInfo);
+            }
+        }
+
+        if (!candidates.isEmpty()) {
+            // TODO 如果 candidates 大于 0 则判断准确的那个
+            return candidates.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    public List<DiskInfo> getDisks() {
+        List<DiskInfo> diskInfoList = new ArrayList<>();
+        hal.getDiskStores().forEach(hwDiskStore -> {
+            String model = hwDiskStore.getModel();
+            String name = hwDiskStore.getName();
+            long size = hwDiskStore.getSize();
+            String sizeStr = byteConverter.convert(size);
+            DiskInfo diskInfo = new DiskInfo(model, name, size, sizeStr);
+            hwDiskStore.getPartitions().forEach(hwPartition -> {
+                String uuid = hwPartition.getUuid();
+                String id = hwPartition.getIdentification();
+                String mountedOn = hwPartition.getMountPoint();
+                String fsType = hwPartition.getType();
+                long pSize = hwPartition.getSize();
+
+                DiskPartition diskPartition = new DiskPartition(name, pSize, uuid, id, mountedOn, fsType);
+                diskPartition.setTotalSpace(pSize);
+                diskInfo.getDiskPartitionList().add(diskPartition);
+            });
+
+            diskInfoList.add(diskInfo);
+        });
+
+        Map<String, DiskPartition> map = diskInfoList.stream()
+                .map(DiskInfo::getDiskPartitionList)
+                .flatMap(Collection::stream)
+                .collect(Collectors.groupingBy(DiskPartition::getUuid,
+                        Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
+        os.getFileSystem().getFileStores().forEach(osFileStore -> {
+            String uuid = osFileStore.getUUID();
+            String vol = osFileStore.getVolume();
+            long totalSpace = osFileStore.getTotalSpace();
+            String totalSpaceStr = byteConverter.convert(totalSpace);
+            long freeSpace = osFileStore.getFreeSpace();
+            String freeSpaceStr = byteConverter.convert(freeSpace);
+            long usableSpace = osFileStore.getUsableSpace();
+            String usableSpaceStr = byteConverter.convert(usableSpace);
+            long totalInode = osFileStore.getTotalInodes();
+            long freeInode = osFileStore.getFreeInodes();
+
+            DiskPartition diskPartition = map.get(uuid);
+            if (diskPartition != null) {
+                diskPartition.setTotalSpace(totalSpace);
+                diskPartition.setTotalSpaceStr(totalSpaceStr);
+                diskPartition.setFreeSpace(freeSpace);
+                diskPartition.setFreeSpaceStr(freeSpaceStr);
+                diskPartition.setUsableSpace(usableSpace);
+                diskPartition.setUsableSpaceStr(usableSpaceStr);
+                double freeSpacePercent = Calculator.divide(freeSpace, totalSpace)*100;
+                diskPartition.setFreeSpacePercent(freeSpacePercent);
+
+                diskPartition.setTotalInode(totalInode);
+                diskPartition.setFreeInode(freeInode);
+                double freeInodePercent = Calculator.divide(freeInode, totalInode)*100;
+                diskPartition.setFreeInodePercent(freeInodePercent);
+            }
+        });
+
+        return diskInfoList;
+    }
+}

+ 76 - 0
common/src/main/java/cn/reghao/bnt/common/machine/Machine.java

@@ -0,0 +1,76 @@
+package cn.reghao.bnt.common.machine;
+
+import cn.reghao.bnt.common.msg.event.EvtAgentHeartbeat;
+import cn.reghao.bnt.common.msg.event.EvtAgentStart;
+import cn.reghao.jutil.jdk.converter.ByteConverter;
+import cn.reghao.jutil.jdk.machine.data.detail.*;
+import cn.reghao.jutil.jdk.machine.id.MachineId;
+import cn.reghao.jutil.jdk.machine.id.MachineIdLinux;
+import cn.reghao.jutil.jdk.result.AppVersion;
+import oshi.SystemInfo;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.OperatingSystem;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author reghao
+ * @date 2020-10-22 15:47:58
+ */
+public class Machine {
+    public final static String ID;
+    public final static String IPV4;
+    static {
+        MachineId machineId = new MachineIdLinux();
+        ID = machineId.id();
+        // TODO ip 发生变化时会引发数据不一致
+        IPV4 = machineId.ipv4();
+    }
+
+    private final CPU cpu;
+    private final Memory memory;
+    private final Disk disk;
+    private final Network network;
+    private final OS os;
+
+    public Machine() {
+        ByteConverter byteConverter = new ByteConverter();
+        SystemInfo si = new SystemInfo();
+        HardwareAbstractionLayer hal = si.getHardware();
+        OperatingSystem operatingSystem = si.getOperatingSystem();
+
+        this.cpu = new CPU(si);
+        this.memory = new Memory(si, byteConverter);
+        this.disk = new Disk(si, byteConverter);
+        this.network = new Network(si, byteConverter);
+        this.os = new OS(si, byteConverter);
+    }
+
+    public EvtAgentStart detail() {
+        EvtAgentStart machineDetail = new EvtAgentStart();
+        machineDetail.setMachineId(Machine.ID);
+        machineDetail.setAppVersion(AppVersion.getVersion());
+
+        machineDetail.setOsDetail(os.detail());
+        List<NetworkDetail> list = network.detail().stream()
+                .peek(networkDetail -> {
+                    networkDetail.setPubicIpv4("0.0.0.0");
+                })
+                .collect(Collectors.toList());
+        machineDetail.setNetworkDetails(list);
+
+        machineDetail.setCpuDetail(cpu.detail());
+        machineDetail.setMemoryDetail(memory.detail());
+        machineDetail.setDiskDetails(disk.detail());
+        return machineDetail;
+    }
+
+    public EvtAgentHeartbeat stat() {
+        EvtAgentHeartbeat machineStat = new EvtAgentHeartbeat();
+        machineStat.setMachineId(Machine.ID);
+        machineStat.setMemoryDetail(memory.detail());
+        machineStat.setDiskDetails(disk.detail());
+        return machineStat;
+    }
+}

+ 76 - 0
common/src/main/java/cn/reghao/bnt/common/machine/Memory.java

@@ -0,0 +1,76 @@
+package cn.reghao.bnt.common.machine;
+
+import cn.reghao.bnt.common.machine.model.MemoryInfo;
+import cn.reghao.bnt.common.machine.model.MemoryStat;
+import cn.reghao.jutil.jdk.converter.ByteConverter;
+import cn.reghao.jutil.jdk.machine.data.MachineData;
+import cn.reghao.jutil.jdk.machine.data.detail.MemoryDetail;
+import cn.reghao.jutil.jdk.math.Calculator;
+import oshi.SystemInfo;
+import oshi.hardware.GlobalMemory;
+import oshi.hardware.VirtualMemory;
+
+/**
+ * @author reghao
+ * @date 2019-10-25 13:21:25
+ */
+public class Memory implements MachineData<MemoryDetail, MemoryStat> {
+    private final GlobalMemory globalMemory;
+    private final VirtualMemory virtualMemory;
+    private MemoryDetail memoryDetail;
+    private ByteConverter byteConverter;
+
+    public Memory(SystemInfo si, ByteConverter byteConverter) {
+        GlobalMemory globalMemory = si.getHardware().getMemory();
+        this.globalMemory = globalMemory;
+        this.virtualMemory = globalMemory.getVirtualMemory();
+        this.byteConverter = byteConverter;
+    }
+
+    @Override
+    public MemoryDetail detail() {
+        long total = globalMemory.getTotal();
+        long avail = globalMemory.getAvailable();
+        long swapTotal = virtualMemory.getSwapTotal();
+        long swapUsed = virtualMemory.getSwapUsed();
+
+        if (memoryDetail == null) {
+            memoryDetail = new MemoryDetail(total, avail, total-avail, swapTotal, swapTotal-swapUsed);
+        }
+
+        return memoryDetail;
+    }
+
+    @Override
+    public MemoryStat stat() {
+        if (memoryDetail == null) {
+            memoryDetail = detail();
+        }
+
+        long total = globalMemory.getTotal();
+        long avail = globalMemory.getAvailable();
+        memoryDetail.setAvail(avail);
+        memoryDetail.setUsed(total-avail);
+
+        long swapTotal = virtualMemory.getSwapTotal();
+        long swapUsed = virtualMemory.getSwapUsed();
+        memoryDetail.setAvail(swapTotal-swapUsed);
+        return null;
+    }
+
+    public MemoryInfo getMemoryInfo() {
+        long total = globalMemory.getTotal();
+        String totalStr = byteConverter.convert(total);
+        long avail = globalMemory.getAvailable();
+        String availStr = byteConverter.convert(avail);
+        double availPercent = Calculator.divide(avail, total)*100;
+
+        long swapTotal = virtualMemory.getSwapTotal();
+        String swapTotalStr = byteConverter.convert(swapTotal);
+        long swapAvail = swapTotal - virtualMemory.getSwapUsed();
+        String swapAvailStr = byteConverter.convert(swapAvail);
+        double swapPercent = Calculator.divide(swapAvail, swapTotal)*100;
+        return new MemoryInfo(total, totalStr, avail, availStr, availPercent,
+                swapTotal, swapTotalStr, swapAvail, swapAvailStr, swapPercent);
+    }
+}

+ 107 - 0
common/src/main/java/cn/reghao/bnt/common/machine/Network.java

@@ -0,0 +1,107 @@
+package cn.reghao.bnt.common.machine;
+
+import cn.reghao.bnt.common.machine.model.NetworkCard;
+import cn.reghao.jutil.jdk.converter.ByteConverter;
+import cn.reghao.jutil.jdk.machine.data.MachineData;
+import cn.reghao.jutil.jdk.machine.data.detail.NetworkDetail;
+import cn.reghao.jutil.jdk.machine.data.stat.NetworkStat;
+import oshi.SystemInfo;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.OperatingSystem;
+
+import java.net.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2021-10-16 18:45:39
+ */
+public class Network implements MachineData<List<NetworkDetail>, NetworkStat> {
+    private final HardwareAbstractionLayer hal;
+    private OperatingSystem os;
+    private final ByteConverter byteConverter;
+
+    public Network(SystemInfo si, ByteConverter byteConverter) {
+        this.hal = si.getHardware();
+        this.os = si.getOperatingSystem();
+        this.byteConverter = byteConverter;
+    }
+
+    @Override
+    public List<NetworkDetail> detail() {
+        List<NetworkDetail> list = new ArrayList<>();
+        try {
+            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+            // 遍历主机的网络接口
+            while (interfaces.hasMoreElements()) {
+                NetworkInterface iface = interfaces.nextElement();
+                String ifaceName = iface.getName();
+                // 过滤掉 localhost 和虚拟网卡
+                if (ifaceName.startsWith("enp")
+                        || ifaceName.startsWith("wlp")
+                        || ifaceName.startsWith("eth")
+                        || ifaceName.startsWith("wlan")
+                        || ifaceName.startsWith("em")) {
+                    String ifaceMac = macAddr(iface.getHardwareAddress());
+                    NetworkDetail networkDetail = new NetworkDetail(ifaceName, ifaceMac);
+
+                    Enumeration<InetAddress> inetAddrs = iface.getInetAddresses();
+                    while (inetAddrs.hasMoreElements()) {
+                        InetAddress address = inetAddrs.nextElement();
+                        if (!address.isLoopbackAddress()) {
+                            if (address instanceof Inet4Address) {
+                                networkDetail.setIpv4(address.getHostAddress());
+                            } else if (address instanceof Inet6Address) {
+                                networkDetail.setIpv6(address.getHostAddress());
+                            }
+                        }
+                    }
+
+                    list.add(networkDetail);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return list;
+    }
+
+    /**
+     * 返回 52-54-00-bf-ab-2d 格式的 MAC 地址
+     *
+     * @param
+     * @return
+     * @date 2020-10-14 下午1:53
+     */
+    private static String macAddr(byte[] addr) {
+        String[] hexadecimal = new String[addr.length];
+        for (int i = 0; i < addr.length; i++) {
+            hexadecimal[i] = String.format("%02x", addr[i]);
+        }
+        return String.join("-", hexadecimal);
+    }
+
+    @Override
+    public NetworkStat stat() {
+        return null;
+    }
+
+    public List<NetworkCard> getNetworkCards() {
+        List<NetworkCard> list = new ArrayList<>();
+        hal.getNetworkIFs().forEach(net -> {
+            String iface = net.getName();
+            String mac = net.getMacaddr();
+            String ipv4 = Arrays.toString(net.getIPv4addr());
+            String ipv6 = Arrays.toString(net.getIPv6addr());
+            long mtu = net.getMTU();
+            long speed = net.getSpeed();
+            String speedStr = byteConverter.convert(speed);
+            list.add(new NetworkCard(iface, mac, ipv4, ipv6, mtu, speed, speedStr));
+        });
+
+        return list;
+    }
+}

+ 40 - 0
common/src/main/java/cn/reghao/bnt/common/machine/OS.java

@@ -0,0 +1,40 @@
+package cn.reghao.bnt.common.machine;
+
+import cn.reghao.jutil.jdk.converter.ByteConverter;
+import cn.reghao.jutil.jdk.machine.data.MachineData;
+import cn.reghao.jutil.jdk.machine.data.detail.OsDetail;
+import cn.reghao.jutil.jdk.machine.data.stat.OsStat;
+import oshi.SystemInfo;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.OperatingSystem;
+
+/**
+ * @author reghao
+ * @date 2020-10-20 23:17:30
+ */
+public class OS implements MachineData<OsDetail, OsStat> {
+    private final HardwareAbstractionLayer hal;
+    private OperatingSystem os;
+    private final ByteConverter byteConverter;
+
+    public OS(SystemInfo si, ByteConverter byteConverter) {
+        this.hal = si.getHardware();
+        this.os = si.getOperatingSystem();
+        this.byteConverter = byteConverter;
+    }
+
+    @Override
+    public OsDetail detail() {
+        OsDetail osDetail = new OsDetail();
+        osDetail.setBootTime(os.getSystemBootTime());
+        return osDetail;
+    }
+
+    @Override
+    public OsStat stat() {
+        return null;
+    }
+
+    public void getOSInfo() {
+    }
+}

+ 8 - 0
common/src/main/java/cn/reghao/bnt/common/machine/model/CPUInfo.java

@@ -0,0 +1,8 @@
+package cn.reghao.bnt.common.machine.model;
+
+/**
+ * @author reghao
+ * @date 2025-09-26 17:29:00
+ */
+public class CPUInfo {
+}

+ 31 - 0
common/src/main/java/cn/reghao/bnt/common/machine/model/DiskInfo.java

@@ -0,0 +1,31 @@
+package cn.reghao.bnt.common.machine.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2025-09-26 13:51:05
+ */
+@AllArgsConstructor
+@Getter
+@Setter
+public class DiskInfo {
+    private String model;
+    private String name;
+    private long size;
+    private String sizeStr;
+    private List<DiskPartition> diskPartitionList;
+
+    public DiskInfo(String model, String name, long size, String sizeStr) {
+        this.model = model;
+        this.name = name;
+        this.size = size;
+        this.sizeStr = sizeStr;
+        this.diskPartitionList = new ArrayList<>();
+    }
+}

+ 40 - 0
common/src/main/java/cn/reghao/bnt/common/machine/model/DiskPartition.java

@@ -0,0 +1,40 @@
+package cn.reghao.bnt.common.machine.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author reghao
+ * @date 2025-09-26 13:51:15
+ */
+@AllArgsConstructor
+@Getter
+@Setter
+public class DiskPartition {
+    private String diskName;
+    private long partitionSize;
+    private String uuid;
+    private String vol;
+    private String mountedOn;
+    private String fsType;
+    private long totalSpace;
+    private String totalSpaceStr;
+    private long freeSpace;
+    private String freeSpaceStr;
+    private double freeSpacePercent;
+    private long usableSpace;
+    private String usableSpaceStr;
+    private long totalInode;
+    private long freeInode;
+    private double freeInodePercent;
+
+    public DiskPartition(String diskName, long partitionSize, String uuid, String vol, String mountedOn, String fsType) {
+        this.diskName = diskName;
+        this.partitionSize = partitionSize;
+        this.uuid = uuid;
+        this.vol = vol;
+        this.mountedOn = mountedOn;
+        this.fsType = fsType;
+    }
+}

+ 28 - 0
common/src/main/java/cn/reghao/bnt/common/machine/model/MemoryInfo.java

@@ -0,0 +1,28 @@
+package cn.reghao.bnt.common.machine.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author reghao
+ * @date 2025-09-26 17:29:17
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class MemoryInfo {
+    private long total;
+    private String totalStr;
+    private long avail;
+    private String availStr;
+    private double availPercent;
+
+    private long swapTotal;
+    private String swapTotalStr;
+    private long swapAvail;
+    private String swapAvailStr;
+    private double swapAvailPercent;
+}

+ 27 - 0
common/src/main/java/cn/reghao/bnt/common/machine/model/MemoryStat.java

@@ -0,0 +1,27 @@
+package cn.reghao.bnt.common.machine.model;
+
+import cn.reghao.jutil.jdk.converter.ByteConverter;
+import cn.reghao.jutil.jdk.converter.ByteType;
+import lombok.Data;
+
+import java.lang.management.MemoryUsage;
+
+/**
+ * @author reghao
+ * @date 2020-10-21 15:49:56
+ */
+@Data
+public class MemoryStat {
+    private String init;
+    private String max;
+    private String used;
+    private String committed;
+
+    public MemoryStat(MemoryUsage memoryUsage) {
+        ByteConverter convert = new ByteConverter();
+        this.init = convert.convert(memoryUsage.getInit());
+        this.max = convert.convert(memoryUsage.getMax());
+        this.used = convert.convert(memoryUsage.getUsed());
+        this.committed = convert.convert(memoryUsage.getCommitted());
+    }
+}

+ 20 - 0
common/src/main/java/cn/reghao/bnt/common/machine/model/NetworkCard.java

@@ -0,0 +1,20 @@
+package cn.reghao.bnt.common.machine.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author reghao
+ * @date 2025-09-26 16:59:22
+ */
+@AllArgsConstructor
+@Getter
+public class NetworkCard {
+    private String iface;
+    private String mac;
+    private String ipv4;
+    private String ipv6;
+    private long mtu;
+    private long speed;
+    private String speedStr;
+}

+ 17 - 0
common/src/main/java/cn/reghao/bnt/common/msg/MessageSender.java

@@ -0,0 +1,17 @@
+package cn.reghao.bnt.common.msg;
+
+import java.io.IOException;
+
+/**
+ * @author reghao
+ * @date 2023-02-23 09:25:57
+ */
+public interface MessageSender {
+    default void connect() {
+    }
+    void setConnected(boolean status);
+    boolean isConnected();
+    void send(String dest, Object message) throws IOException;
+    default void close() {
+    }
+}

+ 9 - 0
common/src/main/java/cn/reghao/bnt/common/msg/constant/AppId.java

@@ -0,0 +1,9 @@
+package cn.reghao.bnt.common.msg.constant;
+
+/**
+ * @author reghao
+ * @date 2021-08-27 17:32:08
+ */
+public enum AppId {
+    mgr, build, agent
+}

+ 9 - 0
common/src/main/java/cn/reghao/bnt/common/msg/constant/AppStatOps.java

@@ -0,0 +1,9 @@
+package cn.reghao.bnt.common.msg.constant;
+
+/**
+ * @author reghao
+ * @date 2020-12-25 19:15:00
+ */
+public enum AppStatOps {
+    start, stop, restart, stat
+}

+ 21 - 0
common/src/main/java/cn/reghao/bnt/common/msg/constant/NodeStatus.java

@@ -0,0 +1,21 @@
+package cn.reghao.bnt.common.msg.constant;
+
+/**
+ * @author reghao
+ * @date 2021-08-27 17:33:20
+ */
+public enum NodeStatus {
+    Online(1),
+    Offline(2),
+    Deprecated(3);
+
+    private final Integer code;
+
+    NodeStatus(Integer code) {
+        this.code = code;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+}

+ 20 - 0
common/src/main/java/cn/reghao/bnt/common/msg/constant/PackType.java

@@ -0,0 +1,20 @@
+package cn.reghao.bnt.common.msg.constant;
+
+/**
+ * 打包方式类型
+ *
+ * @author reghao
+ * @date 2019-11-15 21:59:35
+ */
+public enum PackType {
+    //docker, zip;
+    docker, zip, staticFiles;
+
+    public String getName() {
+        return this.name();
+    }
+
+    public String getValue() {
+        return this.name();
+    }
+}

+ 26 - 0
common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAgentHeartbeat.java

@@ -0,0 +1,26 @@
+package cn.reghao.bnt.common.msg.event;
+
+import cn.reghao.jutil.jdk.event.message.Event;
+import cn.reghao.jutil.jdk.machine.data.detail.DiskDetail;
+import cn.reghao.jutil.jdk.machine.data.detail.MemoryDetail;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2022-05-05 13:59:15
+ */
+@Getter
+@Setter
+public class EvtAgentHeartbeat extends Event {
+    private String machineId;
+    private MemoryDetail memoryDetail;
+    private List<DiskDetail> diskDetails;
+    private Long timestamp;
+
+    public EvtAgentHeartbeat() {
+        this.timestamp = System.currentTimeMillis();
+    }
+}

+ 33 - 0
common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAgentStart.java

@@ -0,0 +1,33 @@
+package cn.reghao.bnt.common.msg.event;
+
+import cn.reghao.jutil.jdk.result.AppVersion;
+import cn.reghao.jutil.jdk.event.message.Event;
+import cn.reghao.jutil.jdk.machine.data.detail.*;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2022-05-05 13:59:15
+ */
+@Getter
+@Setter
+public class EvtAgentStart extends Event {
+    @Deprecated
+    private String protocol;
+    private String machineId;
+    private AppVersion appVersion;
+
+    private OsDetail osDetail;
+    private List<NetworkDetail> networkDetails;
+    private CpuDetail cpuDetail;
+    private MemoryDetail memoryDetail;
+    private List<DiskDetail> diskDetails;
+    private Long timestamp;
+
+    public EvtAgentStart() {
+        this.timestamp = System.currentTimeMillis();
+    }
+}

+ 21 - 0
common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAppDeploy.java

@@ -0,0 +1,21 @@
+package cn.reghao.bnt.common.msg.event;
+
+import cn.reghao.bnt.common.docker.model.DockerAuth;
+import cn.reghao.jutil.jdk.event.message.Event;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author reghao
+ * @date 2022-05-05 13:56:22
+ */
+@Getter
+@Setter
+public class EvtAppDeploy extends Event {
+    private String packType;
+    private String appId;
+    private String packagePath;
+    private String startScript;
+    private String startHome;
+    private DockerAuth dockerAuth;
+}

+ 22 - 0
common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAppStat.java

@@ -0,0 +1,22 @@
+package cn.reghao.bnt.common.msg.event;
+
+import cn.reghao.bnt.common.msg.constant.AppStatOps;
+import cn.reghao.jutil.jdk.event.message.Event;
+import lombok.Getter;
+
+/**
+ * @author reghao
+ * @date 2023-03-06 16:04:48
+ */
+@Getter
+public class EvtAppStat extends Event {
+    private final String packType;
+    private final String appId;
+    private final String ops;
+
+    public EvtAppStat(String packType, String appId, AppStatOps appStatOps) {
+        this.packType = packType;
+        this.appId = appId;
+        this.ops = appStatOps.name();
+    }
+}

+ 32 - 0
common/src/main/java/cn/reghao/bnt/common/msg/event/EvtAppStatResult.java

@@ -0,0 +1,32 @@
+package cn.reghao.bnt.common.msg.event;
+
+import cn.reghao.jutil.jdk.event.message.Event;
+import cn.reghao.jutil.jdk.result.Result;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author reghao
+ * @date 2023-03-06 15:24:22
+ */
+@Setter
+@Getter
+public class EvtAppStatResult extends Event {
+    private String machineId;
+    private String appId;
+    private String commitId;
+    private Boolean running;
+    private LocalDateTime startTime;
+    private Integer pid;
+    private Boolean deploy;
+    private Result result;
+
+    public EvtAppStatResult(String appId, String machineId) {
+        this.appId = appId;
+        this.machineId = machineId;
+        this.running = false;
+        this.deploy = false;
+    }
+}

+ 10 - 0
common/src/main/java/cn/reghao/bnt/common/msg/event/EvtBuildApp.java

@@ -0,0 +1,10 @@
+package cn.reghao.bnt.common.msg.event;
+
+import cn.reghao.jutil.jdk.event.message.Event;
+
+/**
+ * @author reghao
+ * @date 2023-03-16 16:21:35
+ */
+public class EvtBuildApp extends Event {
+}

+ 10 - 0
common/src/main/java/cn/reghao/bnt/common/msg/event/EvtBuildAppResult.java

@@ -0,0 +1,10 @@
+package cn.reghao.bnt.common.msg.event;
+
+import cn.reghao.jutil.jdk.event.message.Event;
+
+/**
+ * @author reghao
+ * @date 2023-03-16 16:22:28
+ */
+public class EvtBuildAppResult extends Event {
+}

+ 90 - 0
common/src/main/java/cn/reghao/bnt/common/ws/WebSocketListenerImpl.java

@@ -0,0 +1,90 @@
+package cn.reghao.bnt.common.ws;
+
+import cn.reghao.jutil.jdk.serializer.JdkSerializer;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.Response;
+import okhttp3.WebSocket;
+import okhttp3.WebSocketListener;
+import okio.ByteString;
+
+import java.io.EOFException;
+import java.net.ConnectException;
+import java.net.ProtocolException;
+
+/**
+ * @author reghao
+ * @date 2023-02-23 09:26:50
+ */
+@Slf4j
+public class WebSocketListenerImpl extends WebSocketListener {
+    private final WsClient wsClient;
+
+    public WebSocketListenerImpl(WsClient wsClient) {
+        this.wsClient = wsClient;
+    }
+
+    @Override
+    public void onOpen(WebSocket webSocket, Response response) {
+        log.info("WebSocket 连接成功");
+        wsClient.setConnected(true);
+        wsClient.resetRetryCount();
+    }
+
+    @Override
+    public void onClosing(WebSocket webSocket, int code, String reason) {
+        log.error("WebSocket 连接被动断开 -> {} - {}", code, reason);
+        wsClient.setConnected(false);
+
+        if (wsClient.isRetry()) {
+            reconnect();
+        }
+    }
+
+    @Override
+    public void onClosed(WebSocket webSocket, int code, String reason) {
+        log.error("WebSocket 连接主动断开 -> {} - {}", code, reason);
+        wsClient.setConnected(false);
+    }
+
+    @Override
+    public void onFailure(WebSocket webSocket, Throwable throwable, Response response) {
+        log.info("WebSocket 异常事件: {}", throwable.toString());
+        if (throwable instanceof ConnectException
+                || throwable instanceof EOFException
+                || throwable instanceof ProtocolException) {
+            wsClient.setConnected(false);
+            if (wsClient.isRetry()) {
+                reconnect();
+            }
+        } else {
+            throwable.printStackTrace();
+        }
+    }
+
+    private void reconnect() {
+        log.info("WebSocket 重连");
+        try {
+            if (wsClient.getRetryCount() > 10) {
+                log.info("WebSocket 重连超过 10 次, 休眠 1 分钟后再尝试");
+                Thread.sleep(60_000);
+                wsClient.resetRetryCount();
+            } else {
+                log.info("休眠 10s 后再尝试重连");
+                Thread.sleep(10_000);
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        wsClient.retryCountIncr();
+        wsClient.connect();
+    }
+
+    @Override
+    public void onMessage(WebSocket webSocket, String text) {
+    }
+
+    @Override
+    public void onMessage(WebSocket webSocket, ByteString bytes) {
+        Object object = JdkSerializer.deserialize(bytes.toByteArray());
+    }
+}

+ 106 - 0
common/src/main/java/cn/reghao/bnt/common/ws/WsClient.java

@@ -0,0 +1,106 @@
+package cn.reghao.bnt.common.ws;
+
+import cn.reghao.jutil.jdk.serializer.JdkSerializer;
+import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.WebSocket;
+import okhttp3.WebSocketListener;
+import okio.ByteString;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author reghao
+ * @date 2023-02-23 09:26:50
+ */
+public class WsClient {
+    private final ScheduledExecutorService scheduler = ThreadPoolWrapper.scheduledThreadPool("ws-heartbeat", 1);
+    private Future<?> heartbeatFuture;
+
+    private final String url;
+    private String token;
+    private WebSocket webSocket;
+    private boolean connected;
+    private final WebSocketListener webSocketListener;
+    private boolean retry;
+    private int retryCount;
+
+    public WsClient(String url) {
+        this.url = url;
+        //this.token = token;
+        this.webSocketListener = new WebSocketListenerImpl(this);
+        this.retry = true;
+        this.retryCount = 0;
+    }
+
+    public void setRetry(boolean retry) {
+        this.retry = retry;
+    }
+
+    public boolean isRetry() {
+        return retry;
+    }
+
+    public void retryCountIncr() {
+        this.retryCount += 1;
+    }
+
+    public void resetRetryCount() {
+        this.retryCount = 0;
+    }
+
+    public int getRetryCount() {
+        return retryCount;
+    }
+
+    public void connect() {
+        Request request = new Request.Builder()
+                .url(url)
+                //.header("Authorization", "Bearer " + token)
+                .build();
+
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(30, TimeUnit.SECONDS)
+                .readTimeout(30, TimeUnit.SECONDS)
+                .writeTimeout(30, TimeUnit.SECONDS)
+                .build();
+        this.webSocket = okHttpClient.newWebSocket(request, webSocketListener);
+    }
+
+    public void setConnected(boolean status) {
+        this.connected = status;
+        if (status) {
+            heartbeatFuture = scheduler.scheduleAtFixedRate(new HeartbeatTask(), 0, 10, TimeUnit.SECONDS);
+        } else {
+            if (heartbeatFuture != null && !heartbeatFuture.isCancelled()) {
+                heartbeatFuture.cancel(true);
+            }
+        }
+    }
+
+    public boolean isConnected() {
+        return connected;
+    }
+
+    public void send(Object message) {
+        if (isConnected()) {
+            byte[] bytes = JdkSerializer.serialize(message);
+            webSocket.send(ByteString.of(bytes));
+        }
+    }
+
+    public void close() {
+        setRetry(false);
+        webSocket.close(1000, "Client Close Connection");
+    }
+
+    class HeartbeatTask implements Runnable {
+        @Override
+        public void run() {
+            send("");
+        }
+    }
+}

+ 0 - 18
common/src/main/java/cn/reghao/devops/common/agent/app/dto/AppInfo.java

@@ -1,18 +0,0 @@
-package cn.reghao.devops.common.agent.app.dto;
-
-import lombok.Getter;
-
-/**
- * @author reghao
- * @date 2023-03-08 10:01:20
- */
-@Getter
-public class AppInfo {
-    private final String packType;
-    private final String appId;
-
-    public AppInfo(String packType, String appId) {
-        this.packType = packType;
-        this.appId = appId;
-    }
-}

+ 0 - 12
common/src/main/java/cn/reghao/devops/common/agent/app/iface/AppDeploy.java

@@ -1,12 +0,0 @@
-package cn.reghao.devops.common.agent.app.iface;
-
-import cn.reghao.devops.common.msg.event.EvtAppDeploy;
-import cn.reghao.devops.common.msg.event.EvtAppStatResult;
-
-/**
- * @author reghao
- * @date 2023-03-06 16:21:07
- */
-public interface AppDeploy {
-    EvtAppStatResult deploy(EvtAppDeploy deployParam) throws Exception;
-}

+ 0 - 20
common/src/main/java/cn/reghao/devops/common/agent/app/iface/AppStat.java

@@ -1,20 +0,0 @@
-package cn.reghao.devops.common.agent.app.iface;
-
-import cn.reghao.devops.common.msg.event.EvtAppStat;
-import cn.reghao.devops.common.msg.event.EvtAppStatResult;
-
-import java.util.List;
-
-/**
- * 应用状态管理
- *
- * @author reghao
- * @date 2023-03-06 15:22:48
- */
-public interface AppStat {
-    EvtAppStatResult start(EvtAppStat evtAppStat) throws Exception;
-    EvtAppStatResult stop(EvtAppStat evtAppStat) throws Exception;
-    EvtAppStatResult restart(EvtAppStat evtAppStat) throws Exception;
-    EvtAppStatResult stat(EvtAppStat evtAppStat) throws Exception;
-    List<EvtAppStatResult> stat() throws Exception;
-}

+ 0 - 28
common/src/main/java/cn/reghao/devops/common/agent/app/iface/impl/AppDeployImpl.java

@@ -1,28 +0,0 @@
-package cn.reghao.devops.common.agent.app.iface.impl;
-
-import cn.reghao.devops.common.agent.app.iface.AppDeploy;
-import cn.reghao.devops.common.msg.constant.PackType;
-import cn.reghao.devops.common.msg.event.EvtAppDeploy;
-import cn.reghao.devops.common.msg.event.EvtAppStatResult;
-
-/**
- * @author reghao
- * @date 2023-03-06 16:21:30
- */
-public class AppDeployImpl implements AppDeploy {
-    private final DockerApp dockerApp;
-
-    public AppDeployImpl(DockerApp dockerApp) {
-        this.dockerApp = dockerApp;
-    }
-
-    @Override
-    public EvtAppStatResult deploy(EvtAppDeploy deployParam) throws Exception {
-        String packType = deployParam.getPackType();
-        if (packType.equals(PackType.docker.name())) {
-            return dockerApp.deploy(deployParam);
-        } else {
-            throw new Exception("zip 打包没有实现");
-        }
-    }
-}

+ 0 - 73
common/src/main/java/cn/reghao/devops/common/agent/app/iface/impl/AppStatImpl.java

@@ -1,73 +0,0 @@
-package cn.reghao.devops.common.agent.app.iface.impl;
-
-import cn.reghao.devops.common.agent.app.iface.AppStat;
-import cn.reghao.devops.common.msg.constant.PackType;
-import cn.reghao.devops.common.msg.event.EvtAppStat;
-import cn.reghao.devops.common.msg.event.EvtAppStatResult;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2023-03-06 16:19:24
- */
-public class AppStatImpl implements AppStat {
-    private final DockerApp dockerApp;
-
-    public AppStatImpl(DockerApp dockerApp) {
-        this.dockerApp = dockerApp;
-    }
-
-    @Override
-    public EvtAppStatResult start(EvtAppStat evtAppStat) throws Exception {
-        String packType = evtAppStat.getPackType();
-        String appId = evtAppStat.getAppId();
-
-        if (packType.equals(PackType.docker.name())) {
-            return dockerApp.start(appId);
-        } else {
-            throw new Exception("zip 打包没有实现");
-        }
-    }
-
-    @Override
-    public EvtAppStatResult stop(EvtAppStat evtAppStat) throws Exception {
-        String packType = evtAppStat.getPackType();
-        String appId = evtAppStat.getAppId();
-
-        if (packType.equals(PackType.docker.name())) {
-            return dockerApp.stop(appId);
-        } else {
-            throw new Exception("zip 打包没有实现");
-        }
-    }
-
-    @Override
-    public EvtAppStatResult restart(EvtAppStat evtAppStat) throws Exception {
-        String packType = evtAppStat.getPackType();
-        String appId = evtAppStat.getAppId();
-
-        if (packType.equals(PackType.docker.name())) {
-            return dockerApp.restart(appId);
-        } else {
-            throw new Exception("zip 打包没有实现");
-        }
-    }
-
-    @Override
-    public EvtAppStatResult stat(EvtAppStat evtAppStat) throws Exception {
-        String packType = evtAppStat.getPackType();
-        String appId = evtAppStat.getAppId();
-
-        if (packType.equals(PackType.docker.name())) {
-            return dockerApp.stat(appId);
-        } else {
-            throw new Exception("zip 打包没有实现");
-        }
-    }
-
-    @Override
-    public List<EvtAppStatResult> stat() throws Exception {
-        return dockerApp.stat();
-    }
-}

+ 0 - 122
common/src/main/java/cn/reghao/devops/common/agent/app/iface/impl/DockerApp.java

@@ -1,122 +0,0 @@
-package cn.reghao.devops.common.agent.app.iface.impl;
-
-import cn.reghao.devops.common.docker.Docker;
-import cn.reghao.devops.common.docker.DockerImpl;
-import cn.reghao.devops.common.docker.model.Config;
-import cn.reghao.devops.common.docker.model.DockerAuth;
-import cn.reghao.devops.common.docker.model.HostConfig;
-import cn.reghao.devops.common.machine.Machine;
-import cn.reghao.devops.common.msg.constant.NodeStatus;
-import cn.reghao.devops.common.msg.event.EvtAppDeploy;
-import cn.reghao.devops.common.msg.event.EvtAppStatResult;
-import cn.reghao.devops.common.util.NotAvailable;
-import cn.reghao.jutil.jdk.converter.DateTimeConverter;
-import cn.reghao.jutil.jdk.serializer.JsonConverter;
-import com.github.dockerjava.api.command.InspectContainerResponse;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * @author reghao
- * @date 2023-03-06 15:26:22
- */
-public class DockerApp {
-    private Map<String, Docker> map = new HashMap<>();
-
-    public DockerApp(Docker docker) {
-        this.map.put("noAuth", docker);
-    }
-
-    public EvtAppStatResult deploy(EvtAppDeploy deployParam) throws Exception {
-        String appId = deployParam.getAppId();
-        String packagePath = deployParam.getPackagePath();
-        Config containerConfig = JsonConverter.jsonToObject(deployParam.getStartScript(), Config.class);
-        if (containerConfig == null) {
-            containerConfig = new Config(packagePath);
-        } else {
-            containerConfig.setImage(packagePath);
-            if (containerConfig.getHostConfig() == null) {
-                containerConfig.setHostConfig(new HostConfig());
-            }
-        }
-
-        Docker docker;
-        DockerAuth dockerAuth = deployParam.getDockerAuth();
-        if (dockerAuth != null) {
-            String registryUrl = dockerAuth.getRegistryUrl();
-            docker = map.get(registryUrl);
-            if (docker == null) {
-                // TODO DockerAuth 修改后 map 中的 Docker 实例无效
-                docker = new DockerImpl(dockerAuth);
-                map.put(registryUrl, docker);
-            }
-        } else {
-            docker = map.get("noAuth");
-        }
-        docker.pull(packagePath);
-        InspectContainerResponse containerInfo = docker.createAndRun(appId, containerConfig);
-        return getStat(appId, containerInfo);
-    }
-
-    public EvtAppStatResult start(String appId) throws Exception {
-        Docker docker = map.get("noAuth");
-        InspectContainerResponse containerInfo = docker.start(appId);
-        return getStat(appId, containerInfo);
-    }
-
-    public EvtAppStatResult stop(String appId) throws Exception {
-        Docker docker = map.get("noAuth");
-        InspectContainerResponse containerInfo = docker.stop(appId);
-        return getStat(appId, containerInfo);
-    }
-
-    public EvtAppStatResult restart(String appId) throws Exception {
-        Docker docker = map.get("noAuth");
-        InspectContainerResponse containerInfo = docker.restart(appId);
-        return getStat(appId, containerInfo);
-    }
-
-    public EvtAppStatResult stat(String appId) throws Exception {
-        Docker docker = map.get("noAuth");
-        InspectContainerResponse containerInfo = docker.inspectContainer(appId);
-        return getStat(appId, containerInfo);
-    }
-
-    public List<EvtAppStatResult> stat() throws Exception {
-        Docker docker = map.get("noAuth");
-        List<InspectContainerResponse> list = docker.psAll();
-        return list.stream().map(response -> {
-            String containerName = response.getName();
-            String appId = containerName.replace("/", "");
-            return getStat(appId, response);
-        }).collect(Collectors.toList());
-    }
-
-    private EvtAppStatResult getStat(String appId, InspectContainerResponse containerInfo) {
-        EvtAppStatResult appStatResult = new EvtAppStatResult(appId, Machine.ID);
-        String image = containerInfo.getConfig().getImage();
-        if (image != null && image.contains(":")) {
-            appStatResult.setCommitId(image.split(":")[1]);
-        } else {
-            appStatResult.setCommitId(NotAvailable.na.getDesc());
-        }
-
-        InspectContainerResponse.ContainerState state = containerInfo.getState();
-        if (state == null || Boolean.FALSE.equals(state.getRunning())) {
-            //appStatResult.setStatus(NodeStatus.Offline.name());
-            appStatResult.setStartTime(null);
-            appStatResult.setPid(-1);
-        } else {
-            String startedAt = state.getStartedAt();
-            //appStatResult.setStatus(NodeStatus.Online.name());
-            appStatResult.setRunning(true);
-            appStatResult.setStartTime(DateTimeConverter.localDateTime(startedAt));
-            appStatResult.setPid(state.getPidLong().intValue());
-        }
-
-        return appStatResult;
-    }
-}

+ 0 - 96
common/src/main/java/cn/reghao/devops/common/agent/machine/MachineEvent.java

@@ -1,96 +0,0 @@
-package cn.reghao.devops.common.agent.machine;
-
-import cn.reghao.devops.common.agent.app.iface.AppStat;
-import cn.reghao.devops.common.machine.Machine;
-import cn.reghao.devops.common.msg.MessageSender;
-import cn.reghao.devops.common.msg.event.EvtAgentHeartbeat;
-import cn.reghao.devops.common.msg.event.EvtAgentStart;
-import cn.reghao.devops.common.msg.event.EvtAppStatResult;
-import cn.reghao.jutil.jdk.event.message.EventMessage;
-import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @author reghao
- * @date 2021-09-03 09:22:42
- */
-@Slf4j
-public class MachineEvent {
-    private final ScheduledExecutorService scheduler;
-    private ScheduledFuture<?> heartbeatFuture;
-    private final Machine machine;
-    private final AppStat appStat;
-    private final MessageSender messageSender;
-    private final int heartbeatInterval;
-    
-    public MachineEvent(MessageSender messageSender, Machine machine, AppStat appStat,
-                        ScheduledExecutorService scheduler, int heartbeatInterval) {
-        this.messageSender = messageSender;
-        this.machine = machine;
-        this.appStat = appStat;
-        this.scheduler = scheduler;
-        this.heartbeatInterval = heartbeatInterval;
-    }
-
-    public void agentStart() {
-        EvtAgentStart evtAgentStart = machine.detail();
-        EventMessage eventMessage = EventMessage.evt(evtAgentStart);
-        pub(eventMessage);
-
-        try {
-            List<EvtAppStatResult> list = appStat.stat();
-            list.forEach(evtAppStatResult -> {
-                EventMessage eventMessage1 = EventMessage.evt(evtAppStatResult);
-                pub(eventMessage1);
-            });
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-
-        agentHeartbeat();
-    }
-
-    public void agentShutdown() {
-        ThreadPoolWrapper.shutdownScheduler(scheduler);
-        EvtAgentHeartbeat machineStat = machine.stat();
-        EventMessage eventMessage = EventMessage.evt(machineStat);
-        pub(eventMessage);
-    }
-
-    public void agentHeartbeat() {
-        heartbeatFuture = scheduler.scheduleAtFixedRate(new Heartbeat(), 5, heartbeatInterval, TimeUnit.SECONDS);
-    }
-
-    public void pauseHeartbeat() {
-        if (!heartbeatFuture.isCancelled()) {
-            heartbeatFuture.cancel(true);
-        }
-    }
-
-    private void pub(EventMessage eventMessage) {
-        if (messageSender.isConnected()) {
-            try {
-                messageSender.send("", eventMessage);
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        } else {
-            log.error("连接断开");
-        }
-    }
-
-    class Heartbeat implements Runnable {
-        @Override
-        public void run() {
-            EvtAgentHeartbeat machineStat = machine.stat();
-            EventMessage eventMessage = EventMessage.evt(machineStat);
-            pub(eventMessage);
-        }
-    }
-}

+ 0 - 34
common/src/main/java/cn/reghao/devops/common/docker/Docker.java

@@ -1,34 +0,0 @@
-package cn.reghao.devops.common.docker;
-
-import cn.reghao.devops.common.docker.model.Config;
-import com.github.dockerjava.api.command.InspectContainerResponse;
-import com.github.dockerjava.api.model.Image;
-import com.github.dockerjava.api.model.Version;
-
-import java.util.List;
-
-/**
- * Docker 客户端
- *
- * @author reghao
- * @date 2021-10-27 04:17:38
- */
-public interface Docker {
-    void auth();
-    Version version();
-    void build(String repoTag, String compileHome, String dockerfileContent) throws Exception;
-    void push(String image) throws Exception;
-    void pull(String repoTag) throws Exception;
-    void stopAndDelete(String containerName) throws Exception;
-    InspectContainerResponse createAndRun(String containerName, Config containerConfig) throws Exception;
-    void runAndRm(Config containerConfig) throws Exception;
-    InspectContainerResponse start(String containerName);
-    InspectContainerResponse stop(String containerName);
-    InspectContainerResponse restart(String containerName);
-    InspectContainerResponse inspectContainer(String containerName);
-    List<Image> images();
-    void imageRm(String imageId);
-    void rm(String containerId);
-    List<InspectContainerResponse> psAll();
-    InspectContainerResponse ps(String containerName);
-}

+ 0 - 438
common/src/main/java/cn/reghao/devops/common/docker/DockerImpl.java

@@ -1,438 +0,0 @@
-package cn.reghao.devops.common.docker;
-
-import cn.reghao.devops.common.docker.model.DockerAuth;
-import cn.reghao.jutil.jdk.exception.ExceptionUtil;
-import cn.reghao.jutil.jdk.text.TextFile;
-import com.github.dockerjava.api.DockerClient;
-import com.github.dockerjava.api.async.ResultCallback;
-import com.github.dockerjava.api.command.*;
-import com.github.dockerjava.api.model.*;
-import com.github.dockerjava.core.DefaultDockerClientConfig;
-import com.github.dockerjava.core.DockerClientConfig;
-import com.github.dockerjava.core.DockerClientImpl;
-import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
-import com.github.dockerjava.transport.DockerHttpClient;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.IOException;
-import java.time.Duration;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-/**
- * Docker 客户端
- *
- * @author reghao
- * @date 2021-10-27 03:41:38
- */
-@Slf4j
-public class DockerImpl implements Docker {
-    private DockerClient dockerClient;
-    private final TextFile textFile = new TextFile();
-    private final String unixSock = "/var/run/docker.sock";
-
-    public DockerImpl() {
-        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
-                .withDockerHost("unix://" + unixSock)
-                .withDockerTlsVerify(false)
-                //.withDockerCertPath(String.format("%s/.docker", System.getProperty("user.home")))
-                //.withRegistryUsername("username")
-                //.withRegistryPassword("password")
-                //.withRegistryEmail(registryMail)
-                //.withRegistryUrl(registryUrl)
-                .build();
-        init(config);
-    }
-
-    public DockerImpl(DockerAuth dockerAuth) {
-        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
-                .withDockerHost("unix://" + unixSock)
-                .withDockerTlsVerify(false)
-                //.withDockerCertPath(String.format("%s/.docker", System.getProperty("user.home")))
-                .withRegistryUrl(dockerAuth.getRegistryUrl())
-                .withRegistryUsername(dockerAuth.getUsername())
-                .withRegistryPassword(dockerAuth.getPassword())
-                //.withRegistryEmail(registryMail)
-                .build();
-        init(config);
-    }
-
-    private void init(DockerClientConfig config) {
-        DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
-                .dockerHost(config.getDockerHost())
-                .sslConfig(config.getSSLConfig())
-                .maxConnections(100)
-                .connectionTimeout(Duration.ofSeconds(60))
-                .responseTimeout(Duration.ofSeconds(60))
-                .build();
-        this.dockerClient = DockerClientImpl.getInstance(config, httpClient);
-    }
-
-    @Override
-    public void auth() {
-        dockerClient.authCmd().exec();
-    }
-
-    @Override
-    public Version version() {
-        return dockerClient.versionCmd().exec();
-    }
-
-    @Override
-    public void build(String repoTag, String compileHome, String dockerfileContent) throws Exception {
-        File dockerfile = new File(compileHome + "/Dockerfile.tmp");
-        try {
-            textFile.write(dockerfile, dockerfileContent);
-            String imageId = dockerClient.buildImageCmd()
-                    .withDockerfile(dockerfile)
-                    // repoTag 格式为 docker.reghao.cn/devops:12345678
-                    .withTags(Set.of(repoTag))
-                    .start()
-                    .awaitImageId(300, TimeUnit.SECONDS);
-        } catch (Exception e) {
-            throw new Exception(ExceptionUtil.errorMsg(e));
-        }
-    }
-
-    public void build(String repoTag, String compileHome) throws Exception {
-        String dockerfilePath = compileHome + "/Dockerfile";
-        dockerClient.buildImageCmd()
-                .withDockerfile(new File(dockerfilePath))
-                .withTags(Set.of(repoTag))
-                .start()
-                .awaitImageId(300, TimeUnit.SECONDS);
-    }
-
-    @Override
-    public void push(String image) throws Exception {
-        try {
-            ResultCallback.Adapter<PushResponseItem> callback = new PushCallback();
-            dockerClient.pushImageCmd(image)
-                    //.exec(new ResultCallback.Adapter<>())
-                    .exec(callback)
-                    .awaitCompletion(300, TimeUnit.SECONDS);
-            PushCallback pushCallback = (PushCallback) callback;
-            int code = pushCallback.getCode();
-            if (code != 0) {
-                throw new Exception(pushCallback.getMsg());
-            }
-        } catch (InterruptedException e) {
-            throw new Exception(ExceptionUtil.errorMsg(e));
-        }
-    }
-
-    @Override
-    public void pull(String image) throws Exception {
-        try {
-            dockerClient.pullImageCmd(image).exec(new PullImageResultCallback()).awaitCompletion();
-        } catch (InterruptedException e) {
-            throw new Exception(ExceptionUtil.errorMsg(e));
-        }
-        /*dockerClient.pullImageCmd(image).exec(new ResultCallback<PullResponseItem>() {
-            public void onStart(Closeable closeable) {
-                System.out.println("开始下载!");
-            }
-
-            public void onNext(PullResponseItem object) {
-                // 实时显示出下载信息
-                System.out.println(object.getStatus());
-            }
-
-            public void onError(Throwable throwable) {
-                throwable.printStackTrace();
-            }
-
-            public void onComplete() {
-                System.out.println("下载完毕!");
-            }
-
-            public void close() throws IOException {
-                System.out.println("下载完毕...");
-            }
-        }).onComplete();*/
-    }
-
-    private String getContainerIdByName(String containerName) {
-        List<Container> list = dockerClient.listContainersCmd()
-                .withShowAll(true)
-                .withNameFilter(List.of(containerName))
-                .exec();
-
-        for (Container container : list) {
-            Set<String> set = new HashSet<>(Arrays.asList(container.getNames()));
-            if (set.contains("/" + containerName)) {
-                return container.getId();
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public void stopAndDelete(String containerName) {
-        String containerId = getContainerIdByName(containerName);
-        if (containerId != null) {
-            InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(containerId).exec();
-            InspectContainerResponse.ContainerState state = containerInfo.getState();
-            boolean isRunning = state.getRunning() != null ? state.getRunning() : false;
-            if (isRunning) {
-                dockerClient.stopContainerCmd(containerId).exec();
-            }
-            dockerClient.removeContainerCmd(containerId).exec();
-        }
-    }
-
-    @Override
-    public InspectContainerResponse createAndRun(String containerName, cn.reghao.devops.common.docker.model.Config containerConfig) throws Exception {
-        stopAndDelete(containerName);
-
-        String image = containerConfig.getImage();
-        CreateContainerCmd createContainerCmd = dockerClient.createContainerCmd(image)
-                .withName(containerName);
-
-        List<String> env = containerConfig.getEnv();
-        if (env != null) {
-            createContainerCmd.withEnv(env);
-        }
-
-        RestartPolicy restartPolicy = RestartPolicy.onFailureRestart(3);
-        HostConfig hostConfig = HostConfig.newHostConfig()
-                // --init 参数
-                //.withInit(true)
-                .withNetworkMode("host")
-                .withRestartPolicy(restartPolicy);
-        if (containerConfig.getVolumes() != null) {
-            Map<String, String> map = containerConfig.getVolumes().getMap();
-            List<Bind> list = new ArrayList<>();
-            for (Map.Entry<String, String> entry : map.entrySet()) {
-                String key = entry.getKey();
-                String value = entry.getValue();
-                Volume volume2 = new Volume(value);
-                Bind bind = new Bind(key, volume2);
-                list.add(bind);
-            }
-            hostConfig.withBinds(list);
-        }
-
-        if (containerConfig.getHostConfig().getInit() != null) {
-            hostConfig.withInit(containerConfig.getHostConfig().getInit());
-        }
-
-        createContainerCmd.withHostConfig(hostConfig);
-        CreateContainerResponse response = createContainerCmd.exec();
-        String containerId = response.getId();
-        dockerClient.startContainerCmd(containerId).exec();
-        return dockerClient.inspectContainerCmd(containerId).exec();
-    }
-
-    public void runAndRm(cn.reghao.devops.common.docker.model.Config containerConfig) throws Exception {
-        String image = containerConfig.getImage();
-        CreateContainerCmd createContainerCmd = dockerClient.createContainerCmd(image).withCmd("rm");
-
-        List<String> env = containerConfig.getEnv();
-        if (env != null) {
-            createContainerCmd.withEnv(env);
-        }
-
-        HostConfig hostConfig = HostConfig.newHostConfig()
-                .withNetworkMode("host")
-                .withRestartPolicy(RestartPolicy.noRestart());
-        if (containerConfig.getVolumes() != null) {
-            Map<String, String> map = containerConfig.getVolumes().getMap();
-            List<Bind> list = new ArrayList<>();
-            for (Map.Entry<String, String> entry : map.entrySet()) {
-                String hostPath = entry.getValue();
-                String containerPath = entry.getKey();
-
-                Volume volume2 = new Volume(containerPath);
-                Bind bind = new Bind(hostPath, volume2);
-                list.add(bind);
-            }
-            hostConfig.withBinds(list);
-        }
-
-        if (containerConfig.getCmd() != null) {
-            createContainerCmd.withCmd(containerConfig.getCmd());
-        }
-
-        createContainerCmd.withHostConfig(hostConfig);
-        CreateContainerResponse response = createContainerCmd.exec();
-        String containerId = response.getId();
-        dockerClient.startContainerCmd(containerId).exec();
-
-        List<String> list = new ArrayList<>();
-        LogContainerCmd logContainerCmd = dockerClient.logContainerCmd(containerId);
-        logContainerCmd.withStdOut(true).withStdErr(true).withFollowStream(true);
-        logContainerCmd.exec(new ResultCallback<Frame>() {
-            @Override
-            public void onStart(Closeable closeable) {
-            }
-
-            @Override
-            public void onNext(Frame object) {
-                if (object.getStreamType().equals(StreamType.STDERR)) {
-                    list.add(object.toString());
-                }
-            }
-
-            @Override
-            public void onError(Throwable throwable) {
-                log.info(throwable.toString());
-            }
-
-            @Override
-            public void onComplete() {
-            }
-
-            @Override
-            public void close() throws IOException {
-            }
-        });
-
-        dockerClient.waitContainerCmd(containerId).exec(new ResultCallback.Adapter<>())
-                .awaitCompletion(300, TimeUnit.SECONDS);
-
-        InspectContainerResponse response1 = dockerClient.inspectContainerCmd(containerId).exec();
-        InspectContainerResponse.ContainerState state = response1.getState();
-        Long exitCode = state.getExitCodeLong();
-        if (Boolean.TRUE.equals(state.getRunning())) {
-            dockerClient.stopContainerCmd(containerId).exec();
-            dockerClient.removeContainerCmd(containerId).exec();
-            throw new Exception("docker build timeout after 300 seconds");
-        } else if (exitCode != null && exitCode == 0) {
-            dockerClient.removeContainerCmd(containerId).exec();
-        } else {
-            dockerClient.removeContainerCmd(containerId).exec();
-            StringBuilder sb = new StringBuilder();
-            list.forEach(line -> {
-                sb.append(line).append(System.lineSeparator());
-            });
-            throw new Exception("docker build failed:\n" + sb.toString());
-        }
-    }
-
-    @Override
-    public InspectContainerResponse start(String containerName) {
-        String containerId = getContainerIdByName(containerName);
-        dockerClient.startContainerCmd(containerId).exec();
-        return dockerClient.inspectContainerCmd(containerId).exec();
-    }
-
-    @Override
-    public InspectContainerResponse stop(String containerName) {
-        String containerId = getContainerIdByName(containerName);
-        dockerClient.stopContainerCmd(containerId).exec();
-        return dockerClient.inspectContainerCmd(containerId).exec();
-    }
-
-    @Override
-    public InspectContainerResponse restart(String containerName) {
-        String containerId = getContainerIdByName(containerName);
-        dockerClient.restartContainerCmd(containerId).exec();
-        return dockerClient.inspectContainerCmd(containerId).exec();
-    }
-
-    @Override
-    public InspectContainerResponse inspectContainer(String containerName) {
-        String containerId = getContainerIdByName(containerName);
-        return dockerClient.inspectContainerCmd(containerId).exec();
-    }
-
-    @Override
-    public List<Image> images() {
-        List<Image> images = dockerClient.listImagesCmd().exec();
-        return images;
-        /*return images.stream().map(image -> {
-            long created = image.getCreated();
-            String[] repoTags = image.getRepoTags();
-            if (repoTags.length == 0) {
-                return null;
-            }
-
-            String imageId = image.getId();
-            String[] repoTag = repoTags[0].split(":");
-            String repo = repoTag[0];
-            String tag = repoTag[1];
-            LocalDateTime created1 = DateTimeConverter.localDateTime(created*1000);
-            return new ImageInfo(repo, tag, imageId, created1);
-        }).filter(Objects::nonNull).collect(Collectors.toList());*/
-    }
-
-    @Override
-    public void imageRm(String imageId) {
-        dockerClient.removeImageCmd(imageId).exec();
-    }
-
-    @Override
-    public void rm(String containerId) {
-        dockerClient.removeContainerCmd(containerId).exec();
-    }
-
-    @Override
-    public List<InspectContainerResponse> psAll() {
-        List<Container> list = dockerClient.listContainersCmd()
-                .withShowAll(true)
-                .exec();
-        return list.stream().map(container -> {
-            String containerId = container.getId();
-            return dockerClient.inspectContainerCmd(containerId).exec();
-        }).collect(Collectors.toList());
-    }
-
-    @Override
-    public InspectContainerResponse ps(String appId) {
-        List<Container> list = dockerClient.listContainersCmd()
-                .withNameFilter(List.of(appId))
-                .exec();
-
-        if (list.isEmpty()) {
-            return null;
-        }
-
-        Container container = list.get(0);
-        String containerId = container.getId();
-        return dockerClient.inspectContainerCmd(containerId).exec();
-    }
-
-    static class PushCallback extends ResultCallback.Adapter<PushResponseItem> {
-        private int code;
-        private String msg;
-
-        public PushCallback() {
-            this.code = 0;
-        }
-
-        public int getCode() {
-            return code;
-        }
-
-        public String getMsg() {
-            return msg;
-        }
-
-        @Override
-        public void onNext(PushResponseItem object) {
-            PushResponseItem.ErrorDetail errorDetail = object.getErrorDetail();
-            if (errorDetail != null) {
-                //log.info("error: {} {}", errorDetail.getCode(), errorDetail.getMessage());
-                code = 1;
-                msg = errorDetail.getMessage();
-            } else {
-                //log.info("info: {} {} {}", object.getStatus(), object.getId(), object.getProgressDetail());
-            }
-        }
-
-        @Override
-        public void onComplete() {
-            super.onComplete();
-        }
-
-        @Override
-        public void onError(Throwable throwable) {
-            throwable.printStackTrace();
-        }
-    }
-}

+ 0 - 55
common/src/main/java/cn/reghao/devops/common/docker/model/Config.java

@@ -1,55 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import com.google.gson.annotations.SerializedName;
-import lombok.Data;
-
-import java.util.List;
-
-/**
- * docker 容器创建时的配置
- *
- * @author reghao
- * @date 2020-01-14 23:11:21
- */
-@Data
-public class Config implements Cloneable {
-    @SerializedName("AttachStderr") private boolean attachStderr;
-    @SerializedName("AttachStdin") private boolean attachStdin;
-    @SerializedName("AttachStdout") private boolean attachStdout;
-    @SerializedName("Cmd") private List<String> cmd;
-    @SerializedName("Domainname") private String domainname;
-    @SerializedName("Env") private List<String> env;
-    @SerializedName("Healthcheck") private Healthcheck healthcheck;
-    @SerializedName("Hostname") private String hostname;
-    @SerializedName("Image") private String image;
-    @SerializedName("Labels") private Labels labels;
-    @SerializedName("MacAddress") private String macAddress;
-    @SerializedName("NetworkDisabled") private boolean networkDisabled;
-    @SerializedName("OpenStdin") private boolean openStdin;
-    @SerializedName("StdinOnce") private boolean stdinOnce;
-    @SerializedName("Tty") private boolean tty;
-    @SerializedName("User") private String user;
-    @SerializedName("Volumes") private Volumes volumes;
-    @SerializedName("WorkingDir") private String workingDir;
-    @SerializedName("StopSignal") private String stopSignal;
-    @SerializedName("StopTimeout") private int stopTimeout;
-
-    @SerializedName("Entrypoint") private String entrypoint;
-    @SerializedName("ExposedPorts") private ExposedPorts exposedPorts;
-    @SerializedName("HostConfig") private HostConfig hostConfig;
-    @SerializedName("NetworkingConfig") private NetworkingConfig networkingConfig;
-
-    public Config() {
-        this.hostConfig = new HostConfig();
-    }
-
-    public Config(String image) {
-        this.image = image;
-        this.hostConfig = new HostConfig();
-    }
-
-    @Override
-    public Object clone() throws CloneNotSupportedException {
-        return super.clone();
-    }
-}

+ 0 - 20
common/src/main/java/cn/reghao/devops/common/docker/model/DockerAuth.java

@@ -1,20 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.io.Serializable;
-
-/**
- * @author reghao
- * @date 2024-07-26 17:29:56
- */
-@AllArgsConstructor
-@Getter
-public class DockerAuth implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String registryUrl;
-    private String username;
-    private String password;
-}

+ 0 - 11
common/src/main/java/cn/reghao/devops/common/docker/model/ExposedPorts.java

@@ -1,11 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2021-02-10 01:30:17
- */
-@Data
-public class ExposedPorts {
-}

+ 0 - 15
common/src/main/java/cn/reghao/devops/common/docker/model/Healthcheck.java

@@ -1,15 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import com.google.gson.annotations.SerializedName;
-import lombok.Data;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2021-02-25 10:02:59
- */
-@Data
-public class Healthcheck {
-    @SerializedName("Test") private List<String> test;
-}

+ 0 - 24
common/src/main/java/cn/reghao/devops/common/docker/model/HostConfig.java

@@ -1,24 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import com.google.gson.annotations.SerializedName;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-/**
- * TODO 部分
- *
- * @author reghao
- * @date 2020-01-14 23:16:52
- */
-@AllArgsConstructor
-@Data
-public class HostConfig {
-    @SerializedName("NetworkMode") private String networkMode;
-    @SerializedName("RestartPolicy") private RestartPolicy restartPolicy;
-    @SerializedName("Init") private Boolean init;
-
-    public HostConfig() {
-        this.networkMode = "host";
-        this.restartPolicy = new RestartPolicy();
-    }
-}

+ 0 - 14
common/src/main/java/cn/reghao/devops/common/docker/model/Labels.java

@@ -1,14 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import lombok.Data;
-
-import java.util.Map;
-
-/**
- * @author reghao
- * @date 2021-02-10 01:28:38
- */
-@Data
-public class Labels {
-    private Map<String, String> map;
-}

+ 0 - 11
common/src/main/java/cn/reghao/devops/common/docker/model/NetworkingConfig.java

@@ -1,11 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2021-02-10 01:33:05
- */
-@Data
-public class NetworkingConfig {
-}

+ 0 - 21
common/src/main/java/cn/reghao/devops/common/docker/model/RestartPolicy.java

@@ -1,21 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import com.google.gson.annotations.SerializedName;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2020-05-19 15:00:50
- */
-@AllArgsConstructor
-@Data
-public class RestartPolicy {
-    @SerializedName("Name") private String name;
-    @SerializedName("MaximumRetryCount") private int maximumRetryCount;
-
-    public RestartPolicy() {
-        this.name = "on-failure";
-        this.maximumRetryCount = 3;
-    }
-}

+ 0 - 15
common/src/main/java/cn/reghao/devops/common/docker/model/Volumes.java

@@ -1,15 +0,0 @@
-package cn.reghao.devops.common.docker.model;
-
-import lombok.Data;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author reghao
- * @date 2021-02-10 01:29:10
- */
-@Data
-public class Volumes {
-    private Map<String, String> map = new HashMap<>();
-}

+ 0 - 33
common/src/main/java/cn/reghao/devops/common/machine/Cpu.java

@@ -1,33 +0,0 @@
-package cn.reghao.devops.common.machine;
-
-import cn.reghao.jutil.jdk.machine.data.MachineData;
-import cn.reghao.jutil.jdk.machine.data.detail.CpuDetail;
-import cn.reghao.jutil.jdk.machine.data.stat.CpuStat;
-import oshi.hardware.CentralProcessor;
-
-/**
- * @author reghao
- * @date 2019-10-25 13:12:36
- */
-public class Cpu implements MachineData<CpuDetail, CpuStat> {
-    private CentralProcessor processor;
-
-    public Cpu(CentralProcessor processor) {
-        this.processor = processor;
-    }
-
-    @Override
-    public CpuDetail detail() {
-        CentralProcessor.ProcessorIdentifier processorIdentifier = processor.getProcessorIdentifier();
-        String vendor = processorIdentifier.getVendor();
-        String name = processorIdentifier.getName();
-        int physicalCore = processor.getPhysicalProcessorCount();
-        int logicalCore = processor.getLogicalProcessorCount();
-        return new CpuDetail(vendor, name, physicalCore, logicalCore);
-    }
-
-    @Override
-    public CpuStat stat() {
-        return null;
-    }
-}

+ 0 - 87
common/src/main/java/cn/reghao/devops/common/machine/Disk.java

@@ -1,87 +0,0 @@
-package cn.reghao.devops.common.machine;
-
-import cn.reghao.jutil.jdk.machine.data.MachineData;
-import cn.reghao.jutil.jdk.machine.data.detail.DiskDetail;
-import cn.reghao.jutil.jdk.machine.data.stat.DiskStat;
-import oshi.SystemInfo;
-import oshi.software.os.OperatingSystem;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @author reghao
- * @date 2019-10-25 13:21:25
- */
-public class Disk implements MachineData<List<DiskDetail>, List<DiskStat>> {
-    private final OperatingSystem os;
-
-    public Disk(SystemInfo si) {
-        this.os = si.getOperatingSystem();
-        //this.os = new SystemInfo().getOperatingSystem();
-    }
-
-    @Override
-    public List<DiskDetail> detail() {
-        return os.getFileSystem().getFileStores().stream()
-                .filter(osFileStore -> osFileStore.getVolume().startsWith("/dev/"))
-                .map(osFileStore -> {
-                    String vol = osFileStore.getVolume();
-                    String mount = osFileStore.getMount();
-                    String fsType = osFileStore.getType();
-
-                    long total = osFileStore.getTotalSpace();
-                    // non-root 用户可用的磁盘空间
-                    long userAvail = osFileStore.getUsableSpace();
-                    // root 用户可用的磁盘空间
-                    long rootAvail = osFileStore.getFreeSpace();
-
-                    long inodeTotal = osFileStore.getTotalInodes();
-                    long inodeFree = osFileStore.getFreeInodes();
-
-                    return new DiskDetail(vol, mount, fsType, total, userAvail, total-userAvail, inodeTotal, inodeFree);
-                })
-                .collect(Collectors.toList());
-    }
-
-    @Override
-    public List<DiskStat> stat() {
-        return null;
-    }
-
-    /**
-     * 根据一个路径确定它所在的分区
-     *
-     * @param
-     * @return
-     * @date 2021-02-06 下午11:25
-     */
-    public DiskDetail diskDetail(String path) {
-        List<DiskDetail> diskInfos = detail();
-        // 根据挂载路径的长度降序
-        diskInfos.sort((o1, o2) -> o2.getMountedOn().length() - o1.getMountedOn().length());
-
-        List<DiskDetail> candidates = new ArrayList<>();
-        for (DiskDetail diskInfo : diskInfos) {
-            String mountedOn = diskInfo.getMountedOn();
-            String[] array = path.split(mountedOn);
-            if (array.length == 0) {
-                return diskInfo;
-            } else if (array.length == 2) {
-                if (array[1].startsWith("/") || "/".equals(mountedOn)) {
-                    candidates.add(diskInfo);
-                }
-            } else if (array.length > 2) {
-                candidates.add(diskInfo);
-            }
-        }
-
-        if (!candidates.isEmpty()) {
-            // TODO 如果 candidates 大于 0 则判断准确的那个
-            return candidates.get(0);
-        } else {
-            return null;
-        }
-    }
-}

+ 0 - 69
common/src/main/java/cn/reghao/devops/common/machine/Machine.java

@@ -1,69 +0,0 @@
-package cn.reghao.devops.common.machine;
-
-import cn.reghao.devops.common.msg.event.EvtAgentHeartbeat;
-import cn.reghao.devops.common.msg.event.EvtAgentStart;
-import cn.reghao.devops.common.version.AppVersion;
-import cn.reghao.jutil.jdk.machine.data.detail.*;
-import cn.reghao.jutil.jdk.machine.id.MachineId;
-import cn.reghao.jutil.jdk.machine.id.MachineIdLinux;
-import oshi.SystemInfo;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @author reghao
- * @date 2020-10-22 15:47:58
- */
-public class Machine {
-    public final static String ID;
-    public final static String IPV4;
-    static {
-        MachineId machineId = new MachineIdLinux();
-        ID = machineId.id();
-        // TODO ip 发生变化时会引发数据不一致
-        IPV4 = machineId.ipv4();
-    }
-
-    private final Os os;
-    private final Network network;
-    private final Cpu cpu;
-    private final Memory memory;
-    private final Disk disk;
-
-    public Machine() {
-        SystemInfo si = new SystemInfo();
-        this.os = new Os(si.getOperatingSystem());
-        this.network = new Network();
-        this.cpu = new Cpu(si.getHardware().getProcessor());
-        this.memory = new Memory(si.getHardware().getMemory());
-        this.disk = new Disk(si);
-    }
-
-    public EvtAgentStart detail() {
-        EvtAgentStart machineDetail = new EvtAgentStart();
-        machineDetail.setMachineId(Machine.ID);
-        machineDetail.setAppVersion(AppVersion.getVersion());
-
-        machineDetail.setOsDetail(os.detail());
-        List<NetworkDetail> list = network.detail().stream()
-                .peek(networkDetail -> {
-                    networkDetail.setPubicIpv4("0.0.0.0");
-                })
-                .collect(Collectors.toList());
-        machineDetail.setNetworkDetails(list);
-
-        machineDetail.setCpuDetail(cpu.detail());
-        machineDetail.setMemoryDetail(memory.detail());
-        machineDetail.setDiskDetails(disk.detail());
-        return machineDetail;
-    }
-
-    public EvtAgentHeartbeat stat() {
-        EvtAgentHeartbeat machineStat = new EvtAgentHeartbeat();
-        machineStat.setMachineId(Machine.ID);
-        machineStat.setMemoryDetail(memory.detail());
-        machineStat.setDiskDetails(disk.detail());
-        return machineStat;
-    }
-}

+ 0 - 52
common/src/main/java/cn/reghao/devops/common/machine/Memory.java

@@ -1,52 +0,0 @@
-package cn.reghao.devops.common.machine;
-
-import cn.reghao.jutil.jdk.machine.data.MachineData;
-import cn.reghao.jutil.jdk.machine.data.detail.MemoryDetail;
-import oshi.hardware.GlobalMemory;
-import oshi.hardware.VirtualMemory;
-
-/**
- * @author reghao
- * @date 2019-10-25 13:21:25
- */
-public class Memory implements MachineData<MemoryDetail, MemoryStat> {
-    private final GlobalMemory globalMemory;
-    private final VirtualMemory virtualMemory;
-    private MemoryDetail memoryDetail;
-
-    public Memory(GlobalMemory globalMemory) {
-        this.globalMemory = globalMemory;
-        this.virtualMemory = globalMemory.getVirtualMemory();
-    }
-
-    @Override
-    public MemoryDetail detail() {
-        long total = globalMemory.getTotal();
-        long avail = globalMemory.getAvailable();
-        long swapTotal = virtualMemory.getSwapTotal();
-        long swapUsed = virtualMemory.getSwapUsed();
-
-        if (memoryDetail == null) {
-            memoryDetail = new MemoryDetail(total, avail, total-avail, swapTotal, swapTotal-swapUsed);
-        }
-
-        return memoryDetail;
-    }
-
-    @Override
-    public MemoryStat stat() {
-        if (memoryDetail == null) {
-            memoryDetail = detail();
-        }
-
-        long total = globalMemory.getTotal();
-        long avail = globalMemory.getAvailable();
-        memoryDetail.setAvail(avail);
-        memoryDetail.setUsed(total-avail);
-
-        long swapTotal = virtualMemory.getSwapTotal();
-        long swapUsed = virtualMemory.getSwapUsed();
-        memoryDetail.setAvail(swapTotal-swapUsed);
-        return null;
-    }
-}

+ 0 - 27
common/src/main/java/cn/reghao/devops/common/machine/MemoryStat.java

@@ -1,27 +0,0 @@
-package cn.reghao.devops.common.machine;
-
-import cn.reghao.jutil.jdk.converter.ByteConverter;
-import cn.reghao.jutil.jdk.converter.ByteType;
-import lombok.Data;
-
-import java.lang.management.MemoryUsage;
-
-/**
- * @author reghao
- * @date 2020-10-21 15:49:56
- */
-@Data
-public class MemoryStat {
-    private String init;
-    private String max;
-    private String used;
-    private String committed;
-
-    public MemoryStat(MemoryUsage memoryUsage) {
-        ByteConverter convert = new ByteConverter();
-        this.init = convert.convert(memoryUsage.getInit());
-        this.max = convert.convert(memoryUsage.getMax());
-        this.used = convert.convert(memoryUsage.getUsed());
-        this.committed = convert.convert(memoryUsage.getCommitted());
-    }
-}

+ 0 - 75
common/src/main/java/cn/reghao/devops/common/machine/Network.java

@@ -1,75 +0,0 @@
-package cn.reghao.devops.common.machine;
-
-import cn.reghao.jutil.jdk.machine.data.MachineData;
-import cn.reghao.jutil.jdk.machine.data.detail.NetworkDetail;
-import cn.reghao.jutil.jdk.machine.data.stat.NetworkStat;
-
-import java.net.*;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2021-10-16 18:45:39
- */
-public class Network implements MachineData<List<NetworkDetail>, NetworkStat> {
-    @Override
-    public List<NetworkDetail> detail() {
-        List<NetworkDetail> list = new ArrayList<>();
-        try {
-            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
-            // 遍历主机的网络接口
-            while (interfaces.hasMoreElements()) {
-                NetworkInterface iface = interfaces.nextElement();
-                String ifaceName = iface.getName();
-                // 过滤掉 localhost 和虚拟网卡
-                if (ifaceName.startsWith("enp")
-                        || ifaceName.startsWith("wlp")
-                        || ifaceName.startsWith("eth")
-                        || ifaceName.startsWith("wlan")
-                        || ifaceName.startsWith("em")) {
-                    String ifaceMac = macAddr(iface.getHardwareAddress());
-                    NetworkDetail networkDetail = new NetworkDetail(ifaceName, ifaceMac);
-
-                    Enumeration<InetAddress> inetAddrs = iface.getInetAddresses();
-                    while (inetAddrs.hasMoreElements()) {
-                        InetAddress address = inetAddrs.nextElement();
-                        if (!address.isLoopbackAddress()) {
-                            if (address instanceof Inet4Address) {
-                                networkDetail.setIpv4(address.getHostAddress());
-                            } else if (address instanceof Inet6Address) {
-                                networkDetail.setIpv6(address.getHostAddress());
-                            }
-                        }
-                    }
-
-                    list.add(networkDetail);
-                }
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return list;
-    }
-
-    /**
-     * 返回 52-54-00-bf-ab-2d 格式的 MAC 地址
-     *
-     * @param
-     * @return
-     * @date 2020-10-14 下午1:53
-     */
-    private static String macAddr(byte[] addr) {
-        String[] hexadecimal = new String[addr.length];
-        for (int i = 0; i < addr.length; i++) {
-            hexadecimal[i] = String.format("%02x", addr[i]);
-        }
-        return String.join("-", hexadecimal);
-    }
-
-    @Override
-    public NetworkStat stat() {
-        return null;
-    }
-}

+ 0 - 30
common/src/main/java/cn/reghao/devops/common/machine/Os.java

@@ -1,30 +0,0 @@
-package cn.reghao.devops.common.machine;
-
-import cn.reghao.jutil.jdk.machine.data.MachineData;
-import cn.reghao.jutil.jdk.machine.data.detail.OsDetail;
-import cn.reghao.jutil.jdk.machine.data.stat.OsStat;
-import oshi.software.os.OperatingSystem;
-
-/**
- * @author reghao
- * @date 2020-10-20 23:17:30
- */
-public class Os implements MachineData<OsDetail, OsStat> {
-    private OperatingSystem os;
-
-    public Os(OperatingSystem os) {
-        this.os = os;
-    }
-
-    @Override
-    public OsDetail detail() {
-        OsDetail osDetail = new OsDetail();
-        osDetail.setBootTime(os.getSystemBootTime());
-        return osDetail;
-    }
-
-    @Override
-    public OsStat stat() {
-        return null;
-    }
-}

+ 0 - 17
common/src/main/java/cn/reghao/devops/common/msg/MessageSender.java

@@ -1,17 +0,0 @@
-package cn.reghao.devops.common.msg;
-
-import java.io.IOException;
-
-/**
- * @author reghao
- * @date 2023-02-23 09:25:57
- */
-public interface MessageSender {
-    default void connect() {
-    }
-    void setConnected(boolean status);
-    boolean isConnected();
-    void send(String dest, Object message) throws IOException;
-    default void close() {
-    }
-}

+ 0 - 9
common/src/main/java/cn/reghao/devops/common/msg/constant/AppId.java

@@ -1,9 +0,0 @@
-package cn.reghao.devops.common.msg.constant;
-
-/**
- * @author reghao
- * @date 2021-08-27 17:32:08
- */
-public enum AppId {
-    mgr, build, agent
-}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů