Merge "Add network segment command object"
This commit is contained in:
commit
37bc7bbf91
54
doc/source/command-objects/network-segment.rst
Normal file
54
doc/source/command-objects/network-segment.rst
Normal file
@ -0,0 +1,54 @@
|
||||
===============
|
||||
network segment
|
||||
===============
|
||||
|
||||
A **network segment** is an isolated Layer 2 segment within a network.
|
||||
A network may contain multiple network segments. Depending on the
|
||||
network configuration, Layer 2 connectivity between network segments
|
||||
within a network may not be guaranteed.
|
||||
|
||||
Network v2
|
||||
|
||||
network segment list
|
||||
--------------------
|
||||
|
||||
List network segments
|
||||
|
||||
.. caution:: This is a beta command and subject to change.
|
||||
Use global option ``--enable-beta-commands`` to
|
||||
enable this command.
|
||||
|
||||
.. program:: network segment list
|
||||
.. code:: bash
|
||||
|
||||
os network segment list
|
||||
[--long]
|
||||
[--network <network>]
|
||||
|
||||
.. option:: --long
|
||||
|
||||
List additional fields in output
|
||||
|
||||
.. option:: --network <network>
|
||||
|
||||
List network segments that belong to this network (name or ID)
|
||||
|
||||
network segment show
|
||||
--------------------
|
||||
|
||||
Display network segment details
|
||||
|
||||
.. caution:: This is a beta command and subject to change.
|
||||
Use global option ``--enable-beta-commands`` to
|
||||
enable this command.
|
||||
|
||||
.. program:: network segment show
|
||||
.. code:: bash
|
||||
|
||||
os network segment show
|
||||
<network-segment>
|
||||
|
||||
.. _network_segment_show-segment:
|
||||
.. describe:: <network-segment>
|
||||
|
||||
Network segment to display (ID only)
|
@ -104,6 +104,7 @@ referring to both Compute and Volume quotas.
|
||||
* ``mapping``: (**Identity**) a definition to translate identity provider attributes to Identity concepts
|
||||
* ``module``: (**Internal**) - installed Python modules in the OSC process
|
||||
* ``network``: (**Compute**, **Network**) - a virtual network for connecting servers and other resources
|
||||
* ``network segment``: (**Network**) - a segment of a virtual network
|
||||
* ``object``: (**Object Storage**) a single file in the Object Storage
|
||||
* ``object store account``: (**Object Storage**) owns a group of Object Storage resources
|
||||
* ``policy``: (**Identity**) determines authorization
|
||||
|
60
functional/tests/network/v2/test_network_segment.py
Normal file
60
functional/tests/network/v2/test_network_segment.py
Normal file
@ -0,0 +1,60 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import testtools
|
||||
import uuid
|
||||
|
||||
from functional.common import test
|
||||
|
||||
|
||||
# NOTE(rtheis): Routed networks is still a WIP and not enabled by default.
|
||||
@testtools.skip("bp/routed-networks")
|
||||
class NetworkSegmentTests(test.TestCase):
|
||||
"""Functional tests for network segment. """
|
||||
NETWORK_NAME = uuid.uuid4().hex
|
||||
PHYSICAL_NETWORK_NAME = uuid.uuid4().hex
|
||||
NETWORK_SEGMENT_ID = None
|
||||
NETWORK_ID = None
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Create a network for the segment.
|
||||
opts = cls.get_show_opts(['id'])
|
||||
raw_output = cls.openstack('network create ' + cls.NETWORK_NAME + opts)
|
||||
cls.NETWORK_ID = raw_output.strip('\n')
|
||||
|
||||
# Get the segment for the network.
|
||||
opts = cls.get_show_opts(['ID', 'Network'])
|
||||
raw_output = cls.openstack('--enable-beta-commands '
|
||||
'network segment list '
|
||||
' --network ' + cls.NETWORK_NAME +
|
||||
' ' + opts)
|
||||
raw_output_row = raw_output.split('\n')[0]
|
||||
cls.NETWORK_SEGMENT_ID = raw_output_row.split(' ')[0]
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
raw_output = cls.openstack('network delete ' + cls.NETWORK_NAME)
|
||||
cls.assertOutput('', raw_output)
|
||||
|
||||
def test_network_segment_list(self):
|
||||
opts = self.get_list_opts(['ID'])
|
||||
raw_output = self.openstack('--enable-beta-commands '
|
||||
'network segment list' + opts)
|
||||
self.assertIn(self.NETWORK_SEGMENT_ID, raw_output)
|
||||
|
||||
def test_network_segment_show(self):
|
||||
opts = self.get_show_opts(['network_id'])
|
||||
raw_output = self.openstack('--enable-beta-commands '
|
||||
'network segment show ' +
|
||||
self.NETWORK_SEGMENT_ID + opts)
|
||||
self.assertEqual(self.NETWORK_ID + "\n", raw_output)
|
124
openstackclient/network/v2/network_segment.py
Normal file
124
openstackclient/network/v2/network_segment.py
Normal file
@ -0,0 +1,124 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""Network segment action implementations"""
|
||||
|
||||
# TODO(rtheis): Add description and name properties when support is available.
|
||||
|
||||
from openstackclient.common import command
|
||||
from openstackclient.common import exceptions
|
||||
from openstackclient.common import utils
|
||||
from openstackclient.i18n import _
|
||||
|
||||
|
||||
class ListNetworkSegment(command.Lister):
|
||||
"""List network segments
|
||||
|
||||
(Caution: This is a beta command and subject to change.
|
||||
Use global option --enable-beta-commands to enable
|
||||
this command)
|
||||
"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListNetworkSegment, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--long',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('List additional fields in output'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--network',
|
||||
metavar='<network>',
|
||||
help=_('List network segments that belong to this '
|
||||
'network (name or ID)'),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
if not self.app.options.enable_beta_commands:
|
||||
msg = _('Caution: This is a beta command and subject to '
|
||||
'change. Use global option --enable-beta-commands '
|
||||
'to enable this command.')
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
network_client = self.app.client_manager.network
|
||||
|
||||
filters = {}
|
||||
if parsed_args.network:
|
||||
_network = network_client.find_network(
|
||||
parsed_args.network,
|
||||
ignore_missing=False
|
||||
)
|
||||
filters = {'network_id': _network.id}
|
||||
data = network_client.segments(**filters)
|
||||
|
||||
headers = (
|
||||
'ID',
|
||||
'Network',
|
||||
'Network Type',
|
||||
'Segment',
|
||||
)
|
||||
columns = (
|
||||
'id',
|
||||
'network_id',
|
||||
'network_type',
|
||||
'segmentation_id',
|
||||
)
|
||||
if parsed_args.long:
|
||||
headers = headers + (
|
||||
'Physical Network',
|
||||
)
|
||||
columns = columns + (
|
||||
'physical_network',
|
||||
)
|
||||
|
||||
return (headers,
|
||||
(utils.get_item_properties(
|
||||
s, columns,
|
||||
formatters={},
|
||||
) for s in data))
|
||||
|
||||
|
||||
class ShowNetworkSegment(command.ShowOne):
|
||||
"""Display network segment details
|
||||
|
||||
(Caution: This is a beta command and subject to change.
|
||||
Use global option --enable-beta-commands to enable
|
||||
this command)
|
||||
"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowNetworkSegment, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'network_segment',
|
||||
metavar='<network-segment>',
|
||||
help=_('Network segment to display (ID only)'),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
if not self.app.options.enable_beta_commands:
|
||||
msg = _('Caution: This is a beta command and subject to '
|
||||
'change. Use global option --enable-beta-commands '
|
||||
'to enable this command.')
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
client = self.app.client_manager.network
|
||||
obj = client.find_segment(
|
||||
parsed_args.network_segment,
|
||||
ignore_missing=False
|
||||
)
|
||||
columns = tuple(sorted(obj.keys()))
|
||||
data = utils.get_item_properties(obj, columns)
|
||||
return (columns, data)
|
@ -97,6 +97,11 @@ class FakeApp(object):
|
||||
self.log = _log
|
||||
|
||||
|
||||
class FakeOptions(object):
|
||||
def __init__(self, **kwargs):
|
||||
self.enable_beta_commands = False
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
@ -275,6 +275,58 @@ class FakeNetwork(object):
|
||||
return mock.MagicMock(side_effect=networks)
|
||||
|
||||
|
||||
class FakeNetworkSegment(object):
|
||||
"""Fake one or more network segments."""
|
||||
|
||||
@staticmethod
|
||||
def create_one_network_segment(attrs=None):
|
||||
"""Create a fake network segment.
|
||||
|
||||
:param Dictionary attrs:
|
||||
A dictionary with all attributes
|
||||
:return:
|
||||
A FakeResource object faking the network segment
|
||||
"""
|
||||
attrs = attrs or {}
|
||||
|
||||
# Set default attributes.
|
||||
network_segment_attrs = {
|
||||
'id': 'segment-id-' + uuid.uuid4().hex,
|
||||
'network_id': 'network-id-' + uuid.uuid4().hex,
|
||||
'network_type': 'vlan',
|
||||
'physical_network': 'physical-network-name-' + uuid.uuid4().hex,
|
||||
'segmentation_id': 1024,
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
network_segment_attrs.update(attrs)
|
||||
|
||||
network_segment = fakes.FakeResource(
|
||||
info=copy.deepcopy(network_segment_attrs),
|
||||
loaded=True
|
||||
)
|
||||
|
||||
return network_segment
|
||||
|
||||
@staticmethod
|
||||
def create_network_segments(attrs=None, count=2):
|
||||
"""Create multiple fake network segments.
|
||||
|
||||
:param Dictionary attrs:
|
||||
A dictionary with all attributes
|
||||
:param int count:
|
||||
The number of network segments to fake
|
||||
:return:
|
||||
A list of FakeResource objects faking the network segments
|
||||
"""
|
||||
network_segments = []
|
||||
for i in range(0, count):
|
||||
network_segments.append(
|
||||
FakeNetworkSegment.create_one_network_segment(attrs)
|
||||
)
|
||||
return network_segments
|
||||
|
||||
|
||||
class FakePort(object):
|
||||
"""Fake one or more ports."""
|
||||
|
||||
|
199
openstackclient/tests/network/v2/test_network_segment.py
Normal file
199
openstackclient/tests/network/v2/test_network_segment.py
Normal file
@ -0,0 +1,199 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import mock
|
||||
|
||||
from openstackclient.common import exceptions
|
||||
from openstackclient.network.v2 import network_segment
|
||||
from openstackclient.tests.network.v2 import fakes as network_fakes
|
||||
from openstackclient.tests import utils as tests_utils
|
||||
|
||||
|
||||
class TestNetworkSegment(network_fakes.TestNetworkV2):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNetworkSegment, self).setUp()
|
||||
|
||||
# Enable beta commands.
|
||||
self.app.options.enable_beta_commands = True
|
||||
|
||||
# Get a shortcut to the network client
|
||||
self.network = self.app.client_manager.network
|
||||
|
||||
|
||||
class TestListNetworkSegment(TestNetworkSegment):
|
||||
_network = network_fakes.FakeNetwork.create_one_network()
|
||||
_network_segments = \
|
||||
network_fakes.FakeNetworkSegment.create_network_segments(count=3)
|
||||
|
||||
columns = (
|
||||
'ID',
|
||||
'Network',
|
||||
'Network Type',
|
||||
'Segment',
|
||||
)
|
||||
columns_long = columns + (
|
||||
'Physical Network',
|
||||
)
|
||||
|
||||
data = []
|
||||
for _network_segment in _network_segments:
|
||||
data.append((
|
||||
_network_segment.id,
|
||||
_network_segment.network_id,
|
||||
_network_segment.network_type,
|
||||
_network_segment.segmentation_id,
|
||||
))
|
||||
|
||||
data_long = []
|
||||
for _network_segment in _network_segments:
|
||||
data_long.append((
|
||||
_network_segment.id,
|
||||
_network_segment.network_id,
|
||||
_network_segment.network_type,
|
||||
_network_segment.segmentation_id,
|
||||
_network_segment.physical_network,
|
||||
))
|
||||
|
||||
def setUp(self):
|
||||
super(TestListNetworkSegment, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = network_segment.ListNetworkSegment(self.app, self.namespace)
|
||||
|
||||
self.network.find_network = mock.Mock(return_value=self._network)
|
||||
self.network.segments = mock.Mock(return_value=self._network_segments)
|
||||
|
||||
def test_list_no_option(self):
|
||||
arglist = []
|
||||
verifylist = [
|
||||
('long', False),
|
||||
('network', None),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.network.segments.assert_called_once_with()
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, list(data))
|
||||
|
||||
def test_list_no_beta_commands(self):
|
||||
self.app.options.enable_beta_commands = False
|
||||
parsed_args = self.check_parser(self.cmd, [], [])
|
||||
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||
parsed_args)
|
||||
|
||||
def test_list_long(self):
|
||||
arglist = [
|
||||
'--long',
|
||||
]
|
||||
verifylist = [
|
||||
('long', True),
|
||||
('network', None),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.network.segments.assert_called_once_with()
|
||||
self.assertEqual(self.columns_long, columns)
|
||||
self.assertEqual(self.data_long, list(data))
|
||||
|
||||
def test_list_network(self):
|
||||
arglist = [
|
||||
'--network',
|
||||
self._network.id,
|
||||
]
|
||||
verifylist = [
|
||||
('long', False),
|
||||
('network', self._network.id)
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.network.segments.assert_called_once_with(
|
||||
**{'network_id': self._network.id}
|
||||
)
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, list(data))
|
||||
|
||||
|
||||
class TestShowNetworkSegment(TestNetworkSegment):
|
||||
|
||||
# The network segment to show.
|
||||
_network_segment = \
|
||||
network_fakes.FakeNetworkSegment.create_one_network_segment()
|
||||
|
||||
columns = (
|
||||
'id',
|
||||
'network_id',
|
||||
'network_type',
|
||||
'physical_network',
|
||||
'segmentation_id',
|
||||
)
|
||||
|
||||
data = (
|
||||
_network_segment.id,
|
||||
_network_segment.network_id,
|
||||
_network_segment.network_type,
|
||||
_network_segment.physical_network,
|
||||
_network_segment.segmentation_id,
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(TestShowNetworkSegment, self).setUp()
|
||||
|
||||
self.network.find_segment = mock.Mock(
|
||||
return_value=self._network_segment
|
||||
)
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = network_segment.ShowNetworkSegment(self.app, self.namespace)
|
||||
|
||||
def test_show_no_options(self):
|
||||
# Missing required args should bail here
|
||||
self.assertRaises(tests_utils.ParserException, self.check_parser,
|
||||
self.cmd, [], [])
|
||||
|
||||
def test_show_no_beta_commands(self):
|
||||
arglist = [
|
||||
self._network_segment.id,
|
||||
]
|
||||
verifylist = [
|
||||
('network_segment', self._network_segment.id),
|
||||
]
|
||||
self.app.options.enable_beta_commands = False
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||
parsed_args)
|
||||
|
||||
def test_show_all_options(self):
|
||||
arglist = [
|
||||
self._network_segment.id,
|
||||
]
|
||||
verifylist = [
|
||||
('network_segment', self._network_segment.id),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.network.find_segment.assert_called_once_with(
|
||||
self._network_segment.id,
|
||||
ignore_missing=False
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
@ -60,6 +60,7 @@ class TestCommand(TestCase):
|
||||
self.fake_log = fakes.FakeLog()
|
||||
self.app = fakes.FakeApp(self.fake_stdout, self.fake_log)
|
||||
self.app.client_manager = fakes.FakeClientManager()
|
||||
self.app.options = fakes.FakeOptions()
|
||||
|
||||
def check_parser(self, cmd, args, verify_args):
|
||||
cmd_parser = cmd.get_parser('check_parser')
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- Add support for the ``network segment`` command object via the
|
||||
``network segment list`` and ``network segment show`` commands.
|
||||
These are beta commands and subject to change. Use global option
|
||||
``--enable-beta-commands`` to enable these commands.
|
||||
[Blueprint `routed-networks <https://blueprints.launchpad.net/neutron/+spec/routed-networks>`_]
|
@ -344,6 +344,9 @@ openstack.network.v2 =
|
||||
network_set = openstackclient.network.v2.network:SetNetwork
|
||||
network_show = openstackclient.network.v2.network:ShowNetwork
|
||||
|
||||
network_segment_list = openstackclient.network.v2.network_segment:ListNetworkSegment
|
||||
network_segment_show = openstackclient.network.v2.network_segment:ShowNetworkSegment
|
||||
|
||||
port_create = openstackclient.network.v2.port:CreatePort
|
||||
port_delete = openstackclient.network.v2.port:DeletePort
|
||||
port_list = openstackclient.network.v2.port:ListPort
|
||||
|
Loading…
Reference in New Issue
Block a user