Locality support for clusters

In order to allow clusters to be all on the same hypervisor
(affinity) or all on different hypervisors (anti-affinity) a new
argument (locality) needed to be added to the Trove cluster-create API.

This changeset addresses the Trove client part of this feature.
A --locality flag is now available on the 'cluster-create' command and
is passed to the server for processing.

Partially implements: blueprint replication-cluster-locality
Change-Id: Ie46cfa69ffe6a64760aca38c495563f5724bd0d0
This commit is contained in:
Peter Stachowski 2016-04-04 20:25:53 +00:00
parent 358dbf3c80
commit db85939433
5 changed files with 44 additions and 5 deletions

View File

@ -0,0 +1,6 @@
---
features:
- A --locality flag was added to the trove cluster-create
command to allow a user to specify whether instances in
a cluster should be on the same hypervisor (affinity)
or on different hypervisors (anti-affinity).

View File

@ -70,17 +70,19 @@ class ClustersTest(testtools.TestCase):
clusters_test = self.get_clusters()
clusters_test._create = mock.Mock(side_effect=side_effect_func)
instance = [{'flavor-id': 11, 'volume': 2}]
instances = [{'flavor-id': 11, 'volume': 2}]
locality = 'affinity'
path, body, resp_key = clusters_test.create("test-name", "datastore",
"datastore-version",
instance)
instances, locality)
self.assertEqual("/clusters", path)
self.assertEqual("cluster", resp_key)
self.assertEqual("test-name", body["cluster"]["name"])
self.assertEqual("datastore", body["cluster"]["datastore"]["type"])
self.assertEqual("datastore-version",
body["cluster"]["datastore"]["version"])
self.assertEqual(instance, body["cluster"]["instances"])
self.assertEqual(instances, body["cluster"]["instances"])
self.assertEqual(locality, body["cluster"]["locality"])
def test_list(self):
page_mock = mock.Mock()

View File

@ -439,6 +439,27 @@ class ShellTest(utils.TestCase):
self.run_command(cmd)
self.assert_called('POST', '/clusters/cls-1234')
def test_cluster_create_with_locality(self):
cmd = ('cluster-create test-clstr2 redis 3.0 --locality=affinity '
'--instance flavor=2,volume=1 '
'--instance flavor=2,volume=1 '
'--instance flavor=2,volume=1 ')
self.run_command(cmd)
self.assert_called_anytime(
'POST', '/clusters',
{'cluster': {
'instances': [
{'flavorRef': '2',
'volume': {'size': '1'}},
{'flavorRef': '2',
'volume': {'size': '1'}},
{'flavorRef': '2',
'volume': {'size': '1'}},
],
'datastore': {'version': '3.0', 'type': 'redis'},
'name': 'test-clstr2',
'locality': 'affinity'}})
def test_cluster_create_with_nic_az(self):
cmd = ('cluster-create test-clstr1 vertica 7.1 '
'--instance flavor=2,volume=2,nic=\'net-id=some-id\','

View File

@ -31,7 +31,8 @@ class Clusters(base.ManagerWithFind):
"""Manage :class:`Cluster` resources."""
resource_class = Cluster
def create(self, name, datastore, datastore_version, instances=None):
def create(self, name, datastore, datastore_version, instances=None,
locality=None):
"""Create (boot) a new cluster."""
body = {"cluster": {
"name": name
@ -43,6 +44,8 @@ class Clusters(base.ManagerWithFind):
body["cluster"]["datastore"] = datastore_obj
if instances:
body["cluster"]["instances"] = instances
if locality:
body["cluster"]["locality"] = locality
return self._create("/clusters", body, "cluster")

View File

@ -688,6 +688,12 @@ def _strip_option(opts_str, opt_name, is_required=True,
"(where net-id=network_id, v4-fixed-ip=IPv4r_fixed_address, "
"port-id=port_id), availability_zone=<AZ_hint_for_Nova>, "
"module=<module_name_or_id>.")
@utils.arg('--locality',
metavar='<policy>',
default=None,
choices=LOCALITY_DOMAIN,
help='Locality policy to use when creating cluster. Choose '
'one of %(choices)s.')
@utils.service_type('database')
def do_cluster_create(cs, args):
"""Creates a new cluster."""
@ -726,7 +732,8 @@ def do_cluster_create(cs, args):
cluster = cs.clusters.create(args.name,
args.datastore,
args.datastore_version,
instances=instances)
instances=instances,
locality=args.locality)
_print_cluster(cluster)