Skip to content

Commit c9d5134

Browse files
committed
in progress
Signed-off-by: Ronan Abhamon <ronan.abhamon@vates.tech>
1 parent d7cd0b1 commit c9d5134

File tree

11 files changed

+289
-93
lines changed

11 files changed

+289
-93
lines changed

drivers/LinstorSR.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -559,23 +559,21 @@ def create(self, uuid, size) -> None:
559559
opterr='Redundancy greater than host count'
560560
)
561561

562-
xenapi = self.session.xenapi
563-
srs = xenapi.SR.get_all_records_where(
564-
'field "type" = "{}"'.format(self.DRIVER_TYPE)
565-
)
566-
srs = dict([e for e in srs.items() if e[1]['uuid'] != self.uuid])
562+
srs = util.get_linstor_srs(self.session)
563+
try:
564+
srs.pop(self.uuid)
565+
except KeyError:
566+
# We cannot guarantee that the new SR key will be there even it should be the case.
567+
pass
567568

568-
for sr in srs.values():
569-
for pbd in sr['PBDs']:
570-
device_config = xenapi.PBD.get_device_config(pbd)
571-
group_name = device_config.get('group-name')
572-
if group_name and group_name == self._group_name:
573-
raise xs_errors.XenError(
574-
'LinstorSRCreate',
575-
opterr='group name must be unique, already used by PBD {}'.format(
576-
xenapi.PBD.get_uuid(pbd)
577-
)
578-
)
569+
pbd_uuid = util.find_pbd_uuid_from_dconf_value(
570+
self.session, srs, "group-name", self._group_name, LinstorVolumeManager.build_group_name
571+
)
572+
if pbd_uuid:
573+
raise xs_errors.XenError(
574+
'LinstorSRCreate',
575+
opterr=f"group name must be unique, already used by PBD {pbd_uuid}"
576+
)
579577

580578
if srs:
581579
raise xs_errors.XenError(
@@ -1838,7 +1836,8 @@ def attach(self, sr_uuid, vdi_uuid) -> str:
18381836
return self._attach_using_http_nbd()
18391837

18401838
# Ensure we have a path...
1841-
self.sr._vhdutil.create_chain_paths(self.uuid, readonly=not writable)
1839+
chain = self.sr._vhdutil.create_chain_paths(self.uuid, not writable, cleanup.LinstorSR.abort_gc_from_openers_vdi)
1840+
chain.close()
18421841

18431842
self.attached = True
18441843
return VDI.VDI.attach(self, self.sr.uuid, self.uuid)
@@ -2375,7 +2374,8 @@ def _snapshot(self, snap_type, cbtlog=None, cbt_consistency=None):
23752374
raise xs_errors.XenError('SnapshotChainTooLong')
23762375

23772376
# Ensure we have a valid path if we don't have a local diskful.
2378-
self.sr._vhdutil.create_chain_paths(self.uuid, readonly=True)
2377+
chain = self.sr._vhdutil.create_chain_paths(self.uuid, True, cleanup.LinstorSR.abort_gc_from_openers_vdi)
2378+
chain.close()
23792379

23802380
volume_path = self.path
23812381
if not util.pathexists(volume_path):

drivers/VDI.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,8 @@ def __init__(self, sr, uuid):
123123

124124
@staticmethod
125125
def from_uuid(session, vdi_uuid):
126-
127-
_VDI = session.xenapi.VDI
128-
vdi_ref = _VDI.get_by_uuid(vdi_uuid)
129-
sr_ref = _VDI.get_SR(vdi_ref)
130-
131-
_SR = session.xenapi.SR
132-
sr_uuid = _SR.get_uuid(sr_ref)
133-
126+
vdi_ref = session.xenapi.VDI.get_by_uuid(vdi_uuid)
127+
sr_uuid = util.get_sr_from_vdi_ref(session, vdi_ref)
134128
sr = SR.SR.from_uuid(session, sr_uuid)
135129

136130
sr.srcmd.params['vdi_ref'] = vdi_ref

drivers/blktap2.py

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
from socket import socket, AF_UNIX, SOCK_STREAM
5656

5757
try:
58-
from linstorvolumemanager import log_drbd_openers
58+
from linstorvolumemanager import get_controller_uri, get_all_volume_openers, LinstorVolumeManager
5959
LINSTOR_AVAILABLE = True
6060
except ImportError:
6161
LINSTOR_AVAILABLE = False
@@ -424,6 +424,8 @@ def unpause(cls, pid, minor, _type=None, _file=None, mirror=None,
424424
args += ["-a", str(params)]
425425
if cbtlog:
426426
args.extend(["-c", cbtlog])
427+
428+
# TODO: Handle issue.
427429
cls._pread(args)
428430

429431
@classmethod
@@ -820,6 +822,42 @@ def cgclassify(pid):
820822
except util.CommandException as e:
821823
util.logException(e)
822824

825+
@staticmethod
826+
def abort_linstor_gc(drbd_path: str) -> bool:
827+
if not LINSTOR_AVAILABLE or not drbd_path.startswith("/dev/drbd/by-res/xcp-volume-"):
828+
return False
829+
830+
_, volume_name, _ = drbd_path.rsplit("/", 2)
831+
group_name = LinstorVolumeManager.get_volume_group_name(volume_name)
832+
833+
openers = get_all_volume_openers(volume_name, "0")
834+
835+
session = XenAPI.xapi_local()
836+
session.xenapi.login_with_password("root", "", "", "SM")
837+
try:
838+
srs = util.get_linstor_srs(session)
839+
pbd_uuid = util.find_pbd_uuid_from_dconf_value(
840+
session, srs, "group-name", group_name, LinstorVolumeManager.build_group_name
841+
)
842+
if pbd_uuid:
843+
pbd_ref = session.xenapi.PBD.get_by_uuid(pbd_uuid)
844+
pbd_rec = session.xenapi.PBD.get_record(pbd_ref)
845+
846+
sr_ref = pbd_rec["SR"]
847+
sr_uuid = session.xenapi.SR.get_uuid(sr_ref)
848+
849+
import cleanup # pylint: disable=C0415
850+
if cleanup.LinstorSR.abort_gc_from_openers_sr(sr_uuid, openers):
851+
return True
852+
else:
853+
util.SMlog(f"Unable to find PBD of LINSTOR group `{group_name}`...")
854+
855+
util.SMlog(f"Unable to run tapdisk, openers of DRBD resource `{drbd_path}`: {openers}")
856+
finally:
857+
session.xenapi.session.logout()
858+
859+
return False
860+
823861
@classmethod
824862
def launch_on_tap(cls, blktap, path, _type, options):
825863

@@ -844,13 +882,13 @@ def launch_on_tap(cls, blktap, path, _type, options):
844882
err = (
845883
'status' in e.info and e.info['status']
846884
) or None
847-
if err in (errno.EIO, errno.EROFS, errno.EAGAIN):
848-
if retry_open < 5:
849-
retry_open += 1
850-
time.sleep(1)
851-
continue
852-
if LINSTOR_AVAILABLE and err == errno.EROFS:
853-
log_drbd_openers(path)
885+
if err in (errno.EROFS, errno.EMEDIUMTYPE) and cls.abort_linstor_gc(path):
886+
continue
887+
888+
if err in (errno.EIO, errno.EAGAIN, errno.EROFS, errno.EMEDIUMTYPE) and retry_open < 5:
889+
retry_open += 1
890+
time.sleep(1)
891+
continue
854892
raise
855893
try:
856894
tapdisk = cls.__from_blktap(blktap)

drivers/cleanup.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# Script to coalesce and garbage collect VHD-based SR's in the background
1919
#
2020

21-
from sm_typing import Optional, override
21+
from sm_typing import Dict, Optional, override
2222

2323
import os
2424
import os.path
@@ -56,8 +56,7 @@
5656
from linstorjournaler import LinstorJournaler
5757
from linstorvhdutil import LinstorVhdUtil
5858
from linstorvolumemanager import get_controller_uri
59-
from linstorvolumemanager import LinstorVolumeManager
60-
from linstorvolumemanager import LinstorVolumeManagerError
59+
from linstorvolumemanager import LinstorVolumeManager, LinstorVolumeManagerError, LinstorVolumeOpeners
6160
from linstorvolumemanager import PERSISTENT_PREFIX as LINSTOR_PERSISTENT_PREFIX
6261

6362
LINSTOR_AVAILABLE = True
@@ -3656,17 +3655,57 @@ def _finishInterruptedCoalesceLeaf(self, childUuid, parentUuid):
36563655

36573656
def _checkSlaves(self, vdi):
36583657
try:
3659-
all_openers = self._linstor.get_volume_openers(vdi.uuid)
3660-
for openers in all_openers.values():
3661-
for opener in openers.values():
3658+
openers = self._linstor.get_volume_openers(vdi.uuid)
3659+
for host_openers in openers.values():
3660+
for opener in host_openers.values():
36623661
if opener['process-name'] != 'tapdisk':
36633662
raise util.SMException(
3664-
'VDI {} is in use: {}'.format(vdi.uuid, all_openers)
3663+
'VDI {} is in use: {}'.format(vdi.uuid, openers)
36653664
)
36663665
except LinstorVolumeManagerError as e:
36673666
if e.code != LinstorVolumeManagerError.ERR_VOLUME_NOT_EXISTS:
36683667
raise
36693668

3669+
@classmethod
3670+
def abort_gc_from_openers_vdi(cls, vdi_uuid: str, openers: "LinstorVolumeOpeners") -> bool:
3671+
return cls._abort_gc_from_openers(vdi_uuid, True, openers)
3672+
3673+
@classmethod
3674+
def abort_gc_from_openers_sr(cls, sr_uuid: str, openers: "LinstorVolumeOpeners") -> bool:
3675+
return cls._abort_gc_from_openers(sr_uuid, False, openers)
3676+
3677+
@staticmethod
3678+
def _abort_gc_from_openers(uuid: str, is_vdi_uuid: bool, openers: "LinstorVolumeOpeners") -> bool:
3679+
from linstorvhdutil import MANAGER_PLUGIN
3680+
3681+
node_name = None
3682+
3683+
for host_openers in openers.values():
3684+
for hostname, opener in host_openers.items():
3685+
# Not the most accurate check but it works...
3686+
# `vhd-util` is probably prefixed with a "+" which is ignored here.
3687+
if not opener["process-name"].endswith("vhd-util") or "coalesce" not in opener["cmdline"]:
3688+
continue
3689+
3690+
if not node_name:
3691+
import socket
3692+
node_name = socket.gethostname()
3693+
3694+
if node_name == hostname:
3695+
continue
3696+
3697+
session = XAPI.getSession()
3698+
try:
3699+
sr_uuid = util.get_sr_from_vdi_uuid(session, uuid) if is_vdi_uuid else uuid
3700+
util.SMlog(f"LINSTOR volume is coalescing on `{sr_uuid}`. We're going to interrupt the GC...")
3701+
return util.strtobool(session.xenapi.host.call_plugin(
3702+
util.get_master_ref(session), MANAGER_PLUGIN, "abortGc", {"srUuid": sr_uuid}
3703+
))
3704+
finally:
3705+
session.xenapi.session.logout()
3706+
return False
3707+
3708+
36703709

36713710
################################################################################
36723711
#

drivers/linstor-manager

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,19 @@ def destroy(session, args):
385385
return str(False)
386386

387387

388+
def abort_gc(session, args):
389+
try:
390+
sr_uuid = args['srUuid']
391+
392+
import cleanup
393+
cleanup.abort(sr_uuid)
394+
395+
return str(True)
396+
except Exception as e:
397+
util.SMlog('linstor-manager:abort_gc error: {}'.format(e))
398+
return str(False)
399+
400+
388401
def check(session, args):
389402
try:
390403
device_path = args['devicePath']
@@ -1231,6 +1244,7 @@ if __name__ == '__main__':
12311244
'attach': attach,
12321245
'detach': detach,
12331246
'destroy': destroy,
1247+
'abortGc': abort_gc,
12341248

12351249
# vhdutil wrappers called by linstorvhdutil.
12361250
# Note: When a VHD is open in RO mode (so for all vhdutil getters),

drivers/linstorjournaler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def connect(uri):
153153
'Unable to find controller uri...'
154154
)
155155
return linstor.KV(
156-
LinstorVolumeManager._build_group_name(group_name),
156+
LinstorVolumeManager.build_group_name(group_name),
157157
uri=uri,
158158
namespace=namespace
159159
)

0 commit comments

Comments
 (0)