]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Adds volume replication methods to xiv/ds8k driver interface.
authorJason Ni <jason.ni.py@gmail.com>
Mon, 25 Aug 2014 05:14:54 +0000 (08:14 +0300)
committerJason Ni <jason.ni.py@gmail.com>
Mon, 25 Aug 2014 08:57:28 +0000 (11:57 +0300)
Change-Id: I99add7e562d7b5e8f14b186f7c705209af27f6a2

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

index 64bb53d562aa3689e8349ae55839fa359c6f18a7..ef4baf65fe1db1fb4c8539537f1090d3c140775c 100644 (file)
@@ -19,6 +19,8 @@
 #   Avishay Traeger <avishay@il.ibm.com>
 
 
+import copy
+
 import mox
 from oslo.config import cfg
 
@@ -33,11 +35,19 @@ FAKE = "fake"
 VOLUME = {'size': 16,
           'name': FAKE,
           'id': 1}
+
 MANAGED_FAKE = "managed_fake"
 MANAGED_VOLUME = {'size': 16,
                   'name': MANAGED_FAKE,
                   'id': 2}
 
+REPLICA_FAKE = "repicated_fake"
+REPLICATED_VOLUME = {'size': 64,
+                     'name': REPLICA_FAKE,
+                     'id': 2}
+
+CONTEXT = {}
+
 CONNECTOR = {'initiator': "iqn.2012-07.org.fake:01:948f189c4695", }
 
 CONF = cfg.CONF
@@ -130,6 +140,32 @@ class XIVDS8KFakeProxyDriver(object):
         return (self.volumes[volume['name']].get('attached', None)
                 == connector)
 
+    def reenable_replication(self, context, volume):
+        model_update = {}
+        if volume['replication_status'] == 'inactive':
+            model_update['replication_status'] = 'active'
+        elif volume['replication_status'] == 'invalid_status_val':
+            raise exception.CinderException()
+        model_update['replication_extended_status'] = 'some_status'
+        model_update['replication_driver_data'] = 'some_data'
+        return model_update
+
+    def get_replication_status(self, context, volume):
+        if volume['replication_status'] == 'invalid_status_val':
+            raise exception.CinderException()
+        return {'replication_status': 'active'}
+
+    def promote_replica(self, context, volume):
+        if volume['replication_status'] == 'invalid_status_val':
+            raise exception.CinderException()
+        return {'replication_status': 'inactive'}
+
+    def create_replica_test_volume(self, volume, src_vref):
+        if volume['size'] != src_vref['size']:
+            raise exception.InvalidVolume(
+                reason="Target and source volumes have different size.")
+        return
+
 
 class XIVDS8KVolumeDriverTest(test.TestCase):
     """Test IBM XIV and DS8K volume driver."""
@@ -317,3 +353,130 @@ class XIVDS8KVolumeDriverTest(test.TestCase):
                           self.driver.manage_existing,
                           VOLUME,
                           existing_ref)
+
+    def test_reenable_replication(self):
+        """Test that reenable_replication returns successfully. """
+
+        self.driver.do_setup(None)
+        # assume the replicated volume is inactive
+        replicated_volume = copy.deepcopy(REPLICATED_VOLUME)
+        replicated_volume['replication_status'] = 'inactive'
+        model_update = self.driver.reenable_replication(
+            CONTEXT,
+            replicated_volume
+        )
+        self.assertEqual(
+            model_update['replication_status'],
+            'active'
+        )
+        self.assertTrue('replication_extended_status' in model_update)
+        self.assertTrue('replication_driver_data' in model_update)
+
+    def test_reenable_replication_fail_on_cinder_exception(self):
+        """Test that reenable_replication fails on driver raising exception."""
+
+        self.driver.do_setup(None)
+
+        replicated_volume = copy.deepcopy(REPLICATED_VOLUME)
+        # on purpose - set invalid value to replication_status
+        # expect an exception.
+        replicated_volume['replication_status'] = 'invalid_status_val'
+        self.assertRaises(
+            exception.CinderException,
+            self.driver.reenable_replication,
+            CONTEXT,
+            replicated_volume
+        )
+
+    def test_get_replication_status(self):
+        """Test that get_replication_status return successfully. """
+
+        self.driver.do_setup(None)
+
+        # assume the replicated volume is inactive
+        replicated_volume = copy.deepcopy(REPLICATED_VOLUME)
+        replicated_volume['replication_status'] = 'inactive'
+        model_update = self.driver.get_replication_status(
+            CONTEXT,
+            replicated_volume
+        )
+        self.assertEqual(
+            model_update['replication_status'],
+            'active'
+        )
+
+    def test_get_replication_status_fail_on_exception(self):
+        """Test that get_replication_status fails on exception"""
+
+        self.driver.do_setup(None)
+
+        replicated_volume = copy.deepcopy(REPLICATED_VOLUME)
+        # on purpose - set invalid value to replication_status
+        # expect an exception.
+        replicated_volume['replication_status'] = 'invalid_status_val'
+        self.assertRaises(
+            exception.CinderException,
+            self.driver.get_replication_status,
+            CONTEXT,
+            replicated_volume
+        )
+
+    def test_promote_replica(self):
+        """Test that promote_replica returns successfully. """
+
+        self.driver.do_setup(None)
+
+        replicated_volume = copy.deepcopy(REPLICATED_VOLUME)
+        # assume the replication_status should be active
+        replicated_volume['replication_status'] = 'active'
+        model_update = self.driver.promote_replica(
+            CONTEXT,
+            replicated_volume
+        )
+        # after promoting, replication_status should be inactive
+        self.assertEqual(
+            model_update['replication_status'],
+            'inactive'
+        )
+
+    def test_promote_replica_fail_on_cinder_exception(self):
+        """Test that promote_replica fails on CinderException. """
+
+        self.driver.do_setup(None)
+
+        replicated_volume = copy.deepcopy(REPLICATED_VOLUME)
+        # on purpose - set invalid value to replication_status
+        # expect an exception.
+        replicated_volume['replication_status'] = 'invalid_status_val'
+        self.assertRaises(
+            exception.CinderException,
+            self.driver.promote_replica,
+            CONTEXT,
+            replicated_volume
+        )
+
+    def test_create_replica_test_volume(self):
+        """Test that create_replica_test_volume returns successfully."""
+
+        self.driver.do_setup(None)
+        tgt_volume = copy.deepcopy(VOLUME)
+        src_volume = copy.deepcopy(REPLICATED_VOLUME)
+        tgt_volume['size'] = src_volume['size']
+        model_update = self.driver.create_replica_test_volume(
+            tgt_volume,
+            src_volume
+        )
+        self.assertTrue(model_update is None)
+
+    def test_create_replica_test_volume_fail_on_diff_size(self):
+        """Test that create_replica_test_volume fails on diff size."""
+
+        self.driver.do_setup(None)
+        tgt_volume = copy.deepcopy(VOLUME)
+        src_volume = copy.deepcopy(REPLICATED_VOLUME)
+        self.assertRaises(
+            exception.InvalidVolume,
+            self.driver.create_replica_test_volume,
+            tgt_volume,
+            src_volume
+        )
index 90ac836880edc8727fc6d7d570c927d10ec46151..3ec94b500b91d904d824a89ea8af66142c599ec4 100644 (file)
@@ -64,10 +64,10 @@ class XIVDS8KDriver(san.SanDriver):
 
         proxy = importutils.import_class(self.configuration.xiv_ds8k_proxy)
 
-        #NOTE: All Array specific configurations are prefixed with:
-        #"xiv_ds8k_array_"
-        #These additional flags should be specified in the cinder.conf
-        #preferably in each backend configuration.
+        # NOTE: All Array specific configurations are prefixed with:
+        # "xiv_ds8k_array_"
+        # These additional flags should be specified in the cinder.conf
+        # preferably in each backend configuration.
 
         self.xiv_ds8k_proxy = proxy(
             {
@@ -201,3 +201,23 @@ class XIVDS8KDriver(san.SanDriver):
         """Removes the specified volume from Cinder management."""
 
         return self.xiv_ds8k_proxy.unmanage_volume(volume)
+
+    def reenable_replication(self, context, volume):
+        """Re-enable volume replication. """
+
+        return self.xiv_ds8k_proxy.reenable_replication(context, volume)
+
+    def get_replication_status(self, context, volume):
+        """Return replication status."""
+
+        return self.xiv_ds8k_proxy.get_replication_status(context, volume)
+
+    def promote_replica(self, context, volume):
+        """Promote the replica to be the primary volume."""
+
+        return self.xiv_ds8k_proxy.promote_replica(context, volume)
+
+    def create_replica_test_volume(self, volume, src_vref):
+        """Creates a test replica clone of the specified replicated volume."""
+
+        return self.xiv_ds8k_proxy.create_replica_test_volume(volume, src_vref)