reghao 4 лет назад
Родитель
Сommit
0f322956a0
41 измененных файлов с 569 добавлено и 117 удалено
  1. 6 0
      common/pom.xml
  2. 11 3
      common/src/main/java/cn/reghao/autodop/common/beans/BeansConfig.java
  3. 3 3
      common/src/main/java/cn/reghao/autodop/common/machine/Cpu.java
  4. 50 7
      common/src/main/java/cn/reghao/autodop/common/machine/Disk.java
  5. 7 9
      common/src/main/java/cn/reghao/autodop/common/machine/Machine.java
  6. 18 4
      common/src/main/java/cn/reghao/autodop/common/machine/Memory.java
  7. 73 0
      common/src/main/java/cn/reghao/autodop/common/machine/Network.java
  8. 3 3
      common/src/main/java/cn/reghao/autodop/common/machine/Os.java
  9. 2 2
      dagent/src/main/java/cn/reghao/autodop/dagent/machine/NodeClazzPubImpl.java
  10. 3 3
      dmaster/pom.xml
  11. 6 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/page/BuildDirPageController.java
  12. 6 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/config/impl/BuildDirServiceImpl.java
  13. 11 6
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/controller/page/MachineHostPageController.java
  14. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/db/crud/MachineHostCrudImpl.java
  15. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/DiskInfo.java
  16. 0 7
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/MachineHost.java
  17. 5 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/MachineInfo.java
  18. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/NetworkInfo.java
  19. 2 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/SshAuth.java
  20. 27 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/vo/DiskInfoVO.java
  21. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/vo/DiskUsage.java
  22. 58 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/vo/MachineInfoVO.java
  23. 0 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/MachineServiceImpl.java
  24. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/page/MachineHostPage.java
  25. 14 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/page/MachineHostPageImpl.java
  26. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/mqttsub/impl/pub/NodePubClazzHandler.java
  27. 2 5
      dmaster/src/main/java/cn/reghao/autodop/dmaster/mqttsub/impl/pub/NodePubClazzImpl.java
  28. 23 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/spring/DmasterLifecycle.java
  29. 19 5
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/SysPageController.java
  30. 11 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/crud/SysEnvCrud.java
  31. 43 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/crud/SysEnvCrudImpl.java
  32. 13 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/query/SysEnvQuery.java
  33. 35 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/query/SysEnvQueryImpl.java
  34. 13 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/repository/SysEnvRepository.java
  35. 26 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/model/SysEnv.java
  36. 43 7
      dmaster/src/main/resources/templates/machine/host/detail.html
  37. 1 1
      dmaster/src/main/resources/templates/machine/host/env.html
  38. 1 1
      dmaster/src/main/resources/templates/machine/host/notify.html
  39. 12 3
      dmaster/src/main/resources/templates/machine/host/sshauth.html
  40. 14 18
      dmaster/src/main/resources/templates/sys/sysenv.html
  41. 0 6
      pom.xml

+ 6 - 0
common/pom.xml

@@ -59,5 +59,11 @@
             <artifactId>httpmime</artifactId>
             <version>4.5.8</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+            <version>5.8.2</version>
+        </dependency>
     </dependencies>
 </project>

+ 11 - 3
common/src/main/java/cn/reghao/autodop/common/beans/BeansConfig.java

@@ -1,6 +1,8 @@
 package cn.reghao.autodop.common.beans;
 
-import cn.reghao.autodop.common.machine.Machine;
+import cn.reghao.autodop.common.util.ByteConverter;
+import cn.reghao.jdkutil.http.WebClient;
+import cn.reghao.jdkutil.http.WebRequest;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import oshi.SystemInfo;
@@ -16,7 +18,13 @@ public class BeansConfig {
         return new SystemInfo();
     }
 
-    public Machine machine() {
-        return new Machine(systemInfo());
+    @Bean
+    public WebRequest webRequest() {
+        return new WebClient();
+    }
+
+    @Bean
+    public ByteConverter byteConverter() {
+        return new ByteConverter();
     }
 }

+ 3 - 3
common/src/main/java/cn/reghao/autodop/common/machine/Cpu.java

@@ -1,8 +1,8 @@
 package cn.reghao.autodop.common.machine;
 
-import cn.reghao.jdkutil.machine.MachineData;
-import cn.reghao.jdkutil.machine.detail.CpuDetail;
-import cn.reghao.jdkutil.machine.stat.CpuStat;
+import cn.reghao.jdkutil.machine.data.MachineData;
+import cn.reghao.jdkutil.machine.data.detail.CpuDetail;
+import cn.reghao.jdkutil.machine.data.stat.CpuStat;
 import oshi.hardware.CentralProcessor;
 
 /**

+ 50 - 7
common/src/main/java/cn/reghao/autodop/common/machine/Disk.java

@@ -1,11 +1,12 @@
 package cn.reghao.autodop.common.machine;
 
-import cn.reghao.jdkutil.machine.MachineData;
-import cn.reghao.jdkutil.machine.detail.DiskDetail;
-import cn.reghao.jdkutil.machine.stat.DiskStat;
+import cn.reghao.jdkutil.machine.data.MachineData;
+import cn.reghao.jdkutil.machine.data.detail.DiskDetail;
+import cn.reghao.jdkutil.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;
 
@@ -14,22 +15,25 @@ import java.util.stream.Collectors;
  * @date 2019-10-25 13:21:25
  */
 public class Disk implements MachineData<List<DiskDetail>, List<DiskStat>> {
-    private OperatingSystem os;
+    private final OperatingSystem os;
 
     public Disk(SystemInfo si) {
         this.os = si.getOperatingSystem();
+        //this.os = new SystemInfo().getOperatingSystem();
     }
 
     @Override
     public List<DiskDetail> detail() {
-        List<DiskDetail> diskDetails = os.getFileSystem().getFileStores().stream()
+        return os.getFileSystem().getFileStores().stream()
                 .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();
@@ -38,12 +42,51 @@ public class Disk implements MachineData<List<DiskDetail>, List<DiskStat>> {
                     return new DiskDetail(vol, mount, fsType, total, userAvail, total-userAvail, inodeTotal, inodeFree);
                 })
                 .collect(Collectors.toList());
-
-        return diskDetails;
     }
 
     @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 static void main(String[] args) {
+        Disk disk = new Disk(new SystemInfo());
+        List<DiskDetail> diskInfos = disk.detail();
+        System.out.println();
+    }
 }

+ 7 - 9
common/src/main/java/cn/reghao/autodop/common/machine/Machine.java

@@ -1,14 +1,11 @@
 package cn.reghao.autodop.common.machine;
 
-import cn.reghao.jdkutil.http.WebClient;
 import cn.reghao.jdkutil.http.WebRequest;
 import cn.reghao.jdkutil.http.WebResponse;
-import cn.reghao.jdkutil.machine.Disk;
-import cn.reghao.jdkutil.machine.Network;
-import cn.reghao.jdkutil.machine.detail.*;
+import cn.reghao.jdkutil.machine.data.detail.*;
 import cn.reghao.jdkutil.machine.id.MachineId;
 import cn.reghao.jdkutil.machine.id.MachineIdLinux;
-import cn.reghao.jdkutil.machine.stat.MachineStat;
+import cn.reghao.jdkutil.machine.data.stat.MachineStat;
 import org.springframework.stereotype.Service;
 import oshi.SystemInfo;
 
@@ -26,23 +23,24 @@ public class Machine {
     static {
         MachineId machineId = new MachineIdLinux();
         ID = machineId.id();
+        // TODO ip 发生变化时会引发数据不一致
         IPV4 = machineId.ipv4();
     }
 
+    private final WebRequest webRequest;
     private final Os os;
     private final Network network;
     private final Cpu cpu;
     private final Memory memory;
     private final Disk disk;
 
-    private final WebRequest webRequest = new WebClient();
-
-    public Machine(SystemInfo si) {
+    public Machine(WebRequest webRequest, SystemInfo si) {
+        this.webRequest = webRequest;
         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();
+        this.disk = new Disk(si);
     }
 
     public MachineDetail detail() {

+ 18 - 4
common/src/main/java/cn/reghao/autodop/common/machine/Memory.java

@@ -1,9 +1,11 @@
 package cn.reghao.autodop.common.machine;
 
 import cn.reghao.autodop.common.util.jvm.po.MemoryStat;
-import cn.reghao.jdkutil.machine.MachineData;
-import cn.reghao.jdkutil.machine.detail.MemoryDetail;
+import cn.reghao.jdkutil.machine.data.MachineData;
+import cn.reghao.jdkutil.machine.data.detail.MemoryDetail;
+import oshi.SystemInfo;
 import oshi.hardware.GlobalMemory;
+import oshi.hardware.Sensors;
 import oshi.hardware.VirtualMemory;
 
 /**
@@ -11,8 +13,8 @@ import oshi.hardware.VirtualMemory;
  * @date 2019-10-25 13:21:25
  */
 public class Memory implements MachineData<MemoryDetail, MemoryStat> {
-    private GlobalMemory globalMemory;
-    private VirtualMemory virtualMemory;
+    private final GlobalMemory globalMemory;
+    private final VirtualMemory virtualMemory;
     private MemoryDetail memoryDetail;
 
     public Memory(GlobalMemory globalMemory) {
@@ -50,4 +52,16 @@ public class Memory implements MachineData<MemoryDetail, MemoryStat> {
         memoryDetail.setAvail(swapTotal-swapUsed);
         return null;
     }
+
+    public static void main(String[] args) {
+        SystemInfo si = new SystemInfo();
+        Memory memory = new Memory(si.getHardware().getMemory());
+        MemoryDetail memoryDetail = memory.detail();
+
+        Sensors sensors = si.getHardware().getSensors();
+        double temperature = sensors.getCpuTemperature();
+        double voltage = sensors.getCpuVoltage();
+        int[] fanSpeeds = sensors.getFanSpeeds();
+        System.out.println();
+    }
 }

+ 73 - 0
common/src/main/java/cn/reghao/autodop/common/machine/Network.java

@@ -0,0 +1,73 @@
+package cn.reghao.autodop.common.machine;
+
+import cn.reghao.jdkutil.machine.data.MachineData;
+import cn.reghao.jdkutil.machine.data.detail.NetworkDetail;
+import cn.reghao.jdkutil.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("lo") || ifaceName.startsWith("docker")
+                        || ifaceName.startsWith("v") || ifaceName.startsWith("br")) {
+                    continue;
+                }
+                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 (SocketException 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;
+    }
+}

+ 3 - 3
common/src/main/java/cn/reghao/autodop/common/machine/Os.java

@@ -1,8 +1,8 @@
 package cn.reghao.autodop.common.machine;
 
-import cn.reghao.jdkutil.machine.MachineData;
-import cn.reghao.jdkutil.machine.detail.OsDetail;
-import cn.reghao.jdkutil.machine.stat.OsStat;
+import cn.reghao.jdkutil.machine.data.MachineData;
+import cn.reghao.jdkutil.machine.data.detail.OsDetail;
+import cn.reghao.jdkutil.machine.data.stat.OsStat;
 import oshi.software.os.OperatingSystem;
 
 /**

+ 2 - 2
dagent/src/main/java/cn/reghao/autodop/dagent/machine/NodeClazzPubImpl.java

@@ -7,8 +7,8 @@ import cn.reghao.autodop.common.msg.MsgQueue;
 import cn.reghao.autodop.common.msg.pub.PubMsg;
 import cn.reghao.autodop.common.msg.pub.clazz.NodePubClazz;
 import cn.reghao.autodop.common.util.thread.ThreadPoolWrapper;
-import cn.reghao.jdkutil.machine.detail.MachineDetail;
-import cn.reghao.jdkutil.machine.stat.MachineStat;
+import cn.reghao.jdkutil.machine.data.detail.MachineDetail;
+import cn.reghao.jdkutil.machine.data.stat.MachineStat;
 import cn.reghao.jdkutil.serializer.JsonConverter;
 import lombok.extern.slf4j.Slf4j;
 import org.eclipse.paho.client.mqttv3.MqttException;

+ 3 - 3
dmaster/pom.xml

@@ -113,7 +113,7 @@
         <dependency>
             <groupId>org.tmatesoft.svnkit</groupId>
             <artifactId>svnkit</artifactId>
-            <version>1.10.1</version>
+            <version>1.10.3</version>
         </dependency>
 
         <dependency>
@@ -134,11 +134,11 @@
             <version>0.9.1</version>
         </dependency>
 
-        <dependency>
+        <!--<dependency>
             <groupId>net.java.dev.jna</groupId>
             <artifactId>jna</artifactId>
             <version>4.1.0</version>
-        </dependency>
+        </dependency>-->
 
         <dependency>
             <groupId>org.libvirt</groupId>

+ 6 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/page/BuildDirPageController.java

@@ -1,11 +1,11 @@
 package cn.reghao.autodop.dmaster.app.controller.page;
 
+import cn.reghao.autodop.common.machine.Disk;
 import cn.reghao.autodop.dmaster.app.db.query.config.BuildDirQuery;
 import cn.reghao.autodop.dmaster.app.model.po.config.build.BuildDir;
 import cn.reghao.autodop.dmaster.machine.model.vo.DiskUsage;
 import cn.reghao.autodop.dmaster.util.db.PageList;
 import cn.reghao.autodop.dmaster.util.db.PageSort;
-import cn.reghao.jdkutil.machine.Disk;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -16,6 +16,7 @@ import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
+import oshi.SystemInfo;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -29,10 +30,11 @@ import java.util.stream.Collectors;
 @Controller
 @RequestMapping("/app/config/build/dir")
 public class BuildDirPageController {
-    private BuildDirQuery buildDirQuery;
-    private Disk disk = new Disk();
+    private final BuildDirQuery buildDirQuery;
+    private final Disk disk;
 
-    public BuildDirPageController(BuildDirQuery buildDirQuery) {
+    public BuildDirPageController(SystemInfo si, BuildDirQuery buildDirQuery) {
+        this.disk = new Disk(si);
         this.buildDirQuery = buildDirQuery;
     }
 

+ 6 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/config/impl/BuildDirServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.reghao.autodop.dmaster.app.service.config.impl;
 
+import cn.reghao.autodop.common.machine.Disk;
 import cn.reghao.autodop.common.machine.Machine;
 import cn.reghao.autodop.common.util.ByteConverter;
 import cn.reghao.autodop.common.util.ByteType;
@@ -9,12 +10,12 @@ import cn.reghao.autodop.dmaster.app.db.query.config.BuildDirQuery;
 import cn.reghao.autodop.dmaster.app.model.po.config.build.BuildDir;
 import cn.reghao.autodop.dmaster.app.model.po.config.build.LocalBuildDir;
 import cn.reghao.autodop.dmaster.app.service.config.BuildDirService;
-import cn.reghao.jdkutil.machine.Disk;
-import cn.reghao.jdkutil.machine.detail.DiskDetail;
+import cn.reghao.jdkutil.machine.data.detail.DiskDetail;
 import cn.reghao.jdkutil.result.Result;
 import cn.reghao.jdkutil.result.ResultStatus;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import oshi.SystemInfo;
 
 import java.io.File;
 import java.io.IOException;
@@ -31,9 +32,10 @@ public class BuildDirServiceImpl implements BuildDirService {
     private final BuildDirQuery buildDirQuery;
     private final BuildDirCrud buildDirCrud;
     private final ByteConverter converter;
-    private Disk disk = new Disk();
+    private final Disk disk;
 
-    public BuildDirServiceImpl(BuildDirQuery buildDirQuery, BuildDirCrud buildDirCrud) {
+    public BuildDirServiceImpl(SystemInfo si, BuildDirQuery buildDirQuery, BuildDirCrud buildDirCrud) {
+        this.disk = new Disk(si);
         this.buildDirQuery = buildDirQuery;
         this.buildDirCrud = buildDirCrud;
         this.converter = new ByteConverter();

+ 11 - 6
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/controller/page/MachineHostPageController.java

@@ -5,8 +5,8 @@ import cn.reghao.autodop.dmaster.app.model.vo.KeyValue;
 import cn.reghao.autodop.dmaster.machine.model.SshConnData;
 import cn.reghao.autodop.dmaster.machine.model.po.MachineHost;
 import cn.reghao.autodop.dmaster.machine.model.po.SshAuth;
-import cn.reghao.autodop.dmaster.machine.model.po.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.model.vo.MachineHostVO;
+import cn.reghao.autodop.dmaster.machine.model.vo.MachineInfoVO;
 import cn.reghao.autodop.dmaster.machine.service.page.MachineHostPage;
 import cn.reghao.autodop.dmaster.machine.service.ssh.Keys;
 import cn.reghao.autodop.dmaster.util.db.PageList;
@@ -42,7 +42,7 @@ public class MachineHostPageController {
 
     @ApiOperation(value = "机器节点页面")
     @GetMapping
-    public String hostPage(@RequestParam(value = "env", required = false) String env,
+    public String indexPage(@RequestParam(value = "env", required = false) String env,
                            @RequestParam(value = "machineIpv4", required = false) String machineIpv4,
                            Model model) {
         if (env == null) {
@@ -76,7 +76,7 @@ public class MachineHostPageController {
         model.addAttribute("machineId", machineId);
         model.addAttribute("environments", envs);
         model.addAttribute("env", env);
-        return "/machine/host/edit";
+        return "/machine/host/env";
     }
 
     @ApiOperation(value = "SSH 认证设置页面")
@@ -84,7 +84,12 @@ public class MachineHostPageController {
     public String sshAuthPage(@PathVariable("machineId") String machineId, Model model) {
         SshAuth sshAuth = machineHostPage.setSshAuthPage(machineId);
 
+        List<KeyValue> ipv4List = new ArrayList<>();
+        String machineIpv4 = "";
+
         model.addAttribute("machineId", machineId);
+        model.addAttribute("machineIpv4", machineIpv4);
+        model.addAttribute("ipv4List", ipv4List);
         model.addAttribute("sshAuth", sshAuth);
         return "/machine/host/sshauth";
     }
@@ -99,7 +104,7 @@ public class MachineHostPageController {
         model.addAttribute("machineId", machineId);
         model.addAttribute("currentSet", currentSet);
         model.addAttribute("list", list);*/
-        return "/machine/host/machinenotify";
+        return "/machine/host/notify";
     }
 
     @ApiOperation(value = "SSH 控制台页面")
@@ -128,8 +133,8 @@ public class MachineHostPageController {
     @ApiOperation(value = "机器信息详情页面")
     @GetMapping("/detail/{machineId}")
     public String hostDetailPage(@PathVariable("machineId") String machineId, Model model) {
-        MachineInfo machineInfo = machineHostPage.hostDetailPage(machineId);
-        model.addAttribute("machine", machineInfo);
+        MachineInfoVO machineInfoVO = machineHostPage.hostDetailPage(machineId);
+        model.addAttribute("machine", machineInfoVO);
         return "/machine/host/detail";
     }
 }

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/db/crud/MachineHostCrudImpl.java

@@ -32,7 +32,7 @@ public class MachineHostCrudImpl implements MachineHostCrud {
 
     @Override
     public void update(MachineHost machineHost) {
-        // 利用 AOP 统一设置更新时间
+        // TODO 利用 AOP 统一设置更新时间
         machineHost.setUpdateTime(LocalDateTime.now());
         hostRepository.save(machineHost);
     }

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/DiskInfo.java

@@ -1,6 +1,6 @@
 package cn.reghao.autodop.dmaster.machine.model.po;
 
-import cn.reghao.jdkutil.machine.detail.DiskDetail;
+import cn.reghao.jdkutil.machine.data.detail.DiskDetail;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 

+ 0 - 7
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/MachineHost.java

@@ -3,10 +3,7 @@ package cn.reghao.autodop.dmaster.machine.model.po;
 import cn.reghao.autodop.common.msg.pub.dto.node.constant.NodeStatus;
 import cn.reghao.autodop.dmaster.app.model.constant.EnvList;
 import cn.reghao.autodop.dmaster.util.db.BaseEntity;
-import cn.reghao.autodop.dmaster.notification.model.po.NotifyGroup;
 import lombok.*;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
 
 import javax.persistence.*;
 import java.util.List;
@@ -32,10 +29,6 @@ public class MachineHost extends BaseEntity<Integer> {
     private long lastCheck;
     @Embedded
     private SshAuth sshAuth;
-    @ManyToMany(cascade = CascadeType.REFRESH)
-    @JoinColumn(name = "notify_group_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
-    @LazyCollection(LazyCollectionOption.FALSE)
-    private List<NotifyGroup> notifyGroups;
 
     // TODO 根据机器所属的地区,机房等维度来分组
     public MachineHost(MachineInfo machineInfo) {

+ 5 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/MachineInfo.java

@@ -1,13 +1,14 @@
 package cn.reghao.autodop.dmaster.machine.model.po;
 
 import cn.reghao.autodop.dmaster.util.db.BaseEntity;
-import cn.reghao.jdkutil.machine.detail.*;
+import cn.reghao.jdkutil.machine.data.detail.*;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 import org.hibernate.annotations.LazyCollection;
 import org.hibernate.annotations.LazyCollectionOption;
 
+import javax.persistence.Column;
 import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
 import java.time.LocalDateTime;
@@ -22,7 +23,8 @@ import java.util.stream.Collectors;
 @Getter
 @Setter
 @Entity
-public class MachineInfo  extends BaseEntity<Integer> {
+public class MachineInfo extends BaseEntity<Integer> {
+    @Column(unique = true, nullable = false)
     private String machineId;
     private String machineIpv4;
 
@@ -65,6 +67,7 @@ public class MachineInfo  extends BaseEntity<Integer> {
 
         MemoryDetail memoryDetail = machineDetail.getMemoryDetail();
         this.memTotal = memoryDetail.getTotal();
+        this.swapTotal = memoryDetail.getSwapTotal();
         this.diskInfos = machineDetail.getDiskDetails().stream().map(DiskInfo::new).collect(Collectors.toList());
         setNetworkInfos(machineDetail.getNetworkDetails());
     }

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/NetworkInfo.java

@@ -1,6 +1,6 @@
 package cn.reghao.autodop.dmaster.machine.model.po;
 
-import cn.reghao.jdkutil.machine.detail.NetworkDetail;
+import cn.reghao.jdkutil.machine.data.detail.NetworkDetail;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 

+ 2 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/po/SshAuth.java

@@ -15,6 +15,8 @@ import javax.validation.constraints.Positive;
 @Data
 @Embeddable
 public class SshAuth {
+    @NotBlank(message = "IPv4 地址为空白字符串")
+    private String ipv4;
     @Positive(message = "SSH 端口必须有效")
     private Integer port;
     @NotBlank(message = "用户名为空白字符串")

+ 27 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/vo/DiskInfoVO.java

@@ -0,0 +1,27 @@
+package cn.reghao.autodop.dmaster.machine.model.vo;
+
+import cn.reghao.autodop.common.util.ByteConverter;
+import cn.reghao.autodop.common.util.ByteType;
+import cn.reghao.autodop.dmaster.machine.model.po.DiskInfo;
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2021-10-15 15:50:32
+ */
+@Data
+public class DiskInfoVO {
+    private String diskPath;
+    private String mountedOn;
+    private String fsType;
+    private String total;
+    private long inodeTotal;
+
+    public DiskInfoVO(DiskInfo diskInfo) {
+        this.diskPath = diskInfo.getDiskPath();
+        this.mountedOn = diskInfo.getMountedOn();
+        this.fsType = diskInfo.getFsType();
+        this.total = new ByteConverter().convert(ByteType.Bytes, diskInfo.getTotal());
+        this.inodeTotal = diskInfo.getInodeTotal();
+    }
+}

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/vo/DiskUsage.java

@@ -2,7 +2,7 @@ package cn.reghao.autodop.dmaster.machine.model.vo;
 
 import cn.reghao.autodop.common.util.ByteConverter;
 import cn.reghao.autodop.common.util.ByteType;
-import cn.reghao.jdkutil.machine.detail.DiskDetail;
+import cn.reghao.jdkutil.machine.data.detail.DiskDetail;
 import lombok.Data;
 
 /**

+ 58 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/model/vo/MachineInfoVO.java

@@ -0,0 +1,58 @@
+package cn.reghao.autodop.dmaster.machine.model.vo;
+
+import cn.reghao.autodop.common.util.ByteConverter;
+import cn.reghao.autodop.common.util.ByteType;
+import cn.reghao.autodop.dmaster.machine.model.po.MachineInfo;
+import cn.reghao.autodop.dmaster.machine.model.po.NetworkInfo;
+import cn.reghao.jdkutil.converter.DateTimeConverter;
+import lombok.Data;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author reghao
+ * @date 2020-12-25 17:53:15
+ */
+@Data
+public class MachineInfoVO {
+    private String machineId;
+    private String machineIpv4;
+
+    private String arch;
+    private String name;
+    // 系统版本或内核版本
+    private String version;
+    private String byteOrder;
+    private String bootTime;
+
+    private String vendor;
+    private String modelName;
+    private int physicalCore;
+    private int logicalCore;
+
+    private String memTotal;
+    private String swapTotal;
+    private List<DiskInfoVO> diskInfoVOs;
+    private List<NetworkInfo> networkInfos;
+
+    public MachineInfoVO(MachineInfo machineInfo) {
+        this.machineId = machineInfo.getMachineId();
+        this.machineIpv4 = machineInfo.getMachineIpv4();
+
+        this.arch = machineInfo.getArch();
+        this.name = machineInfo.getName();
+        this.version = machineInfo.getVersion();
+        this.byteOrder = machineInfo.getByteOrder();
+        this.bootTime = DateTimeConverter.format(machineInfo.getBootTime()*1000);
+
+        this.vendor = machineInfo.getVendor();
+        this.modelName = machineInfo.getModelName();
+        this.physicalCore = machineInfo.getPhysicalCore();
+        this.logicalCore = machineInfo.getLogicalCore();
+        this.memTotal = new ByteConverter().convert(ByteType.Bytes, machineInfo.getMemTotal());
+        this.swapTotal = new ByteConverter().convert(ByteType.Bytes, machineInfo.getSwapTotal());
+        this.diskInfoVOs = machineInfo.getDiskInfos().stream().map(DiskInfoVO::new).collect(Collectors.toList());
+        this.networkInfos = machineInfo.getNetworkInfos();
+    }
+}

+ 0 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/MachineServiceImpl.java

@@ -40,7 +40,6 @@ public class MachineServiceImpl implements MachineService {
     @Override
     public void setMachineNotify(String machineId, List<NotifyGroup> notifyGroups) {
         MachineHost machineHost = hostQuery.findByMachineId(machineId);
-        machineHost.setNotifyGroups(notifyGroups);
         hostCrud.save(machineHost);
     }
 }

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/page/MachineHostPage.java

@@ -1,9 +1,9 @@
 package cn.reghao.autodop.dmaster.machine.service.page;
 
 import cn.reghao.autodop.dmaster.machine.model.po.MachineHost;
-import cn.reghao.autodop.dmaster.machine.model.po.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.model.po.SshAuth;
 import cn.reghao.autodop.dmaster.machine.model.vo.MachineHostVO;
+import cn.reghao.autodop.dmaster.machine.model.vo.MachineInfoVO;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 
@@ -18,5 +18,5 @@ public interface MachineHostPage {
     SshAuth setSshAuthPage(String machineId);
     void setNotifyPage(String machineId);
     MachineHost sshTerminalPage(String machineId);
-    MachineInfo hostDetailPage(String machineId);
+    MachineInfoVO hostDetailPage(String machineId);
 }

+ 14 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/service/page/MachineHostPageImpl.java

@@ -5,8 +5,10 @@ import cn.reghao.autodop.dmaster.machine.db.query.MachineHostQuery;
 import cn.reghao.autodop.dmaster.machine.db.query.MachineInfoQuery;
 import cn.reghao.autodop.dmaster.machine.model.po.MachineHost;
 import cn.reghao.autodop.dmaster.machine.model.po.MachineInfo;
+import cn.reghao.autodop.dmaster.machine.model.po.NetworkInfo;
 import cn.reghao.autodop.dmaster.machine.model.po.SshAuth;
 import cn.reghao.autodop.dmaster.machine.model.vo.MachineHostVO;
+import cn.reghao.autodop.dmaster.machine.model.vo.MachineInfoVO;
 import cn.reghao.autodop.dmaster.notification.db.repository.NotifyGroupRepository;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
@@ -15,6 +17,7 @@ import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -59,6 +62,10 @@ public class MachineHostPageImpl implements MachineHostPage {
 
     @Override
     public SshAuth setSshAuthPage(String machineId) {
+        MachineInfo machineInfo = infoQuery.findByMachineId(machineId);
+        List<String> ipv4List = machineInfo.getNetworkInfos().stream()
+                .map(NetworkInfo::getIpv4).collect(Collectors.toList());
+
         return hostQuery.findByMachineId(machineId).getSshAuth();
     }
 
@@ -72,7 +79,12 @@ public class MachineHostPageImpl implements MachineHostPage {
     }
 
     @Override
-    public MachineInfo hostDetailPage(String machineId) {
-        return infoQuery.findByMachineId(machineId);
+    public MachineInfoVO hostDetailPage(String machineId) {
+        MachineInfo machineInfo = infoQuery.findByMachineId(machineId);
+        if (machineInfo != null) {
+            return new MachineInfoVO(machineInfo);
+        }
+
+        return null;
     }
 }

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/mqttsub/impl/pub/NodePubClazzHandler.java

@@ -2,8 +2,8 @@ package cn.reghao.autodop.dmaster.mqttsub.impl.pub;
 
 import cn.reghao.autodop.common.msg.pub.clazz.NodePubClazz;
 import cn.reghao.autodop.common.msg.pub.dto.node.NodeLogDTO;
-import cn.reghao.jdkutil.machine.detail.MachineDetail;
-import cn.reghao.jdkutil.machine.stat.MachineStat;
+import cn.reghao.jdkutil.machine.data.detail.MachineDetail;
+import cn.reghao.jdkutil.machine.data.stat.MachineStat;
 import cn.reghao.jdkutil.serializer.JsonConverter;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;

+ 2 - 5
dmaster/src/main/java/cn/reghao/autodop/dmaster/mqttsub/impl/pub/NodePubClazzImpl.java

@@ -1,6 +1,5 @@
 package cn.reghao.autodop.dmaster.mqttsub.impl.pub;
 
-import cn.reghao.autodop.common.machine.Machine;
 import cn.reghao.autodop.common.msg.pub.dto.node.NodeLogDTO;
 import cn.reghao.autodop.common.msg.pub.dto.node.constant.NodeStatus;
 import cn.reghao.autodop.dmaster.machine.db.crud.MachineHostCrud;
@@ -11,10 +10,8 @@ import cn.reghao.autodop.dmaster.machine.model.po.MachineHost;
 import cn.reghao.autodop.dmaster.machine.model.po.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.db.crud.NodeLogCrud;
 import cn.reghao.autodop.dmaster.machine.model.po.NodeLog;
-import cn.reghao.jdkutil.http.WebClient;
-import cn.reghao.jdkutil.http.WebRequest;
-import cn.reghao.jdkutil.machine.detail.MachineDetail;
-import cn.reghao.jdkutil.machine.stat.MachineStat;
+import cn.reghao.jdkutil.machine.data.detail.MachineDetail;
+import cn.reghao.jdkutil.machine.data.stat.MachineStat;
 import org.springframework.stereotype.Service;
 
 /**

+ 23 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/spring/DmasterLifecycle.java

@@ -6,10 +6,14 @@ import cn.reghao.autodop.common.log.LoggerConfig;
 import cn.reghao.autodop.common.machine.Machine;
 import cn.reghao.autodop.common.mqtt.DefaultMqttClient;
 import cn.reghao.autodop.common.msg.MsgQueue;
+import cn.reghao.autodop.dmaster.app.model.constant.EnvList;
 import cn.reghao.autodop.dmaster.app.model.po.config.build.BuildDir;
 import cn.reghao.autodop.dmaster.app.service.config.BuildDirService;
 import cn.reghao.autodop.dmaster.mqttsub.MessageListener;
 import cn.reghao.autodop.dmaster.machine.db.crud.NodeLogCrud;
+import cn.reghao.autodop.dmaster.sys.db.crud.SysEnvCrud;
+import cn.reghao.autodop.dmaster.sys.db.query.SysEnvQuery;
+import cn.reghao.autodop.dmaster.sys.model.SysEnv;
 import cn.reghao.autodop.dmaster.util.log.Appenders;
 import lombok.extern.slf4j.Slf4j;
 import org.eclipse.paho.client.mqttv3.MqttException;
@@ -31,13 +35,18 @@ public class DmasterLifecycle implements ApplicationRunner, DisposableBean {
     private final MessageListener messageListener;
     private final DefaultMqttClient mqttClient;
     private final BuildDirService buildDirService;
+    private SysEnvQuery sysEnvQuery;
+    private final SysEnvCrud sysEnvCrud;
 
-    public DmasterLifecycle(NodeLogCrud nodeLogCrud, MessageListener messageListener,
-                            BuildDirService buildDirService, DefaultMqttClient mqttClient) {
+    public DmasterLifecycle(NodeLogCrud nodeLogCrud, MessageListener messageListener, BuildDirService buildDirService,
+                            DefaultMqttClient mqttClient, SysEnvQuery sysEnvQuery, SysEnvCrud sysEnvCrud) {
         this.messageListener = messageListener;
-        this.mqttClient = mqttClient;
         this.buildDirService = buildDirService;
+        this.mqttClient = mqttClient;
+        this.sysEnvQuery = sysEnvQuery;
+        this.sysEnvCrud = sysEnvCrud;
         initLogger(nodeLogCrud);
+        initSysEnv();
     }
 
     private void initLogger(NodeLogCrud nodeLogCrud) {
@@ -72,4 +81,15 @@ public class DmasterLifecycle implements ApplicationRunner, DisposableBean {
             buildDirService.refresh(buildDir);
         }
     }
+
+    private void initSysEnv() {
+        for (EnvList env : EnvList.values()) {
+            String name = env.name();
+            SysEnv sysEnv = sysEnvQuery.findByEnv(name);
+            if (sysEnv == null) {
+                sysEnv = new SysEnv(name, "", false);
+                sysEnvCrud.save(sysEnv);
+            }
+        }
+    }
 }

+ 19 - 5
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/SysPageController.java

@@ -3,10 +3,15 @@ package cn.reghao.autodop.dmaster.sys.controller;
 import cn.reghao.autodop.common.util.jvm.JVM;
 import cn.reghao.autodop.common.util.jvm.po.JvmInfo;
 import cn.reghao.autodop.common.util.jvm.po.JvmStat;
+import cn.reghao.autodop.dmaster.sys.db.query.SysEnvQuery;
+import cn.reghao.autodop.dmaster.sys.model.SysEnv;
+import cn.reghao.autodop.dmaster.util.db.PageList;
 import cn.reghao.jdkutil.result.WebBody;
 import cn.reghao.autodop.dmaster.util.UploadDownload;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
@@ -15,6 +20,8 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * @author reghao
@@ -26,16 +33,23 @@ import java.nio.charset.StandardCharsets;
 public class SysPageController {
     private UploadDownload uploadDownload;
     private JVM jvm;
+    private SysEnvQuery sysEnvQuery;
 
-    public SysPageController(UploadDownload uploadDownload) {
+    public SysPageController(UploadDownload uploadDownload, SysEnvQuery sysEnvQuery) {
         this.uploadDownload = uploadDownload;
+        this.sysEnvQuery = sysEnvQuery;
         this.jvm = new JVM();
     }
 
-    @ApiOperation(value = "系统备份还原页面")
-    @GetMapping("/bak")
-    public String sysBakPage(Model model) {
-        return "/sys/bak";
+    @ApiOperation(value = "系统环境页面")
+    @GetMapping("/env")
+    public String sysEnvPage(Model model) {
+        List<SysEnv> list = sysEnvQuery.findAll();
+        Page<SysEnv> page = new PageImpl<>(list);
+        PageList<SysEnv> pageList = PageList.pageList(page);
+        model.addAttribute("page", page);
+        model.addAttribute("list", pageList.getList());
+        return "/sys/sysenv";
     }
 
     @ApiOperation(value = "JVM 状态页面")

+ 11 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/crud/SysEnvCrud.java

@@ -0,0 +1,11 @@
+package cn.reghao.autodop.dmaster.sys.db.crud;
+
+import cn.reghao.autodop.dmaster.sys.model.SysEnv;
+import cn.reghao.jdkutil.db.BaseCrud;
+
+/**
+ * @author reghao
+ * @date 2021-10-18 14:11:35
+ */
+public interface SysEnvCrud extends BaseCrud<SysEnv> {
+}

+ 43 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/crud/SysEnvCrudImpl.java

@@ -0,0 +1,43 @@
+package cn.reghao.autodop.dmaster.sys.db.crud;
+
+import cn.reghao.autodop.dmaster.sys.db.repository.SysEnvRepository;
+import cn.reghao.autodop.dmaster.sys.model.SysEnv;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2021-10-18 14:11:35
+ */
+@Service
+public class SysEnvCrudImpl implements SysEnvCrud {
+    private final SysEnvRepository sysEnvRepository;
+
+    public SysEnvCrudImpl(SysEnvRepository sysEnvRepository) {
+        this.sysEnvRepository = sysEnvRepository;
+    }
+
+    @Override
+    public SysEnv save(SysEnv sysEnv) {
+        sysEnvRepository.save(sysEnv);
+        return sysEnv;
+    }
+
+    @Override
+    public void saveAll(List<SysEnv> machineInfos) {
+        sysEnvRepository.saveAll(machineInfos);
+    }
+
+    @Override
+    public void update(SysEnv sysEnv) {
+        sysEnv.setUpdateTime(LocalDateTime.now());
+        sysEnvRepository.save(sysEnv);
+    }
+
+    @Override
+    public void delete(SysEnv sysEnv) {
+        sysEnvRepository.delete(sysEnv);
+    }
+}

+ 13 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/query/SysEnvQuery.java

@@ -0,0 +1,13 @@
+package cn.reghao.autodop.dmaster.sys.db.query;
+
+import cn.reghao.autodop.dmaster.sys.model.SysEnv;
+import cn.reghao.jdkutil.db.BaseQuery;
+
+/**
+ * @author reghao
+ * @date 2021-10-18 14:11:35
+ */
+public interface SysEnvQuery extends BaseQuery<SysEnv> {
+    SysEnv findByEnv(String env);
+    SysEnv findDefaultEnv();
+}

+ 35 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/query/SysEnvQueryImpl.java

@@ -0,0 +1,35 @@
+package cn.reghao.autodop.dmaster.sys.db.query;
+
+import cn.reghao.autodop.dmaster.sys.db.repository.SysEnvRepository;
+import cn.reghao.autodop.dmaster.sys.model.SysEnv;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2021-10-18 14:11:35
+ */
+@Service
+public class SysEnvQueryImpl implements SysEnvQuery {
+    private final SysEnvRepository sysEnvRepository;
+
+    public SysEnvQueryImpl(SysEnvRepository sysEnvRepository) {
+        this.sysEnvRepository = sysEnvRepository;
+    }
+
+    @Override
+    public List<SysEnv> findAll() {
+        return sysEnvRepository.findAll();
+    }
+
+    @Override
+    public SysEnv findByEnv(String env) {
+        return sysEnvRepository.findByEnv(env);
+    }
+
+    @Override
+    public SysEnv findDefaultEnv() {
+        return sysEnvRepository.findByIsDefaultTrue();
+    }
+}

+ 13 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/db/repository/SysEnvRepository.java

@@ -0,0 +1,13 @@
+package cn.reghao.autodop.dmaster.sys.db.repository;
+
+import cn.reghao.autodop.dmaster.sys.model.SysEnv;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * @author reghao
+ * @date 2021-10-18 14:10:21
+ */
+public interface SysEnvRepository extends JpaRepository<SysEnv, Integer> {
+    SysEnv findByEnv(String env);
+    SysEnv findByIsDefaultTrue();
+}

+ 26 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/model/SysEnv.java

@@ -0,0 +1,26 @@
+package cn.reghao.autodop.dmaster.sys.model;
+
+import cn.reghao.autodop.dmaster.util.db.BaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+/**
+ * @author reghao
+ * @date 2021-10-18 14:06:33
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+@Entity
+public class SysEnv extends BaseEntity<Integer> {
+    @Column(unique = true, nullable = false)
+    private String env;
+    private String envName;
+    private Boolean isDefault;
+}

+ 43 - 7
dmaster/src/main/resources/templates/machine/host/detail.html

@@ -4,7 +4,7 @@
 
 <body>
     <div class="timo-detail-page">
-        <div class="timo-detail-title">操作系统信息</div>
+        <div class="timo-detail-title">操作系统</div>
         <table class="layui-table timo-detail-table">
             <thead>
             <tr>
@@ -25,7 +25,7 @@
             </tr>
             </tbody>
         </table>
-        <div class="timo-detail-title">网络信息</div>
+        <div class="timo-detail-title">网络</div>
         <table class="layui-table timo-detail-table">
             <thead>
             <tr>
@@ -46,14 +46,14 @@
             </tr>
             </tbody>
         </table>
-        <div class="timo-detail-title">CPU 信息</div>
+        <div class="timo-detail-title">CPU</div>
         <table class="layui-table timo-detail-table">
             <thead>
             <tr>
-                <th data-field="vendor">CPU 品牌</th>
-                <th data-field="modelName">CPU 型号</th>
-                <th data-field="physicalCore">物理 CPU 数量</th>
-                <th data-field="logicalCore">逻辑 CPU 数量</th>
+                <th data-field="vendor">品牌</th>
+                <th data-field="modelName">型号</th>
+                <th data-field="physicalCore">物理</th>
+                <th data-field="logicalCore">逻辑</th>
             </tr>
             </thead>
             <tbody>
@@ -65,6 +65,42 @@
             </tr>
             </tbody>
         </table>
+        <div class="timo-detail-title">内存</div>
+        <table class="layui-table timo-detail-table">
+            <thead>
+            <tr>
+                <th data-field="memTotal">物理内存总量</th>
+                <th data-field="swapTotal">Swap 分区总量</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr>
+                <td th:text="${machine.memTotal}"></td>
+                <td th:text="${machine.swapTotal}"></td>
+            </tr>
+            </tbody>
+        </table>
+        <div class="timo-detail-title">磁盘</div>
+        <table class="layui-table timo-detail-table">
+            <thead>
+            <tr>
+                <th data-field="vendor">磁盘路径</th>
+                <th data-field="modelName">挂载分区</th>
+                <th data-field="physicalCore">文件系统</th>
+                <th data-field="logicalCore">磁盘总量</th>
+                <th data-field="logicalCore">inode 总量</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr th:each="item:${machine.diskInfoVOs}">
+                <td th:text="${item.diskPath}"></td>
+                <td th:text="${item.mountedOn}"></td>
+                <td th:text="${item.fsType}"></td>
+                <td th:text="${item.total}"></td>
+                <td th:text="${item.inodeTotal}"></td>
+            </tr>
+            </tbody>
+        </table>
     </div>
 <script th:replace="/common/template :: script"></script>
 </body>

+ 1 - 1
dmaster/src/main/resources/templates/machine/host/edit.html → dmaster/src/main/resources/templates/machine/host/env.html

@@ -4,7 +4,7 @@
 
 <body>
 <div class="layui-form timo-compile">
-    <form th:action="@{'/api/machine/host/extra/'+${machineId}}">
+    <form th:action="@{'/api/machine/host/env/'+${machineId}}">
         <div class="layui-form-item">
             <label class="layui-form-label required">环境</label>
             <div class="layui-input-inline">

+ 1 - 1
dmaster/src/main/resources/templates/machine/host/machinenotify.html → dmaster/src/main/resources/templates/machine/host/notify.html

@@ -20,7 +20,7 @@
 </head>
 <body>
 <div class="layui-form timo-compile">
-    <form th:action="@{'/api/machine/notify/'+ ${machineId}}">
+    <form th:action="@{'/api/machine/host/notify/'+ ${machineId}}">
         <div class="layui-form-item">
             <div class="layui-input-block">
                 <input th:each="item:${list}" type="checkbox" name="groupId" th:title="${item.groupId}"

+ 12 - 3
dmaster/src/main/resources/templates/machine/host/sshauth.html

@@ -4,7 +4,15 @@
 
 <body>
 <div class="layui-form timo-compile">
-    <form th:action="@{'/api/machine/sshauth/'+${machineId}}">
+    <form th:action="@{'/api/machine/host/sshauth/'+${machineId}}">
+        <div class="layui-form-item">
+            <label class="layui-form-label required">选择地址</label>
+            <div class="layui-input-inline">
+                <select name="machineIpv4">
+                    <option th:each="item : ${ipv4List}" th:value="${item.key}" th:selected="${machineIpv4} eq ${item.key}">[[${item.value}]]</option>
+                </select>
+            </div>
+        </div>
         <div class="layui-form-item">
             <label class="layui-form-label required">SSH 端口</label>
             <div class="layui-input-inline">
@@ -23,12 +31,13 @@
                 <input class="layui-input" type="text" name="password" placeholder="请输入用户密码" required th:value="${sshAuth?.password}">
             </div>
         </div>
-        <div class="layui-form-item">
+        <!-- TODO 暂时不使用私钥登录 -->
+        <!--<div class="layui-form-item">
             <label class="layui-form-label required">RSA 私钥</label>
             <div class="layui-input-inline">
                 <textarea class="layui-textarea" name="rsaPrikey" placeholder="请输入 RSA 私钥" required th:text="${sshAuth?.rsaPrikey}"></textarea>
             </div>
-        </div>
+        </div>-->
         <div class="layui-form-item timo-finally">
             <button class="layui-btn ajax-submit"><i class="fa fa-check-circle"></i> 保存</button>
             <button class="layui-btn btn-secondary close-popup"><i class="fa fa-times-circle"></i> 关闭</button>

+ 14 - 18
dmaster/src/main/resources/templates/sys/bak.html → dmaster/src/main/resources/templates/sys/sysenv.html

@@ -5,7 +5,7 @@
 <body class="timo-layout-page">
 <div class="layui-card" th:attr="data-url=@{/sys/bak}">
     <div class="layui-card-header timo-card-header">
-        <span><i class="fa fa-bars"></i> 备份还原</span>
+        <span><i class="fa fa-bars"></i> 系统环境</span>
         <i class="layui-icon layui-icon-refresh refresh-btn"></i>
     </div>
     <div class="layui-card-body">
@@ -17,30 +17,26 @@
                         <label class="timo-checkbox"><input type="checkbox">
                             <i class="layui-icon layui-icon-ok"></i></label>
                     </th>
-                    <th class="sortable" data-field="title">数据源</th>
-                    <th class="sortable" data-field="name">角色名</th>
-                    <th class="sortable" data-field="createTime">最近一次备份</th>
-                    <th class="sortable" data-field="updateTime">最近一次还原</th>
-                    <th>备份</th>
-                    <th>还原</th>
+                    <th class="sortable" data-field="env">环境</th>
+                    <th class="sortable" data-field="envName">环境名</th>
+                    <th class="sortable" data-field="isDefault">是否默认</th>
+                    <th>操作</th>
                 </tr>
                 </thead>
                 <tbody>
                 <tr th:each="item:${list}">
                     <td><label class="timo-checkbox"><input type="checkbox" th:value="${item.id}">
                         <i class="layui-icon layui-icon-ok"></i></label></td>
-                    <td th:text="${item.title}">数据源</td>
-                    <td th:text="${item.name}">角色名</td>
-                    <td th:text="${item.createTime}">最近一次备份</td>
-                    <td th:text="${item.updateTime}">最近一次还原</td>
+                    <td th:text="${item.env}">环境</td>
+                    <td th:text="${item.envName}">环境名</td>
+                    <td th:text="${item.isDefault}">是否默认</td>
                     <td>
-                        <a th:href="@{/sys/bak/export}"><i class="fa fa-download"></i></a>
-                    </td>
-                    <td>
-                        <button type="button" class="layui-btn upload-image" name="file[]"
-                                th:attr="up-url=@{/sys/bak/import}" up-field="path">
-                            <i class="fa fa-upload"></i>
-                        </button>
+                        <a class="open-popup" data-title="WebTerminal" th:attr="data-url=@{'/api/machine/host/webssh/'+${item.id}}"
+                           href="#">设为默认</a>
+                        <a class="open-popup" data-title="WebTerminal" th:attr="data-url=@{'/api/machine/host/webssh/'+${item.id}}"
+                           href="#">编辑</a>
+                        <a class="ajax-delete" th:attr="data-msg='确定要删除 '+ ${item.envName} + '?'"
+                           th:href="@{'/api/machine/host/' + ${item.id}}">删除</a>
                     </td>
                 </tr>
                 </tbody>

+ 0 - 6
pom.xml

@@ -44,12 +44,6 @@
             <version>1.0.0</version>
         </dependency>
 
-        <dependency>
-            <groupId>com.github.oshi</groupId>
-            <artifactId>oshi-core</artifactId>
-            <version>5.8.2</version>
-        </dependency>
-
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter</artifactId>