Merge "Add network segment command object"

This commit is contained in:
Jenkins 2016-05-30 06:20:21 +00:00 committed by Gerrit Code Review
commit 37bc7bbf91
10 changed files with 506 additions and 0 deletions

View 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)

View File

@ -104,6 +104,7 @@ referring to both Compute and Volume quotas.
* ``mapping``: (**Identity**) a definition to translate identity provider attributes to Identity concepts * ``mapping``: (**Identity**) a definition to translate identity provider attributes to Identity concepts
* ``module``: (**Internal**) - installed Python modules in the OSC process * ``module``: (**Internal**) - installed Python modules in the OSC process
* ``network``: (**Compute**, **Network**) - a virtual network for connecting servers and other resources * ``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``: (**Object Storage**) a single file in the Object Storage
* ``object store account``: (**Object Storage**) owns a group of Object Storage resources * ``object store account``: (**Object Storage**) owns a group of Object Storage resources
* ``policy``: (**Identity**) determines authorization * ``policy``: (**Identity**) determines authorization

View 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)

View 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)

View File

@ -97,6 +97,11 @@ class FakeApp(object):
self.log = _log self.log = _log
class FakeOptions(object):
def __init__(self, **kwargs):
self.enable_beta_commands = False
class FakeClient(object): class FakeClient(object):
def __init__(self, **kwargs): def __init__(self, **kwargs):

View File

@ -275,6 +275,58 @@ class FakeNetwork(object):
return mock.MagicMock(side_effect=networks) 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): class FakePort(object):
"""Fake one or more ports.""" """Fake one or more ports."""

View 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)

View File

@ -60,6 +60,7 @@ class TestCommand(TestCase):
self.fake_log = fakes.FakeLog() self.fake_log = fakes.FakeLog()
self.app = fakes.FakeApp(self.fake_stdout, self.fake_log) self.app = fakes.FakeApp(self.fake_stdout, self.fake_log)
self.app.client_manager = fakes.FakeClientManager() self.app.client_manager = fakes.FakeClientManager()
self.app.options = fakes.FakeOptions()
def check_parser(self, cmd, args, verify_args): def check_parser(self, cmd, args, verify_args):
cmd_parser = cmd.get_parser('check_parser') cmd_parser = cmd.get_parser('check_parser')

View File

@ -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>`_]

View File

@ -344,6 +344,9 @@ openstack.network.v2 =
network_set = openstackclient.network.v2.network:SetNetwork network_set = openstackclient.network.v2.network:SetNetwork
network_show = openstackclient.network.v2.network:ShowNetwork 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_create = openstackclient.network.v2.port:CreatePort
port_delete = openstackclient.network.v2.port:DeletePort port_delete = openstackclient.network.v2.port:DeletePort
port_list = openstackclient.network.v2.port:ListPort port_list = openstackclient.network.v2.port:ListPort