Skip to content

Commit 2e6d7d9

Browse files
committed
Ensure COM threading apartment in iSCSI APIs
1 parent ef50b9d commit 2e6d7d9

File tree

1 file changed

+153
-134
lines changed

1 file changed

+153
-134
lines changed

pkg/os/iscsi/api.go

Lines changed: 153 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -21,190 +21,209 @@ func New() APIImplementor {
2121
}
2222

2323
func (APIImplementor) AddTargetPortal(portal *TargetPortal) error {
24-
existing, err := cim.QueryISCSITargetPortal(portal.Address, portal.Port, nil)
25-
if cim.IgnoreNotFound(err) != nil {
26-
return err
27-
}
24+
return cim.WithCOMThread(func() error {
25+
existing, err := cim.QueryISCSITargetPortal(portal.Address, portal.Port, nil)
26+
if cim.IgnoreNotFound(err) != nil {
27+
return err
28+
}
2829

29-
if existing != nil {
30-
klog.V(2).Infof("target portal at (%s:%d) already exists", portal.Address, portal.Port)
31-
return nil
32-
}
30+
if existing != nil {
31+
klog.V(2).Infof("target portal at (%s:%d) already exists", portal.Address, portal.Port)
32+
return nil
33+
}
3334

34-
_, err = cim.NewISCSITargetPortal(portal.Address, portal.Port, nil, nil, nil, nil)
35-
if err != nil {
36-
return fmt.Errorf("error adding target portal at (%s:%d). err: %v", portal.Address, portal.Port, err)
37-
}
35+
_, err = cim.NewISCSITargetPortal(portal.Address, portal.Port, nil, nil, nil, nil)
36+
if err != nil {
37+
return fmt.Errorf("error adding target portal at (%s:%d). err: %v", portal.Address, portal.Port, err)
38+
}
3839

39-
return nil
40+
return nil
41+
})
4042
}
4143

4244
func (APIImplementor) DiscoverTargetPortal(portal *TargetPortal) ([]string, error) {
43-
targets, err := cim.ListISCSITargetsByTargetPortalAddressAndPort(portal.Address, portal.Port, nil)
44-
if err != nil {
45-
return nil, err
46-
}
47-
4845
var iqns []string
49-
for _, target := range targets {
50-
iqn, err := cim.GetISCSITargetNodeAddress(target)
46+
err := cim.WithCOMThread(func() error {
47+
targets, err := cim.ListISCSITargetsByTargetPortalAddressAndPort(portal.Address, portal.Port, nil)
5148
if err != nil {
52-
return nil, fmt.Errorf("failed parsing node address of target %v to target portal at (%s:%d). err: %w", target, portal.Address, portal.Port, err)
49+
return err
5350
}
5451

55-
iqns = append(iqns, iqn)
56-
}
52+
for _, target := range targets {
53+
iqn, err := cim.GetISCSITargetNodeAddress(target)
54+
if err != nil {
55+
return fmt.Errorf("failed parsing node address of target %v to target portal at (%s:%d). err: %w", target, portal.Address, portal.Port, err)
56+
}
5757

58-
return iqns, nil
58+
iqns = append(iqns, iqn)
59+
}
60+
61+
return nil
62+
})
63+
return iqns, err
5964
}
6065

6166
func (APIImplementor) ListTargetPortals() ([]TargetPortal, error) {
62-
instances, err := cim.ListISCSITargetPortals(cim.ISCSITargetPortalDefaultSelectorList)
63-
if err != nil {
64-
return nil, err
65-
}
66-
6767
var portals []TargetPortal
68-
for _, instance := range instances {
69-
address, port, err := cim.ParseISCSITargetPortal(instance)
68+
err := cim.WithCOMThread(func() error {
69+
instances, err := cim.ListISCSITargetPortals(cim.ISCSITargetPortalDefaultSelectorList)
7070
if err != nil {
71-
return nil, fmt.Errorf("failed parsing target portal %v. err: %w", instance, err)
71+
return err
7272
}
7373

74-
portals = append(portals, TargetPortal{
75-
Address: address,
76-
Port: port,
77-
})
78-
}
74+
for _, instance := range instances {
75+
address, port, err := cim.ParseISCSITargetPortal(instance)
76+
if err != nil {
77+
return fmt.Errorf("failed parsing target portal %v. err: %w", instance, err)
78+
}
7979

80-
return portals, nil
80+
portals = append(portals, TargetPortal{
81+
Address: address,
82+
Port: port,
83+
})
84+
}
85+
86+
return nil
87+
})
88+
return portals, err
8189
}
8290

8391
func (APIImplementor) RemoveTargetPortal(portal *TargetPortal) error {
84-
instance, err := cim.QueryISCSITargetPortal(portal.Address, portal.Port, nil)
85-
if err != nil {
86-
return err
87-
}
92+
return cim.WithCOMThread(func() error {
93+
instance, err := cim.QueryISCSITargetPortal(portal.Address, portal.Port, nil)
94+
if err != nil {
95+
return err
96+
}
8897

89-
result, err := cim.RemoveISCSITargetPortal(instance)
90-
if result != 0 || err != nil {
91-
return fmt.Errorf("error removing target portal at (%s:%d). result: %d, err: %w", portal.Address, portal.Port, result, err)
92-
}
98+
result, err := cim.RemoveISCSITargetPortal(instance)
99+
if result != 0 || err != nil {
100+
return fmt.Errorf("error removing target portal at (%s:%d). result: %d, err: %w", portal.Address, portal.Port, result, err)
101+
}
93102

94-
return nil
103+
return nil
104+
})
95105
}
96106

97107
func (APIImplementor) ConnectTarget(portal *TargetPortal, iqn string, authType string, chapUser string, chapSecret string) error {
98-
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
99-
if err != nil {
100-
return err
101-
}
102-
103-
connected, err := cim.IsISCSITargetConnected(target)
104-
if err != nil {
105-
return err
106-
}
107-
108-
if connected {
109-
klog.V(2).Infof("target %s from target portal at (%s:%d) is connected.", iqn, portal.Address, portal.Port)
110-
return nil
111-
}
108+
return cim.WithCOMThread(func() error {
109+
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
110+
if err != nil {
111+
return err
112+
}
112113

113-
targetAuthType := strings.ToUpper(strings.ReplaceAll(authType, "_", ""))
114+
connected, err := cim.IsISCSITargetConnected(target)
115+
if err != nil {
116+
return err
117+
}
114118

115-
result, err := cim.ConnectISCSITarget(portal.Address, portal.Port, iqn, targetAuthType, &chapUser, &chapSecret)
116-
if err != nil {
117-
return fmt.Errorf("error connecting to target portal. result: %d, err: %w", result, err)
118-
}
119+
if connected {
120+
klog.V(2).Infof("target %s from target portal at (%s:%d) is connected.", iqn, portal.Address, portal.Port)
121+
return nil
122+
}
123+
124+
targetAuthType := strings.ToUpper(strings.ReplaceAll(authType, "_", ""))
119125

120-
return nil
126+
result, err := cim.ConnectISCSITarget(portal.Address, portal.Port, iqn, targetAuthType, &chapUser, &chapSecret)
127+
if err != nil {
128+
return fmt.Errorf("error connecting to target portal. result: %d, err: %w", result, err)
129+
}
130+
131+
return nil
132+
})
121133
}
122134

123135
func (APIImplementor) DisconnectTarget(portal *TargetPortal, iqn string) error {
124-
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
125-
if err != nil {
126-
return err
127-
}
128-
129-
connected, err := cim.IsISCSITargetConnected(target)
130-
if err != nil {
131-
return fmt.Errorf("error query connected of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
132-
}
133-
134-
if !connected {
135-
klog.V(2).Infof("target %s from target portal at (%s:%d) is not connected.", iqn, portal.Address, portal.Port)
136-
return nil
137-
}
136+
return cim.WithCOMThread(func() error {
137+
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
138+
if err != nil {
139+
return err
140+
}
138141

139-
// get session
140-
session, err := cim.QueryISCSISessionByTarget(target)
141-
if err != nil {
142-
return fmt.Errorf("error query session of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
143-
}
142+
connected, err := cim.IsISCSITargetConnected(target)
143+
if err != nil {
144+
return fmt.Errorf("error query connected of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
145+
}
144146

145-
sessionIdentifier, err := cim.GetISCSISessionIdentifier(session)
146-
if err != nil {
147-
return fmt.Errorf("error query session identifier of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
148-
}
147+
if !connected {
148+
klog.V(2).Infof("target %s from target portal at (%s:%d) is not connected.", iqn, portal.Address, portal.Port)
149+
return nil
150+
}
149151

150-
persistent, err := cim.IsISCSISessionPersistent(session)
151-
if err != nil {
152-
return fmt.Errorf("error query session persistency of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
153-
}
152+
// get session
153+
session, err := cim.QueryISCSISessionByTarget(target)
154+
if err != nil {
155+
return fmt.Errorf("error query session of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
156+
}
154157

155-
if persistent {
156-
result, err := cim.UnregisterISCSISession(session)
158+
sessionIdentifier, err := cim.GetISCSISessionIdentifier(session)
157159
if err != nil {
158-
return fmt.Errorf("error unregister session on target %s from target portal at (%s:%d). result: %d, err: %w", iqn, portal.Address, portal.Port, result, err)
160+
return fmt.Errorf("error query session identifier of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
159161
}
160-
}
161162

162-
result, err := cim.DisconnectISCSITarget(target, sessionIdentifier)
163-
if err != nil {
164-
return fmt.Errorf("error disconnecting target %s from target portal at (%s:%d). result: %d, err: %w", iqn, portal.Address, portal.Port, result, err)
165-
}
163+
persistent, err := cim.IsISCSISessionPersistent(session)
164+
if err != nil {
165+
return fmt.Errorf("error query session persistency of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
166+
}
167+
168+
if persistent {
169+
result, err := cim.UnregisterISCSISession(session)
170+
if err != nil {
171+
return fmt.Errorf("error unregister session on target %s from target portal at (%s:%d). result: %d, err: %w", iqn, portal.Address, portal.Port, result, err)
172+
}
173+
}
166174

167-
return nil
175+
result, err := cim.DisconnectISCSITarget(target, sessionIdentifier)
176+
if err != nil {
177+
return fmt.Errorf("error disconnecting target %s from target portal at (%s:%d). result: %d, err: %w", iqn, portal.Address, portal.Port, result, err)
178+
}
179+
180+
return nil
181+
})
168182
}
169183

170184
func (APIImplementor) GetTargetDisks(portal *TargetPortal, iqn string) ([]string, error) {
171-
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
172-
if err != nil {
173-
return nil, err
174-
}
175-
176-
connected, err := cim.IsISCSITargetConnected(target)
177-
if err != nil {
178-
return nil, fmt.Errorf("error query connected of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
179-
}
180-
181-
if !connected {
182-
klog.V(2).Infof("target %s from target portal at (%s:%d) is not connected.", iqn, portal.Address, portal.Port)
183-
return nil, nil
184-
}
185-
186-
disks, err := cim.ListDisksByTarget(target)
187-
if err != nil {
188-
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)
189-
}
190-
191185
var ids []string
192-
for _, disk := range disks {
193-
number, err := cim.GetDiskNumber(disk)
186+
err := cim.WithCOMThread(func() error {
187+
target, err := cim.QueryISCSITarget(portal.Address, portal.Port, iqn)
188+
if err != nil {
189+
return err
190+
}
191+
192+
connected, err := cim.IsISCSITargetConnected(target)
194193
if err != nil {
195-
return nil, fmt.Errorf("error getting number of disk %v on target %s from target portal at (%s:%d). err: %w", disk, iqn, portal.Address, portal.Port, err)
194+
return fmt.Errorf("error query connected of target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
196195
}
197196

198-
ids = append(ids, strconv.Itoa(int(number)))
199-
}
200-
return ids, nil
197+
if !connected {
198+
klog.V(2).Infof("target %s from target portal at (%s:%d) is not connected.", iqn, portal.Address, portal.Port)
199+
return nil
200+
}
201+
202+
disks, err := cim.ListDisksByTarget(target)
203+
if err != nil {
204+
return fmt.Errorf("error getting target disks on target %s from target portal at (%s:%d). err: %w", iqn, portal.Address, portal.Port, err)
205+
}
206+
207+
for _, disk := range disks {
208+
number, err := cim.GetDiskNumber(disk)
209+
if err != nil {
210+
return fmt.Errorf("error getting number of disk %v on target %s from target portal at (%s:%d). err: %w", disk, iqn, portal.Address, portal.Port, err)
211+
}
212+
213+
ids = append(ids, strconv.Itoa(int(number)))
214+
}
215+
return nil
216+
})
217+
return ids, err
201218
}
202219

203220
func (APIImplementor) SetMutualChapSecret(mutualChapSecret string) error {
204-
result, err := cim.SetISCSISessionChapSecret(mutualChapSecret)
205-
if err != nil {
206-
return fmt.Errorf("error setting mutual chap secret. result: %d, err: %v", result, err)
207-
}
221+
return cim.WithCOMThread(func() error {
222+
result, err := cim.SetISCSISessionChapSecret(mutualChapSecret)
223+
if err != nil {
224+
return fmt.Errorf("error setting mutual chap secret. result: %d, err: %v", result, err)
225+
}
208226

209-
return nil
227+
return nil
228+
})
210229
}

0 commit comments

Comments
 (0)