Merge "Add --address-scope option "subnet pool create/set""
This commit is contained in:
commit
1819edf733
doc/source/command-objects
openstackclient
@ -18,6 +18,7 @@ Create subnet pool
|
||||
[--min-prefix-length <min-prefix-length>]
|
||||
[--max-prefix-length <max-prefix-length>]
|
||||
[--project <project> [--project-domain <project-domain>]]
|
||||
[--address-scope <address-scope>]
|
||||
<name>
|
||||
|
||||
.. option:: --pool-prefix <pool-prefix>
|
||||
@ -46,6 +47,11 @@ Create subnet pool
|
||||
Domain the project belongs to (name or ID). This can be used in case
|
||||
collisions between project names exist.
|
||||
|
||||
.. option:: --address-scope <address-scope>
|
||||
|
||||
Set address scope associated with the subnet pool (name or ID).
|
||||
Prefixes must be unique across address scopes.
|
||||
|
||||
.. _subnet_pool_create-name:
|
||||
.. describe:: <name>
|
||||
|
||||
@ -96,6 +102,7 @@ Set subnet pool properties
|
||||
[--default-prefix-length <default-prefix-length>]
|
||||
[--min-prefix-length <min-prefix-length>]
|
||||
[--max-prefix-length <max-prefix-length>]
|
||||
[--address-scope <address-scope> | --no-address-scope]
|
||||
<subnet-pool>
|
||||
|
||||
.. option:: --name <name>
|
||||
@ -119,6 +126,15 @@ Set subnet pool properties
|
||||
|
||||
Set subnet pool maximum prefix length
|
||||
|
||||
.. option:: --address-scope <address-scope>
|
||||
|
||||
Set address scope associated with the subnet pool (name or ID).
|
||||
Prefixes must be unique across address scopes.
|
||||
|
||||
.. option:: --no-address-scope
|
||||
|
||||
Remove address scope associated with the subnet pool
|
||||
|
||||
.. _subnet_pool_set-subnet-pool:
|
||||
.. describe:: <subnet-pool>
|
||||
|
||||
|
@ -35,6 +35,8 @@ _formatters = {
|
||||
|
||||
def _get_attrs(client_manager, parsed_args):
|
||||
attrs = {}
|
||||
network_client = client_manager.network
|
||||
|
||||
if parsed_args.name is not None:
|
||||
attrs['name'] = str(parsed_args.name)
|
||||
if parsed_args.prefixes is not None:
|
||||
@ -46,6 +48,12 @@ def _get_attrs(client_manager, parsed_args):
|
||||
if parsed_args.max_prefix_length is not None:
|
||||
attrs['max_prefixlen'] = parsed_args.max_prefix_length
|
||||
|
||||
if parsed_args.address_scope is not None:
|
||||
attrs['address_scope_id'] = network_client.find_address_scope(
|
||||
parsed_args.address_scope, ignore_missing=False).id
|
||||
if 'no_address_scope' in parsed_args and parsed_args.no_address_scope:
|
||||
attrs['address_scope_id'] = None
|
||||
|
||||
# "subnet pool set" command doesn't support setting project.
|
||||
if 'project' in parsed_args and parsed_args.project is not None:
|
||||
identity_client = client_manager.identity
|
||||
@ -105,7 +113,13 @@ class CreateSubnetPool(command.ShowOne):
|
||||
help="Owner's project (name or ID)",
|
||||
)
|
||||
identity_common.add_project_domain_option_to_parser(parser)
|
||||
|
||||
parser.add_argument(
|
||||
'--address-scope',
|
||||
metavar='<address-scope>',
|
||||
help="Set address scope associated with the subnet pool "
|
||||
"(name or ID). Prefixes must be unique across address "
|
||||
"scopes.",
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
@ -204,7 +218,19 @@ class SetSubnetPool(command.Command):
|
||||
help='Set subnet pool name',
|
||||
)
|
||||
_add_prefix_options(parser)
|
||||
|
||||
address_scope_group = parser.add_mutually_exclusive_group()
|
||||
address_scope_group.add_argument(
|
||||
'--address-scope',
|
||||
metavar='<address-scope>',
|
||||
help="Set address scope associated with the subnet pool "
|
||||
"(name or ID). Prefixes must be unique across address "
|
||||
"scopes.",
|
||||
)
|
||||
address_scope_group.add_argument(
|
||||
'--no-address-scope',
|
||||
action='store_true',
|
||||
help="Remove address scope associated with the subnet pool",
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
|
@ -71,6 +71,43 @@ class TestNetworkV2(utils.TestCommand):
|
||||
)
|
||||
|
||||
|
||||
class FakeAddressScope(object):
|
||||
"""Fake one or more address scopes."""
|
||||
|
||||
@staticmethod
|
||||
def create_one_address_scope(attrs=None):
|
||||
"""Create a fake address scope.
|
||||
|
||||
:param Dictionary attrs:
|
||||
A dictionary with all attributes
|
||||
:return:
|
||||
A FakeResource object with name, id, etc.
|
||||
"""
|
||||
if attrs is None:
|
||||
attrs = {}
|
||||
|
||||
# Set default attributes.
|
||||
address_scope_attrs = {
|
||||
'name': 'address-scope-name-' + uuid.uuid4().hex,
|
||||
'id': 'address-scope-id-' + uuid.uuid4().hex,
|
||||
'tenant_id': 'project-id-' + uuid.uuid4().hex,
|
||||
'shared': False,
|
||||
'ip_version': 4,
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
address_scope_attrs.update(attrs)
|
||||
|
||||
address_scope = fakes.FakeResource(
|
||||
info=copy.deepcopy(address_scope_attrs),
|
||||
loaded=True)
|
||||
|
||||
# Set attributes with special mapping in OpenStack SDK.
|
||||
address_scope.project_id = address_scope_attrs['tenant_id']
|
||||
|
||||
return address_scope
|
||||
|
||||
|
||||
class FakeAvailabilityZone(object):
|
||||
"""Fake one or more network availability zones (AZs)."""
|
||||
|
||||
|
@ -38,6 +38,8 @@ class TestCreateSubnetPool(TestSubnetPool):
|
||||
# The new subnet pool to create.
|
||||
_subnet_pool = network_fakes.FakeSubnetPool.create_one_subnet_pool()
|
||||
|
||||
_address_scope = network_fakes.FakeAddressScope.create_one_address_scope()
|
||||
|
||||
columns = (
|
||||
'address_scope_id',
|
||||
'default_prefixlen',
|
||||
@ -76,6 +78,9 @@ class TestCreateSubnetPool(TestSubnetPool):
|
||||
# Get the command object to test
|
||||
self.cmd = subnet_pool.CreateSubnetPool(self.app, self.namespace)
|
||||
|
||||
self.network.find_address_scope = mock.Mock(
|
||||
return_value=self._address_scope)
|
||||
|
||||
# Set identity client. And get a shortcut to Identity client.
|
||||
identity_client = identity_fakes_v3.FakeIdentityv3Client(
|
||||
endpoint=fakes.AUTH_URL,
|
||||
@ -193,6 +198,29 @@ class TestCreateSubnetPool(TestSubnetPool):
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
def test_create_address_scope_option(self):
|
||||
arglist = [
|
||||
'--pool-prefix', '10.0.10.0/24',
|
||||
'--address-scope', self._address_scope.id,
|
||||
self._subnet_pool.name,
|
||||
]
|
||||
verifylist = [
|
||||
('prefixes', ['10.0.10.0/24']),
|
||||
('address_scope', self._address_scope.id),
|
||||
('name', self._subnet_pool.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = (self.cmd.take_action(parsed_args))
|
||||
|
||||
self.network.create_subnet_pool.assert_called_once_with(**{
|
||||
'prefixes': ['10.0.10.0/24'],
|
||||
'address_scope_id': self._address_scope.id,
|
||||
'name': self._subnet_pool.name,
|
||||
})
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
|
||||
class TestDeleteSubnetPool(TestSubnetPool):
|
||||
|
||||
@ -301,6 +329,8 @@ class TestSetSubnetPool(TestSubnetPool):
|
||||
# The subnet_pool to set.
|
||||
_subnet_pool = network_fakes.FakeSubnetPool.create_one_subnet_pool()
|
||||
|
||||
_address_scope = network_fakes.FakeAddressScope.create_one_address_scope()
|
||||
|
||||
def setUp(self):
|
||||
super(TestSetSubnetPool, self).setUp()
|
||||
|
||||
@ -309,21 +339,24 @@ class TestSetSubnetPool(TestSubnetPool):
|
||||
self.network.find_subnet_pool = mock.Mock(
|
||||
return_value=self._subnet_pool)
|
||||
|
||||
self.network.find_address_scope = mock.Mock(
|
||||
return_value=self._address_scope)
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = subnet_pool.SetSubnetPool(self.app, self.namespace)
|
||||
|
||||
def test_set_this(self):
|
||||
arglist = [
|
||||
self._subnet_pool.name,
|
||||
'--name', 'noob',
|
||||
'--default-prefix-length', '8',
|
||||
'--min-prefix-length', '8',
|
||||
self._subnet_pool.name,
|
||||
]
|
||||
verifylist = [
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
('name', 'noob'),
|
||||
('default_prefix_length', '8'),
|
||||
('min_prefix_length', '8'),
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
@ -340,15 +373,15 @@ class TestSetSubnetPool(TestSubnetPool):
|
||||
|
||||
def test_set_that(self):
|
||||
arglist = [
|
||||
self._subnet_pool.name,
|
||||
'--pool-prefix', '10.0.1.0/24',
|
||||
'--pool-prefix', '10.0.2.0/24',
|
||||
'--max-prefix-length', '16',
|
||||
self._subnet_pool.name,
|
||||
]
|
||||
verifylist = [
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
('prefixes', ['10.0.1.0/24', '10.0.2.0/24']),
|
||||
('max_prefix_length', '16'),
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
@ -374,17 +407,73 @@ class TestSetSubnetPool(TestSubnetPool):
|
||||
|
||||
def test_set_len_negative(self):
|
||||
arglist = [
|
||||
self._subnet_pool.name,
|
||||
'--max-prefix-length', '-16',
|
||||
self._subnet_pool.name,
|
||||
]
|
||||
verifylist = [
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
('max_prefix_length', '-16'),
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
]
|
||||
|
||||
self.assertRaises(argparse.ArgumentTypeError, self.check_parser,
|
||||
self.cmd, arglist, verifylist)
|
||||
|
||||
def test_set_address_scope(self):
|
||||
arglist = [
|
||||
'--address-scope', self._address_scope.id,
|
||||
self._subnet_pool.name,
|
||||
]
|
||||
verifylist = [
|
||||
('address_scope', self._address_scope.id),
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
attrs = {
|
||||
'address_scope_id': self._address_scope.id,
|
||||
}
|
||||
self.network.update_subnet_pool.assert_called_once_with(
|
||||
self._subnet_pool, **attrs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_set_no_address_scope(self):
|
||||
arglist = [
|
||||
'--no-address-scope',
|
||||
self._subnet_pool.name,
|
||||
]
|
||||
verifylist = [
|
||||
('no_address_scope', True),
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
attrs = {
|
||||
'address_scope_id': None,
|
||||
}
|
||||
self.network.update_subnet_pool.assert_called_once_with(
|
||||
self._subnet_pool, **attrs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_set_no_address_scope_conflict(self):
|
||||
arglist = [
|
||||
'--address-scope', self._address_scope.id,
|
||||
'--no-address-scope',
|
||||
self._subnet_pool.name,
|
||||
]
|
||||
verifylist = [
|
||||
('address_scope', self._address_scope.id),
|
||||
('no_address_scope', True),
|
||||
('subnet_pool', self._subnet_pool.name),
|
||||
]
|
||||
|
||||
# Exclusive arguments will conflict here.
|
||||
self.assertRaises(tests_utils.ParserException, self.check_parser,
|
||||
self.cmd, arglist, verifylist)
|
||||
|
||||
|
||||
class TestShowSubnetPool(TestSubnetPool):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user