Add manage/unmanage to DISCO driver

This commit is to add the feature manage/unmanage a volume for
DISCO volume driver of ITRI.

It also includes the unit tests.

DocImpact
Implements: blueprint add-manage-unmanage-feature

Change-Id: If71f6e798747f78ad204bcc92118ae18612fa33d
This commit is contained in:
Guy Kim 2016-07-26 11:04:15 +08:00
parent 6a1af6c168
commit 458153db30
3 changed files with 202 additions and 0 deletions

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,3 @@
---
Features:
- Added volume manage/unmanage support for disco driver.