cinder/cinder/tests/unit/volume/drivers/test_prophetstor_dpl.py

932 lines
38 KiB
Python

# Copyright (c) 2014 ProphetStor, Inc.
# All Rights Reserved.
# 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.
import errno
import re
from unittest import mock
from oslo_utils import units
from six.moves import http_client
from cinder import context
from cinder import exception
from cinder.objects import fields
from cinder import test
from cinder.tests.unit import fake_constants
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import utils as test_utils
from cinder.volume import configuration as conf
from cinder.volume.drivers.prophetstor import dpl_iscsi as DPLDRIVER
from cinder.volume.drivers.prophetstor import dplcommon as DPLCOMMON
from cinder.volume import group_types
POOLUUID = 'ac33fc6e417440d5a1ef27d7231e1cc4'
VOLUMEUUID = 'a000000000000000000000000000001'
INITIATOR = 'iqn.2013-08.org.debian:01:aaaaaaaa'
DATA_IN_CONNECTOR = {'initiator': INITIATOR}
DATA_SERVER_INFO = 0, {
'metadata': {'vendor': 'ProphetStor',
'version': '1.5'}}
DATA_POOLS = 0, {
'children': [POOLUUID]
}
DATA_POOLINFO = 0, {
'capabilitiesURI': '',
'children': [],
'childrenrange': '',
'completionStatus': 'Complete',
'metadata': {'available_capacity': 4294967296,
'ctime': 1390551362349,
'vendor': 'prophetstor',
'version': '1.5',
'display_description': 'Default Pool',
'display_name': 'default_pool',
'event_uuid': '4f7c4d679a664857afa4d51f282a516a',
'physical_device': {'cache': [],
'data': ['disk_uuid_0',
'disk_uuid_1',
'disk_uuid_2'],
'log': [],
'spare': []},
'pool_uuid': POOLUUID,
'properties': {'raid_level': 'raid0'},
'state': 'Online',
'used_capacity': 0,
'total_capacity': 4294967296,
'zpool_guid': '8173612007304181810'},
'objectType': 'application/cdmi-container',
'percentComplete': 100}
DATA_ASSIGNVDEV = 0, {
'children': [],
'childrenrange': '',
'completionStatus': 'Complete',
'domainURI': '',
'exports': {'Network/iSCSI': [
{'logical_unit_name': '',
'logical_unit_number': '101',
'permissions': [INITIATOR],
'portals': ['172.31.1.210:3260'],
'target_identifier':
'iqn.2013-09.com.prophetstor:hypervisor.886423051816'
}]},
'metadata': {'ctime': 0,
'event_uuid': 'c11e90287e9348d0b4889695f1ec4be5',
'type': 'volume'},
'objectID': '',
'objectName': 'd827e23d403f4f12bb208a6fec208fd8',
'objectType': 'application/cdmi-container',
'parentID': '8daa374670af447e8efea27e16bf84cd',
'parentURI': '/dpl_volume',
'snapshots': []
}
DATA_OUTPUT = 0, None
MOD_OUTPUT = {'status': 'available'}
DATA_IN_GROUP = {'id': 'fe2dbc51-5810-451d-ab2f-8c8a48d15bee',
'name': 'group123',
'description': 'des123',
'status': ''}
DATA_IN_VOLUME = {'id': 'c11e902-87e9-348d-0b48-89695f1ec4be5',
'display_name': 'abc123',
'display_description': '',
'size': 10,
'host': "hostname@backend#%s" % POOLUUID}
DATA_IN_VOLUME_VG = {'id': 'fe2dbc5-1581-0451-dab2-f8c8a48d15bee',
'display_name': 'abc123',
'display_description': '',
'size': 10,
'group_id':
'fe2dbc51-5810-451d-ab2f-8c8a48d15bee',
'status': 'available',
'host': "hostname@backend#%s" % POOLUUID}
DATA_IN_REMOVE_VOLUME_VG = {
'id': 'fe2dbc515810451dab2f8c8a48d15bee',
'display_name': 'fe2dbc515810451dab2f8c8a48d15bee',
'display_description': '',
'size': 10,
'group_id': 'fe2dbc51-5810-451d-ab2f-8c8a48d15bee',
'status': 'available',
'host': "hostname@backend#%s" % POOLUUID}
DATA_IN_VOLUME1 = {'id': 'c11e902-87e9-348d-0b48-89695f1ec4bef',
'display_name': 'abc456',
'display_description': '',
'size': 10,
'host': "hostname@backend#%s" % POOLUUID}
DATA_IN_CG_SNAPSHOT = {
'group_id': 'fe2dbc51-5810-451d-ab2f-8c8a48d15bee',
'id': 'cgsnapshot1',
'name': 'cgsnapshot1',
'description': 'cgsnapshot1',
'status': ''}
DATA_IN_SNAPSHOT = {'id': 'fe2dbc5-1581-0451-dab2-f8c8a48d15bee',
'volume_id': 'c11e902-87e9-348d-0b48-89695f1ec4be5',
'display_name': 'snapshot1',
'display_description': '',
'volume_size': 5}
DATA_OUT_SNAPSHOT_CG = {
'id': 'snapshot1',
'volume_id': 'c11e902-87e9-348d-0b48-89695f1ec4be5',
'display_name': 'snapshot1',
'display_description': '',
'group_snapshot_id': 'fe2dbc51-5810-451d-ab2f-8c8a48d15bee'}
DATA_OUT_CG = {
"objectType": "application/cdmi-container",
"objectID": "fe2dbc515810451dab2f8c8a48d15bee",
"objectName": "<new_volume_group_uuid>",
"parentURI": "/dpl_volgroup",
"parentID": "fe2dbc515810451dab2f8c8a48d15bee",
"domainURI": "",
"capabilitiesURI": "",
"completionStatus": "Complete",
"percentComplete": 100,
"metadata":
{
"type": "volume|snapshot|replica",
"volume_group_uuid": "<volume_group_uuid>",
"origin_uuid": "<origin_uuid>",
"snapshot_uuid": "<snapshot_uuid>",
"display_name": "<display name>",
"display_description": "<display description>",
"ctime": 12345678,
"total_capacity": 1024,
"snapshot_used_capacity": 0,
"maximum_snapshot": 1024,
"snapshot_quota": 0,
"state": "<state>",
"properties":
{
"snapshot_rotation": True,
}
},
"childrenrange": "<range>",
"children":
[
'fe2dbc515810451dab2f8c8a48d15bee',
],
}
class TestProphetStorDPLVolume(test.TestCase):
def _gen_snapshot_url(self, vdevid, snapshotid):
snapshot_url = '/%s/%s/%s' % (vdevid, DPLCOMMON.DPL_OBJ_SNAPSHOT,
snapshotid)
return snapshot_url
def setUp(self):
super(TestProphetStorDPLVolume, self).setUp()
self.dplcmd = DPLCOMMON.DPLVolume('1.1.1.1', 8356, 'admin', 'password')
self.DPL_MOCK = mock.MagicMock()
self.dplcmd.objCmd = self.DPL_MOCK
self.DPL_MOCK.send_cmd.return_value = DATA_OUTPUT
def test_getserverinfo(self):
self.dplcmd.get_server_info()
self.DPL_MOCK.send_cmd.assert_called_once_with(
'GET',
'/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_SYSTEM),
None,
[http_client.OK, http_client.ACCEPTED])
def test_createvdev(self):
self.dplcmd.create_vdev(DATA_IN_VOLUME['id'],
DATA_IN_VOLUME['display_name'],
DATA_IN_VOLUME['display_description'],
POOLUUID,
int(DATA_IN_VOLUME['size']) * units.Gi)
metadata = {}
metadata['display_name'] = DATA_IN_VOLUME['display_name']
metadata['display_description'] = DATA_IN_VOLUME['display_description']
metadata['pool_uuid'] = POOLUUID
metadata['total_capacity'] = int(DATA_IN_VOLUME['size']) * units.Gi
metadata['maximum_snapshot'] = 1024
metadata['properties'] = dict(thin_provision=True)
params = {}
params['metadata'] = metadata
self.DPL_MOCK.send_cmd.assert_called_once_with(
'PUT',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id']),
params,
[http_client.OK, http_client.ACCEPTED, http_client.CREATED])
def test_extendvdev(self):
self.dplcmd.extend_vdev(DATA_IN_VOLUME['id'],
DATA_IN_VOLUME['display_name'],
DATA_IN_VOLUME['display_description'],
int(DATA_IN_VOLUME['size']) * units.Gi)
metadata = {}
metadata['display_name'] = DATA_IN_VOLUME['display_name']
metadata['display_description'] = DATA_IN_VOLUME['display_description']
metadata['total_capacity'] = int(DATA_IN_VOLUME['size']) * units.Gi
metadata['maximum_snapshot'] = 1024
params = {}
params['metadata'] = metadata
self.DPL_MOCK.send_cmd.assert_called_once_with(
'PUT',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id']),
params,
[http_client.OK, http_client.ACCEPTED, http_client.CREATED])
def test_deletevdev(self):
self.dplcmd.delete_vdev(DATA_IN_VOLUME['id'], True)
metadata = {}
params = {}
metadata['force'] = True
params['metadata'] = metadata
self.DPL_MOCK.send_cmd.assert_called_once_with(
'DELETE',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id']),
params,
[http_client.OK, http_client.ACCEPTED, http_client.NOT_FOUND,
http_client.NO_CONTENT])
def test_createvdevfromsnapshot(self):
self.dplcmd.create_vdev_from_snapshot(
DATA_IN_VOLUME['id'],
DATA_IN_VOLUME['display_name'],
DATA_IN_VOLUME['display_description'],
DATA_IN_SNAPSHOT['id'],
POOLUUID)
metadata = {}
params = {}
metadata['snapshot_operation'] = 'copy'
metadata['display_name'] = DATA_IN_VOLUME['display_name']
metadata['display_description'] = DATA_IN_VOLUME['display_description']
metadata['pool_uuid'] = POOLUUID
metadata['maximum_snapshot'] = 1024
metadata['properties'] = dict(thin_provision=True)
params['metadata'] = metadata
params['copy'] = self._gen_snapshot_url(DATA_IN_VOLUME['id'],
DATA_IN_SNAPSHOT['id'])
self.DPL_MOCK.send_cmd.assert_called_once_with(
'PUT',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id']),
params,
[http_client.OK, http_client.ACCEPTED, http_client.CREATED])
def test_getpool(self):
self.dplcmd.get_pool(POOLUUID)
self.DPL_MOCK.send_cmd.assert_called_once_with(
'GET',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_POOL,
POOLUUID),
None,
[http_client.OK, http_client.ACCEPTED])
def test_clonevdev(self):
self.dplcmd.clone_vdev(
DATA_IN_VOLUME['id'],
DATA_IN_VOLUME1['id'],
POOLUUID,
DATA_IN_VOLUME['display_name'],
DATA_IN_VOLUME['display_description'],
int(DATA_IN_VOLUME['size']) * units.Gi
)
metadata = {}
params = {}
metadata["snapshot_operation"] = "clone"
metadata["display_name"] = DATA_IN_VOLUME['display_name']
metadata["display_description"] = DATA_IN_VOLUME['display_description']
metadata["pool_uuid"] = POOLUUID
metadata["total_capacity"] = int(DATA_IN_VOLUME['size']) * units.Gi
metadata['maximum_snapshot'] = 1024
metadata['properties'] = dict(thin_provision=True)
params["metadata"] = metadata
params["copy"] = DATA_IN_VOLUME['id']
self.DPL_MOCK.send_cmd.assert_called_once_with(
'PUT',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME1['id']),
params,
[http_client.OK, http_client.CREATED, http_client.ACCEPTED])
def test_createvdevsnapshot(self):
self.dplcmd.create_vdev_snapshot(
DATA_IN_VOLUME['id'],
DATA_IN_SNAPSHOT['id'],
DATA_IN_SNAPSHOT['display_name'],
DATA_IN_SNAPSHOT['display_description']
)
metadata = {}
params = {}
metadata['display_name'] = DATA_IN_SNAPSHOT['display_name']
metadata['display_description'] = (
DATA_IN_SNAPSHOT['display_description'])
params['metadata'] = metadata
params['snapshot'] = DATA_IN_SNAPSHOT['id']
self.DPL_MOCK.send_cmd.assert_called_once_with(
'PUT',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id']),
params,
[http_client.OK, http_client.CREATED, http_client.ACCEPTED])
def test_getvdev(self):
self.dplcmd.get_vdev(DATA_IN_VOLUME['id'])
self.DPL_MOCK.send_cmd.assert_called_once_with(
'GET',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1, DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id']),
None,
[http_client.OK, http_client.ACCEPTED, http_client.NOT_FOUND])
def test_getvdevstatus(self):
self.dplcmd.get_vdev_status(DATA_IN_VOLUME['id'], '123456')
self.DPL_MOCK.send_cmd.assert_called_once_with(
'GET',
'/%s/%s/%s/?event_uuid=%s' % (DPLCOMMON.DPL_VER_V1,
DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id'],
'123456'),
None,
[http_client.OK, http_client.NOT_FOUND])
def test_getpoolstatus(self):
self.dplcmd.get_pool_status(POOLUUID, '123456')
self.DPL_MOCK.send_cmd.assert_called_once_with(
'GET',
'/%s/%s/%s/?event_uuid=%s' % (DPLCOMMON.DPL_VER_V1,
DPLCOMMON.DPL_OBJ_POOL,
POOLUUID,
'123456'),
None,
[http_client.OK, http_client.NOT_FOUND])
def test_assignvdev(self):
self.dplcmd.assign_vdev(
DATA_IN_VOLUME['id'],
'iqn.1993-08.org.debian:01:test1',
'',
'1.1.1.1:3260',
0
)
params = {}
metadata = {}
exports = {}
metadata['export_operation'] = 'assign'
exports['Network/iSCSI'] = {}
target_info = {}
target_info['logical_unit_number'] = 0
target_info['logical_unit_name'] = ''
permissions = []
portals = []
portals.append('1.1.1.1:3260')
permissions.append('iqn.1993-08.org.debian:01:test1')
target_info['permissions'] = permissions
target_info['portals'] = portals
exports['Network/iSCSI'] = target_info
params['metadata'] = metadata
params['exports'] = exports
self.DPL_MOCK.send_cmd.assert_called_once_with(
'PUT',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1,
DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id']),
params,
[http_client.OK, http_client.ACCEPTED, http_client.CREATED])
def test_unassignvdev(self):
self.dplcmd.unassign_vdev(DATA_IN_VOLUME['id'],
'iqn.1993-08.org.debian:01:test1',
'')
params = {}
metadata = {}
exports = {}
metadata['export_operation'] = 'unassign'
params['metadata'] = metadata
exports['Network/iSCSI'] = {}
exports['Network/iSCSI']['target_identifier'] = ''
permissions = []
permissions.append('iqn.1993-08.org.debian:01:test1')
exports['Network/iSCSI']['permissions'] = permissions
params['exports'] = exports
self.DPL_MOCK.send_cmd.assert_called_once_with(
'PUT',
'/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1,
DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id']),
params,
[http_client.OK, http_client.ACCEPTED,
http_client.NO_CONTENT, http_client.NOT_FOUND])
def test_deletevdevsnapshot(self):
self.dplcmd.delete_vdev_snapshot(DATA_IN_VOLUME['id'],
DATA_IN_SNAPSHOT['id'])
params = {}
params['copy'] = self._gen_snapshot_url(DATA_IN_VOLUME['id'],
DATA_IN_SNAPSHOT['id'])
self.DPL_MOCK.send_cmd.assert_called_once_with(
'DELETE',
'/%s/%s/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1,
DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id'],
DPLCOMMON.DPL_OBJ_SNAPSHOT,
DATA_IN_SNAPSHOT['id']),
None,
[http_client.OK, http_client.ACCEPTED, http_client.NO_CONTENT,
http_client.NOT_FOUND])
def test_listvdevsnapshots(self):
self.dplcmd.list_vdev_snapshots(DATA_IN_VOLUME['id'])
self.DPL_MOCK.send_cmd.assert_called_once_with(
'GET',
'/%s/%s/%s/%s/' % (DPLCOMMON.DPL_VER_V1,
DPLCOMMON.DPL_OBJ_VOLUME,
DATA_IN_VOLUME['id'],
DPLCOMMON.DPL_OBJ_SNAPSHOT),
None,
[http_client.OK])
class TestProphetStorDPLDriver(test.TestCase):
def __init__(self, method):
super(TestProphetStorDPLDriver, self).__init__(method)
def _conver_uuid2hex(self, strID):
return strID.replace('-', '')
def setUp(self):
super(TestProphetStorDPLDriver, self).setUp()
self.configuration = mock.Mock(conf.Configuration)
self.configuration.san_ip = '1.1.1.1'
self.configuration.dpl_port = 8356
self.configuration.san_login = 'admin'
self.configuration.san_password = 'password'
self.configuration.dpl_pool = POOLUUID
self.configuration.target_port = 3260
self.configuration.san_is_local = False
self.configuration.san_thin_provision = True
self.configuration.driver_ssl_cert_verify = False
self.configuration.driver_ssl_cert_path = None
self.context = context.get_admin_context()
self.DPL_MOCK = mock.MagicMock()
self.DB_MOCK = mock.MagicMock()
self.dpldriver = DPLDRIVER.DPLISCSIDriver(
configuration=self.configuration)
self.dpldriver.dpl = self.DPL_MOCK
self.dpldriver.db = self.DB_MOCK
self.dpldriver.do_setup(self.context)
def test_get_volume_stats(self):
self.DPL_MOCK.get_pool.return_value = DATA_POOLINFO
self.DPL_MOCK.get_server_info.return_value = DATA_SERVER_INFO
res = self.dpldriver.get_volume_stats(True)
self.assertEqual('ProphetStor', res['vendor_name'])
self.assertEqual('1.5', res['driver_version'])
pool = res["pools"][0]
self.assertEqual(4, pool['total_capacity_gb'])
self.assertEqual(4, pool['free_capacity_gb'])
self.assertEqual(0, pool['reserved_percentage'])
self.assertFalse(pool['QoS_support'])
def test_create_volume(self):
volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME['id'],
display_name=DATA_IN_VOLUME['display_name'],
size=DATA_IN_VOLUME['size'],
host=DATA_IN_VOLUME['host'])
self.DPL_MOCK.create_vdev.return_value = DATA_OUTPUT
self.dpldriver.create_volume(volume)
self.DPL_MOCK.create_vdev.assert_called_once_with(
self._conver_uuid2hex(volume.id),
volume.display_name,
volume.display_description,
self.configuration.dpl_pool,
int(volume.size) * units.Gi,
True)
def test_create_volume_without_pool(self):
volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME['id'],
display_name=DATA_IN_VOLUME['display_name'],
size=DATA_IN_VOLUME['size'],
host=DATA_IN_VOLUME['host'])
self.DPL_MOCK.create_vdev.return_value = DATA_OUTPUT
self.configuration.dpl_pool = ""
volume.host = "host@backend" # missing pool
self.assertRaises(exception.InvalidHost, self.dpldriver.create_volume,
volume=volume)
def test_create_volume_with_configuration_pool(self):
volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME['id'],
display_name=DATA_IN_VOLUME['display_name'],
size=DATA_IN_VOLUME['size'],
host="host@backend")
self.DPL_MOCK.create_vdev.return_value = DATA_OUTPUT
self.dpldriver.create_volume(volume)
self.DPL_MOCK.create_vdev.assert_called_once_with(
self._conver_uuid2hex(volume.id),
volume.display_name, volume.display_description,
self.configuration.dpl_pool, int(volume.size) * units.Gi, True)
def test_create_volume_of_group(self):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
group = test_utils.create_group(
self.context,
id=fake_constants.CONSISTENCY_GROUP_ID,
host='host@backend#unit_test_pool',
group_type_id=group_type.id)
self.DPL_MOCK.create_vdev.return_value = DATA_OUTPUT
self.DPL_MOCK.join_vg.return_value = DATA_OUTPUT
volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME_VG['id'],
display_name=DATA_IN_VOLUME_VG['display_name'],
size=DATA_IN_VOLUME_VG['size'],
group_id=group.id,
host=DATA_IN_VOLUME_VG['host'])
self.dpldriver.create_volume(volume)
self.DPL_MOCK.create_vdev.assert_called_once_with(
self._conver_uuid2hex(volume.id),
volume.display_name,
volume.display_description,
self.configuration.dpl_pool,
int(volume.size) * units.Gi,
True)
self.DPL_MOCK.join_vg.assert_called_once_with(
self._conver_uuid2hex(volume.id),
self._conver_uuid2hex(volume.group_id))
def test_delete_volume(self):
volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME['id'],
display_name=DATA_IN_VOLUME['display_name'],
size=DATA_IN_VOLUME['size'],
host=DATA_IN_VOLUME['host'])
self.DPL_MOCK.delete_vdev.return_value = DATA_OUTPUT
self.dpldriver.delete_volume(volume)
self.DPL_MOCK.delete_vdev.assert_called_once_with(
self._conver_uuid2hex(volume.id))
def test_delete_volume_of_group(self):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
group = test_utils.create_group(
self.context,
id=fake_constants.CONSISTENCY_GROUP_ID,
host='host@backend#unit_test_pool',
group_type_id=group_type.id)
volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME_VG['id'],
display_name=DATA_IN_VOLUME_VG['display_name'],
size=DATA_IN_VOLUME_VG['size'],
group_id=group.id,
host=DATA_IN_VOLUME_VG['host'])
self.DPL_MOCK.delete_vdev.return_value = DATA_OUTPUT
self.DPL_MOCK.leave_vg.return_volume = DATA_OUTPUT
self.dpldriver.delete_volume(volume)
self.DPL_MOCK.leave_vg.assert_called_once_with(
self._conver_uuid2hex(volume.id),
self._conver_uuid2hex(volume.group_id)
)
self.DPL_MOCK.delete_vdev.assert_called_once_with(
self._conver_uuid2hex(volume.id))
def test_create_volume_from_snapshot(self):
self.DPL_MOCK.create_vdev_from_snapshot.return_value = DATA_OUTPUT
self.DPL_MOCK.extend_vdev.return_value = DATA_OUTPUT
volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME_VG['id'],
display_name=DATA_IN_VOLUME_VG['display_name'],
size=DATA_IN_VOLUME_VG['size'],
host=DATA_IN_VOLUME_VG['host'])
self.dpldriver.create_volume_from_snapshot(
volume, DATA_IN_SNAPSHOT)
self.DPL_MOCK.create_vdev_from_snapshot.assert_called_once_with(
self._conver_uuid2hex(volume.id),
volume.display_name,
volume.display_description,
self._conver_uuid2hex(volume.id),
self.configuration.dpl_pool,
True)
self.DPL_MOCK.extend_vdev.assert_called_once_with(
self._conver_uuid2hex(volume.id),
volume.display_name,
volume.display_description,
volume.size * units.Gi)
def test_create_cloned_volume(self):
new_volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME1['id'],
display_name=DATA_IN_VOLUME1['display_name'],
size=DATA_IN_VOLUME1['size'],
host=DATA_IN_VOLUME1['host'])
src_volume = test_utils.create_volume(
self.context,
id=DATA_IN_VOLUME['id'])
self.DPL_MOCK.clone_vdev.return_value = DATA_OUTPUT
self.dpldriver.create_cloned_volume(new_volume, src_volume)
self.DPL_MOCK.clone_vdev.assert_called_once_with(
self._conver_uuid2hex(src_volume.id),
self._conver_uuid2hex(new_volume.id),
self.configuration.dpl_pool,
new_volume.display_name,
new_volume.display_description,
int(new_volume.size) *
units.Gi,
True)
def test_create_snapshot(self):
self.DPL_MOCK.create_vdev_snapshot.return_value = DATA_OUTPUT
self.dpldriver.create_snapshot(DATA_IN_SNAPSHOT)
self.DPL_MOCK.create_vdev_snapshot.assert_called_once_with(
self._conver_uuid2hex(DATA_IN_SNAPSHOT['volume_id']),
self._conver_uuid2hex(DATA_IN_SNAPSHOT['id']),
DATA_IN_SNAPSHOT['display_name'],
DATA_IN_SNAPSHOT['display_description'])
def test_delete_snapshot(self):
self.DPL_MOCK.delete_vdev_snapshot.return_value = DATA_OUTPUT
self.dpldriver.delete_snapshot(DATA_IN_SNAPSHOT)
self.DPL_MOCK.delete_vdev_snapshot.assert_called_once_with(
self._conver_uuid2hex(DATA_IN_SNAPSHOT['volume_id']),
self._conver_uuid2hex(DATA_IN_SNAPSHOT['id']))
def test_initialize_connection(self):
self.DPL_MOCK.assign_vdev.return_value = DATA_ASSIGNVDEV
self.DPL_MOCK.get_vdev.return_value = DATA_ASSIGNVDEV
res = self.dpldriver.initialize_connection(DATA_IN_VOLUME,
DATA_IN_CONNECTOR)
self.assertEqual('iscsi', res['driver_volume_type'])
self.assertEqual(101, res['data']['target_lun'])
self.assertTrue(res['data']['target_discovered'])
self.assertEqual('172.31.1.210:3260', res['data']['target_portal'])
self.assertEqual(
'iqn.2013-09.com.prophetstor:hypervisor.886423051816',
res['data']['target_iqn'])
def test_terminate_connection(self):
self.DPL_MOCK.unassign_vdev.return_value = DATA_OUTPUT
self.dpldriver.terminate_connection(DATA_IN_VOLUME, DATA_IN_CONNECTOR)
self.DPL_MOCK.unassign_vdev.assert_called_once_with(
self._conver_uuid2hex(DATA_IN_VOLUME['id']),
DATA_IN_CONNECTOR['initiator'])
def test_terminate_connection_volume_detached(self):
self.DPL_MOCK.unassign_vdev.return_value = errno.ENODATA, None
self.dpldriver.terminate_connection(DATA_IN_VOLUME, DATA_IN_CONNECTOR)
self.DPL_MOCK.unassign_vdev.assert_called_once_with(
self._conver_uuid2hex(DATA_IN_VOLUME['id']),
DATA_IN_CONNECTOR['initiator'])
def test_terminate_connection_failed(self):
self.DPL_MOCK.unassign_vdev.return_value = errno.EFAULT, None
ex = self.assertRaises(
exception.VolumeBackendAPIException,
self.dpldriver.terminate_connection,
volume=DATA_IN_VOLUME, connector=DATA_IN_CONNECTOR)
self.assertIsNotNone(
re.match(r".*Flexvisor failed", ex.msg))
def test_get_pool_info(self):
self.DPL_MOCK.get_pool.return_value = DATA_POOLINFO
_, res = self.dpldriver._get_pool_info(POOLUUID)
self.assertEqual(4294967296, res['metadata']['available_capacity'])
self.assertEqual(1390551362349, res['metadata']['ctime'])
self.assertEqual('Default Pool',
res['metadata']['display_description'])
self.assertEqual('default_pool',
res['metadata']['display_name'])
self.assertEqual('4f7c4d679a664857afa4d51f282a516a',
res['metadata']['event_uuid'])
self.assertEqual(
{'cache': [],
'data': ['disk_uuid_0', 'disk_uuid_1', 'disk_uuid_2'],
'log': [],
'spare': []},
res['metadata']['physical_device'])
self.assertEqual(POOLUUID, res['metadata']['pool_uuid'])
self.assertEqual(
{'raid_level': 'raid0'},
res['metadata']['properties'])
self.assertEqual('Online', res['metadata']['state'])
self.assertEqual(4294967296, res['metadata']['total_capacity'])
self.assertEqual('8173612007304181810', res['metadata']['zpool_guid'])
def test_create_group(self):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
group = test_utils.create_group(
self.context,
id=fake_constants.CONSISTENCY_GROUP_ID,
host='host@backend#unit_test_pool',
group_type_id=group_type.id)
self.DPL_MOCK.create_vg.return_value = DATA_OUTPUT
model_update = self.dpldriver.create_group(self.context, group)
self.DPL_MOCK.create_vg.assert_called_once_with(
self._conver_uuid2hex(fake_constants.CONSISTENCY_GROUP_ID),
'test_group',
'this is a test group')
self.assertDictEqual({'status': (
fields.ConsistencyGroupStatus.AVAILABLE)}, model_update)
def test_delete_group(self):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
group = test_utils.create_group(
self.context,
id=fake_constants.CONSISTENCY_GROUP_ID,
host='host@backend#unit_test_pool',
group_type_id=group_type.id)
self.DB_MOCK.volume_get_all_by_group.return_value = (
[DATA_IN_VOLUME_VG])
self.DPL_MOCK.delete_vdev.return_value = DATA_OUTPUT
self.DPL_MOCK.delete_cg.return_value = DATA_OUTPUT
model_update, volumes = self.dpldriver.delete_group(
self.context, group, [])
self.DPL_MOCK.delete_vg.assert_called_once_with(
self._conver_uuid2hex(fake_constants.CONSISTENCY_GROUP_ID))
self.DPL_MOCK.delete_vdev.assert_called_once_with(
self._conver_uuid2hex((DATA_IN_VOLUME_VG['id'])))
self.assertDictEqual({'status': (
fields.ConsistencyGroupStatus.DELETED)}, model_update)
def test_update_group(self):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
self.DPL_MOCK.get_vg.return_value = (0, DATA_OUT_CG)
self.DPL_MOCK.join_vg.return_value = DATA_OUTPUT
self.DPL_MOCK.leave_vg.return_value = DATA_OUTPUT
group = test_utils.create_group(
self.context,
id='fe2dbc51-5810-451d-ab2f-8c8a48d15bee',
host='host@backend#unit_test_pool',
group_type_id=group_type.id)
vol_add = test_utils.create_volume(
self.context,
id=fake_constants.VOLUME2_ID,
display_name=DATA_IN_VOLUME_VG['display_name'],
size=DATA_IN_VOLUME_VG['size'],
group_id='fe2dbc51-5810-451d-ab2f-8c8a48d15bee',
host=DATA_IN_VOLUME_VG['host'])
vol_del = test_utils.create_volume(
self.context,
id=DATA_IN_REMOVE_VOLUME_VG['id'],
display_name=DATA_IN_REMOVE_VOLUME_VG['display_name'],
size=DATA_IN_REMOVE_VOLUME_VG['size'],
group_id='fe2dbc51-5810-451d-ab2f-8c8a48d15bee',
host=DATA_IN_REMOVE_VOLUME_VG['host'])
(model_update, add_vols, remove_vols) = (
self.dpldriver.update_group(
self.context, group, [vol_add], [vol_del]))
self.DPL_MOCK.join_vg.assert_called_once_with(
self._conver_uuid2hex(vol_add.id),
self._conver_uuid2hex(group.id))
self.DPL_MOCK.leave_vg.assert_called_once_with(
self._conver_uuid2hex(vol_del.id),
self._conver_uuid2hex(group.id))
self.assertDictEqual({'status': (
fields.ConsistencyGroupStatus.AVAILABLE)}, model_update)
def test_update_group_exception_join(self):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
self.DPL_MOCK.get_vg.return_value = (0, DATA_OUT_CG)
self.DPL_MOCK.join_vg.return_value = -1, None
self.DPL_MOCK.leave_vg.return_value = DATA_OUTPUT
volume = test_utils.create_volume(
self.context,
id=fake_constants.VOLUME2_ID,
display_name=DATA_IN_VOLUME_VG['display_name'],
size=DATA_IN_VOLUME_VG['size'],
host=DATA_IN_VOLUME_VG['host'])
group = test_utils.create_group(
self.context,
id=fake_constants.CONSISTENCY_GROUP_ID,
host='host@backend#unit_test_pool',
group_type_id=group_type.id)
self.assertRaises(exception.VolumeBackendAPIException,
self.dpldriver.update_group,
context=None,
group=group,
add_volumes=[volume],
remove_volumes=None)
def test_update_group_exception_leave(self):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
self.DPL_MOCK.get_vg.return_value = (0, DATA_OUT_CG)
self.DPL_MOCK.leave_vg.return_value = -1, None
volume = test_utils.create_volume(
self.context,
id='fe2dbc51-5810-451d-ab2f-8c8a48d15bee',
display_name=DATA_IN_VOLUME_VG['display_name'],
size=DATA_IN_VOLUME_VG['size'],
host=DATA_IN_VOLUME_VG['host'])
group = test_utils.create_group(
self.context,
id=fake_constants.CONSISTENCY_GROUP_ID,
host='host@backend#unit_test_pool',
group_type_id=group_type.id)
self.assertRaises(exception.VolumeBackendAPIException,
self.dpldriver.update_group,
context=None,
group=group,
add_volumes=None,
remove_volumes=[volume])
@mock.patch(
'cinder.objects.snapshot.SnapshotList.get_all_for_group_snapshot')
def test_create_group_snapshot(self, get_all_for_group_snapshot):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context)
snapshot_obj.group_id = \
DATA_IN_CG_SNAPSHOT['group_id']
snapshot_obj.group_type_id = group_type.id
get_all_for_group_snapshot.return_value = [snapshot_obj]
self.DPL_MOCK.create_vdev_snapshot.return_value = DATA_OUTPUT
model_update, snapshots = self.dpldriver.create_group_snapshot(
self.context, snapshot_obj, [])
self.assertDictEqual({'status': 'available'}, model_update)
@mock.patch(
'cinder.objects.snapshot.SnapshotList.get_all_for_group_snapshot')
def test_delete_group_snapshot(self, get_all_for_group_snapshot):
group_type = group_types.create(
self.context,
'group',
{'consistent_group_snapshot_enabled': '<is> True'}
)
snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context)
snapshot_obj.group_id = \
DATA_IN_CG_SNAPSHOT['group_id']
snapshot_obj.group_type_id = group_type.id
get_all_for_group_snapshot.return_value = [snapshot_obj]
self.DPL_MOCK.delete_group_snapshot.return_value = DATA_OUTPUT
model_update, snapshots = self.dpldriver.delete_group_snapshot(
self.context, snapshot_obj, [])
self.DPL_MOCK.delete_vdev_snapshot.assert_called_once_with(
self._conver_uuid2hex(snapshot_obj.group_id),
self._conver_uuid2hex(snapshot_obj.id),
True)
self.assertDictEqual({'status': 'deleted'}, model_update)