LBaaS updates to reflect shared pools feature
These updates allow the CLI user to fully take advantage of the shared pools functionality being added to Neutron LBaaS in preparation for L7 switching functionality. The Neutron LBaaS patch is here: https://review.openstack.org/#/c/218560/ Partially-Implements: blueprint lbaas-l7-rules Change-Id: Ib72d743ff0d6ca7f0fde034a8c73029308ca01a1
This commit is contained in:

committed by
Stephen Balukoff

parent
82ec2abb22
commit
c422c2610e
@@ -16,18 +16,27 @@
|
||||
#
|
||||
|
||||
from neutronclient._i18n import _
|
||||
from neutronclient.common import exceptions
|
||||
from neutronclient.common import utils
|
||||
from neutronclient.neutron import v2_0 as neutronV20
|
||||
|
||||
|
||||
def _get_loadbalancer_id(client, lb_id_or_name):
|
||||
return neutronV20.find_resourceid_by_name_or_id(
|
||||
client,
|
||||
'loadbalancer',
|
||||
lb_id_or_name,
|
||||
client, 'loadbalancer', lb_id_or_name,
|
||||
cmd_resource='lbaas_loadbalancer')
|
||||
|
||||
|
||||
def _get_pool(client, pool_id_or_name):
|
||||
return neutronV20.find_resource_by_name_or_id(
|
||||
client, 'pool', pool_id_or_name, cmd_resource='lbaas_pool')
|
||||
|
||||
|
||||
def _get_pool_id(client, pool_id_or_name):
|
||||
return neutronV20.find_resourceid_by_name_or_id(
|
||||
client, 'pool', pool_id_or_name, cmd_resource='lbaas_pool')
|
||||
|
||||
|
||||
class ListListener(neutronV20.ListCommand):
|
||||
"""LBaaS v2 List listeners that belong to a given tenant."""
|
||||
|
||||
@@ -64,7 +73,8 @@ class CreateListener(neutronV20.CreateCommand):
|
||||
help=_('Description of the listener.'))
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
help=_('The name of the listener.'))
|
||||
help=_('The name of the listener. At least one of --default-pool '
|
||||
'or --loadbalancer must be specified.'))
|
||||
parser.add_argument(
|
||||
'--default-tls-container-ref',
|
||||
dest='default_tls_container_ref',
|
||||
@@ -75,9 +85,11 @@ class CreateListener(neutronV20.CreateCommand):
|
||||
dest='sni_container_refs',
|
||||
nargs='+',
|
||||
help=_('List of TLS container references for SNI.'))
|
||||
parser.add_argument(
|
||||
'--default-pool',
|
||||
help=_('Default pool for the listener.'))
|
||||
parser.add_argument(
|
||||
'--loadbalancer',
|
||||
required=True,
|
||||
metavar='LOADBALANCER',
|
||||
help=_('ID or name of the load balancer.'))
|
||||
parser.add_argument(
|
||||
@@ -93,22 +105,29 @@ class CreateListener(neutronV20.CreateCommand):
|
||||
help=_('Protocol port for the listener.'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
resource = {
|
||||
'protocol': parsed_args.protocol,
|
||||
'protocol_port': parsed_args.protocol_port,
|
||||
'admin_state_up': parsed_args.admin_state
|
||||
}
|
||||
if not parsed_args.loadbalancer and not parsed_args.default_pool:
|
||||
message = _('Either --default-pool or --loadbalancer must be '
|
||||
'specified.')
|
||||
raise exceptions.CommandError(message)
|
||||
if parsed_args.loadbalancer:
|
||||
parsed_args.loadbalancer = _get_loadbalancer_id(
|
||||
self.get_client(),
|
||||
parsed_args.loadbalancer)
|
||||
body = {'loadbalancer_id': parsed_args.loadbalancer,
|
||||
'protocol': parsed_args.protocol,
|
||||
'protocol_port': parsed_args.protocol_port,
|
||||
'admin_state_up': parsed_args.admin_state}
|
||||
loadbalancer_id = _get_loadbalancer_id(
|
||||
self.get_client(), parsed_args.loadbalancer)
|
||||
resource['loadbalancer_id'] = loadbalancer_id
|
||||
if parsed_args.default_pool:
|
||||
default_pool_id = _get_pool_id(
|
||||
self.get_client(), parsed_args.default_pool)
|
||||
resource['default_pool_id'] = default_pool_id
|
||||
|
||||
neutronV20.update_dict(parsed_args, body,
|
||||
neutronV20.update_dict(parsed_args, resource,
|
||||
['connection_limit', 'description',
|
||||
'loadbalancer_id', 'name',
|
||||
'default_tls_container_ref',
|
||||
'sni_container_refs',
|
||||
'tenant_id'])
|
||||
return {self.resource: body}
|
||||
'name', 'default_tls_container_ref',
|
||||
'sni_container_refs', 'tenant_id'])
|
||||
return {self.resource: resource}
|
||||
|
||||
|
||||
class UpdateListener(neutronV20.UpdateCommand):
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# Copyright 2013 Mirantis Inc.
|
||||
# Copyright 2014 Blue Box Group, Inc.
|
||||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
# Copyright 2015 Blue Box, an IBM Company
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@@ -17,10 +18,27 @@
|
||||
#
|
||||
|
||||
from neutronclient._i18n import _
|
||||
from neutronclient.common import exceptions
|
||||
from neutronclient.common import utils
|
||||
from neutronclient.neutron import v2_0 as neutronV20
|
||||
|
||||
|
||||
def _get_loadbalancer_id(client, lb_id_or_name):
|
||||
return neutronV20.find_resourceid_by_name_or_id(
|
||||
client, 'loadbalancer', lb_id_or_name,
|
||||
cmd_resource='lbaas_loadbalancer')
|
||||
|
||||
|
||||
def _get_listener(client, listener_id_or_name):
|
||||
return neutronV20.find_resource_by_name_or_id(
|
||||
client, 'listener', listener_id_or_name)
|
||||
|
||||
|
||||
def _get_listener_id(client, listener_id_or_name):
|
||||
return neutronV20.find_resourceid_by_name_or_id(
|
||||
client, 'listener', listener_id_or_name)
|
||||
|
||||
|
||||
class ListPool(neutronV20.ListCommand):
|
||||
"""LBaaS v2 List pools that belong to a given tenant."""
|
||||
|
||||
@@ -70,16 +88,22 @@ class CreatePool(neutronV20.CreateCommand):
|
||||
'cookie name'))
|
||||
parser.add_argument(
|
||||
'--name', help=_('The name of the pool.'))
|
||||
parser.add_argument(
|
||||
'--listener',
|
||||
help=_('Listener whose default-pool should be set to this pool. '
|
||||
'At least one of --listener or --loadbalancer must be '
|
||||
'specified.'))
|
||||
parser.add_argument(
|
||||
'--loadbalancer',
|
||||
help=_('Loadbalancer with which this pool should be associated. '
|
||||
'At least one of --listener or --loadbalancer must be '
|
||||
'specified.'))
|
||||
parser.add_argument(
|
||||
'--lb-algorithm',
|
||||
required=True,
|
||||
choices=['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP'],
|
||||
help=_('The algorithm used to distribute load between the members '
|
||||
'of the pool.'))
|
||||
parser.add_argument(
|
||||
'--listener',
|
||||
required=True,
|
||||
help=_('The listener to associate with the pool'))
|
||||
parser.add_argument(
|
||||
'--protocol',
|
||||
required=True,
|
||||
@@ -88,16 +112,29 @@ class CreatePool(neutronV20.CreateCommand):
|
||||
help=_('Protocol for balancing.'))
|
||||
|
||||
def args2body(self, parsed_args):
|
||||
_listener_id = neutronV20.find_resourceid_by_name_or_id(
|
||||
self.get_client(), 'listener', parsed_args.listener)
|
||||
body = {'admin_state_up': parsed_args.admin_state,
|
||||
'protocol': parsed_args.protocol,
|
||||
'lb_algorithm': parsed_args.lb_algorithm,
|
||||
'listener_id': _listener_id}
|
||||
neutronV20.update_dict(parsed_args, body,
|
||||
resource = {
|
||||
'admin_state_up': parsed_args.admin_state,
|
||||
'protocol': parsed_args.protocol,
|
||||
'lb_algorithm': parsed_args.lb_algorithm
|
||||
}
|
||||
if not parsed_args.listener and not parsed_args.loadbalancer:
|
||||
message = _('At least one of --listener or --loadbalancer must be '
|
||||
'specified.')
|
||||
raise exceptions.CommandError(message)
|
||||
if parsed_args.listener:
|
||||
listener_id = _get_listener_id(
|
||||
self.get_client(),
|
||||
parsed_args.listener)
|
||||
resource['listener_id'] = listener_id
|
||||
if parsed_args.loadbalancer:
|
||||
loadbalancer_id = _get_loadbalancer_id(
|
||||
self.get_client(),
|
||||
parsed_args.loadbalancer)
|
||||
resource['loadbalancer_id'] = loadbalancer_id
|
||||
neutronV20.update_dict(parsed_args, resource,
|
||||
['description', 'name',
|
||||
'session_persistence', 'tenant_id'])
|
||||
return {self.resource: body}
|
||||
return {self.resource: resource}
|
||||
|
||||
|
||||
class UpdatePool(neutronV20.UpdateCommand):
|
||||
|
@@ -16,14 +16,15 @@
|
||||
|
||||
import sys
|
||||
|
||||
from neutronclient.common import exceptions
|
||||
from neutronclient.neutron.v2_0.lb.v2 import listener
|
||||
from neutronclient.tests.unit import test_cli20
|
||||
|
||||
|
||||
class CLITestV20LbListenerJSON(test_cli20.CLITestV20Base):
|
||||
|
||||
def test_create_listener_with_mandatory_params(self):
|
||||
# lbaas-listener-create with mandatory params only.
|
||||
def test_create_listener_with_loadbalancer(self):
|
||||
# lbaas-listener-create with --loadbalancer
|
||||
resource = 'listener'
|
||||
cmd_resource = 'lbaas_listener'
|
||||
cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None)
|
||||
@@ -40,6 +41,41 @@ class CLITestV20LbListenerJSON(test_cli20.CLITestV20Base):
|
||||
position_names, position_values,
|
||||
cmd_resource=cmd_resource)
|
||||
|
||||
def test_create_listener_with_default_pool(self):
|
||||
# lbaas-listener-create with --default-pool and no --loadbalancer.
|
||||
resource = 'listener'
|
||||
cmd_resource = 'lbaas_listener'
|
||||
cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
default_pool_id = 'default-pool'
|
||||
protocol = 'TCP'
|
||||
protocol_port = '80'
|
||||
args = ['--protocol', protocol, '--protocol-port', protocol_port,
|
||||
'--default-pool', default_pool_id]
|
||||
position_names = ['protocol', 'protocol_port', 'default_pool_id']
|
||||
position_values = [protocol, protocol_port, default_pool_id,
|
||||
True]
|
||||
self._test_create_resource(resource, cmd, '', my_id, args,
|
||||
position_names, position_values,
|
||||
cmd_resource=cmd_resource)
|
||||
|
||||
def test_create_listener_with_no_loadbalancer_or_default_pool(self):
|
||||
# lbaas-listener-create without --default-pool or --loadbalancer.
|
||||
resource = 'listener'
|
||||
cmd_resource = 'lbaas_listener'
|
||||
cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
protocol = 'TCP'
|
||||
protocol_port = '80'
|
||||
args = ['--protocol', protocol, '--protocol-port', protocol_port]
|
||||
position_names = ['protocol', 'protocol_port']
|
||||
position_values = [protocol, protocol_port, True]
|
||||
self._test_create_resource(resource, cmd, '', my_id, args,
|
||||
position_names, position_values,
|
||||
cmd_resource=cmd_resource,
|
||||
no_api_call=True,
|
||||
expected_exception=exceptions.CommandError)
|
||||
|
||||
def test_create_listener_with_all_params(self):
|
||||
# lbaas-listener-create with all params set.
|
||||
resource = 'listener'
|
||||
@@ -47,6 +83,7 @@ class CLITestV20LbListenerJSON(test_cli20.CLITestV20Base):
|
||||
cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
loadbalancer = 'loadbalancer'
|
||||
default_pool_id = 'default-pool'
|
||||
protocol = 'TCP'
|
||||
protocol_port = '80'
|
||||
connection_limit = 10
|
||||
@@ -54,14 +91,17 @@ class CLITestV20LbListenerJSON(test_cli20.CLITestV20Base):
|
||||
args = ['--admin-state-down',
|
||||
'--protocol', protocol, '--protocol-port', protocol_port,
|
||||
'--loadbalancer', loadbalancer,
|
||||
'--default-pool', default_pool_id,
|
||||
'--default-tls-container-ref', def_tls_cont_ref,
|
||||
'--sni-container-refs', '1111', '2222', '3333',
|
||||
'--connection-limit', '10']
|
||||
position_names = ['admin_state_up',
|
||||
'protocol', 'protocol_port', 'loadbalancer_id',
|
||||
'default_pool_id',
|
||||
'default_tls_container_ref', 'sni_container_refs',
|
||||
'connection_limit']
|
||||
position_values = [False, protocol, protocol_port, loadbalancer,
|
||||
default_pool_id,
|
||||
def_tls_cont_ref, ['1111', '2222', '3333'],
|
||||
connection_limit]
|
||||
self._test_create_resource(resource, cmd, '', my_id, args,
|
||||
|
@@ -16,14 +16,15 @@
|
||||
|
||||
import sys
|
||||
|
||||
from neutronclient.common import exceptions
|
||||
from neutronclient.neutron.v2_0.lb.v2 import pool
|
||||
from neutronclient.tests.unit import test_cli20
|
||||
|
||||
|
||||
class CLITestV20LbPoolJSON(test_cli20.CLITestV20Base):
|
||||
|
||||
def test_create_pool_with_mandatory_params(self):
|
||||
# lbaas-pool-create with mandatory params only.
|
||||
def test_create_pool_with_listener(self):
|
||||
# lbaas-pool-create with listener
|
||||
resource = 'pool'
|
||||
cmd_resource = 'lbaas_pool'
|
||||
cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None)
|
||||
@@ -40,6 +41,41 @@ class CLITestV20LbPoolJSON(test_cli20.CLITestV20Base):
|
||||
position_names, position_values,
|
||||
cmd_resource=cmd_resource)
|
||||
|
||||
def test_create_pool_with_loadbalancer_no_listener(self):
|
||||
"""lbaas-pool-create with loadbalancer, no listener."""
|
||||
resource = 'pool'
|
||||
cmd_resource = 'lbaas_pool'
|
||||
cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
lb_algorithm = 'ROUND_ROBIN'
|
||||
loadbalancer = 'loadbalancer'
|
||||
protocol = 'TCP'
|
||||
args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol,
|
||||
'--loadbalancer', loadbalancer]
|
||||
position_names = ['admin_state_up', 'lb_algorithm', 'protocol',
|
||||
'loadbalancer_id']
|
||||
position_values = [True, lb_algorithm, protocol, loadbalancer]
|
||||
self._test_create_resource(resource, cmd, '', my_id, args,
|
||||
position_names, position_values,
|
||||
cmd_resource=cmd_resource)
|
||||
|
||||
def test_create_pool_with_no_listener_or_loadbalancer(self):
|
||||
"""lbaas-pool-create with no listener or loadbalancer."""
|
||||
resource = 'pool'
|
||||
cmd_resource = 'lbaas_pool'
|
||||
cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None)
|
||||
my_id = 'my-id'
|
||||
lb_algorithm = 'ROUND_ROBIN'
|
||||
protocol = 'TCP'
|
||||
args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol]
|
||||
position_names = ['admin_state_up', 'lb_algorithm', 'protocol']
|
||||
position_values = [True, lb_algorithm, protocol]
|
||||
self._test_create_resource(resource, cmd, '', my_id, args,
|
||||
position_names, position_values,
|
||||
cmd_resource=cmd_resource,
|
||||
no_api_call=True,
|
||||
expected_exception=exceptions.CommandError)
|
||||
|
||||
def test_create_pool_with_all_params(self):
|
||||
# lbaas-pool-create with all params set.
|
||||
resource = 'pool'
|
||||
@@ -48,6 +84,7 @@ class CLITestV20LbPoolJSON(test_cli20.CLITestV20Base):
|
||||
my_id = 'my-id'
|
||||
lb_algorithm = 'ROUND_ROBIN'
|
||||
listener = 'listener'
|
||||
loadbalancer = 'loadbalancer'
|
||||
protocol = 'TCP'
|
||||
description = 'description'
|
||||
session_persistence_str = 'type=APP_COOKIE,cookie_name=1234'
|
||||
@@ -57,12 +94,13 @@ class CLITestV20LbPoolJSON(test_cli20.CLITestV20Base):
|
||||
args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol,
|
||||
'--description', description, '--session-persistence',
|
||||
session_persistence_str, '--admin-state-down', '--name', name,
|
||||
'--listener', listener]
|
||||
'--listener', listener, '--loadbalancer', loadbalancer]
|
||||
position_names = ['lb_algorithm', 'protocol', 'description',
|
||||
'session_persistence', 'admin_state_up', 'name',
|
||||
'listener_id']
|
||||
'listener_id', 'loadbalancer_id']
|
||||
position_values = [lb_algorithm, protocol, description,
|
||||
session_persistence, False, name, listener]
|
||||
session_persistence, False, name, listener,
|
||||
loadbalancer]
|
||||
self._test_create_resource(resource, cmd, '', my_id, args,
|
||||
position_names, position_values,
|
||||
cmd_resource=cmd_resource)
|
||||
|
@@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
CLI support for Neutron-LBaaS v2 shared pools added.
|
||||
|
||||
* Pools can be created independently from listeners.
|
||||
* Listeners can share the same default_pool.
|
||||
* Makes Layer 7 switching support much more useful.
|
Reference in New Issue
Block a user