]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
XIV volume manage/unmanage support
authorAlon Marx <alonma@il.ibm.com>
Sun, 13 Jul 2014 08:53:41 +0000 (11:53 +0300)
committerAlon Marx <alonma@il.ibm.com>
Tue, 15 Jul 2014 17:18:14 +0000 (20:18 +0300)
XIV support for managing and unmanaging volumes.

Partially Implements: blueprint add-export-import-volumes

Change-Id: I305d2652709181bacd9f5b21f0201858f91f7a15

cinder/tests/test_ibm_xiv_ds8k.py
cinder/volume/drivers/ibm/xiv_ds8k.py

index 1ce1d7eae1baf8bb664335773cffcf78f5c191a1..0716d380c4e7115c9d0de428287828c6b9f9605f 100644 (file)
@@ -32,6 +32,10 @@ FAKE = "fake"
 VOLUME = {'size': 16,
           'name': FAKE,
           'id': 1}
+MANAGED_FAKE = "managed_fake"
+MANAGED_VOLUME = {'size': 16,
+                  'name': MANAGED_FAKE,
+                  'id': 2}
 
 CONNECTOR = {'initiator': "iqn.2012-07.org.fake:01:948f189c4695", }
 
@@ -74,6 +78,20 @@ class XIVDS8KFakeProxyDriver(object):
         if self.volumes.get(volume['name'], None) is not None:
             del self.volumes[volume['name']]
 
+    def manage_volume_get_size(self, volume, existing_ref):
+        if self.volumes.get(existing_ref['existing_ref'], None) is None:
+            raise self.exception.VolumeNotFound(volume_id=volume['id'])
+        return self.volumes[existing_ref['existing_ref']]['size']
+
+    def manage_volume(self, volume, existing_ref):
+        if self.volumes.get(existing_ref['existing_ref'], None) is None:
+            raise self.exception.VolumeNotFound(volume_id=volume['id'])
+        volume['size'] = MANAGED_VOLUME['size']
+        return {}
+
+    def unmanage_volume(self, volume):
+        pass
+
     def initialize_connection(self, volume, connector):
         if not self.volume_exists(volume):
             raise self.exception.VolumeNotFound(volume_id=volume['id'])
@@ -248,3 +266,55 @@ class XIVDS8KVolumeDriverTest(test.TestCase):
                           self.driver.terminate_connection,
                           VOLUME,
                           CONNECTOR)
+
+    def test_manage_existing_get_size(self):
+        """Test that manage_existing_get_size returns the expected size. """
+
+        self.driver.do_setup(None)
+        self.driver.create_volume(MANAGED_VOLUME)
+        existing_ref = {'existing_ref': MANAGED_VOLUME['name']}
+        return_size = self.driver.manage_existing_get_size(
+            VOLUME,
+            existing_ref)
+        self.assertEqual(return_size, MANAGED_VOLUME['size'])
+
+        # cover both case, whether driver renames the volume or not
+        self.driver.delete_volume(VOLUME)
+        self.driver.delete_volume(MANAGED_VOLUME)
+
+    def test_manage_existing_get_size_should_fail_on_non_existing_volume(self):
+        """Test that manage_existing_get_size fails on non existing volume. """
+
+        self.driver.do_setup(None)
+        # on purpose - do NOT create managed volume
+        existing_ref = {'existing_ref': MANAGED_VOLUME['name']}
+        self.assertRaises(exception.VolumeNotFound,
+                          self.driver.manage_existing_get_size,
+                          VOLUME,
+                          existing_ref)
+
+    def test_manage_existing(self):
+        """Test that manage_existing returns successfully. """
+
+        self.driver.do_setup(None)
+        self.driver.create_volume(MANAGED_VOLUME)
+        existing_ref = {'existing_ref': MANAGED_VOLUME['name']}
+        has_volume = self.driver.manage_existing(
+            VOLUME,
+            existing_ref)
+        self.assertEqual(VOLUME['size'], MANAGED_VOLUME['size'])
+
+        # cover both case, whether driver renames the volume or not
+        self.driver.delete_volume(VOLUME)
+        self.driver.delete_volume(MANAGED_VOLUME)
+
+    def test_manage_existing_should_fail_on_non_existing_volume(self):
+        """Test that manage_existing fails on non existing volume. """
+
+        self.driver.do_setup(None)
+        # on purpose - do NOT create managed volume
+        existing_ref = {'existing_ref': MANAGED_VOLUME['name']}
+        self.assertRaises(exception.VolumeNotFound,
+                          self.driver.manage_existing,
+                          VOLUME,
+                          existing_ref)
index 179c5d6030658a930737bfb23fa50978677faea8..90ac836880edc8727fc6d7d570c927d10ec46151 100644 (file)
@@ -159,3 +159,45 @@ class XIVDS8KDriver(san.SanDriver):
         """Migrate the volume to the specified host."""
 
         return self.xiv_ds8k_proxy.migrate_volume(context, volume, host)
+
+    def manage_existing(self, volume, existing_ref):
+        """Brings an existing backend storage object under Cinder management.
+
+        existing_ref is passed straight through from the API request's
+        manage_existing_ref value, and it is up to the driver how this should
+        be interpreted.  It should be sufficient to identify a storage object
+        that the driver should somehow associate with the newly-created cinder
+        volume structure.
+        In the case of XIV, the existing_ref consists of a single field named
+        'existing_ref' representing the name of the volume on the storage.
+
+        There are two ways to do this:
+
+        1. Rename the backend storage object so that it matches the,
+           volume['name'] which is how drivers traditionally map between a
+           cinder volume and the associated backend storage object.
+
+        2. Place some metadata on the volume, or somewhere in the backend, that
+           allows other driver requests (e.g. delete, clone, attach, detach...)
+           to locate the backend storage object when required.
+
+        If the existing_ref doesn't make sense, or doesn't refer to an existing
+        backend storage object, raise a ManageExistingInvalidReference
+        exception.
+
+        The volume may have a volume_type, and the driver can inspect that and
+        compare against the properties of the referenced backend storage
+        object.  If they are incompatible, raise a
+        ManageExistingVolumeTypeMismatch, specifying a reason for the failure.
+        """
+        return self.xiv_ds8k_proxy.manage_volume(volume, existing_ref)
+
+    def manage_existing_get_size(self, volume, existing_ref):
+        """Return size of volume to be managed by manage_existing."""
+
+        return self.xiv_ds8k_proxy.manage_volume_get_size(volume, existing_ref)
+
+    def unmanage(self, volume):
+        """Removes the specified volume from Cinder management."""
+
+        return self.xiv_ds8k_proxy.unmanage_volume(volume)