Skip to content

Commit 431e79d

Browse files
committed
Regroup all session creation in util get_localAPI_session or APISession class.
New APISession class to handle lifecycle of the session, with context, or atexit handlers. Use various originator for xapi session creation, to differentiate where they are being created. Signed-off-by: Arnaud Garcia-Fernandez <arnaud.garcia-fernandez@vates.tech>
1 parent 189b763 commit 431e79d

15 files changed

Lines changed: 184 additions & 241 deletions

drivers/LinstorSR.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,7 +2585,9 @@ def _start_persistent_http_server(volume_name):
25852585
# Use a timeout call because XAPI may be unusable on startup
25862586
# or if the host has been ejected. So in this case the call can
25872587
# block indefinitely.
2588-
session = util.timeout(5, util.get_localAPI_session)
2588+
apisession = util.timeout(
2589+
5, util.APISession, "SM-LinstorSR-http")
2590+
session = apisession.session
25892591
host_ip = util.get_this_host_address(session)
25902592
except:
25912593
# Fallback using the XHA file if session not available.
@@ -2669,7 +2671,9 @@ def _start_persistent_nbd_server(self, volume_name):
26692671
device_size = 256 * 1024 * 1024
26702672

26712673
try:
2672-
session = util.timeout(5, util.get_localAPI_session)
2674+
apisession = util.timeout(
2675+
5, util.APISession, "SM-LinstorSR-nbd")
2676+
session = apisession.session
26732677
ips = util.get_host_addresses(session)
26742678
except Exception as e:
26752679
_, ips = get_ips_from_xha_config_file()

drivers/blktap2.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,14 +1152,9 @@ def get_o_direct_capability(self, options):
11521152

11531153
@classmethod
11541154
def from_cli(cls, uuid):
1155-
session = XenAPI.xapi_local()
1156-
session.xenapi.login_with_password('root', '', '', 'SM')
1157-
1158-
target = sm.VDI.from_uuid(session, uuid)
1159-
driver_info = target.sr.srcmd.driver_info
1160-
1161-
session.xenapi.session.logout()
1162-
1155+
with util.APISession("SM-blktap2") as session:
1156+
target = sm.VDI.from_uuid(session, uuid)
1157+
driver_info = target.sr.srcmd.driver_info
11631158
return cls(uuid, target, driver_info)
11641159

11651160
@staticmethod

drivers/cleanup.py

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -299,18 +299,12 @@ class XAPI:
299299
class LookupError(util.SMException):
300300
pass
301301

302-
@staticmethod
303-
def getSession():
304-
session = XenAPI.xapi_local()
305-
session.xenapi.login_with_password(XAPI.USER, '', '', 'SM')
306-
return session
307-
308302
def __init__(self, session, srUuid):
309-
self.sessionPrivate = False
310303
self.session = session
304+
self.apisession = None
311305
if self.session is None:
312-
self.session = self.getSession()
313-
self.sessionPrivate = True
306+
self.apisession = util.APISession("SM-cleanup-XAPI")
307+
self.session = self.apisession.session
314308
self._srRef = self.session.xenapi.SR.get_by_uuid(srUuid)
315309
self.srRecord = self.session.xenapi.SR.get_record(self._srRef)
316310
self.hostUuid = util.get_this_host()
@@ -319,8 +313,8 @@ def __init__(self, session, srUuid):
319313
self.task_progress = {"coalescable": 0, "done": 0}
320314

321315
def __del__(self):
322-
if self.sessionPrivate:
323-
self.session.xenapi.session.logout()
316+
if self.apisession:
317+
self.apisession.logout()
324318

325319
@property
326320
def srRef(self):
@@ -2127,32 +2121,31 @@ def msg_cleared(self, xapi_session, msg_ref):
21272121
return msg is None
21282122

21292123
def check_no_space_candidates(self):
2130-
xapi_session = self.xapi.getSession()
2131-
2132-
msg_id = self.xapi.srRecord["sm_config"].get(VDI.DB_GC_NO_SPACE)
2133-
if self.no_space_candidates:
2134-
if msg_id is None or self.msg_cleared(xapi_session, msg_id):
2135-
util.SMlog("Could not coalesce due to a lack of space "
2136-
f"in SR {self.uuid}")
2137-
msg_body = ("Unable to perform data coalesce due to a lack "
2138-
f"of space in SR {self.uuid}")
2139-
msg_id = xapi_session.xenapi.message.create(
2140-
'SM_GC_NO_SPACE',
2141-
3,
2142-
"SR",
2143-
self.uuid,
2144-
msg_body)
2145-
xapi_session.xenapi.SR.remove_from_sm_config(
2146-
self.xapi.srRef, VDI.DB_GC_NO_SPACE)
2147-
xapi_session.xenapi.SR.add_to_sm_config(
2148-
self.xapi.srRef, VDI.DB_GC_NO_SPACE, msg_id)
2149-
2150-
for candidate in self.no_space_candidates.values():
2151-
candidate.setConfig(VDI.DB_GC_NO_SPACE, msg_id)
2152-
elif msg_id is not None:
2153-
# Everything was coalescable, remove the message
2154-
xapi_session.xenapi.SR.remove_from_sm_config(self.xapi.srRef, VDI.DB_GC_NO_SPACE)
2155-
xapi_session.xenapi.message.destroy(msg_id)
2124+
with util.APISession("SM-cleanup-SR-check_no_space_candidates") as xapi_session:
2125+
msg_id = self.xapi.srRecord["sm_config"].get(VDI.DB_GC_NO_SPACE)
2126+
if self.no_space_candidates:
2127+
if msg_id is None or self.msg_cleared(xapi_session, msg_id):
2128+
util.SMlog("Could not coalesce due to a lack of space "
2129+
f"in SR {self.uuid}")
2130+
msg_body = ("Unable to perform data coalesce due to a lack "
2131+
f"of space in SR {self.uuid}")
2132+
msg_id = xapi_session.xenapi.message.create(
2133+
'SM_GC_NO_SPACE',
2134+
3,
2135+
"SR",
2136+
self.uuid,
2137+
msg_body)
2138+
xapi_session.xenapi.SR.remove_from_sm_config(
2139+
self.xapi.srRef, VDI.DB_GC_NO_SPACE)
2140+
xapi_session.xenapi.SR.add_to_sm_config(
2141+
self.xapi.srRef, VDI.DB_GC_NO_SPACE, msg_id)
2142+
2143+
for candidate in self.no_space_candidates.values():
2144+
candidate.setConfig(VDI.DB_GC_NO_SPACE, msg_id)
2145+
elif msg_id is not None:
2146+
# Everything was coalescable, remove the message
2147+
xapi_session.xenapi.SR.remove_from_sm_config(self.xapi.srRef, VDI.DB_GC_NO_SPACE)
2148+
xapi_session.xenapi.message.destroy(msg_id)
21562149

21572150
def clear_no_space_msg(self, vdi):
21582151
msg_id = None

drivers/coalesce-leaf

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
#
33
# Copyright (C) Citrix Systems Inc.
44
#
5-
# This program is free software; you can redistribute it and/or modify
6-
# it under the terms of the GNU Lesser General Public License as published
5+
# This program is free software; you can redistribute it and/or modify
6+
# it under the terms of the GNU Lesser General Public License as published
77
# by the Free Software Foundation; version 2.1 only.
88
#
9-
# This program is distributed in the hope that it will be useful,
10-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1212
# GNU Lesser General Public License for more details.
1313
#
1414
# You should have received a copy of the GNU Lesser General Public License
@@ -229,12 +229,9 @@ def main():
229229
print(USAGE_STRING % sys.argv[0])
230230
sys.exit(-1)
231231

232-
session = XenAPI.xapi_local()
233-
session.xenapi.login_with_password('root', '', '', 'SM')
234-
atexit.register(session.xenapi.session.logout)
235-
236-
ret, messages = vm_leaf_coalesce(session, uuid)
237-
if len(messages):
232+
with util.APISession("SM-coalesce-leaf") as session:
233+
ret, messages = vm_leaf_coalesce(session, uuid)
234+
if messages:
238235
print("\n".join(messages))
239236
sys.exit(ret)
240237

drivers/lcache.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,9 @@ def from_session(cls, session):
221221

222222
@classmethod
223223
def from_cli(cls):
224-
import XenAPI # pylint: disable=import-error
225-
226-
session = XenAPI.xapi_local()
227-
session.xenapi.login_with_password('root', '', '', 'SM')
228-
229-
return cls.from_session(session)
224+
import util
225+
with util.APISession("SM-lcache-CacheFileSR") as session:
226+
return cls.from_session(session)
230227

231228
def statvfs(self):
232229
return os.statvfs(self.sr_path)

drivers/linstorcowutil.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -648,19 +648,10 @@ def clear(self):
648648
self.linstor = None
649649
self.vdi_type_to_cowutil = {}
650650

651-
class Load:
652-
def __init__(self, session):
653-
self.session = session
654-
655-
def cleanup(self):
656-
if self.session:
657-
self.session.xenapi.session.logout()
658-
self.session = None
659-
660651
def __init__(self, uri, group_name) -> None:
661652
self._uri = uri
662653
self._group_name = group_name
663-
self._loads: List[MultiLinstorCowUtil.Load] = []
654+
self._loads: List[util.APISession] = []
664655
self._executor_data = self.ExecutorData()
665656

666657
def __del__(self):
@@ -687,8 +678,8 @@ def get_local_cowutil(self, vdi_type):
687678
return instance
688679

689680
def _init_executor_thread(self):
690-
session = util.get_localAPI_session()
691-
load = self.Load(session)
681+
apisession = util.APISession("SM-linstorvhdutil")
682+
session = apisession.session
692683
try:
693684
linstor = LinstorVolumeManager(
694685
self._uri,
@@ -700,15 +691,13 @@ def _init_executor_thread(self):
700691
self._executor_data.session = session
701692
except:
702693
self._executor_data.clear()
703-
load.cleanup()
704694
raise
705-
706-
self._loads.append(load)
695+
self._loads.append(apisession)
707696

708697
def _cleanup(self):
709698
for load in self._loads:
710699
try:
711-
load.cleanup()
700+
load.logout()
712701
except Exception as e:
713702
util.SMlog(f"Failed to clean load executor: {e}")
714703
self._loads.clear()

drivers/linstorvolumemanager.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -101,28 +101,27 @@ def get_all_volume_openers(resource_name, volume) -> LinstorVolumeOpeners:
101101
volume = str(volume)
102102
openers = {}
103103

104-
session = util.get_localAPI_session()
105-
106-
hosts = session.xenapi.host.get_all_records()
107-
for host_ref, host_record in hosts.items():
108-
node_name = host_record['hostname']
109-
try:
110-
if not session.xenapi.host_metrics.get_record(
111-
host_record['metrics']
112-
)['live']:
113-
# Ensure we call plugin on online hosts only.
114-
continue
104+
with util.APISession("SM-linstorvolumemanager-get_all_volume_openers") as session:
105+
hosts = session.xenapi.host.get_all_records()
106+
for host_ref, host_record in hosts.items():
107+
node_name = host_record['hostname']
108+
try:
109+
if not session.xenapi.host_metrics.get_record(
110+
host_record['metrics']
111+
)['live']:
112+
# Ensure we call plugin on online hosts only.
113+
continue
115114

116-
openers[node_name] = json.loads(
117-
session.xenapi.host.call_plugin(host_ref, PLUGIN, PLUGIN_CMD, {
118-
'resourceName': resource_name,
119-
'volume': volume
120-
})
121-
)
122-
except Exception as e:
123-
util.SMlog('Failed to get openers of `{}` on `{}`: {}'.format(
124-
resource_name, node_name, e
125-
))
115+
openers[node_name] = json.loads(
116+
session.xenapi.host.call_plugin(host_ref, PLUGIN, PLUGIN_CMD, {
117+
'resourceName': resource_name,
118+
'volume': volume
119+
})
120+
)
121+
except Exception as e:
122+
util.SMlog('Failed to get openers of `{}` on `{}`: {}'.format(
123+
resource_name, node_name, e
124+
))
126125

127126
return openers
128127

@@ -191,7 +190,8 @@ def get_controller_node_name():
191190
if res:
192191
return res.groups()[0]
193192

194-
session = util.timeout(5, util.get_localAPI_session)
193+
apisession = util.timeout(5, util.APISession, "SM-linstorvolumemanager-get_controller_node_name")
194+
session = apisession.session
195195

196196
for host_ref, host_record in session.xenapi.host.get_all_records().items():
197197
node_name = host_record['hostname']
@@ -214,7 +214,8 @@ def get_controller_node_name():
214214
def demote_drbd_resource(node_name, resource_name):
215215
PLUGIN_CMD = 'demoteDrbdResource'
216216

217-
session = util.timeout(5, util.get_localAPI_session)
217+
apisession = util.timeout(5, util.APISession, "SM-linstorvolumemanager-demote_drbd_resource")
218+
session = apisession.session
218219

219220
for host_ref, host_record in session.xenapi.host.get_all_records().items():
220221
if host_record['hostname'] != node_name:
@@ -1417,7 +1418,8 @@ def destroy(self):
14171418
# It needs to be done locally by each host so we go through the linstor-manager plugin.
14181419
# If we don't do this sometimes, the destroy will fail when trying to destroy the resource groups with:
14191420
# "linstor-manager:destroy error: Failed to destroy SP `xcp-sr-linstor_group_thin_device` on node `r620-s2`: The specified storage pool 'xcp-sr-linstor_group_thin_device' on node 'r620-s2' can not be deleted as volumes / snapshot-volumes are still using it."
1420-
session = util.timeout(5, util.get_localAPI_session)
1421+
apisession = util.timeout(5, util.APISession, "SM-linstorvolumemanager-destroy")
1422+
session = apisession.session
14211423
for host_ref in session.xenapi.host.get_all():
14221424
try:
14231425
response = session.xenapi.host.call_plugin(

drivers/mpathcount.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,6 @@ def get_dm_major():
5353
return cached_DM_maj
5454

5555

56-
def mpc_exit(session, code):
57-
if session is not None:
58-
try:
59-
session.xenapi.session.logout()
60-
except:
61-
pass
62-
sys.exit(code)
63-
64-
6556
def match_host_id(s):
6657
regex = re.compile("^INSTALLATION_UUID")
6758
return regex.search(s, 0)
@@ -231,9 +222,9 @@ def _run_command(command, timeout):
231222

232223
if __name__ == '__main__':
233224
try:
234-
session = util.get_localAPI_session()
235-
except:
236-
print("Unable to open local XAPI session")
225+
apisession = util.APISession("SM-mpathcount")
226+
session = apisession.session
227+
except xs_errors.XenError:
237228
sys.exit(-1)
238229

239230
localhost = session.xenapi.host.get_by_uuid(get_localhost_uuid())
@@ -252,7 +243,6 @@ def _run_command(command, timeout):
252243
def _remove(key):
253244
session.xenapi.host.remove_from_other_config(localhost, key)
254245

255-
256246
def _add(key, val):
257247
session.xenapi.host.add_to_other_config(localhost, key, val)
258248
config = session.xenapi.host.get_other_config(localhost)
@@ -261,20 +251,19 @@ def _add(key, val):
261251

262252
except:
263253
util.SMlog("MPATH: Failure updating Host.other-config:mpath-boot db")
264-
mpc_exit(session, -1)
254+
sys.exit(-1)
265255

266256
try:
267257
pbds = session.xenapi.PBD.get_all_records_where("field \"host\" = \"%s\"" % localhost)
268258
except:
269-
mpc_exit(session, -1)
259+
sys.exit(-1)
270260

271261
try:
272262
mpath_status: Dict[str, str] = {}
273263
for pbd in pbds:
274264
def remove(key):
275265
session.xenapi.PBD.remove_from_other_config(pbd, key)
276266

277-
278267
def add(key, val):
279268
session.xenapi.PBD.add_to_other_config(pbd, key, val)
280269
record = pbds[pbd]
@@ -290,8 +279,8 @@ def add(key, val):
290279
os.chmod(MPATH_FILE_NAME, 0o0644)
291280
except:
292281
util.SMlog("MPATH: Failure updating db. %s" % str(sys.exc_info()))
293-
mpc_exit(session, -1)
282+
sys.exit(-1)
294283

295284
util.SMlog("MPATH: Update done")
296285

297-
mpc_exit(session, 0)
286+
sys.exit(0)

0 commit comments

Comments
 (0)