Add group to cluster when init host
If cluster is enabled, the group should be updated with cluster as well. Change-Id: I72dc6c61f10417f8382c7c488be27ed5199b75b9 Implements: blueprint cinder-volume-active-active-support
This commit is contained in:
parent
c7f15a4fa5
commit
48ce34a68e
|
@ -1352,6 +1352,23 @@ def consistencygroup_include_in_cluster(context, cluster, partial_rename=True,
|
|||
**filters)
|
||||
|
||||
|
||||
def group_include_in_cluster(context, cluster, partial_rename=True, **filters):
|
||||
"""Include all generic groups matching the filters into a cluster.
|
||||
|
||||
When partial_rename is set we will not set the cluster_name with cluster
|
||||
parameter value directly, we'll replace provided cluster_name or host
|
||||
filter value with cluster instead.
|
||||
|
||||
This is useful when we want to replace just the cluster name but leave
|
||||
the backend and pool information as it is. If we are using cluster_name
|
||||
to filter, we'll use that same DB field to replace the cluster value and
|
||||
leave the rest as it is. Likewise if we use the host to filter.
|
||||
|
||||
Returns the number of generic groups that have been changed.
|
||||
"""
|
||||
return IMPL.group_include_in_cluster(context, cluster, partial_rename,
|
||||
**filters)
|
||||
|
||||
###################
|
||||
|
||||
|
||||
|
|
|
@ -5528,6 +5528,12 @@ def consistencygroup_include_in_cluster(context, cluster,
|
|||
partial_rename, filters)
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def group_include_in_cluster(context, cluster, partial_rename=True, **filters):
|
||||
"""Include all generic groups matching the filters into a cluster."""
|
||||
return _include_in_cluster(context, cluster, models.Group, partial_rename,
|
||||
filters)
|
||||
|
||||
###############################
|
||||
|
||||
|
||||
|
|
|
@ -231,3 +231,22 @@ class GroupList(base.ObjectListBase, base.CinderObject):
|
|||
if grp.is_replicated]
|
||||
|
||||
return out_groups
|
||||
|
||||
@staticmethod
|
||||
def include_in_cluster(context, cluster, partial_rename=True, **filters):
|
||||
"""Include all generic groups matching the filters into a cluster.
|
||||
|
||||
When partial_rename is set we will not set the cluster_name with
|
||||
cluster parameter value directly, we'll replace provided cluster_name
|
||||
or host filter value with cluster instead.
|
||||
|
||||
This is useful when we want to replace just the cluster name but leave
|
||||
the backend and pool information as it is. If we are using
|
||||
cluster_name to filter, we'll use that same DB field to replace the
|
||||
cluster value and leave the rest as it is. Likewise if we use the host
|
||||
to filter.
|
||||
|
||||
Returns the number of generic groups that have been changed.
|
||||
"""
|
||||
return db.group_include_in_cluster(context, cluster, partial_rename,
|
||||
**filters)
|
||||
|
|
|
@ -272,3 +272,24 @@ class TestGroupList(test_objects.BaseObjectsTestCase):
|
|||
else:
|
||||
self.assertEqual(fake.GROUP_ID, res[0].id)
|
||||
self.assertIsNone(res[0].cluster_name)
|
||||
|
||||
@mock.patch('cinder.db.group_include_in_cluster')
|
||||
def test_include_in_cluster(self, include_mock):
|
||||
filters = {'host': mock.sentinel.host,
|
||||
'cluster_name': mock.sentinel.cluster_name}
|
||||
cluster = 'new_cluster'
|
||||
objects.GroupList.include_in_cluster(self.context, cluster, **filters)
|
||||
include_mock.assert_called_once_with(self.context, cluster, True,
|
||||
**filters)
|
||||
|
||||
@mock.patch('cinder.db.group_include_in_cluster')
|
||||
def test_include_in_cluster_specify_partial(self, include_mock):
|
||||
filters = {'host': mock.sentinel.host,
|
||||
'cluster_name': mock.sentinel.cluster_name}
|
||||
cluster = 'new_cluster'
|
||||
objects.GroupList.include_in_cluster(self.context, cluster,
|
||||
mock.sentinel.partial_rename,
|
||||
**filters)
|
||||
include_mock.assert_called_once_with(self.context, cluster,
|
||||
mock.sentinel.partial_rename,
|
||||
**filters)
|
||||
|
|
|
@ -3095,6 +3095,7 @@ class DBAPIBackendTestCase(BaseTest):
|
|||
db.is_backend_frozen(self.ctxt, host, cluster))
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class DBAPIGroupTestCase(BaseTest):
|
||||
def test_group_get_all_by_host(self):
|
||||
grp_type = db.group_type_create(self.ctxt, {'name': 'my_group_type'})
|
||||
|
@ -3148,3 +3149,72 @@ class DBAPIGroupTestCase(BaseTest):
|
|||
db.group_destroy(self.ctxt, grp_foobar['id'])
|
||||
|
||||
db.group_type_destroy(self.ctxt, grp_type['id'])
|
||||
|
||||
def _create_gs_to_test_include_in(self):
|
||||
"""Helper method for test_group_include_in_* tests."""
|
||||
return [
|
||||
db.group_create(
|
||||
self.ctxt, {'host': 'host1@backend1#pool1',
|
||||
'cluster_name': 'cluster1@backend1#pool1'}),
|
||||
db.group_create(
|
||||
self.ctxt, {'host': 'host1@backend2#pool2',
|
||||
'cluster_name': 'cluster1@backend2#pool1'}),
|
||||
db.group_create(
|
||||
self.ctxt, {'host': 'host2@backend#poo1',
|
||||
'cluster_name': 'cluster2@backend#pool'}),
|
||||
]
|
||||
|
||||
@ddt.data('host1@backend1#pool1', 'host1@backend1')
|
||||
def test_group_include_in_cluster_by_host(self, host):
|
||||
group = self._create_gs_to_test_include_in()[0]
|
||||
|
||||
cluster_name = 'my_cluster'
|
||||
result = db.group_include_in_cluster(self.ctxt, cluster_name,
|
||||
partial_rename=False, host=host)
|
||||
self.assertEqual(1, result)
|
||||
db_group = db.group_get(self.ctxt, group.id)
|
||||
self.assertEqual(cluster_name, db_group.cluster_name)
|
||||
|
||||
def test_group_include_in_cluster_by_host_multiple(self):
|
||||
groups = self._create_gs_to_test_include_in()[0:2]
|
||||
|
||||
host = 'host1'
|
||||
cluster_name = 'my_cluster'
|
||||
result = db.group_include_in_cluster(self.ctxt, cluster_name,
|
||||
partial_rename=True, host=host)
|
||||
self.assertEqual(2, result)
|
||||
db_group = [db.group_get(self.ctxt, groups[0].id),
|
||||
db.group_get(self.ctxt, groups[1].id)]
|
||||
for i in range(2):
|
||||
self.assertEqual(cluster_name + groups[i].host[len(host):],
|
||||
db_group[i].cluster_name)
|
||||
|
||||
@ddt.data('cluster1@backend1#pool1', 'cluster1@backend1')
|
||||
def test_group_include_in_cluster_by_cluster_name(self, cluster_name):
|
||||
group = self._create_gs_to_test_include_in()[0]
|
||||
|
||||
new_cluster_name = 'cluster_new@backend1#pool'
|
||||
result = db.group_include_in_cluster(self.ctxt, new_cluster_name,
|
||||
partial_rename=False,
|
||||
cluster_name=cluster_name)
|
||||
|
||||
self.assertEqual(1, result)
|
||||
db_group = db.group_get(self.ctxt, group.id)
|
||||
self.assertEqual(new_cluster_name, db_group.cluster_name)
|
||||
|
||||
def test_group_include_in_cluster_by_cluster_multiple(self):
|
||||
groups = self._create_gs_to_test_include_in()[0:2]
|
||||
|
||||
cluster_name = 'cluster1'
|
||||
new_cluster_name = 'my_cluster'
|
||||
result = db.group_include_in_cluster(self.ctxt, new_cluster_name,
|
||||
partial_rename=True,
|
||||
cluster_name=cluster_name)
|
||||
|
||||
self.assertEqual(2, result)
|
||||
db_groups = [db.group_get(self.ctxt, groups[0].id),
|
||||
db.group_get(self.ctxt, groups[1].id)]
|
||||
for i in range(2):
|
||||
self.assertEqual(
|
||||
new_cluster_name + groups[i].cluster_name[len(cluster_name):],
|
||||
db_groups[i].cluster_name)
|
||||
|
|
|
@ -239,6 +239,7 @@ class VolumeInitHostTestCase(base.BaseVolumeTestCase):
|
|||
service_id=self.service_id)
|
||||
include_in_cluster_mock.assert_not_called()
|
||||
|
||||
@mock.patch('cinder.objects.group.GroupList.include_in_cluster')
|
||||
@mock.patch('cinder.objects.snapshot.SnapshotList.get_all',
|
||||
return_value=[])
|
||||
@mock.patch('cinder.objects.volume.VolumeList.get_all', return_value=[])
|
||||
|
@ -249,7 +250,7 @@ class VolumeInitHostTestCase(base.BaseVolumeTestCase):
|
|||
def test_init_host_added_to_cluster(self, image_cache_include_mock,
|
||||
cg_include_mock,
|
||||
vol_include_mock, vol_get_all_mock,
|
||||
snap_get_all_mock):
|
||||
snap_get_all_mock, group_include_mock):
|
||||
cluster = str(mock.sentinel.cluster)
|
||||
self.mock_object(self.volume, 'cluster', cluster)
|
||||
self.volume.init_host(added_to_cluster=True,
|
||||
|
@ -261,6 +262,8 @@ class VolumeInitHostTestCase(base.BaseVolumeTestCase):
|
|||
host=self.volume.host)
|
||||
image_cache_include_mock.assert_called_once_with(mock.ANY, cluster,
|
||||
host=self.volume.host)
|
||||
group_include_mock.assert_called_once_with(mock.ANY, cluster,
|
||||
host=self.volume.host)
|
||||
vol_get_all_mock.assert_called_once_with(
|
||||
mock.ANY, filters={'cluster_name': cluster})
|
||||
snap_get_all_mock.assert_called_once_with(
|
||||
|
|
|
@ -412,12 +412,15 @@ class VolumeManager(manager.CleanableManager,
|
|||
ctxt, self.cluster, host=self.host)
|
||||
num_cgs = objects.ConsistencyGroupList.include_in_cluster(
|
||||
ctxt, self.cluster, host=self.host)
|
||||
num_gs = objects.GroupList.include_in_cluster(
|
||||
ctxt, self.cluster, host=self.host)
|
||||
num_cache = db.image_volume_cache_include_in_cluster(
|
||||
ctxt, self.cluster, host=self.host)
|
||||
LOG.info('%(num_vols)s volumes, %(num_cgs)s consistency groups, '
|
||||
'and %(num_cache)s image volume caches from host '
|
||||
'%(host)s have been included in cluster %(cluster)s.',
|
||||
{'num_vols': num_vols, 'num_cgs': num_cgs,
|
||||
'%(num_gs)s generic groups and %(num_cache)s image '
|
||||
'volume caches from host %(host)s have been included in '
|
||||
'cluster %(cluster)s.',
|
||||
{'num_vols': num_vols, 'num_cgs': num_cgs, 'num_gs': num_gs,
|
||||
'host': self.host, 'cluster': self.cluster,
|
||||
'num_cache': num_cache})
|
||||
|
||||
|
|
Loading…
Reference in New Issue