1
2
3
4
5 package oshi.hardware.platform.linux;
6
7 import static oshi.software.os.linux.LinuxOperatingSystem.HAS_UDEV;
8
9 import java.io.File;
10 import java.util.Collections;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.stream.Collectors;
17
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 import com.sun.jna.platform.linux.Udev;
22
23 import oshi.hardware.LogicalVolumeGroup;
24 import oshi.hardware.common.AbstractLogicalVolumeGroup;
25 import oshi.util.ExecutingCommand;
26 import oshi.util.ParseUtil;
27 import oshi.util.Util;
28 import oshi.util.platform.linux.DevPath;
29
30 final class LinuxLogicalVolumeGroup extends AbstractLogicalVolumeGroup {
31
32 private static final Logger LOG = LoggerFactory.getLogger(LinuxLogicalVolumeGroup.class);
33
34 private static final String BLOCK = "block";
35 private static final String DM_UUID = "DM_UUID";
36 private static final String DM_VG_NAME = "DM_VG_NAME";
37 private static final String DM_LV_NAME = "DM_LV_NAME";
38
39 LinuxLogicalVolumeGroup(String name, Map<String, Set<String>> lvMap, Set<String> pvSet) {
40 super(name, lvMap, pvSet);
41 }
42
43 static List<LogicalVolumeGroup> getLogicalVolumeGroups() {
44 if (!HAS_UDEV) {
45 LOG.warn("Logical Volume Group information requires libudev, which is not present.");
46 return Collections.emptyList();
47 }
48 Map<String, Map<String, Set<String>>> logicalVolumesMap = new HashMap<>();
49 Map<String, Set<String>> physicalVolumesMap = new HashMap<>();
50
51
52
53 for (String s : ExecutingCommand.runNative("pvs -o vg_name,pv_name")) {
54 String[] split = ParseUtil.whitespaces.split(s.trim());
55 if (split.length == 2 && split[1].startsWith(DevPath.DEV)) {
56 physicalVolumesMap.computeIfAbsent(split[0], k -> new HashSet<>()).add(split[1]);
57 }
58 }
59
60
61 Udev.UdevContext udev = Udev.INSTANCE.udev_new();
62 try {
63 Udev.UdevEnumerate enumerate = udev.enumerateNew();
64 try {
65 enumerate.addMatchSubsystem(BLOCK);
66 enumerate.scanDevices();
67 for (Udev.UdevListEntry entry = enumerate.getListEntry(); entry != null; entry = entry.getNext()) {
68 String syspath = entry.getName();
69 Udev.UdevDevice device = udev.deviceNewFromSyspath(syspath);
70 if (device != null) {
71 try {
72 String devnode = device.getDevnode();
73 if (devnode != null && devnode.startsWith(DevPath.DM)) {
74 String uuid = device.getPropertyValue(DM_UUID);
75 if (uuid != null && uuid.startsWith("LVM-")) {
76 String vgName = device.getPropertyValue(DM_VG_NAME);
77 String lvName = device.getPropertyValue(DM_LV_NAME);
78 if (!Util.isBlank(vgName) && !Util.isBlank(lvName)) {
79 logicalVolumesMap.computeIfAbsent(vgName, k -> new HashMap<>());
80 Map<String, Set<String>> lvMapForGroup = logicalVolumesMap.get(vgName);
81
82 physicalVolumesMap.computeIfAbsent(vgName, k -> new HashSet<>());
83 Set<String> pvSetForGroup = physicalVolumesMap.get(vgName);
84
85 File slavesDir = new File(syspath + "/slaves");
86 File[] slaves = slavesDir.listFiles();
87 if (slaves != null) {
88 for (File f : slaves) {
89 String pvName = f.getName();
90 lvMapForGroup.computeIfAbsent(lvName, k -> new HashSet<>())
91 .add(DevPath.DEV + pvName);
92
93
94 pvSetForGroup.add(DevPath.DEV + pvName);
95 }
96 }
97 }
98 }
99 }
100 } finally {
101 device.unref();
102 }
103 }
104 }
105 } finally {
106 enumerate.unref();
107 }
108 } finally {
109 udev.unref();
110 }
111 return logicalVolumesMap.entrySet().stream()
112 .map(e -> new LinuxLogicalVolumeGroup(e.getKey(), e.getValue(), physicalVolumesMap.get(e.getKey())))
113 .collect(Collectors.toList());
114 }
115 }