Procházet zdrojové kódy

精简 mgr/machine 模块

reghao před 6 měsíci
rodič
revize
97f5f40315
26 změnil soubory, kde provedl 303 přidání a 555 odebrání
  1. 42 8
      mgr/src/main/java/cn/reghao/devops/mgr/machine/controller/MachineController.java
  2. 0 62
      mgr/src/main/java/cn/reghao/devops/mgr/machine/controller/MachineHostController.java
  3. 2 4
      mgr/src/main/java/cn/reghao/devops/mgr/machine/db/query/MachineQuery.java
  4. 3 18
      mgr/src/main/java/cn/reghao/devops/mgr/machine/db/query/impl/MachineQueryImpl.java
  5. 0 13
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/MachineShell.java
  6. 0 20
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/dto/KeepalivedState.java
  7. 0 39
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/DiskInfo.java
  8. 1 8
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/MachineHost.java
  9. 4 23
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/MachineInfo.java
  10. 0 38
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/NetworkInfo.java
  11. 0 31
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/SshAuth.java
  12. 0 33
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/DiskUsage.java
  13. 0 15
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineAddress.java
  14. 2 4
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineDetail.java
  15. 0 49
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineInfoVO.java
  16. 0 18
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineSshAuth.java
  17. 0 17
      mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MemoryUsage.java
  18. 0 2
      mgr/src/main/java/cn/reghao/devops/mgr/machine/service/MachineService.java
  19. 2 15
      mgr/src/main/java/cn/reghao/devops/mgr/machine/service/impl/MachineServiceImpl.java
  20. 1 1
      mgr/src/main/java/cn/reghao/devops/mgr/machine/util/SshConnData.java
  21. 1 1
      mgr/src/main/java/cn/reghao/devops/mgr/machine/util/SshConnInfo.java
  22. 110 5
      mgr/src/main/java/cn/reghao/devops/mgr/machine/util/WebSsh.java
  23. 0 127
      mgr/src/main/java/cn/reghao/devops/mgr/machine/util/WebSshImpl.java
  24. 1 1
      mgr/src/main/resources/templates/devops/machine/host/env.html
  25. 2 2
      mgr/src/main/resources/templates/devops/machine/host/index.html
  26. 132 1
      mgr/src/test/java/cn/reghao/devops/mgr/devops/DockerTest.java

+ 42 - 8
mgr/src/main/java/cn/reghao/devops/mgr/machine/controller/MachineHostPageController.java → mgr/src/main/java/cn/reghao/devops/mgr/machine/controller/MachineController.java

@@ -2,23 +2,24 @@ package cn.reghao.devops.mgr.machine.controller;
 
 import cn.reghao.devops.common.util.KeyValue;
 import cn.reghao.devops.mgr.machine.db.query.MachineQuery;
+import cn.reghao.devops.mgr.machine.service.MachineService;
 import cn.reghao.devops.mgr.util.DefaultSetting;
 import cn.reghao.devops.mgr.util.PageSort;
 import cn.reghao.devops.mgr.builder.model.constant.EnvType;
 import cn.reghao.devops.mgr.machine.model.po.MachineHost;
-import cn.reghao.devops.mgr.machine.model.vo.MachineHostVO;
+import cn.reghao.devops.mgr.machine.model.vo.MachineDetail;
+import cn.reghao.jutil.jdk.result.Result;
+import cn.reghao.jutil.web.WebResult;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
+import org.springframework.http.MediaType;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 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 org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.*;
 
@@ -30,11 +31,13 @@ import java.util.*;
 @Api(tags = "机器节点页面")
 @Controller
 @RequestMapping("/machine/host")
-public class MachineHostPageController {
+public class MachineController {
     private final MachineQuery machineQuery;
+    private final MachineService machineService;
 
-    public MachineHostPageController(MachineQuery machineQuery) {
+    public MachineController(MachineQuery machineQuery, MachineService machineService) {
         this.machineQuery = machineQuery;
+        this.machineService = machineService;
     }
 
     @ApiOperation(value = "机器节点页面", notes = "N")
@@ -46,13 +49,35 @@ public class MachineHostPageController {
         }
 
         PageRequest pageRequest = PageSort.pageRequest();
-        Page<MachineHostVO> page = machineQuery.getMachineHostByPage(env, pageRequest);
+        Page<MachineDetail> page = machineQuery.getMachineHostByPage(env, pageRequest);
         model.addAttribute("env", env);
         model.addAttribute("page", page);
         model.addAttribute("list", page.getContent());
         return "/devops/machine/host/index";
     }
 
+    @ApiOperation(value = "设置机器为弃用状态", notes = "N")
+    @PreAuthorize("hasRole('ROLE_ADMIN')")
+    @PostMapping(value = "/deprecate/{machineId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public String deleteAll(@PathVariable("machineId") String machineId) {
+        Result result = machineService.setMachinesDeprecate(List.of(machineId));
+        return WebResult.result(result);
+    }
+
+    @ApiOperation(value = "删除机器", notes = "N")
+    @PreAuthorize("hasRole('ROLE_ADMIN')")
+    @DeleteMapping(value = "/{machineId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public String machine(@PathVariable("machineId") String machineId) {
+        if (machineQuery.isAgentOnline(machineId)) {
+            return WebResult.failWithMsg("机器处于在线状态, 不能删除");
+        }
+
+        Result result = machineService.deleteMachine(machineId);
+        return WebResult.result(result);
+    }
+
     @ApiOperation(value = "使用某机器的应用列表页面", notes = "N")
     @PreAuthorize("hasRole('ROLE_ADMIN')")
     @GetMapping("/app/{machineId}")
@@ -78,4 +103,13 @@ public class MachineHostPageController {
         model.addAttribute("env", env);
         return "/devops/machine/host/env";
     }
+
+    @ApiOperation(value = "设置机器环境", notes = "N")
+    @PreAuthorize("hasRole('ROLE_ADMIN')")
+    @PostMapping(value = "/env/{machineId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public String editExtraMachineInfo(@PathVariable("machineId") String machineId, @RequestParam("env") String env) {
+        machineService.setMachineEnv(machineId, env);
+        return WebResult.success();
+    }
 }

+ 0 - 62
mgr/src/main/java/cn/reghao/devops/mgr/machine/controller/MachineHostController.java

@@ -1,62 +0,0 @@
-package cn.reghao.devops.mgr.machine.controller;
-
-import cn.reghao.devops.mgr.machine.db.query.MachineQuery;
-import cn.reghao.devops.mgr.machine.service.MachineService;
-import cn.reghao.jutil.jdk.result.Result;
-import cn.reghao.jutil.jdk.result.WebResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2019-08-30 18:49:15
- */
-@Slf4j
-@Api(tags = "机器接口")
-@RestController
-@RequestMapping("/api/machine/host")
-public class MachineHostController {
-    private final MachineService machineService;
-    private final MachineQuery machineQuery;
-
-    public MachineHostController(MachineService machineService, MachineQuery machineQuery) {
-        this.machineService = machineService;
-        this.machineQuery = machineQuery;
-    }
-
-    @ApiOperation(value = "设置机器环境", notes = "N")
-    @PreAuthorize("hasRole('ROLE_ADMIN')")
-    @PostMapping(value = "/env/{machineId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<String> editExtraMachineInfo(@PathVariable("machineId") String machineId,
-                                                       @RequestParam("env") String env) {
-        machineService.setMachineEnv(machineId, env);
-        return ResponseEntity.ok().body(WebResult.success());
-    }
-
-    @ApiOperation(value = "删除机器", notes = "N")
-    @PreAuthorize("hasRole('ROLE_ADMIN')")
-    @DeleteMapping(value = "/{machineId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String machine(@PathVariable("machineId") String machineId) {
-        if (machineQuery.isAgentOnline(machineId)) {
-            return WebResult.failWithMsg("机器处于在线状态, 不能删除");
-        }
-
-        Result result = machineService.deleteMachine(machineId);
-        return WebResult.result(result);
-    }
-
-    @ApiOperation(value = "设置机器为弃用状态", notes = "N")
-    @PreAuthorize("hasRole('ROLE_ADMIN')")
-    @PostMapping(value = "/deprecate/{machineId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String deleteAll(@PathVariable("machineId") String machineId) {
-        Result result = machineService.setMachinesDeprecate(List.of(machineId));
-        return WebResult.result(result);
-    }
-}

+ 2 - 4
mgr/src/main/java/cn/reghao/devops/mgr/machine/db/query/MachineQuery.java

@@ -3,8 +3,7 @@ package cn.reghao.devops.mgr.machine.db.query;
 import cn.reghao.devops.common.util.KeyValue;
 import cn.reghao.devops.mgr.machine.model.po.MachineHost;
 import cn.reghao.devops.mgr.machine.model.po.MachineInfo;
-import cn.reghao.devops.mgr.machine.model.vo.MachineHostVO;
-import cn.reghao.devops.mgr.machine.model.vo.MachineSshAuth;
+import cn.reghao.devops.mgr.machine.model.vo.MachineDetail;
 import cn.reghao.devops.mgr.machine.model.vo.MachineStat;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
@@ -16,11 +15,10 @@ import java.util.List;
  * @date 2024-08-04 19:57:45
  */
 public interface MachineQuery {
-    Page<MachineHostVO> getMachineHostByPage(String env, Pageable pageable);
+    Page<MachineDetail> getMachineHostByPage(String env, Pageable pageable);
     List<KeyValue> getMachineApps(String machineId);
     List<MachineStat> getMachineStats();
     MachineHost getMachineHost(String machineId);
-    MachineSshAuth getMachineSshAuth(String machineId);
     MachineInfo getMachineInfo(String machineId);
     List<MachineInfo> getMachineInfos(List<String> machineIds);
     List<MachineInfo> getMachineInfos(int stat);

+ 3 - 18
mgr/src/main/java/cn/reghao/devops/mgr/machine/db/query/impl/MachineQueryImpl.java

@@ -8,10 +8,7 @@ import cn.reghao.devops.mgr.machine.db.repository.MachineHostRepository;
 import cn.reghao.devops.mgr.machine.db.repository.MachineInfoRepository;
 import cn.reghao.devops.mgr.machine.model.po.MachineHost;
 import cn.reghao.devops.mgr.machine.model.po.MachineInfo;
-import cn.reghao.devops.mgr.machine.model.po.NetworkInfo;
-import cn.reghao.devops.mgr.machine.model.po.SshAuth;
-import cn.reghao.devops.mgr.machine.model.vo.MachineHostVO;
-import cn.reghao.devops.mgr.machine.model.vo.MachineSshAuth;
+import cn.reghao.devops.mgr.machine.model.vo.MachineDetail;
 import cn.reghao.devops.mgr.machine.model.vo.MachineStat;
 import cn.reghao.jutil.jdk.converter.DateTimeConverter;
 import org.springframework.data.domain.Page;
@@ -43,7 +40,7 @@ public class MachineQueryImpl implements MachineQuery {
     }
 
     @Override
-    public Page<MachineHostVO> getMachineHostByPage(String env, Pageable pageable) {
+    public Page<MachineDetail> getMachineHostByPage(String env, Pageable pageable) {
         Page<MachineHost> page = machineHostRepository.findByEnv(env, pageable);
         return page.map(machineHost -> {
             int used = deployConfigRepository.countByMachineHost(machineHost);
@@ -51,7 +48,7 @@ public class MachineQueryImpl implements MachineQuery {
             long bootTime = machineInfo.getBootTime();
             String bootTimeStr = DateTimeConverter.format(bootTime*1000);
             String status = getMachineStat(machineInfo);
-            return new MachineHostVO(machineHost, bootTimeStr, status, used);
+            return new MachineDetail(machineHost, bootTimeStr, status, used);
         });
     }
 
@@ -112,18 +109,6 @@ public class MachineQueryImpl implements MachineQuery {
         return machineHostRepository.findByMachineId(machineId);
     }
 
-    @Override
-    public MachineSshAuth getMachineSshAuth(String machineId) {
-        SshAuth sshAuth = machineHostRepository.findByMachineId(machineId).getSshAuth();
-        MachineInfo machineInfo = machineInfoRepository.findByMachineId(machineId);
-        List<String> ipv4List = machineInfo.getNetworkInfos().stream()
-                .map(NetworkInfo::getIpv4).collect(Collectors.toList());
-        List<String> ipv4List1 = machineInfo.getNetworkInfos().stream()
-                .map(NetworkInfo::getPublicIpv4).collect(Collectors.toList());
-        ipv4List.addAll(ipv4List1);
-        return new MachineSshAuth(sshAuth, ipv4List);
-    }
-
     @Override
     public MachineInfo getMachineInfo(String machineId) {
         MachineInfo machineInfo = machineInfoRepository.findByMachineId(machineId);

+ 0 - 13
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/MachineShell.java

@@ -1,13 +0,0 @@
-package cn.reghao.devops.mgr.machine.model;
-
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2020-12-25 17:55:46
- */
-@Data
-public class MachineShell {
-    private int exitStatus;
-    private String result;
-}

+ 0 - 20
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/dto/KeepalivedState.java

@@ -1,20 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.dto;
-
-import lombok.Getter;
-import lombok.Setter;
-
-import javax.validation.constraints.NotBlank;
-
-/**
- * @author reghao
- * @date 2024-01-05 09:16:24
- */
-@Setter
-@Getter
-public class KeepalivedState {
-    @NotBlank
-    private String host;
-    @NotBlank
-    private String state;
-    private String realServer;
-}

+ 0 - 39
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/DiskInfo.java

@@ -1,39 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.po;
-
-import cn.reghao.jutil.jdk.machine.data.detail.DiskDetail;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.Embeddable;
-import java.io.Serializable;
-
-/**
- * @author reghao
- * @date 2024-07-26 09:28:35
- */
-@NoArgsConstructor
-@Data
-@Embeddable
-public class DiskInfo implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String diskPath;
-    private String mountedOn;
-    private String fsType;
-    private Long total;
-    private Long avail;
-    private Long used;
-    private long inodeTotal;
-    private long inodeAvail;
-
-    public DiskInfo(DiskDetail diskDetail) {
-        this.diskPath = diskDetail.getDiskPath();
-        this.mountedOn = diskDetail.getMountedOn();
-        this.fsType = diskDetail.getFsType();
-        this.total = diskDetail.getTotal();
-        this.avail = diskDetail.getAvail();
-        this.used = diskDetail.getUsed();
-        this.inodeTotal = diskDetail.getInodeTotal();
-        this.inodeAvail = diskDetail.getInodeAvail();
-    }
-}

+ 1 - 8
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/MachineHost.java

@@ -6,7 +6,6 @@ import lombok.*;
 
 import javax.persistence.*;
 import javax.validation.constraints.NotNull;
-import java.util.List;
 
 /**
  * @author reghao
@@ -27,18 +26,12 @@ public class MachineHost extends BaseEntity {
     private String machineIpv4;
     @NotNull
     private String env;
-    private SshAuth sshAuth;
 
     // TODO 根据机器所属的地区,机房等维度来分组
     public MachineHost(MachineInfo machineInfo) {
         this.machineInfo = machineInfo;
         this.machineId = machineInfo.getMachineId();
-        List<NetworkInfo> list = machineInfo.getNetworkInfos();
-        if (!list.isEmpty()) {
-            this.machineIpv4 = list.get(0).getIpv4();
-        } else {
-            this.machineIpv4 = "127.0.0.1";
-        }
+        this.machineIpv4 = machineInfo.getMachineIpv4();
         this.env = DefaultSetting.getDefaultEnv();
     }
 }

+ 4 - 23
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/MachineInfo.java

@@ -3,17 +3,15 @@ package cn.reghao.devops.mgr.machine.model.po;
 import cn.reghao.devops.common.msg.constant.NodeStatus;
 import cn.reghao.devops.mgr.util.BaseEntity;
 import cn.reghao.devops.common.msg.event.EvtAgentStart;
+import cn.reghao.devops.mgr.util.DefaultSetting;
 import cn.reghao.jutil.jdk.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.*;
 import javax.validation.constraints.NotNull;
 import java.util.List;
-import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -43,18 +41,7 @@ public class MachineInfo extends BaseEntity {
     @NotNull
     private String agentVersion;
     private Integer stat;
-
-    @NotNull
-    @ElementCollection(targetClass = NetworkInfo.class)
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @CollectionTable(name = "devops_machine_info_networks")
-    private List<NetworkInfo> networkInfos;
-
-    @NotNull
-    @ElementCollection(targetClass = DiskInfo.class)
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @CollectionTable(name = "devops_machine_info_disks")
-    private List<DiskInfo> diskInfos;
+    private String env;
 
     public MachineInfo(EvtAgentStart machineDetail) {
         this.machineId = machineDetail.getMachineId();
@@ -66,17 +53,11 @@ public class MachineInfo extends BaseEntity {
         this.bootTime = osDetail.getBootTime();
         this.agentVersion = machineDetail.getAppVersion().getCommitId();
         this.stat = NodeStatus.Online.getCode();
-
         setNetworkInfos(machineDetail.getNetworkDetails());
-        setDiskInfos(machineDetail.getDiskDetails());
+        this.env = DefaultSetting.getDefaultEnv();
     }
 
     private void setNetworkInfos(List<NetworkDetail> networkDetails) {
-        this.networkInfos = networkDetails.stream().map(NetworkInfo::new).collect(Collectors.toList());
-        this.machineIpv4 = networkInfos.isEmpty() ? "127.0.0.1" : networkInfos.get(0).getIpv4();
-    }
-
-    private void setDiskInfos(List<DiskDetail> diskDetails) {
-        this.diskInfos = diskDetails.stream().map(DiskInfo::new).collect(Collectors.toList());
+        this.machineIpv4 = networkDetails.isEmpty() ? "127.0.0.1" : networkDetails.get(0).getIpv4();
     }
 }

+ 0 - 38
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/NetworkInfo.java

@@ -1,38 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.po;
-
-import cn.reghao.jutil.jdk.machine.data.detail.NetworkDetail;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.Embeddable;
-import javax.validation.constraints.NotNull;
-import java.io.Serializable;
-
-/**
- * @author reghao
- * @date 2021-10-15 15:49:43
- */
-@NoArgsConstructor
-@Embeddable
-@Data
-public class NetworkInfo implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    @NotNull
-    private String iface;
-    @NotNull
-    private String mac;
-    @NotNull
-    private String ipv4;
-    @NotNull
-    private String publicIpv4;
-    private String ipv6;
-
-    public NetworkInfo(NetworkDetail networkDetail) {
-        this.iface = networkDetail.getIface();
-        this.mac = networkDetail.getMac();
-        this.ipv4 = networkDetail.getIpv4();
-        this.publicIpv4 = networkDetail.getPubicIpv4();
-        this.ipv6 = networkDetail.getIpv6();
-    }
-}

+ 0 - 31
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/po/SshAuth.java

@@ -1,31 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.po;
-
-import lombok.Getter;
-import lombok.Setter;
-
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Lob;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
-
-/**
- * @author reghao
- * @date 2021-07-07 17:30:12
- */
-@Setter
-@Getter
-@Embeddable
-public class SshAuth {
-    @NotBlank(message = "IPv4 地址为空白字符串")
-    private String ipv4;
-    @NotNull
-    @Positive(message = "SSH 端口必须有效")
-    private Integer port;
-    private String username;
-    private String password;
-    @Lob
-    @Column(columnDefinition="text")
-    private String rsaPrikey;
-}

+ 0 - 33
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/DiskUsage.java

@@ -1,33 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.vo;
-
-import cn.reghao.jutil.jdk.converter.ByteConverter;
-import cn.reghao.jutil.jdk.converter.ByteType;
-import cn.reghao.jutil.jdk.machine.data.detail.DiskDetail;
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2020-10-20 10:51:59
- */
-@Data
-public class DiskUsage {
-    private String mountedOn;
-    private String fsType;
-    private String total;
-    private String used;
-    private String avail;
-    private long inodeTotal;
-    private long inodeAvail;
-
-    public DiskUsage(DiskDetail diskDetail) {
-        this.mountedOn = diskDetail.getMountedOn();
-        this.fsType = diskDetail.getFsType();
-        this.inodeTotal = diskDetail.getInodeTotal();
-        this.inodeAvail = diskDetail.getInodeAvail();
-
-        ByteConverter converter = new ByteConverter();
-        this.total = converter.convert(ByteType.Bytes, diskDetail.getTotal());
-        this.used = converter.convertStr(ByteType.Bytes, ByteType.MiB, diskDetail.getUsed());
-        this.avail = converter.convertStr(ByteType.Bytes, ByteType.MiB, diskDetail.getAvail());
-    }
-}

+ 0 - 15
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineAddress.java

@@ -1,15 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.vo;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2021-07-09 17:10:47
- */
-@AllArgsConstructor
-@Data
-public class MachineAddress {
-    private String machineId;
-    private String machineIpv4;
-}

+ 2 - 4
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineHostVO.java → mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineDetail.java

@@ -8,7 +8,7 @@ import lombok.Data;
  * @date 2020-10-19 15:02:59
  */
 @Data
-public class MachineHostVO {
+public class MachineDetail {
     private String machineId;
     private String machineIpv4;
     private String bootTime;
@@ -17,11 +17,9 @@ public class MachineHostVO {
     private String osVersion;
     private String agentVersion;
     private String status;
-    @Deprecated
-    private String lastCheck;
     private int used;
 
-    public MachineHostVO(MachineHost machineHost, String bootTime, String status, int used) {
+    public MachineDetail(MachineHost machineHost, String bootTime, String status, int used) {
         this.machineId = machineHost.getMachineId();
         this.machineIpv4 = machineHost.getMachineIpv4();
         this.bootTime = bootTime;

+ 0 - 49
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineInfoVO.java

@@ -1,49 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.vo;
-
-import cn.reghao.devops.mgr.machine.model.po.DiskInfo;
-import cn.reghao.devops.mgr.machine.model.po.MachineInfo;
-import cn.reghao.devops.mgr.machine.model.po.NetworkInfo;
-import cn.reghao.jutil.jdk.converter.DateTimeConverter;
-import lombok.Data;
-
-import java.util.List;
-
-/**
- * @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<NetworkInfo> networkInfos;
-    private List<DiskInfo> diskInfos;
-
-    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.networkInfos = machineInfo.getNetworkInfos();
-        this.diskInfos = machineInfo.getDiskInfos();
-    }
-}

+ 0 - 18
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MachineSshAuth.java

@@ -1,18 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.vo;
-
-import cn.reghao.devops.mgr.machine.model.po.SshAuth;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2021-10-18 15:06:23
- */
-@AllArgsConstructor
-@Data
-public class MachineSshAuth {
-    private SshAuth sshAuth;
-    private List<String> ipv4List;
-}

+ 0 - 17
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/vo/MemoryUsage.java

@@ -1,17 +0,0 @@
-package cn.reghao.devops.mgr.machine.model.vo;
-
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2020-10-20 10:51:50
- */
-@Data
-public class MemoryUsage {
-    private String total;
-    private String used;
-    private String avail;
-    private String swapTotal;
-    private String swapUsed;
-    private String swapAvail;
-}

+ 0 - 2
mgr/src/main/java/cn/reghao/devops/mgr/machine/service/MachineService.java

@@ -3,7 +3,6 @@ package cn.reghao.devops.mgr.machine.service;
 import cn.reghao.devops.common.msg.constant.NodeStatus;
 import cn.reghao.devops.common.msg.event.EvtAgentHeartbeat;
 import cn.reghao.devops.common.msg.event.EvtAgentStart;
-import cn.reghao.devops.mgr.machine.model.po.SshAuth;
 import cn.reghao.jutil.jdk.result.Result;
 
 import java.util.List;
@@ -16,7 +15,6 @@ public interface MachineService {
     void addOrUpdateMachine(EvtAgentStart evtAgentStart);
     void updateMachine(EvtAgentHeartbeat evtAgentHeartbeat);
     void setMachineEnv(String machineId, String env);
-    void setMachineSshAuth(String machineId, SshAuth sshAuth);
     Result setMachinesDeprecate(List<String> machineIds);
     Result deleteMachine(String machineId);
     void setAgentStatus(String machineId, NodeStatus nodeStatus);

+ 2 - 15
mgr/src/main/java/cn/reghao/devops/mgr/machine/service/impl/MachineServiceImpl.java

@@ -8,7 +8,6 @@ import cn.reghao.devops.mgr.machine.db.repository.MachineHostRepository;
 import cn.reghao.devops.mgr.machine.db.repository.MachineInfoRepository;
 import cn.reghao.devops.mgr.machine.model.po.MachineHost;
 import cn.reghao.devops.mgr.machine.model.po.MachineInfo;
-import cn.reghao.devops.mgr.machine.model.po.SshAuth;
 import cn.reghao.devops.mgr.machine.service.MachineService;
 import cn.reghao.jutil.jdk.machine.data.detail.DiskDetail;
 import cn.reghao.jutil.jdk.machine.data.detail.MemoryDetail;
@@ -89,29 +88,17 @@ public class MachineServiceImpl implements MachineService {
         machineHostRepository.save(machineHost);
     }
 
-    @Override
-    public void setMachineSshAuth(String machineId, SshAuth sshAuth) {
-        // TODO 检测主机可达, 端口可达, 协议正确
-        String ipv4 = sshAuth.getIpv4();
-        int port = sshAuth.getPort();
-
-        MachineHost machineHost = machineQuery.getMachineHost(machineId);
-        machineHost.setSshAuth(sshAuth);
-        machineHostRepository.save(machineHost);
-    }
-
     @Override
     public Result setMachinesDeprecate(List<String> machineIds) {
         List<MachineInfo> list = machineQuery.getMachineInfos(machineIds);
-        // TODO 这里并没有调用 save, 但仍会持久化
-        List<MachineInfo> list1 = list.stream()
+        /*List<MachineInfo> list1 = list.stream()
                 .filter(machineInfo -> !Objects.equals(machineInfo.getStat(), NodeStatus.Online.getCode()))
                 .peek(machineInfo -> machineInfo.setStat(NodeStatus.Deprecated.getCode()))
                 .collect(Collectors.toList());
 
         if (!list1.isEmpty()) {
             machineInfoRepository.saveAll(list1);
-        }
+        }*/
 
         return Result.result(ResultStatus.SUCCESS);
     }

+ 1 - 1
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/SshConnData.java → mgr/src/main/java/cn/reghao/devops/mgr/machine/util/SshConnData.java

@@ -1,4 +1,4 @@
-package cn.reghao.devops.mgr.machine.model;
+package cn.reghao.devops.mgr.machine.util;
 
 import lombok.Data;
 

+ 1 - 1
mgr/src/main/java/cn/reghao/devops/mgr/machine/model/SshConnInfo.java → mgr/src/main/java/cn/reghao/devops/mgr/machine/util/SshConnInfo.java

@@ -1,4 +1,4 @@
-package cn.reghao.devops.mgr.machine.model;
+package cn.reghao.devops.mgr.machine.util;
 
 import com.jcraft.jsch.Channel;
 import com.jcraft.jsch.JSch;

+ 110 - 5
mgr/src/main/java/cn/reghao/devops/mgr/machine/util/WebSsh.java

@@ -1,15 +1,45 @@
 package cn.reghao.devops.mgr.machine.util;
 
+import cn.reghao.jutil.jdk.serializer.JsonConverter;
+import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
+import com.jcraft.jsch.Channel;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.web.socket.TextMessage;
 import org.springframework.web.socket.WebSocketSession;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
 
 /**
  * @author reghao
  * @date 2021-07-07 13:19:42
  */
-public interface WebSsh {
-    void init(WebSocketSession session);
+@Slf4j
+@Service
+public class WebSsh {
+    private static final Map<String, SshConnInfo> sshConnMap = new ConcurrentHashMap<>();
+    private final ExecutorService threadPool = ThreadPoolWrapper.threadPool("webssh-service");
+
+    public void init(WebSocketSession session) {
+        JSch jSch = new JSch();
+        SshConnInfo connInfo = new SshConnInfo();
+        connInfo.setWebSocketSession(session);
+        connInfo.setJSch(jSch);
+        String uuid = String.valueOf(session.getAttributes().get(Keys.USER_UUID));
+        sshConnMap.put(uuid, connInfo);
+    }
+
     /**
      * 处理客户端发送的消息
      *
@@ -17,7 +47,30 @@ public interface WebSsh {
      * @return
      * @date 2021-07-07 下午4:45
      */
-    void handleMessage(String buffer, WebSocketSession session);
+    public void handleMessage(String buffer, WebSocketSession session) {
+        SshConnData sshConnData = JsonConverter.jsonToObject(buffer, SshConnData.class);
+        String uuid = String.valueOf(session.getAttributes().get(Keys.USER_UUID));
+        SshConnInfo sshConnInfo = sshConnMap.get(uuid);
+        if (sshConnData.getOps().equals(Keys.OPS_CONNECT)) {
+            threadPool.submit(() -> {
+                try {
+                    establishSshConn(sshConnInfo, sshConnData, session);
+                } catch (JSchException | IOException e) {
+                    log.error("SSH 连接建立失败 -> {}", e.getMessage());
+                }
+            });
+        } else if (sshConnData.getOps().equals(Keys.OPS_COMMAND)) {
+            String cmd = sshConnData.getCommand();
+            if (cmd == null) {
+                log.error("command 操作的参数为 null");
+                return;
+            }
+            sendToSsh(sshConnInfo.getChannel(), sshConnData.getCommand());
+        } else {
+            log.error("无法处理 {} 操作", sshConnData.getOps());
+        }
+    }
+
     /**
      * 返回消息给客户端
      *
@@ -25,6 +78,58 @@ public interface WebSsh {
      * @return
      * @date 2021-07-07 下午4:45
      */
-    void sendBack(WebSocketSession session, byte[] buffer) throws IOException;
-    void close(WebSocketSession session);
+    public void sendBack(WebSocketSession session, byte[] buffer) throws IOException {
+        session.sendMessage(new TextMessage(buffer));
+    }
+
+    public void close(WebSocketSession session) {
+        String uuid = String.valueOf(session.getAttributes().get(Keys.USER_UUID));
+        SshConnInfo connInfo = sshConnMap.get(uuid);
+        if (connInfo != null) {
+            if (connInfo.getChannel() != null) {
+                connInfo.getChannel().disconnect();
+            }
+            sshConnMap.remove(uuid);
+        }
+    }
+
+    private void establishSshConn(SshConnInfo connInfo, SshConnData connData, WebSocketSession session) throws JSchException, IOException {
+        Properties config = new Properties();
+        config.put("StrictHostKeyChecking", "no");
+
+        Session sshSession = connInfo.getJSch()
+                .getSession(connData.getUsername(), connData.getHost(), connData.getPort());
+        sshSession.setConfig(config);
+        sshSession.setPassword(connData.getPassword());
+        sshSession.connect(30_000);
+        Channel channel = sshSession.openChannel("shell");
+        channel.connect(30_000);
+        connInfo.setChannel(channel);
+        sendToSsh(channel, "\r");
+
+        try (InputStream input = channel.getInputStream()) {
+            byte[] buffer = new byte[1024];
+            int i;
+            while ((i = input.read(buffer)) != -1) {
+                sendBack(session, Arrays.copyOfRange(buffer, 0, i));
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            sshSession.disconnect();
+            channel.disconnect();
+        }
+    }
+
+    private void sendToSsh(Channel channel, String cmd) {
+        if (channel != null && channel.isConnected()) {
+            try {
+                OutputStream out = channel.getOutputStream();
+                out.write(cmd.getBytes(StandardCharsets.UTF_8));
+                out.flush();
+            } catch (IOException e) {
+                log.error("向 SSH 发送数据失败 -> {}", e.getMessage());
+            }
+        }
+    }
 }

+ 0 - 127
mgr/src/main/java/cn/reghao/devops/mgr/machine/util/WebSshImpl.java

@@ -1,127 +0,0 @@
-package cn.reghao.devops.mgr.machine.util;
-
-import cn.reghao.devops.mgr.machine.model.SshConnData;
-import cn.reghao.jutil.jdk.serializer.JsonConverter;
-import cn.reghao.devops.mgr.machine.model.SshConnInfo;
-import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
-import com.jcraft.jsch.Channel;
-import com.jcraft.jsch.JSch;
-import com.jcraft.jsch.JSchException;
-import com.jcraft.jsch.Session;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.web.socket.TextMessage;
-import org.springframework.web.socket.WebSocketSession;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
-
-/**
- * @author reghao
- * @date 2021-07-07 13:19:42
- */
-@Slf4j
-@Service
-public class WebSshImpl implements WebSsh {
-    private static final Map<String, SshConnInfo> sshConnMap = new ConcurrentHashMap<>();
-    private final ExecutorService threadPool = ThreadPoolWrapper.threadPool("webssh-service");
-
-    @Override
-    public void init(WebSocketSession session) {
-        JSch jSch = new JSch();
-        SshConnInfo connInfo = new SshConnInfo();
-        connInfo.setWebSocketSession(session);
-        connInfo.setJSch(jSch);
-        String uuid = String.valueOf(session.getAttributes().get(Keys.USER_UUID));
-        sshConnMap.put(uuid, connInfo);
-    }
-
-    @Override
-    public void sendBack(WebSocketSession session, byte[] buffer) throws IOException {
-        session.sendMessage(new TextMessage(buffer));
-    }
-
-    @Override
-    public void handleMessage(String buffer, WebSocketSession session) {
-        SshConnData sshConnData = JsonConverter.jsonToObject(buffer, SshConnData.class);
-        String uuid = String.valueOf(session.getAttributes().get(Keys.USER_UUID));
-        SshConnInfo sshConnInfo = sshConnMap.get(uuid);
-        if (sshConnData.getOps().equals(Keys.OPS_CONNECT)) {
-            threadPool.submit(() -> {
-                try {
-                    establishSshConn(sshConnInfo, sshConnData, session);
-                } catch (JSchException | IOException e) {
-                    log.error("SSH 连接建立失败 -> {}", e.getMessage());
-                }
-            });
-        } else if (sshConnData.getOps().equals(Keys.OPS_COMMAND)) {
-            String cmd = sshConnData.getCommand();
-            if (cmd == null) {
-                log.error("command 操作的参数为 null");
-                return;
-            }
-            sendToSsh(sshConnInfo.getChannel(), sshConnData.getCommand());
-        } else {
-            log.error("无法处理 {} 操作", sshConnData.getOps());
-        }
-    }
-
-    @Override
-    public void close(WebSocketSession session) {
-        String uuid = String.valueOf(session.getAttributes().get(Keys.USER_UUID));
-        SshConnInfo connInfo = sshConnMap.get(uuid);
-        if (connInfo != null) {
-            if (connInfo.getChannel() != null) {
-                connInfo.getChannel().disconnect();
-            }
-            sshConnMap.remove(uuid);
-        }
-    }
-
-    private void establishSshConn(SshConnInfo connInfo, SshConnData connData, WebSocketSession session) throws JSchException, IOException {
-        Properties config = new Properties();
-        config.put("StrictHostKeyChecking", "no");
-
-        Session sshSession = connInfo.getJSch()
-                .getSession(connData.getUsername(), connData.getHost(), connData.getPort());
-        sshSession.setConfig(config);
-        sshSession.setPassword(connData.getPassword());
-        sshSession.connect(30_000);
-        Channel channel = sshSession.openChannel("shell");
-        channel.connect(30_000);
-        connInfo.setChannel(channel);
-        sendToSsh(channel, "\r");
-
-        try (InputStream input = channel.getInputStream()) {
-            byte[] buffer = new byte[1024];
-            int i;
-            while ((i = input.read(buffer)) != -1) {
-                sendBack(session, Arrays.copyOfRange(buffer, 0, i));
-            }
-        } catch (IOException e) {
-            e.printStackTrace();
-        } finally {
-            sshSession.disconnect();
-            channel.disconnect();
-        }
-    }
-
-    private void sendToSsh(Channel channel, String cmd) {
-        if (channel != null && channel.isConnected()) {
-            try {
-                OutputStream out = channel.getOutputStream();
-                out.write(cmd.getBytes(StandardCharsets.UTF_8));
-                out.flush();
-            } catch (IOException e) {
-                log.error("向 SSH 发送数据失败 -> {}", e.getMessage());
-            }
-        }
-    }
-}

+ 1 - 1
mgr/src/main/resources/templates/devops/machine/host/env.html

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

+ 2 - 2
mgr/src/main/resources/templates/devops/machine/host/index.html

@@ -59,9 +59,9 @@
                     </td>
                     <td>
                         <a class="ajax-post" th:attr="data-msg='确定要弃用 '+ ${item.machineIpv4} + ' 机器?'"
-                           th:href="@{'/api/machine/host/deprecate/' + ${item.machineId}}">弃用</a>
+                           th:href="@{'/machine/host/deprecate/' + ${item.machineId}}">弃用</a>
                         <a class="ajax-delete" th:attr="data-msg='确定要删除 '+ ${item.machineIpv4} + ' 机器?'"
-                           th:href="@{'/api/machine/host/' + ${item.machineId}}">删除</a>
+                           th:href="@{'/machine/host/' + ${item.machineId}}">删除</a>
                     </td>
                 </tr>
                 </tbody>

+ 132 - 1
mgr/src/test/java/cn/reghao/devops/mgr/devops/DockerTest.java

@@ -8,19 +8,22 @@ import cn.reghao.devops.common.docker.model.Config;
 import cn.reghao.devops.common.docker.model.Volumes;
 import cn.reghao.jutil.jdk.converter.IpAddressConverter;
 import cn.reghao.jutil.jdk.serializer.JsonConverter;
+import cn.reghao.jutil.jdk.shell.ShellExecutor;
+import cn.reghao.jutil.jdk.shell.ShellResult;
 import com.github.dockerjava.api.command.InspectContainerResponse;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
+import lombok.NoArgsConstructor;
 import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 import org.junit.Test;
 import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
 import oshi.SystemInfo;
 import oshi.software.os.InternetProtocolStats;
 import oshi.software.os.OperatingSystem;
 
 import java.util.*;
-import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
@@ -83,8 +86,11 @@ public class DockerTest {
         setLogLevel();
 
         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();
@@ -97,8 +103,11 @@ public class DockerTest {
                 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();
     }
 
     @Test
@@ -175,6 +184,14 @@ public class DockerTest {
         }
     }
 
+    @AllArgsConstructor
+    @Getter
+    static class DockerProcess {
+        private int pid;
+        private String containerId;
+        private String appId;
+    }
+
     @AllArgsConstructor
     @Getter
     static class SysProcess {
@@ -182,4 +199,118 @@ public class DockerTest {
         private String name;
         private int ppid;
     }
+
+    @Test
+    public void dockerConfigTest() {
+        Config config = new Config();
+
+        Volumes volumes = new Volumes();
+        volumes.getMap().put("/app1", "/app1");
+        volumes.getMap().put("/app2", "/app2");
+        config.setVolumes(volumes);
+
+        System.out.println(JsonConverter.objectToJson(config));
+    }
+
+    @Test
+    public void linuxPackageTest() {
+        ShellExecutor shell = new ShellExecutor();
+        String versionCmd = "/usr/bin/pacman -Q";
+
+        List<String> pkgList = new ArrayList<>();
+        ShellResult shellResult = shell.exec(versionCmd.split("\\s+"));
+        if (shellResult.getExitCode() == 0) {
+            for (String line : shellResult.getResult().split(System.lineSeparator())) {
+                String[] arr = line.split("\\s+");
+                pkgList.add(arr[0]);
+            }
+        }
+
+        Map<String, LinuxPkg> linuxPkgMap = new HashMap<>();
+        for (int i = 0; i < pkgList.size(); i++) {
+            String pkg = pkgList.get(i);
+            versionCmd = "/usr/bin/pacman -Qi " + pkg;
+            shellResult = shell.exec(versionCmd.split("\\s+"));
+
+            Map<String, String> map = new HashMap<>();
+            if (shellResult.getExitCode() == 0) {
+                for (String line : shellResult.getResult().split(System.lineSeparator())) {
+                    if (line.startsWith("Optional Deps")) {
+                        continue;
+                    }
+
+                    String[] arr = line.split(": ");
+                    try {
+                        map.put(StringUtils.trimAllWhitespace(arr[0]), arr[1]);
+                    } catch (Exception e) {
+                        //e.printStackTrace();
+                    }
+                }
+            }
+
+            int id = linuxPkgMap.size()+1;
+            String name = map.get("Name");
+            LinuxPkg linuxPkg = linuxPkgMap.computeIfAbsent(name, v -> new LinuxPkg(id, name));
+            String dependsOn = map.get("DependsOn");
+            if (!dependsOn.equals("None")) {
+                for (String line : dependsOn.split(" ")) {
+                    String pkgName = StringUtils.trimAllWhitespace(line);
+                    if (!pkgName.isBlank()) {
+                        for (String key : pkgList) {
+                            if (pkgName.startsWith(key)) {
+                                int id1 = linuxPkgMap.size()+1;
+                                LinuxPkg linuxPkg1 = linuxPkgMap.computeIfAbsent(key, v -> new LinuxPkg(id1, key));
+                            }
+                        }
+                    }
+                }
+            }
+
+            String requiredBy = map.get("RequiredBy");
+            if (!requiredBy.equals("None")) {
+                for (String line : requiredBy.split(" ")) {
+                    String pkgName = StringUtils.trimAllWhitespace(line);
+                    if (!pkgName.isBlank()) {
+                        for (String key : pkgList) {
+                            int id1 = linuxPkgMap.size()+1;
+                            if (pkgName.equals(key)) {
+                                LinuxPkg linuxPkg1 = linuxPkgMap.computeIfAbsent(key, v -> new LinuxPkg(id1, key));
+                                linuxPkg.getChildren().add(key);
+                            } else if (pkgName.startsWith(key)) {
+                                LinuxPkg linuxPkg1 = linuxPkgMap.computeIfAbsent(key, v -> new LinuxPkg(id1, key));
+                                linuxPkg.getChildren().add(key);
+                            }
+                        }
+                    }
+                }
+            }
+
+            System.out.printf("%s: %s\n", i, pkg);
+        }
+
+        linuxPkgMap.forEach((name, value) -> {
+            for (String child : value.getChildren()) {
+                linuxPkgMap.get(child).setPid(value.getId());
+            }
+        });
+
+        Map<Integer, List<LinuxPkg>> groupMap = linuxPkgMap.values().stream()
+                .collect(Collectors.groupingBy(LinuxPkg::getPid));
+        System.out.println();
+    }
+
+    @NoArgsConstructor
+    @Setter
+    @Getter
+    static class LinuxPkg {
+        private int id;
+        private int pid;
+        private String name;
+        private Set<String> children = new HashSet<>();
+
+        public LinuxPkg(int id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+    }
 }