Add cluster-grow and cluster-shrink to OSC
This change adds database support to python-openstackclient project for the cluster-grow and cluster-shrink commands. The trove command cluster-grow is now: openstack database cluster grow The trove command cluster-shrink is now: openstack database cluster shrink Change-Id: I449e7f7d841ea266611ff79f8a41f6e730fced3c Partially-Implements: blueprint trove-support-in-python-openstackclient Signed-off-by: Zhao Chao <zhaochao1984@gmail.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The command ``trove cluster-grow`` is now available
|
||||||
|
to use in the python-openstackclient CLI as ``openstack database
|
||||||
|
cluster grow``
|
||||||
|
- |
|
||||||
|
The command ``trove cluster-shrink`` is now available
|
||||||
|
to use in the python-openstackclient CLI as ``openstack database
|
||||||
|
cluster shrink``
|
@@ -38,10 +38,12 @@ openstack.database.v1 =
|
|||||||
database_cluster_create = troveclient.osc.v1.database_clusters:CreateDatabaseCluster
|
database_cluster_create = troveclient.osc.v1.database_clusters:CreateDatabaseCluster
|
||||||
database_cluster_delete = troveclient.osc.v1.database_clusters:DeleteDatabaseCluster
|
database_cluster_delete = troveclient.osc.v1.database_clusters:DeleteDatabaseCluster
|
||||||
database_cluster_force_delete = troveclient.osc.v1.database_clusters:ForceDeleteDatabaseCluster
|
database_cluster_force_delete = troveclient.osc.v1.database_clusters:ForceDeleteDatabaseCluster
|
||||||
|
database_cluster_grow = troveclient.osc.v1.database_clusters:GrowDatabaseCluster
|
||||||
database_cluster_list = troveclient.osc.v1.database_clusters:ListDatabaseClusters
|
database_cluster_list = troveclient.osc.v1.database_clusters:ListDatabaseClusters
|
||||||
database_cluster_list_instances = troveclient.osc.v1.database_clusters:ListDatabaseClusterInstances
|
database_cluster_list_instances = troveclient.osc.v1.database_clusters:ListDatabaseClusterInstances
|
||||||
database_cluster_reset_status = troveclient.osc.v1.database_clusters:ResetDatabaseClusterStatus
|
database_cluster_reset_status = troveclient.osc.v1.database_clusters:ResetDatabaseClusterStatus
|
||||||
database_cluster_show = troveclient.osc.v1.database_clusters:ShowDatabaseCluster
|
database_cluster_show = troveclient.osc.v1.database_clusters:ShowDatabaseCluster
|
||||||
|
database_cluster_shrink = troveclient.osc.v1.database_clusters:ShrinkDatabaseCluster
|
||||||
database_cluster_upgrade = troveclient.osc.v1.database_clusters:UpgradeDatabaseCluster
|
database_cluster_upgrade = troveclient.osc.v1.database_clusters:UpgradeDatabaseCluster
|
||||||
database_configuration_attach = troveclient.osc.v1.database_configurations:AttachDatabaseConfiguration
|
database_configuration_attach = troveclient.osc.v1.database_configurations:AttachDatabaseConfiguration
|
||||||
database_configuration_create = troveclient.osc.v1.database_configurations:CreateDatabaseConfiguration
|
database_configuration_create = troveclient.osc.v1.database_configurations:CreateDatabaseConfiguration
|
||||||
|
@@ -19,6 +19,8 @@ import six
|
|||||||
|
|
||||||
from troveclient.i18n import _
|
from troveclient.i18n import _
|
||||||
from troveclient.v1.shell import _parse_instance_options
|
from troveclient.v1.shell import _parse_instance_options
|
||||||
|
from troveclient.v1.shell import INSTANCE_HELP
|
||||||
|
from troveclient.v1.shell import INSTANCE_METAVAR
|
||||||
|
|
||||||
|
|
||||||
def set_attributes_for_print_detail(cluster):
|
def set_attributes_for_print_detail(cluster):
|
||||||
@@ -149,21 +151,11 @@ class CreateDatabaseCluster(command.ShowOne):
|
|||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--instance',
|
'--instance',
|
||||||
metavar='"opt=<value>[,opt=<value> ...] "',
|
metavar=INSTANCE_METAVAR,
|
||||||
action='append',
|
action='append',
|
||||||
dest='instances',
|
dest='instances',
|
||||||
default=[],
|
default=[],
|
||||||
help=_("Add an instance to the cluster. Specify multiple "
|
help=INSTANCE_HELP,
|
||||||
"times to create multiple instances. "
|
|
||||||
"Valid options are: flavor=<flavor_name_or_id>, "
|
|
||||||
"volume=<disk_size_in_GB>, volume_type=<type>, "
|
|
||||||
"nic='<net-id=<net-uuid>, v4-fixed-ip=<ip-addr>, "
|
|
||||||
"port-id=<port-uuid>>' "
|
|
||||||
"(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>, type=<type_of_cluster_node>, "
|
|
||||||
"related_to=<related_attribute>."),
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--locality',
|
'--locality',
|
||||||
@@ -284,3 +276,74 @@ class ForceDeleteDatabaseCluster(command.Command):
|
|||||||
msg = (_("Failed to delete cluster %(cluster)s: %(e)s")
|
msg = (_("Failed to delete cluster %(cluster)s: %(e)s")
|
||||||
% {'cluster': parsed_args.cluster, 'e': e})
|
% {'cluster': parsed_args.cluster, 'e': e})
|
||||||
raise exceptions.CommandError(msg)
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
class GrowDatabaseCluster(command.Command):
|
||||||
|
|
||||||
|
_description = _("Adds more instances to a cluster.")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(GrowDatabaseCluster, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'--instance',
|
||||||
|
metavar=INSTANCE_METAVAR,
|
||||||
|
action='append',
|
||||||
|
dest='instances',
|
||||||
|
default=[],
|
||||||
|
help=INSTANCE_HELP
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'cluster',
|
||||||
|
metavar='<cluster>',
|
||||||
|
help=_('ID or name of the cluster.')
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
database_client_manager = self.app.client_manager.database
|
||||||
|
|
||||||
|
db_clusters = database_client_manager.clusters
|
||||||
|
cluster = utils.find_resource(db_clusters,
|
||||||
|
parsed_args.cluster)
|
||||||
|
|
||||||
|
instances = _parse_instance_options(database_client_manager,
|
||||||
|
parsed_args.instances,
|
||||||
|
for_grow=True)
|
||||||
|
db_clusters.grow(cluster, instances=instances)
|
||||||
|
|
||||||
|
|
||||||
|
class ShrinkDatabaseCluster(command.Command):
|
||||||
|
|
||||||
|
_description = _("Drops instances from a cluster.")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ShrinkDatabaseCluster, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'cluster',
|
||||||
|
metavar='<cluster>',
|
||||||
|
help=_('ID or name of the cluster.')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'instances',
|
||||||
|
metavar='<instance>',
|
||||||
|
nargs='+',
|
||||||
|
default=[],
|
||||||
|
help=_("Drop instance(s) from the cluster. Specify "
|
||||||
|
"multiple ids to drop multiple instances.")
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
database_client_manager = self.app.client_manager.database
|
||||||
|
|
||||||
|
db_clusters = database_client_manager.clusters
|
||||||
|
cluster = utils.find_resource(db_clusters,
|
||||||
|
parsed_args.cluster)
|
||||||
|
|
||||||
|
db_instances = database_client_manager.instances
|
||||||
|
instances = [
|
||||||
|
{'id': utils.find_resource(db_instances,
|
||||||
|
instance).id}
|
||||||
|
for instance in parsed_args.instances
|
||||||
|
]
|
||||||
|
db_clusters.shrink(cluster, instances)
|
||||||
|
@@ -51,10 +51,14 @@ class FakeClusters(object):
|
|||||||
fake_clusters = fakes.FakeHTTPClient().get_clusters()[2]['clusters']
|
fake_clusters = fakes.FakeHTTPClient().get_clusters()[2]['clusters']
|
||||||
fake_cluster = (fakes.FakeHTTPClient()
|
fake_cluster = (fakes.FakeHTTPClient()
|
||||||
.get_clusters_cls_1234()[2]['cluster'])
|
.get_clusters_cls_1234()[2]['cluster'])
|
||||||
|
fake_cluster_member = fake_cluster['instances'][1]
|
||||||
|
|
||||||
def get_clusters_cls_1234(self):
|
def get_clusters_cls_1234(self):
|
||||||
return clusters.Cluster(None, self.fake_cluster)
|
return clusters.Cluster(None, self.fake_cluster)
|
||||||
|
|
||||||
|
def get_clusters_member_2(self):
|
||||||
|
return instances.Instance(None, self.fake_cluster_member)
|
||||||
|
|
||||||
|
|
||||||
class FakeConfigurations(object):
|
class FakeConfigurations(object):
|
||||||
fake_config = (fakes.FakeHTTPClient().get_configurations()
|
fake_config = (fakes.FakeHTTPClient().get_configurations()
|
||||||
|
@@ -233,3 +233,51 @@ class TestDatabaseClusterForceDelete(TestClusters):
|
|||||||
self.assertRaises(exceptions.CommandError,
|
self.assertRaises(exceptions.CommandError,
|
||||||
self.cmd.take_action,
|
self.cmd.take_action,
|
||||||
parsed_args)
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDatabaseClusterGrow(TestClusters):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestDatabaseClusterGrow, self).setUp()
|
||||||
|
self.cmd = database_clusters.GrowDatabaseCluster(self.app, None)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, 'find_resource')
|
||||||
|
@mock.patch.object(database_clusters, '_parse_instance_options')
|
||||||
|
def test_cluster_grow(self, mock_parse_instance_opts,
|
||||||
|
mock_find_resource):
|
||||||
|
args = ['test-clstr',
|
||||||
|
'--instance',
|
||||||
|
'name=test-clstr-member-3,flavor=3']
|
||||||
|
parsed_instance_opts = [
|
||||||
|
{'name': 'test-clstr-member-3',
|
||||||
|
'flavor': 3}
|
||||||
|
]
|
||||||
|
mock_parse_instance_opts.return_value = parsed_instance_opts
|
||||||
|
mock_find_resource.return_value = args[0]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, args, [])
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.cluster_client.grow.assert_called_with(
|
||||||
|
'test-clstr',
|
||||||
|
instances=parsed_instance_opts)
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDatabaseClusterShrink(TestClusters):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestDatabaseClusterShrink, self).setUp()
|
||||||
|
self.cmd = database_clusters.ShrinkDatabaseCluster(self.app, None)
|
||||||
|
self.cluster_member = self.fake_clusters.get_clusters_member_2()
|
||||||
|
|
||||||
|
@mock.patch.object(utils, 'find_resource')
|
||||||
|
def test_cluster_grow(self, mock_find_resource):
|
||||||
|
args = ['test-clstr', 'test-clstr-member-2']
|
||||||
|
mock_find_resource.side_effect = [
|
||||||
|
args[0], self.cluster_member]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, args, [])
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.cluster_client.shrink.assert_called_with('test-clstr',
|
||||||
|
[{'id': 'member-2'}])
|
||||||
|
self.assertIsNone(result)
|
||||||
|
Reference in New Issue
Block a user