Skip to content

Commit 6a6b192

Browse files
committed
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
1 parent df71ae8 commit 6a6b192

6 files changed

Lines changed: 157 additions & 25 deletions

File tree

doc/source/command-beta.rst

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,29 @@ To address these challenges, an OpenStackClient command may
1212
be labeled as a beta command according to the guidelines
1313
below. Such commands may introduce backwards incompatible
1414
changes and may use REST API enhancements not yet released.
15+
This also applies to command options associated with the beta
16+
command object.
1517

16-
See the examples below on how to label a command as a beta
17-
by updating the command documentation, help and implementation.
18+
See the examples below on how to label an entire command or
19+
a specific option as a beta by updating the documentation
20+
and implementation.
1821

19-
The initial release note must label the new command as a beta.
20-
No further release notes are required until the command
21-
is no longer a beta. At which time, the command beta label
22-
or the command itself must be removed and a new release note
22+
The initial release note must label the new command or option
23+
as a beta. No further release notes are required until the command
24+
or option is no longer a beta. At which time, the beta label or
25+
the command or option itself must be removed and a new release note
2326
must be provided.
2427

28+
Beta Command Example
29+
--------------------
30+
2531
Documentation
26-
-------------
32+
~~~~~~~~~~~~~
2733

2834
The command documentation must label the command as a beta.
2935

3036
example list
31-
~~~~~~~~~~~~
37+
++++++++++++
3238

3339
List examples
3440

@@ -42,7 +48,7 @@ List examples
4248
os example list
4349
4450
Help
45-
----
51+
~~~~
4652

4753
The command help must label the command as a beta.
4854

@@ -57,7 +63,7 @@ The command help must label the command as a beta.
5763
"""
5864
5965
Implementation
60-
--------------
66+
~~~~~~~~~~~~~~
6167

6268
The command must raise a ``CommandError`` exception if beta commands
6369
are not enabled via ``--os-beta-command`` global option.
@@ -66,3 +72,35 @@ are not enabled via ``--os-beta-command`` global option.
6672
6773
def take_action(self, parsed_args):
6874
self.validate_os_beta_command_enabled()
75+
76+
Beta Option Example
77+
-------------------
78+
79+
Documentation
80+
~~~~~~~~~~~~~
81+
82+
The option documentation must label the option as a beta.
83+
84+
.. option:: --example <example>
85+
86+
Example
87+
88+
.. caution:: This is a beta command option and subject
89+
to change. Use global option ``--os-beta-command``
90+
to enable this command option.
91+
92+
Implementation
93+
~~~~~~~~~~~~~~
94+
95+
The option must not be added if beta commands are not
96+
enabled via ``--os-beta-command`` global option.
97+
98+
.. code-block:: python
99+
100+
def get_parser(self, prog_name):
101+
if self.app.options.os_beta_command:
102+
parser.add_argument(
103+
'--example',
104+
metavar='<example>',
105+
help=_("Example")
106+
)

doc/source/command-objects/subnet.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Create new subnet
2828
[--ip-version {4,6}]
2929
[--ipv6-ra-mode {dhcpv6-stateful,dhcpv6-stateless,slaac}]
3030
[--ipv6-address-mode {dhcpv6-stateful,dhcpv6-stateless,slaac}]
31+
[--network-segment <network-segment>]
3132
--network <network>
3233
<name>
3334
@@ -107,6 +108,14 @@ Create new subnet
107108
108109
IPv6 address mode, valid modes: [dhcpv6-stateful, dhcpv6-stateless, slaac]
109110
111+
.. option:: --network-segment <network-segment>
112+
113+
Network segment to associate with this subnet (ID only)
114+
115+
.. caution:: This is a beta command option and subject
116+
to change. Use global option ``--os-beta-command``
117+
to enable this command option.
118+
110119
.. option:: --network <network>
111120
112121
Network this subnet belongs to (name or ID)

openstackclient/network/v2/subnet.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ def _get_attrs(client_manager, parsed_args, is_create=True):
136136
attrs['ipv6_ra_mode'] = parsed_args.ipv6_ra_mode
137137
if parsed_args.ipv6_address_mode is not None:
138138
attrs['ipv6_address_mode'] = parsed_args.ipv6_address_mode
139+
if 'network_segment' in parsed_args:
140+
attrs['segment_id'] = client.find_segment(
141+
parsed_args.network_segment, ignore_missing=False).id
139142

140143
if 'gateway' in parsed_args and parsed_args.gateway is not None:
141144
gateway = parsed_args.gateway.lower()
@@ -249,6 +252,13 @@ def get_parser(self, prog_name):
249252
help=_("IPv6 address mode, "
250253
"valid modes: [dhcpv6-stateful, dhcpv6-stateless, slaac]")
251254
)
255+
if self.app.options.os_beta_command:
256+
parser.add_argument(
257+
'--network-segment',
258+
metavar='<network-segment>',
259+
help=_("Network segment to associate with this subnet "
260+
"(ID only)")
261+
)
252262
parser.add_argument(
253263
'--network',
254264
required=True,

openstackclient/tests/network/v2/fakes.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def create_one_network_segment(attrs=None):
352352

353353
# Set default attributes.
354354
network_segment_attrs = {
355-
'id': 'segment-id-' + uuid.uuid4().hex,
355+
'id': 'network-segment-id-' + uuid.uuid4().hex,
356356
'network_id': 'network-id-' + uuid.uuid4().hex,
357357
'network_type': 'vlan',
358358
'physical_network': 'physical-network-name-' + uuid.uuid4().hex,
@@ -699,9 +699,10 @@ def create_one_subnet(attrs=None):
699699
'host_routes': [],
700700
'ip_version': 4,
701701
'gateway_ip': '10.10.10.1',
702-
'ipv6_address_mode': 'None',
703-
'ipv6_ra_mode': 'None',
704-
'subnetpool_id': 'None',
702+
'ipv6_address_mode': None,
703+
'ipv6_ra_mode': None,
704+
'segment_id': None,
705+
'subnetpool_id': None,
705706
}
706707

707708
# Overwrite default attributes.

openstackclient/tests/network/v2/test_subnet.py

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ class TestCreateSubnet(TestSubnet):
8888
}
8989
)
9090

91+
# The network segment to be returned from find_segment
92+
_network_segment = \
93+
network_fakes.FakeNetworkSegment.create_one_network_segment(
94+
attrs={
95+
'network_id': _subnet.network_id,
96+
}
97+
)
98+
9199
columns = (
92100
'allocation_pools',
93101
'cidr',
@@ -102,6 +110,7 @@ class TestCreateSubnet(TestSubnet):
102110
'name',
103111
'network_id',
104112
'project_id',
113+
'segment_id',
105114
'subnetpool_id',
106115
)
107116

@@ -119,6 +128,7 @@ class TestCreateSubnet(TestSubnet):
119128
_subnet.name,
120129
_subnet.network_id,
121130
_subnet.project_id,
131+
_subnet.segment_id,
122132
_subnet.subnetpool_id,
123133
)
124134

@@ -136,6 +146,7 @@ class TestCreateSubnet(TestSubnet):
136146
_subnet_from_pool.name,
137147
_subnet_from_pool.network_id,
138148
_subnet_from_pool.project_id,
149+
_subnet_from_pool.segment_id,
139150
_subnet_from_pool.subnetpool_id,
140151
)
141152

@@ -153,6 +164,7 @@ class TestCreateSubnet(TestSubnet):
153164
_subnet_ipv6.name,
154165
_subnet_ipv6.network_id,
155166
_subnet_ipv6.project_id,
167+
_subnet_ipv6.segment_id,
156168
_subnet_ipv6.subnetpool_id,
157169
)
158170

@@ -186,6 +198,15 @@ def setUp(self):
186198
loaded=True,
187199
)
188200

201+
# Mock SDK calls for all tests.
202+
self.network.find_network = mock.Mock(return_value=self._network)
203+
self.network.find_segment = mock.Mock(
204+
return_value=self._network_segment
205+
)
206+
self.network.find_subnet_pool = mock.Mock(
207+
return_value=self._subnet_pool
208+
)
209+
189210
def test_create_no_options(self):
190211
arglist = []
191212
verifylist = []
@@ -196,11 +217,9 @@ def test_create_no_options(self):
196217
self.check_parser, self.cmd, arglist, verifylist)
197218

198219
def test_create_default_options(self):
199-
# Mock create_subnet and find_network sdk calls to return the
200-
# values we want for this test
220+
# Mock SDK calls for this test.
201221
self.network.create_subnet = mock.Mock(return_value=self._subnet)
202222
self._network.id = self._subnet.network_id
203-
self.network.find_network = mock.Mock(return_value=self._network)
204223

205224
arglist = [
206225
"--subnet-range", self._subnet.cidr,
@@ -230,14 +249,10 @@ def test_create_default_options(self):
230249
self.assertEqual(self.data, data)
231250

232251
def test_create_from_subnet_pool_options(self):
233-
# Mock create_subnet, find_subnet_pool, and find_network sdk calls
234-
# to return the values we want for this test
252+
# Mock SDK calls for this test.
235253
self.network.create_subnet = \
236254
mock.Mock(return_value=self._subnet_from_pool)
237255
self._network.id = self._subnet_from_pool.network_id
238-
self.network.find_network = mock.Mock(return_value=self._network)
239-
self.network.find_subnet_pool = \
240-
mock.Mock(return_value=self._subnet_pool)
241256

242257
arglist = [
243258
self._subnet_from_pool.name,
@@ -290,11 +305,9 @@ def test_create_from_subnet_pool_options(self):
290305
self.assertEqual(self.data_subnet_pool, data)
291306

292307
def test_create_options_subnet_range_ipv6(self):
293-
# Mock create_subnet and find_network sdk calls to return the
294-
# values we want for this test
308+
# Mock SDK calls for this test.
295309
self.network.create_subnet = mock.Mock(return_value=self._subnet_ipv6)
296310
self._network.id = self._subnet_ipv6.network_id
297-
self.network.find_network = mock.Mock(return_value=self._network)
298311

299312
arglist = [
300313
self._subnet_ipv6.name,
@@ -357,6 +370,59 @@ def test_create_options_subnet_range_ipv6(self):
357370
self.assertEqual(self.columns, columns)
358371
self.assertEqual(self.data_ipv6, data)
359372

373+
def test_create_no_beta_command_options(self):
374+
arglist = [
375+
"--subnet-range", self._subnet.cidr,
376+
"--network-segment", self._network_segment.id,
377+
"--network", self._subnet.network_id,
378+
self._subnet.name,
379+
]
380+
verifylist = [
381+
('name', self._subnet.name),
382+
('subnet_range', self._subnet.cidr),
383+
('network-segment', self._network_segment.id),
384+
('network', self._subnet.network_id),
385+
]
386+
self.app.options.os_beta_command = False
387+
self.assertRaises(tests_utils.ParserException,
388+
self.check_parser, self.cmd, arglist, verifylist)
389+
390+
def test_create_with_network_segment(self):
391+
# Mock SDK calls for this test.
392+
self.network.create_subnet = mock.Mock(return_value=self._subnet)
393+
self._network.id = self._subnet.network_id
394+
395+
arglist = [
396+
"--subnet-range", self._subnet.cidr,
397+
"--network-segment", self._network_segment.id,
398+
"--network", self._subnet.network_id,
399+
self._subnet.name,
400+
]
401+
verifylist = [
402+
('name', self._subnet.name),
403+
('subnet_range', self._subnet.cidr),
404+
('network_segment', self._network_segment.id),
405+
('network', self._subnet.network_id),
406+
('ip_version', self._subnet.ip_version),
407+
('gateway', 'auto'),
408+
409+
]
410+
411+
self.app.options.os_beta_command = True
412+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
413+
columns, data = self.cmd.take_action(parsed_args)
414+
415+
self.network.create_subnet.assert_called_once_with(**{
416+
'cidr': self._subnet.cidr,
417+
'enable_dhcp': self._subnet.enable_dhcp,
418+
'ip_version': self._subnet.ip_version,
419+
'name': self._subnet.name,
420+
'network_id': self._subnet.network_id,
421+
'segment_id': self._network_segment.id,
422+
})
423+
self.assertEqual(self.columns, columns)
424+
self.assertEqual(self.data, data)
425+
360426

361427
class TestDeleteSubnet(TestSubnet):
362428

@@ -593,6 +659,7 @@ class TestShowSubnet(TestSubnet):
593659
'name',
594660
'network_id',
595661
'project_id',
662+
'segment_id',
596663
'subnetpool_id',
597664
)
598665

@@ -610,6 +677,7 @@ class TestShowSubnet(TestSubnet):
610677
_subnet.name,
611678
_subnet.network_id,
612679
_subnet.tenant_id,
680+
_subnet.segment_id,
613681
_subnet.subnetpool_id,
614682
)
615683

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
features:
3+
- Add ``--network-segment`` option to the ``subnet create`` command.
4+
This is a beta command option and subject to change. Use global option
5+
``--os-beta-command`` to enable this option.
6+
[Blueprint `routed-networks <https://blueprints.launchpad.net/neutron/+spec/routed-networks>`_]

0 commit comments

Comments
 (0)