From 3b53c1b8e18aaff41a6be31699ca9d2176c43790 Mon Sep 17 00:00:00 2001 From: Adam Harwell Date: Mon, 10 Jun 2019 18:20:19 -0700 Subject: [PATCH] Allow creating/showing LBs with Additional VIPs Story: 2005608 Task: 30845 Depends-On: https://review.opendev.org/660239 Change-Id: Iabb79df54c5bac5720f2d38d0c812e2ee4b189e8 --- octaviaclient/osc/v2/constants.py | 1 + octaviaclient/osc/v2/load_balancer.py | 7 ++++ octaviaclient/osc/v2/utils.py | 39 +++++++++++++++++++ octaviaclient/tests/unit/osc/v2/constants.py | 7 ++++ .../tests/unit/osc/v2/test_load_balancer.py | 33 ++++++++++++++++ ...port-additional-vips-cd0164f1838ee676.yaml | 7 ++++ 6 files changed, 94 insertions(+) create mode 100644 releasenotes/notes/support-additional-vips-cd0164f1838ee676.yaml diff --git a/octaviaclient/osc/v2/constants.py b/octaviaclient/osc/v2/constants.py index 7dda5ae..46b99ca 100644 --- a/octaviaclient/osc/v2/constants.py +++ b/octaviaclient/osc/v2/constants.py @@ -33,6 +33,7 @@ LOAD_BALANCER_ROWS = ( 'vip_qos_policy_id', 'vip_subnet_id', 'tags', + 'additional_vips', ) LOAD_BALANCER_COLUMNS = ( diff --git a/octaviaclient/osc/v2/load_balancer.py b/octaviaclient/osc/v2/load_balancer.py index aa69166..9308c30 100644 --- a/octaviaclient/osc/v2/load_balancer.py +++ b/octaviaclient/osc/v2/load_balancer.py @@ -89,6 +89,13 @@ class CreateLoadBalancer(command.ShowOne): metavar='', help="Set QoS policy ID for VIP port. Unset with 'None'.", ) + parser.add_argument( + '--additional-vip', + metavar='subnet-id=[,ip-address=]', + action='append', + help="Expose an additional VIP on the load balancer. This " + "parameter can be provided more than once." + ) parser.add_argument( '--project', diff --git a/octaviaclient/osc/v2/utils.py b/octaviaclient/osc/v2/utils.py index 2809722..45d9e38 100644 --- a/octaviaclient/osc/v2/utils.py +++ b/octaviaclient/osc/v2/utils.py @@ -12,6 +12,9 @@ # under the License. # +import functools +import ipaddress + import munch from openstackclient.identity import common as identity_common from osc_lib import exceptions as osc_exc @@ -181,6 +184,37 @@ def add_tags_attr_map(attr_map): attr_map.update(tags_attr_map) +def validate_vip_dict(vip_dict, client_manager): + # We have validation in two places -- _map_attrs checks sub-resources, and + # later _check_attrs does further api-specific validation. We need both for + # additional vips, so we may as well just do both here while we're at it. + if 'subnet_id' not in vip_dict: + raise osc_exc.CommandError( + 'Additional VIPs must include a subnet-id.') + subnet_id = get_resource_id(client_manager.neutronclient.list_subnets, + 'subnets', vip_dict['subnet_id']) + vip_dict['subnet_id'] = subnet_id + if 'ip_address' in vip_dict: + try: + ipaddress.ip_address(vip_dict['ip_address']) + except ValueError as e: + raise osc_exc.CommandError(str(e)) + + +def handle_additional_vips(vips, client_manager): + additional_vips = [] + for vip in vips: + vip_dict = {} + parts = vip.split(',') + for part in parts: + k, v = part.split('=') + vip_dict[k.replace('-', '_')] = v + validate_vip_dict(vip_dict, client_manager) + additional_vips.append(vip_dict) + + return additional_vips + + def get_loadbalancer_attrs(client_manager, parsed_args): attr_map = { 'name': ('name', str), @@ -231,6 +265,11 @@ def get_loadbalancer_attrs(client_manager, parsed_args): client_manager.load_balancer.flavor_list ), 'availability_zone': ('availability_zone', str), + 'additional_vip': ( + 'additional_vips', + functools.partial( + handle_additional_vips, client_manager=client_manager) + ), } add_tags_attr_map(attr_map) diff --git a/octaviaclient/tests/unit/osc/v2/constants.py b/octaviaclient/tests/unit/osc/v2/constants.py index 5d68375..39fcfaf 100644 --- a/octaviaclient/tests/unit/osc/v2/constants.py +++ b/octaviaclient/tests/unit/osc/v2/constants.py @@ -97,6 +97,13 @@ LOADBALANCER_ATTRS = { "operating_status": "ONLINE", "provider": "octavia", "flavor_id": uuidutils.generate_uuid(dashed=True), + "additional_vips": [{ + "subnet_id": uuidutils.generate_uuid(dashed=True), + "ip_address": "192.0.2.156" + }, { + "subnet_id": uuidutils.generate_uuid(dashed=True), + "ip_address": "192.0.2.179" + }], "tags": ["foo", "bar"] } diff --git a/octaviaclient/tests/unit/osc/v2/test_load_balancer.py b/octaviaclient/tests/unit/osc/v2/test_load_balancer.py index 7687a43..4008b37 100644 --- a/octaviaclient/tests/unit/osc/v2/test_load_balancer.py +++ b/octaviaclient/tests/unit/osc/v2/test_load_balancer.py @@ -398,6 +398,39 @@ class TestLoadBalancerCreate(TestLoadBalancer): self.api_mock.load_balancer_create.assert_called_with( json={'loadbalancer': lb_info}) + @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') + def test_load_balancer_create_with_additional_vips(self, mock_client): + mock_client.return_value = self.lb_info + + arglist = [ + '--name', self._lb.name, + '--vip-subnet-id', self._lb.vip_subnet_id, + '--project', self._lb.project_id, + '--additional-vip', 'subnet-id={},ip-address={}'.format( + self._lb.additional_vips[0]['subnet_id'], + self._lb.additional_vips[0]['ip_address']), + '--additional-vip', 'subnet-id={},ip-address={}'.format( + self._lb.additional_vips[1]['subnet_id'], + self._lb.additional_vips[1]['ip_address']) + ] + verifylist = [ + ('name', self._lb.name), + ('vip_subnet_id', self._lb.vip_subnet_id), + ('project', self._lb.project_id), + ('additional_vip', [ + 'subnet-id={},ip-address={}'.format( + self._lb.additional_vips[0]['subnet_id'], + self._lb.additional_vips[0]['ip_address']), + 'subnet-id={},ip-address={}'.format( + self._lb.additional_vips[1]['subnet_id'], + self._lb.additional_vips[1]['ip_address'])]) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.load_balancer_create.assert_called_with( + json={'loadbalancer': self.lb_info}) + @mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs') def test_load_balancer_create_with_provider(self, mock_client): provider = 'foobar' diff --git a/releasenotes/notes/support-additional-vips-cd0164f1838ee676.yaml b/releasenotes/notes/support-additional-vips-cd0164f1838ee676.yaml new file mode 100644 index 0000000..c9be434 --- /dev/null +++ b/releasenotes/notes/support-additional-vips-cd0164f1838ee676.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + It is now possible to create a loadbalancer with more than one VIP by + passing ``--additional-vip subnet-id=[,ip-address=]`` to + the create command. + Additional VIPs will also appear in the ``show`` details of a loadbalancer.