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:
Stephen Balukoff
2015-08-29 02:52:41 -07:00
committed by Stephen Balukoff
parent 82ec2abb22
commit c422c2610e
5 changed files with 179 additions and 37 deletions

View File

@@ -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):

View File

@@ -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):

View File

@@ -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,

View File

@@ -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)

View File

@@ -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.