Change in vdsm[master]: WIP: Remove Vdsm's dependency on gluster-server package.

dnarayan at redhat.com dnarayan at redhat.com
Thu May 28 10:41:37 UTC 2015


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 <dnarayan at 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 <dnarayan at redhat.com>


More information about the vdsm-patches mailing list