Change in vdsm[master]: storage: WIP: Add support for Storage Array management using...

deepakcs at linux.vnet.ibm.com deepakcs at linux.vnet.ibm.com
Thu Apr 18 11:11:23 UTC 2013


Deepak C Shetty has uploaded a new change for review.

Change subject: storage: WIP: Add support for Storage Array management using libstoragemgmt
......................................................................

storage: WIP: Add support for Storage Array management using libstoragemgmt

NOTE: This is a WIP patch.

Use libstoragemgmt (libSM) to provide ability to manage Storage Arrays in
a vendor neutral way.

In future, we can look at adding a specialised storage domain to exploit
array offload capabilities, so that VDSM can create and offload vmdisk
operations to the array, using libSM.

Change-Id: I449e51f2532d8ed47460b5e53653f880b36672cf
Signed-off-by: Deepak C Shetty <deepakcs at linux.vnet.ibm.com>
---
M vdsm/API.py
M vdsm/BindingXMLRPC.py
A vdsm/storage/array.py
M vdsm/storage/hsm.py
4 files changed, 224 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/33/14033/1

diff --git a/vdsm/API.py b/vdsm/API.py
index ee72116..cda652a 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -1026,6 +1026,63 @@
         return self._irs.removeVM(self._UUID, vmUUID, sdUUID)
 
 
+class StorageArray(APIBase):
+    """
+    This class represents a Storage Array.
+
+    VDSM will use libstoragemgmt (libSM) to provide ability to work with
+    Storage array in a vendor nuetral way.
+
+    More detauls about libSM, its APIs, how it works can be found @
+    http://sourceforge.net/p/libstoragemgmt/wiki/Home/
+    """
+
+    def __init__(self, UUID):
+        APIBase.__init__(self)
+        self._UUID = UUID
+
+    def connect(self, conInfo, options):
+        # conInfo: has stuff to connect to array. id, user, pass
+        # options: has stuff that maps to libSM: Options. eg: -w for timeout
+        #          other libSM:Options don't make sense for this API
+        # returns: the system info (libSM: -l SYSTEMS), as a dict
+        return self._irs.connectStorageArray(self._UUID, conInfo, options)
+
+    def getSystemInfo(self, cmd_options, options):
+        # options: has stuff that maps to libSM: Options. eg. -H, -t SEP etc
+        # cmd_options: has stuff that maps to libSM: Command Options
+        #              eg: --size, --pool etc
+        # returns: libSM: -l SYSTEMS
+        return self._irs.arrayGetSystemInfo(self._UUID, cmd_options, options)
+
+    def getPluginInfo(self, cmd_options, options):
+        # return: libSM: --plugin-info
+        return self._irs.arrayGetPlugInfo(self._UUID, cmd_options, options)
+
+    def getPools(self, cmd_options, options):
+        # return: libSM: -l POOLS
+        self._irs.arrayGetPools(self._UUID, cmd_options, options)
+
+    def getVolumes(self, cmd_options, options):
+        # return: libSM: -l VOLUMES
+        return self._irs.arrayGetVolumes(self._UUID, cmd_options, options)
+
+    def getCapabilities(self, system_id, cmd_options, options):
+        # return: libSM: --capabilities=system-id
+        return self._irs.arrayGetCapabilities(self._UUID, system_id,
+                                              cmd_options, options)
+
+    def createVolume(self, volname, cmd_options, options):
+        # return: libSM: --create-volume=volname
+        return self._irs.arrayCreateVolume(self._UUID, volname, cmd_options,
+                                           options)
+
+    def deleteVolume(self, volID, cmd_options, options):
+        # return: libSM: --delete-volume=volID
+        return self._irs.arrayDeleteVolume(self._UUID, volID, cmd_options,
+                                           options)
+
+
 class Global(APIBase):
     ctorArgs = []
 
@@ -1456,3 +1513,9 @@
                 logging.warn("options %s is deprecated. Use %s instead" %
                              (k, _translationMap[k]))
                 options[_translationMap[k]] = options.pop(k)
+
+    # libSM doesn't have support for this yet!
+    def getSupportedArrays(self):
+        # libSM should iterate thru each of the plugins
+        # and return the plugin desc & protocol info
+        pass
diff --git a/vdsm/BindingXMLRPC.py b/vdsm/BindingXMLRPC.py
index 9a4db12..1a7a853 100644
--- a/vdsm/BindingXMLRPC.py
+++ b/vdsm/BindingXMLRPC.py
@@ -765,6 +765,30 @@
     def storageServerConnectionRefsStatuses(self):
         return API.ConnectionRefs().statuses()
 
+    def arrayConnect(self, saUUID, conInfo, options=None):
+        return API.StorageArray(saUUID).connect(conInfo, options)
+
+    def arrayGetSystemInfo(self, saUUID, cmd_options=None, options=None):
+        return API.StorageArray(saUUID).getSystemInfo(cmd_options, options)
+
+    def arrayGetPluginInfo(self, saUUID, cmd_options=None, options=None):
+        return API.StorageArray(saUUID).getPluginInfo(cmd_options, options)
+
+    def arrayGetPools(self, saUUID, cmd_options, options=None):
+        return API.StorageArray(saUUID).getPools(cmd_options, options)
+
+    def arrayGetVolumes(self, saUUID, cmd_options, options=None):
+        return API.StorageArray(saUUID).getVolumes(cmd_options, options)
+
+    def arrayGetCaps(self, saUUID, sys_id, cmd_options, options=None):
+        return API.StorageArray(saUUID).getCapabilities(sys_id, cmd_options, options)
+
+    def arrayCreateVolume(self, saUUID, volName, cmd_options, options=None):
+        return API.StorageArray(saUUID).createVolume(volName, cmd_options, options)
+
+    def arrayDeleteVolume(self, volID, cmd_options, options=None):
+        return API.StorageArray(saUUID).deleteVolume(volID, cmd_options, options)
+
     def getGlobalMethods(self):
         return ((self.vmDestroy, 'destroy'),
                 (self.vmCreate, 'create'),
@@ -897,7 +921,15 @@
                 (self.storageServerConnectionRefsRelease,
                  'storageServer_ConnectionRefs_release'),
                 (self.storageServerConnectionRefsStatuses,
-                 'storageServer_ConnectionRefs_statuses'),)
+                 'storageServer_ConnectionRefs_statuses'),
+                (self.arrayConnect, 'connectStorageArray'),
+                (self.arrayGetSystemInfo, 'getArraySystemInfo'),
+                (self.arrayGetPluginInfo, 'getArrayPluginInfo'),
+                (self.arrayGetPools, 'getArrayPools'),
+                (self.arrayGetVolumes, 'getArrayVolumes'),
+                (self.arrayGetCaps, 'getArrayCaps'),
+                (self.arrayCreateVolume, 'arrayCreateVolume'),
+                (self.arrayDeleteVolume, 'arrayDeleteVolume'),)
 
 
 def wrapApiMethod(f):
diff --git a/vdsm/storage/array.py b/vdsm/storage/array.py
new file mode 100644
index 0000000..655af7f
--- /dev/null
+++ b/vdsm/storage/array.py
@@ -0,0 +1,67 @@
+import lsm
+import sys
+
+# Array types
+TYPE_SAN = 0
+TYPE_NAS = 1
+TYPE_UNIFIED = 2
+
+ARRAY_TYPES = {TYPE_SAN: "SAN", TYPE_NAS: "NAS", TYPE_UNIFIED: "UNIFIED"}
+
+
+class Array(object):
+    def __init__(self, uuid, uri, plain_text_passwd=None,
+                 timeout_ms=30000, flags=0):
+        self.uuid = uuid
+        self.client = lsm.Client(uri, plain_text_passwd, timeout_ms, flags)
+        # TODO: Persist array metadata, so that this can be re-constructed
+        #       post vdsm restart, system reboot etc
+
+    def getSystemInfo(self, flags=0):
+        # Assume 1 system being managed
+        # TODO: Return a custom dict, after deciphering data from lsm
+        #       returned data types
+        return self.client.systems(flags)
+
+    def getPluginInfo(self, flags=0):
+        # TODO: Return a custom dict, after deciphering data from lsm
+        #       returned data types
+        return self.client.plugin_info(flags)
+
+    def getPools(self, flags=0):
+        # TODO: Return a custom dict, after deciphering data from lsm
+        #       returned data types
+        return self.client.pools(flags)
+
+    def getVolumes(self, flags=0):
+        # TODO: Return a custom dict, after deciphering data from lsm
+        #       returned data types
+        self.client.volumes(flags)
+
+    def getCapabilities(self, system_id, flags=0):
+        # TODO: Assert system_id == self.id, otherwise return error
+        # Assume 1 system being managed
+        # TODO: Return a custom dict, after deciphering data from lsm
+        #       returned data types
+        return self.client.capabilities(self.getSystemInfo()[0], flags)
+
+    def createVolume(self, volname, cmd_options, options, flags=0):
+        # TODO: Return a custom dict, after deciphering data from lsm
+        #       returned data types
+        return self.client.volume_create(cmd_options['pool'], volname,
+                                  cmd_options['size'], cmd_options['prov'],
+                                  flags)
+
+    def deleteVolume(self, volID, cmd_options, options, flags=0):
+        # TODO: Return a custom dict, after deciphering data from lsm
+        #       returned data types
+        vols = self.getVolumes()
+        dvol = None
+        for vol in vols:
+            if(vol.id == volID):
+                dvol = vol
+                break
+        # TODO: Raise error if dvol is None
+        return self.client.volume_delete(dvol, flags)
+
+
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index ae35b11..be1e210 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -69,6 +69,9 @@
 import supervdsm
 import storageServer
 from vdsm import utils
+import array
+# TODO: Add arrayCache framework similar to sdCache
+from arrayc import arrayCache
 
 GUID = "guid"
 NAME = "name"
@@ -3417,3 +3420,61 @@
                 result[d] = repo_stats[d]['result']
 
         return result
+
+    @public
+    def connectStorageArray(self, saUUID, conInfo, options):
+        scheme = conInfo['scheme']
+        user = conInfo['user']
+        passwd = conInfo['passwd']
+        hostname = conInfo['hostname']
+
+        uri = scheme + '://' + user + '@' + hostname
+        sa = None
+        timeout_ms = None
+
+        if options:
+            if options.has_key('timeout_secs'):
+                timeout_ms = options['timeout_secs'] * 1000
+
+        if timeout_ms:
+            sa = array.Array(saUUID, uri, passwd, timeout_ms)
+        else:
+            sa = array.Array(saUUID, uri, passwd)
+
+        # TODO: Add arrayCache framework and put the sa into it
+        return sa.getSystemInfo()
+
+    @public
+    def arrayGetSystemInfo(self, saUUID, cmd_options, options):
+        sa = arrayCache.produce(saUUID)
+        return sa.getSystemInfo()
+
+    @public
+    def arrayGetPlugInfo(self, saUUID, cmd_options, options):
+       sa = arrayCache.produce(saUUID)
+       return sa.getPluginInfo()
+
+    @public
+    def arrayGetPools(self, saUUID, cmd_options, options):
+        sa = arrayCache.produce(saUUID)
+        return sa.getPools()
+
+    @public
+    def arrayGetVolumes(self, saUUID, cmd_options, options):
+        sa = arrayCache.produce(saUUID)
+        return sa.getVolumes()
+
+    @public
+    def arrayGetCapabilities(self, saUUID, system_id, cmd_options, options):
+        sa = arrayCache.produce(saUUID)
+        return sa.getCapabilities(system_id)
+
+    @public
+    def arrayCreateVolume(self, saUUID, volname, cmd_options, options):
+        sa = arrayCache.produce(saUUID)
+        return sa.createVolume(volname)
+
+    @public
+    def arrayDeleteVolume(self, saUUID, volID, cmd_options, options):
+        sa = arrayCache.produce(saUUID)
+        return sa.deleteVolume(volID)


--
To view, visit http://gerrit.ovirt.org/14033
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I449e51f2532d8ed47460b5e53653f880b36672cf
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Deepak C Shetty <deepakcs at linux.vnet.ibm.com>


More information about the vdsm-patches mailing list