1
2
3
4
5 package oshi.hardware.platform.windows;
6
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Map.Entry;
14 import java.util.Objects;
15 import java.util.Set;
16 import java.util.regex.Matcher;
17 import java.util.regex.Pattern;
18
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import com.sun.jna.platform.win32.VersionHelpers;
23 import com.sun.jna.platform.win32.COM.COMException;
24 import com.sun.jna.platform.win32.COM.WbemcliUtil.WmiResult;
25
26 import oshi.driver.windows.wmi.MSFTStorage;
27 import oshi.driver.windows.wmi.MSFTStorage.PhysicalDiskProperty;
28 import oshi.driver.windows.wmi.MSFTStorage.StoragePoolProperty;
29 import oshi.driver.windows.wmi.MSFTStorage.StoragePoolToPhysicalDiskProperty;
30 import oshi.driver.windows.wmi.MSFTStorage.VirtualDiskProperty;
31 import oshi.hardware.LogicalVolumeGroup;
32 import oshi.hardware.common.AbstractLogicalVolumeGroup;
33 import oshi.util.ParseUtil;
34 import oshi.util.platform.windows.WmiQueryHandler;
35 import oshi.util.platform.windows.WmiUtil;
36 import oshi.util.tuples.Pair;
37
38 final class WindowsLogicalVolumeGroup extends AbstractLogicalVolumeGroup {
39
40 private static final Logger LOG = LoggerFactory.getLogger(WindowsLogicalVolumeGroup.class);
41
42 private static final Pattern SP_OBJECT_ID = Pattern.compile(".*ObjectId=.*SP:(\\{.*\\}).*");
43 private static final Pattern PD_OBJECT_ID = Pattern.compile(".*ObjectId=.*PD:(\\{.*\\}).*");
44 private static final Pattern VD_OBJECT_ID = Pattern.compile(".*ObjectId=.*VD:(\\{.*\\})(\\{.*\\}).*");
45
46 private static final boolean IS_WINDOWS8_OR_GREATER = VersionHelpers.IsWindows8OrGreater();
47
48 WindowsLogicalVolumeGroup(String name, Map<String, Set<String>> lvMap, Set<String> pvSet) {
49 super(name, lvMap, pvSet);
50 }
51
52 static List<LogicalVolumeGroup> getLogicalVolumeGroups() {
53
54 if (!IS_WINDOWS8_OR_GREATER) {
55 return Collections.emptyList();
56 }
57 WmiQueryHandler h = Objects.requireNonNull(WmiQueryHandler.createInstance());
58 boolean comInit = false;
59 try {
60 comInit = h.initCOM();
61
62 WmiResult<StoragePoolProperty> sp = MSFTStorage.queryStoragePools(h);
63 int count = sp.getResultCount();
64 if (count == 0) {
65 return Collections.emptyList();
66 }
67
68
69
70 Map<String, String> vdMap = new HashMap<>();
71 WmiResult<VirtualDiskProperty> vds = MSFTStorage.queryVirtualDisks(h);
72 count = vds.getResultCount();
73 for (int i = 0; i < count; i++) {
74 String vdObjectId = WmiUtil.getString(vds, VirtualDiskProperty.OBJECTID, i);
75 Matcher m = VD_OBJECT_ID.matcher(vdObjectId);
76 if (m.matches()) {
77 vdObjectId = m.group(2) + " " + m.group(1);
78 }
79
80 vdMap.put(vdObjectId, WmiUtil.getString(vds, VirtualDiskProperty.FRIENDLYNAME, i));
81 }
82
83
84 Map<String, Pair<String, String>> pdMap = new HashMap<>();
85 WmiResult<PhysicalDiskProperty> pds = MSFTStorage.queryPhysicalDisks(h);
86 count = pds.getResultCount();
87 for (int i = 0; i < count; i++) {
88 String pdObjectId = WmiUtil.getString(pds, PhysicalDiskProperty.OBJECTID, i);
89 Matcher m = PD_OBJECT_ID.matcher(pdObjectId);
90 if (m.matches()) {
91 pdObjectId = m.group(1);
92 }
93
94 pdMap.put(pdObjectId, new Pair<>(WmiUtil.getString(pds, PhysicalDiskProperty.FRIENDLYNAME, i),
95 WmiUtil.getString(pds, PhysicalDiskProperty.PHYSICALLOCATION, i)));
96 }
97
98
99 Map<String, String> sppdMap = new HashMap<>();
100 WmiResult<StoragePoolToPhysicalDiskProperty> sppd = MSFTStorage.queryStoragePoolPhysicalDisks(h);
101 count = sppd.getResultCount();
102 for (int i = 0; i < count; i++) {
103
104 String spObjectId = WmiUtil.getRefString(sppd, StoragePoolToPhysicalDiskProperty.STORAGEPOOL, i);
105 Matcher m = SP_OBJECT_ID.matcher(spObjectId);
106 if (m.matches()) {
107 spObjectId = m.group(1);
108 }
109 String pdObjectId = WmiUtil.getRefString(sppd, StoragePoolToPhysicalDiskProperty.PHYSICALDISK, i);
110 m = PD_OBJECT_ID.matcher(pdObjectId);
111 if (m.matches()) {
112 pdObjectId = m.group(1);
113 }
114 sppdMap.put(spObjectId + " " + pdObjectId, pdObjectId);
115 }
116
117
118 List<LogicalVolumeGroup> lvgList = new ArrayList<>();
119 count = sp.getResultCount();
120 for (int i = 0; i < count; i++) {
121
122 String name = WmiUtil.getString(sp, StoragePoolProperty.FRIENDLYNAME, i);
123
124 String spObjectId = WmiUtil.getString(sp, StoragePoolProperty.OBJECTID, i);
125 Matcher m = SP_OBJECT_ID.matcher(spObjectId);
126 if (m.matches()) {
127 spObjectId = m.group(1);
128 }
129
130 Set<String> physicalVolumeSet = new HashSet<>();
131 for (Entry<String, String> entry : sppdMap.entrySet()) {
132 if (entry.getKey().contains(spObjectId)) {
133 String pdObjectId = entry.getValue();
134 Pair<String, String> nameLoc = pdMap.get(pdObjectId);
135 if (nameLoc != null) {
136 physicalVolumeSet.add(nameLoc.getA() + " @ " + nameLoc.getB());
137 }
138 }
139 }
140
141 Map<String, Set<String>> logicalVolumeMap = new HashMap<>();
142 for (Entry<String, String> entry : vdMap.entrySet()) {
143 if (entry.getKey().contains(spObjectId)) {
144 String vdObjectId = ParseUtil.whitespaces.split(entry.getKey())[0];
145 logicalVolumeMap.put(entry.getValue() + " " + vdObjectId, physicalVolumeSet);
146 }
147 }
148
149 lvgList.add(new WindowsLogicalVolumeGroup(name, logicalVolumeMap, physicalVolumeSet));
150 }
151
152 return lvgList;
153 } catch (COMException e) {
154 LOG.warn("COM exception: {}", e.getMessage());
155 return Collections.emptyList();
156 } finally {
157 if (comInit) {
158 h.unInitCOM();
159 }
160 }
161 }
162 }