Skip to content

Commit 161c412

Browse files
committed
Use associator to find iSCSI WMI instances
1 parent 028e9dc commit 161c412

File tree

2 files changed

+81
-191
lines changed

2 files changed

+81
-191
lines changed

pkg/cim/iscsi.go

Lines changed: 75 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"strconv"
99

1010
"github.com/microsoft/wmi/pkg/base/query"
11-
cim "github.com/microsoft/wmi/pkg/wmiinstance"
1211
"github.com/microsoft/wmi/server2019/root/microsoft/windows/storage"
1312
)
1413

@@ -103,242 +102,136 @@ func NewISCSITargetPortal(targetPortalAddress string,
103102
return QueryISCSITargetPortal(targetPortalAddress, targetPortalPortNumber, nil)
104103
}
105104

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.
193107
//
194-
// SELECT [selectors] FROM MSFT_iSCSITarget
108+
// WMI association MSFT_iSCSITargetToiSCSITargetPortal:
195109
//
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...
197113
//
198114
// Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsitarget
199115
// 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) {
223117
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")
226120
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)
228122
}
229123

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+
}
231132
}
232133

233134
return targets, nil
234135
}
235136

236137
// 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) {
238139
portal, err := QueryISCSITargetPortal(address, port, nil)
239140
if err != nil {
240141
return nil, err
241142
}
242143

243-
targets, err := ListISCSITargetsByTargetPortalWithFilters(selectorList, []*storage.MSFT_iSCSITargetPortal{portal},
244-
query.NewWmiQueryFilter("NodeAddress", nodeAddress, query.Equals))
144+
targets, err := ListISCSITargetsByTargetPortal([]*storage.MSFT_iSCSITargetPortal{portal})
245145
if err != nil {
246146
return nil, err
247147
}
248148

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
250161
}
251162

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.
255165
//
256-
// SELECT [selectors] FROM MSFT_iSCSISession
166+
// WMI association MSFT_iSCSITargetToiSCSISession:
257167
//
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...
259171
//
260172
// Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsisession
261173
// 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")
265176
if err != nil {
266-
return nil, err
177+
return nil, fmt.Errorf("failed to query associated iSCSISession for %v. error: %v", target, err)
267178
}
268179

269-
targetToTargetSessionMapping, err := ListISCSISessionToISCSITargetMapping()
270-
if err != nil {
271-
return nil, err
180+
if len(collection) == 0 {
181+
return nil, nil
272182
}
273183

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])
280185
return session, err
281186
}
282187

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.
284191
//
285-
// It lists all the iSCSI connections via the following WMI query
192+
// WMI association MSFT_iSCSITargetToiSCSIConnection:
286193
//
287-
// SELECT [selectors] FROM MSFT_iSCSIConnection
194+
// iSCSIConnection | iSCSITarget
195+
// --------------- | -----------
196+
// MSFT_iSCSIConnection (ConnectionIdentifier = "ffffac0cacbff010-15") | MSFT_iSCSITarget (NodeAddress = "iqn.1991-05.com...
288197
//
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...
291203
//
292204
// Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/iscsidisc/msft-iscsiconnection
293205
// 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) {
295207
// 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")
313209
if err != nil {
314-
return nil, err
210+
return nil, fmt.Errorf("failed to query associated iSCSISession for %v. error: %v", target, err)
315211
}
316212

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
320215
}
321216

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")
335220
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)
337222
}
338223

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+
}
340232
}
341-
return filteredDisks, err
233+
234+
return result, err
342235
}
343236

344237
// ConnectISCSITarget establishes a connection to an iSCSI target with optional CHAP authentication credential.

pkg/os/iscsi/api.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (APIImplementor) DiscoverTargetPortal(portal *TargetPortal) ([]string, erro
6060
return nil, err
6161
}
6262

63-
targets, err := cim.ListISCSITargetsByTargetPortalWithFilters(nil, []*storage.MSFT_iSCSITargetPortal{instance})
63+
targets, err := cim.ListISCSITargetsByTargetPortal([]*storage.MSFT_iSCSITargetPortal{instance})
6464
if err != nil {
6565
return nil, err
6666
}
@@ -125,7 +125,7 @@ func (APIImplementor) RemoveTargetPortal(portal *TargetPortal) error {
125125
}
126126

127127
func (APIImplementor) ConnectTarget(portal *TargetPortal, iqn string, authType string, chapUser string, chapSecret string) error {
128-
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn, nil)
128+
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
129129
if err != nil {
130130
return err
131131
}
@@ -151,7 +151,7 @@ func (APIImplementor) ConnectTarget(portal *TargetPortal, iqn string, authType s
151151
}
152152

153153
func (APIImplementor) DisconnectTarget(portal *TargetPortal, iqn string) error {
154-
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn, nil)
154+
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
155155
if err != nil {
156156
return err
157157
}
@@ -167,7 +167,7 @@ func (APIImplementor) DisconnectTarget(portal *TargetPortal, iqn string) error {
167167
}
168168

169169
// get session
170-
session, err := cim.QueryISCSISessionByTarget(target, nil)
170+
session, err := cim.QueryISCSISessionByTarget(target)
171171
if err != nil {
172172
return fmt.Errorf("error query session of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
173173
}
@@ -198,9 +198,7 @@ func (APIImplementor) DisconnectTarget(portal *TargetPortal, iqn string) error {
198198
}
199199

200200
func (APIImplementor) GetTargetDisks(portal *TargetPortal, iqn string) ([]string, error) {
201-
// Converting DiskNumber to string for compatibility with disk api group
202-
// Not using pipeline in order to validate that items are non-empty
203-
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn, nil)
201+
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
204202
if err != nil {
205203
return nil, err
206204
}
@@ -215,8 +213,7 @@ func (APIImplementor) GetTargetDisks(portal *TargetPortal, iqn string) ([]string
215213
return nil, nil
216214
}
217215

218-
disks, err := cim.ListDisksByTarget(target, []string{})
219-
216+
disks, err := cim.ListDisksByTarget(target)
220217
if err != nil {
221218
return nil, fmt.Errorf("error getting target disks on target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
222219
}

0 commit comments

Comments
 (0)