Darshan N has uploaded a new change for review. Change subject: WIP: Remove Vdsm's dependency on gluster-server package. ......................................................................
WIP: Remove Vdsm's dependency on gluster-server package. In this patch have segregated the glusterVolumeInfo code such that, vdsm package will not be dependent on vdsm-gluster in turn gluster-server. Pending: suitable spec file changes. Change-Id: I43c8f16e8171693d1bbbff40198c59646022603e Signed-off-by: Darshan N <dnara...@redhat.com> --- M tests/functional/networkTests.py M tests/gluster_cli_tests.py M vdsm.spec.in M vdsm/gluster/cli.py M vdsm/storage/Makefile.am A vdsm/storage/glusterUtils.py M vdsm/storage/glusterVolume.py M vdsm/supervdsmServer 8 files changed, 157 insertions(+), 84 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/68/41568/1 diff --git a/tests/functional/networkTests.py b/tests/functional/networkTests.py index 553f479..f70bedc 100644 --- a/tests/functional/networkTests.py +++ b/tests/functional/networkTests.py @@ -90,7 +90,7 @@ @RequireDummyMod def setupModule(): """Persists network configuration.""" - vdsm = VdsProxy() + # vdsm = VdsProxy() vdsm.save_config() for _ in range(DUMMY_POOL_SIZE): dummyPool.add(dummy.create()) @@ -98,7 +98,7 @@ def tearDownModule(): """Restores the network configuration previous to running tests.""" - vdsm = VdsProxy() + # vdsm = VdsProxy() vdsm.restoreNetConfig() for nic in dummyPool: dummy.remove(nic) diff --git a/tests/gluster_cli_tests.py b/tests/gluster_cli_tests.py index dfbb79a..5e6636a 100644 --- a/tests/gluster_cli_tests.py +++ b/tests/gluster_cli_tests.py @@ -20,6 +20,7 @@ from testlib import VdsmTestCase as TestCaseBase from gluster import cli as gcli +from storage import glusterUtils as gu import xml.etree.cElementTree as etree from nose.plugins.skip import SkipTest import glusterTestData @@ -38,7 +39,7 @@ </cliOutput> """ tree = etree.fromstring(out) - self.assertFalse(gcli._parseVolumeInfo(tree)) + self.assertFalse(gu.parseVolumeInfo(tree)) def _parseVolumeInfo_test(self): out = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?> @@ -123,10 +124,10 @@ 'stripeCount': '1', 'disperseCount': '0', 'redundancyCount': '0', - 'transportType': [gcli.TransportType.TCP], + 'transportType': [gu.TransportType.TCP], 'uuid': 'b3114c71-741b-4c6f-a39e-80384c4ea3cf', 'volumeName': 'music', - 'volumeStatus': gcli.VolumeStatus.ONLINE, + 'volumeStatus': gu.VolumeStatus.ONLINE, 'volumeType': 'REPLICATE'}, 'test1': {'brickCount': '1', 'bricks': ['192.168.122.2:/tmp/t_b1'], @@ -140,12 +141,12 @@ 'stripeCount': '1', 'disperseCount': '0', 'redundancyCount': '0', - 'transportType': [gcli.TransportType.RDMA], + 'transportType': [gu.TransportType.RDMA], 'uuid': 'b444ed94-f346-4cda-bd55-0282f21d22db', 'volumeName': 'test1', - 'volumeStatus': gcli.VolumeStatus.OFFLINE, + 'volumeStatus': gu.VolumeStatus.OFFLINE, 'volumeType': 'DISTRIBUTE'}} - volumeInfo = gcli._parseVolumeInfo(tree) + volumeInfo = gu.parseVolumeInfo(tree) self.assertEquals(volumeInfo, oVolumeInfo) def test_parseVolumeInfo(self): diff --git a/vdsm.spec.in b/vdsm.spec.in index 5937398..5c99188 100644 --- a/vdsm.spec.in +++ b/vdsm.spec.in @@ -1153,6 +1153,7 @@ %{_datadir}/%{vdsm_name}/storage/fileVolume.py* %{_datadir}/%{vdsm_name}/storage/fuser.py* %{_datadir}/%{vdsm_name}/storage/glusterSD.py* +%{_datadir}/%{vdsm_name}/storage/glusterUtils.py* %{_datadir}/%{vdsm_name}/storage/glusterVolume.py* %{_datadir}/%{vdsm_name}/storage/hba.py* %{_datadir}/%{vdsm_name}/storage/hsm.py* diff --git a/vdsm/gluster/cli.py b/vdsm/gluster/cli.py index d53a1c8..0d3f041 100644 --- a/vdsm/gluster/cli.py +++ b/vdsm/gluster/cli.py @@ -27,6 +27,7 @@ import exception as ge from hostname import getHostNameFqdn, HostNameException from . import makePublic +from storage import glusterUtils as gu _glusterCommandPath = utils.CommandPath("gluster", "/usr/sbin/gluster", @@ -41,15 +42,15 @@ def _getGlusterVolCmd(): - return [_glusterCommandPath.cmd, "--mode=script", "volume"] + return [gu.glusterCommandPath.cmd, "--mode=script", "volume"] def _getGlusterPeerCmd(): - return [_glusterCommandPath.cmd, "--mode=script", "peer"] + return [gu.glusterCommandPath.cmd, "--mode=script", "peer"] def _getGlusterSystemCmd(): - return [_glusterCommandPath.cmd, "system::"] + return [gu.glusterCommandPath.cmd, "system::"] def _getGlusterVolGeoRepCmd(): @@ -57,7 +58,7 @@ def _getGlusterSnapshotCmd(): - return [_glusterCommandPath.cmd, "--mode=script", "snapshot"] + return [gu.glusterCommandPath.cmd, "--mode=script", "snapshot"] class BrickStatus: @@ -72,16 +73,6 @@ CONNECTED = 'CONNECTED' DISCONNECTED = 'DISCONNECTED' UNKNOWN = 'UNKNOWN' - - -class VolumeStatus: - ONLINE = 'ONLINE' - OFFLINE = 'OFFLINE' - - -class TransportType: - TCP = 'TCP' - RDMA = 'RDMA' class TaskType: @@ -357,64 +348,6 @@ raise ge.GlusterXmlErrorException(err=[etree.tostring(xmltree)]) -def _parseVolumeInfo(tree): - """ - {VOLUMENAME: {'brickCount': BRICKCOUNT, - 'bricks': [BRICK1, BRICK2, ...], - 'options': {OPTION: VALUE, ...}, - 'transportType': [TCP,RDMA, ...], - 'uuid': UUID, - 'volumeName': NAME, - 'volumeStatus': STATUS, - 'volumeType': TYPE, - 'disperseCount': DISPERSE_COUNT, - 'redundancyCount': REDUNDANCY_COUNT}, ...} - """ - volumes = {} - for el in tree.findall('volInfo/volumes/volume'): - value = {} - value['volumeName'] = el.find('name').text - value['uuid'] = el.find('id').text - value['volumeType'] = el.find('typeStr').text.upper().replace('-', '_') - status = el.find('statusStr').text.upper() - if status == 'STARTED': - value["volumeStatus"] = VolumeStatus.ONLINE - else: - value["volumeStatus"] = VolumeStatus.OFFLINE - value['brickCount'] = el.find('brickCount').text - value['distCount'] = el.find('distCount').text - value['stripeCount'] = el.find('stripeCount').text - value['replicaCount'] = el.find('replicaCount').text - value['disperseCount'] = el.find('disperseCount').text - value['redundancyCount'] = el.find('redundancyCount').text - transportType = el.find('transport').text - if transportType == '0': - value['transportType'] = [TransportType.TCP] - elif transportType == '1': - value['transportType'] = [TransportType.RDMA] - else: - value['transportType'] = [TransportType.TCP, TransportType.RDMA] - value['bricks'] = [] - value['options'] = {} - value['bricksInfo'] = [] - for b in el.findall('bricks/brick'): - value['bricks'].append(b.text) - for o in el.findall('options/option'): - value['options'][o.find('name').text] = o.find('value').text - for d in el.findall('bricks/brick'): - brickDetail = {} - # this try block is to maintain backward compatibility - # it returns an empty list when gluster doesnot return uuid - try: - brickDetail['name'] = d.find('name').text - brickDetail['hostUuid'] = d.find('hostUuid').text - value['bricksInfo'].append(brickDetail) - except AttributeError: - break - volumes[value['volumeName']] = value - return volumes - - def _parseVolumeProfileInfo(tree, nfs): bricks = [] if nfs: @@ -493,7 +426,7 @@ except ge.GlusterCmdFailedException as e: raise ge.GlusterVolumesListFailedException(rc=e.rc, err=e.err) try: - return _parseVolumeInfo(xmltree) + return gu.parseVolumeInfo(xmltree) except _etreeExceptions: raise ge.GlusterXmlErrorException(err=[etree.tostring(xmltree)]) diff --git a/vdsm/storage/Makefile.am b/vdsm/storage/Makefile.am index 4ebe0a2..fb32d83 100644 --- a/vdsm/storage/Makefile.am +++ b/vdsm/storage/Makefile.am @@ -36,6 +36,7 @@ fileVolume.py \ fuser.py \ glusterSD.py \ + glusterUtils.py \ glusterVolume.py \ hba.py \ hsm.py \ diff --git a/vdsm/storage/glusterUtils.py b/vdsm/storage/glusterUtils.py new file mode 100644 index 0000000..bde3722 --- /dev/null +++ b/vdsm/storage/glusterUtils.py @@ -0,0 +1,132 @@ +import xml.etree.cElementTree as etree + +from vdsm import utils +from vdsm.exception import VdsmException + + +glusterCommandPath = utils.CommandPath("gluster", + "/usr/sbin/gluster",) + +if hasattr(etree, 'ParseError'): + _etreeExceptions = (etree.ParseError, AttributeError, ValueError) +else: + _etreeExceptions = (SyntaxError, AttributeError, ValueError) + + +class VolumeStatus: + ONLINE = 'ONLINE' + OFFLINE = 'OFFLINE' + + +class TransportType: + TCP = 'TCP' + RDMA = 'RDMA' + + +class GlusterVolumeInfoFailedException(VdsmException): + message = "Gluster volume info command failed" + + def __init__(self, rc=0, out=(), err=()): + self.rc = rc + self.out = out + self.err = err + + def __str__(self): + o = '\n'.join(self.out) + e = '\n'.join(self.err) + if o and e: + m = o + '\n' + e + else: + m = o or e + + s = self.message + if m: + s += '\nerror: ' + m + if self.rc: + s += '\nreturn code: %s' % self.rc + + return s + + +def parseVolumeInfo(tree): + """ + {VOLUMENAME: {'brickCount': BRICKCOUNT, + 'bricks': [BRICK1, BRICK2, ...], + 'options': {OPTION: VALUE, ...}, + 'transportType': [TCP,RDMA, ...], + 'uuid': UUID, + 'volumeName': NAME, + 'volumeStatus': STATUS, + 'volumeType': TYPE, + 'disperseCount': DISPERSE_COUNT, + 'redundancyCount': REDUNDANCY_COUNT}, ...} + """ + volumes = {} + for el in tree.findall('volInfo/volumes/volume'): + value = {} + value['volumeName'] = el.find('name').text + value['uuid'] = el.find('id').text + value['volumeType'] = el.find('typeStr').text.upper().replace('-', '_') + status = el.find('statusStr').text.upper() + if status == 'STARTED': + value["volumeStatus"] = VolumeStatus.ONLINE + else: + value["volumeStatus"] = VolumeStatus.OFFLINE + value['brickCount'] = el.find('brickCount').text + value['distCount'] = el.find('distCount').text + value['stripeCount'] = el.find('stripeCount').text + value['replicaCount'] = el.find('replicaCount').text + value['disperseCount'] = el.find('disperseCount').text + value['redundancyCount'] = el.find('redundancyCount').text + transportType = el.find('transport').text + if transportType == '0': + value['transportType'] = [TransportType.TCP] + elif transportType == '1': + value['transportType'] = [TransportType.RDMA] + else: + value['transportType'] = [TransportType.TCP, TransportType.RDMA] + value['bricks'] = [] + value['options'] = {} + value['bricksInfo'] = [] + for b in el.findall('bricks/brick'): + value['bricks'].append(b.text) + for o in el.findall('options/option'): + value['options'][o.find('name').text] = o.find('value').text + for d in el.findall('bricks/brick'): + brickDetail = {} + # this try block is to maintain backward compatibility + # it returns an empty list when gluster doesnot return uuid + try: + brickDetail['name'] = d.find('name').text + brickDetail['hostUuid'] = d.find('hostUuid').text + value['bricksInfo'].append(brickDetail) + except AttributeError: + break + volumes[value['volumeName']] = value + return volumes + + +def volumeInfo(remoteServer, volumeName=None): + command = [glusterCommandPath.cmd, "--mode=script", "volume", + "info"] + ['--remote-host=%s' % remoteServer] + if volumeName: + command.append(volumeName) + command.append("--xml") + rc, out, err = utils.execCmd(command) + if rc != 0: + raise GlusterVolumeInfoFailedException(rc, out, err) + try: + tree = etree.fromstring('\n'.join(out)) + rv = int(tree.find('opRet').text) + msg = tree.find('opErrstr').text + errNo = int(tree.find('opErrno').text) + except _etreeExceptions: + raise GlusterVolumeInfoFailedException(err=out) + if rv != 0: + if errNo != 0: + rv = errNo + raise GlusterVolumeInfoFailedException(rc=rv, err=[msg]) + try: + return parseVolumeInfo(tree) + except _etreeExceptions: + raise GlusterVolumeInfoFailedException(err=[etree.tostring(tree)]) diff --git a/vdsm/storage/glusterVolume.py b/vdsm/storage/glusterVolume.py index 647b1ec..910b22f 100644 --- a/vdsm/storage/glusterVolume.py +++ b/vdsm/storage/glusterVolume.py @@ -3,7 +3,7 @@ from sdc import sdCache import supervdsm as svdsm try: - from gluster.exception import GlusterException + from glusterUtils import GlusterVolumeInfoFailedException _glusterEnabled = True except ImportError: _glusterEnabled = False @@ -31,9 +31,9 @@ svdsmProxy = svdsm.getProxy() try: - volInfo = svdsmProxy.glusterVolumeInfo(volname, volfileServer) + volInfo = svdsmProxy.volumeInfo(volname, volfileServer) volTrans = VOLUME_TRANS_MAP[volInfo[volname]['transportType'][0]] - except GlusterException: + except GlusterVolumeInfoFailedException: # In case of issues with finding transport type, default to tcp self.log.warning("Unable to find transport type for GlusterFS" " volume %s. GlusterFS server = %s." diff --git a/vdsm/supervdsmServer b/vdsm/supervdsmServer index ef7a710..53e80f2 100755 --- a/vdsm/supervdsmServer +++ b/vdsm/supervdsmServer @@ -68,6 +68,7 @@ from storage.iscsi import readSessionInfo as _readSessionInfo from supervdsm import _SuperVdsmManager from storage import hba +from storage import glusterUtils from storage.fileUtils import chown, resolveGid, resolveUid from storage.fileUtils import validateAccess as _validateAccess from vdsm.constants import METADATA_GROUP, EXT_CHOWN, EXT_UDEVADM, \ @@ -419,6 +420,10 @@ sysctl.set_rp_filter_loose(dev) @logDecorator + def volumeInfo(self, remoteServer, volumeName=None): + return glusterUtils.volumeInfo(remoteServer, volumeName) + + @logDecorator def set_rp_filter_strict(self, dev): sysctl.set_rp_filter_strict(dev) -- To view, visit https://gerrit.ovirt.org/41568 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I43c8f16e8171693d1bbbff40198c59646022603e Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: master Gerrit-Owner: Darshan N <dnara...@redhat.com> _______________________________________________ vdsm-patches mailing list vdsm-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches