|
8 | 8 | "strconv"
|
9 | 9 |
|
10 | 10 | "github.com/microsoft/wmi/pkg/base/query"
|
11 |
| - cim "github.com/microsoft/wmi/pkg/wmiinstance" |
12 | 11 | "github.com/microsoft/wmi/server2019/root/microsoft/windows/storage"
|
13 | 12 | )
|
14 | 13 |
|
@@ -103,242 +102,136 @@ func NewISCSITargetPortal(targetPortalAddress string,
|
103 | 102 | return QueryISCSITargetPortal(targetPortalAddress, targetPortalPortNumber, nil)
|
104 | 103 | }
|
105 | 104 |
|
106 |
| -var ( |
107 |
| - // Indexes iSCSI targets by their Object ID specified in node address |
108 |
| - mappingISCSITargetIndexer = mappingObjectRefIndexer("iSCSITarget", "MSFT_iSCSITarget", "NodeAddress") |
109 |
| - // Indexes iSCSI target portals by their Object ID specified in portal address |
110 |
| - mappingISCSITargetPortalIndexer = mappingObjectRefIndexer("iSCSITargetPortal", "MSFT_iSCSITargetPortal", "TargetPortalAddress") |
111 |
| - // Indexes iSCSI connections by their Object ID specified in connection identifier |
112 |
| - mappingISCSIConnectionIndexer = mappingObjectRefIndexer("iSCSIConnection", "MSFT_iSCSIConnection", "ConnectionIdentifier") |
113 |
| - // Indexes iSCSI sessions by their Object ID specified in session identifier |
114 |
| - mappingISCSISessionIndexer = mappingObjectRefIndexer("iSCSISession", "MSFT_iSCSISession", "SessionIdentifier") |
115 |
| - |
116 |
| - // Indexes iSCSI targets by their node address |
117 |
| - iscsiTargetIndexer = stringPropertyIndexer("NodeAddress") |
118 |
| - // Indexes iSCSI targets by their target portal address |
119 |
| - iscsiTargetPortalIndexer = stringPropertyIndexer("TargetPortalAddress") |
120 |
| - // Indexes iSCSI connections by their connection identifier |
121 |
| - iscsiConnectionIndexer = stringPropertyIndexer("ConnectionIdentifier") |
122 |
| - // Indexes iSCSI sessions by their session identifier |
123 |
| - iscsiSessionIndexer = stringPropertyIndexer("SessionIdentifier") |
124 |
| -) |
125 |
| - |
126 |
| -// ListISCSITargetToISCSITargetPortalMapping builds a mapping between iSCSI target and iSCSI target portal with iSCSI target as the key. |
127 |
| -// |
128 |
| -// The equivalent WMI query is: |
129 |
| -// |
130 |
| -// SELECT [selectors] FROM MSFT_iSCSITargetToiSCSITargetPortal |
131 |
| -// |
132 |
| -// iSCSITarget | iSCSITargetPortal |
133 |
| -// ----------- | ----------------- |
134 |
| -// MSFT_iSCSITarget (NodeAddress = "iqn.1991-05.com.microsoft:win-8e2evaq9q...) | MSFT_iSCSITargetPortal (TargetPortalAdd... |
135 |
| -// |
136 |
| -// Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsitargettoiscsitargetportal |
137 |
| -// for the WMI class definition. |
138 |
| -func ListISCSITargetToISCSITargetPortalMapping() (map[string]string, error) { |
139 |
| - return ListWMIInstanceMappings(WMINamespaceStorage, "MSFT_iSCSITargetToiSCSITargetPortal", nil, mappingISCSITargetIndexer, mappingISCSITargetPortalIndexer) |
140 |
| -} |
141 |
| - |
142 |
| -// ListISCSIConnectionToISCSITargetMapping builds a mapping between iSCSI connection and iSCSI target with iSCSI connection as the key. |
143 |
| -// |
144 |
| -// The equivalent WMI query is: |
145 |
| -// |
146 |
| -// SELECT [selectors] FROM MSFT_iSCSITargetToiSCSIConnection |
147 |
| -// |
148 |
| -// iSCSIConnection | iSCSITarget |
149 |
| -// --------------- | ----------- |
150 |
| -// MSFT_iSCSIConnection (ConnectionIdentifier = "ffffac0cacbff010-15") | MSFT_iSCSITarget (NodeAddress = "iqn.1991-05.com... |
151 |
| -// |
152 |
| -// Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsitargettoiscsitargetportal |
153 |
| -// for the WMI class definition. |
154 |
| -func ListISCSIConnectionToISCSITargetMapping() (map[string]string, error) { |
155 |
| - return ListWMIInstanceMappings(WMINamespaceStorage, "MSFT_iSCSITargetToiSCSIConnection", nil, mappingISCSIConnectionIndexer, mappingISCSITargetIndexer) |
156 |
| -} |
157 |
| - |
158 |
| -// ListISCSISessionToISCSITargetMapping builds a mapping between iSCSI session and iSCSI target with iSCSI session as the key. |
159 |
| -// |
160 |
| -// The equivalent WMI query is: |
161 |
| -// |
162 |
| -// SELECT [selectors] FROM MSFT_iSCSITargetToiSCSISession |
163 |
| -// |
164 |
| -// iSCSISession | iSCSITarget |
165 |
| -// ------------ | ----------- |
166 |
| -// MSFT_iSCSISession (SessionIdentifier = "ffffac0cacbff010-4000013700000016") | MSFT_iSCSITarget (NodeAddress = "iqn.199... |
167 |
| -// |
168 |
| -// Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsitargettoiscsisession |
169 |
| -// for the WMI class definition. |
170 |
| -func ListISCSISessionToISCSITargetMapping() (map[string]string, error) { |
171 |
| - return ListWMIInstanceMappings(WMINamespaceStorage, "MSFT_iSCSITargetToiSCSISession", nil, mappingISCSISessionIndexer, mappingISCSITargetIndexer) |
172 |
| -} |
173 |
| - |
174 |
| -// ListDiskToISCSIConnectionMapping builds a mapping between disk and iSCSI connection with disk Object ID as the key. |
175 |
| -// |
176 |
| -// The equivalent WMI query is: |
177 |
| -// |
178 |
| -// SELECT [selectors] FROM MSFT_iSCSIConnectionToDisk |
179 |
| -// |
180 |
| -// Disk | iSCSIConnection |
181 |
| -// ---- | --------------- |
182 |
| -// MSFT_Disk (ObjectId = "{1}\\WIN-8E2EVAQ9QSB\root/Microsoft/Win...) | MSFT_iSCSIConnection (ConnectionIdentifier = "fff... |
183 |
| -// |
184 |
| -// Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsiconnectiontodisk |
185 |
| -// for the WMI class definition. |
186 |
| -func ListDiskToISCSIConnectionMapping() (map[string]string, error) { |
187 |
| - return ListWMIInstanceMappings(WMINamespaceStorage, "MSFT_iSCSIConnectionToDisk", nil, mappingObjectRefIndexer("Disk", "MSFT_Disk", "ObjectId"), mappingISCSIConnectionIndexer) |
188 |
| -} |
189 |
| - |
190 |
| -// ListISCSITargetsByTargetPortalWithFilters retrieves all iSCSI targets from the specified iSCSI target portal and conditions by query filters. |
191 |
| -// |
192 |
| -// It lists all the iSCSI targets via the following WMI query |
| 105 | +// ListISCSITargetsByTargetPortal retrieves all iSCSI targets from the specified iSCSI target portal |
| 106 | +// using MSFT_iSCSITargetToiSCSITargetPortal association. |
193 | 107 | //
|
194 |
| -// SELECT [selectors] FROM MSFT_iSCSITarget |
| 108 | +// WMI association MSFT_iSCSITargetToiSCSITargetPortal: |
195 | 109 | //
|
196 |
| -// Then find all iSCSITarget objects from MSFT_iSCSITargetToiSCSITargetPortal mapping. |
| 110 | +// iSCSITarget | iSCSITargetPortal |
| 111 | +// ----------- | ----------------- |
| 112 | +// MSFT_iSCSITarget (NodeAddress = "iqn.1991-05.com.microsoft:win-8e2evaq9q...) | MSFT_iSCSITargetPortal (TargetPortalAdd... |
197 | 113 | //
|
198 | 114 | // Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsitarget
|
199 | 115 | // for the WMI class definition.
|
200 |
| -func ListISCSITargetsByTargetPortalWithFilters(targetSelectorList []string, portals []*storage.MSFT_iSCSITargetPortal, filters ...*query.WmiQueryFilter) ([]*storage.MSFT_iSCSITarget, error) { |
201 |
| - targetQuery := query.NewWmiQueryWithSelectList("MSFT_iSCSITarget", targetSelectorList) |
202 |
| - targetQuery.Filters = append(targetQuery.Filters, filters...) |
203 |
| - instances, err := QueryInstances(WMINamespaceStorage, targetQuery) |
204 |
| - if err != nil { |
205 |
| - return nil, err |
206 |
| - } |
207 |
| - |
208 |
| - var portalInstances []*cim.WmiInstance |
209 |
| - for _, portal := range portals { |
210 |
| - portalInstances = append(portalInstances, portal.WmiInstance) |
211 |
| - } |
212 |
| - |
213 |
| - targetToTargetPortalMapping, err := ListISCSITargetToISCSITargetPortalMapping() |
214 |
| - if err != nil { |
215 |
| - return nil, err |
216 |
| - } |
217 |
| - |
218 |
| - targetInstances, err := FindInstancesByMapping(instances, iscsiTargetIndexer, portalInstances, iscsiTargetPortalIndexer, targetToTargetPortalMapping) |
219 |
| - if err != nil { |
220 |
| - return nil, err |
221 |
| - } |
222 |
| - |
| 116 | +func ListISCSITargetsByTargetPortal(portals []*storage.MSFT_iSCSITargetPortal) ([]*storage.MSFT_iSCSITarget, error) { |
223 | 117 | var targets []*storage.MSFT_iSCSITarget
|
224 |
| - for _, instance := range targetInstances { |
225 |
| - target, err := storage.NewMSFT_iSCSITargetEx1(instance) |
| 118 | + for _, portal := range portals { |
| 119 | + collection, err := portal.GetAssociated("MSFT_iSCSITargetToiSCSITargetPortal", "MSFT_iSCSITarget", "iSCSITarget", "iSCSITargetPortal") |
226 | 120 | if err != nil {
|
227 |
| - return nil, fmt.Errorf("failed to query iSCSI target %v. %v", instance, err) |
| 121 | + return nil, fmt.Errorf("failed to query associated iSCSITarget for %v. error: %v", portal, err) |
228 | 122 | }
|
229 | 123 |
|
230 |
| - targets = append(targets, target) |
| 124 | + for _, instance := range collection { |
| 125 | + target, err := storage.NewMSFT_iSCSITargetEx1(instance) |
| 126 | + if err != nil { |
| 127 | + return nil, fmt.Errorf("failed to query iSCSI target %v. error: %v", instance, err) |
| 128 | + } |
| 129 | + |
| 130 | + targets = append(targets, target) |
| 131 | + } |
231 | 132 | }
|
232 | 133 |
|
233 | 134 | return targets, nil
|
234 | 135 | }
|
235 | 136 |
|
236 | 137 | // QueryISCSITarget retrieves the iSCSI target from the specified portal address, portal and node address.
|
237 |
| -func QueryISCSITarget(address string, port uint32, nodeAddress string, selectorList []string) (*storage.MSFT_iSCSITarget, error) { |
| 138 | +func QueryISCSITarget(address string, port uint32, nodeAddress string) (*storage.MSFT_iSCSITarget, error) { |
238 | 139 | portal, err := QueryISCSITargetPortal(address, port, nil)
|
239 | 140 | if err != nil {
|
240 | 141 | return nil, err
|
241 | 142 | }
|
242 | 143 |
|
243 |
| - targets, err := ListISCSITargetsByTargetPortalWithFilters(selectorList, []*storage.MSFT_iSCSITargetPortal{portal}, |
244 |
| - query.NewWmiQueryFilter("NodeAddress", nodeAddress, query.Equals)) |
| 144 | + targets, err := ListISCSITargetsByTargetPortal([]*storage.MSFT_iSCSITargetPortal{portal}) |
245 | 145 | if err != nil {
|
246 | 146 | return nil, err
|
247 | 147 | }
|
248 | 148 |
|
249 |
| - return targets[0], nil |
| 149 | + for _, target := range targets { |
| 150 | + targetNodeAddress, err := target.GetProperty("NodeAddress") |
| 151 | + if err != nil { |
| 152 | + return nil, fmt.Errorf("failed to query iSCSI target %v. error: %v", target, err) |
| 153 | + } |
| 154 | + |
| 155 | + if targetNodeAddress == nodeAddress { |
| 156 | + return target, nil |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + return nil, nil |
250 | 161 | }
|
251 | 162 |
|
252 |
| -// QueryISCSISessionByTarget retrieves the iSCSI session from the specified iSCSI target. |
253 |
| -// |
254 |
| -// It lists all the iSCSI sessions via the following WMI query |
| 163 | +// QueryISCSISessionByTarget retrieves the iSCSI session from the specified iSCSI target |
| 164 | +// using MSFT_iSCSITargetToiSCSISession association. |
255 | 165 | //
|
256 |
| -// SELECT [selectors] FROM MSFT_iSCSISession |
| 166 | +// WMI association MSFT_iSCSITargetToiSCSISession: |
257 | 167 | //
|
258 |
| -// Then find all MSFT_iSCSISession objects from MSFT_iSCSITargetToiSCSISession mapping. |
| 168 | +// iSCSISession | iSCSITarget |
| 169 | +// ------------ | ----------- |
| 170 | +// MSFT_iSCSISession (SessionIdentifier = "ffffac0cacbff010-4000013700000016") | MSFT_iSCSITarget (NodeAddress = "iqn.199... |
259 | 171 | //
|
260 | 172 | // Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsisession
|
261 | 173 | // for the WMI class definition.
|
262 |
| -func QueryISCSISessionByTarget(target *storage.MSFT_iSCSITarget, selectorList []string) (*storage.MSFT_iSCSISession, error) { |
263 |
| - sessionQuery := query.NewWmiQueryWithSelectList("MSFT_iSCSISession", selectorList) |
264 |
| - sessionInstances, err := QueryInstances(WMINamespaceStorage, sessionQuery) |
| 174 | +func QueryISCSISessionByTarget(target *storage.MSFT_iSCSITarget) (*storage.MSFT_iSCSISession, error) { |
| 175 | + collection, err := target.GetAssociated("MSFT_iSCSITargetToiSCSISession", "MSFT_iSCSISession", "iSCSISession", "iSCSITarget") |
265 | 176 | if err != nil {
|
266 |
| - return nil, err |
| 177 | + return nil, fmt.Errorf("failed to query associated iSCSISession for %v. error: %v", target, err) |
267 | 178 | }
|
268 | 179 |
|
269 |
| - targetToTargetSessionMapping, err := ListISCSISessionToISCSITargetMapping() |
270 |
| - if err != nil { |
271 |
| - return nil, err |
| 180 | + if len(collection) == 0 { |
| 181 | + return nil, nil |
272 | 182 | }
|
273 | 183 |
|
274 |
| - filtered, err := FindInstancesByMapping(sessionInstances, iscsiSessionIndexer, []*cim.WmiInstance{target.WmiInstance}, iscsiTargetIndexer, targetToTargetSessionMapping) |
275 |
| - if err != nil { |
276 |
| - return nil, err |
277 |
| - } |
278 |
| - |
279 |
| - session, err := storage.NewMSFT_iSCSISessionEx1(filtered[0]) |
| 184 | + session, err := storage.NewMSFT_iSCSISessionEx1(collection[0]) |
280 | 185 | return session, err
|
281 | 186 | }
|
282 | 187 |
|
283 |
| -// ListDisksByTarget lists all the disks on the specified iSCSI target. |
| 188 | +// ListDisksByTarget find all disks associated with an iSCSITarget. |
| 189 | +// It finds out the iSCSIConnections from MSFT_iSCSITargetToiSCSIConnection association, |
| 190 | +// then locate MSFT_Disk objects from MSFT_iSCSIConnectionToDisk association. |
284 | 191 | //
|
285 |
| -// It lists all the iSCSI connections via the following WMI query |
| 192 | +// WMI association MSFT_iSCSITargetToiSCSIConnection: |
286 | 193 | //
|
287 |
| -// SELECT [selectors] FROM MSFT_iSCSIConnection |
| 194 | +// iSCSIConnection | iSCSITarget |
| 195 | +// --------------- | ----------- |
| 196 | +// MSFT_iSCSIConnection (ConnectionIdentifier = "ffffac0cacbff010-15") | MSFT_iSCSITarget (NodeAddress = "iqn.1991-05.com... |
288 | 197 | //
|
289 |
| -// Then find all MSFT_iSCSIConnection objects from MSFT_iSCSITargetToiSCSIConnection mapping, |
290 |
| -// locate the MSFT_Disk objects using MSFT_iSCSIConnectionToDisk mapping. |
| 198 | +// WMI association MSFT_iSCSIConnectionToDisk: |
| 199 | +// |
| 200 | +// Disk | iSCSIConnection |
| 201 | +// ---- | --------------- |
| 202 | +// MSFT_Disk (ObjectId = "{1}\\WIN-8E2EVAQ9QSB\root/Microsoft/Win...) | MSFT_iSCSIConnection (ConnectionIdentifier = "fff... |
291 | 203 | //
|
292 | 204 | // Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsiconnection
|
293 | 205 | // for the WMI class definition.
|
294 |
| -func ListDisksByTarget(target *storage.MSFT_iSCSITarget, selectorList []string) ([]*storage.MSFT_Disk, error) { |
| 206 | +func ListDisksByTarget(target *storage.MSFT_iSCSITarget) ([]*storage.MSFT_Disk, error) { |
295 | 207 | // list connections to the given iSCSI target
|
296 |
| - connectionQuery := query.NewWmiQueryWithSelectList("MSFT_iSCSIConnection", selectorList) |
297 |
| - connectionInstances, err := QueryInstances(WMINamespaceStorage, connectionQuery) |
298 |
| - if err != nil { |
299 |
| - return nil, err |
300 |
| - } |
301 |
| - |
302 |
| - connectionToTargetMapping, err := ListISCSIConnectionToISCSITargetMapping() |
303 |
| - if err != nil { |
304 |
| - return nil, err |
305 |
| - } |
306 |
| - |
307 |
| - connectionsToTarget, err := FindInstancesByMapping(connectionInstances, iscsiConnectionIndexer, []*cim.WmiInstance{target.WmiInstance}, iscsiTargetIndexer, connectionToTargetMapping) |
308 |
| - if err != nil { |
309 |
| - return nil, err |
310 |
| - } |
311 |
| - |
312 |
| - disks, err := ListDisks(selectorList) |
| 208 | + collection, err := target.GetAssociated("MSFT_iSCSITargetToiSCSIConnection", "MSFT_iSCSIConnection", "iSCSIConnection", "iSCSITarget") |
313 | 209 | if err != nil {
|
314 |
| - return nil, err |
| 210 | + return nil, fmt.Errorf("failed to query associated iSCSISession for %v. error: %v", target, err) |
315 | 211 | }
|
316 | 212 |
|
317 |
| - var diskInstances []*cim.WmiInstance |
318 |
| - for _, disk := range disks { |
319 |
| - diskInstances = append(diskInstances, disk.WmiInstance) |
| 213 | + if len(collection) == 0 { |
| 214 | + return nil, nil |
320 | 215 | }
|
321 | 216 |
|
322 |
| - diskToConnectionMapping, err := ListDiskToISCSIConnectionMapping() |
323 |
| - if err != nil { |
324 |
| - return nil, err |
325 |
| - } |
326 |
| - |
327 |
| - filtered, err := FindInstancesByMapping(diskInstances, objectIDPropertyIndexer, connectionsToTarget, iscsiConnectionIndexer, diskToConnectionMapping) |
328 |
| - if err != nil { |
329 |
| - return nil, err |
330 |
| - } |
331 |
| - |
332 |
| - var filteredDisks []*storage.MSFT_Disk |
333 |
| - for _, instance := range filtered { |
334 |
| - disk, err := storage.NewMSFT_DiskEx1(instance) |
| 217 | + var result []*storage.MSFT_Disk |
| 218 | + for _, conn := range collection { |
| 219 | + instances, err := conn.GetAssociated("MSFT_iSCSIConnectionToDisk", "MSFT_Disk", "Disk", "iSCSIConnection") |
335 | 220 | if err != nil {
|
336 |
| - return nil, fmt.Errorf("failed to query disk %v. error: %v", disk, err) |
| 221 | + return nil, fmt.Errorf("failed to query associated disk for %v. error: %v", target, err) |
337 | 222 | }
|
338 | 223 |
|
339 |
| - filteredDisks = append(filteredDisks, disk) |
| 224 | + for _, instance := range instances { |
| 225 | + disk, err := storage.NewMSFT_DiskEx1(instance) |
| 226 | + if err != nil { |
| 227 | + return nil, fmt.Errorf("failed to query associated disk %v. error: %v", instance, err) |
| 228 | + } |
| 229 | + |
| 230 | + result = append(result, disk) |
| 231 | + } |
340 | 232 | }
|
341 |
| - return filteredDisks, err |
| 233 | + |
| 234 | + return result, err |
342 | 235 | }
|
343 | 236 |
|
344 | 237 | // ConnectISCSITarget establishes a connection to an iSCSI target with optional CHAP authentication credential.
|
|
0 commit comments