diff --git a/doc/source/cli/osc/v2/load-balancer.rst b/doc/source/cli/osc/v2/load-balancer.rst index ed6b2ef..d7ba416 100644 --- a/doc/source/cli/osc/v2/load-balancer.rst +++ b/doc/source/cli/osc/v2/load-balancer.rst @@ -26,6 +26,9 @@ loadbalancer .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer stats show +.. autoprogram-cliff:: openstack.load_balancer.v2 + :command: loadbalancer failover + ======== listener ======== @@ -74,3 +77,10 @@ quota .. autoprogram-cliff:: openstack.load_balancer.v2 :command: loadbalancer quota * + +======= +amphora +======= + +.. autoprogram-cliff:: openstack.load_balancer.v2 + :command: loadbalancer amphora * diff --git a/octaviaclient/api/constants.py b/octaviaclient/api/constants.py index 59bed04..8330cc8 100644 --- a/octaviaclient/api/constants.py +++ b/octaviaclient/api/constants.py @@ -11,27 +11,34 @@ # under the License. # -BASE_LOADBALANCER_URL = '/loadbalancers' +BASE_LBAAS_ENDPOINT = '/lbaas' +BASE_OCTAVIA_ENDPOINT = '/octavia' + +BASE_LOADBALANCER_URL = BASE_LBAAS_ENDPOINT + '/loadbalancers' BASE_SINGLE_LB_URL = BASE_LOADBALANCER_URL + '/{uuid}' BASE_LB_STATS_URL = BASE_SINGLE_LB_URL + '/stats' +BASE_LOADBALANCER_FAILOVER_URL = BASE_SINGLE_LB_URL + '/failover' -BASE_LISTENER_URL = '/listeners' +BASE_LISTENER_URL = BASE_LBAAS_ENDPOINT + '/listeners' BASE_SINGLE_LISTENER_URL = BASE_LISTENER_URL + '/{uuid}' -BASE_POOL_URL = '/pools' +BASE_POOL_URL = BASE_LBAAS_ENDPOINT + '/pools' BASE_SINGLE_POOL_URL = BASE_POOL_URL + '/{pool_id}' BASE_MEMBER_URL = BASE_SINGLE_POOL_URL + '/members' BASE_SINGLE_MEMBER_URL = BASE_MEMBER_URL + '/{member_id}' -BASE_HEALTH_MONITOR_URL = '/healthmonitors' +BASE_HEALTH_MONITOR_URL = BASE_LBAAS_ENDPOINT + '/healthmonitors' BASE_SINGLE_HEALTH_MONITOR_URL = BASE_HEALTH_MONITOR_URL + '/{uuid}' -BASE_L7POLICY_URL = '/l7policies' +BASE_L7POLICY_URL = BASE_LBAAS_ENDPOINT + '/l7policies' BASE_SINGLE_L7POLICY_URL = BASE_L7POLICY_URL + '/{policy_uuid}' BASE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/rules' BASE_SINGLE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/rules/{rule_uuid}' -BASE_QUOTA_URL = '/quotas' +BASE_QUOTA_URL = BASE_LBAAS_ENDPOINT + '/quotas' BASE_SINGLE_QUOTA_URL = BASE_QUOTA_URL + '/{uuid}' BASE_QUOTA_DEFAULT_URL = BASE_QUOTA_URL + '/defaults' + +BASE_AMPHORA_URL = BASE_OCTAVIA_ENDPOINT + "/amphorae" +BASE_SINGLE_AMPHORA_URL = BASE_AMPHORA_URL + "/{amphora_id}" diff --git a/octaviaclient/api/v2/__init__.py b/octaviaclient/api/v2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/octaviaclient/api/load_balancer_v2.py b/octaviaclient/api/v2/octavia.py similarity index 92% rename from octaviaclient/api/load_balancer_v2.py rename to octaviaclient/api/v2/octavia.py index 396874d..35da865 100644 --- a/octaviaclient/api/load_balancer_v2.py +++ b/octaviaclient/api/v2/octavia.py @@ -11,7 +11,7 @@ # under the License. # -"""Load Balancer v2 API Library""" +"""Octavia API Library""" from osc_lib.api import api @@ -40,13 +40,13 @@ def correct_return_codes(func): return wrapper -class APIv2(api.BaseAPI): - """Load Balancer v2 API""" +class OctaviaAPI(api.BaseAPI): + """Octavia API""" - _endpoint_suffix = '/v2.0/lbaas' + _endpoint_suffix = '/v2.0' def __init__(self, endpoint=None, **kwargs): - super(APIv2, self).__init__(endpoint=endpoint, **kwargs) + super(OctaviaAPI, self).__init__(endpoint=endpoint, **kwargs) self.endpoint = self.endpoint.rstrip('/') self._build_url() @@ -58,7 +58,7 @@ class APIv2(api.BaseAPI): """List all load balancers :param params: - Parameters to filter on (not implemented) + Parameters to filter on :return: List of load balancers """ @@ -114,7 +114,7 @@ class APIv2(api.BaseAPI): """Update a load balancer's settings :param string lb_id: - The ID of the load baalancer to update + The ID of the load balancer to update :param params: A dict of arguments to update a loadbalancer :return: @@ -138,11 +138,25 @@ class APIv2(api.BaseAPI): return response + @correct_return_codes + def load_balancer_failover(self, lb_id): + """Trigger load balancer failover + + :param string lb_id: + ID of the load balancer to failover + :return: + Response Code from the API + """ + url = const.BASE_LOADBALANCER_FAILOVER_URL.format(uuid=lb_id) + response = self.create(url, method='PUT') + + return response + def listener_list(self, **kwargs): """List all listeners :param kwargs: - Parameters to filter on (not implemented) + Parameters to filter on :return: List of listeners """ @@ -155,6 +169,7 @@ class APIv2(api.BaseAPI): """Show a listener :param string listener_id: + ID of the listener to show :return: A dict of the specified listener's settings """ @@ -210,7 +225,7 @@ class APIv2(api.BaseAPI): """List all pools :param kwargs: - Parameters to filter on (not implemented) + Parameters to filter on :return: List of pools """ @@ -363,7 +378,7 @@ class APIv2(api.BaseAPI): """List all l7policies :param kwargs: - Parameters to filter on (not implemented) + Parameters to filter on :return: List of l7policies """ @@ -432,7 +447,7 @@ class APIv2(api.BaseAPI): """List all l7rules for a l7policy :param kwargs: - Parameters to filter on (not implemented) + Parameters to filter on :return: List of l7policies """ @@ -512,7 +527,7 @@ class APIv2(api.BaseAPI): """List all health monitors :param kwargs: - Parameters to filter on (not implemented) + Parameters to filter on :return: A dict containing a list of health monitors """ @@ -646,6 +661,32 @@ class APIv2(api.BaseAPI): return response + def amphora_show(self, amphora_id): + """Show an amphora + + :param string amphora_id: + ID of the amphora to show + :return: + A ``dict`` of the specified amphora's attributes + """ + url = const.BASE_AMPHORA_URL + response = self.find(path=url, value=amphora_id) + + return response + + def amphora_list(self, **kwargs): + """List all amphorae + + :param kwargs: + Parameters to filter on + :return: + A ``dict`` containing a list of amphorae + """ + url = const.BASE_AMPHORA_URL + response = self.list(path=url, **kwargs) + + return response + class OctaviaClientException(Exception): """The base exception class for all exceptions this library raises.""" diff --git a/octaviaclient/osc/plugin.py b/octaviaclient/osc/plugin.py index 8760f50..ecbb550 100644 --- a/octaviaclient/osc/plugin.py +++ b/octaviaclient/osc/plugin.py @@ -14,7 +14,7 @@ import logging -from octaviaclient.api import load_balancer_v2 +from octaviaclient.api.v2 import octavia from osc_lib import utils LOG = logging.getLogger(__name__) @@ -24,7 +24,7 @@ API_VERSION_OPTION = 'os_loadbalancer_api_version' API_NAME = 'load_balancer' LOAD_BALANCER_API_TYPE = 'loadbalancer' LOAD_BALANCER_API_VERSIONS = { - '2.0': 'octaviaclient.api.load_balancer_v2.APIv2', + '2.0': 'octaviaclient.api.v2.octavia.OctaviaAPI', } @@ -35,7 +35,7 @@ def make_client(instance): region_name=instance.region_name, interface=instance.interface, ) - client = load_balancer_v2.APIv2( + client = octavia.OctaviaAPI( session=instance.session, service_type='load-balancer', endpoint=endpoint, diff --git a/octaviaclient/osc/v2/amphora.py b/octaviaclient/osc/v2/amphora.py new file mode 100644 index 0000000..348c8c6 --- /dev/null +++ b/octaviaclient/osc/v2/amphora.py @@ -0,0 +1,117 @@ +# 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. +# + +"""Amphora action implementation""" + + +from cliff import lister +from osc_lib.command import command +from osc_lib import utils + +from octaviaclient.osc.v2 import constants as const +from octaviaclient.osc.v2 import utils as v2_utils + + +class ListAmphora(lister.Lister): + """List amphorae""" + + def get_parser(self, prog_name): + parser = super(ListAmphora, self).get_parser(prog_name) + + parser.add_argument( + '--loadbalancer', + metavar='', + dest='loadbalancer', + help="Filter by load balancer (name or ID).", + ) + parser.add_argument( + '--compute-id', + metavar='', + help="Filter by compute ID.", + ) + + role_choices = {'MASTER', 'BACKUP', 'STANDALONE'} + parser.add_argument( + '--role', + metavar='{' + ','.join(role_choices) + '}', + choices=role_choices, + type=lambda s: s.upper(), # case insensitive + help="Filter by role." + ) + + status_choices = { + 'ALLOCATED', 'BOOTING', 'DELETED', 'ERROR', + 'PENDING_CREATE', 'PENDING_DELETE', 'READY', + } + parser.add_argument( + '--status', '--provisioning-status', + dest='status', + metavar='{' + ','.join(status_choices) + '}', + choices=status_choices, + type=lambda s: s.upper(), # case insensitive + help="Filter by amphora provisioning status." + ) + + return parser + + def take_action(self, parsed_args): + columns = const.AMPHORA_COLUMNS + attrs = v2_utils.get_amphora_attrs(self.app.client_manager, + parsed_args) + + data = self.app.client_manager.load_balancer.amphora_list(**attrs) + + formatters = { + 'amphorae': v2_utils.format_list, + } + + return ( + columns, + (utils.get_dict_properties( + amp, + columns, + formatters=formatters, + ) for amp in data['amphorae']), + ) + + +class ShowAmphora(command.ShowOne): + """Show the details of a single amphora""" + + def get_parser(self, prog_name): + parser = super(ShowAmphora, self).get_parser(prog_name) + + parser.add_argument( + 'amphora_id', + metavar='', + help='UUID of the amphora.', + ) + + return parser + + def take_action(self, parsed_args): + attrs = v2_utils.get_amphora_attrs(self.app.client_manager, + parsed_args) + + data = self.app.client_manager.load_balancer.amphora_show( + amphora_id=attrs.pop('amphora_id'), + ) + + rows = const.AMPHORA_ROWS + formatters = { + 'loadbalancers': v2_utils.format_list, + 'amphorae': v2_utils.format_list, + } + + return (rows, utils.get_dict_properties(data, rows, + formatters=formatters)) diff --git a/octaviaclient/osc/v2/constants.py b/octaviaclient/osc/v2/constants.py index c3ca91f..53e3401 100644 --- a/octaviaclient/osc/v2/constants.py +++ b/octaviaclient/osc/v2/constants.py @@ -29,7 +29,8 @@ LOAD_BALANCER_ROWS = ( 'vip_address', 'vip_network_id', 'vip_port_id', - 'vip_subnet_id') + 'vip_subnet_id', +) LOAD_BALANCER_COLUMNS = ( 'id', @@ -212,7 +213,7 @@ QUOTA_ROWS = ( 'listener', 'pool', 'health_monitor', - 'member' + 'member', ) QUOTA_COLUMNS = ( @@ -221,5 +222,33 @@ QUOTA_COLUMNS = ( 'listener', 'pool', 'health_monitor', - 'member' + 'member', +) + +AMPHORA_ROWS = ( + 'id', + 'loadbalancer_id', + 'compute_id', + 'lb_network_ip', + 'vrrp_ip', + 'ha_ip', + 'vrrp_port_id', + 'ha_port_id', + 'cert_expiration', + 'cert_busy', + 'role', + 'status', + 'vrrp_interface', + 'vrrp_id', + 'vrrp_priority', + 'cached_zone', +) + +AMPHORA_COLUMNS = ( + 'id', + 'loadbalancer_id', + 'status', + 'role', + 'lb_network_ip', + 'ha_ip', ) diff --git a/octaviaclient/osc/v2/listener.py b/octaviaclient/osc/v2/listener.py index d9ecbcb..296899c 100644 --- a/octaviaclient/osc/v2/listener.py +++ b/octaviaclient/osc/v2/listener.py @@ -31,7 +31,7 @@ class CreateListener(command.ShowOne): parser.add_argument( 'loadbalancer', - metavar='', + metavar='', help="Load balancer for the listener (name or ID)." ) parser.add_argument( @@ -155,12 +155,17 @@ class ListListener(lister.Lister): def get_parser(self, prog_name): parser = super(ListListener, self).get_parser(prog_name) - # Filtering will soon be implemented to allow this parser.add_argument( '--name', metavar='', help="List listeners by listener name." ) + parser.add_argument( + '--loadbalancer', + metavar='', + help="Filter by load balancer (name or ID).", + ) + admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', @@ -174,6 +179,7 @@ class ListListener(lister.Lister): default=None, help="List disabled listeners." ) + parser.add_argument( '--project', metavar='', diff --git a/octaviaclient/osc/v2/load_balancer.py b/octaviaclient/osc/v2/load_balancer.py index 404b0d3..9dd6c55 100644 --- a/octaviaclient/osc/v2/load_balancer.py +++ b/octaviaclient/osc/v2/load_balancer.py @@ -81,6 +81,7 @@ class CreateLoadBalancer(command.ShowOne): metavar='', help="Project for the load balancer (name or ID)." ) + admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', @@ -148,6 +149,27 @@ class DeleteLoadBalancer(command.Command): lb_id=lb_id, **attrs) +class FailoverLoadBalancer(command.Command): + """Trigger load balancer failover""" + + def get_parser(self, prog_name): + parser = super(FailoverLoadBalancer, self).get_parser(prog_name) + + parser.add_argument( + 'loadbalancer', + metavar='', + help="Name or UUID of the load balancer." + ) + + return parser + + def take_action(self, parsed_args): + attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager, + parsed_args) + self.app.client_manager.load_balancer.load_balancer_failover( + lb_id=attrs.pop('loadbalancer_id')) + + class ListLoadBalancer(lister.Lister): """List load balancers""" @@ -250,6 +272,7 @@ class SetLoadBalancer(command.Command): metavar='', help="Set load balancer description." ) + admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( '--enable', diff --git a/octaviaclient/osc/v2/pool.py b/octaviaclient/osc/v2/pool.py index 081e0c7..b96cddd 100644 --- a/octaviaclient/osc/v2/pool.py +++ b/octaviaclient/osc/v2/pool.py @@ -127,12 +127,18 @@ class ListPool(lister.Lister): def get_parser(self, prog_name): parser = super(ListPool, self).get_parser(prog_name) + parser.add_argument( + '--loadbalancer', + metavar='', + help="Filter by load balancer (name or ID).", + ) + return parser def take_action(self, parsed_args): columns = const.POOL_COLUMNS - - data = self.app.client_manager.load_balancer.pool_list() + attrs = v2_utils.get_pool_attrs(self.app.client_manager, parsed_args) + data = self.app.client_manager.load_balancer.pool_list(**attrs) formatters = {'loadbalancers': v2_utils.format_list, 'members': v2_utils.format_list, 'listeners': v2_utils.format_list} diff --git a/octaviaclient/osc/v2/utils.py b/octaviaclient/osc/v2/utils.py index 94b6572..1fa90b6 100644 --- a/octaviaclient/osc/v2/utils.py +++ b/octaviaclient/osc/v2/utils.py @@ -17,6 +17,47 @@ from osc_lib import exceptions from openstackclient.identity import common as identity_common +def _map_attrs(args, source_attr_map): + res = {} + for k, v in args.items(): + if (v is None) or (k not in source_attr_map): + continue + source_val = source_attr_map[k] + # Attributes with 2 values map directly to a callable + if len(source_val) == 2: + res[source_val[0]] = source_val[1](v) + # Attributes with 3 values map directly to a resource + elif len(source_val) == 3: + if not isinstance(v, list): + res[source_val[0]] = get_resource_id( + source_val[2], + source_val[1], + v, + ) + else: + res[source_val[0]] = [get_resource_id( + source_val[2], + source_val[1], + x, + ) for x in v] + + # Attributes with 4 values map to a resource with a parent + elif len(source_val) == 4: + parent = source_attr_map[source_val[2]] + parent_id = get_resource_id( + parent[2], + parent[1], + args[source_val[2]], + ) + child = source_val + res[child[0]] = get_resource_id( + child[3], + child[1], + {child[0]: str(v), parent[0]: str(parent_id)}, + ) + return res + + def get_resource_id(resource, resource_name, name): """Converts a resource name into a UUID for consumption for the API @@ -359,6 +400,26 @@ def get_quota_attrs(client_manager, parsed_args): return attrs +def get_amphora_attrs(client_manager, parsed_args): + attr_map = { + 'amphora_id': ( + 'amphora_id', + 'amphorae', + client_manager.load_balancer.amphora_list, + ), + 'loadbalancer': ( + 'loadbalancer_id', + 'loadbalancers', + client_manager.load_balancer.load_balancer_list, + ), + 'compute_id': ('compute_id', str), + 'role': ('role', str), + 'status': ('status', str), + } + + return _map_attrs(vars(parsed_args), attr_map) + + def format_list(data): return '\n'.join(i['id'] for i in data) @@ -378,35 +439,3 @@ def _format_kv(data): formatted_kv[k] = v return formatted_kv - - -def _map_attrs(attrs, attr_map): - mapped_attrs = {} - for k, v in attrs.items(): - if v is not None and k in attr_map.keys(): - # Attributes with 2 values map directly to a callable - if len(attr_map[k]) is 2: - mapped_attrs[attr_map[k][0]] = attr_map[k][1](v) - # Attributes with 3 values map directly to a resource - elif len(attr_map[k]) is 3: - mapped_attrs[attr_map[k][0]] = get_resource_id( - attr_map[k][2], - attr_map[k][1], - v - ) - # Attributes with 4 values map to a resource with a parent - else: - parent = attr_map[attr_map[k][2]] - parent_id = get_resource_id( - parent[2], - parent[1], - attrs[attr_map[k][2]] - ) - child = attr_map[k] - mapped_attrs[child[0]] = get_resource_id( - child[3], - child[1], - {child[0]: str(v), parent[0]: str(parent_id)} - ) - - return mapped_attrs diff --git a/octaviaclient/tests/unit/api/test_load_balancer.py b/octaviaclient/tests/unit/api/test_octavia.py similarity index 78% rename from octaviaclient/tests/unit/api/test_load_balancer.py rename to octaviaclient/tests/unit/api/test_octavia.py index af77b25..8c4f9ab 100644 --- a/octaviaclient/tests/unit/api/test_load_balancer.py +++ b/octaviaclient/tests/unit/api/test_octavia.py @@ -17,12 +17,14 @@ from keystoneauth1 import session from oslo_utils import uuidutils from requests_mock.contrib import fixture -from octaviaclient.api import load_balancer_v2 as lb from osc_lib.tests import utils +from octaviaclient.api.v2 import octavia + FAKE_ACCOUNT = 'q12we34r' FAKE_AUTH = '11223344556677889900' -FAKE_URL = 'http://example.com/v2.0/lbaas/' +FAKE_URL = 'http://example.com/v2.0/' +FAKE_LBAAS_URL = FAKE_URL + 'lbaas/' FAKE_LB = uuidutils.generate_uuid() FAKE_LI = uuidutils.generate_uuid() @@ -111,23 +113,23 @@ SINGLE_QT_RESP = {'quota': {'pool': -1}} SINGLE_QT_UPDATE = {'quota': {'pool': -1}} -class TestLoadBalancerv2(utils.TestCase): +class TestOctaviaClient(utils.TestCase): def setUp(self): - super(TestLoadBalancerv2, self).setUp() + super(TestOctaviaClient, self).setUp() sess = session.Session() - self.api = lb.APIv2(session=sess, endpoint=FAKE_URL) + self.api = octavia.OctaviaAPI(session=sess, endpoint=FAKE_URL) self.requests_mock = self.useFixture(fixture.Fixture()) -class TestLoadBalancer(TestLoadBalancerv2): +class TestLoadBalancer(TestOctaviaClient): _error_message = ("Validation failure: Test message.") def test_list_load_balancer_no_options(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'loadbalancers', + FAKE_LBAAS_URL + 'loadbalancers', json=LIST_LB_RESP, status_code=200, ) @@ -137,7 +139,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_show_load_balancer(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'loadbalancers/' + FAKE_LB, + FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, json=SINGLE_LB_RESP, status_code=200 ) @@ -147,7 +149,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_load_balancer(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'loadbalancers', + FAKE_LBAAS_URL + 'loadbalancers', json=SINGLE_LB_RESP, status_code=200 ) @@ -157,11 +159,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_load_balancer_error(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'loadbalancers', + FAKE_LBAAS_URL + 'loadbalancers', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.load_balancer_create, json=SINGLE_LB_RESP) @@ -169,7 +171,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_load_balancer(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'loadbalancers/' + FAKE_LB, + FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, json=SINGLE_LB_UPDATE, status_code=200 ) @@ -179,20 +181,41 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_load_balancer_error(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'loadbalancers/' + FAKE_LB, + FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.load_balancer_set, FAKE_LB, json=SINGLE_LB_UPDATE) + def test_failover_load_balancer(self): + self.requests_mock.register_uri( + 'PUT', + FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB + '/failover', + status_code=202, + ) + ret = self.api.load_balancer_failover(FAKE_LB) + self.assertEqual(202, ret.status_code) + + def test_failover_load_balancer_error(self): + self.requests_mock.register_uri( + 'PUT', + FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB + '/failover', + text='{"faultstring": "%s"}' % self._error_message, + status_code=409, + ) + self.assertRaisesRegex(octavia.OctaviaClientException, + self._error_message, + self.api.load_balancer_failover, + FAKE_LB) + def test_delete_load_balancer(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'loadbalancers/' + FAKE_LB, + FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, status_code=200 ) ret = self.api.load_balancer_delete(FAKE_LB) @@ -201,11 +224,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_load_balancer_error(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'loadbalancers/' + FAKE_LB, + FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.load_balancer_delete, FAKE_LB) @@ -213,7 +236,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_stats_show_load_balancer(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'loadbalancers/' + FAKE_LB + '/stats', + FAKE_LBAAS_URL + 'loadbalancers/' + FAKE_LB + '/stats', json=SINGLE_LB_STATS_RESP, status_code=200, ) @@ -223,7 +246,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_list_listeners_no_options(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'listeners', + FAKE_LBAAS_URL + 'listeners', json=LIST_LI_RESP, status_code=200, ) @@ -233,7 +256,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_show_listener(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'listeners/' + FAKE_LI, + FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, json=SINGLE_LI_RESP, status_code=200 ) @@ -243,7 +266,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_listener(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'listeners', + FAKE_LBAAS_URL + 'listeners', json=SINGLE_LI_RESP, status_code=200 ) @@ -253,11 +276,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_listener_error(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'listeners', + FAKE_LBAAS_URL + 'listeners', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.listener_create, json=SINGLE_LI_RESP) @@ -265,7 +288,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_listeners(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'listeners/' + FAKE_LI, + FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, json=SINGLE_LI_UPDATE, status_code=200 ) @@ -275,11 +298,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_listeners_error(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'listeners/' + FAKE_LI, + FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.listener_set, FAKE_LI, json=SINGLE_LI_UPDATE) @@ -287,7 +310,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_listener(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'listeners/' + FAKE_LI, + FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, status_code=200 ) ret = self.api.listener_delete(FAKE_LI) @@ -296,11 +319,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_listener_error(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'listeners/' + FAKE_LI, + FAKE_LBAAS_URL + 'listeners/' + FAKE_LI, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.listener_delete, FAKE_LI) @@ -308,7 +331,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_list_pool_no_options(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'pools', + FAKE_LBAAS_URL + 'pools', json=LIST_PO_RESP, status_code=200, ) @@ -318,7 +341,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_show_pool(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'pools/' + FAKE_PO, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO, json=SINGLE_PO_RESP, status_code=200 ) @@ -328,7 +351,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_pool(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'pools', + FAKE_LBAAS_URL + 'pools', json=SINGLE_PO_RESP, status_code=200 ) @@ -338,11 +361,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_pool_error(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'pools', + FAKE_LBAAS_URL + 'pools', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.pool_create, json=SINGLE_PO_RESP) @@ -350,7 +373,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_pool(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'pools/' + FAKE_PO, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO, json=SINGLE_PO_UPDATE, status_code=200 ) @@ -360,11 +383,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_pool_error(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'pools/' + FAKE_PO, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.pool_set, FAKE_PO, json=SINGLE_PO_UPDATE) @@ -372,7 +395,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_pool(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'pools/' + FAKE_PO, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO, status_code=200 ) ret = self.api.pool_delete(FAKE_PO) @@ -381,11 +404,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_pool_error(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'pools/' + FAKE_PO, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.pool_delete, FAKE_PO) @@ -393,7 +416,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_list_member_no_options(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'pools/' + FAKE_PO + '/members', + FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members', json=LIST_ME_RESP, status_code=200, ) @@ -403,7 +426,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_show_member(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, json=SINGLE_ME_RESP, status_code=200 ) @@ -413,7 +436,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_member(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'pools/' + FAKE_PO + '/members', + FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members', json=SINGLE_ME_RESP, status_code=200 ) @@ -423,11 +446,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_member_error(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'pools/' + FAKE_PO + '/members', + FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.member_create, json=SINGLE_ME_RESP, pool_id=FAKE_PO) @@ -435,7 +458,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_member(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, json=SINGLE_ME_UPDATE, status_code=200 ) @@ -446,11 +469,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_member_error(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.member_set, pool_id=FAKE_PO, member_id=FAKE_ME, @@ -459,7 +482,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_member(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, status_code=200 ) ret = self.api.member_delete(pool_id=FAKE_PO, member_id=FAKE_ME) @@ -468,11 +491,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_member_error(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, + FAKE_LBAAS_URL + 'pools/' + FAKE_PO + '/members/' + FAKE_ME, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.member_delete, pool_id=FAKE_PO, member_id=FAKE_ME) @@ -480,7 +503,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_list_l7policy_no_options(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'l7policies', + FAKE_LBAAS_URL + 'l7policies', json=LIST_L7PO_RESP, status_code=200, ) @@ -490,7 +513,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_show_l7policy(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'l7policies/' + FAKE_L7PO, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, json=SINGLE_L7PO_RESP, status_code=200 ) @@ -500,7 +523,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_l7policy(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'l7policies', + FAKE_LBAAS_URL + 'l7policies', json=SINGLE_L7PO_RESP, status_code=200 ) @@ -510,11 +533,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_l7policy_error(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'l7policies', + FAKE_LBAAS_URL + 'l7policies', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.l7policy_create, json=SINGLE_L7PO_RESP) @@ -522,7 +545,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_l7policy(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'l7policies/' + FAKE_L7PO, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, json=SINGLE_L7PO_UPDATE, status_code=200 ) @@ -532,11 +555,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_l7policy_error(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'l7policies/' + FAKE_L7PO, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.l7policy_set, FAKE_L7PO, json=SINGLE_L7PO_UPDATE) @@ -544,7 +567,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_l7policy(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'l7policies/' + FAKE_L7PO, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, status_code=200 ) ret = self.api.l7policy_delete(FAKE_L7PO) @@ -553,11 +576,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_l7policy_error(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'l7policies/' + FAKE_L7PO, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.l7policy_delete, FAKE_L7PO) @@ -565,7 +588,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_list_l7rule_no_options(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules', + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules', json=LIST_L7RU_RESP, status_code=200, ) @@ -575,7 +598,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_show_l7rule(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, json=SINGLE_L7RU_RESP, status_code=200 ) @@ -585,7 +608,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_l7rule(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules', + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules', json=SINGLE_L7RU_RESP, status_code=200 ) @@ -595,11 +618,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_l7rule_error(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules', + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.l7rule_create, FAKE_L7PO, json=SINGLE_L7RU_RESP) @@ -607,7 +630,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_l7rule(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, json=SINGLE_L7RU_UPDATE, status_code=200 ) @@ -621,11 +644,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_l7rule_error(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.l7rule_set, l7rule_id=FAKE_L7RU, @@ -635,7 +658,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_l7rule(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, status_code=200 ) ret = self.api.l7rule_delete( @@ -647,11 +670,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_l7rule_error(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, + FAKE_LBAAS_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.l7rule_delete, l7rule_id=FAKE_L7RU, @@ -660,7 +683,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_list_health_monitor_no_options(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'healthmonitors', + FAKE_LBAAS_URL + 'healthmonitors', json=LIST_HM_RESP, status_code=200, ) @@ -670,7 +693,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_show_health_monitor(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'healthmonitors/' + FAKE_HM, + FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, json=SINGLE_HM_RESP, status_code=200 ) @@ -680,7 +703,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_health_monitor(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'healthmonitors', + FAKE_LBAAS_URL + 'healthmonitors', json=SINGLE_HM_RESP, status_code=200 ) @@ -690,11 +713,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_create_health_monitor_error(self): self.requests_mock.register_uri( 'POST', - FAKE_URL + 'healthmonitors', + FAKE_LBAAS_URL + 'healthmonitors', text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.health_monitor_create, json=SINGLE_HM_RESP) @@ -702,7 +725,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_health_monitor(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'healthmonitors/' + FAKE_HM, + FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, json=SINGLE_HM_UPDATE, status_code=200 ) @@ -712,11 +735,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_health_monitor_error(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'healthmonitors/' + FAKE_HM, + FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.health_monitor_set, FAKE_HM, json=SINGLE_HM_UPDATE) @@ -724,7 +747,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_health_monitor(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'healthmonitors/' + FAKE_HM, + FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, status_code=200 ) ret = self.api.health_monitor_delete(FAKE_HM) @@ -733,11 +756,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_delete_health_monitor_error(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'healthmonitors/' + FAKE_HM, + FAKE_LBAAS_URL + 'healthmonitors/' + FAKE_HM, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.health_monitor_delete, FAKE_HM) @@ -745,7 +768,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_list_quota_no_options(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'quotas', + FAKE_LBAAS_URL + 'quotas', json=LIST_QT_RESP, status_code=200, ) @@ -755,7 +778,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_show_quota(self): self.requests_mock.register_uri( 'GET', - FAKE_URL + 'quotas/' + FAKE_PRJ, + FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, json=SINGLE_QT_RESP, status_code=200 ) @@ -765,7 +788,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_quota(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'quotas/' + FAKE_PRJ, + FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, json=SINGLE_QT_UPDATE, status_code=200 ) @@ -775,11 +798,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_set_quota_error(self): self.requests_mock.register_uri( 'PUT', - FAKE_URL + 'quotas/' + FAKE_PRJ, + FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.quota_set, FAKE_PRJ, json=SINGLE_QT_UPDATE) @@ -787,7 +810,7 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_reset_quota(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'quotas/' + FAKE_PRJ, + FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, status_code=200 ) ret = self.api.quota_reset(FAKE_PRJ) @@ -796,11 +819,11 @@ class TestLoadBalancer(TestLoadBalancerv2): def test_reset_quota_error(self): self.requests_mock.register_uri( 'DELETE', - FAKE_URL + 'quotas/' + FAKE_PRJ, + FAKE_LBAAS_URL + 'quotas/' + FAKE_PRJ, text='{"faultstring": "%s"}' % self._error_message, status_code=400 ) - self.assertRaisesRegex(lb.OctaviaClientException, + self.assertRaisesRegex(octavia.OctaviaClientException, self._error_message, self.api.quota_reset, FAKE_PRJ) diff --git a/octaviaclient/tests/unit/osc/v2/fakes.py b/octaviaclient/tests/unit/osc/v2/fakes.py index a2ab14d..3a77ee9 100644 --- a/octaviaclient/tests/unit/osc/v2/fakes.py +++ b/octaviaclient/tests/unit/osc/v2/fakes.py @@ -28,7 +28,7 @@ LOADBALANCER = { } -class FakeLoadBalancerv2Client(object): +class FakeOctaviaClient(object): def __init__(self, **kwargs): self.load_balancers = mock.Mock() self.load_balancers.resource_class = fakes.FakeResource(None, {}) @@ -36,11 +36,11 @@ class FakeLoadBalancerv2Client(object): self.management_url = kwargs['endpoint'] -class TestLoadBalancerv2(utils.TestCommand): +class TestOctaviaClient(utils.TestCommand): def setUp(self): - super(TestLoadBalancerv2, self).setUp() - self.app.client_manager.load_balancer = FakeLoadBalancerv2Client( + super(TestOctaviaClient, self).setUp() + self.app.client_manager.load_balancer = FakeOctaviaClient( endpoint=fakes.AUTH_URL, token=fakes.AUTH_TOKEN, ) @@ -112,7 +112,7 @@ class FakeListener(object): class FakePool(object): - """Fake one or more pool.""" + """Fake one or more pools.""" @staticmethod def create_one_pool(attrs=None): @@ -142,6 +142,7 @@ class FakePool(object): class FakeMember(object): + """Fake one or more members.""" @staticmethod def create_member(attrs=None): @@ -170,7 +171,7 @@ class FakeMember(object): class FakeL7Policy(object): - """Fake one or more L7policy.""" + """Fake one or more L7policies.""" @staticmethod def create_one_l7policy(attrs=None): @@ -199,7 +200,7 @@ class FakeL7Policy(object): class FakeL7Rule(object): - """Fake one or more L7policy.""" + """Fake one or more L7rules.""" @staticmethod def create_one_l7rule(attrs=None): @@ -229,7 +230,7 @@ class FakeL7Rule(object): class FakeHM(object): - """Fake one or more L7policy.""" + """Fake one or more health monitors.""" @staticmethod def create_one_health_monitor(attrs=None): @@ -289,3 +290,36 @@ class FakeQT(object): loaded=True) return qt + + +class FakeAmphora(object): + """Fake one or more amphorae.""" + + @staticmethod + def create_one_amphora(attrs=None): + attrs = attrs or {} + + amphora = { + "id": uuidutils.generate_uuid(dashed=True), + "loadbalancer_id": uuidutils.generate_uuid(dashed=True), + "compute_id": uuidutils.generate_uuid(dashed=True), + "lb_network_ip": "192.168.1.3", + "vrrp_ip": "192.168.1.6", + "ha_ip": "192.168.1.10", + "vrrp_port_id": uuidutils.generate_uuid(dashed=True), + "ha_port_id": uuidutils.generate_uuid(dashed=True), + "cert_expiration": "2019-09-19 00:34:51", + "cert_busy": 0, + "role": "BACKUP", + "status": "ALLOCATED", + "vrrp_interface": "eth1", + "vrrp_id": 1, + "vrrp_priority": 200, + "cached_zone": "zone2", + } + + amphora.update(attrs) + + return fakes.FakeResource( + info=copy.deepcopy(amphora), + loaded=True) diff --git a/octaviaclient/tests/unit/osc/v2/test_amphora.py b/octaviaclient/tests/unit/osc/v2/test_amphora.py new file mode 100644 index 0000000..607ba85 --- /dev/null +++ b/octaviaclient/tests/unit/osc/v2/test_amphora.py @@ -0,0 +1,175 @@ +# 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. +# + +import copy +import mock + +import osc_lib.tests.utils as osc_test_utils + +from octaviaclient.osc.v2 import amphora +from octaviaclient.osc.v2 import constants +from octaviaclient.tests.unit.osc.v2 import fakes as amp_fakes + +AUTH_TOKEN = "foobar" +AUTH_URL = "http://192.0.2.2" + + +class TestAmphora(amp_fakes.TestOctaviaClient): + + _amp = amp_fakes.FakeAmphora.create_one_amphora() + + columns = constants.AMPHORA_COLUMNS + rows = constants.AMPHORA_ROWS + + data_show = ( + ( + _amp.id, + _amp.loadbalancer_id, + _amp.compute_id, + _amp.lb_network_ip, + _amp.vrrp_ip, + _amp.ha_ip, + _amp.vrrp_port_id, + _amp.ha_port_id, + _amp.cert_expiration, + _amp.cert_busy, + _amp.role, + _amp.status, + _amp.vrrp_interface, + _amp.vrrp_id, + _amp.vrrp_priority, + _amp.cached_zone, + ), + ) + + info_show = { + 'id': _amp.id, + 'loadbalancer_id': _amp.loadbalancer_id, + 'compute_id': _amp.compute_id, + 'lb_network_ip': _amp.lb_network_ip, + 'vrrp_ip': _amp.vrrp_ip, + 'ha_ip': _amp.ha_ip, + 'vrrp_port_id': _amp.vrrp_port_id, + 'ha_port_id': _amp.ha_port_id, + 'cert_expiration': _amp.cert_expiration, + 'cert_busy': _amp.cert_busy, + 'role': _amp.role, + 'status': _amp.status, + 'vrrp_interface': _amp.vrrp_interface, + 'vrrp_id': _amp.vrrp_id, + 'vrrp_priority': _amp.vrrp_priority, + 'cached_zone': _amp.cached_zone, + } + + data_list = ( + ( + _amp.id, + _amp.loadbalancer_id, + _amp.status, + _amp.role, + _amp.lb_network_ip, + _amp.ha_ip, + ), + ) + + info_list = { + 'amphorae': + [{ + 'id': _amp.id, + 'loadbalancer_id': _amp.loadbalancer_id, + 'status': _amp.status, + 'role': _amp.role, + 'lb_network_ip': _amp.lb_network_ip, + 'ha_ip': _amp.ha_ip, + }], + } + amp_info = copy.deepcopy(info_list) + + def setUp(self): + super(TestAmphora, self).setUp() + + self.api_mock = mock.Mock() + self.api_mock.amphora_list.return_value = self.amp_info + self.api_mock.amphora_show.return_value = { + "amphora": self.amp_info['amphorae'][0], + } + lb_client = self.app.client_manager + lb_client.load_balancer = self.api_mock + + +class TestAmphoraList(TestAmphora): + + def setUp(self): + super(TestAmphoraList, self).setUp() + self.cmd = amphora.ListAmphora(self.app, None) + + def test_amphora_list_no_options(self): + arglist = [] + verify_list = [] + + parsed_args = self.check_parser(self.cmd, arglist, verify_list) + columns, data = self.cmd.take_action(parsed_args) + + self.api_mock.amphora_list.assert_called_with() + self.assertEqual(self.columns, columns) + self.assertEqual(self.data_list, tuple(data)) + + @mock.patch('octaviaclient.osc.v2.utils.get_amphora_attrs') + def test_amphora_list_with_loadbalancer(self, mock_client): + mock_client.return_value = { + 'loadbalancer_id': self._amp.loadbalancer_id, + 'compute_id': self._amp.compute_id, + 'role': self._amp.role, + 'status': self._amp.status, + } + arglist = [ + '--loadbalancer', self._amp.loadbalancer_id, + '--compute-id', self._amp.compute_id, + '--role', 'Master', + '--status', 'allocAted', + ] + verify_list = [ + ('loadbalancer', self._amp.loadbalancer_id), + ('compute_id', self._amp.compute_id), + ('role', 'MASTER'), + ('status', 'ALLOCATED'), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verify_list) + columns, data = self.cmd.take_action(parsed_args) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data_list, tuple(data)) + + +class TestAmphoraShow(TestAmphora): + + def setUp(self): + super(TestAmphoraShow, self).setUp() + self.cmd = amphora.ShowAmphora(self.app, None) + + def test_amphora_show_no_args(self): + self.assertRaises( + osc_test_utils.ParserException, + self.check_parser, self.cmd, [], [], + ) + + @mock.patch('octaviaclient.osc.v2.utils.get_amphora_attrs') + def test_amphora_show(self, mock_client): + mock_client.return_value = {'amphora_id': self._amp.id} + arglist = [self._amp.id] + verify_list = [('amphora_id', self._amp.id)] + + parsed_args = self.check_parser(self.cmd, arglist, verify_list) + rows, data = self.cmd.take_action(parsed_args) + self.assertEqual(self.rows, rows) + self.api_mock.amphora_show.assert_called_with(amphora_id=self._amp.id) diff --git a/octaviaclient/tests/unit/osc/v2/test_health_monitor.py b/octaviaclient/tests/unit/osc/v2/test_health_monitor.py index 58fed03..b885027 100644 --- a/octaviaclient/tests/unit/osc/v2/test_health_monitor.py +++ b/octaviaclient/tests/unit/osc/v2/test_health_monitor.py @@ -23,7 +23,7 @@ AUTH_TOKEN = "foobar" AUTH_URL = "http://192.0.2.2" -class TestHealthMonitor(hm_fakes.TestLoadBalancerv2): +class TestHealthMonitor(hm_fakes.TestOctaviaClient): _hm = hm_fakes.FakeHM.create_one_health_monitor() diff --git a/octaviaclient/tests/unit/osc/v2/test_l7policy.py b/octaviaclient/tests/unit/osc/v2/test_l7policy.py index 1c3e9c0..955299b 100644 --- a/octaviaclient/tests/unit/osc/v2/test_l7policy.py +++ b/octaviaclient/tests/unit/osc/v2/test_l7policy.py @@ -23,7 +23,7 @@ AUTH_TOKEN = "foobar" AUTH_URL = "http://192.0.2.2" -class TestL7Policy(po_fakes.TestLoadBalancerv2): +class TestL7Policy(po_fakes.TestOctaviaClient): _l7po = po_fakes.FakeL7Policy.create_one_l7policy() diff --git a/octaviaclient/tests/unit/osc/v2/test_l7rule.py b/octaviaclient/tests/unit/osc/v2/test_l7rule.py index 326f49d..34a59a9 100644 --- a/octaviaclient/tests/unit/osc/v2/test_l7rule.py +++ b/octaviaclient/tests/unit/osc/v2/test_l7rule.py @@ -21,7 +21,7 @@ AUTH_TOKEN = "foobar" AUTH_URL = "http://192.0.2.2" -class TestL7Policy(ru_fakes.TestLoadBalancerv2): +class TestL7Policy(ru_fakes.TestOctaviaClient): _l7ru = ru_fakes.FakeL7Rule.create_one_l7rule() _l7po = ru_fakes.FakeL7Policy.create_one_l7policy() diff --git a/octaviaclient/tests/unit/osc/v2/test_listener.py b/octaviaclient/tests/unit/osc/v2/test_listener.py index 6022563..337d65f 100644 --- a/octaviaclient/tests/unit/osc/v2/test_listener.py +++ b/octaviaclient/tests/unit/osc/v2/test_listener.py @@ -23,7 +23,7 @@ AUTH_TOKEN = "foobar" AUTH_URL = "http://192.0.2.2" -class TestListener(li_fakes.TestLoadBalancerv2): +class TestListener(li_fakes.TestOctaviaClient): _li = li_fakes.FakeListener.create_one_listener() diff --git a/octaviaclient/tests/unit/osc/v2/test_load_balancer.py b/octaviaclient/tests/unit/osc/v2/test_load_balancer.py index e9b9e09..61d55ab 100644 --- a/octaviaclient/tests/unit/osc/v2/test_load_balancer.py +++ b/octaviaclient/tests/unit/osc/v2/test_load_balancer.py @@ -24,7 +24,7 @@ AUTH_TOKEN = "foobar" AUTH_URL = "http://192.0.2.2" -class TestLoadBalancer(lb_fakes.TestLoadBalancerv2): +class TestLoadBalancer(lb_fakes.TestOctaviaClient): _lb = lb_fakes.FakeLoadBalancer.create_one_load_balancer() @@ -257,3 +257,21 @@ class TestLoadBalancerStats(TestLoadBalancer): self.cmd.take_action(parsed_args) self.api_mock.load_balancer_stats_show.assert_called_with( lb_id=self._lb.id) + + +class TestLoadBalancerFailover(TestLoadBalancer): + + def setUp(self): + super(TestLoadBalancerFailover, self).setUp() + self.cmd = load_balancer.FailoverLoadBalancer(self.app, None) + + def test_load_balancer_failover(self): + arglist = [self._lb.id] + verifylist = [ + ('loadbalancer', self._lb.id) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.load_balancer_failover.assert_called_with( + lb_id=self._lb.id) diff --git a/octaviaclient/tests/unit/osc/v2/test_member.py b/octaviaclient/tests/unit/osc/v2/test_member.py index 6699775..728ef96 100644 --- a/octaviaclient/tests/unit/osc/v2/test_member.py +++ b/octaviaclient/tests/unit/osc/v2/test_member.py @@ -17,10 +17,10 @@ import mock from octaviaclient.osc.v2 import member from octaviaclient.tests.unit.osc.v2 import fakes as mem_fakes -from osc_lib.tests.utils import ParserException +import osc_lib.tests.utils as osc_test_utils -class TestMember(mem_fakes.TestLoadBalancerv2): +class TestMember(mem_fakes.TestOctaviaClient): mem = mem_fakes.FakeMember.create_member() @@ -84,7 +84,7 @@ class TestListMember(TestMember): arglist = [] verifylist = [] - self.assertRaises(ParserException, + self.assertRaises(osc_test_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @mock.patch('octaviaclient.osc.v2.utils.get_member_attrs') diff --git a/octaviaclient/tests/unit/osc/v2/test_pool.py b/octaviaclient/tests/unit/osc/v2/test_pool.py index b10927d..eb0052f 100644 --- a/octaviaclient/tests/unit/osc/v2/test_pool.py +++ b/octaviaclient/tests/unit/osc/v2/test_pool.py @@ -23,7 +23,7 @@ AUTH_TOKEN = "foobar" AUTH_URL = "http://192.0.2.2" -class TestPool(po_fakes.TestLoadBalancerv2): +class TestPool(po_fakes.TestOctaviaClient): _po = po_fakes.FakePool.create_one_pool() diff --git a/octaviaclient/tests/unit/osc/v2/test_quota.py b/octaviaclient/tests/unit/osc/v2/test_quota.py index 503632d..fc64ec2 100644 --- a/octaviaclient/tests/unit/osc/v2/test_quota.py +++ b/octaviaclient/tests/unit/osc/v2/test_quota.py @@ -23,7 +23,7 @@ AUTH_TOKEN = "foobar" AUTH_URL = "http://192.0.2.2" -class TestQuota(qt_fakes.TestLoadBalancerv2): +class TestQuota(qt_fakes.TestOctaviaClient): _qt = qt_fakes.FakeQT.create_one_quota() diff --git a/octaviaclient/tests/utils.py b/octaviaclient/tests/utils.py index a2f2e8e..caa2a6d 100644 --- a/octaviaclient/tests/utils.py +++ b/octaviaclient/tests/utils.py @@ -19,10 +19,7 @@ import os import testtools from octaviaclient.tests import fakes - - -class ParserException(Exception): - pass +import osc_lib.tests.utils as osc_test_utils class TestCase(testtools.TestCase): @@ -65,8 +62,10 @@ class TestCommand(TestCase): cmd_parser = cmd.get_parser('check_parser') try: parsed_args = cmd_parser.parse_args(args) + except osc_test_utils.ParserException: + raise except SystemExit: - raise ParserException("Argument parse failed") + raise osc_test_utils.ParserException("Argument parse failed") for av in verify_args: attr, value = av if attr: diff --git a/releasenotes/notes/add-new-commands-and-options-d520b36d870cbcb4.yaml b/releasenotes/notes/add-new-commands-and-options-d520b36d870cbcb4.yaml new file mode 100644 index 0000000..a7cbf83 --- /dev/null +++ b/releasenotes/notes/add-new-commands-and-options-d520b36d870cbcb4.yaml @@ -0,0 +1,5 @@ +--- +features: + - Loadbalancer failover command, which allows to trigger failover protocol. + - Amphora commands, to query amphorae by ID or by loadbalancer ID, etc. + - Filter 'list' calls by loadbalancer ID, for both listeners and pools. diff --git a/setup.cfg b/setup.cfg index 582c153..aac6d02 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,6 +33,7 @@ openstack.load_balancer.v2 = loadbalancer_delete = octaviaclient.osc.v2.load_balancer:DeleteLoadBalancer loadbalancer_set = octaviaclient.osc.v2.load_balancer:SetLoadBalancer loadbalancer_stats_show = octaviaclient.osc.v2.load_balancer:ShowLoadBalancerStats + loadbalancer_failover = octaviaclient.osc.v2.load_balancer:FailoverLoadBalancer loadbalancer_listener_create = octaviaclient.osc.v2.listener:CreateListener loadbalancer_listener_list = octaviaclient.osc.v2.listener:ListListener loadbalancer_listener_show = octaviaclient.osc.v2.listener:ShowListener @@ -68,6 +69,8 @@ openstack.load_balancer.v2 = loadbalancer_quota_defaults_show = octaviaclient.osc.v2.quota:ShowQuotaDefaults loadbalancer_quota_reset = octaviaclient.osc.v2.quota:ResetQuota loadbalancer_quota_set = octaviaclient.osc.v2.quota:SetQuota + loadbalancer_amphora_list = octaviaclient.osc.v2.amphora:ListAmphora + loadbalancer_amphora_show = octaviaclient.osc.v2.amphora:ShowAmphora [build_sphinx] source-dir = doc/source