Set cluster name for volume groups
In Active/Active HA mode we need to store not only worker hostname but cluster name too. This patch saves cluster name for groups created from other groups or snaphshots. Change-Id: I6f160cc44350f0d378fdddb7943e8cdcc15be1b8 Closes-Bug: #1867906
This commit is contained in:
parent
8bf454b0b5
commit
8d67562831
@ -6129,15 +6129,18 @@ def group_create(context, values, group_snapshot_id=None,
|
||||
values.pop('group_type_id', None)
|
||||
values.pop('availability_zone', None)
|
||||
values.pop('host', None)
|
||||
values.pop('cluster_name', None)
|
||||
# NOTE(xyang): Save volume_type_ids to update later.
|
||||
volume_type_ids = values.pop('volume_type_ids', [])
|
||||
|
||||
sel = session.query(group_model.group_type_id,
|
||||
group_model.availability_zone,
|
||||
group_model.host,
|
||||
group_model.cluster_name,
|
||||
*(bindparam(k, v) for k, v in values.items())
|
||||
).filter(*conditions)
|
||||
names = ['group_type_id', 'availability_zone', 'host']
|
||||
names = ['group_type_id', 'availability_zone', 'host',
|
||||
'cluster_name']
|
||||
names.extend(values.keys())
|
||||
insert_stmt = group_model.__table__.insert().from_select(
|
||||
names, sel)
|
||||
|
@ -97,6 +97,15 @@ class API(base.Base):
|
||||
|
||||
return availability_zone
|
||||
|
||||
def _update_volumes_host(self, context, group):
|
||||
volumes = objects.VolumeList.get_all_by_generic_group(context,
|
||||
group.id)
|
||||
for vol in volumes:
|
||||
# Update the host field for the volume.
|
||||
vol.host = group.host
|
||||
vol.cluster_name = group.cluster_name
|
||||
vol.save()
|
||||
|
||||
def create(self, context, name, description, group_type,
|
||||
volume_types, availability_zone=None):
|
||||
context.authorize(group_policy.CREATE_POLICY)
|
||||
@ -247,8 +256,9 @@ class API(base.Base):
|
||||
kwargs = {'group_id': group.id,
|
||||
'volume_properties': objects.VolumeProperties(size=size)}
|
||||
|
||||
if not group.host or not self.scheduler_rpcapi.validate_host_capacity(
|
||||
context, group.host, objects.RequestSpec(**kwargs)):
|
||||
host = group.resource_backend
|
||||
if not host or not self.scheduler_rpcapi.validate_host_capacity(
|
||||
context, host, objects.RequestSpec(**kwargs)):
|
||||
msg = _("No valid host to create group %s.") % group.id
|
||||
LOG.error(msg)
|
||||
raise exception.InvalidGroup(reason=msg)
|
||||
@ -335,12 +345,7 @@ class API(base.Base):
|
||||
{'group': group.id,
|
||||
'group_snap': group_snapshot.id})
|
||||
|
||||
volumes = objects.VolumeList.get_all_by_generic_group(context,
|
||||
group.id)
|
||||
for vol in volumes:
|
||||
# Update the host field for the volume.
|
||||
vol.host = group.host
|
||||
vol.save()
|
||||
self._update_volumes_host(context, group)
|
||||
|
||||
self.volume_rpcapi.create_group_from_src(
|
||||
context, group, group_snapshot)
|
||||
@ -418,12 +423,7 @@ class API(base.Base):
|
||||
{'group': group.id,
|
||||
'source_group': source_group.id})
|
||||
|
||||
volumes = objects.VolumeList.get_all_by_generic_group(context,
|
||||
group.id)
|
||||
for vol in volumes:
|
||||
# Update the host field for the volume.
|
||||
vol.host = group.host
|
||||
vol.save()
|
||||
self._update_volumes_host(context, group)
|
||||
|
||||
self.volume_rpcapi.create_group_from_src(context, group,
|
||||
None, source_group)
|
||||
|
@ -500,6 +500,7 @@ class GroupAPITestCase(test.TestCase):
|
||||
vol1.destroy()
|
||||
grp_snap.destroy()
|
||||
|
||||
@mock.patch('cinder.group.api.API._update_volumes_host')
|
||||
@mock.patch('cinder.objects.VolumeType.get_by_name_or_id')
|
||||
@mock.patch('cinder.db.group_volume_type_mapping_create')
|
||||
@mock.patch('cinder.volume.api.API.create')
|
||||
@ -512,7 +513,8 @@ class GroupAPITestCase(test.TestCase):
|
||||
mock_snap_get_all, mock_group_snap_get,
|
||||
mock_volume_api_create,
|
||||
mock_mapping_create,
|
||||
mock_get_volume_type):
|
||||
mock_get_volume_type,
|
||||
mock_update_volumes_host):
|
||||
vol_type = fake_volume.fake_volume_type_obj(
|
||||
self.ctxt,
|
||||
id=fake.VOLUME_TYPE_ID,
|
||||
@ -566,12 +568,17 @@ class GroupAPITestCase(test.TestCase):
|
||||
mock_rpc_create_group_from_src.assert_called_once_with(
|
||||
self.ctxt, grp, grp_snap)
|
||||
|
||||
mock_update_volumes_host.assert_called_once_with(
|
||||
self.ctxt, grp
|
||||
)
|
||||
|
||||
vol2.destroy()
|
||||
grp.destroy()
|
||||
snap.destroy()
|
||||
vol1.destroy()
|
||||
grp_snap.destroy()
|
||||
|
||||
@mock.patch('cinder.group.api.API._update_volumes_host')
|
||||
@mock.patch('cinder.objects.VolumeType.get_by_name_or_id')
|
||||
@mock.patch('cinder.db.group_volume_type_mapping_create')
|
||||
@mock.patch('cinder.volume.api.API.create')
|
||||
@ -583,7 +590,8 @@ class GroupAPITestCase(test.TestCase):
|
||||
mock_group_get,
|
||||
mock_volume_api_create,
|
||||
mock_mapping_create,
|
||||
mock_get_volume_type):
|
||||
mock_get_volume_type,
|
||||
mock_update_volumes_host):
|
||||
vol_type = fake_volume.fake_volume_type_obj(
|
||||
self.ctxt,
|
||||
id=fake.VOLUME_TYPE_ID,
|
||||
@ -631,6 +639,10 @@ class GroupAPITestCase(test.TestCase):
|
||||
mock_rpc_create_group_from_src.assert_called_once_with(
|
||||
self.ctxt, grp2, None, grp)
|
||||
|
||||
mock_update_volumes_host.assert_called_once_with(
|
||||
self.ctxt, grp2
|
||||
)
|
||||
|
||||
vol2.destroy()
|
||||
grp2.destroy()
|
||||
vol.destroy()
|
||||
@ -781,6 +793,42 @@ class GroupAPITestCase(test.TestCase):
|
||||
self.ctxt, 'group', 'desc',
|
||||
group_snapshot_id=None, source_group_id=group.id)
|
||||
|
||||
@mock.patch('cinder.objects.volume.Volume.host',
|
||||
new_callable=mock.PropertyMock)
|
||||
@mock.patch('cinder.objects.volume.Volume.cluster_name',
|
||||
new_callable=mock.PropertyMock)
|
||||
@mock.patch('cinder.objects.VolumeList.get_all_by_generic_group')
|
||||
def test_update_volumes_host(self, mock_volume_get_all, mock_cluster_name,
|
||||
mock_host):
|
||||
vol_type = utils.create_volume_type(self.ctxt, name='test_vol_type')
|
||||
grp = utils.create_group(self.ctxt, group_type_id=fake.GROUP_TYPE_ID,
|
||||
volume_type_ids=[vol_type['id']],
|
||||
availability_zone='nova',
|
||||
status=fields.GroupStatus.CREATING,
|
||||
cluster_name='fake_cluster')
|
||||
|
||||
vol1 = utils.create_volume(
|
||||
self.ctxt,
|
||||
availability_zone=grp.availability_zone,
|
||||
volume_type_id=fake.VOLUME_TYPE_ID,
|
||||
group_id=grp.id)
|
||||
|
||||
mock_volume = mock.Mock()
|
||||
mock_volume_get_all.return_value = [mock_volume]
|
||||
group_api = cinder.group.api.API()
|
||||
group_api._update_volumes_host(None, grp)
|
||||
|
||||
mock_cluster_name.assert_called()
|
||||
mock_host.assert_called()
|
||||
|
||||
self.assertEqual(grp.host, mock_volume.host)
|
||||
self.assertEqual(grp.cluster_name, mock_volume.cluster_name)
|
||||
mock_volume.save.assert_called_once_with()
|
||||
|
||||
vol1.destroy()
|
||||
|
||||
grp.destroy()
|
||||
|
||||
def test_delete_group_frozen(self):
|
||||
service = utils.create_service(self.ctxt, {'frozen': True})
|
||||
group = utils.create_group(self.ctxt, host=service.host,
|
||||
|
Loading…
Reference in New Issue
Block a user