Merge "Allow creating/showing LBs with Additional VIPs"
This commit is contained in:
commit
03083c3dab
@ -33,6 +33,7 @@ LOAD_BALANCER_ROWS = (
|
|||||||
'vip_qos_policy_id',
|
'vip_qos_policy_id',
|
||||||
'vip_subnet_id',
|
'vip_subnet_id',
|
||||||
'tags',
|
'tags',
|
||||||
|
'additional_vips',
|
||||||
)
|
)
|
||||||
|
|
||||||
LOAD_BALANCER_COLUMNS = (
|
LOAD_BALANCER_COLUMNS = (
|
||||||
|
@ -89,6 +89,13 @@ class CreateLoadBalancer(command.ShowOne):
|
|||||||
metavar='<vip_qos_policy_id>',
|
metavar='<vip_qos_policy_id>',
|
||||||
help="Set QoS policy ID for VIP port. Unset with 'None'.",
|
help="Set QoS policy ID for VIP port. Unset with 'None'.",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--additional-vip',
|
||||||
|
metavar='subnet-id=<name-or-uuid>[,ip-address=<ip>]',
|
||||||
|
action='append',
|
||||||
|
help="Expose an additional VIP on the load balancer. This "
|
||||||
|
"parameter can be provided more than once."
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--project',
|
'--project',
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
import munch
|
import munch
|
||||||
from openstackclient.identity import common as identity_common
|
from openstackclient.identity import common as identity_common
|
||||||
from osc_lib import exceptions as osc_exc
|
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)
|
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):
|
def get_loadbalancer_attrs(client_manager, parsed_args):
|
||||||
attr_map = {
|
attr_map = {
|
||||||
'name': ('name', str),
|
'name': ('name', str),
|
||||||
@ -231,6 +265,11 @@ def get_loadbalancer_attrs(client_manager, parsed_args):
|
|||||||
client_manager.load_balancer.flavor_list
|
client_manager.load_balancer.flavor_list
|
||||||
),
|
),
|
||||||
'availability_zone': ('availability_zone', str),
|
'availability_zone': ('availability_zone', str),
|
||||||
|
'additional_vip': (
|
||||||
|
'additional_vips',
|
||||||
|
functools.partial(
|
||||||
|
handle_additional_vips, client_manager=client_manager)
|
||||||
|
),
|
||||||
}
|
}
|
||||||
add_tags_attr_map(attr_map)
|
add_tags_attr_map(attr_map)
|
||||||
|
|
||||||
|
@ -97,6 +97,13 @@ LOADBALANCER_ATTRS = {
|
|||||||
"operating_status": "ONLINE",
|
"operating_status": "ONLINE",
|
||||||
"provider": "octavia",
|
"provider": "octavia",
|
||||||
"flavor_id": uuidutils.generate_uuid(dashed=True),
|
"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"]
|
"tags": ["foo", "bar"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +398,39 @@ class TestLoadBalancerCreate(TestLoadBalancer):
|
|||||||
self.api_mock.load_balancer_create.assert_called_with(
|
self.api_mock.load_balancer_create.assert_called_with(
|
||||||
json={'loadbalancer': lb_info})
|
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')
|
@mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs')
|
||||||
def test_load_balancer_create_with_provider(self, mock_client):
|
def test_load_balancer_create_with_provider(self, mock_client):
|
||||||
provider = 'foobar'
|
provider = 'foobar'
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
It is now possible to create a loadbalancer with more than one VIP by
|
||||||
|
passing ``--additional-vip subnet-id=<name-or-uuid>[,ip-address=<ip>]`` to
|
||||||
|
the create command.
|
||||||
|
Additional VIPs will also appear in the ``show`` details of a loadbalancer.
|
Loading…
Reference in New Issue
Block a user