Skip to content

Commit be646e3

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 103267f commit be646e3

15 files changed

Lines changed: 211 additions & 233 deletions

drivers/LinstorSR.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2573,7 +2573,9 @@ def _start_persistent_http_server(volume_name):
25732573
# Use a timeout call because XAPI may be unusable on startup
25742574
# or if the host has been ejected. So in this case the call can
25752575
# block indefinitely.
2576-
session = util.timeout_call(5, util.get_localAPI_session)
2576+
apisession = util.timeout_call(
2577+
5, util.APISession, "SM-LinstorSR-http")
2578+
session = apisession.session
25772579
host_ip = util.get_this_host_address(session)
25782580
except:
25792581
# Fallback using the XHA file if session not available.
@@ -2657,7 +2659,9 @@ def _start_persistent_nbd_server(self, volume_name):
26572659
device_size = 256 * 1024 * 1024
26582660

26592661
try:
2660-
session = util.timeout_call(5, util.get_localAPI_session)
2662+
apisession = util.timeout_call(
2663+
5, util.APISession, "SM-LinstorSR-nbd")
2664+
session = apisession.session
26612665
ips = util.get_host_addresses(session)
26622666
except Exception as e:
26632667
_, ips = get_ips_from_xha_config_file()

drivers/blktap2.py

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

10671067
@classmethod
10681068
def from_cli(cls, uuid):
1069-
session = XenAPI.xapi_local()
1070-
session.xenapi.login_with_password('root', '', '', 'SM')
1071-
1072-
target = sm.VDI.from_uuid(session, uuid)
1073-
driver_info = target.sr.srcmd.driver_info
1074-
1075-
session.xenapi.session.logout()
1076-
1069+
with util.APISession("SM-blktap2") as session:
1070+
target = sm.VDI.from_uuid(session, uuid)
1071+
driver_info = target.sr.srcmd.driver_info
10771072
return cls(uuid, target, driver_info)
10781073

10791074
@staticmethod

drivers/cleanup.py

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -295,18 +295,12 @@ class XAPI:
295295
class LookupError(util.SMException):
296296
pass
297297

298-
@staticmethod
299-
def getSession():
300-
session = XenAPI.xapi_local()
301-
session.xenapi.login_with_password(XAPI.USER, '', '', 'SM')
302-
return session
303-
304298
def __init__(self, session, srUuid):
305-
self.sessionPrivate = False
306299
self.session = session
300+
self.apisession = None
307301
if self.session is None:
308-
self.session = self.getSession()
309-
self.sessionPrivate = True
302+
self.apisession = util.APISession("SM-cleanup-XAPI")
303+
self.session = self.apisession.session
310304
self._srRef = self.session.xenapi.SR.get_by_uuid(srUuid)
311305
self.srRecord = self.session.xenapi.SR.get_record(self._srRef)
312306
self.hostUuid = util.get_this_host()
@@ -315,8 +309,8 @@ def __init__(self, session, srUuid):
315309
self.task_progress = {"coalescable": 0, "done": 0}
316310

317311
def __del__(self):
318-
if self.sessionPrivate:
319-
self.session.xenapi.session.logout()
312+
if self.apisession:
313+
self.apisession.logout()
320314

321315
@property
322316
def srRef(self):
@@ -1999,32 +1993,31 @@ def msg_cleared(self, xapi_session, msg_ref):
19991993
return msg is None
20001994

20011995
def check_no_space_candidates(self):
2002-
xapi_session = self.xapi.getSession()
2003-
2004-
msg_id = self.xapi.srRecord["sm_config"].get(VDI.DB_GC_NO_SPACE)
2005-
if self.no_space_candidates:
2006-
if msg_id is None or self.msg_cleared(xapi_session, msg_id):
2007-
util.SMlog("Could not coalesce due to a lack of space "
2008-
f"in SR {self.uuid}")
2009-
msg_body = ("Unable to perform data coalesce due to a lack "
2010-
f"of space in SR {self.uuid}")
2011-
msg_id = xapi_session.xenapi.message.create(
2012-
'SM_GC_NO_SPACE',
2013-
3,
2014-
"SR",
2015-
self.uuid,
2016-
msg_body)
2017-
xapi_session.xenapi.SR.remove_from_sm_config(
2018-
self.xapi.srRef, VDI.DB_GC_NO_SPACE)
2019-
xapi_session.xenapi.SR.add_to_sm_config(
2020-
self.xapi.srRef, VDI.DB_GC_NO_SPACE, msg_id)
2021-
2022-
for candidate in self.no_space_candidates.values():
2023-
candidate.setConfig(VDI.DB_GC_NO_SPACE, msg_id)
2024-
elif msg_id is not None:
2025-
# Everything was coalescable, remove the message
2026-
xapi_session.xenapi.SR.remove_from_sm_config(self.xapi.srRef, VDI.DB_GC_NO_SPACE)
2027-
xapi_session.xenapi.message.destroy(msg_id)
1996+
with util.APISession("SM-cleanup-SR-check_no_space_candidates") as xapi_session:
1997+
msg_id = self.xapi.srRecord["sm_config"].get(VDI.DB_GC_NO_SPACE)
1998+
if self.no_space_candidates:
1999+
if msg_id is None or self.msg_cleared(xapi_session, msg_id):
2000+
util.SMlog("Could not coalesce due to a lack of space "
2001+
f"in SR {self.uuid}")
2002+
msg_body = ("Unable to perform data coalesce due to a lack "
2003+
f"of space in SR {self.uuid}")
2004+
msg_id = xapi_session.xenapi.message.create(
2005+
'SM_GC_NO_SPACE',
2006+
3,
2007+
"SR",
2008+
self.uuid,
2009+
msg_body)
2010+
xapi_session.xenapi.SR.remove_from_sm_config(
2011+
self.xapi.srRef, VDI.DB_GC_NO_SPACE)
2012+
xapi_session.xenapi.SR.add_to_sm_config(
2013+
self.xapi.srRef, VDI.DB_GC_NO_SPACE, msg_id)
2014+
2015+
for candidate in self.no_space_candidates.values():
2016+
candidate.setConfig(VDI.DB_GC_NO_SPACE, msg_id)
2017+
elif msg_id is not None:
2018+
# Everything was coalescable, remove the message
2019+
xapi_session.xenapi.SR.remove_from_sm_config(self.xapi.srRef, VDI.DB_GC_NO_SPACE)
2020+
xapi_session.xenapi.message.destroy(msg_id)
20282021

20292022
def clear_no_space_msg(self, vdi):
20302023
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: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,8 @@ def from_session(cls, session):
219219

220220
@classmethod
221221
def from_cli(cls):
222-
import XenAPI # pylint: disable=import-error
223-
224-
session = XenAPI.xapi_local()
225-
session.xenapi.login_with_password('root', '', '', 'SM')
226-
222+
import util
223+
session = util.get_localAPI_session("SM-lcache-CacheFileSR")
227224
return cls.from_session(session)
228225

229226
def statvfs(self):

drivers/linstorvhdutil.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -611,19 +611,10 @@ def clear(self):
611611
self.linstor = None
612612
self.vhdutil = None
613613

614-
class Load:
615-
def __init__(self, session):
616-
self.session = session
617-
618-
def cleanup(self):
619-
if self.session:
620-
self.session.xenapi.session.logout()
621-
self.session = None
622-
623614
def __init__(self, uri, group_name) -> None:
624615
self._uri = uri
625616
self._group_name = group_name
626-
self._loads: List[MultiLinstorVhdUtil.Load] = []
617+
self._loads: List[util.APISession] = []
627618
self._executor_data = self.ExecutorData()
628619

629620
def __del__(self):
@@ -643,8 +634,8 @@ def local_vhdutil(self):
643634
return self._executor_data.vhdutil
644635

645636
def _init_executor_thread(self):
646-
session = util.get_localAPI_session()
647-
load = self.Load(session)
637+
apisession = util.APISession("SM-linstorvhdutil")
638+
session = apisession.session
648639
try:
649640
linstor = LinstorVolumeManager(
650641
self._uri,
@@ -657,15 +648,13 @@ def _init_executor_thread(self):
657648
self._executor_data.session = session
658649
except:
659650
self._executor_data.clear()
660-
load.cleanup()
661651
raise
662-
663-
self._loads.append(load)
652+
self._loads.append(apisession)
664653

665654
def _cleanup(self):
666655
for load in self._loads:
667656
try:
668-
load.cleanup()
657+
load.logout()
669658
except Exception as e:
670659
util.SMlog(f"Failed to clean load executor: {e}")
671660
self._loads.clear()

drivers/linstorvolumemanager.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -90,28 +90,27 @@ def get_all_volume_openers(resource_name, volume):
9090
volume = str(volume)
9191
openers = {}
9292

93-
session = util.get_localAPI_session()
94-
95-
hosts = session.xenapi.host.get_all_records()
96-
for host_ref, host_record in hosts.items():
97-
node_name = host_record['hostname']
98-
try:
99-
if not session.xenapi.host_metrics.get_record(
100-
host_record['metrics']
101-
)['live']:
102-
# Ensure we call plugin on online hosts only.
103-
continue
93+
with util.APISession("SM-linstorvolumemanager-get_all_volume_openers") as session:
94+
hosts = session.xenapi.host.get_all_records()
95+
for host_ref, host_record in hosts.items():
96+
node_name = host_record['hostname']
97+
try:
98+
if not session.xenapi.host_metrics.get_record(
99+
host_record['metrics']
100+
)['live']:
101+
# Ensure we call plugin on online hosts only.
102+
continue
104103

105-
openers[node_name] = json.loads(
106-
session.xenapi.host.call_plugin(host_ref, PLUGIN, PLUGIN_CMD, {
107-
'resourceName': resource_name,
108-
'volume': volume
109-
})
110-
)
111-
except Exception as e:
112-
util.SMlog('Failed to get openers of `{}` on `{}`: {}'.format(
113-
resource_name, node_name, e
114-
))
104+
openers[node_name] = json.loads(
105+
session.xenapi.host.call_plugin(host_ref, PLUGIN, PLUGIN_CMD, {
106+
'resourceName': resource_name,
107+
'volume': volume
108+
})
109+
)
110+
except Exception as e:
111+
util.SMlog('Failed to get openers of `{}` on `{}`: {}'.format(
112+
resource_name, node_name, e
113+
))
115114

116115
return openers
117116

@@ -180,7 +179,8 @@ def get_controller_node_name():
180179
if res:
181180
return res.groups()[0]
182181

183-
session = util.timeout_call(5, util.get_localAPI_session)
182+
apisession = util.timeout_call(5, util.APISession, "SM-linstorvolumemanager-get_controller_node_name")
183+
session = apisession.session
184184

185185
for host_ref, host_record in session.xenapi.host.get_all_records().items():
186186
node_name = host_record['hostname']
@@ -203,7 +203,8 @@ def get_controller_node_name():
203203
def demote_drbd_resource(node_name, resource_name):
204204
PLUGIN_CMD = 'demoteDrbdResource'
205205

206-
session = util.timeout_call(5, util.get_localAPI_session)
206+
apisession = util.timeout_call(5, util.APISession, "SM-linstorvolumemanager-demote_drbd_resource")
207+
session = apisession.session
207208

208209
for host_ref, host_record in session.xenapi.host.get_all_records().items():
209210
if host_record['hostname'] != node_name:
@@ -1395,7 +1396,8 @@ def destroy(self):
13951396
# It needs to be done locally by each host so we go through the linstor-manager plugin.
13961397
# If we don't do this sometimes, the destroy will fail when trying to destroy the resource groups with:
13971398
# "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."
1398-
session = util.timeout_call(5, util.get_localAPI_session)
1399+
apisession = util.timeout_call(5, util.APISession, "SM-linstorvolumemanager-destroy")
1400+
session = apisession.session
13991401
for host_ref in session.xenapi.host.get_all():
14001402
try:
14011403
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)

drivers/plugins/keymanagerutil.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ def load_key(key_hash, vdi_uuid):
3939

4040

4141
def _check_key(key_hash, vdi_uuid):
42-
session = XenAPI.xapi_local()
43-
session.xenapi.login_with_password('root', '', '', PROGRAM_NAME)
44-
try:
42+
with util.APISession(PROGRAM_NAME) as session:
4543
vdi = session.xenapi.VDI.get_by_uuid(vdi_uuid)
4644
sm_config = session.xenapi.VDI.get_sm_config(vdi)
4745
if 'key_hash' in sm_config:
@@ -54,8 +52,6 @@ def _check_key(key_hash, vdi_uuid):
5452
raise Exception('Encryption key requested for VDI {}'
5553
' whose sm_config does not contain the key_hash'
5654
' entry. Its sm_config is {}'.format(vdi_uuid, sm_config))
57-
finally:
58-
session.xenapi.logout()
5955

6056

6157
class InputError(Exception):

0 commit comments

Comments
 (0)