Skip to content

Commit 6a55e05

Browse files
committed
Add network segment command object
Add network segment command object in support of routed networks. This patch set includes documentation, unit tests and functional tests (currently skipped until segments enabled in neutron by default) for the following new commands: - "os network segment list" - "os network segment show" These new commands are currently marked as beta commands. Change-Id: I1a79b48dc6820fe2a39fcceb11c8cae3bda413a0 Partially-Implements: blueprint routed-networks
1 parent 9da02d1 commit 6a55e05

10 files changed

Lines changed: 506 additions & 0 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
===============
2+
network segment
3+
===============
4+
5+
A **network segment** is an isolated Layer 2 segment within a network.
6+
A network may contain multiple network segments. Depending on the
7+
network configuration, Layer 2 connectivity between network segments
8+
within a network may not be guaranteed.
9+
10+
Network v2
11+
12+
network segment list
13+
--------------------
14+
15+
List network segments
16+
17+
.. caution:: This is a beta command and subject to change.
18+
Use global option ``--enable-beta-commands`` to
19+
enable this command.
20+
21+
.. program:: network segment list
22+
.. code:: bash
23+
24+
os network segment list
25+
[--long]
26+
[--network <network>]
27+
28+
.. option:: --long
29+
30+
List additional fields in output
31+
32+
.. option:: --network <network>
33+
34+
List network segments that belong to this network (name or ID)
35+
36+
network segment show
37+
--------------------
38+
39+
Display network segment details
40+
41+
.. caution:: This is a beta command and subject to change.
42+
Use global option ``--enable-beta-commands`` to
43+
enable this command.
44+
45+
.. program:: network segment show
46+
.. code:: bash
47+
48+
os network segment show
49+
<network-segment>
50+
51+
.. _network_segment_show-segment:
52+
.. describe:: <network-segment>
53+
54+
Network segment to display (ID only)

doc/source/commands.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ referring to both Compute and Volume quotas.
104104
* ``mapping``: (**Identity**) a definition to translate identity provider attributes to Identity concepts
105105
* ``module``: (**Internal**) - installed Python modules in the OSC process
106106
* ``network``: (**Compute**, **Network**) - a virtual network for connecting servers and other resources
107+
* ``network segment``: (**Network**) - a segment of a virtual network
107108
* ``object``: (**Object Storage**) a single file in the Object Storage
108109
* ``object store account``: (**Object Storage**) owns a group of Object Storage resources
109110
* ``policy``: (**Identity**) determines authorization
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
import testtools
14+
import uuid
15+
16+
from functional.common import test
17+
18+
19+
# NOTE(rtheis): Routed networks is still a WIP and not enabled by default.
20+
@testtools.skip("bp/routed-networks")
21+
class NetworkSegmentTests(test.TestCase):
22+
"""Functional tests for network segment. """
23+
NETWORK_NAME = uuid.uuid4().hex
24+
PHYSICAL_NETWORK_NAME = uuid.uuid4().hex
25+
NETWORK_SEGMENT_ID = None
26+
NETWORK_ID = None
27+
28+
@classmethod
29+
def setUpClass(cls):
30+
# Create a network for the segment.
31+
opts = cls.get_show_opts(['id'])
32+
raw_output = cls.openstack('network create ' + cls.NETWORK_NAME + opts)
33+
cls.NETWORK_ID = raw_output.strip('\n')
34+
35+
# Get the segment for the network.
36+
opts = cls.get_show_opts(['ID', 'Network'])
37+
raw_output = cls.openstack('--enable-beta-commands '
38+
'network segment list '
39+
' --network ' + cls.NETWORK_NAME +
40+
' ' + opts)
41+
raw_output_row = raw_output.split('\n')[0]
42+
cls.NETWORK_SEGMENT_ID = raw_output_row.split(' ')[0]
43+
44+
@classmethod
45+
def tearDownClass(cls):
46+
raw_output = cls.openstack('network delete ' + cls.NETWORK_NAME)
47+
cls.assertOutput('', raw_output)
48+
49+
def test_network_segment_list(self):
50+
opts = self.get_list_opts(['ID'])
51+
raw_output = self.openstack('--enable-beta-commands '
52+
'network segment list' + opts)
53+
self.assertIn(self.NETWORK_SEGMENT_ID, raw_output)
54+
55+
def test_network_segment_show(self):
56+
opts = self.get_show_opts(['network_id'])
57+
raw_output = self.openstack('--enable-beta-commands '
58+
'network segment show ' +
59+
self.NETWORK_SEGMENT_ID + opts)
60+
self.assertEqual(self.NETWORK_ID + "\n", raw_output)
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
14+
"""Network segment action implementations"""
15+
16+
# TODO(rtheis): Add description and name properties when support is available.
17+
18+
from openstackclient.common import command
19+
from openstackclient.common import exceptions
20+
from openstackclient.common import utils
21+
from openstackclient.i18n import _
22+
23+
24+
class ListNetworkSegment(command.Lister):
25+
"""List network segments
26+
27+
(Caution: This is a beta command and subject to change.
28+
Use global option --enable-beta-commands to enable
29+
this command)
30+
"""
31+
32+
def get_parser(self, prog_name):
33+
parser = super(ListNetworkSegment, self).get_parser(prog_name)
34+
parser.add_argument(
35+
'--long',
36+
action='store_true',
37+
default=False,
38+
help=_('List additional fields in output'),
39+
)
40+
parser.add_argument(
41+
'--network',
42+
metavar='<network>',
43+
help=_('List network segments that belong to this '
44+
'network (name or ID)'),
45+
)
46+
return parser
47+
48+
def take_action(self, parsed_args):
49+
if not self.app.options.enable_beta_commands:
50+
msg = _('Caution: This is a beta command and subject to '
51+
'change. Use global option --enable-beta-commands '
52+
'to enable this command.')
53+
raise exceptions.CommandError(msg)
54+
55+
network_client = self.app.client_manager.network
56+
57+
filters = {}
58+
if parsed_args.network:
59+
_network = network_client.find_network(
60+
parsed_args.network,
61+
ignore_missing=False
62+
)
63+
filters = {'network_id': _network.id}
64+
data = network_client.segments(**filters)
65+
66+
headers = (
67+
'ID',
68+
'Network',
69+
'Network Type',
70+
'Segment',
71+
)
72+
columns = (
73+
'id',
74+
'network_id',
75+
'network_type',
76+
'segmentation_id',
77+
)
78+
if parsed_args.long:
79+
headers = headers + (
80+
'Physical Network',
81+
)
82+
columns = columns + (
83+
'physical_network',
84+
)
85+
86+
return (headers,
87+
(utils.get_item_properties(
88+
s, columns,
89+
formatters={},
90+
) for s in data))
91+
92+
93+
class ShowNetworkSegment(command.ShowOne):
94+
"""Display network segment details
95+
96+
(Caution: This is a beta command and subject to change.
97+
Use global option --enable-beta-commands to enable
98+
this command)
99+
"""
100+
101+
def get_parser(self, prog_name):
102+
parser = super(ShowNetworkSegment, self).get_parser(prog_name)
103+
parser.add_argument(
104+
'network_segment',
105+
metavar='<network-segment>',
106+
help=_('Network segment to display (ID only)'),
107+
)
108+
return parser
109+
110+
def take_action(self, parsed_args):
111+
if not self.app.options.enable_beta_commands:
112+
msg = _('Caution: This is a beta command and subject to '
113+
'change. Use global option --enable-beta-commands '
114+
'to enable this command.')
115+
raise exceptions.CommandError(msg)
116+
117+
client = self.app.client_manager.network
118+
obj = client.find_segment(
119+
parsed_args.network_segment,
120+
ignore_missing=False
121+
)
122+
columns = tuple(sorted(obj.keys()))
123+
data = utils.get_item_properties(obj, columns)
124+
return (columns, data)

openstackclient/tests/fakes.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ def __init__(self, _stdout, _log):
9797
self.log = _log
9898

9999

100+
class FakeOptions(object):
101+
def __init__(self, **kwargs):
102+
self.enable_beta_commands = False
103+
104+
100105
class FakeClient(object):
101106

102107
def __init__(self, **kwargs):

openstackclient/tests/network/v2/fakes.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,58 @@ def get_networks(networks=None, count=2):
256256
return mock.MagicMock(side_effect=networks)
257257

258258

259+
class FakeNetworkSegment(object):
260+
"""Fake one or more network segments."""
261+
262+
@staticmethod
263+
def create_one_network_segment(attrs=None):
264+
"""Create a fake network segment.
265+
266+
:param Dictionary attrs:
267+
A dictionary with all attributes
268+
:return:
269+
A FakeResource object faking the network segment
270+
"""
271+
attrs = attrs or {}
272+
273+
# Set default attributes.
274+
network_segment_attrs = {
275+
'id': 'segment-id-' + uuid.uuid4().hex,
276+
'network_id': 'network-id-' + uuid.uuid4().hex,
277+
'network_type': 'vlan',
278+
'physical_network': 'physical-network-name-' + uuid.uuid4().hex,
279+
'segmentation_id': 1024,
280+
}
281+
282+
# Overwrite default attributes.
283+
network_segment_attrs.update(attrs)
284+
285+
network_segment = fakes.FakeResource(
286+
info=copy.deepcopy(network_segment_attrs),
287+
loaded=True
288+
)
289+
290+
return network_segment
291+
292+
@staticmethod
293+
def create_network_segments(attrs=None, count=2):
294+
"""Create multiple fake network segments.
295+
296+
:param Dictionary attrs:
297+
A dictionary with all attributes
298+
:param int count:
299+
The number of network segments to fake
300+
:return:
301+
A list of FakeResource objects faking the network segments
302+
"""
303+
network_segments = []
304+
for i in range(0, count):
305+
network_segments.append(
306+
FakeNetworkSegment.create_one_network_segment(attrs)
307+
)
308+
return network_segments
309+
310+
259311
class FakePort(object):
260312
"""Fake one or more ports."""
261313

0 commit comments

Comments
 (0)