Add CG capability to generic groups in Huawei driver
This patch adds the consistency group capability to generic group in Huawei driver. Consistency groups will be used as generic groups. DocImpact: Implements: blueprint huawei-generic-group Change-Id: I16937c0ccd9f5a4ffad79f35c49ab32ee6092620
This commit is contained in:
parent
d1b5a11325
commit
2e06995ad5
@ -25,9 +25,10 @@ from xml.dom import minidom
|
||||
|
||||
from cinder import context
|
||||
from cinder import exception
|
||||
from cinder.objects import fields
|
||||
from cinder import test
|
||||
from cinder.tests.unit.consistencygroup import fake_cgsnapshot
|
||||
from cinder.tests.unit.consistencygroup import fake_consistencygroup
|
||||
from cinder.tests.unit import fake_group
|
||||
from cinder.tests.unit import fake_group_snapshot
|
||||
from cinder.tests.unit import fake_snapshot
|
||||
from cinder.tests.unit import fake_volume
|
||||
from cinder.tests.unit import utils
|
||||
@ -42,6 +43,7 @@ from cinder.volume.drivers.huawei import replication
|
||||
from cinder.volume.drivers.huawei import rest_client
|
||||
from cinder.volume.drivers.huawei import smartx
|
||||
from cinder.volume import qos_specs
|
||||
from cinder.volume import utils as volume_utils
|
||||
from cinder.volume import volume_types
|
||||
|
||||
admin_contex = context.get_admin_context()
|
||||
@ -382,7 +384,7 @@ FAKE_POOLS_SUPPORT_REPORT = {
|
||||
'max_over_subscription_ratio': 20.0,
|
||||
'luncopy': True,
|
||||
'hypermetro': True,
|
||||
'consistencygroup_support': True
|
||||
'consistent_group_snapshot_enabled': True
|
||||
}
|
||||
|
||||
FAKE_LUN_GET_SUCCESS_RESPONSE = """
|
||||
@ -2020,6 +2022,15 @@ MAP_COMMAND_TO_FAKE_RESPONSE['/mappingview/associate/portgroup?TYPE=245&ASSOC'
|
||||
REPLICA_BACKEND_ID = 'huawei-replica-1'
|
||||
|
||||
|
||||
def cg_or_cg_snapshot(func):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
self.mock_object(volume_utils,
|
||||
'is_group_a_cg_snapshot_type',
|
||||
return_value=True)
|
||||
return func(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
class FakeHuaweiConf(huawei_conf.HuaweiConf):
|
||||
def __init__(self, conf, protocol):
|
||||
self.conf = conf
|
||||
@ -2241,10 +2252,10 @@ class HuaweiTestBase(test.TestCase):
|
||||
admin_contex, id=ID, provider_location=PROVIDER_LOCATION,
|
||||
name_id=ID)
|
||||
|
||||
self.cgsnapshot = fake_cgsnapshot.fake_cgsnapshot_obj(
|
||||
admin_contex, id=ID, consistencygroup_id=ID, status='available')
|
||||
self.group_snapshot = fake_group_snapshot.fake_group_snapshot_obj(
|
||||
admin_contex, id=ID, group_id=ID, status='available')
|
||||
|
||||
self.cg = fake_consistencygroup.fake_consistencyobject_obj(
|
||||
self.group = fake_group.fake_group_obj(
|
||||
admin_contex, id=ID, status='available')
|
||||
|
||||
def test_encode_name(self):
|
||||
@ -4286,49 +4297,52 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase):
|
||||
iqn = self.driver.client._get_tgt_iqn_from_rest(ip)
|
||||
self.assertIsNone(iqn)
|
||||
|
||||
def test_create_cgsnapshot(self):
|
||||
@cg_or_cg_snapshot
|
||||
def test_create_group_snapshot(self):
|
||||
test_snapshots = [self.snapshot]
|
||||
ctxt = context.get_admin_context()
|
||||
model, snapshots = self.driver.create_cgsnapshot(ctxt,
|
||||
self.cgsnapshot,
|
||||
test_snapshots)
|
||||
model, snapshots = (
|
||||
self.driver.create_group_snapshot(ctxt, self.group_snapshot,
|
||||
test_snapshots))
|
||||
snapshots_model_update = [{'id': '21ec7341-9256-497b-97d9'
|
||||
'-ef48edcf0635',
|
||||
'status': 'available',
|
||||
'provider_location': 11}]
|
||||
self.assertEqual(snapshots_model_update, snapshots)
|
||||
self.assertEqual('available', model['status'])
|
||||
self.assertEqual(fields.GroupSnapshotStatus.AVAILABLE, model['status'])
|
||||
|
||||
def test_create_cgsnapshot_create_snapshot_fail(self):
|
||||
@cg_or_cg_snapshot
|
||||
def test_create_group_snapshot_with_create_snapshot_fail(self):
|
||||
test_snapshots = [self.snapshot]
|
||||
ctxt = context.get_admin_context()
|
||||
self.mock_object(rest_client.RestClient, 'create_snapshot',
|
||||
side_effect=(
|
||||
exception.VolumeBackendAPIException(data='err')))
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_cgsnapshot,
|
||||
self.driver.create_group_snapshot,
|
||||
ctxt,
|
||||
self.cgsnapshot,
|
||||
self.group_snapshot,
|
||||
test_snapshots)
|
||||
|
||||
def test_create_cgsnapshot_active_snapshot_fail(self):
|
||||
@cg_or_cg_snapshot
|
||||
def test_create_group_snapshot_with_active_snapshot_fail(self):
|
||||
test_snapshots = [self.snapshot]
|
||||
ctxt = context.get_admin_context()
|
||||
self.mock_object(rest_client.RestClient, 'activate_snapshot',
|
||||
side_effect=(
|
||||
exception.VolumeBackendAPIException(data='err')))
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_cgsnapshot,
|
||||
self.driver.create_group_snapshot,
|
||||
ctxt,
|
||||
self.cgsnapshot,
|
||||
self.group_snapshot,
|
||||
test_snapshots)
|
||||
|
||||
def test_delete_cgsnapshot(self):
|
||||
@cg_or_cg_snapshot
|
||||
def test_delete_group_snapshot(self):
|
||||
test_snapshots = [self.snapshot]
|
||||
ctxt = context.get_admin_context()
|
||||
self.driver.delete_cgsnapshot(ctxt,
|
||||
self.cgsnapshot,
|
||||
test_snapshots)
|
||||
self.driver.delete_group_snapshot(ctxt, self.group_snapshot,
|
||||
test_snapshots)
|
||||
|
||||
|
||||
class FCSanLookupService(object):
|
||||
@ -5109,95 +5123,81 @@ class HuaweiFCDriverTestCase(HuaweiTestBase):
|
||||
self.assertFalse(res)
|
||||
|
||||
@mock.patch.object(huawei_driver.HuaweiBaseDriver,
|
||||
'_get_consistencygroup_type',
|
||||
return_value={"hypermetro": "true"})
|
||||
def test_create_hypermetro_consistencygroup_success(self, mock_grouptype):
|
||||
"""Test that create_consistencygroup return successfully."""
|
||||
'_get_group_type',
|
||||
return_value=[{"hypermetro": "true"}])
|
||||
@cg_or_cg_snapshot
|
||||
def test_create_hypermetro_group_success(self, mock_grouptype):
|
||||
"""Test that create_group return successfully."""
|
||||
ctxt = context.get_admin_context()
|
||||
# Create consistency group
|
||||
model_update = self.driver.create_consistencygroup(ctxt, self.cg)
|
||||
# Create group
|
||||
model_update = self.driver.create_group(ctxt, self.group)
|
||||
|
||||
self.assertEqual('available',
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'],
|
||||
"Consistency Group created failed")
|
||||
"Group created failed")
|
||||
|
||||
@mock.patch.object(huawei_driver.HuaweiBaseDriver,
|
||||
'_get_consistencygroup_type',
|
||||
return_value={"hypermetro": "false"})
|
||||
def test_create_normal_consistencygroup_success(self,
|
||||
mock_grouptype):
|
||||
"""Test that create_consistencygroup return successfully."""
|
||||
'_get_group_type',
|
||||
return_value=[{"hypermetro": "false"}])
|
||||
@cg_or_cg_snapshot
|
||||
def test_create_normal_group_success(self, mock_grouptype):
|
||||
"""Test that create_group return successfully."""
|
||||
ctxt = context.get_admin_context()
|
||||
# Create consistency group
|
||||
model_update = self.driver.create_consistencygroup(ctxt, self.cg)
|
||||
# Create group
|
||||
model_update = self.driver.create_group(ctxt, self.group)
|
||||
|
||||
self.assertEqual('available',
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update['status'],
|
||||
"Consistency Group created failed")
|
||||
"Group created failed")
|
||||
|
||||
@mock.patch.object(huawei_driver.HuaweiBaseDriver,
|
||||
'_get_consistencygroup_type',
|
||||
return_value={"hypermetro": "true"})
|
||||
def test_delete_hypermetro_consistencygroup_success(self, mock_grouptype):
|
||||
"""Test that create_consistencygroup return successfully."""
|
||||
'_get_group_type',
|
||||
return_value=[{"hypermetro": "true"}])
|
||||
@cg_or_cg_snapshot
|
||||
def test_delete_hypermetro_group_success(self, mock_grouptype):
|
||||
"""Test that delete_group return successfully."""
|
||||
test_volumes = [self.volume]
|
||||
ctxt = context.get_admin_context()
|
||||
# Create consistency group
|
||||
model, volumes = self.driver.delete_consistencygroup(ctxt,
|
||||
self.cg,
|
||||
test_volumes)
|
||||
self.assertEqual('available',
|
||||
# Delete group
|
||||
model, volumes = self.driver.delete_group(ctxt, self.group,
|
||||
test_volumes)
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model['status'],
|
||||
"Consistency Group created failed")
|
||||
|
||||
def test_delete_normal_consistencygroup_success(self):
|
||||
ctxt = context.get_admin_context()
|
||||
test_volumes = [self.volume]
|
||||
self.mock_object(huawei_driver.HuaweiBaseDriver,
|
||||
'_get_consistencygroup_type',
|
||||
return_value={"hypermetro": "false"})
|
||||
|
||||
model, volumes = self.driver.delete_consistencygroup(ctxt,
|
||||
self.cg,
|
||||
test_volumes)
|
||||
self.assertEqual('available',
|
||||
model['status'],
|
||||
"Consistency Group created failed")
|
||||
"Group deleted failed")
|
||||
|
||||
@mock.patch.object(huawei_driver.HuaweiBaseDriver,
|
||||
'_get_consistencygroup_type',
|
||||
return_value={"hypermetro": "true"})
|
||||
'_get_group_type',
|
||||
return_value=[{"hypermetro": "false"}])
|
||||
@cg_or_cg_snapshot
|
||||
def test_delete_normal_group_success(self, mock_grouptype):
|
||||
"""Test that delete_group return successfully."""
|
||||
ctxt = context.get_admin_context()
|
||||
test_volumes = [self.volume]
|
||||
# Delete group
|
||||
model, volumes = self.driver.delete_group(ctxt, self.group,
|
||||
test_volumes)
|
||||
self.assertEqual(fields.GroupStatus.DELETED,
|
||||
model['status'],
|
||||
"Group deleted failed")
|
||||
|
||||
@mock.patch.object(huawei_driver.HuaweiBaseDriver,
|
||||
'_get_group_type',
|
||||
return_value=[{"hypermetro": "true"}])
|
||||
@mock.patch.object(huawei_driver.huawei_utils, 'get_volume_metadata',
|
||||
return_value={'hypermetro_id': '3400a30d844d0007',
|
||||
'remote_lun_id': '59'})
|
||||
def test_update_consistencygroup_success(self,
|
||||
mock_grouptype,
|
||||
mock_metadata):
|
||||
"""Test that create_consistencygroup return successfully."""
|
||||
@cg_or_cg_snapshot
|
||||
def test_update_group_success(self, mock_grouptype, mock_metadata):
|
||||
"""Test that update_group return successfully."""
|
||||
ctxt = context.get_admin_context()
|
||||
add_volumes = [self.volume]
|
||||
remove_volumes = [self.volume]
|
||||
# Create consistency group
|
||||
model_update = self.driver.update_consistencygroup(ctxt,
|
||||
self.cg,
|
||||
add_volumes,
|
||||
remove_volumes)
|
||||
self.assertEqual('available',
|
||||
# Update group
|
||||
model_update = self.driver.update_group(ctxt, self.group,
|
||||
add_volumes, remove_volumes)
|
||||
self.assertEqual(fields.GroupStatus.AVAILABLE,
|
||||
model_update[0]['status'],
|
||||
"Consistency Group update failed")
|
||||
|
||||
def test_create_hypermetro_consistencygroup_success_2(self):
|
||||
ctxt = context.get_admin_context()
|
||||
# Create consistency group
|
||||
temp_cg = copy.deepcopy(self.cg)
|
||||
temp_cg['volume_type_id'] = '550c089b-bfdd-4f7f-86e1-3ba88125555c,'
|
||||
self.mock_object(volume_types, 'get_volume_type',
|
||||
return_value=test_hypermetro_type)
|
||||
model_update = self.driver.create_consistencygroup(ctxt, temp_cg)
|
||||
|
||||
self.assertEqual('available',
|
||||
model_update['status'],
|
||||
"Consistency Group created failed")
|
||||
"Group update failed")
|
||||
|
||||
def test_is_initiator_associated_to_host_raise(self):
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
|
@ -29,6 +29,7 @@ from cinder import context
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import interface
|
||||
from cinder.objects import fields
|
||||
from cinder import utils
|
||||
from cinder.volume import driver
|
||||
from cinder.volume.drivers.huawei import constants
|
||||
@ -191,6 +192,7 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
pool['thick_provisioning_support'] = True
|
||||
pool['thin_provisioning_support'] = True
|
||||
pool['smarttier'] = True
|
||||
pool['consistent_group_snapshot_enabled'] = True
|
||||
|
||||
if self.configuration.san_product == "Dorado":
|
||||
pool['smarttier'] = False
|
||||
@ -198,8 +200,6 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
|
||||
if self.metro_flag:
|
||||
pool['hypermetro'] = self.check_func_support("HyperMetroPair")
|
||||
pool['consistencygroup_support'] = (
|
||||
self.check_func_support("HyperMetro_ConsistentGroup"))
|
||||
|
||||
# Asign the support function to global paramenter.
|
||||
self.support_func = pool
|
||||
@ -224,17 +224,28 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
opts = self._get_volume_params_from_specs(specs)
|
||||
return opts
|
||||
|
||||
def _get_consistencygroup_type(self, group):
|
||||
specs = {}
|
||||
opts = {}
|
||||
type_id = group.volume_type_id.split(",")
|
||||
if type_id[0] and len(type_id) == 2:
|
||||
ctxt = context.get_admin_context()
|
||||
volume_type = volume_types.get_volume_type(ctxt, type_id[0])
|
||||
specs = dict(volume_type).get('extra_specs')
|
||||
opts = self._get_volume_params_from_specs(specs)
|
||||
def _get_group_type(self, group):
|
||||
opts = []
|
||||
vol_types = group.volume_types
|
||||
|
||||
for vol_type in vol_types:
|
||||
specs = vol_type.extra_specs
|
||||
opts.append(self._get_volume_params_from_specs(specs))
|
||||
|
||||
return opts
|
||||
|
||||
def _check_volume_type_support(self, opts, vol_type):
|
||||
if not opts:
|
||||
return False
|
||||
|
||||
support = True
|
||||
for opt in opts:
|
||||
if opt.get(vol_type) != 'true':
|
||||
support = False
|
||||
break
|
||||
|
||||
return support
|
||||
|
||||
def _get_volume_params_from_specs(self, specs):
|
||||
"""Return the volume parameters from extra specs."""
|
||||
opts_capability = {
|
||||
@ -1599,24 +1610,26 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
self.client.is_host_associated_to_hostgroup(host_id)):
|
||||
self.client.remove_host(host_id)
|
||||
|
||||
def create_consistencygroup(self, context, group):
|
||||
"""Creates a consistencygroup."""
|
||||
model_update = {'status': 'available'}
|
||||
opts = self._get_consistencygroup_type(group)
|
||||
if (opts.get('hypermetro') == 'true'):
|
||||
@huawei_utils.check_whether_operate_consistency_group
|
||||
def create_group(self, context, group):
|
||||
"""Creates a group."""
|
||||
model_update = {'status': fields.GroupStatus.AVAILABLE}
|
||||
opts = self._get_group_type(group)
|
||||
if self._check_volume_type_support(opts, 'hypermetro'):
|
||||
metro = hypermetro.HuaweiHyperMetro(self.client,
|
||||
self.rmt_client,
|
||||
self.configuration)
|
||||
metro.create_consistencygroup(group)
|
||||
return model_update
|
||||
|
||||
# Array will create CG at create_cgsnapshot time. Cinder will
|
||||
# maintain the CG and volumes relationship in the db.
|
||||
# Array will create group at create_group_snapshot time. Cinder will
|
||||
# maintain the group and volumes relationship in the db.
|
||||
return model_update
|
||||
|
||||
def delete_consistencygroup(self, context, group, volumes):
|
||||
opts = self._get_consistencygroup_type(group)
|
||||
if opts.get('hypermetro') == 'true':
|
||||
@huawei_utils.check_whether_operate_consistency_group
|
||||
def delete_group(self, context, group, volumes):
|
||||
opts = self._get_group_type(group)
|
||||
if self._check_volume_type_support(opts, 'hypermetro'):
|
||||
metro = hypermetro.HuaweiHyperMetro(self.client,
|
||||
self.rmt_client,
|
||||
self.configuration)
|
||||
@ -1624,7 +1637,7 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
|
||||
model_update = {}
|
||||
volumes_model_update = []
|
||||
model_update.update({'status': group.status})
|
||||
model_update.update({'status': fields.GroupStatus.DELETED})
|
||||
|
||||
for volume_ref in volumes:
|
||||
try:
|
||||
@ -1637,12 +1650,12 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
|
||||
return model_update, volumes_model_update
|
||||
|
||||
def update_consistencygroup(self, context, group,
|
||||
add_volumes,
|
||||
remove_volumes):
|
||||
model_update = {'status': 'available'}
|
||||
opts = self._get_consistencygroup_type(group)
|
||||
if opts.get('hypermetro') == 'true':
|
||||
@huawei_utils.check_whether_operate_consistency_group
|
||||
def update_group(self, context, group,
|
||||
add_volumes=None, remove_volumes=None):
|
||||
model_update = {'status': fields.GroupStatus.AVAILABLE}
|
||||
opts = self._get_group_type(group)
|
||||
if self._check_volume_type_support(opts, 'hypermetro'):
|
||||
metro = hypermetro.HuaweiHyperMetro(self.client,
|
||||
self.rmt_client,
|
||||
self.configuration)
|
||||
@ -1651,15 +1664,23 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
remove_volumes)
|
||||
return model_update, None, None
|
||||
|
||||
# Array will create CG at create_cgsnapshot time. Cinder will
|
||||
# maintain the CG and volumes relationship in the db.
|
||||
# Array will create group at create_group_snapshot time. Cinder will
|
||||
# maintain the group and volumes relationship in the db.
|
||||
return model_update, None, None
|
||||
|
||||
def create_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Create cgsnapshot."""
|
||||
LOG.info('Create cgsnapshot for consistency group'
|
||||
': %(group_id)s',
|
||||
{'group_id': cgsnapshot.consistencygroup_id})
|
||||
@huawei_utils.check_whether_operate_consistency_group
|
||||
def create_group_from_src(self, context, group, volumes,
|
||||
group_snapshot=None, snapshots=None,
|
||||
source_group=None, source_vols=None):
|
||||
err_msg = _("Huawei Storage doesn't support create_group_from_src.")
|
||||
LOG.error(err_msg)
|
||||
raise exception.VolumeBackendAPIException(data=err_msg)
|
||||
|
||||
@huawei_utils.check_whether_operate_consistency_group
|
||||
def create_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Create group snapshot."""
|
||||
LOG.info('Create group snapshot for group'
|
||||
': %(group_id)s', {'group_id': group_snapshot.group_id})
|
||||
|
||||
model_update = {}
|
||||
snapshots_model_update = []
|
||||
@ -1682,48 +1703,50 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
info = self.client.create_snapshot(lun_id,
|
||||
snapshot_name,
|
||||
snapshot_description)
|
||||
snapshot_model_update = {'id': snapshot.id,
|
||||
'status': 'available',
|
||||
'provider_location': info['ID']}
|
||||
snapshots_model_update.append(snapshot_model_update)
|
||||
snap_model_update = {'id': snapshot.id,
|
||||
'status': fields.SnapshotStatus.AVAILABLE,
|
||||
'provider_location': info['ID']}
|
||||
snapshots_model_update.append(snap_model_update)
|
||||
added_snapshots_info.append(info)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("Create cgsnapshots failed. "
|
||||
"Cgsnapshot id: %s.", cgsnapshot.id)
|
||||
LOG.error("Create group snapshots failed. "
|
||||
"Group snapshot id: %s.", group_snapshot.id)
|
||||
snapshot_ids = [added_snapshot['ID']
|
||||
for added_snapshot in added_snapshots_info]
|
||||
try:
|
||||
self.client.activate_snapshot(snapshot_ids)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("Active cgsnapshots failed. "
|
||||
"Cgsnapshot id: %s.", cgsnapshot.id)
|
||||
LOG.error("Active group snapshots failed. "
|
||||
"Group snapshot id: %s.", group_snapshot.id)
|
||||
|
||||
model_update['status'] = 'available'
|
||||
model_update['status'] = fields.GroupSnapshotStatus.AVAILABLE
|
||||
|
||||
return model_update, snapshots_model_update
|
||||
|
||||
def delete_cgsnapshot(self, context, cgsnapshot, snapshots):
|
||||
"""Delete consistency group snapshot."""
|
||||
LOG.info('Delete cgsnapshot %(snap_id)s for consistency group: '
|
||||
@huawei_utils.check_whether_operate_consistency_group
|
||||
def delete_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
"""Delete group snapshot."""
|
||||
LOG.info('Delete group snapshot %(snap_id)s for group: '
|
||||
'%(group_id)s',
|
||||
{'snap_id': cgsnapshot.id,
|
||||
'group_id': cgsnapshot.consistencygroup_id})
|
||||
{'snap_id': group_snapshot.id,
|
||||
'group_id': group_snapshot.group_id})
|
||||
|
||||
model_update = {}
|
||||
snapshots_model_update = []
|
||||
model_update['status'] = cgsnapshot.status
|
||||
model_update['status'] = fields.GroupSnapshotStatus.DELETED
|
||||
|
||||
for snapshot in snapshots:
|
||||
try:
|
||||
self.delete_snapshot(snapshot)
|
||||
snapshots_model_update.append({'id': snapshot.id,
|
||||
'status': 'deleted'})
|
||||
snapshot_model = {'id': snapshot.id,
|
||||
'status': fields.SnapshotStatus.DELETED}
|
||||
snapshots_model_update.append(snapshot_model)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("Delete cg snapshots failed. "
|
||||
"Cgsnapshot id: %s", cgsnapshot.id)
|
||||
LOG.error("Delete group snapshot failed. "
|
||||
"Group snapshot id: %s", group_snapshot.id)
|
||||
|
||||
return model_update, snapshots_model_update
|
||||
|
||||
|
@ -24,6 +24,7 @@ from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import objects
|
||||
from cinder.volume.drivers.huawei import constants
|
||||
from cinder.volume import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -112,3 +113,14 @@ def get_snapshot_metadata_value(snapshot):
|
||||
return {item['key']: item['value'] for item in metadata}
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
def check_whether_operate_consistency_group(func):
|
||||
def wrapper(self, context, group, *args, **kwargs):
|
||||
if not utils.is_group_a_cg_snapshot_type(group):
|
||||
msg = _("%s, the group or group snapshot is not cg or "
|
||||
"cg_snapshot") % func.__name__
|
||||
LOG.debug(msg)
|
||||
raise NotImplementedError(msg)
|
||||
return func(self, context, group, *args, **kwargs)
|
||||
return wrapper
|
||||
|
@ -18,6 +18,7 @@ from oslo_log import log as logging
|
||||
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder.objects import fields
|
||||
from cinder.volume.drivers.huawei import constants
|
||||
from cinder.volume.drivers.huawei import huawei_utils
|
||||
|
||||
@ -286,7 +287,7 @@ class HuaweiHyperMetro(object):
|
||||
{'group': group.id})
|
||||
model_update = {}
|
||||
volumes_model_update = []
|
||||
model_update['status'] = group.status
|
||||
model_update['status'] = fields.GroupStatus.DELETED
|
||||
metrogroup_id = self.check_consistencygroup_need_to_stop(group)
|
||||
if metrogroup_id:
|
||||
self.client.delete_metrogroup(metrogroup_id)
|
||||
@ -304,8 +305,6 @@ class HuaweiHyperMetro(object):
|
||||
LOG.info("Update Consistency Group: %(group)s. "
|
||||
"This adds or removes volumes from a CG.",
|
||||
{'group': group.id})
|
||||
model_update = {}
|
||||
model_update['status'] = group.status
|
||||
metrogroup_id = self.check_consistencygroup_need_to_stop(group)
|
||||
if metrogroup_id:
|
||||
# Deal with add volumes to CG
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Add CG capability to generic volume groups in Huawei driver.
|
Loading…
Reference in New Issue
Block a user