diff --git a/quantumclient/quantum/v2_0/__init__.py b/quantumclient/quantum/v2_0/__init__.py index 530b07a84..fbc64ed60 100644 --- a/quantumclient/quantum/v2_0/__init__.py +++ b/quantumclient/quantum/v2_0/__init__.py @@ -141,7 +141,10 @@ def parse_args_to_dict(values_specs): current_arg = _options[_item] _item = _temp elif _item.startswith('type='): - if current_arg is not None: + if current_arg is None: + raise exceptions.CommandError( + "invalid values_specs %s" % ' '.join(values_specs)) + if 'type' not in current_arg: _type_str = _item.split('=', 2)[1] current_arg.update({'type': eval(_type_str)}) if _type_str == 'bool': @@ -149,9 +152,6 @@ def parse_args_to_dict(values_specs): elif _type_str == 'dict': current_arg.update({'type': utils.str2dict}) continue - else: - raise exceptions.CommandError( - "invalid values_specs %s" % ' '.join(values_specs)) elif _item == 'list=true': _list_flag = True continue @@ -212,6 +212,12 @@ def _merge_args(qCmd, parsed_args, _extra_values, value_specs): _extra_values.pop(key) +def update_dict(obj, dict, attributes): + for attribute in attributes: + if hasattr(obj, attribute) and getattr(obj, attribute): + dict[attribute] = getattr(obj, attribute) + + class QuantumCommand(command.OpenStackCommand): api = 'network' log = logging.getLogger(__name__ + '.QuantumCommand') diff --git a/quantumclient/quantum/v2_0/lb/__init__.py b/quantumclient/quantum/v2_0/lb/__init__.py new file mode 100644 index 000000000..1668497e7 --- /dev/null +++ b/quantumclient/quantum/v2_0/lb/__init__.py @@ -0,0 +1,16 @@ +# Copyright 2013 OpenStack LLC. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 diff --git a/quantumclient/quantum/v2_0/lb/healthmonitor.py b/quantumclient/quantum/v2_0/lb/healthmonitor.py new file mode 100644 index 000000000..9aa287401 --- /dev/null +++ b/quantumclient/quantum/v2_0/lb/healthmonitor.py @@ -0,0 +1,172 @@ +# Copyright 2013 Mirantis Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Ilya Shakhat, Mirantis Inc. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import logging + +from quantumclient.quantum import v2_0 as quantumv20 + + +class ListHealthMonitor(quantumv20.ListCommand): + """List healthmonitors that belong to a given tenant.""" + + resource = 'health_monitor' + log = logging.getLogger(__name__ + '.ListHealthMonitor') + list_columns = ['id', 'type', 'admin_state_up', 'status'] + _formatters = {} + + +class ShowHealthMonitor(quantumv20.ShowCommand): + """Show information of a given healthmonitor.""" + + resource = 'health_monitor' + log = logging.getLogger(__name__ + '.ShowHealthMonitor') + + +class CreateHealthMonitor(quantumv20.CreateCommand): + """Create a healthmonitor""" + + resource = 'health_monitor' + log = logging.getLogger(__name__ + '.CreateHealthMonitor') + + def add_known_arguments(self, parser): + parser.add_argument( + '--admin-state-down', + default=True, action='store_false', + help='set admin state up to false') + parser.add_argument( + '--delay', + required=True, + help='the minimum time in seconds between regular connections ' + 'of the member.') + parser.add_argument( + '--expected-codes', + help='the list of HTTP status codes expected in ' + 'response from the member to declare it healthy. This ' + 'attribute can contain one value, ' + 'or a list of values separated by comma, ' + 'or a range of values (e.g. "200-299"). If this attribute ' + 'is not specified, it defaults to "200". ') + parser.add_argument( + '--http-method', + help='the HTTP method used for requests by the monitor of type ' + 'HTTP.') + parser.add_argument( + '--max-retries', + required=True, + help='number of permissible connection failures before changing ' + 'the member status to INACTIVE.') + parser.add_argument( + '--timeout', + required=True, + help='maximum number of seconds for a monitor to wait for a ' + 'connection to be established before it times out. The ' + 'value must be less than the delay value.') + parser.add_argument( + '--type', + required=True, + help='one of predefined health monitor types, e.g. RoundRobin') + parser.add_argument( + '--url-path', + help='the HTTP path used in the HTTP request used by the monitor' + ' to test a member health. This must be a string ' + 'beginning with a / (forward slash)') + + def args2body(self, parsed_args): + body = { + self.resource: { + 'admin_state_up': parsed_args.admin_state_down, + 'delay': parsed_args.delay, + 'max_retries': parsed_args.max_retries, + 'timeout': parsed_args.timeout, + 'type': parsed_args.type, + }, + } + quantumv20.update_dict(parsed_args, body[self.resource], + ['expected_codes', 'http_method', 'url_path', + 'tenant_id']) + return body + + +class UpdateHealthMonitor(quantumv20.UpdateCommand): + """Update a given healthmonitor.""" + + resource = 'health_monitor' + log = logging.getLogger(__name__ + '.UpdateHealthMonitor') + + +class DeleteHealthMonitor(quantumv20.DeleteCommand): + """Delete a given healthmonitor.""" + + resource = 'health_monitor' + log = logging.getLogger(__name__ + '.DeleteHealthMonitor') + + +class AssociateHealthMonitor(quantumv20.QuantumCommand): + """Create a mapping between a health monitor and a pool.""" + + log = logging.getLogger(__name__ + '.AssociateHealthMonitor') + resource = 'health_monitor' + + def get_parser(self, prog_name): + parser = super(AssociateHealthMonitor, self).get_parser(prog_name) + parser.add_argument( + 'health_monitor_id', + help='Health monitor to associate') + parser.add_argument( + 'pool_id', + help='ID of the pool to be associated with the health monitor') + return parser + + def run(self, parsed_args): + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + body = {'health_monitor': {'id': parsed_args.health_monitor_id}} + pool_id = quantumv20.find_resourceid_by_name_or_id( + quantum_client, 'pool', parsed_args.pool_id) + quantum_client.associate_health_monitor(pool_id, body) + print >>self.app.stdout, (_('Associated health monitor ' + '%s') % parsed_args.health_monitor_id) + + +class DisassociateHealthMonitor(quantumv20.QuantumCommand): + """Remove a mapping from a health monitor to a pool.""" + + log = logging.getLogger(__name__ + '.DisassociateHealthMonitor') + resource = 'health_monitor' + + def get_parser(self, prog_name): + parser = super(DisassociateHealthMonitor, self).get_parser(prog_name) + parser.add_argument( + 'health_monitor_id', + help='Health monitor to associate') + parser.add_argument( + 'pool_id', + help='ID of the pool to be associated with the health monitor') + return parser + + def run(self, parsed_args): + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + pool_id = quantumv20.find_resourceid_by_name_or_id( + quantum_client, 'pool', parsed_args.pool_id) + quantum_client.disassociate_health_monitor(pool_id, + parsed_args + .health_monitor_id) + print >>self.app.stdout, (_('Disassociated health monitor ' + '%s') % parsed_args.health_monitor_id) diff --git a/quantumclient/quantum/v2_0/lb/member.py b/quantumclient/quantum/v2_0/lb/member.py new file mode 100644 index 000000000..25707175a --- /dev/null +++ b/quantumclient/quantum/v2_0/lb/member.py @@ -0,0 +1,93 @@ +# Copyright 2013 Mirantis Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Ilya Shakhat, Mirantis Inc. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import logging + +from quantumclient.quantum import v2_0 as quantumv20 + + +class ListMember(quantumv20.ListCommand): + """List members that belong to a given tenant.""" + + resource = 'member' + log = logging.getLogger(__name__ + '.ListMember') + list_columns = ['id', 'address', 'port', 'admin_state_up', 'status'] + _formatters = {} + + +class ShowMember(quantumv20.ShowCommand): + """Show information of a given member.""" + + resource = 'member' + log = logging.getLogger(__name__ + '.ShowMember') + + +class CreateMember(quantumv20.CreateCommand): + """Create a member""" + + resource = 'member' + log = logging.getLogger(__name__ + '.CreateMember') + + def add_known_arguments(self, parser): + parser.add_argument( + 'pool_id', metavar='pool', + help='Pool id or name this vip belongs to') + parser.add_argument( + '--address', + required=True, + help='IP address of the pool member on the pool network. ') + parser.add_argument( + '--admin-state-down', + default=True, action='store_false', + help='set admin state up to false') + parser.add_argument( + '--port', + required=True, + help='port on which the pool member listens for requests or ' + 'connections. ') + parser.add_argument( + '--weight', + help='weight of pool member in the pool') + + def args2body(self, parsed_args): + _pool_id = quantumv20.find_resourceid_by_name_or_id( + self.get_client(), 'pool', parsed_args.pool_id) + body = { + self.resource: { + 'pool_id': _pool_id, + 'admin_state_up': parsed_args.admin_state_down, + }, + } + quantumv20.update_dict(parsed_args, body[self.resource], + ['address', 'port', 'weight', 'tenant_id']) + return body + + +class UpdateMember(quantumv20.UpdateCommand): + """Update a given member.""" + + resource = 'member' + log = logging.getLogger(__name__ + '.UpdateMember') + + +class DeleteMember(quantumv20.DeleteCommand): + """Delete a given member.""" + + resource = 'member' + log = logging.getLogger(__name__ + '.DeleteMember') diff --git a/quantumclient/quantum/v2_0/lb/pool.py b/quantumclient/quantum/v2_0/lb/pool.py new file mode 100644 index 000000000..b39c68459 --- /dev/null +++ b/quantumclient/quantum/v2_0/lb/pool.py @@ -0,0 +1,120 @@ +# Copyright 2013 Mirantis Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Ilya Shakhat, Mirantis Inc. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import logging + +from quantumclient.quantum import v2_0 as quantumv20 + + +class ListPool(quantumv20.ListCommand): + """List pools that belong to a given tenant.""" + + resource = 'pool' + log = logging.getLogger(__name__ + '.ListPool') + list_columns = ['id', 'name', 'lb_method', 'protocol', + 'admin_state_up', 'status'] + _formatters = {} + + +class ShowPool(quantumv20.ShowCommand): + """Show information of a given pool.""" + + resource = 'pool' + log = logging.getLogger(__name__ + '.ShowPool') + + +class CreatePool(quantumv20.CreateCommand): + """Create a pool""" + + resource = 'pool' + log = logging.getLogger(__name__ + '.CreatePool') + + def add_known_arguments(self, parser): + parser.add_argument( + '--admin-state-down', + default=True, action='store_false', + help='set admin state up to false') + parser.add_argument( + '--description', + help='description of the pool') + parser.add_argument( + '--lb-method', + required=True, + help='the algorithm used to distribute load between the members ' + 'of the pool') + parser.add_argument( + '--name', + required=True, + help='the name of the pool') + parser.add_argument( + '--protocol', + required=True, + help='protocol for balancing') + parser.add_argument( + '--subnet-id', + required=True, + help='the subnet on which the members of the pool will be located') + + def args2body(self, parsed_args): + body = { + self.resource: { + 'admin_state_up': parsed_args.admin_state_down, + }, + } + quantumv20.update_dict(parsed_args, body[self.resource], + ['description', 'lb_method', 'name', + 'subnet_id', 'protocol', 'tenant_id']) + return body + + +class UpdatePool(quantumv20.UpdateCommand): + """Update a given pool.""" + + resource = 'pool' + log = logging.getLogger(__name__ + '.UpdatePool') + + +class DeletePool(quantumv20.DeleteCommand): + """Delete a given pool.""" + + resource = 'pool' + log = logging.getLogger(__name__ + '.DeletePool') + + +class RetrievePoolStats(quantumv20.ShowCommand): + """Retrieve stats for a given pool.""" + + resource = 'pool' + log = logging.getLogger(__name__ + '.RetrievePoolStats') + + def get_data(self, parsed_args): + self.log.debug('run(%s)' % parsed_args) + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + params = {} + if parsed_args.fields: + params = {'fields': parsed_args.fields} + + data = quantum_client.retrieve_pool_stats(parsed_args.id, **params) + self.format_output_data(data) + stats = data['stats'] + if 'stats' in data: + return zip(*sorted(stats.iteritems())) + else: + return None diff --git a/quantumclient/quantum/v2_0/lb/vip.py b/quantumclient/quantum/v2_0/lb/vip.py new file mode 100644 index 000000000..741b14d67 --- /dev/null +++ b/quantumclient/quantum/v2_0/lb/vip.py @@ -0,0 +1,111 @@ +# Copyright 2013 Mirantis Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Ilya Shakhat, Mirantis Inc. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import logging + +from quantumclient.quantum import v2_0 as quantumv20 + + +class ListVip(quantumv20.ListCommand): + """List vips that belong to a given tenant.""" + + resource = 'vip' + log = logging.getLogger(__name__ + '.ListVip') + list_columns = ['id', 'name', 'algorithm', 'protocol', + 'admin_state_up', 'status'] + _formatters = {} + + +class ShowVip(quantumv20.ShowCommand): + """Show information of a given vip.""" + + resource = 'vip' + log = logging.getLogger(__name__ + '.ShowVip') + + +class CreateVip(quantumv20.CreateCommand): + """Create a vip""" + + resource = 'vip' + log = logging.getLogger(__name__ + '.CreateVip') + + def add_known_arguments(self, parser): + parser.add_argument( + 'pool_id', metavar='pool', + help='Pool id or name this vip belongs to') + parser.add_argument( + '--address', + help='IP address of the vip') + parser.add_argument( + '--admin-state-down', + default=True, action='store_false', + help='set admin state up to false') + parser.add_argument( + '--connection-limit', + help='the maximum number of connections per second allowed for ' + 'the vip') + parser.add_argument( + '--description', + help='description of the vip') + parser.add_argument( + '--name', + required=True, + help='name of the vip') + parser.add_argument( + '--port', + required=True, + help='TCP port on which to listen for client traffic that is ' + 'associated with the vip address') + parser.add_argument( + '--protocol', + required=True, + help='protocol for balancing') + parser.add_argument( + '--subnet-id', + required=True, + help='the subnet on which to allocate the vip address') + + def args2body(self, parsed_args): + _pool_id = quantumv20.find_resourceid_by_name_or_id( + self.get_client(), 'pool', parsed_args.pool_id) + body = { + self.resource: { + 'pool_id': _pool_id, + 'admin_state_up': parsed_args.admin_state_down, + }, + } + quantumv20.update_dict(parsed_args, body[self.resource], + ['address', 'connection_limit', 'description', + 'name', 'port', 'protocol', 'subnet_id', + 'tenant_id']) + return body + + +class UpdateVip(quantumv20.UpdateCommand): + """Update a given vip.""" + + resource = 'vip' + log = logging.getLogger(__name__ + '.UpdateVip') + + +class DeleteVip(quantumv20.DeleteCommand): + """Delete a given vip.""" + + resource = 'vip' + log = logging.getLogger(__name__ + '.DeleteVip') diff --git a/quantumclient/shell.py b/quantumclient/shell.py index 8008978ac..3b8ae5c84 100644 --- a/quantumclient/shell.py +++ b/quantumclient/shell.py @@ -145,6 +145,53 @@ COMMAND_V2 = { 'quantumclient.quantum.v2_0.securitygroup.CreateSecurityGroupRule'), 'security-group-rule-delete': utils.import_class( 'quantumclient.quantum.v2_0.securitygroup.DeleteSecurityGroupRule'), + 'lb-vip-list': utils.import_class( + 'quantumclient.quantum.v2_0.lb.vip.ListVip'), + 'lb-vip-show': utils.import_class( + 'quantumclient.quantum.v2_0.lb.vip.ShowVip'), + 'lb-vip-create': utils.import_class( + 'quantumclient.quantum.v2_0.lb.vip.CreateVip'), + 'lb-vip-update': utils.import_class( + 'quantumclient.quantum.v2_0.lb.vip.UpdateVip'), + 'lb-vip-delete': utils.import_class( + 'quantumclient.quantum.v2_0.lb.vip.DeleteVip'), + 'lb-pool-list': utils.import_class( + 'quantumclient.quantum.v2_0.lb.pool.ListPool'), + 'lb-pool-show': utils.import_class( + 'quantumclient.quantum.v2_0.lb.pool.ShowPool'), + 'lb-pool-create': utils.import_class( + 'quantumclient.quantum.v2_0.lb.pool.CreatePool'), + 'lb-pool-update': utils.import_class( + 'quantumclient.quantum.v2_0.lb.pool.UpdatePool'), + 'lb-pool-delete': utils.import_class( + 'quantumclient.quantum.v2_0.lb.pool.DeletePool'), + 'lb-pool-stats': utils.import_class( + 'quantumclient.quantum.v2_0.lb.pool.RetrievePoolStats'), + 'lb-member-list': utils.import_class( + 'quantumclient.quantum.v2_0.lb.member.ListMember'), + 'lb-member-show': utils.import_class( + 'quantumclient.quantum.v2_0.lb.member.ShowMember'), + 'lb-member-create': utils.import_class( + 'quantumclient.quantum.v2_0.lb.member.CreateMember'), + 'lb-member-update': utils.import_class( + 'quantumclient.quantum.v2_0.lb.member.UpdateMember'), + 'lb-member-delete': utils.import_class( + 'quantumclient.quantum.v2_0.lb.member.DeleteMember'), + 'lb-healthmonitor-list': utils.import_class( + 'quantumclient.quantum.v2_0.lb.healthmonitor.ListHealthMonitor'), + 'lb-healthmonitor-show': utils.import_class( + 'quantumclient.quantum.v2_0.lb.healthmonitor.ShowHealthMonitor'), + 'lb-healthmonitor-create': utils.import_class( + 'quantumclient.quantum.v2_0.lb.healthmonitor.CreateHealthMonitor'), + 'lb-healthmonitor-update': utils.import_class( + 'quantumclient.quantum.v2_0.lb.healthmonitor.UpdateHealthMonitor'), + 'lb-healthmonitor-delete': utils.import_class( + 'quantumclient.quantum.v2_0.lb.healthmonitor.DeleteHealthMonitor'), + 'lb-healthmonitor-associate': utils.import_class( + 'quantumclient.quantum.v2_0.lb.healthmonitor.AssociateHealthMonitor'), + 'lb-healthmonitor-disassociate': utils.import_class( + 'quantumclient.quantum.v2_0.lb.healthmonitor' + '.DisassociateHealthMonitor'), } COMMANDS = {'2.0': COMMAND_V2} diff --git a/quantumclient/tests/unit/lb/__init__.py b/quantumclient/tests/unit/lb/__init__.py new file mode 100644 index 000000000..1668497e7 --- /dev/null +++ b/quantumclient/tests/unit/lb/__init__.py @@ -0,0 +1,16 @@ +# Copyright 2013 OpenStack LLC. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 diff --git a/quantumclient/tests/unit/lb/test_cli20_healthmonitor.py b/quantumclient/tests/unit/lb/test_cli20_healthmonitor.py new file mode 100644 index 000000000..657b24e73 --- /dev/null +++ b/quantumclient/tests/unit/lb/test_cli20_healthmonitor.py @@ -0,0 +1,189 @@ +# Copyright 2013 Mirantis Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Ilya Shakhat, Mirantis Inc. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import sys + +from mox import ContainsKeyValue + +from quantumclient.quantum.v2_0.lb import healthmonitor +from quantumclient.tests.unit import test_cli20 + + +class CLITestV20LbHealthmonitor(test_cli20.CLITestV20Base): + def test_create_healthmonitor_with_all_params(self): + """lb-healthmonitor-create with mandatory params only""" + resource = 'health_monitor' + cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), + None) + delay = '60' + max_retries = '2' + timeout = '10' + type = 'tcp' + tenant_id = 'my-tenant' + my_id = 'my-id' + args = ['--admin-state-down', + '--delay', delay, + '--max-retries', max_retries, + '--timeout', timeout, + '--type', type, + '--tenant-id', tenant_id] + position_names = ['admin_state_up', 'delay', 'max_retries', 'timeout', + 'type', 'tenant_id'] + position_values = [True, delay, max_retries, timeout, type, + tenant_id] + self._test_create_resource(resource, cmd, '', my_id, args, + position_names, position_values) + + def test_create_healthmonitor_with_all_params(self): + """lb-healthmonitor-create with all params set""" + resource = 'health_monitor' + cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), + None) + admin_state_up = False + delay = '60' + expected_codes = '200-202,204' + http_method = 'HEAD' + max_retries = '2' + timeout = '10' + type = 'tcp' + tenant_id = 'my-tenant' + url_path = '/health' + my_id = 'my-id' + args = ['--admin-state-down', + '--delay', delay, + '--expected-codes', expected_codes, + '--http-method', http_method, + '--max-retries', max_retries, + '--timeout', timeout, + '--type', type, + '--tenant-id', tenant_id, + '--url-path', url_path] + position_names = ['admin_state_up', 'delay', + 'expected_codes', 'http_method', + 'max_retries', 'timeout', + 'type', 'tenant_id', 'url_path'] + position_values = [admin_state_up, delay, + expected_codes, http_method, + max_retries, timeout, + type, tenant_id, url_path] + self._test_create_resource(resource, cmd, '', my_id, args, + position_names, position_values) + + def test_list_healthmonitors(self): + """lb-healthmonitor-list""" + resources = "health_monitors" + cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), + None) + self._test_list_resources(resources, cmd, True) + + def test_show_healthmonitor_id(self): + """lb-healthmonitor-show test_id""" + resource = 'health_monitor' + cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout), + None) + args = ['--fields', 'id', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, args, ['id']) + + def test_show_healthmonitor_id_name(self): + """lb-healthmonitor-show""" + resource = 'health_monitor' + cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout), + None) + args = ['--fields', 'id', '--fields', 'name', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, + args, ['id', 'name']) + + def test_update_health_monitor(self): + """lb-healthmonitor-update myid --name myname --tags a b.""" + resource = 'health_monitor' + cmd = healthmonitor.UpdateHealthMonitor(test_cli20.MyApp(sys.stdout), + None) + self._test_update_resource(resource, cmd, 'myid', + ['myid', '--timeout', '5'], + {'timeout': '5', }) + + def test_delete_healthmonitor(self): + """lb-healthmonitor-delete my-id""" + resource = 'health_monitor' + cmd = healthmonitor.DeleteHealthMonitor(test_cli20.MyApp(sys.stdout), + None) + my_id = 'my-id' + args = [my_id] + self._test_delete_resource(resource, cmd, my_id, args) + + def test_associate_healthmonitor(self): + cmd = healthmonitor.AssociateHealthMonitor( + test_cli20.MyApp(sys.stdout), + None) + resource = 'health_monitor' + health_monitor_id = 'hm-id' + pool_id = 'p_id' + args = [health_monitor_id, pool_id] + + self.mox.StubOutWithMock(cmd, "get_client") + self.mox.StubOutWithMock(self.client.httpclient, "request") + cmd.get_client().MultipleTimes().AndReturn(self.client) + + body = {resource: {'id': health_monitor_id}} + result = {resource: {'id': health_monitor_id}, } + result_str = self.client.serialize(result) + + path = getattr(self.client, + "associate_pool_health_monitors_path") % pool_id + return_tup = (test_cli20.MyResp(200), result_str) + self.client.httpclient.request( + test_cli20.end_url(path), 'POST', + body=test_cli20.MyComparator(body, self.client), + headers=ContainsKeyValue('X-Auth-Token', + test_cli20.TOKEN)).AndReturn(return_tup) + self.mox.ReplayAll() + cmd_parser = cmd.get_parser('test_' + resource) + parsed_args = cmd_parser.parse_args(args) + cmd.run(parsed_args) + self.mox.VerifyAll() + self.mox.UnsetStubs() + + def test_disassociate_healthmonitor(self): + cmd = healthmonitor.DisassociateHealthMonitor( + test_cli20.MyApp(sys.stdout), + None) + resource = 'health_monitor' + health_monitor_id = 'hm-id' + pool_id = 'p_id' + args = [health_monitor_id, pool_id] + + self.mox.StubOutWithMock(cmd, "get_client") + self.mox.StubOutWithMock(self.client.httpclient, "request") + cmd.get_client().MultipleTimes().AndReturn(self.client) + + path = getattr(self.client, + "disassociate_pool_health_monitors_path") % \ + {'pool': pool_id, 'health_monitor': health_monitor_id} + return_tup = (test_cli20.MyResp(204), None) + self.client.httpclient.request( + test_cli20.end_url(path), 'DELETE', + body=None, + headers=ContainsKeyValue('X-Auth-Token', + test_cli20.TOKEN)).AndReturn(return_tup) + self.mox.ReplayAll() + cmd_parser = cmd.get_parser('test_' + resource) + parsed_args = cmd_parser.parse_args(args) + cmd.run(parsed_args) + self.mox.VerifyAll() + self.mox.UnsetStubs() diff --git a/quantumclient/tests/unit/lb/test_cli20_member.py b/quantumclient/tests/unit/lb/test_cli20_member.py new file mode 100644 index 000000000..7155073a5 --- /dev/null +++ b/quantumclient/tests/unit/lb/test_cli20_member.py @@ -0,0 +1,104 @@ +# Copyright 2013 Mirantis Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Ilya Shakhat, Mirantis Inc. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import sys + +from quantumclient.quantum.v2_0.lb import member +from quantumclient.tests.unit import test_cli20 + + +class CLITestV20LbMember(test_cli20.CLITestV20Base): + def test_create_member(self): + """lb-member-create with mandatory params only""" + resource = 'member' + cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) + address = '10.0.0.1' + port = '8080' + tenant_id = 'my-tenant' + my_id = 'my-id' + pool_id = 'pool-id' + args = ['--address', address, '--port', port, + '--tenant-id', tenant_id, pool_id] + position_names = ['address', 'port', 'tenant_id', 'pool_id', + 'admin_state_up'] + position_values = [address, port, tenant_id, pool_id, + True] + self._test_create_resource(resource, cmd, None, my_id, args, + position_names, position_values, + admin_state_up=None) + + def test_create_member_all_params(self): + """lb-member-create with all available params""" + resource = 'member' + cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) + address = '10.0.0.1' + admin_state_up = False + port = '8080' + weight = '1' + tenant_id = 'my-tenant' + my_id = 'my-id' + pool_id = 'pool-id' + args = ['--address', address, '--admin-state-down', + '--port', port, '--weight', weight, + '--tenant-id', tenant_id, pool_id] + position_names = ['address', 'admin_state_up', 'port', 'weight', + 'tenant_id', 'pool_id'] + position_values = [address, admin_state_up, port, weight, + tenant_id, pool_id] + self._test_create_resource(resource, cmd, None, my_id, args, + position_names, position_values, + admin_state_up=None) + + def test_list_members(self): + """lb-member-list""" + resources = "members" + cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) + self._test_list_resources(resources, cmd, True) + + def test_show_member_id(self): + """lb-member-show test_id""" + resource = 'member' + cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None) + args = ['--fields', 'id', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, args, ['id']) + + def test_show_member_id_name(self): + """lb-member-show""" + resource = 'member' + cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None) + args = ['--fields', 'id', '--fields', 'name', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, + args, ['id', 'name']) + + def test_update_member(self): + """lb-member-update myid --name myname --tags a b.""" + resource = 'member' + cmd = member.UpdateMember(test_cli20.MyApp(sys.stdout), None) + self._test_update_resource(resource, cmd, 'myid', + ['myid', '--name', 'myname', + '--tags', 'a', 'b'], + {'name': 'myname', 'tags': ['a', 'b'], }) + + def test_delete_member(self): + """lb-member-delete my-id""" + resource = 'member' + cmd = member.DeleteMember(test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + args = [my_id] + self._test_delete_resource(resource, cmd, my_id, args) diff --git a/quantumclient/tests/unit/lb/test_cli20_pool.py b/quantumclient/tests/unit/lb/test_cli20_pool.py new file mode 100644 index 000000000..ee2f4e3eb --- /dev/null +++ b/quantumclient/tests/unit/lb/test_cli20_pool.py @@ -0,0 +1,145 @@ +# Copyright 2013 Mirantis Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Ilya Shakhat, Mirantis Inc. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import sys + +from mox import ContainsKeyValue + +from quantumclient.quantum.v2_0.lb import pool +from quantumclient.tests.unit import test_cli20 + + +class CLITestV20LbPool(test_cli20.CLITestV20Base): + + def test_create_pool_with_mandatory_params(self): + """lb-pool-create with mandatory params only""" + resource = 'pool' + cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) + name = 'my-name' + lb_method = 'round-robin' + protocol = 'http' + subnet_id = 'subnet-id' + tenant_id = 'my-tenant' + my_id = 'my-id' + args = ['--lb-method', lb_method, + '--name', name, + '--protocol', protocol, + '--subnet-id', subnet_id, + '--tenant-id', tenant_id] + position_names = ['admin_state_up', 'lb_method', 'name', + 'protocol', 'subnet_id', 'tenant_id'] + position_values = [True, lb_method, name, + protocol, subnet_id, tenant_id] + self._test_create_resource(resource, cmd, name, my_id, args, + position_names, position_values) + + def test_create_pool_with_all_params(self): + """lb-pool-create with all params set""" + resource = 'pool' + cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) + name = 'my-name' + description = 'my-desc' + lb_method = 'round-robin' + protocol = 'http' + subnet_id = 'subnet-id' + tenant_id = 'my-tenant' + my_id = 'my-id' + args = ['--admin-state-down', + '--description', description, + '--lb-method', lb_method, + '--name', name, + '--protocol', protocol, + '--subnet-id', subnet_id, + '--tenant-id', tenant_id] + position_names = ['admin_state_up', 'description', 'lb_method', 'name', + 'protocol', 'subnet_id', 'tenant_id'] + position_values = [False, description, lb_method, name, + protocol, subnet_id, tenant_id] + self._test_create_resource(resource, cmd, name, my_id, args, + position_names, position_values) + + def test_list_pools(self): + """lb-pool-list""" + resources = "pools" + cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) + self._test_list_resources(resources, cmd, True) + + def test_show_pool_id(self): + """lb-pool-show test_id""" + resource = 'pool' + cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) + args = ['--fields', 'id', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, args, ['id']) + + def test_show_pool_id_name(self): + """lb-pool-show""" + resource = 'pool' + cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) + args = ['--fields', 'id', '--fields', 'name', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, + args, ['id', 'name']) + + def test_update_pool(self): + """lb-pool-update myid --name newname --tags a b.""" + resource = 'pool' + cmd = pool.UpdatePool(test_cli20.MyApp(sys.stdout), None) + self._test_update_resource(resource, cmd, 'myid', + ['myid', '--name', 'newname'], + {'name': 'newname', }) + + def test_delete_pool(self): + """lb-pool-delete my-id""" + resource = 'pool' + cmd = pool.DeletePool(test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + args = [my_id] + self._test_delete_resource(resource, cmd, my_id, args) + + def test_retrieve_pool_stats(self): + """lb-pool-stats test_id""" + resource = 'pool' + cmd = pool.RetrievePoolStats(test_cli20.MyApp(sys.stdout), None) + my_id = self.test_id + fields = ['bytes_in', 'bytes_out'] + args = ['--fields', 'bytes_in', '--fields', 'bytes_out', my_id] + + self.mox.StubOutWithMock(cmd, "get_client") + self.mox.StubOutWithMock(self.client.httpclient, "request") + cmd.get_client().MultipleTimes().AndReturn(self.client) + query = "&".join(["fields=%s" % field for field in fields]) + expected_res = {'stats': {'bytes_in': '1234', 'bytes_out': '4321'}} + resstr = self.client.serialize(expected_res) + path = getattr(self.client, "pool_path_stats") + return_tup = (test_cli20.MyResp(200), resstr) + self.client.httpclient.request( + test_cli20.end_url(path % my_id, query), 'GET', + body=None, + headers=ContainsKeyValue('X-Auth-Token', + test_cli20.TOKEN)).AndReturn(return_tup) + self.mox.ReplayAll() + + cmd_parser = cmd.get_parser("test_" + resource) + parsed_args = cmd_parser.parse_args(args) + cmd.run(parsed_args) + + self.mox.VerifyAll() + self.mox.UnsetStubs() + _str = self.fake_stdout.make_string() + self.assertTrue('bytes_in' in _str) + self.assertTrue('bytes_out' in _str) diff --git a/quantumclient/tests/unit/lb/test_cli20_vip.py b/quantumclient/tests/unit/lb/test_cli20_vip.py new file mode 100644 index 000000000..8b7d17621 --- /dev/null +++ b/quantumclient/tests/unit/lb/test_cli20_vip.py @@ -0,0 +1,185 @@ +# Copyright 2013 Mirantis Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Ilya Shakhat, Mirantis Inc. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import sys + +from quantumclient.quantum.v2_0.lb import vip +from quantumclient.tests.unit import test_cli20 + + +class CLITestV20LbVip(test_cli20.CLITestV20Base): + def test_create_vip_with_mandatory_params(self): + """lb-vip-create with all mandatory params""" + resource = 'vip' + cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) + pool_id = 'my-pool-id' + name = 'my-name' + subnet_id = 'subnet-id' + port = '1000' + protocol = 'tcp' + tenant_id = 'my-tenant' + my_id = 'my-id' + args = ['--name', name, + '--port', port, + '--protocol', protocol, + '--subnet-id', subnet_id, + '--tenant-id', tenant_id, + pool_id] + position_names = ['pool_id', 'name', 'port', 'protocol', + 'subnet_id', 'tenant_id'] + position_values = [pool_id, name, port, protocol, + subnet_id, tenant_id] + self._test_create_resource(resource, cmd, name, my_id, args, + position_names, position_values, + admin_state_up=True) + + def test_create_vip_with_all_params(self): + """lb-vip-create with all params""" + resource = 'vip' + cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) + pool_id = 'my-pool-id' + name = 'my-name' + description = 'my-desc' + address = '10.0.0.2' + admin_state = False + connection_limit = '1000' + subnet_id = 'subnet-id' + port = '80' + protocol = 'tcp' + tenant_id = 'my-tenant' + my_id = 'my-id' + args = ['--name', name, + '--description', description, + '--address', address, + '--admin-state-down', + '--connection-limit', connection_limit, + '--port', port, + '--protocol', protocol, + '--subnet-id', subnet_id, + '--tenant-id', tenant_id, + pool_id] + position_names = ['pool_id', 'name', 'description', 'address', + 'admin_state_up', 'connection_limit', 'port', + 'protocol', 'subnet_id', + 'tenant_id'] + position_values = [pool_id, name, description, address, + admin_state, connection_limit, port, + protocol, subnet_id, + tenant_id] + self._test_create_resource(resource, cmd, name, my_id, args, + position_names, position_values) + + def test_create_vip_with_session_persistence_params(self): + """lb-vip-create with mandatory and session-persistence params""" + resource = 'vip' + cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) + pool_id = 'my-pool-id' + name = 'my-name' + subnet_id = 'subnet-id' + port = '1000' + protocol = 'tcp' + tenant_id = 'my-tenant' + my_id = 'my-id' + args = ['--name', name, + '--port', port, + '--protocol', protocol, + '--subnet-id', subnet_id, + '--tenant-id', tenant_id, + pool_id, + '--session-persistence', 'type=dict', + 'type=cookie,cookie_name=pie', + '--optional-param', 'any'] + position_names = ['pool_id', 'name', 'port', 'protocol', + 'subnet_id', 'tenant_id', 'optional_param'] + position_values = [pool_id, name, port, protocol, + subnet_id, tenant_id, 'any'] + extra_body = { + 'session_persistence': { + 'type': 'cookie', + 'cookie_name': 'pie', + }, + } + self._test_create_resource(resource, cmd, name, my_id, args, + position_names, position_values, + admin_state_up=True, extra_body=extra_body) + + def test_list_vips(self): + """lb-vip-list""" + resources = "vips" + cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) + self._test_list_resources(resources, cmd, True) + + def test_show_vip_id(self): + """lb-vip-show test_id""" + resource = 'vip' + cmd = vip.ShowVip(test_cli20.MyApp(sys.stdout), None) + args = ['--fields', 'id', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, args, ['id']) + + def test_show_vip_id_name(self): + """lb-vip-show""" + resource = 'vip' + cmd = vip.ShowVip(test_cli20.MyApp(sys.stdout), None) + args = ['--fields', 'id', '--fields', 'name', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, + args, ['id', 'name']) + + def test_update_vip(self): + """lb-vip-update myid --name myname --tags a b.""" + resource = 'vip' + cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) + self._test_update_resource(resource, cmd, 'myid', + ['myid', '--name', 'myname', + '--tags', 'a', 'b'], + {'name': 'myname', 'tags': ['a', 'b'], }) + + def test_update_vip_with_session_persistence(self): + resource = 'vip' + cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) + body = { + 'session_persistence': { + 'type': 'source', + }, + } + args = ['myid', '--session-persistence', 'type=dict', + 'type=source'] + self._test_update_resource(resource, cmd, 'myid', args, body) + + def test_update_vip_with_session_persistence_and_name(self): + resource = 'vip' + cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) + body = { + 'name': 'newname', + 'session_persistence': { + 'type': 'cookie', + 'cookie_name': 'pie', + }, + } + args = ['myid', '--name', 'newname', + '--session-persistence', 'type=dict', + 'type=cookie,cookie_name=pie'] + self._test_update_resource(resource, cmd, 'myid', args, body) + + def test_delete_vip(self): + """lb-vip-delete my-id""" + resource = 'vip' + cmd = vip.DeleteVip(test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + args = [my_id] + self._test_delete_resource(resource, cmd, my_id, args) diff --git a/quantumclient/tests/unit/test_casual_args.py b/quantumclient/tests/unit/test_casual_args.py index c827e0e41..150edec2d 100644 --- a/quantumclient/tests/unit/test_casual_args.py +++ b/quantumclient/tests/unit/test_casual_args.py @@ -53,6 +53,16 @@ class CLITestArgs(testtools.TestCase): self.assertRaises(exceptions.CommandError, quantumV20.parse_args_to_dict, _specs) + def test_badarg_duplicate(self): + _specs = ['--tag=t', '--arg1', 'value1', '--arg1', 'value1'] + self.assertRaises(exceptions.CommandError, + quantumV20.parse_args_to_dict, _specs) + + def test_badarg_early_type_specification(self): + _specs = ['type=dict', 'key=value'] + self.assertRaises(exceptions.CommandError, + quantumV20.parse_args_to_dict, _specs) + def test_arg(self): _specs = ['--tag=t', '--arg1', 'value1'] self.assertEqual('value1', @@ -64,6 +74,12 @@ class CLITestArgs(testtools.TestCase): self.assertEqual('value1', arg1['key1']) self.assertEqual('value2', arg1['key2']) + def test_dict_arg_with_attribute_named_type(self): + _specs = ['--tag=t', '--arg1', 'type=dict', 'type=value1,key2=value2'] + arg1 = quantumV20.parse_args_to_dict(_specs)['arg1'] + self.assertEqual('value1', arg1['type']) + self.assertEqual('value2', arg1['key2']) + def test_list_of_dict_arg(self): _specs = ['--tag=t', '--arg1', 'type=dict', 'list=true', 'key1=value1,key2=value2'] diff --git a/quantumclient/tests/unit/test_cli20.py b/quantumclient/tests/unit/test_cli20.py index 0c9e6a0a5..1a97eb1b4 100644 --- a/quantumclient/tests/unit/test_cli20.py +++ b/quantumclient/tests/unit/test_cli20.py @@ -135,7 +135,8 @@ class CLITestV20Base(testtools.TestCase): def _test_create_resource(self, resource, cmd, name, myid, args, position_names, position_values, tenant_id=None, - tags=None, admin_state_up=True, shared=False): + tags=None, admin_state_up=True, shared=False, + extra_body=None): self.mox.StubOutWithMock(cmd, "get_client") self.mox.StubOutWithMock(self.client.httpclient, "request") cmd.get_client().MultipleTimes().AndReturn(self.client) @@ -151,6 +152,8 @@ class CLITestV20Base(testtools.TestCase): body[resource].update({'tags': tags}) if shared: body[resource].update({'shared': shared}) + if extra_body: + body[resource].update(extra_body) for i in xrange(len(position_names)): body[resource].update({position_names[i]: position_values[i]}) diff --git a/quantumclient/v2_0/client.py b/quantumclient/v2_0/client.py index 542f83ff0..305ea1e5f 100644 --- a/quantumclient/v2_0/client.py +++ b/quantumclient/v2_0/client.py @@ -168,6 +168,18 @@ class Client(object): security_group_path = "/security-groups/%s" security_group_rules_path = "/security-group-rules" security_group_rule_path = "/security-group-rules/%s" + vips_path = "/lb/vips" + vip_path = "/lb/vips/%s" + pools_path = "/lb/pools" + pool_path = "/lb/pools/%s" + pool_path_stats = "/lb/pools/%s/stats" + members_path = "/lb/members" + member_path = "/lb/members/%s" + health_monitors_path = "/lb/health_monitors" + health_monitor_path = "/lb/health_monitors/%s" + associate_pool_health_monitors_path = "/lb/pools/%s/health_monitors" + disassociate_pool_health_monitors_path = ( + "/lb/pools/%(pool)s/health_monitors/%(health_monitor)s") @APIParamsCall def get_quotas_tenant(self, **_params): @@ -475,6 +487,175 @@ class Client(object): return self.get(self.security_group_rule_path % (security_group_rule), params=_params) + @APIParamsCall + def list_vips(self, **_params): + """ + Fetches a list of all load balancer vips for a tenant + """ + # Pass filters in "params" argument to do_request + return self.get(self.vips_path, params=_params) + + @APIParamsCall + def show_vip(self, vip, **_params): + """ + Fetches information of a certain load balancer vip + """ + return self.get(self.vip_path % (vip), params=_params) + + @APIParamsCall + def create_vip(self, body=None): + """ + Creates a new load balancer vip + """ + return self.post(self.vips_path, body=body) + + @APIParamsCall + def update_vip(self, vip, body=None): + """ + Updates a load balancer vip + """ + return self.put(self.vip_path % (vip), body=body) + + @APIParamsCall + def delete_vip(self, vip): + """ + Deletes the specified load balancer vip + """ + return self.delete(self.vip_path % (vip)) + + @APIParamsCall + def list_pools(self, **_params): + """ + Fetches a list of all load balancer pools for a tenant + """ + # Pass filters in "params" argument to do_request + return self.get(self.pools_path, params=_params) + + @APIParamsCall + def show_pool(self, pool, **_params): + """ + Fetches information of a certain load balancer pool + """ + return self.get(self.pool_path % (pool), params=_params) + + @APIParamsCall + def create_pool(self, body=None): + """ + Creates a new load balancer pool + """ + return self.post(self.pools_path, body=body) + + @APIParamsCall + def update_pool(self, pool, body=None): + """ + Updates a load balancer pool + """ + return self.put(self.pool_path % (pool), body=body) + + @APIParamsCall + def delete_pool(self, pool): + """ + Deletes the specified load balancer pool + """ + return self.delete(self.pool_path % (pool)) + + @APIParamsCall + def retrieve_pool_stats(self, pool, **_params): + """ + Retrieves stats for a certain load balancer pool + """ + return self.get(self.pool_path_stats % (pool), params=_params) + + @APIParamsCall + def list_members(self, **_params): + """ + Fetches a list of all load balancer members for a tenant + """ + # Pass filters in "params" argument to do_request + return self.get(self.members_path, params=_params) + + @APIParamsCall + def show_member(self, member, **_params): + """ + Fetches information of a certain load balancer member + """ + return self.get(self.member_path % (member), params=_params) + + @APIParamsCall + def create_member(self, body=None): + """ + Creates a new load balancer member + """ + return self.post(self.members_path, body=body) + + @APIParamsCall + def update_member(self, member, body=None): + """ + Updates a load balancer member + """ + return self.put(self.member_path % (member), body=body) + + @APIParamsCall + def delete_member(self, member): + """ + Deletes the specified load balancer member + """ + return self.delete(self.member_path % (member)) + + @APIParamsCall + def list_health_monitors(self, **_params): + """ + Fetches a list of all load balancer health monitors for a tenant + """ + # Pass filters in "params" argument to do_request + return self.get(self.health_monitors_path, params=_params) + + @APIParamsCall + def show_health_monitor(self, health_monitor, **_params): + """ + Fetches information of a certain load balancer health monitor + """ + return self.get(self.health_monitor_path % (health_monitor), + params=_params) + + @APIParamsCall + def create_health_monitor(self, body=None): + """ + Creates a new load balancer health monitor + """ + return self.post(self.health_monitors_path, body=body) + + @APIParamsCall + def update_health_monitor(self, health_monitor, body=None): + """ + Updates a load balancer health monitor + """ + return self.put(self.health_monitor_path % (health_monitor), body=body) + + @APIParamsCall + def delete_health_monitor(self, health_monitor): + """ + Deletes the specified load balancer health monitor + """ + return self.delete(self.health_monitor_path % (health_monitor)) + + @APIParamsCall + def associate_health_monitor(self, pool, body): + """ + Associate specified load balancer health monitor and pool + """ + return self.post(self.associate_pool_health_monitors_path % (pool), + body=body) + + @APIParamsCall + def disassociate_health_monitor(self, pool, health_monitor): + """ + Disassociate specified load balancer health monitor and pool + """ + path = (self.disassociate_pool_health_monitors_path % + {'pool': pool, 'health_monitor': health_monitor}) + return self.delete(path) + def __init__(self, **kwargs): """ Initialize a new client for the Quantum v2.0 API. """ super(Client, self).__init__()