Add "--network-segment" option to "subnet create"

Add "--network-segment" option to the "subnet create" command.
This is a beta command option and subject to change. Use global
option "--os-beta-command" to enable this option.

This patch set also provides a devref update for beta command
options.

Change-Id: I4d0fbe079b2a873307364c41c22ce9ba88e632e6
Partially-Implements: blueprint routed-networks
This commit is contained in:
Richard Theis 2016-06-10 16:01:31 -05:00
parent df71ae814e
commit 6a6b192dde
6 changed files with 157 additions and 25 deletions

View File

@ -12,23 +12,29 @@ To address these challenges, an OpenStackClient command may
be labeled as a beta command according to the guidelines
below. Such commands may introduce backwards incompatible
changes and may use REST API enhancements not yet released.
This also applies to command options associated with the beta
command object.
See the examples below on how to label a command as a beta
by updating the command documentation, help and implementation.
See the examples below on how to label an entire command or
a specific option as a beta by updating the documentation
and implementation.
The initial release note must label the new command as a beta.
No further release notes are required until the command
is no longer a beta. At which time, the command beta label
or the command itself must be removed and a new release note
The initial release note must label the new command or option
as a beta. No further release notes are required until the command
or option is no longer a beta. At which time, the beta label or
the command or option itself must be removed and a new release note
must be provided.
Beta Command Example
--------------------
Documentation
-------------
~~~~~~~~~~~~~
The command documentation must label the command as a beta.
example list
~~~~~~~~~~~~
++++++++++++
List examples
@ -42,7 +48,7 @@ List examples
os example list
Help
----
~~~~
The command help must label the command as a beta.
@ -57,7 +63,7 @@ The command help must label the command as a beta.
"""
Implementation
--------------
~~~~~~~~~~~~~~
The command must raise a ``CommandError`` exception if beta commands
are not enabled via ``--os-beta-command`` global option.
@ -66,3 +72,35 @@ are not enabled via ``--os-beta-command`` global option.
def take_action(self, parsed_args):
self.validate_os_beta_command_enabled()
Beta Option Example
-------------------
Documentation
~~~~~~~~~~~~~
The option documentation must label the option as a beta.
.. option:: --example <example>
Example
.. caution:: This is a beta command option and subject
to change. Use global option ``--os-beta-command``
to enable this command option.
Implementation
~~~~~~~~~~~~~~
The option must not be added if beta commands are not
enabled via ``--os-beta-command`` global option.
.. code-block:: python
def get_parser(self, prog_name):
if self.app.options.os_beta_command:
parser.add_argument(
'--example',
metavar='<example>',
help=_("Example")
)

View File

@ -28,6 +28,7 @@ Create new subnet
[--ip-version {4,6}]
[--ipv6-ra-mode {dhcpv6-stateful,dhcpv6-stateless,slaac}]
[--ipv6-address-mode {dhcpv6-stateful,dhcpv6-stateless,slaac}]
[--network-segment <network-segment>]
--network <network>
<name>
@ -107,6 +108,14 @@ Create new subnet
IPv6 address mode, valid modes: [dhcpv6-stateful, dhcpv6-stateless, slaac]
.. option:: --network-segment <network-segment>
Network segment to associate with this subnet (ID only)
.. caution:: This is a beta command option and subject
to change. Use global option ``--os-beta-command``
to enable this command option.
.. option:: --network <network>
Network this subnet belongs to (name or ID)

View File

@ -136,6 +136,9 @@ def _get_attrs(client_manager, parsed_args, is_create=True):
attrs['ipv6_ra_mode'] = parsed_args.ipv6_ra_mode
if parsed_args.ipv6_address_mode is not None:
attrs['ipv6_address_mode'] = parsed_args.ipv6_address_mode
if 'network_segment' in parsed_args:
attrs['segment_id'] = client.find_segment(
parsed_args.network_segment, ignore_missing=False).id
if 'gateway' in parsed_args and parsed_args.gateway is not None:
gateway = parsed_args.gateway.lower()
@ -249,6 +252,13 @@ class CreateSubnet(command.ShowOne):
help=_("IPv6 address mode, "
"valid modes: [dhcpv6-stateful, dhcpv6-stateless, slaac]")
)
if self.app.options.os_beta_command:
parser.add_argument(
'--network-segment',
metavar='<network-segment>',
help=_("Network segment to associate with this subnet "
"(ID only)")
)
parser.add_argument(
'--network',
required=True,

View File

@ -352,7 +352,7 @@ class FakeNetworkSegment(object):
# Set default attributes.
network_segment_attrs = {
'id': 'segment-id-' + uuid.uuid4().hex,
'id': 'network-segment-id-' + uuid.uuid4().hex,
'network_id': 'network-id-' + uuid.uuid4().hex,
'network_type': 'vlan',
'physical_network': 'physical-network-name-' + uuid.uuid4().hex,
@ -699,9 +699,10 @@ class FakeSubnet(object):
'host_routes': [],
'ip_version': 4,
'gateway_ip': '10.10.10.1',
'ipv6_address_mode': 'None',
'ipv6_ra_mode': 'None',
'subnetpool_id': 'None',
'ipv6_address_mode': None,
'ipv6_ra_mode': None,
'segment_id': None,
'subnetpool_id': None,
}
# Overwrite default attributes.

View File

@ -88,6 +88,14 @@ class TestCreateSubnet(TestSubnet):
}
)
# The network segment to be returned from find_segment
_network_segment = \
network_fakes.FakeNetworkSegment.create_one_network_segment(
attrs={
'network_id': _subnet.network_id,
}
)
columns = (
'allocation_pools',
'cidr',
@ -102,6 +110,7 @@ class TestCreateSubnet(TestSubnet):
'name',
'network_id',
'project_id',
'segment_id',
'subnetpool_id',
)
@ -119,6 +128,7 @@ class TestCreateSubnet(TestSubnet):
_subnet.name,
_subnet.network_id,
_subnet.project_id,
_subnet.segment_id,
_subnet.subnetpool_id,
)
@ -136,6 +146,7 @@ class TestCreateSubnet(TestSubnet):
_subnet_from_pool.name,
_subnet_from_pool.network_id,
_subnet_from_pool.project_id,
_subnet_from_pool.segment_id,
_subnet_from_pool.subnetpool_id,
)
@ -153,6 +164,7 @@ class TestCreateSubnet(TestSubnet):
_subnet_ipv6.name,
_subnet_ipv6.network_id,
_subnet_ipv6.project_id,
_subnet_ipv6.segment_id,
_subnet_ipv6.subnetpool_id,
)
@ -186,6 +198,15 @@ class TestCreateSubnet(TestSubnet):
loaded=True,
)
# Mock SDK calls for all tests.
self.network.find_network = mock.Mock(return_value=self._network)
self.network.find_segment = mock.Mock(
return_value=self._network_segment
)
self.network.find_subnet_pool = mock.Mock(
return_value=self._subnet_pool
)
def test_create_no_options(self):
arglist = []
verifylist = []
@ -196,11 +217,9 @@ class TestCreateSubnet(TestSubnet):
self.check_parser, self.cmd, arglist, verifylist)
def test_create_default_options(self):
# Mock create_subnet and find_network sdk calls to return the
# values we want for this test
# Mock SDK calls for this test.
self.network.create_subnet = mock.Mock(return_value=self._subnet)
self._network.id = self._subnet.network_id
self.network.find_network = mock.Mock(return_value=self._network)
arglist = [
"--subnet-range", self._subnet.cidr,
@ -230,14 +249,10 @@ class TestCreateSubnet(TestSubnet):
self.assertEqual(self.data, data)
def test_create_from_subnet_pool_options(self):
# Mock create_subnet, find_subnet_pool, and find_network sdk calls
# to return the values we want for this test
# Mock SDK calls for this test.
self.network.create_subnet = \
mock.Mock(return_value=self._subnet_from_pool)
self._network.id = self._subnet_from_pool.network_id
self.network.find_network = mock.Mock(return_value=self._network)
self.network.find_subnet_pool = \
mock.Mock(return_value=self._subnet_pool)
arglist = [
self._subnet_from_pool.name,
@ -290,11 +305,9 @@ class TestCreateSubnet(TestSubnet):
self.assertEqual(self.data_subnet_pool, data)
def test_create_options_subnet_range_ipv6(self):
# Mock create_subnet and find_network sdk calls to return the
# values we want for this test
# Mock SDK calls for this test.
self.network.create_subnet = mock.Mock(return_value=self._subnet_ipv6)
self._network.id = self._subnet_ipv6.network_id
self.network.find_network = mock.Mock(return_value=self._network)
arglist = [
self._subnet_ipv6.name,
@ -357,6 +370,59 @@ class TestCreateSubnet(TestSubnet):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data_ipv6, data)
def test_create_no_beta_command_options(self):
arglist = [
"--subnet-range", self._subnet.cidr,
"--network-segment", self._network_segment.id,
"--network", self._subnet.network_id,
self._subnet.name,
]
verifylist = [
('name', self._subnet.name),
('subnet_range', self._subnet.cidr),
('network-segment', self._network_segment.id),
('network', self._subnet.network_id),
]
self.app.options.os_beta_command = False
self.assertRaises(tests_utils.ParserException,
self.check_parser, self.cmd, arglist, verifylist)
def test_create_with_network_segment(self):
# Mock SDK calls for this test.
self.network.create_subnet = mock.Mock(return_value=self._subnet)
self._network.id = self._subnet.network_id
arglist = [
"--subnet-range", self._subnet.cidr,
"--network-segment", self._network_segment.id,
"--network", self._subnet.network_id,
self._subnet.name,
]
verifylist = [
('name', self._subnet.name),
('subnet_range', self._subnet.cidr),
('network_segment', self._network_segment.id),
('network', self._subnet.network_id),
('ip_version', self._subnet.ip_version),
('gateway', 'auto'),
]
self.app.options.os_beta_command = True
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.network.create_subnet.assert_called_once_with(**{
'cidr': self._subnet.cidr,
'enable_dhcp': self._subnet.enable_dhcp,
'ip_version': self._subnet.ip_version,
'name': self._subnet.name,
'network_id': self._subnet.network_id,
'segment_id': self._network_segment.id,
})
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
class TestDeleteSubnet(TestSubnet):
@ -593,6 +659,7 @@ class TestShowSubnet(TestSubnet):
'name',
'network_id',
'project_id',
'segment_id',
'subnetpool_id',
)
@ -610,6 +677,7 @@ class TestShowSubnet(TestSubnet):
_subnet.name,
_subnet.network_id,
_subnet.tenant_id,
_subnet.segment_id,
_subnet.subnetpool_id,
)

View File

@ -0,0 +1,6 @@
---
features:
- Add ``--network-segment`` option to the ``subnet create`` command.
This is a beta command option and subject to change. Use global option
``--os-beta-command`` to enable this option.
[Blueprint `routed-networks <https://blueprints.launchpad.net/neutron/+spec/routed-networks>`_]