diff --git a/cinder/tests/unit/volume/drivers/disco/test_manage_existing.py b/cinder/tests/unit/volume/drivers/disco/test_manage_existing.py new file mode 100644 index 00000000000..c0366978011 --- /dev/null +++ b/cinder/tests/unit/volume/drivers/disco/test_manage_existing.py @@ -0,0 +1,133 @@ +# (c) Copyright 2016 Industrial Technology Research Institute. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Test case for the function manage_existing.""" + +import mock + +from cinder import exception +from cinder.tests.unit.volume.drivers import disco + + +class ManageExistingTestCase(disco.TestDISCODriver): + """Test cases for Disco connector.""" + + def setUp(self): + """Initialize variables and mock functions.""" + super(ManageExistingTestCase, self).setUp() + + # Mock function to extract volume information by its ID + mock.patch.object(self.requester, + 'volumeDetail', + self.perform_disco_request).start() + + # Mock function to extract volume information by its Name + mock.patch.object(self.requester, + 'volumeDetailByName', + self.perform_disco_request).start() + + self.response = {'volumeInfoResult': { + 'volumeName': 'abcdefg', + 'volumeId': 1234567, + 'volSizeMb': 2 + }, + 'status': 0 + } + + self.existing_ref_no_identification = {} + self.existing_ref_with_id = {'source-id': 1234567} + self.existing_ref_with_name = {'source-name': 'abcdefg'} + self.existing_ref_no_identification = self.existing_ref_with_id + + def perform_disco_request(self, *args, **kwargs): + """Mock volumeDetail/volumeDetailByName function from rest client.""" + return self.response + + def call_manage_existing(self): + """Manage an existing volume.""" + self.driver.manage_existing( + self.volume, + self.existing_ref_no_identification) + + def test_manage_existing_no_identification(self): + """Manage an existing volume, no id/name.""" + self.existing_ref_no_identification = {} + self.assertRaises(exception.VolumeBackendAPIException, + self.call_manage_existing) + + def test_manage_existing_case_id(self): + """Manage an existing volume, by its id.""" + expected = {'display_name': 'abcdefg'} + ret = self.driver.manage_existing(self.volume, + self.existing_ref_with_id) + actual = {'display_name': ret['display_name']} + self.assertEqual(expected, actual) + + def test_manage_existing_case_name(self): + """Manage an existing volume, by its name.""" + expected = {'provider_location': 1234567} + ret = self.driver.manage_existing(self.volume, + self.existing_ref_with_name) + actual = {'provider_location': ret['provider_location']} + self.assertEqual(expected, actual) + + def test_manage_existing_get_size(self): + """Get size of an existing volume.""" + self.driver.manage_existing_get_size( + self.volume, + self.existing_ref_no_identification) + + def test_manage_existing_get_size_no_identification(self): + """Error while getting size of an existing volume, no id/name.""" + self.existing_ref_no_identification = {} + self.assertRaises(exception.VolumeBackendAPIException, + self.test_manage_existing_get_size) + + def test_manage_existing_get_size_case_id(self): + """Get size of an existing volume, by its id.""" + expected = 2 + ret = self.driver.manage_existing_get_size(self.volume, + self.existing_ref_with_id) + self.assertEqual(expected, ret) + + def test_manage_existing_get_size_case_name(self): + """Get size of an existing volume, by its name.""" + expected = 2 + ret = self.driver.manage_existing_get_size(self.volume, + self.existing_ref_with_name) + self.assertEqual(expected, ret) + + def test_manage_existing_case_id_fail(self): + """Request to DISCO failed.""" + self.response['status'] = 1 + self.assertRaises(exception.VolumeBackendAPIException, + self.test_manage_existing_case_id) + + def test_manage_existing_case_name_fail(self): + """Request to DISCO failed.""" + self.response['status'] = 1 + self.assertRaises(exception.VolumeBackendAPIException, + self.test_manage_existing_case_name) + + def test_manage_existing_get_size_case_id_fail(self): + """Request to DISCO failed.""" + self.response['status'] = 1 + self.assertRaises(exception.VolumeBackendAPIException, + self.test_manage_existing_get_size_case_id) + + def test_manage_existing_get_size_case_name_fail(self): + """Request to DISCO failed.""" + self.response['status'] = 1 + self.assertRaises(exception.VolumeBackendAPIException, + self.test_manage_existing_get_size_case_name) diff --git a/cinder/volume/drivers/disco/disco.py b/cinder/volume/drivers/disco/disco.py index f89030b5c58..dfed29f8512 100644 --- a/cinder/volume/drivers/disco/disco.py +++ b/cinder/volume/drivers/disco/disco.py @@ -452,6 +452,72 @@ class DiscoDriver(driver.VolumeDriver): """Return the path to the DISCO volume.""" return "/dev/dms%s" % volume['name'] + def manage_existing(self, volume, existing_ref): + """Manage an existing volume.""" + if 'source-name' not in existing_ref and'source-id'not in existing_ref: + msg = _("No source-id/source-name in existing_ref") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + elif 'source-name' not in existing_ref: + src_vol = self.client.volumeDetail( + existing_ref['source-id']) + if src_vol['status']: + vol_id = existing_ref['source-id'] + msg = (_("Error while getting volume details, " + "[status] %(stat)s - [volume id] %(vol_id)s") % + {'stat': six.text_type(src_vol['status']), + 'vol_id': vol_id}) + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + return {'display_name': src_vol['volumeInfoResult']['volumeName'], + 'provider_location': existing_ref['source-id']} + else: + src_vol = self.client.volumeDetailByName( + existing_ref['source-name']) + if src_vol['status']: + vol_name = existing_ref['source-name'] + msg = (_("Error while getting volume details with the name " + "%(name)s: [status] %(stat)s") % {'name': vol_name, + 'stat': src_vol['status']}) + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + return { + 'provider_location': src_vol['volumeInfoResult']['volumeId']} + + def unmanage(self, volume): + """Unmanage an existing volume.""" + LOG.debug("unmanage is called", resource=volume) + + def manage_existing_get_size(self, volume, existing_ref): + """Return size of an existing volume.""" + if 'source-name' not in existing_ref and'source-id'not in existing_ref: + msg = _("No source-id/source-name in existing_ref") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + elif 'source-name' not in existing_ref: + src_vol = self.client.volumeDetail( + existing_ref['source-id']) + if src_vol['status']: + vol_id = existing_ref['source-id'] + msg = (_("Error while getting volume details, " + "[status] %(stat)s - [volume id] %(vol_id)s") % + {'stat': six.text_type(src_vol['status']), + 'vol_id': vol_id}) + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + return src_vol['volumeInfoResult']['volSizeMb'] + else: + src_vol = self.client.volumeDetailByName( + existing_ref['source-name']) + if src_vol['status']: + vol_name = existing_ref['source-name'] + msg = (_("Error while getting volume details with the name " + "%(name)s: [status] %(stat)s") % {'name': vol_name, + 'stat': src_vol['status']}) + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + return src_vol['volumeInfoResult']['volSizeMb'] + def ensure_export(self, context, volume): """Ensure an export.""" pass diff --git a/releasenotes/notes/add_manage_unmanage_itri_disco_driver-1c9ee31cc86b6eda.yaml b/releasenotes/notes/add_manage_unmanage_itri_disco_driver-1c9ee31cc86b6eda.yaml new file mode 100644 index 00000000000..642a950ceba --- /dev/null +++ b/releasenotes/notes/add_manage_unmanage_itri_disco_driver-1c9ee31cc86b6eda.yaml @@ -0,0 +1,3 @@ +--- +Features: + - Added volume manage/unmanage support for disco driver.