Merge "Added CG capability to volume group in CoprHD"
This commit is contained in:
commit
dd8e524e94
@ -13,13 +13,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from mock import Mock
|
||||
import mock
|
||||
|
||||
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_constants as fake
|
||||
from cinder.volume.drivers.coprhd import common as coprhd_common
|
||||
from cinder.volume.drivers.coprhd import fc as coprhd_fc
|
||||
from cinder.volume.drivers.coprhd import iscsi as coprhd_iscsi
|
||||
@ -185,60 +184,68 @@ scaleio_itl_list = {"itl": [{"hlu": -1,
|
||||
"target": {}}]}
|
||||
|
||||
|
||||
def get_test_volume_data(volume_type_id):
|
||||
test_volume = {'name': 'test-vol1',
|
||||
'size': 1,
|
||||
'volume_name': 'test-vol1',
|
||||
'id': '1',
|
||||
'consistencygroup_id': None,
|
||||
'provider_auth': None,
|
||||
'project_id': 'project',
|
||||
'display_name': 'test-vol1',
|
||||
'display_description': 'test volume',
|
||||
'volume_type_id': volume_type_id,
|
||||
'provider_id': '1',
|
||||
}
|
||||
return test_volume
|
||||
class test_volume_data(object):
|
||||
name = 'test-vol1'
|
||||
size = 1
|
||||
volume_name = 'test-vol1'
|
||||
id = fake.VOLUME_ID
|
||||
group_id = None
|
||||
provider_auth = None
|
||||
project_id = fake.PROJECT_ID
|
||||
display_name = 'test-vol1'
|
||||
display_description = 'test volume',
|
||||
volume_type_id = None
|
||||
provider_id = fake.PROVIDER_ID
|
||||
|
||||
def __init__(self, volume_type_id):
|
||||
self.volume_type_id = volume_type_id
|
||||
|
||||
|
||||
def get_source_test_volume_data(volume_type_id):
|
||||
test_volume = {'name': 'source_test-vol1',
|
||||
'size': 1,
|
||||
'volume_name': 'source_test-vol1',
|
||||
'id': '1234',
|
||||
'consistencygroup_id': None,
|
||||
'provider_auth': None,
|
||||
'project_id': 'project',
|
||||
'display_name': 'source_test-vol1',
|
||||
'display_description': 'test volume',
|
||||
'volume_type_id': volume_type_id}
|
||||
return test_volume
|
||||
class source_test_volume_data(object):
|
||||
name = 'source_test-vol1'
|
||||
size = 1
|
||||
volume_name = 'source_test-vol1'
|
||||
id = fake.VOLUME2_ID
|
||||
group_id = None
|
||||
provider_auth = None
|
||||
project_id = fake.PROJECT_ID
|
||||
display_name = 'source_test-vol1'
|
||||
display_description = 'test volume'
|
||||
volume_type_id = None
|
||||
|
||||
def __init__(self, volume_type_id):
|
||||
self.volume_type_id = volume_type_id
|
||||
|
||||
|
||||
def get_clone_volume_data(volume_type_id):
|
||||
clone_test_volume = {'name': 'clone-test-vol1',
|
||||
'size': 1,
|
||||
'volume_name': 'clone-test-vol1',
|
||||
'id': '2',
|
||||
'provider_auth': None,
|
||||
'project_id': 'project',
|
||||
'display_name': 'clone-test-vol1',
|
||||
'display_description': 'clone test volume',
|
||||
'volume_type_id': volume_type_id}
|
||||
return clone_test_volume
|
||||
class test_clone_volume_data(object):
|
||||
name = 'clone-test-vol1'
|
||||
size = 1
|
||||
volume_name = 'clone-test-vol1'
|
||||
id = fake.VOLUME3_ID
|
||||
provider_auth = None
|
||||
project_id = fake.PROJECT_ID
|
||||
display_name = 'clone-test-vol1'
|
||||
display_description = 'clone test volume'
|
||||
volume_type_id = None
|
||||
|
||||
def __init__(self, volume_type_id):
|
||||
self.volume_type_id = volume_type_id
|
||||
|
||||
|
||||
def get_test_snapshot_data(src_volume):
|
||||
test_snapshot = {'name': 'snapshot1',
|
||||
'display_name': 'snapshot1',
|
||||
'size': 1,
|
||||
'id': '1111',
|
||||
'volume_name': 'test-vol1',
|
||||
'volume_id': '1234',
|
||||
'volume': src_volume,
|
||||
'volume_size': 1,
|
||||
'project_id': 'project'}
|
||||
return test_snapshot
|
||||
class test_snapshot_data(object):
|
||||
name = 'snapshot1'
|
||||
display_name = 'snapshot1'
|
||||
size = 1
|
||||
id = fake.SNAPSHOT_ID
|
||||
volume_name = 'test-vol1'
|
||||
volume_id = fake.VOLUME_ID
|
||||
volume = None
|
||||
volume_size = 1
|
||||
project_id = fake.PROJECT_ID
|
||||
status = fields.SnapshotStatus.AVAILABLE
|
||||
|
||||
def __init__(self, src_volume):
|
||||
self.volume = src_volume
|
||||
|
||||
|
||||
def get_connector_data():
|
||||
@ -250,26 +257,41 @@ def get_connector_data():
|
||||
return connector
|
||||
|
||||
|
||||
def get_test_CG_data(volume_type_id):
|
||||
test_CG = {'name': 'consistency_group_name',
|
||||
'id': fake_constants.CONSISTENCY_GROUP_ID,
|
||||
'volume_type_id': volume_type_id,
|
||||
'status': fields.ConsistencyGroupStatus.AVAILABLE
|
||||
}
|
||||
return test_CG
|
||||
class test_group_data(object):
|
||||
name = 'group_name'
|
||||
display_name = 'group_name'
|
||||
id = fake.GROUP_ID
|
||||
volume_type_ids = None
|
||||
volume_types = None
|
||||
group_type_id = None
|
||||
status = fields.GroupStatus.AVAILABLE
|
||||
|
||||
def __init__(self, volume_types, group_type_id):
|
||||
self.group_type_id = group_type_id
|
||||
self.volume_types = volume_types
|
||||
|
||||
|
||||
def get_test_CG_snap_data(volume_type_id):
|
||||
test_CG_snapshot = {'name': 'cg_snap_name',
|
||||
'id': fake_constants.SNAPSHOT_ID,
|
||||
'consistencygroup_id':
|
||||
fake_constants.CONSISTENCY_GROUP_ID,
|
||||
'status': fields.ConsistencyGroupStatus.AVAILABLE,
|
||||
'snapshots': [],
|
||||
'consistencygroup': get_test_CG_data(volume_type_id),
|
||||
'cgsnapshot_id': fake_constants.CGSNAPSHOT_ID,
|
||||
}
|
||||
return test_CG_snapshot
|
||||
class test_group_type_data(object):
|
||||
name = 'group_name'
|
||||
display_name = 'group_name'
|
||||
groupsnapshot_id = None
|
||||
id = fake.GROUP_TYPE_ID
|
||||
description = 'group'
|
||||
|
||||
|
||||
class test_group_snap_data(object):
|
||||
name = 'cg_snap_name'
|
||||
display_name = 'cg_snap_name'
|
||||
id = fake.GROUP_SNAPSHOT_ID
|
||||
group_id = fake.GROUP_ID
|
||||
status = fields.GroupStatus.AVAILABLE
|
||||
snapshots = []
|
||||
group = None
|
||||
group_type_id = None
|
||||
|
||||
def __init__(self, volume_types, group_type_id):
|
||||
self.group_type_id = group_type_id
|
||||
self.group = test_group_data(volume_types, group_type_id)
|
||||
|
||||
|
||||
class MockedEMCCoprHDDriverCommon(coprhd_common.EMCCoprHDDriverCommon):
|
||||
@ -300,22 +322,21 @@ class MockedEMCCoprHDDriverCommon(coprhd_common.EMCCoprHDDriverCommon):
|
||||
return "cg_uri"
|
||||
|
||||
def init_volume_api(self):
|
||||
self.volume_api = Mock()
|
||||
self.volume_api = mock.Mock()
|
||||
self.volume_api.get.return_value = {
|
||||
'name': 'source_test-vol1',
|
||||
'size': 1,
|
||||
'volume_name': 'source_test-vol1',
|
||||
'id': fake_constants.VOLUME_ID,
|
||||
'consistencygroup_id': fake_constants.CONSISTENCYGROUP_ID,
|
||||
'id': fake.VOLUME_ID,
|
||||
'group_id': fake.GROUP_ID,
|
||||
'provider_auth': None,
|
||||
'project_id': fake_constants.PROJECT_ID,
|
||||
'project_id': fake.PROJECT_ID,
|
||||
'display_name': 'source_test-vol1',
|
||||
'display_description': 'test volume',
|
||||
'volume_type_id': fake_constants.VOLUME_TYPE_ID,
|
||||
}
|
||||
'volume_type_id': fake.VOLUME_TYPE_ID}
|
||||
|
||||
def init_coprhd_api_components(self):
|
||||
self.volume_obj = Mock()
|
||||
self.volume_obj = mock.Mock()
|
||||
self.volume_obj.create.return_value = "volume_created"
|
||||
self.volume_obj.volume_query.return_value = "volume_uri"
|
||||
self.volume_obj.get_storageAttributes.return_value = (
|
||||
@ -342,12 +363,12 @@ class MockedEMCCoprHDDriverCommon(coprhd_common.EMCCoprHDDriverCommon):
|
||||
self.volume_obj.show.return_value = {"id": "vol_id"}
|
||||
self.volume_obj.expand.return_value = "expanded"
|
||||
|
||||
self.tag_obj = Mock()
|
||||
self.tag_obj = mock.Mock()
|
||||
self.tag_obj.list_tags.return_value = [
|
||||
"Openstack-vol", "Openstack-vol1"]
|
||||
self.tag_obj.tag_resource.return_value = "Tagged"
|
||||
|
||||
self.exportgroup_obj = Mock()
|
||||
self.exportgroup_obj = mock.Mock()
|
||||
self.exportgroup_obj.exportgroup_list.return_value = (
|
||||
export_group_list)
|
||||
self.exportgroup_obj.exportgroup_show.return_value = (
|
||||
@ -356,7 +377,7 @@ class MockedEMCCoprHDDriverCommon(coprhd_common.EMCCoprHDDriverCommon):
|
||||
self.exportgroup_obj.exportgroup_add_volumes.return_value = (
|
||||
"volume-added")
|
||||
|
||||
self.host_obj = Mock()
|
||||
self.host_obj = mock.Mock()
|
||||
self.host_obj.list_by_tenant.return_value = []
|
||||
self.host_obj.list_all.return_value = [{'id': "host1_id",
|
||||
'name': "host1"}]
|
||||
@ -365,11 +386,11 @@ class MockedEMCCoprHDDriverCommon(coprhd_common.EMCCoprHDDriverCommon):
|
||||
{'name': "12:34:56:78:90:54:32:11"},
|
||||
{'name': "bfdf432500000004"}]
|
||||
|
||||
self.hostinitiator_obj = Mock()
|
||||
self.varray_obj = Mock()
|
||||
self.hostinitiator_obj = mock.Mock()
|
||||
self.varray_obj = mock.Mock()
|
||||
self.varray_obj.varray_show.return_value = varray_detail_data
|
||||
|
||||
self.snapshot_obj = Mock()
|
||||
self.snapshot_obj = mock.Mock()
|
||||
mocked_snap_obj = self.snapshot_obj.return_value
|
||||
mocked_snap_obj.storageResource_query.return_value = (
|
||||
"resourceUri")
|
||||
@ -377,10 +398,10 @@ class MockedEMCCoprHDDriverCommon(coprhd_common.EMCCoprHDDriverCommon):
|
||||
"snapshot_created")
|
||||
mocked_snap_obj.snapshot_query.return_value = "snapshot_uri"
|
||||
|
||||
self.consistencygroup_obj = Mock()
|
||||
mocked_cg_object = self.consistencygroup_obj.return_value
|
||||
mocked_cg_object.create.return_value = "CG-Created"
|
||||
mocked_cg_object.consistencygroup_query.return_value = "CG-uri"
|
||||
self.consistencygroup_obj = mock.Mock()
|
||||
mocked_group_object = self.consistencygroup_obj.return_value
|
||||
mocked_group_object.create.return_value = "CG-Created"
|
||||
mocked_group_object.consistencygroup_query.return_value = "CG-uri"
|
||||
|
||||
|
||||
class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
@ -391,7 +412,7 @@ class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
|
||||
def create_coprhd_setup(self):
|
||||
|
||||
self.configuration = Mock()
|
||||
self.configuration = mock.Mock()
|
||||
self.configuration.coprhd_hostname = "10.10.10.10"
|
||||
self.configuration.coprhd_port = "4443"
|
||||
self.configuration.volume_backend_name = "EMCCoprHDISCSIDriver"
|
||||
@ -402,7 +423,10 @@ class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
self.configuration.coprhd_varray = "varray"
|
||||
self.configuration.coprhd_emulate_snapshot = False
|
||||
|
||||
self.volume_type_id = self.create_coprhd_volume_type()
|
||||
self.volume_type = self.create_coprhd_volume_type()
|
||||
self.volume_type_id = self.volume_type.id
|
||||
self.group_type = test_group_type_data()
|
||||
self.group_type_id = self.group_type.id
|
||||
|
||||
self.mock_object(coprhd_iscsi.EMCCoprHDISCSIDriver,
|
||||
'_get_common_driver',
|
||||
@ -423,8 +447,7 @@ class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
"coprhd-volume-type",
|
||||
{'CoprHD:VPOOL':
|
||||
'vpool_coprhd'})
|
||||
volume_id = vipr_volume_type['id']
|
||||
return volume_id
|
||||
return vipr_volume_type
|
||||
|
||||
def _get_mocked_common_driver(self):
|
||||
return MockedEMCCoprHDDriverCommon(
|
||||
@ -437,7 +460,7 @@ class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
volume_types.destroy(ctx, self.volume_type_id)
|
||||
|
||||
def test_create_destroy(self):
|
||||
volume = get_test_volume_data(self.volume_type_id)
|
||||
volume = test_volume_data(self.volume_type_id)
|
||||
|
||||
self.driver.create_volume(volume)
|
||||
self.driver.delete_volume(volume)
|
||||
@ -447,17 +470,17 @@ class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
self.assertEqual('unknown', vol_stats['free_capacity_gb'])
|
||||
|
||||
def test_create_volume_clone(self):
|
||||
src_volume_data = get_test_volume_data(self.volume_type_id)
|
||||
clone_volume_data = get_clone_volume_data(self.volume_type_id)
|
||||
src_volume_data = test_volume_data(self.volume_type_id)
|
||||
clone_volume_data = test_clone_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(src_volume_data)
|
||||
self.driver.create_cloned_volume(clone_volume_data, src_volume_data)
|
||||
self.driver.delete_volume(src_volume_data)
|
||||
self.driver.delete_volume(clone_volume_data)
|
||||
|
||||
def test_create_destroy_snapshot(self):
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
snapshot_data = get_test_snapshot_data(
|
||||
get_source_test_volume_data(self.volume_type_id))
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
snapshot_data = test_snapshot_data(
|
||||
source_test_volume_data(self.volume_type_id))
|
||||
|
||||
self.driver.create_volume(volume_data)
|
||||
self.driver.create_snapshot(snapshot_data)
|
||||
@ -466,11 +489,11 @@ class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
|
||||
def test_create_volume_from_snapshot(self):
|
||||
|
||||
src_vol_data = get_source_test_volume_data(self.volume_type_id)
|
||||
src_vol_data = source_test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(src_vol_data)
|
||||
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
snapshot_data = get_test_snapshot_data(src_vol_data)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
snapshot_data = test_snapshot_data(src_vol_data)
|
||||
|
||||
self.driver.create_snapshot(snapshot_data)
|
||||
self.driver.create_volume_from_snapshot(volume_data, snapshot_data)
|
||||
@ -480,14 +503,14 @@ class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_extend_volume(self):
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(volume_data)
|
||||
self.driver.extend_volume(volume_data, 2)
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_initialize_and_terminate_connection(self):
|
||||
connector_data = get_connector_data()
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
|
||||
self.driver.create_volume(volume_data)
|
||||
res_initialize = self.driver.initialize_connection(
|
||||
@ -498,54 +521,63 @@ class EMCCoprHDISCSIDriverTest(test.TestCase):
|
||||
'target_iqn':
|
||||
'50:00:09:73:00:18:95:19',
|
||||
'target_discovered': False,
|
||||
'volume_id': '1'}}
|
||||
'volume_id': fake.VOLUME_ID}}
|
||||
self.assertEqual(
|
||||
expected_initialize, res_initialize, 'Unexpected return data')
|
||||
|
||||
self.driver.terminate_connection(volume_data, connector_data)
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_create_delete_empty_CG(self):
|
||||
cg_data = get_test_CG_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_delete_empty_group(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True]
|
||||
group_data = test_group_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
self.driver.create_consistencygroup(ctx, cg_data)
|
||||
self.driver.create_group(ctx, group_data)
|
||||
model_update, volumes_model_update = (
|
||||
self.driver.delete_consistencygroup(ctx, cg_data, []))
|
||||
self.driver.delete_group(ctx, group_data, []))
|
||||
self.assertEqual([], volumes_model_update, 'Unexpected return data')
|
||||
|
||||
def test_create_update_delete_CG(self):
|
||||
cg_data = get_test_CG_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_update_delete_group(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True, True, True]
|
||||
group_data = test_group_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
self.driver.create_consistencygroup(ctx, cg_data)
|
||||
self.driver.create_group(ctx, group_data)
|
||||
|
||||
volume = get_test_volume_data(self.volume_type_id)
|
||||
volume = test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(volume)
|
||||
|
||||
model_update, ret1, ret2 = (
|
||||
self.driver.update_consistencygroup(ctx, cg_data, [volume], []))
|
||||
self.driver.update_group(ctx, group_data, [volume], []))
|
||||
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
|
||||
model_update, volumes_model_update = (
|
||||
self.driver.delete_consistencygroup(ctx, cg_data, [volume]))
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.driver.delete_group(ctx, group_data, [volume]))
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
self.assertEqual([{'status': 'deleted', 'id': '1'}],
|
||||
self.assertEqual([{'status': 'deleted', 'id': fake.VOLUME_ID}],
|
||||
volumes_model_update)
|
||||
|
||||
def test_create_delete_CG_snap(self):
|
||||
cg_snap_data = get_test_CG_snap_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_delete_group_snap(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True]
|
||||
group_snap_data = test_group_snap_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
|
||||
model_update, snapshots_model_update = (
|
||||
self.driver.create_cgsnapshot(ctx, cg_snap_data, []))
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.driver.create_group_snapshot(ctx, group_snap_data, []))
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
self.assertEqual([], snapshots_model_update, 'Unexpected return data')
|
||||
|
||||
model_update, snapshots_model_update = (
|
||||
self.driver.delete_cgsnapshot(ctx, cg_snap_data, []))
|
||||
self.driver.delete_group_snapshot(ctx, group_snap_data, []))
|
||||
self.assertEqual({}, model_update, 'Unexpected return data')
|
||||
self.assertEqual([], snapshots_model_update, 'Unexpected return data')
|
||||
|
||||
@ -558,7 +590,7 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
|
||||
def create_coprhd_setup(self):
|
||||
|
||||
self.configuration = Mock()
|
||||
self.configuration = mock.Mock()
|
||||
self.configuration.coprhd_hostname = "10.10.10.10"
|
||||
self.configuration.coprhd_port = "4443"
|
||||
self.configuration.volume_backend_name = "EMCCoprHDFCDriver"
|
||||
@ -569,7 +601,10 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
self.configuration.coprhd_varray = "varray"
|
||||
self.configuration.coprhd_emulate_snapshot = False
|
||||
|
||||
self.volume_type_id = self.create_coprhd_volume_type()
|
||||
self.volume_type = self.create_coprhd_volume_type()
|
||||
self.volume_type_id = self.volume_type.id
|
||||
self.group_type = test_group_type_data()
|
||||
self.group_type_id = self.group_type.id
|
||||
|
||||
self.mock_object(coprhd_fc.EMCCoprHDFCDriver,
|
||||
'_get_common_driver',
|
||||
@ -589,8 +624,7 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
vipr_volume_type = volume_types.create(ctx,
|
||||
"coprhd-volume-type",
|
||||
{'CoprHD:VPOOL': 'vpool_vipr'})
|
||||
volume_id = vipr_volume_type['id']
|
||||
return volume_id
|
||||
return vipr_volume_type
|
||||
|
||||
def _get_mocked_common_driver(self):
|
||||
return MockedEMCCoprHDDriverCommon(
|
||||
@ -603,7 +637,7 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
volume_types.destroy(ctx, self.volume_type_id)
|
||||
|
||||
def test_create_destroy(self):
|
||||
volume = get_test_volume_data(self.volume_type_id)
|
||||
volume = test_volume_data(self.volume_type_id)
|
||||
|
||||
self.driver.create_volume(volume)
|
||||
self.driver.delete_volume(volume)
|
||||
@ -614,8 +648,8 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
|
||||
def test_create_volume_clone(self):
|
||||
|
||||
src_volume_data = get_test_volume_data(self.volume_type_id)
|
||||
clone_volume_data = get_clone_volume_data(self.volume_type_id)
|
||||
src_volume_data = test_volume_data(self.volume_type_id)
|
||||
clone_volume_data = test_clone_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(src_volume_data)
|
||||
self.driver.create_cloned_volume(clone_volume_data, src_volume_data)
|
||||
self.driver.delete_volume(src_volume_data)
|
||||
@ -623,9 +657,9 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
|
||||
def test_create_destroy_snapshot(self):
|
||||
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
snapshot_data = get_test_snapshot_data(
|
||||
get_source_test_volume_data(self.volume_type_id))
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
snapshot_data = test_snapshot_data(
|
||||
source_test_volume_data(self.volume_type_id))
|
||||
|
||||
self.driver.create_volume(volume_data)
|
||||
self.driver.create_snapshot(snapshot_data)
|
||||
@ -633,11 +667,11 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_create_volume_from_snapshot(self):
|
||||
src_vol_data = get_source_test_volume_data(self.volume_type_id)
|
||||
src_vol_data = source_test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(src_vol_data)
|
||||
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
snapshot_data = get_test_snapshot_data(src_vol_data)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
snapshot_data = test_snapshot_data(src_vol_data)
|
||||
|
||||
self.driver.create_snapshot(snapshot_data)
|
||||
self.driver.create_volume_from_snapshot(volume_data, snapshot_data)
|
||||
@ -646,22 +680,8 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
self.driver.delete_volume(src_vol_data)
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_create_volume_from_cg_snapshot(self):
|
||||
ctx = context.get_admin_context()
|
||||
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
cg_snap_data = get_test_CG_snap_data(self.volume_type_id)
|
||||
|
||||
self.driver.create_cgsnapshot(ctx, cg_snap_data, [])
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_volume_from_snapshot,
|
||||
volume_data, cg_snap_data)
|
||||
|
||||
self.driver.delete_cgsnapshot(ctx, cg_snap_data, [])
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_extend_volume(self):
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(volume_data)
|
||||
self.driver.extend_volume(volume_data, 2)
|
||||
self.driver.delete_volume(volume_data)
|
||||
@ -669,7 +689,7 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
def test_initialize_and_terminate_connection(self):
|
||||
|
||||
connector_data = get_connector_data()
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
|
||||
self.driver.create_volume(volume_data)
|
||||
res_initiatlize = self.driver.initialize_connection(
|
||||
@ -686,7 +706,7 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
'target_wwn': ['1234567890123456',
|
||||
'1234567890123456'],
|
||||
'target_discovered': False,
|
||||
'volume_id': '1'}}
|
||||
'volume_id': fake.VOLUME_ID}}
|
||||
self.assertEqual(
|
||||
expected_initialize, res_initiatlize, 'Unexpected return data')
|
||||
|
||||
@ -707,47 +727,56 @@ class EMCCoprHDFCDriverTest(test.TestCase):
|
||||
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_create_delete_empty_CG(self):
|
||||
cg_data = get_test_CG_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_delete_empty_group(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True]
|
||||
group_data = test_group_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
self.driver.create_consistencygroup(ctx, cg_data)
|
||||
self.driver.create_group(ctx, group_data)
|
||||
model_update, volumes_model_update = (
|
||||
self.driver.delete_consistencygroup(ctx, cg_data, []))
|
||||
self.driver.delete_group(ctx, group_data, []))
|
||||
self.assertEqual([], volumes_model_update, 'Unexpected return data')
|
||||
|
||||
def test_create_update_delete_CG(self):
|
||||
cg_data = get_test_CG_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_update_delete_group(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True, True]
|
||||
group_data = test_group_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
self.driver.create_consistencygroup(ctx, cg_data)
|
||||
self.driver.create_group(ctx, group_data)
|
||||
|
||||
volume = get_test_volume_data(self.volume_type_id)
|
||||
volume = test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(volume)
|
||||
|
||||
model_update, ret1, ret2 = (
|
||||
self.driver.update_consistencygroup(ctx, cg_data, [volume], []))
|
||||
self.driver.update_group(ctx, group_data, [volume], []))
|
||||
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
|
||||
model_update, volumes_model_update = (
|
||||
self.driver.delete_consistencygroup(ctx, cg_data, [volume]))
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.driver.delete_group(ctx, group_data, [volume]))
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
self.assertEqual([{'status': 'deleted', 'id': '1'}],
|
||||
self.assertEqual([{'status': 'deleted', 'id': fake.VOLUME_ID}],
|
||||
volumes_model_update)
|
||||
|
||||
def test_create_delete_CG_snap(self):
|
||||
cg_snap_data = get_test_CG_snap_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_delete_group_snap(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True]
|
||||
group_snap_data = test_group_snap_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
|
||||
model_update, snapshots_model_update = (
|
||||
self.driver.create_cgsnapshot(ctx, cg_snap_data, []))
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.driver.create_group_snapshot(ctx, group_snap_data, []))
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
self.assertEqual([], snapshots_model_update, 'Unexpected return data')
|
||||
|
||||
model_update, snapshots_model_update = (
|
||||
self.driver.delete_cgsnapshot(ctx, cg_snap_data, []))
|
||||
self.driver.delete_group_snapshot(ctx, group_snap_data, []))
|
||||
self.assertEqual({}, model_update, 'Unexpected return data')
|
||||
self.assertEqual([], snapshots_model_update, 'Unexpected return data')
|
||||
|
||||
@ -760,7 +789,7 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
|
||||
def create_coprhd_setup(self):
|
||||
|
||||
self.configuration = Mock()
|
||||
self.configuration = mock.Mock()
|
||||
self.configuration.coprhd_hostname = "10.10.10.10"
|
||||
self.configuration.coprhd_port = "4443"
|
||||
self.configuration.volume_backend_name = "EMCCoprHDFCDriver"
|
||||
@ -779,7 +808,10 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
self.configuration.scaleio_server_certificate_path = (
|
||||
"/etc/scaleio/certs")
|
||||
|
||||
self.volume_type_id = self.create_coprhd_volume_type()
|
||||
self.volume_type = self.create_coprhd_volume_type()
|
||||
self.volume_type_id = self.volume_type.id
|
||||
self.group_type = test_group_type_data()
|
||||
self.group_type_id = self.group_type.id
|
||||
|
||||
self.mock_object(coprhd_scaleio.EMCCoprHDScaleIODriver,
|
||||
'_get_common_driver',
|
||||
@ -802,8 +834,7 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
vipr_volume_type = volume_types.create(ctx,
|
||||
"coprhd-volume-type",
|
||||
{'CoprHD:VPOOL': 'vpool_vipr'})
|
||||
volume_id = vipr_volume_type['id']
|
||||
return volume_id
|
||||
return vipr_volume_type
|
||||
|
||||
def _get_mocked_common_driver(self):
|
||||
return MockedEMCCoprHDDriverCommon(
|
||||
@ -820,7 +851,7 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
volume_types.destroy(ctx, self.volume_type_id)
|
||||
|
||||
def test_create_destroy(self):
|
||||
volume = get_test_volume_data(self.volume_type_id)
|
||||
volume = test_volume_data(self.volume_type_id)
|
||||
|
||||
self.driver.create_volume(volume)
|
||||
self.driver.delete_volume(volume)
|
||||
@ -831,8 +862,8 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
|
||||
def test_create_volume_clone(self):
|
||||
|
||||
src_volume_data = get_test_volume_data(self.volume_type_id)
|
||||
clone_volume_data = get_clone_volume_data(self.volume_type_id)
|
||||
src_volume_data = test_volume_data(self.volume_type_id)
|
||||
clone_volume_data = test_clone_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(src_volume_data)
|
||||
self.driver.create_cloned_volume(clone_volume_data, src_volume_data)
|
||||
self.driver.delete_volume(src_volume_data)
|
||||
@ -840,9 +871,9 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
|
||||
def test_create_destroy_snapshot(self):
|
||||
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
snapshot_data = get_test_snapshot_data(
|
||||
get_source_test_volume_data(self.volume_type_id))
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
snapshot_data = test_snapshot_data(
|
||||
source_test_volume_data(self.volume_type_id))
|
||||
|
||||
self.driver.create_volume(volume_data)
|
||||
self.driver.create_snapshot(snapshot_data)
|
||||
@ -850,11 +881,11 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_create_volume_from_snapshot(self):
|
||||
src_vol_data = get_source_test_volume_data(self.volume_type_id)
|
||||
src_vol_data = source_test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(src_vol_data)
|
||||
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
snapshot_data = get_test_snapshot_data(src_vol_data)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
snapshot_data = test_snapshot_data(src_vol_data)
|
||||
|
||||
self.driver.create_snapshot(snapshot_data)
|
||||
self.driver.create_volume_from_snapshot(volume_data, snapshot_data)
|
||||
@ -864,7 +895,7 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_extend_volume(self):
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(volume_data)
|
||||
self.driver.extend_volume(volume_data, 2)
|
||||
self.driver.delete_volume(volume_data)
|
||||
@ -872,16 +903,17 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
def test_initialize_and_terminate_connection(self):
|
||||
|
||||
connector_data = get_connector_data()
|
||||
volume_data = get_test_volume_data(self.volume_type_id)
|
||||
volume_data = test_volume_data(self.volume_type_id)
|
||||
|
||||
self.driver.create_volume(volume_data)
|
||||
res_initiatlize = self.driver.initialize_connection(
|
||||
volume_data, connector_data)
|
||||
exp_name = res_initiatlize['data']['scaleIO_volname']
|
||||
expected_initialize = {'data': {'bandwidthLimit': None,
|
||||
'hostIP': '10.0.0.2',
|
||||
'iopsLimit': None,
|
||||
'scaleIO_volname': 'test-vol1',
|
||||
'scaleIO_volume_id': '1',
|
||||
'scaleIO_volname': exp_name,
|
||||
'scaleIO_volume_id': fake.PROVIDER_ID,
|
||||
'serverIP': '10.10.10.11',
|
||||
'serverPassword': 'scaleio_password',
|
||||
'serverPort': 443,
|
||||
@ -895,46 +927,55 @@ class EMCCoprHDScaleIODriverTest(test.TestCase):
|
||||
volume_data, connector_data)
|
||||
self.driver.delete_volume(volume_data)
|
||||
|
||||
def test_create_delete_empty_CG(self):
|
||||
cg_data = get_test_CG_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_delete_empty_group(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True]
|
||||
group_data = test_group_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
self.driver.create_consistencygroup(ctx, cg_data)
|
||||
self.driver.create_group(ctx, group_data)
|
||||
model_update, volumes_model_update = (
|
||||
self.driver.delete_consistencygroup(ctx, cg_data, []))
|
||||
self.driver.delete_group(ctx, group_data, []))
|
||||
self.assertEqual([], volumes_model_update, 'Unexpected return data')
|
||||
|
||||
def test_create_update_delete_CG(self):
|
||||
cg_data = get_test_CG_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_update_delete_group(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True, True, True]
|
||||
group_data = test_group_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
self.driver.create_consistencygroup(ctx, cg_data)
|
||||
self.driver.create_group(ctx, group_data)
|
||||
|
||||
volume = get_test_volume_data(self.volume_type_id)
|
||||
volume = test_volume_data(self.volume_type_id)
|
||||
self.driver.create_volume(volume)
|
||||
|
||||
model_update, ret1, ret2 = (
|
||||
self.driver.update_consistencygroup(ctx, cg_data, [volume], []))
|
||||
self.driver.update_group(ctx, group_data, [volume], []))
|
||||
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
|
||||
model_update, volumes_model_update = (
|
||||
self.driver.delete_consistencygroup(ctx, cg_data, [volume]))
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.driver.delete_group(ctx, group_data, [volume]))
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
self.assertEqual([{'status': 'deleted', 'id': '1'}],
|
||||
self.assertEqual([{'status': 'deleted', 'id': fake.VOLUME_ID}],
|
||||
volumes_model_update)
|
||||
|
||||
def test_create_delete_CG_snap(self):
|
||||
cg_snap_data = get_test_CG_snap_data(self.volume_type_id)
|
||||
@mock.patch('cinder.volume.utils.is_group_a_cg_snapshot_type')
|
||||
def test_create_delete_group_snap(self, cg_ss_enabled):
|
||||
cg_ss_enabled.side_effect = [True, True]
|
||||
group_snap_data = test_group_snap_data([self.volume_type],
|
||||
self.group_type_id)
|
||||
ctx = context.get_admin_context()
|
||||
|
||||
model_update, snapshots_model_update = (
|
||||
self.driver.create_cgsnapshot(ctx, cg_snap_data, []))
|
||||
self.assertEqual({'status': fields.ConsistencyGroupStatus.AVAILABLE},
|
||||
self.driver.create_group_snapshot(ctx, group_snap_data, []))
|
||||
self.assertEqual({'status': fields.GroupStatus.AVAILABLE},
|
||||
model_update)
|
||||
self.assertEqual([], snapshots_model_update, 'Unexpected return data')
|
||||
|
||||
model_update, snapshots_model_update = (
|
||||
self.driver.delete_cgsnapshot(ctx, cg_snap_data, []))
|
||||
self.driver.delete_group_snapshot(ctx, group_snap_data, []))
|
||||
self.assertEqual({}, model_update, 'Unexpected return data')
|
||||
self.assertEqual([], snapshots_model_update, 'Unexpected return data')
|
||||
|
@ -45,9 +45,9 @@ from cinder.volume.drivers.coprhd.helpers import tag as coprhd_tag
|
||||
from cinder.volume.drivers.coprhd.helpers import (
|
||||
virtualarray as coprhd_varray)
|
||||
from cinder.volume.drivers.coprhd.helpers import volume as coprhd_vol
|
||||
from cinder.volume import utils as volume_utils
|
||||
from cinder.volume import volume_types
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
MAX_RETRIES = 10
|
||||
@ -88,6 +88,10 @@ CONF.register_opts(volume_opts, group=configuration.SHARED_CONF_GROUP)
|
||||
URI_VPOOL_VARRAY_CAPACITY = '/block/vpools/{0}/varrays/{1}/capacity'
|
||||
URI_BLOCK_EXPORTS_FOR_INITIATORS = '/block/exports?initiators={0}'
|
||||
EXPORT_RETRY_COUNT = 5
|
||||
MAX_DEFAULT_NAME_LENGTH = 128
|
||||
MAX_SNAPSHOT_NAME_LENGTH = 63
|
||||
MAX_CONSISTENCY_GROUP_NAME_LENGTH = 64
|
||||
MAX_SIO_LEN = 31
|
||||
|
||||
|
||||
def retry_wrapper(func):
|
||||
@ -225,8 +229,9 @@ class EMCCoprHDDriverCommon(object):
|
||||
|
||||
def create_volume(self, vol, driver, truncate_name=False):
|
||||
self.authenticate_user()
|
||||
name = self._get_resource_name(vol, truncate_name)
|
||||
size = int(vol['size']) * units.Gi
|
||||
name = self._get_resource_name(vol, MAX_DEFAULT_NAME_LENGTH,
|
||||
truncate_name)
|
||||
size = int(vol.size) * units.Gi
|
||||
|
||||
vpool = self._get_vpool(vol)
|
||||
self.vpool = vpool['CoprHD:VPOOL']
|
||||
@ -234,14 +239,17 @@ class EMCCoprHDDriverCommon(object):
|
||||
try:
|
||||
coprhd_cgid = None
|
||||
try:
|
||||
cgid = vol['consistencygroup_id']
|
||||
if cgid:
|
||||
coprhd_cgid = self._get_coprhd_cgid(cgid)
|
||||
if vol.group_id:
|
||||
if volume_utils.is_group_a_cg_snapshot_type(vol.group):
|
||||
coprhd_cgid = self._get_coprhd_cgid(vol.group_id)
|
||||
except KeyError:
|
||||
coprhd_cgid = None
|
||||
except AttributeError:
|
||||
coprhd_cgid = None
|
||||
|
||||
full_project_name = ("%s/%s" % (self.configuration.coprhd_tenant,
|
||||
self.configuration.coprhd_project))
|
||||
self.configuration.coprhd_project)
|
||||
)
|
||||
self.volume_obj.create(full_project_name, name, size,
|
||||
self.configuration.coprhd_varray,
|
||||
self.vpool,
|
||||
@ -249,6 +257,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
sync=True,
|
||||
# no longer specified in volume creation
|
||||
consistencygroup=coprhd_cgid)
|
||||
|
||||
except coprhd_utils.CoprHdError as e:
|
||||
coprhd_err_msg = (_("Volume %(name)s: create failed\n%(err)s") %
|
||||
{'name': name, 'err': six.text_type(e.msg)})
|
||||
@ -260,7 +269,9 @@ class EMCCoprHDDriverCommon(object):
|
||||
@retry_wrapper
|
||||
def create_consistencygroup(self, context, group, truncate_name=False):
|
||||
self.authenticate_user()
|
||||
name = self._get_resource_name(group, truncate_name)
|
||||
name = self._get_resource_name(group,
|
||||
MAX_CONSISTENCY_GROUP_NAME_LENGTH,
|
||||
truncate_name)
|
||||
|
||||
try:
|
||||
self.consistencygroup_obj.create(
|
||||
@ -291,8 +302,8 @@ class EMCCoprHDDriverCommon(object):
|
||||
def update_consistencygroup(self, group, add_volumes,
|
||||
remove_volumes):
|
||||
self.authenticate_user()
|
||||
model_update = {'status': fields.ConsistencyGroupStatus.AVAILABLE}
|
||||
cg_uri = self._get_coprhd_cgid(group['id'])
|
||||
model_update = {'status': fields.GroupStatus.AVAILABLE}
|
||||
cg_uri = self._get_coprhd_cgid(group.id)
|
||||
add_volnames = []
|
||||
remove_volnames = []
|
||||
|
||||
@ -329,7 +340,9 @@ class EMCCoprHDDriverCommon(object):
|
||||
def delete_consistencygroup(self, context, group, volumes,
|
||||
truncate_name=False):
|
||||
self.authenticate_user()
|
||||
name = self._get_resource_name(group, truncate_name)
|
||||
name = self._get_resource_name(group,
|
||||
MAX_CONSISTENCY_GROUP_NAME_LENGTH,
|
||||
truncate_name)
|
||||
volumes_model_update = []
|
||||
|
||||
try:
|
||||
@ -344,20 +357,20 @@ class EMCCoprHDDriverCommon(object):
|
||||
sync=True,
|
||||
force_delete=True)
|
||||
|
||||
update_item = {'id': vol['id'],
|
||||
update_item = {'id': vol.id,
|
||||
'status':
|
||||
fields.ConsistencyGroupStatus.DELETED}
|
||||
fields.GroupStatus.DELETED}
|
||||
volumes_model_update.append(update_item)
|
||||
|
||||
except exception.VolumeBackendAPIException:
|
||||
update_item = {'id': vol['id'],
|
||||
update_item = {'id': vol.id,
|
||||
'status': fields.ConsistencyGroupStatus.
|
||||
ERROR_DELETING}
|
||||
|
||||
volumes_model_update.append(update_item)
|
||||
|
||||
LOG.exception("Failed to delete the volume %s of CG.",
|
||||
vol['name'])
|
||||
vol.name)
|
||||
|
||||
self.consistencygroup_obj.delete(
|
||||
name,
|
||||
@ -365,7 +378,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
self.configuration.coprhd_tenant)
|
||||
|
||||
model_update = {}
|
||||
model_update['status'] = group['status']
|
||||
model_update['status'] = group.status
|
||||
|
||||
return model_update, volumes_model_update
|
||||
|
||||
@ -384,9 +397,19 @@ class EMCCoprHDDriverCommon(object):
|
||||
self.authenticate_user()
|
||||
|
||||
snapshots_model_update = []
|
||||
cgsnapshot_name = self._get_resource_name(cgsnapshot, truncate_name)
|
||||
cg_id = cgsnapshot['consistencygroup_id']
|
||||
cg_group = cgsnapshot.get('consistencygroup')
|
||||
cgsnapshot_name = self._get_resource_name(cgsnapshot,
|
||||
MAX_SNAPSHOT_NAME_LENGTH,
|
||||
truncate_name)
|
||||
|
||||
cg_id = None
|
||||
cg_group = None
|
||||
|
||||
try:
|
||||
cg_id = cgsnapshot.group_id
|
||||
cg_group = cgsnapshot.group
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
cg_name = None
|
||||
coprhd_cgid = None
|
||||
|
||||
@ -408,7 +431,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
True)
|
||||
|
||||
for snapshot in snapshots:
|
||||
vol_id_of_snap = snapshot['volume_id']
|
||||
vol_id_of_snap = snapshot.volume_id
|
||||
|
||||
# Finding the volume in CoprHD for this volume id
|
||||
tagname = "OpenStack:id:" + vol_id_of_snap
|
||||
@ -470,7 +493,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
|
||||
snapshot['status'] = fields.SnapshotStatus.AVAILABLE
|
||||
snapshots_model_update.append(
|
||||
{'id': snapshot['id'], 'status':
|
||||
{'id': snapshot.id, 'status':
|
||||
fields.SnapshotStatus.AVAILABLE})
|
||||
|
||||
model_update = {'status': fields.ConsistencyGroupStatus.AVAILABLE}
|
||||
@ -493,19 +516,28 @@ class EMCCoprHDDriverCommon(object):
|
||||
@retry_wrapper
|
||||
def delete_cgsnapshot(self, cgsnapshot, snapshots, truncate_name=False):
|
||||
self.authenticate_user()
|
||||
cgsnapshot_id = cgsnapshot['id']
|
||||
cgsnapshot_name = self._get_resource_name(cgsnapshot, truncate_name)
|
||||
cgsnapshot_id = cgsnapshot.id
|
||||
cgsnapshot_name = self._get_resource_name(cgsnapshot,
|
||||
MAX_SNAPSHOT_NAME_LENGTH,
|
||||
truncate_name)
|
||||
|
||||
snapshots_model_update = []
|
||||
cg_id = cgsnapshot['consistencygroup_id']
|
||||
cg_group = cgsnapshot.get('consistencygroup')
|
||||
|
||||
cg_id = None
|
||||
cg_group = None
|
||||
|
||||
try:
|
||||
cg_id = cgsnapshot.group_id
|
||||
cg_group = cgsnapshot.group
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
coprhd_cgid = self._get_coprhd_cgid(cg_id)
|
||||
cg_name = self._get_consistencygroup_name(cg_group)
|
||||
|
||||
model_update = {}
|
||||
LOG.info('Delete cgsnapshot %(snap_name)s for consistency group: '
|
||||
'%(group_name)s', {'snap_name': cgsnapshot['name'],
|
||||
'%(group_name)s', {'snap_name': cgsnapshot.name,
|
||||
'group_name': cg_name})
|
||||
|
||||
try:
|
||||
@ -531,7 +563,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
|
||||
for snapshot in snapshots:
|
||||
snapshots_model_update.append(
|
||||
{'id': snapshot['id'],
|
||||
{'id': snapshot.id,
|
||||
'status': fields.SnapshotStatus.DELETED})
|
||||
|
||||
return model_update, snapshots_model_update
|
||||
@ -557,7 +589,9 @@ class EMCCoprHDDriverCommon(object):
|
||||
exempt_tags = []
|
||||
|
||||
self.authenticate_user()
|
||||
name = self._get_resource_name(vol, truncate_name)
|
||||
name = self._get_resource_name(vol,
|
||||
MAX_DEFAULT_NAME_LENGTH,
|
||||
truncate_name)
|
||||
full_project_name = ("%s/%s" % (
|
||||
self.configuration.coprhd_tenant,
|
||||
self.configuration.coprhd_project))
|
||||
@ -613,11 +647,16 @@ class EMCCoprHDDriverCommon(object):
|
||||
if ((not prop.startswith("status") and not
|
||||
prop.startswith("obj_status") and
|
||||
prop != "obj_volume") and value):
|
||||
add_tags.append(
|
||||
"%s:%s:%s" % (self.OPENSTACK_TAG, prop,
|
||||
six.text_type(value)))
|
||||
tag = ("%s:%s:%s" %
|
||||
(self.OPENSTACK_TAG, prop,
|
||||
six.text_type(value)))
|
||||
|
||||
if len(tag) > 128:
|
||||
tag = tag[0:128]
|
||||
add_tags.append(tag)
|
||||
except TypeError:
|
||||
LOG.error("Error tagging the resource property %s", prop)
|
||||
LOG.error(
|
||||
"Error tagging the resource property %s", prop)
|
||||
except TypeError:
|
||||
LOG.error("Error tagging the resource properties")
|
||||
|
||||
@ -638,17 +677,21 @@ class EMCCoprHDDriverCommon(object):
|
||||
def create_cloned_volume(self, vol, src_vref, truncate_name=False):
|
||||
"""Creates a clone of the specified volume."""
|
||||
self.authenticate_user()
|
||||
name = self._get_resource_name(vol, truncate_name)
|
||||
name = self._get_resource_name(vol,
|
||||
MAX_DEFAULT_NAME_LENGTH,
|
||||
truncate_name)
|
||||
srcname = self._get_coprhd_volume_name(src_vref)
|
||||
|
||||
try:
|
||||
if src_vref['consistencygroup_id']:
|
||||
if src_vref.group_id:
|
||||
raise coprhd_utils.CoprHdError(
|
||||
coprhd_utils.CoprHdError.SOS_FAILURE_ERR,
|
||||
_("Clone can't be taken individually on a volume"
|
||||
" that is part of a Consistency Group"))
|
||||
except KeyError as e:
|
||||
pass
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
(storageres_type,
|
||||
storageres_typename) = self.volume_obj.get_storageAttributes(
|
||||
@ -691,13 +734,21 @@ class EMCCoprHDDriverCommon(object):
|
||||
self._raise_or_log_exception(e.err_code, coprhd_err_msg,
|
||||
log_err_msg)
|
||||
|
||||
try:
|
||||
src_vol_size = src_vref['size']
|
||||
except KeyError:
|
||||
src_vol_size = src_vref['volume_size']
|
||||
src_vol_size = 0
|
||||
dest_vol_size = 0
|
||||
|
||||
if vol['size'] > src_vol_size:
|
||||
size_in_bytes = coprhd_utils.to_bytes("%sG" % vol['size'])
|
||||
try:
|
||||
src_vol_size = src_vref.size
|
||||
except AttributeError:
|
||||
src_vol_size = src_vref.volume_size
|
||||
|
||||
try:
|
||||
dest_vol_size = vol.size
|
||||
except AttributeError:
|
||||
dest_vol_size = vol.volume_size
|
||||
|
||||
if dest_vol_size > src_vol_size:
|
||||
size_in_bytes = coprhd_utils.to_bytes("%sG" % dest_vol_size)
|
||||
try:
|
||||
self.volume_obj.expand(
|
||||
("%s/%s" % (self.configuration.coprhd_tenant,
|
||||
@ -733,7 +784,8 @@ class EMCCoprHDDriverCommon(object):
|
||||
{'volume_name': volume_name,
|
||||
'err': six.text_type(e.msg)})
|
||||
|
||||
log_err_msg = "Volume : %s expand failed" % volume_name
|
||||
log_err_msg = ("Volume : %s expand failed" %
|
||||
volume_name)
|
||||
self._raise_or_log_exception(e.err_code, coprhd_err_msg,
|
||||
log_err_msg)
|
||||
|
||||
@ -747,15 +799,20 @@ class EMCCoprHDDriverCommon(object):
|
||||
self.create_cloned_volume(volume, snapshot, truncate_name)
|
||||
return
|
||||
|
||||
if snapshot.get('cgsnapshot_id'):
|
||||
raise coprhd_utils.CoprHdError(
|
||||
coprhd_utils.CoprHdError.SOS_FAILURE_ERR,
|
||||
_("Volume cannot be created individually from a snapshot "
|
||||
"that is part of a Consistency Group"))
|
||||
try:
|
||||
if snapshot.group_snapshot_id:
|
||||
raise coprhd_utils.CoprHdError(
|
||||
coprhd_utils.CoprHdError.SOS_FAILURE_ERR,
|
||||
_("Volume cannot be created individually from a snapshot "
|
||||
"that is part of a Consistency Group"))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
src_snapshot_name = None
|
||||
src_vol_ref = snapshot['volume']
|
||||
new_volume_name = self._get_resource_name(volume, truncate_name)
|
||||
src_vol_ref = snapshot.volume
|
||||
new_volume_name = self._get_resource_name(volume,
|
||||
MAX_DEFAULT_NAME_LENGTH,
|
||||
truncate_name)
|
||||
|
||||
try:
|
||||
coprhd_vol_info = self._get_coprhd_volume_name(
|
||||
@ -786,12 +843,13 @@ class EMCCoprHDDriverCommon(object):
|
||||
{'src_snapshot_name': src_snapshot_name,
|
||||
'err': six.text_type(e.msg)})
|
||||
|
||||
log_err_msg = "Snapshot : %s clone failed" % src_snapshot_name
|
||||
log_err_msg = ("Snapshot : %s clone failed" %
|
||||
src_snapshot_name)
|
||||
self._raise_or_log_exception(e.err_code, coprhd_err_msg,
|
||||
log_err_msg)
|
||||
|
||||
if volume['size'] > snapshot['volume_size']:
|
||||
size_in_bytes = coprhd_utils.to_bytes("%sG" % volume['size'])
|
||||
if volume.size > snapshot.volume_size:
|
||||
size_in_bytes = coprhd_utils.to_bytes("%sG" % volume.size)
|
||||
|
||||
try:
|
||||
self.volume_obj.expand(
|
||||
@ -805,7 +863,8 @@ class EMCCoprHDDriverCommon(object):
|
||||
{'volume_name': new_volume_name,
|
||||
'err': six.text_type(e.msg)})
|
||||
|
||||
log_err_msg = "Volume : %s expand failed" % new_volume_name
|
||||
log_err_msg = ("Volume : %s expand failed" %
|
||||
new_volume_name)
|
||||
self._raise_or_log_exception(e.err_code, coprhd_err_msg,
|
||||
log_err_msg)
|
||||
|
||||
@ -829,7 +888,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
"\n%(err)s") %
|
||||
{'name': name, 'err': six.text_type(e.msg)})
|
||||
|
||||
log_err_msg = "Volume : %s delete failed" % name
|
||||
log_err_msg = ("Volume : %s delete failed" % name)
|
||||
self._raise_or_log_exception(e.err_code, coprhd_err_msg,
|
||||
log_err_msg)
|
||||
|
||||
@ -837,10 +896,10 @@ class EMCCoprHDDriverCommon(object):
|
||||
def create_snapshot(self, snapshot, truncate_name=False):
|
||||
self.authenticate_user()
|
||||
|
||||
volume = snapshot['volume']
|
||||
volume = snapshot.volume
|
||||
|
||||
try:
|
||||
if volume['consistencygroup_id']:
|
||||
if volume.group_id:
|
||||
raise coprhd_utils.CoprHdError(
|
||||
coprhd_utils.CoprHdError.SOS_FAILURE_ERR,
|
||||
_("Snapshot can't be taken individually on a volume"
|
||||
@ -855,8 +914,10 @@ class EMCCoprHDDriverCommon(object):
|
||||
return
|
||||
|
||||
try:
|
||||
snapshotname = self._get_resource_name(snapshot, truncate_name)
|
||||
vol = snapshot['volume']
|
||||
snapshotname = self._get_resource_name(snapshot,
|
||||
MAX_SNAPSHOT_NAME_LENGTH,
|
||||
truncate_name)
|
||||
vol = snapshot.volume
|
||||
|
||||
volumename = self._get_coprhd_volume_name(vol)
|
||||
projectname = self.configuration.coprhd_project
|
||||
@ -894,7 +955,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
"\n%(err)s") % {'snapshotname': snapshotname,
|
||||
'err': six.text_type(e.msg)})
|
||||
|
||||
log_err_msg = "Snapshot : %s create failed" % snapshotname
|
||||
log_err_msg = ("Snapshot : %s create failed" % snapshotname)
|
||||
self._raise_or_log_exception(e.err_code, coprhd_err_msg,
|
||||
log_err_msg)
|
||||
|
||||
@ -902,10 +963,10 @@ class EMCCoprHDDriverCommon(object):
|
||||
def delete_snapshot(self, snapshot):
|
||||
self.authenticate_user()
|
||||
|
||||
vol = snapshot['volume']
|
||||
vol = snapshot.volume
|
||||
|
||||
try:
|
||||
if vol['consistencygroup_id']:
|
||||
if vol.group_id:
|
||||
raise coprhd_utils.CoprHdError(
|
||||
coprhd_utils.CoprHdError.SOS_FAILURE_ERR,
|
||||
_("Snapshot delete can't be done individually on a volume"
|
||||
@ -949,7 +1010,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
coprhd_err_msg = (_("Snapshot %s : Delete Failed\n") %
|
||||
snapshotname)
|
||||
|
||||
log_err_msg = "Snapshot : %s delete failed" % snapshotname
|
||||
log_err_msg = ("Snapshot : %s delete failed" % snapshotname)
|
||||
self._raise_or_log_exception(e.err_code, coprhd_err_msg,
|
||||
log_err_msg)
|
||||
|
||||
@ -1170,7 +1231,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
(_("Consistency Group %s not found") % cgid))
|
||||
|
||||
def _get_consistencygroup_name(self, consisgrp):
|
||||
return consisgrp['name']
|
||||
return consisgrp.name
|
||||
|
||||
def _get_coprhd_snapshot_name(self, snapshot, resUri):
|
||||
tagname = self.OPENSTACK_TAG + ":id:" + snapshot['id']
|
||||
@ -1200,7 +1261,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
return rslt_snap['name']
|
||||
|
||||
def _get_coprhd_volume_name(self, vol, verbose=False):
|
||||
tagname = self.OPENSTACK_TAG + ":id:" + vol['id']
|
||||
tagname = self.OPENSTACK_TAG + ":id:" + vol.id
|
||||
rslt = coprhd_utils.search_by_tag(
|
||||
coprhd_vol.Volume.URI_SEARCH_VOLUMES_BY_TAG.format(tagname),
|
||||
self.configuration.coprhd_hostname,
|
||||
@ -1210,7 +1271,7 @@ class EMCCoprHDDriverCommon(object):
|
||||
# as "OpenStack:obj_id"
|
||||
# as snapshots will be having the obj_id instead of just id.
|
||||
if len(rslt) == 0:
|
||||
tagname = self.OPENSTACK_TAG + ":obj_id:" + vol['id']
|
||||
tagname = self.OPENSTACK_TAG + ":obj_id:" + vol.id
|
||||
rslt = coprhd_utils.search_by_tag(
|
||||
coprhd_vol.Volume.URI_SEARCH_VOLUMES_BY_TAG.format(tagname),
|
||||
self.configuration.coprhd_hostname,
|
||||
@ -1228,21 +1289,36 @@ class EMCCoprHDDriverCommon(object):
|
||||
coprhd_utils.CoprHdError.NOT_FOUND_ERR,
|
||||
(_("Volume %s not found") % vol['display_name']))
|
||||
|
||||
def _get_resource_name(self, resource, truncate_name=False):
|
||||
name = resource.get('display_name', None)
|
||||
|
||||
def _get_resource_name(self, resource,
|
||||
max_name_cap=MAX_DEFAULT_NAME_LENGTH,
|
||||
truncate_name=False):
|
||||
# 36 refers to the length of UUID and +1 for '-'
|
||||
permitted_name_length = max_name_cap - (36 + 1)
|
||||
name = resource.display_name
|
||||
if not name:
|
||||
name = resource['name']
|
||||
name = resource.name
|
||||
|
||||
if truncate_name and len(name) > 31:
|
||||
'''
|
||||
for scaleio, truncate_name will be true. We make sure the
|
||||
total name is less than or equal to 31 characters.
|
||||
_id_to_base64 will return a 24 character name'''
|
||||
if truncate_name:
|
||||
name = self._id_to_base64(resource.id)
|
||||
return name
|
||||
|
||||
return name
|
||||
elif len(name) > permitted_name_length:
|
||||
'''
|
||||
The maximum length of resource name in CoprHD is 128. Hence we use
|
||||
only first 91 characters of the resource name'''
|
||||
return name[0:permitted_name_length] + "-" + resource.id
|
||||
|
||||
else:
|
||||
return name + "-" + resource.id
|
||||
|
||||
def _get_vpool(self, volume):
|
||||
vpool = {}
|
||||
ctxt = context.get_admin_context()
|
||||
type_id = volume['volume_type_id']
|
||||
type_id = volume.volume_type_id
|
||||
if type_id is not None:
|
||||
volume_type = volume_types.get_volume_type(ctxt, type_id)
|
||||
specs = volume_type.get('extra_specs')
|
||||
@ -1363,7 +1439,8 @@ class EMCCoprHDDriverCommon(object):
|
||||
self.authenticate_user()
|
||||
|
||||
try:
|
||||
self.stats['consistencygroup_support'] = 'True'
|
||||
self.stats['consistencygroup_support'] = True
|
||||
self.stats['consistent_group_snapshot_enabled'] = True
|
||||
vols = self.volume_obj.list_volumes(
|
||||
self.configuration.coprhd_tenant +
|
||||
"/" +
|
||||
|
@ -20,9 +20,13 @@ import re
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import interface
|
||||
from cinder.volume import driver
|
||||
from cinder.volume.drivers.coprhd import common as coprhd_common
|
||||
from cinder.volume import utils as volume_utils
|
||||
|
||||
from cinder.zonemanager import utils as fczm_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -89,30 +93,67 @@ class EMCCoprHDFCDriver(driver.FibreChannelDriver):
|
||||
pass
|
||||
|
||||
def remove_export(self, context, volume):
|
||||
"""Driver exntry point to remove an export for a volume."""
|
||||
"""Driver entry point to remove an export for a volume."""
|
||||
pass
|
||||
|
||||
def create_consistencygroup(self, context, group):
|
||||
"""Creates a consistencygroup."""
|
||||
return self.common.create_consistencygroup(context, group)
|
||||
def create_group(self, context, group):
|
||||
"""Creates a group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.create_consistencygroup(context, group)
|
||||
|
||||
def update_consistencygroup(self, context, group, add_volumes=None,
|
||||
remove_volumes=None):
|
||||
"""Updates volumes in consistency group."""
|
||||
return self.common.update_consistencygroup(group, add_volumes,
|
||||
remove_volumes)
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_consistencygroup(self, context, group, volumes):
|
||||
"""Deletes a consistency group."""
|
||||
return self.common.delete_consistencygroup(context, group, volumes)
|
||||
def update_group(self, context, group, add_volumes=None,
|
||||
remove_volumes=None):
|
||||
"""Updates volumes in group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.update_consistencygroup(group, add_volumes,
|
||||
remove_volumes)
|
||||
|
||||
def create_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Creates a cgsnapshot."""
|
||||
return self.common.create_cgsnapshot(cgsnapshot, snapshots)
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Deletes a cgsnapshot."""
|
||||
return self.common.delete_cgsnapshot(cgsnapshot, snapshots)
|
||||
def create_group_from_src(self, ctxt, group, volumes,
|
||||
group_snapshot=None, snapshots=None,
|
||||
source_group=None, source_vols=None):
|
||||
"""Creates a group from source."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
message = _("create group from source is not supported "
|
||||
"for CoprHD if the group type supports "
|
||||
"consistent group snapshot.")
|
||||
raise exception.VolumeBackendAPIException(data=message)
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_group(self, context, group, volumes):
|
||||
"""Deletes a group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.delete_consistencygroup(context, group, volumes)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def create_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Creates a group snapshot."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
|
||||
return self.common.create_cgsnapshot(group_snapshot, snapshots)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Deletes a group snapshot."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
|
||||
return self.common.delete_cgsnapshot(group_snapshot, snapshots)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def check_for_export(self, context, volume_id):
|
||||
"""Make sure volume is exported."""
|
||||
@ -123,14 +164,12 @@ class EMCCoprHDFCDriver(driver.FibreChannelDriver):
|
||||
"""Initializes the connection and returns connection info."""
|
||||
|
||||
properties = {}
|
||||
properties['volume_id'] = volume['id']
|
||||
properties['volume_id'] = volume.id
|
||||
properties['target_discovered'] = False
|
||||
properties['target_wwn'] = []
|
||||
|
||||
init_ports = self._build_initport_list(connector)
|
||||
itls = self.common.initialize_connection(volume,
|
||||
'FC',
|
||||
init_ports,
|
||||
itls = self.common.initialize_connection(volume, 'FC', init_ports,
|
||||
connector['host'])
|
||||
|
||||
target_wwns = None
|
||||
@ -144,7 +183,12 @@ class EMCCoprHDFCDriver(driver.FibreChannelDriver):
|
||||
properties['target_wwn'] = target_wwns
|
||||
properties['initiator_target_map'] = initiator_target_map
|
||||
|
||||
auth = volume['provider_auth']
|
||||
auth = None
|
||||
try:
|
||||
auth = volume.provider_auth
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if auth:
|
||||
(auth_method, auth_username, auth_secret) = auth.split()
|
||||
properties['auth_method'] = auth_method
|
||||
@ -162,9 +206,7 @@ class EMCCoprHDFCDriver(driver.FibreChannelDriver):
|
||||
"""Driver entry point to detach a volume from an instance."""
|
||||
|
||||
init_ports = self._build_initport_list(connector)
|
||||
itls = self.common.terminate_connection(volume,
|
||||
'FC',
|
||||
init_ports,
|
||||
itls = self.common.terminate_connection(volume, 'FC', init_ports,
|
||||
connector['host'])
|
||||
|
||||
volumes_count = self.common.get_exports_count_by_initiators(init_ports)
|
||||
|
@ -18,10 +18,12 @@
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import interface
|
||||
from cinder.volume import driver
|
||||
from cinder.volume.drivers.coprhd import common as coprhd_common
|
||||
|
||||
from cinder.volume import utils as volume_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -67,7 +69,7 @@ class EMCCoprHDISCSIDriver(driver.ISCSIDriver):
|
||||
self.common.expand_volume(volume, new_size)
|
||||
|
||||
def delete_volume(self, volume):
|
||||
"""Deletes an volume."""
|
||||
"""Deletes a volume."""
|
||||
self.common.delete_volume(volume)
|
||||
|
||||
def create_snapshot(self, snapshot):
|
||||
@ -90,27 +92,65 @@ class EMCCoprHDISCSIDriver(driver.ISCSIDriver):
|
||||
"""Driver entry point to remove an export for a volume."""
|
||||
pass
|
||||
|
||||
def create_consistencygroup(self, context, group):
|
||||
"""Creates a consistencygroup."""
|
||||
return self.common.create_consistencygroup(context, group)
|
||||
def create_group(self, context, group):
|
||||
"""Creates a group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.create_consistencygroup(context, group)
|
||||
|
||||
def delete_consistencygroup(self, context, group, volumes):
|
||||
"""Deletes a consistency group."""
|
||||
return self.common.delete_consistencygroup(context, group, volumes)
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def update_consistencygroup(self, context, group,
|
||||
add_volumes=None, remove_volumes=None):
|
||||
"""Updates volumes in consistency group."""
|
||||
return self.common.update_consistencygroup(group, add_volumes,
|
||||
remove_volumes)
|
||||
def create_group_from_src(self, ctxt, group, volumes,
|
||||
group_snapshot=None, snapshots=None,
|
||||
source_group=None, source_vols=None):
|
||||
"""Creates a group from source."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
message = _("create group from source is not supported "
|
||||
"for CoprHD if the group type supports "
|
||||
"consistent group snapshot.")
|
||||
raise exception.VolumeBackendAPIException(data=message)
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
def create_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Creates a cgsnapshot."""
|
||||
return self.common.create_cgsnapshot(cgsnapshot, snapshots)
|
||||
def update_group(self, context, group, add_volumes=None,
|
||||
remove_volumes=None):
|
||||
"""Updates volumes in group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.update_consistencygroup(group, add_volumes,
|
||||
remove_volumes)
|
||||
|
||||
def delete_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Deletes a cgsnapshot."""
|
||||
return self.common.delete_cgsnapshot(cgsnapshot, snapshots)
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_group(self, context, group, volumes):
|
||||
"""Deletes a group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.delete_consistencygroup(context, group, volumes)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def create_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Creates a group snapshot."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
|
||||
LOG.debug("creating a group snapshot")
|
||||
return self.common.create_cgsnapshot(group_snapshot, snapshots)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Deletes a group snapshot."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
|
||||
return self.common.delete_cgsnapshot(group_snapshot, snapshots)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def check_for_export(self, context, volume_id):
|
||||
"""Make sure volume is exported."""
|
||||
@ -127,14 +167,20 @@ class EMCCoprHDISCSIDriver(driver.ISCSIDriver):
|
||||
connector['host'])
|
||||
properties = {}
|
||||
properties['target_discovered'] = False
|
||||
properties['volume_id'] = volume['id']
|
||||
properties['volume_id'] = volume.id
|
||||
if itls:
|
||||
properties['target_iqn'] = itls[0]['target']['port']
|
||||
properties['target_portal'] = '%s:%s' % (
|
||||
itls[0]['target']['ip_address'],
|
||||
itls[0]['target']['tcp_port'])
|
||||
properties['target_lun'] = itls[0]['hlu']
|
||||
auth = volume['provider_auth']
|
||||
|
||||
auth = None
|
||||
try:
|
||||
auth = volume.provider_auth
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if auth:
|
||||
(auth_method, auth_username, auth_secret) = auth.split()
|
||||
properties['auth_method'] = auth_method
|
||||
|
@ -29,6 +29,7 @@ from cinder import interface
|
||||
from cinder.volume import configuration
|
||||
from cinder.volume import driver
|
||||
from cinder.volume.drivers.coprhd import common as coprhd_common
|
||||
from cinder.volume import utils as volume_utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -92,7 +93,7 @@ class EMCCoprHDScaleIODriver(driver.VolumeDriver):
|
||||
"""Creates a Volume."""
|
||||
self.common.create_volume(volume, self, True)
|
||||
self.common.set_volume_tags(volume, ['_obj_volume_type'], True)
|
||||
vol_size = self._update_volume_size(int(volume['size']))
|
||||
vol_size = self._update_volume_size(int(volume.size))
|
||||
return {'size': vol_size}
|
||||
|
||||
def _update_volume_size(self, vol_size):
|
||||
@ -141,28 +142,68 @@ class EMCCoprHDScaleIODriver(driver.VolumeDriver):
|
||||
"""Driver exntry point to remove an export for a volume."""
|
||||
pass
|
||||
|
||||
def create_consistencygroup(self, context, group):
|
||||
"""Creates a consistencygroup."""
|
||||
return self.common.create_consistencygroup(context, group, True)
|
||||
def create_group(self, context, group):
|
||||
"""Creates a group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.create_consistencygroup(context, group, True)
|
||||
|
||||
def update_consistencygroup(self, context, group,
|
||||
add_volumes=None, remove_volumes=None):
|
||||
"""Updates volumes in consistency group."""
|
||||
return self.common.update_consistencygroup(group, add_volumes,
|
||||
remove_volumes)
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_consistencygroup(self, context, group, volumes):
|
||||
"""Deletes a consistency group."""
|
||||
return self.common.delete_consistencygroup(context, group,
|
||||
volumes, True)
|
||||
def update_group(self, context, group, add_volumes=None,
|
||||
remove_volumes=None):
|
||||
"""Updates volumes in group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.update_consistencygroup(group, add_volumes,
|
||||
remove_volumes)
|
||||
|
||||
def create_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Creates a cgsnapshot."""
|
||||
return self.common.create_cgsnapshot(cgsnapshot, snapshots, True)
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Deletes a cgsnapshot."""
|
||||
return self.common.delete_cgsnapshot(cgsnapshot, snapshots, True)
|
||||
def create_group_from_src(self, ctxt, group, volumes,
|
||||
group_snapshot=None, snapshots=None,
|
||||
source_group=None, source_vols=None):
|
||||
"""Creates a group from source."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
message = _("create group from source is not supported "
|
||||
"for CoprHD if the group type supports "
|
||||
"consistent group snapshot.")
|
||||
raise exception.VolumeBackendAPIException(data=message)
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_group(self, context, group, volumes):
|
||||
"""Deletes a group."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group):
|
||||
return self.common.delete_consistencygroup(context, group,
|
||||
volumes, True)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def create_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Creates a group snapshot."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
|
||||
LOG.debug("creating a group snapshot")
|
||||
return self.common.create_cgsnapshot(group_snapshot, snapshots,
|
||||
True)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Deletes a group snapshot."""
|
||||
if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
|
||||
return self.common.delete_cgsnapshot(group_snapshot, snapshots,
|
||||
True)
|
||||
|
||||
# If the group is not consistency group snapshot enabled, then
|
||||
# we shall rely on generic volume group implementation
|
||||
raise NotImplementedError()
|
||||
|
||||
def check_for_export(self, context, volume_id):
|
||||
"""Make sure volume is exported."""
|
||||
@ -171,11 +212,13 @@ class EMCCoprHDScaleIODriver(driver.VolumeDriver):
|
||||
def initialize_connection(self, volume, connector):
|
||||
"""Initializes the connection and returns connection info."""
|
||||
|
||||
volname = self.common._get_resource_name(volume, True)
|
||||
volname = self.common._get_resource_name(volume,
|
||||
coprhd_common.MAX_SIO_LEN,
|
||||
True)
|
||||
|
||||
properties = {}
|
||||
properties['scaleIO_volname'] = volname
|
||||
properties['scaleIO_volume_id'] = volume['provider_id']
|
||||
properties['scaleIO_volume_id'] = volume.provider_id
|
||||
properties['hostIP'] = connector['ip']
|
||||
properties[
|
||||
'serverIP'] = self.configuration.coprhd_scaleio_rest_gateway_host
|
||||
@ -215,10 +258,10 @@ class EMCCoprHDScaleIODriver(driver.VolumeDriver):
|
||||
def terminate_connection(self, volume, connector, **kwargs):
|
||||
"""Disallow connection from connector."""
|
||||
|
||||
volname = volume['display_name']
|
||||
volname = volume.display_name
|
||||
properties = {}
|
||||
properties['scaleIO_volname'] = volname
|
||||
properties['scaleIO_volume_id'] = volume['provider_id']
|
||||
properties['scaleIO_volume_id'] = volume.provider_id
|
||||
properties['hostIP'] = connector['ip']
|
||||
properties[
|
||||
'serverIP'] = self.configuration.coprhd_scaleio_rest_gateway_host
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Add consistent group capability to generic volume groups in CoprHD driver.
|
Loading…
x
Reference in New Issue
Block a user