diff --git a/trove/common/cfg.py b/trove/common/cfg.py index 5dda7aca91..afab91ce5f 100644 --- a/trove/common/cfg.py +++ b/trove/common/cfg.py @@ -604,8 +604,8 @@ pxc_opts = [ help='Users to exclude when listing users.'), cfg.BoolOpt('cluster_support', default=True, help='Enable clusters to be created and managed.'), - cfg.IntOpt('cluster_member_count', default=3, - help='Number of members in PXC cluster.'), + cfg.IntOpt('min_cluster_member_count', default=3, + help='Minimum number of members in PXC cluster.'), cfg.StrOpt('api_strategy', default='trove.common.strategies.cluster.experimental.' 'pxc.api.PXCAPIStrategy', diff --git a/trove/common/exception.py b/trove/common/exception.py index 280f06a1bd..22ce29f5f1 100644 --- a/trove/common/exception.py +++ b/trove/common/exception.py @@ -513,6 +513,11 @@ class ClusterNumInstancesNotSupported(TroveError): "be %(num_instances)s.") +class ClusterNumInstancesNotLargeEnough(TroveError): + message = _("The number of instances for your initial cluster must " + "be at least %(num_instances)s.") + + class ClusterInstanceOperationNotSupported(TroveError): message = _("Operation not supported for instances that are part of a " "cluster.") diff --git a/trove/common/strategies/cluster/experimental/pxc/api.py b/trove/common/strategies/cluster/experimental/pxc/api.py index 2fa8308860..c6aa403385 100644 --- a/trove/common/strategies/cluster/experimental/pxc/api.py +++ b/trove/common/strategies/cluster/experimental/pxc/api.py @@ -60,10 +60,10 @@ class PXCCluster(models.Cluster): pxc_conf = CONF.get(datastore_version.manager) num_instances = len(instances) - # Matching number of instances with configured cluster_member_count - if num_instances != pxc_conf.cluster_member_count: - raise exception.ClusterNumInstancesNotSupported( - num_instances=pxc_conf.cluster_member_count) + # Check number of instances is at least min_cluster_member_count + if num_instances < pxc_conf.min_cluster_member_count: + raise exception.ClusterNumInstancesNotLargeEnough( + num_instances=pxc_conf.min_cluster_member_count) # Checking flavors flavor_ids = [instance['flavor_id'] for instance in instances] diff --git a/trove/tests/unittests/cluster/test_pxc_cluster.py b/trove/tests/unittests/cluster/test_pxc_cluster.py index b2ed002cdf..36ed457300 100644 --- a/trove/tests/unittests/cluster/test_pxc_cluster.py +++ b/trove/tests/unittests/cluster/test_pxc_cluster.py @@ -33,9 +33,9 @@ CONF = cfg.CONF class FakeOptGroup(object): - def __init__(self, cluster_member_count=3, + def __init__(self, min_cluster_member_count=3, volume_support=True, device_path='/dev/vdb'): - self.cluster_member_count = cluster_member_count + self.min_cluster_member_count = min_cluster_member_count self.volume_support = volume_support self.device_path = device_path @@ -72,7 +72,7 @@ class ClusterTest(trove_testtools.TestCase): super(ClusterTest, self).tearDown() def test_create_empty_instances(self): - self.assertRaises(exception.ClusterNumInstancesNotSupported, + self.assertRaises(exception.ClusterNumInstancesNotLargeEnough, Cluster.create, Mock(), self.cluster_name, @@ -215,6 +215,28 @@ class ClusterTest(trove_testtools.TestCase): mock_db_create.return_value.id) self.assertEqual(3, mock_ins_create.call_count) + @patch.object(inst_models.Instance, 'create') + @patch.object(DBCluster, 'create') + @patch.object(task_api, 'load') + @patch.object(QUOTAS, 'check_quotas') + @patch.object(remote, 'create_nova_client') + def test_create_over_limit(self, mock_client, mock_check_quotas, + mock_task_api, mock_db_create, mock_ins_create): + instances = [{'volume_size': 1, 'flavor_id': '1234'}, + {'volume_size': 1, 'flavor_id': '1234'}, + {'volume_size': 1, 'flavor_id': '1234'}, + {'volume_size': 1, 'flavor_id': '1234'}] + flavors = Mock() + mock_client.return_value.flavors = flavors + self.cluster.create(Mock(), + self.cluster_name, + self.datastore, + self.datastore_version, + instances, {}) + mock_task_api.return_value.create_cluster.assert_called_with( + mock_db_create.return_value.id) + self.assertEqual(4, mock_ins_create.call_count) + @patch.object(pxc_api, 'CONF') @patch.object(inst_models.Instance, 'create') @patch.object(DBCluster, 'create')