Use resource_backend for volumes and groups
resource_backend should be used during groups update validation procedure instead of 'host' attribute because it works well both in clustered and single node deployments. Change-Id: I4f80bb3e39e04ac5c524c7c1ad8859eef76a910a Closes-Bug: #1876133
This commit is contained in:
parent
fff95fa6a6
commit
7d211d6221
@ -723,7 +723,7 @@ class API(base.Base):
|
|||||||
|
|
||||||
for add_vol in add_volumes_list:
|
for add_vol in add_volumes_list:
|
||||||
try:
|
try:
|
||||||
add_vol_ref = self.db.volume_get(context, add_vol)
|
add_vol_ref = objects.Volume.get_by_id(context, add_vol)
|
||||||
except exception.VolumeNotFound:
|
except exception.VolumeNotFound:
|
||||||
msg = (_("Cannot add volume %(volume_id)s to "
|
msg = (_("Cannot add volume %(volume_id)s to "
|
||||||
"group %(group_id)s because volume cannot be "
|
"group %(group_id)s because volume cannot be "
|
||||||
@ -731,7 +731,7 @@ class API(base.Base):
|
|||||||
{'volume_id': add_vol,
|
{'volume_id': add_vol,
|
||||||
'group_id': group.id})
|
'group_id': group.id})
|
||||||
raise exception.InvalidVolume(reason=msg)
|
raise exception.InvalidVolume(reason=msg)
|
||||||
orig_group = add_vol_ref.get('group_id', None)
|
orig_group = add_vol_ref.group_id
|
||||||
if orig_group:
|
if orig_group:
|
||||||
# If volume to be added is already in the group to be updated,
|
# If volume to be added is already in the group to be updated,
|
||||||
# it should have been removed from the add_volumes_list in the
|
# it should have been removed from the add_volumes_list in the
|
||||||
@ -740,7 +740,7 @@ class API(base.Base):
|
|||||||
msg = (_("Cannot add volume %(volume_id)s to group "
|
msg = (_("Cannot add volume %(volume_id)s to group "
|
||||||
"%(group_id)s because it is already in "
|
"%(group_id)s because it is already in "
|
||||||
"group %(orig_group)s.") %
|
"group %(orig_group)s.") %
|
||||||
{'volume_id': add_vol_ref['id'],
|
{'volume_id': add_vol_ref.id,
|
||||||
'group_id': group.id,
|
'group_id': group.id,
|
||||||
'orig_group': orig_group})
|
'orig_group': orig_group})
|
||||||
raise exception.InvalidVolume(reason=msg)
|
raise exception.InvalidVolume(reason=msg)
|
||||||
@ -749,15 +749,15 @@ class API(base.Base):
|
|||||||
msg = (_("Cannot add volume %(volume_id)s to group "
|
msg = (_("Cannot add volume %(volume_id)s to group "
|
||||||
"%(group_id)s as they belong to different "
|
"%(group_id)s as they belong to different "
|
||||||
"projects.") %
|
"projects.") %
|
||||||
{'volume_id': add_vol_ref['id'],
|
{'volume_id': add_vol_ref.id,
|
||||||
'group_id': group.id})
|
'group_id': group.id})
|
||||||
raise exception.InvalidVolume(reason=msg)
|
raise exception.InvalidVolume(reason=msg)
|
||||||
add_vol_type_id = add_vol_ref.get('volume_type_id', None)
|
add_vol_type_id = add_vol_ref.volume_type_id
|
||||||
if not add_vol_type_id:
|
if not add_vol_type_id:
|
||||||
msg = (_("Cannot add volume %(volume_id)s to group "
|
msg = (_("Cannot add volume %(volume_id)s to group "
|
||||||
"%(group_id)s because it has no volume "
|
"%(group_id)s because it has no volume "
|
||||||
"type.") %
|
"type.") %
|
||||||
{'volume_id': add_vol_ref['id'],
|
{'volume_id': add_vol_ref.id,
|
||||||
'group_id': group.id})
|
'group_id': group.id})
|
||||||
raise exception.InvalidVolume(reason=msg)
|
raise exception.InvalidVolume(reason=msg)
|
||||||
vol_type_ids = [v_type.id for v_type in group.volume_types]
|
vol_type_ids = [v_type.id for v_type in group.volume_types]
|
||||||
@ -766,27 +766,29 @@ class API(base.Base):
|
|||||||
"%(group_id)s because volume type "
|
"%(group_id)s because volume type "
|
||||||
"%(volume_type)s is not supported by the "
|
"%(volume_type)s is not supported by the "
|
||||||
"group.") %
|
"group.") %
|
||||||
{'volume_id': add_vol_ref['id'],
|
{'volume_id': add_vol_ref.id,
|
||||||
'group_id': group.id,
|
'group_id': group.id,
|
||||||
'volume_type': add_vol_type_id})
|
'volume_type': add_vol_type_id})
|
||||||
raise exception.InvalidVolume(reason=msg)
|
raise exception.InvalidVolume(reason=msg)
|
||||||
if (add_vol_ref['status'] not in
|
if (add_vol_ref.status not in
|
||||||
VALID_ADD_VOL_TO_GROUP_STATUS):
|
VALID_ADD_VOL_TO_GROUP_STATUS):
|
||||||
msg = (_("Cannot add volume %(volume_id)s to group "
|
msg = (_("Cannot add volume %(volume_id)s to group "
|
||||||
"%(group_id)s because volume is in an "
|
"%(group_id)s because volume is in an "
|
||||||
"invalid state: %(status)s. Valid states are: "
|
"invalid state: %(status)s. Valid states are: "
|
||||||
"%(valid)s.") %
|
"%(valid)s.") %
|
||||||
{'volume_id': add_vol_ref['id'],
|
{'volume_id': add_vol_ref.id,
|
||||||
'group_id': group.id,
|
'group_id': group.id,
|
||||||
'status': add_vol_ref['status'],
|
'status': add_vol_ref.status,
|
||||||
'valid': VALID_ADD_VOL_TO_GROUP_STATUS})
|
'valid': VALID_ADD_VOL_TO_GROUP_STATUS})
|
||||||
raise exception.InvalidVolume(reason=msg)
|
raise exception.InvalidVolume(reason=msg)
|
||||||
|
|
||||||
# group.host and add_vol_ref['host'] are in this format:
|
# group.resource_backend and add_vol_ref.resource_backend are
|
||||||
# 'host@backend#pool'. Extract host (host@backend) before
|
# in this format like 'host@backend#pool' in a non-HA
|
||||||
# doing comparison.
|
# deployment and will contain cluster_name in
|
||||||
vol_host = volume_utils.extract_host(add_vol_ref['host'])
|
# A/A HA deployment.
|
||||||
group_host = volume_utils.extract_host(group.host)
|
vol_host = volume_utils.extract_host(
|
||||||
|
add_vol_ref.resource_backend)
|
||||||
|
group_host = volume_utils.extract_host(group.resource_backend)
|
||||||
if group_host != vol_host:
|
if group_host != vol_host:
|
||||||
raise exception.InvalidVolume(
|
raise exception.InvalidVolume(
|
||||||
reason=_("Volume is not local to this node."))
|
reason=_("Volume is not local to this node."))
|
||||||
@ -794,12 +796,12 @@ class API(base.Base):
|
|||||||
# Volume exists. It will be added to CG.
|
# Volume exists. It will be added to CG.
|
||||||
if add_volumes_new:
|
if add_volumes_new:
|
||||||
add_volumes_new += ","
|
add_volumes_new += ","
|
||||||
add_volumes_new += add_vol_ref['id']
|
add_volumes_new += add_vol_ref.id
|
||||||
|
|
||||||
else:
|
else:
|
||||||
msg = (_("Cannot add volume %(volume_id)s to group "
|
msg = (_("Cannot add volume %(volume_id)s to group "
|
||||||
"%(group_id)s because volume does not exist.") %
|
"%(group_id)s because volume does not exist.") %
|
||||||
{'volume_id': add_vol_ref['id'],
|
{'volume_id': add_vol_ref.id,
|
||||||
'group_id': group.id})
|
'group_id': group.id})
|
||||||
raise exception.InvalidVolume(reason=msg)
|
raise exception.InvalidVolume(reason=msg)
|
||||||
|
|
||||||
|
@ -274,6 +274,8 @@ class GroupAPITestCase(test.TestCase):
|
|||||||
self.group_api._validate_add_volumes, self.ctxt,
|
self.group_api._validate_add_volumes, self.ctxt,
|
||||||
[], ['123456789'], grp)
|
[], ['123456789'], grp)
|
||||||
|
|
||||||
|
@ddt.data(['test_host@fakedrv#fakepool', 'test_host@fakedrv#fakepool'],
|
||||||
|
['test_host@fakedrv#fakepool', 'test_host2@fakedrv#fakepool'])
|
||||||
@mock.patch('cinder.volume.rpcapi.VolumeAPI.update_group')
|
@mock.patch('cinder.volume.rpcapi.VolumeAPI.update_group')
|
||||||
@mock.patch('cinder.db.volume_get_all_by_generic_group')
|
@mock.patch('cinder.db.volume_get_all_by_generic_group')
|
||||||
@mock.patch('cinder.group.api.API._cast_create_group')
|
@mock.patch('cinder.group.api.API._cast_create_group')
|
||||||
@ -281,7 +283,7 @@ class GroupAPITestCase(test.TestCase):
|
|||||||
@mock.patch('cinder.objects.Group')
|
@mock.patch('cinder.objects.Group')
|
||||||
@mock.patch('cinder.db.group_type_get')
|
@mock.patch('cinder.db.group_type_get')
|
||||||
@mock.patch('cinder.db.volume_types_get_by_name_or_id')
|
@mock.patch('cinder.db.volume_types_get_by_name_or_id')
|
||||||
def test_update(self, mock_volume_types_get,
|
def test_update(self, hosts, mock_volume_types_get,
|
||||||
mock_group_type_get, mock_group,
|
mock_group_type_get, mock_group,
|
||||||
mock_update_quota, mock_cast_create_group,
|
mock_update_quota, mock_cast_create_group,
|
||||||
mock_volume_get_all, mock_rpc_update_group):
|
mock_volume_get_all, mock_rpc_update_group):
|
||||||
@ -307,26 +309,32 @@ class GroupAPITestCase(test.TestCase):
|
|||||||
self.assertEqual(grp.obj_to_primitive(), ret_group.obj_to_primitive())
|
self.assertEqual(grp.obj_to_primitive(), ret_group.obj_to_primitive())
|
||||||
|
|
||||||
ret_group.volume_types = [vol_type]
|
ret_group.volume_types = [vol_type]
|
||||||
ret_group.host = "test_host@fakedrv#fakepool"
|
ret_group.host = hosts[0]
|
||||||
|
# set resource_backend directly because ret_group
|
||||||
|
# is instance of MagicMock
|
||||||
|
ret_group.resource_backend = 'fake-cluster'
|
||||||
ret_group.status = fields.GroupStatus.AVAILABLE
|
ret_group.status = fields.GroupStatus.AVAILABLE
|
||||||
|
|
||||||
ret_group.id = fake.GROUP_ID
|
ret_group.id = fake.GROUP_ID
|
||||||
|
|
||||||
vol1 = utils.create_volume(
|
vol1 = utils.create_volume(
|
||||||
self.ctxt, host=ret_group.host,
|
self.ctxt, host=hosts[1],
|
||||||
availability_zone=ret_group.availability_zone,
|
|
||||||
volume_type_id=fake.VOLUME_TYPE_ID)
|
|
||||||
|
|
||||||
vol2 = utils.create_volume(
|
|
||||||
self.ctxt, host=ret_group.host,
|
|
||||||
availability_zone=ret_group.availability_zone,
|
availability_zone=ret_group.availability_zone,
|
||||||
volume_type_id=fake.VOLUME_TYPE_ID,
|
volume_type_id=fake.VOLUME_TYPE_ID,
|
||||||
group_id=fake.GROUP_ID)
|
cluster_name='fake-cluster')
|
||||||
|
|
||||||
|
vol2 = utils.create_volume(
|
||||||
|
self.ctxt, host=hosts[1],
|
||||||
|
availability_zone=ret_group.availability_zone,
|
||||||
|
volume_type_id=fake.VOLUME_TYPE_ID,
|
||||||
|
group_id=fake.GROUP_ID,
|
||||||
|
cluster_name='fake-cluster')
|
||||||
vol2_dict = {
|
vol2_dict = {
|
||||||
'id': vol2.id,
|
'id': vol2.id,
|
||||||
'group_id': fake.GROUP_ID,
|
'group_id': fake.GROUP_ID,
|
||||||
'volume_type_id': fake.VOLUME_TYPE_ID,
|
'volume_type_id': fake.VOLUME_TYPE_ID,
|
||||||
'availability_zone': ret_group.availability_zone,
|
'availability_zone': ret_group.availability_zone,
|
||||||
'host': ret_group.host,
|
'host': hosts[1],
|
||||||
'status': 'available',
|
'status': 'available',
|
||||||
}
|
}
|
||||||
mock_volume_get_all.return_value = [vol2_dict]
|
mock_volume_get_all.return_value = [vol2_dict]
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixed volume group action in Active/Active HA deployment:
|
||||||
|
|
||||||
|
* Update group
|
||||||
|
(`#1876133 <https://bugs.launchpad.net/cinder/+bug/1876133>`_)
|
||||||
|
|
||||||
|
* Create group from group snapshot
|
||||||
|
(`#1867906 <https://bugs.launchpad.net/cinder/+bug/1867906>`_)
|
Loading…
Reference in New Issue
Block a user