From: Alon Marx Date: Sun, 13 Jul 2014 08:53:41 +0000 (+0300) Subject: XIV volume manage/unmanage support X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=65902674a95847490489c047dac465fa08c0a483;p=openstack-build%2Fcinder-build.git XIV volume manage/unmanage support XIV support for managing and unmanaging volumes. Partially Implements: blueprint add-export-import-volumes Change-Id: I305d2652709181bacd9f5b21f0201858f91f7a15 --- diff --git a/cinder/tests/test_ibm_xiv_ds8k.py b/cinder/tests/test_ibm_xiv_ds8k.py index 1ce1d7eae..0716d380c 100644 --- a/cinder/tests/test_ibm_xiv_ds8k.py +++ b/cinder/tests/test_ibm_xiv_ds8k.py @@ -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) diff --git a/cinder/volume/drivers/ibm/xiv_ds8k.py b/cinder/volume/drivers/ibm/xiv_ds8k.py index 179c5d603..90ac83688 100644 --- a/cinder/volume/drivers/ibm/xiv_ds8k.py +++ b/cinder/volume/drivers/ibm/xiv_ds8k.py @@ -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)