From 5f6971909604bcc19dfea11f8d3f5409a9442ace Mon Sep 17 00:00:00 2001 From: Vieri <15050873171@163.com> Date: Tue, 9 Oct 2018 13:59:30 +0000 Subject: [PATCH 001/149] Don't quote {posargs} in tox.ini Quotes around {posargs} cause the entire string to be combined into one arg that gets passed to stestr. This prevents passing multiple args (e.g. '--concurrency=16 some-regex') Change-Id: I30687b4bcdacb167599b54b6f07e018363980fc7 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 76c62a262..032d3cc22 100644 --- a/tox.ini +++ b/tox.ini @@ -51,7 +51,7 @@ setenv = {[testenv]setenv} PYTHON=coverage run --source neutronclient --parallel-mode commands = - stestr run '{posargs}' + stestr run {posargs} coverage combine coverage html -d cover coverage xml -o cover/coverage.xml From 3de4353dcd75cf6563b1c9a33c516cb599147e95 Mon Sep 17 00:00:00 2001 From: Lucian Petrut Date: Fri, 2 Nov 2018 15:08:45 +0200 Subject: [PATCH 002/149] Fix api version handling, which completely breaks the client The neutron client does not work with recent openstacksdk versions (>=0.18.0): http://paste.openstack.org/raw/734040/ This change addresses a mismatch in the api version format. The neutron client passes a dict while the openstack sdk expects a string. Change-Id: I33c868f1c1e40d7673ba6651abedf3dfe0850660 Closes-Bug: #1801360 --- neutronclient/neutron/client.py | 2 +- neutronclient/shell.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/neutronclient/neutron/client.py b/neutronclient/neutron/client.py index 7961a4ca2..d859d815d 100644 --- a/neutronclient/neutron/client.py +++ b/neutronclient/neutron/client.py @@ -28,7 +28,7 @@ def make_client(instance): """Returns an neutron client.""" neutron_client = utils.get_client_class( API_NAME, - instance._api_version[API_NAME], + instance._api_version, API_VERSIONS, ) instance.initialize() diff --git a/neutronclient/shell.py b/neutronclient/shell.py index 4814c8118..6dced26cd 100644 --- a/neutronclient/shell.py +++ b/neutronclient/shell.py @@ -596,8 +596,6 @@ def initialize_app(self, argv): super(NeutronShell, self).initialize_app(argv) - self.api_version = {'network': self.api_version} - # If the user is not asking for help, make sure they # have given us auth. cmd_name = None From da7e2916bc0d871857ecd4f0296d8f20f6db3cb2 Mon Sep 17 00:00:00 2001 From: "huang.zhiping" Date: Sun, 21 Oct 2018 02:31:59 +0000 Subject: [PATCH 003/149] Update min tox version to 2.3.2 The commands used by constraints need at least tox 2.3.2. Update to reflect reality, which should help with local running of constraints targets. Change-Id: I22dec4ff510123520a2c035c3fa1c80f18ce4cdd Closes-Bug: #1801360 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 032d3cc22..7d5eecb23 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] # py3 first to avoid .testrepository incompatibility envlist = py35,py27,pypy,pep8 -minversion = 1.6 +minversion = 2.3.2 skipsdist = True [testenv] From cb1e24b1784fdee751a21d2b793b584538fefe58 Mon Sep 17 00:00:00 2001 From: mid_one Date: Mon, 12 Nov 2018 23:41:39 +0800 Subject: [PATCH 004/149] Fix docstring in method list_networks_on_dhcp_agent For function list_networks_on_dhcp_agent in the python-neutronclient\neutronclient\v2_0\client.py, the description is "Fetches a list of dhcp agents hosting a network". However this function fetches a list of networks hosted on a DHCP agent. Change the docstring. Change-Id: Ifa833d9a7ecab8ba55283d41d7a336d20cb578c3 Closes-Bug: 1802472 --- neutronclient/v2_0/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index cb84b9fc9..dddfba0db 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -1494,7 +1494,7 @@ def list_dhcp_agent_hosting_networks(self, network, **_params): params=_params) def list_networks_on_dhcp_agent(self, dhcp_agent, **_params): - """Fetches a list of dhcp agents hosting a network.""" + """Fetches a list of networks hosted on a DHCP agent.""" return self.get((self.agent_path + self.DHCP_NETS) % dhcp_agent, params=_params) From 1d45522a48bae0b454479e0f0a3876c773d7034e Mon Sep 17 00:00:00 2001 From: mid_one Date: Tue, 13 Nov 2018 00:35:37 +0800 Subject: [PATCH 005/149] Fix docstring in method list_routers_on_l3_agent For function list_routers_on_l3_agent in the python-neutronclient\neutronclient\v2_0\client.py, the description is "Fetches a list of L3 agents hosting a router". However this function fetches a list of routers hosted on a L3 agent. Change the docstring. Change-Id: Ia2156b5f6f016f338549a6536a0f31bf9e96c7cf Closes-Bug: 1802475 --- neutronclient/v2_0/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index cb84b9fc9..988a9ca22 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -1514,7 +1514,7 @@ def list_l3_agent_hosting_routers(self, router, **_params): params=_params) def list_routers_on_l3_agent(self, l3_agent, **_params): - """Fetches a list of L3 agents hosting a router.""" + """Fetches a list of routers hosted on an L3 agent.""" return self.get((self.agent_path + self.L3_ROUTERS) % l3_agent, params=_params) From b60283cd161300ab5805239c895b0d9a8d5eb511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Barr=C3=A9?= Date: Tue, 20 Feb 2018 15:12:31 +0100 Subject: [PATCH 006/149] Support of the boolean advertise_extra_routes This Boolean attribute is added to the Router Association resource (Neutron API, 'bgpvpn' and 'bgpvpn-routes-control' API extensions) in order to support routes control. This allow to propagate routes of subnets not directly connected to the router The corresponding code in networking-bgpvpn has already merged See https://blueprints.launchpad.net/bgpvpn/+spec/routes-control Change-Id: Icdd7f6592a9d657b6414645406f06b74b6f3bb11 Implements: blueprint routes-control --- .../networking_bgpvpn/router_association.py | 51 +++ .../unit/osc/v2/networking_bgpvpn/fakes.py | 42 ++- .../test_router_association.py | 291 ++++++++++++++++++ ...ort-routes-advertise-9356a38cf3e2fe5a.yaml | 6 + setup.cfg | 2 + 5 files changed, 391 insertions(+), 1 deletion(-) create mode 100644 neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py create mode 100644 releasenotes/notes/support-routes-advertise-9356a38cf3e2fe5a.yaml diff --git a/neutronclient/osc/v2/networking_bgpvpn/router_association.py b/neutronclient/osc/v2/networking_bgpvpn/router_association.py index 40664b6dc..c382f1621 100644 --- a/neutronclient/osc/v2/networking_bgpvpn/router_association.py +++ b/neutronclient/osc/v2/networking_bgpvpn/router_association.py @@ -24,8 +24,12 @@ DeleteBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ ListBgpvpnResAssoc +from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ + SetBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ ShowBgpvpnResAssoc +from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ + UnsetBgpvpnResAssoc class BgpvpnRouterAssoc(object): @@ -38,15 +42,62 @@ class BgpvpnRouterAssoc(object): ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), column_util.LIST_BOTH), + ('advertise_extra_routes', 'Advertise extra routes', + column_util.LIST_LONG_ONLY), ) _formatters = {} + def _get_common_parser(self, parser): + """Adds to parser arguments common to create, set and unset commands. + + :params ArgumentParser parser: argparse object contains all command's + arguments + """ + ADVERTISE_ROUTES = _("Routes will be advertised to the " + "BGP VPN%s") % ( + _(' (default)') if self._action == 'create' + else "") + NOT_ADVERTISE_ROUTES = _("Routes from the router will not be " + "advertised to the BGP VPN") + + group_advertise_extra_routes = parser.add_mutually_exclusive_group() + group_advertise_extra_routes.add_argument( + '--advertise_extra_routes', + action='store_true', + help=NOT_ADVERTISE_ROUTES if self._action == 'unset' + else ADVERTISE_ROUTES, + ) + group_advertise_extra_routes.add_argument( + '--no-advertise_extra_routes', + action='store_true', + help=ADVERTISE_ROUTES if self._action == 'unset' + else NOT_ADVERTISE_ROUTES, + ) + + def _args2body(self, _, args): + attrs = {} + + if args.advertise_extra_routes: + attrs['advertise_extra_routes'] = self._action != 'unset' + elif args.no_advertise_extra_routes: + attrs['advertise_extra_routes'] = self._action == 'unset' + + return {self._resource: attrs} + class CreateBgpvpnRouterAssoc(BgpvpnRouterAssoc, CreateBgpvpnResAssoc): _description = _("Create a BGP VPN router association") pass +class SetBgpvpnRouterAssoc(BgpvpnRouterAssoc, SetBgpvpnResAssoc): + _description = _("Set BGP VPN router association properties") + + +class UnsetBgpvpnRouterAssoc(BgpvpnRouterAssoc, UnsetBgpvpnResAssoc): + _description = _("Unset BGP VPN router association properties") + + class DeleteBgpvpnRouterAssoc(BgpvpnRouterAssoc, DeleteBgpvpnResAssoc): _description = _("Delete a BGP VPN router association(s) for a given BGP " "VPN") diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py index 21b9a762b..b3a538f5a 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py @@ -33,6 +33,12 @@ ShowBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ UnsetBgpvpnResAssoc +from neutronclient.osc.v2.networking_bgpvpn.router_association import\ + CreateBgpvpnRouterAssoc +from neutronclient.osc.v2.networking_bgpvpn.router_association import\ + SetBgpvpnRouterAssoc +from neutronclient.osc.v2.networking_bgpvpn.router_association import\ + ShowBgpvpnRouterAssoc from neutronclient.tests.unit.osc.v2 import fakes as test_fakes @@ -139,6 +145,35 @@ class ShowBgpvpnFakeResAssoc(BgpvpnFakeAssoc, ShowBgpvpnResAssoc): pass +class BgpvpnFakeRouterAssoc(object): + _assoc_res_name = 'fake_resource' + _resource = '%s_association' % _assoc_res_name + _resource_plural = '%ss' % _resource + + _attr_map = ( + ('id', 'ID', column_util.LIST_BOTH), + ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), + ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), + column_util.LIST_BOTH), + ('advertise_extra_routes', 'Advertise extra routes', + column_util.LIST_LONG_ONLY), + ) + _formatters = {} + + +class CreateBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, + CreateBgpvpnRouterAssoc): + pass + + +class SetBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, SetBgpvpnRouterAssoc): + pass + + +class ShowBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, ShowBgpvpnRouterAssoc): + pass + + class FakeResource(object): """Fake resource with minimal attributes.""" @@ -177,14 +212,19 @@ class FakeResAssoc(object): """Fake resource association with minimal attributes.""" @staticmethod - def create_one_resource_association(resource): + def create_one_resource_association(resource, attrs=None): """Create a fake resource association.""" + attrs = attrs or {} + res_assoc_attrs = { 'id': 'fake_association_id', 'tenant_id': resource['tenant_id'], 'fake_resource_id': resource['id'], } + + # Overwrite default attributes. + res_assoc_attrs.update(attrs) return copy.deepcopy(res_assoc_attrs) @staticmethod diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py new file mode 100644 index 000000000..fb17bdb67 --- /dev/null +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py @@ -0,0 +1,291 @@ +# Copyright (c) 2018 Orange SA. +# All Rights Reserved. +# +# 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 copy +import operator + +import mock +from osc_lib.tests.utils import ParserException +from osc_lib import utils as osc_utils +from osc_lib.utils import columns as column_util + +from neutronclient.tests.unit.osc.v2.networking_bgpvpn import fakes + + +columns_short = tuple(col for col, _, listing_mode + in fakes.BgpvpnFakeRouterAssoc._attr_map + if listing_mode in (column_util.LIST_BOTH, + column_util.LIST_SHORT_ONLY)) +columns_long = tuple(col for col, _, listing_mode + in fakes.BgpvpnFakeRouterAssoc._attr_map + if listing_mode in (column_util.LIST_BOTH, + column_util.LIST_LONG_ONLY)) +headers_short = tuple(head for _, head, listing_mode + in fakes.BgpvpnFakeRouterAssoc._attr_map + if listing_mode in (column_util.LIST_BOTH, + column_util.LIST_SHORT_ONLY)) +headers_long = tuple(head for _, head, listing_mode + in fakes.BgpvpnFakeRouterAssoc._attr_map + if listing_mode in (column_util.LIST_BOTH, + column_util.LIST_LONG_ONLY)) +sorted_attr_map = sorted(fakes.BgpvpnFakeRouterAssoc._attr_map, + key=operator.itemgetter(1)) +sorted_columns = tuple(col for col, _, _ in sorted_attr_map) +sorted_headers = tuple(head for _, head, _ in sorted_attr_map) + + +def _get_data(attrs, columns=sorted_columns): + return osc_utils.get_dict_properties( + attrs, columns, formatters=fakes.BgpvpnFakeAssoc._formatters) + + +class TestCreateRouterAssoc(fakes.TestNeutronClientBgpvpn): + def setUp(self): + super(TestCreateRouterAssoc, self).setUp() + self.cmd = fakes.CreateBgpvpnFakeRouterAssoc(self.app, self.namespace) + self.fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() + self.fake_router = fakes.FakeResource.create_one_resource() + + def _build_args(self, param=None): + arglist_base = [ + self.fake_bgpvpn['id'], + self.fake_router['id'], + '--project', self.fake_bgpvpn['tenant_id'] + ] + if param is not None: + if isinstance(param, list): + arglist_base.extend(param) + else: + arglist_base.append(param) + return arglist_base + + def _build_verify_list(self, param=None): + verifylist = [ + ('bgpvpn', self.fake_bgpvpn['id']), + ('resource', self.fake_router['id']), + ('project', self.fake_bgpvpn['tenant_id']) + ] + if param is not None: + verifylist.append(param) + return verifylist + + def _exec_create_router_association( + self, fake_res_assoc, arglist, verifylist): + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + cols, data = self.cmd.take_action(parsed_args) + + fake_res_assoc_call = copy.deepcopy(fake_res_assoc) + fake_res_assoc_call.pop('id') + + self.neutronclient.create_bgpvpn_fake_resource_assoc.\ + assert_called_once_with( + self.fake_bgpvpn['id'], + {fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc_call}) + return cols, data + + def test_create_router_association(self): + fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + self.fake_router) + + self.neutronclient.create_bgpvpn_fake_resource_assoc = mock.Mock( + return_value={ + fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc, + 'advertise_extra_routes': True}) + + arglist = self._build_args() + # advertise_extra_routes will be False since none + # of the mutually exclusive args present + verifylist = self._build_verify_list(('advertise_extra_routes', False)) + + self._exec_create_router_association( + fake_res_assoc, arglist, verifylist) + + def test_create_router_association_advertise(self): + fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + self.fake_router, + {'advertise_extra_routes': True}) + + self.neutronclient.create_bgpvpn_fake_resource_assoc = mock.Mock( + return_value={ + fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc}) + + arglist = self._build_args('--advertise_extra_routes') + verifylist = self._build_verify_list(('advertise_extra_routes', True)) + + cols, data = self._exec_create_router_association( + fake_res_assoc, arglist, verifylist) + self.assertEqual(sorted_headers, cols) + self.assertEqual(_get_data(fake_res_assoc), data) + + def test_create_router_association_no_advertise(self): + fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + self.fake_router, + {'advertise_extra_routes': False}) + + self.neutronclient.create_bgpvpn_fake_resource_assoc = mock.Mock( + return_value={ + fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc}) + + arglist = self._build_args('--no-advertise_extra_routes') + verifylist = self._build_verify_list(('advertise_extra_routes', False)) + + cols, data = self._exec_create_router_association( + fake_res_assoc, arglist, verifylist) + self.assertEqual(sorted_headers, cols) + self.assertEqual(_get_data(fake_res_assoc), data) + + def test_create_router_association_advertise_fault(self): + arglist = self._build_args( + ['--advertise_extra_routes', '--no-advertise_extra_routes']) + + try: + self._exec_create_router_association(None, arglist, None) + except ParserException as e: + self.assertEqual(format(e), 'Argument parse failed') + + def test_router_association_unknown_arg(self): + arglist = self._build_args('--unknown arg') + + try: + self._exec_create_router_association(None, arglist, None) + except ParserException as e: + self.assertEqual(format(e), 'Argument parse failed') + + +class TestSetRouterAssoc(fakes.TestNeutronClientBgpvpn): + + def setUp(self): + super(TestSetRouterAssoc, self).setUp() + self.cmd = fakes.SetBgpvpnFakeRouterAssoc(self.app, self.namespace) + self.fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() + self.fake_router = fakes.FakeResource.create_one_resource() + + def _build_args(self, fake_res_assoc, param=None): + arglist_base = [ + fake_res_assoc['id'], + self.fake_bgpvpn['id'] + ] + if param is not None: + if isinstance(param, list): + arglist_base.extend(param) + else: + arglist_base.append(param) + return arglist_base + + def _build_verify_list(self, fake_res_assoc, param=None): + verifylist = [ + ('resource_association_id', fake_res_assoc['id']), + ('bgpvpn', self.fake_bgpvpn['id']) + ] + if param is not None: + verifylist.append(param) + return verifylist + + def test_set_router_association_no_advertise(self): + fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + self.fake_router, + {'advertise_extra_routes': True}) + self.neutronclient.update_bgpvpn_fake_resource_assoc = mock.Mock() + + arglist = self._build_args( + fake_res_assoc, + '--no-advertise_extra_routes') + verifylist = [ + ('resource_association_id', fake_res_assoc['id']), + ('bgpvpn', self.fake_bgpvpn['id']), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + fake_res_assoc_call = copy.deepcopy(fake_res_assoc) + fake_res_assoc_call.pop('id') + + self.neutronclient.update_bgpvpn_fake_resource_assoc.\ + assert_called_once_with( + self.fake_bgpvpn['id'], + fake_res_assoc['id'], + { + fakes.BgpvpnFakeRouterAssoc._resource: { + 'advertise_extra_routes': False + } + }) + self.assertIsNone(result) + + def test_set_router_association_advertise(self): + fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + self.fake_router, + {'advertise_extra_routes': False}) + self.neutronclient.update_bgpvpn_fake_resource_assoc = mock.Mock() + + arglist = self._build_args( + fake_res_assoc, + '--advertise_extra_routes') + verifylist = [ + ('resource_association_id', fake_res_assoc['id']), + ('bgpvpn', self.fake_bgpvpn['id']), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + fake_res_assoc_call = copy.deepcopy(fake_res_assoc) + fake_res_assoc_call.pop('id') + + self.neutronclient.update_bgpvpn_fake_resource_assoc.\ + assert_called_once_with( + self.fake_bgpvpn['id'], + fake_res_assoc['id'], + { + fakes.BgpvpnFakeRouterAssoc._resource: { + 'advertise_extra_routes': True + } + }) + self.assertIsNone(result) + + +class TestShowRouterAssoc(fakes.TestNeutronClientBgpvpn): + def setUp(self): + super(TestShowRouterAssoc, self).setUp() + self.cmd = fakes.ShowBgpvpnFakeRouterAssoc(self.app, self.namespace) + + def test_show_router_association(self): + fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() + fake_res = fakes.FakeResource.create_one_resource() + fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_res, + {'advertise_extra_routes': True}) + self.neutronclient.show_bgpvpn_fake_resource_assoc = mock.Mock( + return_value={fakes.BgpvpnFakeAssoc._resource: fake_res_assoc}) + arglist = [ + fake_res_assoc['id'], + fake_bgpvpn['id'], + ] + verifylist = [ + ('resource_association_id', fake_res_assoc['id']), + ('bgpvpn', fake_bgpvpn['id']), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + headers, data = self.cmd.take_action(parsed_args) + + self.neutronclient.show_bgpvpn_fake_resource_assoc.\ + assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) + self.assertEqual(sorted_headers, headers) + self.assertEqual(data, _get_data(fake_res_assoc)) diff --git a/releasenotes/notes/support-routes-advertise-9356a38cf3e2fe5a.yaml b/releasenotes/notes/support-routes-advertise-9356a38cf3e2fe5a.yaml new file mode 100644 index 000000000..f1dbd5ed0 --- /dev/null +++ b/releasenotes/notes/support-routes-advertise-9356a38cf3e2fe5a.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Add optional flag to control the advertisement in BGPVPNs + of the routes defined on a Router resource + (``bgpvpn-routes-control`` API extension). diff --git a/setup.cfg b/setup.cfg index 41857c7a6..d9938af5a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -123,7 +123,9 @@ openstack.neutronclient.v2 = bgpvpn_router_association_create = neutronclient.osc.v2.networking_bgpvpn.router_association:CreateBgpvpnRouterAssoc bgpvpn_router_association_delete = neutronclient.osc.v2.networking_bgpvpn.router_association:DeleteBgpvpnRouterAssoc bgpvpn_router_association_list = neutronclient.osc.v2.networking_bgpvpn.router_association:ListBgpvpnRouterAssoc + bgpvpn_router_association_set = neutronclient.osc.v2.networking_bgpvpn.router_association:SetBgpvpnRouterAssoc bgpvpn_router_association_show = neutronclient.osc.v2.networking_bgpvpn.router_association:ShowBgpvpnRouterAssoc + bgpvpn_router_association_unset = neutronclient.osc.v2.networking_bgpvpn.router_association:UnsetBgpvpnRouterAssoc bgpvpn_port_association_create = neutronclient.osc.v2.networking_bgpvpn.port_association:CreateBgpvpnPortAssoc bgpvpn_port_association_set = neutronclient.osc.v2.networking_bgpvpn.port_association:SetBgpvpnPortAssoc bgpvpn_port_association_unset = neutronclient.osc.v2.networking_bgpvpn.port_association:UnsetBgpvpnPortAssoc From c17db9f29542c38709d7e026aefc44ac1134bbcd Mon Sep 17 00:00:00 2001 From: qingszhao Date: Fri, 30 Nov 2018 07:07:33 +0000 Subject: [PATCH 007/149] Add Python 3.6 classifier to setup.cfg Change-Id: Id7864c23b73b5f2b265ba04d24d01540b326d105 --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index d9938af5a..c4f1c9323 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,6 +18,7 @@ classifier = Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 [files] packages = From 1e2e98b51983197bf8faf3c2a40c3d13c067b1d1 Mon Sep 17 00:00:00 2001 From: sunjia Date: Mon, 3 Dec 2018 21:56:09 -0500 Subject: [PATCH 008/149] Change openstack-dev to openstack-discuss Mailinglists have been updated. Openstack-discuss replaces openstack-dev. Change-Id: I4be1b808bee0a4f9feaea5b203317d04037e3dfd --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index d9938af5a..cf5567e73 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,7 +4,7 @@ summary = CLI and Client Library for OpenStack Networking description-file = README.rst author = OpenStack Networking Project -author-email = openstack-dev@lists.openstack.org +author-email = openstack-discuss@lists.openstack.org home-page = https://docs.openstack.org/python-neutronclient/latest/ classifier = Environment :: OpenStack From 9cbdfb2181f1d0acb303214deeee781f57ba48d9 Mon Sep 17 00:00:00 2001 From: mid_one Date: Tue, 4 Dec 2018 01:43:11 +0800 Subject: [PATCH 009/149] Add support for querying quotas with usage The neutron HTTP API supports issuing a GET call on /v2.0/quotas/{project_id}/details.json in order to obtain quotas with usage information for a given tenant. However, this capability is not currently exposed in the python-neutronclient code. Add path: quota_details_path Add function show_quota_details Closes-Bug: #1808451 Related-Bug: #1599488 Change-Id: Ia02172f62b9d9915273021627b0feb52a4f376da --- neutronclient/v2_0/client.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index 2c0d88ee8..560b531d0 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -501,6 +501,7 @@ class Client(ClientBase): quotas_path = "/quotas" quota_path = "/quotas/%s" quota_default_path = "/quotas/%s/default" + quota_details_path = "/quotas/%s/details.json" extensions_path = "/extensions" extension_path = "/extensions/%s" routers_path = "/routers" @@ -753,6 +754,13 @@ def show_quota(self, project_id, **_params): """Fetch information of a certain project's quotas.""" return self.get(self.quota_path % (project_id), params=_params) + @debtcollector.renames.renamed_kwarg( + 'tenant_id', 'project_id', replace=True) + def show_quota_details(self, project_id, **_params): + """Fetch information of a certain project's quota details.""" + return self.get(self.quota_details_path % (project_id), + params=_params) + @debtcollector.renames.renamed_kwarg( 'tenant_id', 'project_id', replace=True) def show_quota_default(self, project_id, **_params): From aa19ab71efe0af94b56440095f712905b6ed8b8d Mon Sep 17 00:00:00 2001 From: chenlx Date: Mon, 17 Dec 2018 19:33:05 +0800 Subject: [PATCH 010/149] Update mailinglist from dev to discuss openstack-dev was decomissioned this night in https://review.openstack.org/621258 Update openstack-dev to openstack-discuss Change-Id: Ib88759901998ebec8a3e3817d1148fa70323cee5 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index c4f1c9323..b5a837b25 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,7 +4,7 @@ summary = CLI and Client Library for OpenStack Networking description-file = README.rst author = OpenStack Networking Project -author-email = openstack-dev@lists.openstack.org +author-email = openstack-discuss@lists.openstack.org home-page = https://docs.openstack.org/python-neutronclient/latest/ classifier = Environment :: OpenStack From f99c63f98ae8f4c43a152774dab8c9f9741de360 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Thu, 31 Jan 2019 10:42:21 +0900 Subject: [PATCH 011/149] Update hacking version to 1.1 Older hacking depends on pep8, but pep8 module is replaced by pycodestyle. This can be resolved by updating hackinng version. This commit also fixes E117 (over-indented) and W605 (invalid escape sequence) warnings. pep8 is dropped from lower-constraints.txt as it is no longer used. Change-Id: I3a8e3b0dedf9422e4db02b525b333d12ce012a95 --- lower-constraints.txt | 3 +- neutronclient/neutron/v2_0/lb/v2/l7rule.py | 52 +++++++++---------- neutronclient/neutron/v2_0/lb/v2/member.py | 15 +++--- .../osc/v2/sfc/sfc_flow_classifier.py | 28 +++++----- .../functional/core/test_readonly_neutron.py | 2 +- test-requirements.txt | 2 +- 6 files changed, 50 insertions(+), 52 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index 117d04b2e..b37c137a0 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -25,7 +25,7 @@ flake8==2.5.5 future==0.16.0 futurist==1.2.0 greenlet==0.4.10 -hacking==0.12.0 +hacking==1.1.0 idna==2.6 imagesize==0.7.1 iso8601==0.1.11 @@ -68,7 +68,6 @@ paramiko==2.0.0 Paste==2.0.2 PasteDeploy==1.5.0 pbr==2.0.0 -pep8==1.5.7 pika-pool==0.1.3 pika==0.10.0 positional==1.2.1 diff --git a/neutronclient/neutron/v2_0/lb/v2/l7rule.py b/neutronclient/neutron/v2_0/lb/v2/l7rule.py index 1286559f2..3c468cabf 100644 --- a/neutronclient/neutron/v2_0/lb/v2/l7rule.py +++ b/neutronclient/neutron/v2_0/lb/v2/l7rule.py @@ -39,32 +39,32 @@ def add_known_arguments(self, parser): def _add_common_args(parser, is_create=True): - parser.add_argument( - '--type', - required=is_create, - type=utils.convert_to_uppercase, - choices=['HOST_NAME', 'PATH', 'FILE_TYPE', 'HEADER', 'COOKIE'], - help=_('Rule type.')) - parser.add_argument( - '--compare-type', - required=is_create, - type=utils.convert_to_uppercase, - choices=['REGEX', 'STARTS_WITH', 'ENDS_WITH', - 'CONTAINS', 'EQUAL_TO'], - help=_('Rule compare type.')) - parser.add_argument( - '--invert-compare', - dest='invert', - action='store_true', - help=_('Invert the compare type.')) - parser.add_argument( - '--key', - help=_('Key to compare.' - ' Relevant for HEADER and COOKIE types only.')) - parser.add_argument( - '--value', - required=is_create, - help=_('Value to compare.')) + parser.add_argument( + '--type', + required=is_create, + type=utils.convert_to_uppercase, + choices=['HOST_NAME', 'PATH', 'FILE_TYPE', 'HEADER', 'COOKIE'], + help=_('Rule type.')) + parser.add_argument( + '--compare-type', + required=is_create, + type=utils.convert_to_uppercase, + choices=['REGEX', 'STARTS_WITH', 'ENDS_WITH', + 'CONTAINS', 'EQUAL_TO'], + help=_('Rule compare type.')) + parser.add_argument( + '--invert-compare', + dest='invert', + action='store_true', + help=_('Invert the compare type.')) + parser.add_argument( + '--key', + help=_('Key to compare.' + ' Relevant for HEADER and COOKIE types only.')) + parser.add_argument( + '--value', + required=is_create, + help=_('Value to compare.')) def _common_args2body(client, parsed_args, is_create=True): diff --git a/neutronclient/neutron/v2_0/lb/v2/member.py b/neutronclient/neutron/v2_0/lb/v2/member.py index 3fec7760d..ee3c090a9 100644 --- a/neutronclient/neutron/v2_0/lb/v2/member.py +++ b/neutronclient/neutron/v2_0/lb/v2/member.py @@ -38,17 +38,16 @@ def add_known_arguments(self, parser): def _add_common_args(parser): - parser.add_argument( - '--name', - help=_('Name of the member.')) - parser.add_argument( - '--weight', - help=_('Weight of the member in the pool (default:1, [0..256]).')) + parser.add_argument( + '--name', + help=_('Name of the member.')) + parser.add_argument( + '--weight', + help=_('Weight of the member in the pool (default:1, [0..256]).')) def _parse_common_args(body, parsed_args): - neutronV20.update_dict(parsed_args, body, - ['weight', 'name']) + neutronV20.update_dict(parsed_args, body, ['weight', 'name']) class ListMember(LbaasMemberMixin, neutronV20.ListCommand): diff --git a/neutronclient/osc/v2/sfc/sfc_flow_classifier.py b/neutronclient/osc/v2/sfc/sfc_flow_classifier.py index ad35aa6bd..d223674c4 100755 --- a/neutronclient/osc/v2/sfc/sfc_flow_classifier.py +++ b/neutronclient/osc/v2/sfc/sfc_flow_classifier.py @@ -300,20 +300,20 @@ def _get_attrs(client_manager, attrs, parsed_args): def _fill_protocol_port_info(attrs, port_type, port_val): - min_port, sep, max_port = port_val.partition(":") - if not min_port: - msg = ("Invalid port value '%s', expected format is " - "min-port:max-port or min-port.") - raise argparse.ArgumentTypeError(msg % port_val) - if not max_port: - max_port = min_port - try: - attrs[port_type + '_port_range_min'] = int(min_port) - attrs[port_type + '_port_range_max'] = int(max_port) - except ValueError: - message = (_("Protocol port value %s must be an integer " - "or integer:integer.") % port_val) - raise nc_exc.CommandError(message=message) + min_port, sep, max_port = port_val.partition(":") + if not min_port: + msg = ("Invalid port value '%s', expected format is " + "min-port:max-port or min-port.") + raise argparse.ArgumentTypeError(msg % port_val) + if not max_port: + max_port = min_port + try: + attrs[port_type + '_port_range_min'] = int(min_port) + attrs[port_type + '_port_range_max'] = int(max_port) + except ValueError: + message = (_("Protocol port value %s must be an integer " + "or integer:integer.") % port_val) + raise nc_exc.CommandError(message=message) def _get_id(client, id_or_name, resource): diff --git a/neutronclient/tests/functional/core/test_readonly_neutron.py b/neutronclient/tests/functional/core/test_readonly_neutron.py index 9429c9a4c..20e1484e5 100644 --- a/neutronclient/tests/functional/core/test_readonly_neutron.py +++ b/neutronclient/tests/functional/core/test_readonly_neutron.py @@ -110,7 +110,7 @@ def test_neutron_help(self): commands = [] cmds_start = lines.index('Commands for API v2.0:') - command_pattern = re.compile('^ {2}([a-z0-9\-\_]+)') + command_pattern = re.compile(r'^ {2}([a-z0-9\-\_]+)') for line in lines[cmds_start:]: match = command_pattern.match(line) if match: diff --git a/test-requirements.txt b/test-requirements.txt index 11865b828..dabdb0e02 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,7 +1,7 @@ # The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 +hacking>=1.1.0 # Apache-2.0 bandit>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 From c2ac394a8880000bca2109985760347e8df7d76d Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Thu, 31 Jan 2019 10:46:33 +0900 Subject: [PATCH 012/149] Remove basepython from [flake8] section basepython is not a valid option for flake8 and it is complaned when running tox -e pep8. It seems to have been added accidentally. Change-Id: Ia5d093bab0c175b2693e7ae47a6bc29c1d44db36 --- tox.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/tox.ini b/tox.ini index 7d5eecb23..cae97f1cb 100644 --- a/tox.ini +++ b/tox.ini @@ -68,7 +68,6 @@ deps = -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] -basepython = python3 show-source = true exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,tools import-order-style = pep8 From b4a0e27ec61c47f2d14983d3767f778ef5545402 Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Wed, 20 Feb 2019 15:38:59 -0500 Subject: [PATCH 013/149] add python 3.7 unit test job This is a mechanically generated patch to add a unit test job running under Python 3.7. See ML discussion here [1] for context. [1] http://lists.openstack.org/pipermail/openstack-dev/2018-October/135626.html Change-Id: Icb961e81e0d99ab1912f75b1ce83ed371fc1107c Story: #2004073 --- .zuul.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.zuul.yaml b/.zuul.yaml index 7fde244be..d38182be9 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -5,6 +5,7 @@ - openstack-python-jobs - openstack-python35-jobs - openstack-python36-jobs + - openstack-python37-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing From 1f35b8f25cb328ede6aea7933ecd33a1cd713ba8 Mon Sep 17 00:00:00 2001 From: "cao.yuan" Date: Mon, 25 Feb 2019 00:55:22 +0800 Subject: [PATCH 014/149] Update json module to jsonutils oslo project provide jsonutils, and neutronclient use it in many place[1], this PS to update the remained json module to oslo jsonutils for consistency. [1]: https://github.com/openstack/python-neutronclient/search?utf8=%E2%9C%93&q=jsonutils&type= Change-Id: Ic4639628c8910b88a14b0fe8f37638bb4f9474be --- neutronclient/client.py | 11 ++++------- neutronclient/tests/unit/test_cli20.py | 8 ++++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/neutronclient/client.py b/neutronclient/client.py index 2482eb434..c5f467668 100644 --- a/neutronclient/client.py +++ b/neutronclient/client.py @@ -14,16 +14,13 @@ # under the License. # -try: - import json -except ImportError: - import simplejson as json import logging import os import debtcollector.renames from keystoneauth1 import access from keystoneauth1 import adapter +from oslo_serialization import jsonutils from oslo_utils import importutils import requests @@ -239,14 +236,14 @@ def _authenticate_keystone(self): token_url = self.auth_url + "/tokens" resp, resp_body = self._cs_request(token_url, "POST", - body=json.dumps(body), + body=jsonutils.dumps(body), content_type="application/json", allow_redirects=True) if resp.status_code != 200: raise exceptions.Unauthorized(message=resp_body) if resp_body: try: - resp_body = json.loads(resp_body) + resp_body = jsonutils.loads(resp_body) except ValueError: pass else: @@ -282,7 +279,7 @@ def _get_endpoint_url(self): self.authenticate() return self.endpoint_url - body = json.loads(body) + body = jsonutils.loads(body) for endpoint in body.get('endpoints', []): if (endpoint['type'] == 'network' and endpoint.get('region') == self.region_name): diff --git a/neutronclient/tests/unit/test_cli20.py b/neutronclient/tests/unit/test_cli20.py index cfba9fafd..3a8bb4719 100644 --- a/neutronclient/tests/unit/test_cli20.py +++ b/neutronclient/tests/unit/test_cli20.py @@ -16,10 +16,10 @@ import contextlib import itertools -import json import sys import mock +from oslo_serialization import jsonutils from oslo_utils import encodeutils from oslotest import base import requests @@ -1153,7 +1153,7 @@ def test_create_resource_table(self): def test_create_resource_json(self): self._test_create_resource_with_formatter('json') - data = json.loads(self.fake_stdout.make_string()) + data = jsonutils.loads(self.fake_stdout.make_string()) self.assertEqual('myname', data['name']) self.assertEqual('myid', data['id']) @@ -1178,7 +1178,7 @@ def test_show_resource_table(self): def test_show_resource_json(self): self._test_show_resource_with_formatter('json') - data = json.loads(''.join(self.fake_stdout.content)) + data = jsonutils.loads(''.join(self.fake_stdout.content)) self.assertEqual('myname', data['name']) self.assertEqual('myid', data['id']) @@ -1206,7 +1206,7 @@ def test_list_resources_table(self): def test_list_resources_json(self): self._test_list_resources_with_formatter('json') - data = json.loads(''.join(self.fake_stdout.content)) + data = jsonutils.loads(''.join(self.fake_stdout.content)) self.assertEqual(['myid1', 'myid2'], [d['id'] for d in data]) def test_list_resources_yaml(self): From 680b417111dbbda9e318700286c4efd9055f1af3 Mon Sep 17 00:00:00 2001 From: Ryan Tidwell Date: Tue, 5 Feb 2019 10:59:09 -0600 Subject: [PATCH 015/149] Add subnet onboard CLI This is the implementation of the "onboard network subnets" CLI. This enables the subnet onboard feature of neutron to be driven via CLI. Depends-On: https://review.openstack.org/348080 Change-Id: Ic637ed689b0d3806d2c33faa419c3a98a310effa Implements: blueprint subnet-onboard --- doc/source/cli/osc/v2/subnet-onboard.rst | 17 ++++++ .../osc/v2/subnet_onboard/__init__.py | 0 .../osc/v2/subnet_onboard/subnet_onboard.py | 59 +++++++++++++++++++ .../unit/osc/v2/subnet_onboard/__init__.py | 0 .../test_network_onboard_subnets.py | 54 +++++++++++++++++ neutronclient/v2_0/client.py | 6 ++ .../add-subnet-onboard-e60772bc4984f698.yaml | 5 ++ setup.cfg | 2 + 8 files changed, 143 insertions(+) create mode 100644 doc/source/cli/osc/v2/subnet-onboard.rst create mode 100644 neutronclient/osc/v2/subnet_onboard/__init__.py create mode 100644 neutronclient/osc/v2/subnet_onboard/subnet_onboard.py create mode 100644 neutronclient/tests/unit/osc/v2/subnet_onboard/__init__.py create mode 100644 neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py create mode 100644 releasenotes/notes/add-subnet-onboard-e60772bc4984f698.yaml diff --git a/doc/source/cli/osc/v2/subnet-onboard.rst b/doc/source/cli/osc/v2/subnet-onboard.rst new file mode 100644 index 000000000..006970372 --- /dev/null +++ b/doc/source/cli/osc/v2/subnet-onboard.rst @@ -0,0 +1,17 @@ +======================= +network onboard subnets +======================= + +**network onboard subnets** enables a subnet to be adopted or +"onboarded" into an existing subnet pool. The CIDR of the subnet +is checked for uniqueness across any applicable address scopes +and all subnets allocated from the target subnet pool. Once +onboarded, the subnet CIDR is added to the prefix list of the +subnet pool and the subnet appears as though it has been allocated +from the subnet pool. The subnet also begins participating in the +applicable address scope if the subnet pool belongs to one. + +Network v2 + +.. autoprogram-cliff:: openstack.neutronclient.v2 + :command: network onboard subnets diff --git a/neutronclient/osc/v2/subnet_onboard/__init__.py b/neutronclient/osc/v2/subnet_onboard/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neutronclient/osc/v2/subnet_onboard/subnet_onboard.py b/neutronclient/osc/v2/subnet_onboard/subnet_onboard.py new file mode 100644 index 000000000..10c6ab4c2 --- /dev/null +++ b/neutronclient/osc/v2/subnet_onboard/subnet_onboard.py @@ -0,0 +1,59 @@ +# Copyright (c) 2019 SUSE Linux Products GmbH +# All Rights Reserved +# +# 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. +# + +"""Subnet onboard action implementation""" +import logging + +from osc_lib.command import command +from osc_lib import exceptions + +from neutronclient._i18n import _ + +LOG = logging.getLogger(__name__) + + +class NetworkOnboardSubnets(command.Command): + """Onboard network subnets into a subnet pool""" + + def get_parser(self, prog_name): + parser = super(NetworkOnboardSubnets, self).get_parser(prog_name) + parser.add_argument( + 'network', + metavar="", + help=_("Onboard all subnets associated with this network") + ) + parser.add_argument( + 'subnetpool', + metavar="", + help=_("Target subnet pool for onboarding subnets") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + subnetpool_id = _get_id(client, parsed_args.subnetpool, 'subnetpool') + network_id = _get_id(client, parsed_args.network, 'network') + body = {'network_id': network_id} + try: + client.onboard_network_subnets(subnetpool_id, body) + except Exception as e: + msg = (_("Failed to onboard subnets for network '%(n)s': %(e)s") + % {'n': parsed_args.network, 'e': e}) + raise exceptions.CommandError(msg) + + +def _get_id(client, id_or_name, resource): + return client.find_resource(resource, str(id_or_name))['id'] diff --git a/neutronclient/tests/unit/osc/v2/subnet_onboard/__init__.py b/neutronclient/tests/unit/osc/v2/subnet_onboard/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py b/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py new file mode 100644 index 000000000..efd3d1d11 --- /dev/null +++ b/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py @@ -0,0 +1,54 @@ +# Copyright (c) 2019 SUSE Linux Products GmbH +# All Rights Reserved +# +# 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 neutronclient.osc.v2.subnet_onboard import subnet_onboard +from neutronclient.tests.unit.osc.v2 import fakes as test_fakes + + +def _get_id(client, id_or_name, resource): + return id_or_name + + +class TestNetworkOnboardSubnets(test_fakes.TestNeutronClientOSCV2): + + def setUp(self): + super(TestNetworkOnboardSubnets, self).setUp() + mock.patch( + 'neutronclient.osc.v2.subnet_onboard.subnet_onboard._get_id', + new=_get_id).start() + + self.network_id = 'my_network_id' + self.subnetpool_id = 'my_subnetpool_id' + + # Get the command object to test + self.cmd = subnet_onboard.NetworkOnboardSubnets(self.app, + self.namespace) + + def test_options(self): + arglist = [ + self.network_id, + self.subnetpool_id + ] + verifylist = [ + ('network', self.network_id), + ('subnetpool', self.subnetpool_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.neutronclient.onboard_network_subnets.assert_called_once_with( + self.subnetpool_id, {'network_id': self.network_id}) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index 560b531d0..ed8dbd49d 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -494,6 +494,7 @@ class Client(ClientBase): port_path = "/ports/%s" subnets_path = "/subnets" subnet_path = "/subnets/%s" + onboard_network_subnets_path = "/subnetpools/%s/onboard_network_subnets" subnetpools_path = "/subnetpools" subnetpool_path = "/subnetpools/%s" address_scopes_path = "/address-scopes" @@ -2370,6 +2371,11 @@ def list_network_loggable_resources(self, retrieve_all=True, **_params): return self.list('loggable_resources', self.network_loggables_path, retrieve_all, **_params) + def onboard_network_subnets(self, subnetpool, body=None): + """Onboard the specified network's subnets into a subnet pool.""" + return self.put(self.onboard_network_subnets_path % (subnetpool), + body=body) + def __init__(self, **kwargs): """Initialize a new client for the Neutron v2.0 API.""" super(Client, self).__init__(**kwargs) diff --git a/releasenotes/notes/add-subnet-onboard-e60772bc4984f698.yaml b/releasenotes/notes/add-subnet-onboard-e60772bc4984f698.yaml new file mode 100644 index 000000000..358fdf006 --- /dev/null +++ b/releasenotes/notes/add-subnet-onboard-e60772bc4984f698.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Add ``network onboard subnets`` OSC command to enable subnet onboard support from the CLI + [Blueprint `subnet-onboard `_] diff --git a/setup.cfg b/setup.cfg index b5a837b25..0262adf9e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -171,6 +171,8 @@ openstack.neutronclient.v2 = vpn_ipsec_site_connection_set = neutronclient.osc.v2.vpnaas.ipsec_site_connection:SetIPsecSiteConnection vpn_ipsec_site_connection_show = neutronclient.osc.v2.vpnaas.ipsec_site_connection:ShowIPsecSiteConnection + network_onboard_subnets = neutronclient.osc.v2.subnet_onboard.subnet_onboard:NetworkOnboardSubnets + neutron.cli.v2 = bash-completion = neutronclient.shell:BashCompletionCommand From ca875adf388599d2cd0a30c15a2c8cd7c52efe8f Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Mon, 18 Mar 2019 14:53:55 +0000 Subject: [PATCH 016/149] Update master for stable/stein Add file to the reno documentation build to show release notes for stable/stein. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/stein. Change-Id: I9add4f457af409830f3faff0af2661e0b3909b40 Sem-Ver: feature --- releasenotes/source/index.rst | 1 + releasenotes/source/stein.rst | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/stein.rst diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index f73e97659..446a2a869 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + stein rocky queens pike diff --git a/releasenotes/source/stein.rst b/releasenotes/source/stein.rst new file mode 100644 index 000000000..efaceb667 --- /dev/null +++ b/releasenotes/source/stein.rst @@ -0,0 +1,6 @@ +=================================== + Stein Series Release Notes +=================================== + +.. release-notes:: + :branch: stable/stein From d572f2cdd209b4b4ad114a194ed3d75b6e71e9f2 Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Sun, 24 Mar 2019 20:35:53 +0000 Subject: [PATCH 017/149] Replace openstack.org git:// URLs with https:// This is a mechanically generated change to replace openstack.org git:// URLs with https:// equivalents. This is in aid of a planned future move of the git hosting infrastructure to a self-hosted instance of gitea (https://gitea.io), which does not support the git wire protocol at this stage. This update should result in no functional change. For more information see the thread at http://lists.openstack.org/pipermail/openstack-discuss/2019-March/003825.html Change-Id: I15a69bcf6d51bfb1d5ade8f5119bb77bb2387f77 --- neutronclient/tests/functional/hooks/fwaas | 2 +- neutronclient/tests/functional/hooks/vpnaas | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/neutronclient/tests/functional/hooks/fwaas b/neutronclient/tests/functional/hooks/fwaas index 8f53b16a0..5292897ce 100644 --- a/neutronclient/tests/functional/hooks/fwaas +++ b/neutronclient/tests/functional/hooks/fwaas @@ -1,2 +1,2 @@ -enable_plugin neutron-fwaas git://git.openstack.org/openstack/neutron-fwaas +enable_plugin neutron-fwaas https://git.openstack.org/openstack/neutron-fwaas enable_service q-fwaas diff --git a/neutronclient/tests/functional/hooks/vpnaas b/neutronclient/tests/functional/hooks/vpnaas index 11cecb91f..b121a6f0e 100644 --- a/neutronclient/tests/functional/hooks/vpnaas +++ b/neutronclient/tests/functional/hooks/vpnaas @@ -1 +1 @@ -enable_plugin neutron-vpnaas git://git.openstack.org/openstack/neutron-vpnaas +enable_plugin neutron-vpnaas https://git.openstack.org/openstack/neutron-vpnaas From da62ba30297d78dbdcf6c454a3c539cf91bd2d16 Mon Sep 17 00:00:00 2001 From: Ghanshyam Mann Date: Mon, 15 Apr 2019 02:30:04 +0000 Subject: [PATCH 018/149] Dropping the py35 testing All the integration testing has been moved to Bionic now[1] and py3.5 is not tested runtime for Train or stable/stein[2]. As per below ML thread, we are good to drop the py35 testing now: http://lists.openstack.org/pipermail/openstack-discuss/2019-April/005097.html [1] http://lists.openstack.org/pipermail/openstack-discuss/2019-April/004647.html [2] https://governance.openstack.org/tc/reference/runtimes/stein.html https://governance.openstack.org/tc/reference/runtimes/train.html Change-Id: I612c7c40e07f23afa920c92bf4b51b278282dd9d --- .zuul.yaml | 1 - setup.cfg | 1 - tox.ini | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index d38182be9..db6d10cd9 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -3,7 +3,6 @@ - openstack-cover-jobs - openstack-lower-constraints-jobs - openstack-python-jobs - - openstack-python35-jobs - openstack-python36-jobs - openstack-python37-jobs - publish-openstack-docs-pti diff --git a/setup.cfg b/setup.cfg index 0262adf9e..867678087 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,7 +17,6 @@ classifier = Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 [files] diff --git a/tox.ini b/tox.ini index cae97f1cb..d4ba1b5f6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] # py3 first to avoid .testrepository incompatibility -envlist = py35,py27,pypy,pep8 +envlist = py36,py27,pypy,pep8 minversion = 2.3.2 skipsdist = True From b62a1cd1a469c9fbbf188646b8ecc44aa9a0f463 Mon Sep 17 00:00:00 2001 From: OpenDev Sysadmins Date: Fri, 19 Apr 2019 19:44:46 +0000 Subject: [PATCH 019/149] OpenDev Migration Patch This commit was bulk generated and pushed by the OpenDev sysadmins as a part of the Git hosting and code review systems migration detailed in these mailing list posts: http://lists.openstack.org/pipermail/openstack-discuss/2019-March/003603.html http://lists.openstack.org/pipermail/openstack-discuss/2019-April/004920.html Attempts have been made to correct repository namespaces and hostnames based on simple pattern matching, but it's possible some were updated incorrectly or missed entirely. Please reach out to us via the contact information listed at https://opendev.org/ with any questions you may have. --- .gitreview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitreview b/.gitreview index 994b07a43..faf5d1f5b 100644 --- a/.gitreview +++ b/.gitreview @@ -1,4 +1,4 @@ [gerrit] -host=review.openstack.org +host=review.opendev.org port=29418 project=openstack/python-neutronclient.git From 9a91b4ad38ac5ff3ab2e2cdc0dd63727f0e90691 Mon Sep 17 00:00:00 2001 From: jacky06 Date: Tue, 23 Apr 2019 13:44:39 +0800 Subject: [PATCH 020/149] Replace git.openstack.org URLs with opendev.org URLs Change-Id: I3cc418bd8219a3d4f3ab5c018adf06b66ef36b46 --- README.rst | 2 +- doc/source/contributor/transition_to_osc.rst | 10 +++++----- .../neutron/v2_0/qos/minimum_bandwidth_rule.py | 2 +- neutronclient/tests/functional/hooks/fwaas | 2 +- neutronclient/tests/functional/hooks/vpnaas | 2 +- tox.ini | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index cec75c908..6f57c698c 100644 --- a/README.rst +++ b/README.rst @@ -32,6 +32,6 @@ provides a Python API (the ``neutronclient`` module) and a command-line tool .. _Launchpad project: https://launchpad.net/python-neutronclient .. _Blueprints: https://blueprints.launchpad.net/python-neutronclient .. _Bugs: https://bugs.launchpad.net/python-neutronclient -.. _Source: https://git.openstack.org/cgit/openstack/python-neutronclient +.. _Source: https://opendev.org/openstack/python-neutronclient .. _Developer's Guide: http://docs.openstack.org/infra/manual/developers.html .. _Release Notes: https://docs.openstack.org/releasenotes/python-neutronclient diff --git a/doc/source/contributor/transition_to_osc.rst b/doc/source/contributor/transition_to_osc.rst index d64658d06..b745d2f0c 100644 --- a/doc/source/contributor/transition_to_osc.rst +++ b/doc/source/contributor/transition_to_osc.rst @@ -29,7 +29,7 @@ command-line interface (CLI), to the `OpenStack Client (OSC) `_ and the `OpenStack Python SDK `_. This transition is being guided by the -`Deprecate individual CLIs in favour of OSC `_ +`Deprecate individual CLIs in favour of OSC `_ OpenStack spec. See the `Neutron RFE `_, `OSC neutron support etherpad `_ and details below for the overall progress of this transition. @@ -56,16 +56,16 @@ Transition Steps ---------------- 1. **Done:** OSC adds OpenStack Python SDK as a dependency. See the following - patch set: https://review.openstack.org/#/c/138745/ + patch set: https://review.opendev.org/#/c/138745/ 2. **Done:** OSC switches its networking support for the `network `_ command object to use the OpenStack Python SDK instead of the neutron client's Python library. See the following patch set: - https://review.openstack.org/#/c/253348/ + https://review.opendev.org/#/c/253348/ 3. **Done:** OSC removes its python-neutronclient dependency. - See the following patch set: https://review.openstack.org/#/c/255545/ + See the following patch set: https://review.opendev.org/#/c/255545/ 4. **In Progress:** OpenStack Python SDK releases version 1.0 to guarantee backwards compatibility of its networking support and OSC updates @@ -99,7 +99,7 @@ Transition Steps developer guide section below for more information on this step. 7. **In Progress:** Deprecate the ``neutron`` CLI. Running the CLI after - it has been `deprecated `_ + it has been `deprecated `_ will issue a warning message: ``neutron CLI is deprecated and will be removed in the future. Use openstack CLI instead.`` In addition, no new features will be added to the CLI, though fixes to diff --git a/neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py b/neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py index cc64549af..0dda0fb3d 100644 --- a/neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py +++ b/neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py @@ -31,7 +31,7 @@ def add_minimum_bandwidth_arguments(parser): help=_('QoS minimum bandwidth assurance, expressed in kilobits ' 'per second.')) # NOTE(ralonsoh): the only direction implemented is "egress". Please, - # refer to the spec (https://review.openstack.org/#/c/316082/). + # refer to the spec (https://review.opendev.org/#/c/316082/). parser.add_argument( '--direction', # NOTE(ihrachys): though server picks the default for us (egress), it's diff --git a/neutronclient/tests/functional/hooks/fwaas b/neutronclient/tests/functional/hooks/fwaas index 5292897ce..d9fc704ef 100644 --- a/neutronclient/tests/functional/hooks/fwaas +++ b/neutronclient/tests/functional/hooks/fwaas @@ -1,2 +1,2 @@ -enable_plugin neutron-fwaas https://git.openstack.org/openstack/neutron-fwaas +enable_plugin neutron-fwaas https://opendev.org/openstack/neutron-fwaas enable_service q-fwaas diff --git a/neutronclient/tests/functional/hooks/vpnaas b/neutronclient/tests/functional/hooks/vpnaas index b121a6f0e..8b94b37b0 100644 --- a/neutronclient/tests/functional/hooks/vpnaas +++ b/neutronclient/tests/functional/hooks/vpnaas @@ -1 +1 @@ -enable_plugin neutron-vpnaas https://git.openstack.org/openstack/neutron-vpnaas +enable_plugin neutron-vpnaas https://opendev.org/openstack/neutron-vpnaas diff --git a/tox.ini b/tox.ini index cae97f1cb..fcc934cd2 100644 --- a/tox.ini +++ b/tox.ini @@ -12,7 +12,7 @@ setenv = VIRTUAL_ENV={envdir} PYTHONWARNINGS=default::DeprecationWarning usedevelop = True install_command = pip install {opts} {packages} -deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} +deps = -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt # Delete bytecodes from normal directories before running tests. From dc10f44128b26e7c964957c5e9c8d00ff91a3c0e Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Fri, 10 May 2019 10:54:03 +0900 Subject: [PATCH 021/149] doc: Remove prompt from python binding examples The current python binding examples have prompts of python interactive mode, but these prompts make it difficult to copy-and-paste the examples. This commit removes them. Change-Id: Ia5d35fbb585ed0d0d11c8d035196981e9dd46785 --- doc/source/reference/index.rst | 72 +++++++++++++++++----------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/doc/source/reference/index.rst b/doc/source/reference/index.rst index ee4761053..5678d6578 100644 --- a/doc/source/reference/index.rst +++ b/doc/source/reference/index.rst @@ -33,23 +33,23 @@ information on this keystoneauth API, see `Using Sessions`_. .. code-block:: python - >>> from keystoneauth1 import identity - >>> from keystoneauth1 import session - >>> from neutronclient.v2_0 import client - >>> username='username' - >>> password='password' - >>> project_name='demo' - >>> project_domain_id='default' - >>> user_domain_id='default' - >>> auth_url='http://auth.example.com:5000/v3' - >>> auth = identity.Password(auth_url=auth_url, - ... username=username, - ... password=password, - ... project_name=project_name, - ... project_domain_id=project_domain_id, - ... user_domain_id=user_domain_id) - >>> sess = session.Session(auth=auth) - >>> neutron = client.Client(session=sess) + from keystoneauth1 import identity + from keystoneauth1 import session + from neutronclient.v2_0 import client + username='username' + password='password' + project_name='demo' + project_domain_id='default' + user_domain_id='default' + auth_url='http://auth.example.com:5000/v3' + auth = identity.Password(auth_url=auth_url, + username=username, + password=password, + project_name=project_name, + project_domain_id=project_domain_id, + user_domain_id=user_domain_id) + sess = session.Session(auth=auth) + neutron = client.Client(session=sess) If you are using Identity v2.0 API (DEPRECATED), create an auth plugin using the appropriate parameters and `keystoneauth1.identity` will handle Identity @@ -58,38 +58,38 @@ like the previous example. .. code-block:: python - >>> auth = identity.Password(auth_url=auth_url, - ... username=username, - ... password=password, - ... project_name=project_name) - >>> # create a Session and a Neutronclient + auth = identity.Password(auth_url=auth_url, + username=username, + password=password, + project_name=project_name) + # create a Session and a Neutronclient Now you can call various methods on the client instance. .. code-block:: python - >>> network = {'name': 'mynetwork', 'admin_state_up': True} - >>> neutron.create_network({'network':network}) - >>> networks = neutron.list_networks(name='mynetwork') - >>> print networks - >>> network_id = networks['networks'][0]['id'] - >>> neutron.delete_network(network_id) + network = {'name': 'mynetwork', 'admin_state_up': True} + neutron.create_network({'network':network}) + networks = neutron.list_networks(name='mynetwork') + print networks + network_id = networks['networks'][0]['id'] + neutron.delete_network(network_id) Alternatively, you can create a client instance using an auth token and a service endpoint URL directly. .. code-block:: python - >>> from neutronclient.v2_0 import client - >>> neutron = client.Client(endpoint_url='http://192.168.206.130:9696/', - ... token='d3f9226f27774f338019aa2611112ef6') + from neutronclient.v2_0 import client + neutron = client.Client(endpoint_url='http://192.168.206.130:9696/', + token='d3f9226f27774f338019aa2611112ef6') You can get ``X-Openstack-Request-Id`` as ``request_ids`` from the result. .. code-block:: python - >>> network = {'name': 'mynetwork', 'admin_state_up': True} - >>> neutron.create_network({'network':network}) - >>> networks = neutron.list_networks(name='mynetwork') - >>> print networks.request_ids - ['req-978a0160-7ab0-44f0-8a93-08e9a4e785fa'] + network = {'name': 'mynetwork', 'admin_state_up': True} + neutron.create_network({'network':network}) + networks = neutron.list_networks(name='mynetwork') + print networks.request_ids + # -> ['req-978a0160-7ab0-44f0-8a93-08e9a4e785fa'] From e2ee92e2e1d87694cdffcd2e49974c5461d91a55 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Tue, 28 May 2019 11:49:52 +0900 Subject: [PATCH 022/149] Blacklist bandit 1.6.0 due to directory exclusion bug Bandit 1.6.0 introduces a regression[0] with the -x option, a fix is expected to be included in 1.6.1 soon. This commit also aligns Sphinx requirement with the requirements project [2]. This is required to pass requirements-check. The lower bound for sphinx was missing and requirements-check now requires it, so the lower bound sphinx >=1.6.2 was added. [0] https://github.com/PyCQA/bandit/issues/488 [1] https://github.com/PyCQA/bandit/pull/489 [2] https://review.opendev.org/#/c/657890/ Change-Id: I937cfa722f5234ca4d5506047001d9cb07728cd8 --- doc/requirements.txt | 3 ++- test-requirements.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index d959d4431..af1aeb8b3 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -3,4 +3,5 @@ # process, which may cause wedges in the gate later. openstackdocstheme>=1.18.1 # Apache-2.0 reno>=2.5.0 # Apache-2.0 -sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD +sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD +sphinx!=1.6.6,!=1.6.7,>=1.6.2;python_version>='3.4' # BSD diff --git a/test-requirements.txt b/test-requirements.txt index dabdb0e02..a1eb9b1d1 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -3,7 +3,7 @@ # process, which may cause wedges in the gate later. hacking>=1.1.0 # Apache-2.0 -bandit>=1.1.0 # Apache-2.0 +bandit!=1.6.0,>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 fixtures>=3.0.0 # Apache-2.0/BSD flake8-import-order==0.12 # LGPLv3 From cf95be3ea5e4396f26564a76e5ab67342afe6de5 Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Fri, 5 Jul 2019 11:46:03 -0400 Subject: [PATCH 023/149] Add Python 3 Train unit tests This is a mechanically generated patch to ensure unit testing is in place for all of the Tested Runtimes for Train. See the Train python3-updates goal document for details: https://governance.openstack.org/tc/goals/train/python3-updates.html Change-Id: If79694b32ece897c93d1889da28daff641e46f1c Story: #2005924 Task: #34225 --- .zuul.yaml | 3 +-- setup.cfg | 1 + tox.ini | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index db6d10cd9..80a5f4e4f 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -3,8 +3,7 @@ - openstack-cover-jobs - openstack-lower-constraints-jobs - openstack-python-jobs - - openstack-python36-jobs - - openstack-python37-jobs + - openstack-python3-train-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing diff --git a/setup.cfg b/setup.cfg index 867678087..0045e57ec 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,6 +18,7 @@ classifier = Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 [files] packages = diff --git a/tox.ini b/tox.ini index a5f18cc5a..5ef67b98d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] # py3 first to avoid .testrepository incompatibility -envlist = py36,py27,pypy,pep8 +envlist = py37,py27,pypy,pep8 minversion = 2.3.2 skipsdist = True From 34924865b3f684fa22f6356c64d03d42d11d46f6 Mon Sep 17 00:00:00 2001 From: zhanghao2 Date: Tue, 16 Jul 2019 22:41:52 -0400 Subject: [PATCH 024/149] Add friendly event hints for logging When creating a network log with the '--event' parameter, it is impossible to know which parameter values can be specified, and it is necessary to add a prompt. Change-Id: I6aa4f95b650cdc7b04e74b851a78a2ae42fc288a --- neutronclient/osc/v2/logging/network_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/osc/v2/logging/network_log.py b/neutronclient/osc/v2/logging/network_log.py index 1946a4066..df48fc1e5 100644 --- a/neutronclient/osc/v2/logging/network_log.py +++ b/neutronclient/osc/v2/logging/network_log.py @@ -118,7 +118,7 @@ def get_parser(self, prog_name): help=_('Name for the network log')) parser.add_argument( '--event', - metavar='', + metavar='{ALL,ACCEPT,DROP}', choices=['ALL', 'ACCEPT', 'DROP'], type=nc_utils.convert_to_uppercase, help=_('An event to store with log')) From 2af19d55d6029712f3888a37c019be5a25eba1fe Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Thu, 18 Jul 2019 16:31:38 +0900 Subject: [PATCH 025/149] Run functional test correctly legacy-neutronclient-test-dsvm-functional job actually runs neutronclient.tests.unit because .stestr.conf does not honor OS_TEST_PATH. This commit fixes .stestr.conf to honor OS_TEST_PATH specified in tox.ini. Also fixes the logic of is_extension_enabled() in ClientTestBase to check whether FWaaS v1 (fwaas) is enabled correctly. Previously the logic checks a substring of a specified extension, so 'fwaas' (FWaaS v1) matches 'fwaas_v2' (FWaaS v2), which leads to a failure of FWaaS v1 CLI tests. Change-Id: I958ad496b16cca8d03a7b84ebf5f8f031e4248ea --- .stestr.conf | 2 +- neutronclient/tests/functional/base.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.stestr.conf b/.stestr.conf index 6a6b6f120..875bb1461 100644 --- a/.stestr.conf +++ b/.stestr.conf @@ -1,3 +1,3 @@ [DEFAULT] -test_path=./neutronclient/tests/unit +test_path=${OS_TEST_PATH:-./neutronclient/tests/unit} top_dir=./ diff --git a/neutronclient/tests/functional/base.py b/neutronclient/tests/functional/base.py index d92d6936d..655c6c4f8 100644 --- a/neutronclient/tests/functional/base.py +++ b/neutronclient/tests/functional/base.py @@ -76,7 +76,5 @@ def neutron_non_admin(self, *args, **kwargs): def is_extension_enabled(self, extension_alias): extensions = self.parser.listing(self.neutron('ext-list')) - for extension in extensions: - if extension_alias in extension['alias']: - return True - return False + aliases = [e['alias'] for e in extensions] + return extension_alias in aliases From 6330cc1980958f57cb95684c8d7a1aaa89a7fbf6 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Thu, 18 Jul 2019 20:55:38 +0900 Subject: [PATCH 026/149] Convert legacy functional jobs to zuulv3 This commit merges the legacy functional test jobs (core and adv-svcs) into neutronclient-functional. FWaaS v1 was dropped in Stein and adv-svcs job now checks only VPNaaS, so it looks too much to have a separate job for VPNaaS. Note that tls-proxy is disabled as the base class for functional tests (neutronclient.tests.functional.base.ClientTestBase) does not support HTTPS endpoints. This can be tackled separately. Change-Id: I714efd1bc14cbba85f7b4caf6834ce375ff89547 --- .zuul.yaml | 35 +++++++++++++++++++++++------------ tox.ini | 7 +------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index 80a5f4e4f..60c7788e3 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -12,20 +12,10 @@ - openstackclient-plugin-jobs check: jobs: - - legacy-neutronclient-test-dsvm-functional: - irrelevant-files: &project-irrelevant-files - - ^.*\.rst$ - - ^doc/.*$ - - ^neutron/locale/.*$ - - ^releasenotes/.*$ - - legacy-neutronclient-test-dsvm-functional-adv-svcs: - irrelevant-files: *project-irrelevant-files + - neutronclient-functional gate: jobs: - - legacy-neutronclient-test-dsvm-functional: - irrelevant-files: *project-irrelevant-files - - legacy-neutronclient-test-dsvm-functional-adv-svcs: - irrelevant-files: *project-irrelevant-files + - neutronclient-functional experimental: jobs: - legacy-grenade-dsvm-neutron-libs: @@ -33,3 +23,24 @@ - ^(test-|)requirements.txt$ - ^setup.cfg$ +- job: + name: neutronclient-functional + parent: devstack-tox-functional + irrelevant-files: + - ^.*\.rst$ + - ^doc/.*$ + - ^releasenotes/.*$ + required-projects: + - openstack/python-neutronclient + - openstack/neutron + - openstack/neutron-vpnaas + vars: + tox_envlist: functional + devstack_services: + # NOTE: neutronclient.tests.functional.base.ClientTestBase does not + # support HTTPS endpoints now, so tls-proxy needs to be disabled. + tls-proxy: false + devstack_localrc: + LIBS_FROM_GIT: python-neutronclient + devstack_plugins: + neutron-vpnaas: https://opendev.org/openstack/neutron-vpnaas diff --git a/tox.ini b/tox.ini index 5ef67b98d..13a45d2d2 100644 --- a/tox.ini +++ b/tox.ini @@ -37,12 +37,7 @@ commands = {posargs} [testenv:functional] setenv = - OS_TEST_PATH = ./neutronclient/tests/functional/core - OS_NEUTRONCLIENT_EXEC_DIR = {envdir}/bin - -[testenv:functional-adv-svcs] -setenv = - OS_TEST_PATH = ./neutronclient/tests/functional/adv-svcs + OS_TEST_PATH = ./neutronclient/tests/functional OS_NEUTRONCLIENT_EXEC_DIR = {envdir}/bin [testenv:cover] From 1a8fdf355de233ccbc7aa0beb588fb02d436aa5c Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Wed, 24 Jul 2019 23:00:09 +0900 Subject: [PATCH 027/149] Switch functional job to python3 Change-Id: I7aa4566b8f2c81da6a00e664908506f5628cd0a1 --- .zuul.yaml | 1 + tox.ini | 1 + 2 files changed, 2 insertions(+) diff --git a/.zuul.yaml b/.zuul.yaml index 60c7788e3..0210d6406 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -41,6 +41,7 @@ # support HTTPS endpoints now, so tls-proxy needs to be disabled. tls-proxy: false devstack_localrc: + USE_PYTHON3: true LIBS_FROM_GIT: python-neutronclient devstack_plugins: neutron-vpnaas: https://opendev.org/openstack/neutron-vpnaas diff --git a/tox.ini b/tox.ini index 13a45d2d2..e248ee06d 100644 --- a/tox.ini +++ b/tox.ini @@ -36,6 +36,7 @@ basepython = python3 commands = {posargs} [testenv:functional] +basepython = python3 setenv = OS_TEST_PATH = ./neutronclient/tests/functional OS_NEUTRONCLIENT_EXEC_DIR = {envdir}/bin From ab426a791ad1937ea2cf3b340202b3968a378978 Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Tue, 13 Aug 2019 18:10:49 +0400 Subject: [PATCH 028/149] Use secure sha256 instead of sha1 Fix for bandit B303: Use of insecure MD2, MD4, MD5, or SHA1 hash function. Change-Id: I00403d7bd3b40ae00420e6cddcf40f45488284a9 Partial-Bug: #1759250 --- neutronclient/common/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/common/utils.py b/neutronclient/common/utils.py index 3a0469dbb..994e2a9db 100644 --- a/neutronclient/common/utils.py +++ b/neutronclient/common/utils.py @@ -183,7 +183,7 @@ def http_log_req(_logger, args, kwargs): for (key, value) in six.iteritems(kwargs['headers']): if key in SENSITIVE_HEADERS: v = value.encode('utf-8') - h = hashlib.sha1(v) + h = hashlib.sha256(v) d = h.hexdigest() value = "{SHA1}%s" % d header = ' -H "%s: %s"' % (key, value) From 62f4868e6e240ebbb4d6e29b8c1e1d23a24fcc15 Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Tue, 20 Aug 2019 15:15:36 +0400 Subject: [PATCH 029/149] Fix string in header Commit ab426a791ad1937ea2cf3b340202b3968a378978 changed sha1 to sha256. Need to change string correspondingly Change-Id: I8b35350c32ab551d513f21325931d6697f62fb2f Related-Bug: #1759250 --- neutronclient/common/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/common/utils.py b/neutronclient/common/utils.py index 994e2a9db..b61ee3b7a 100644 --- a/neutronclient/common/utils.py +++ b/neutronclient/common/utils.py @@ -185,7 +185,7 @@ def http_log_req(_logger, args, kwargs): v = value.encode('utf-8') h = hashlib.sha256(v) d = h.hexdigest() - value = "{SHA1}%s" % d + value = "{SHA256}%s" % d header = ' -H "%s: %s"' % (key, value) string_parts.append(header) From e35b3c160b5314ff573e913f3236cc98ccf500bc Mon Sep 17 00:00:00 2001 From: jiasirui Date: Thu, 29 Aug 2019 16:09:56 +0800 Subject: [PATCH 030/149] Improve help text Change-Id: Idc8f55567d0d4c95968d34d3b7aa95048623d9d0 --- neutronclient/shell.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/neutronclient/shell.py b/neutronclient/shell.py index 6dced26cd..fbc91209f 100644 --- a/neutronclient/shell.py +++ b/neutronclient/shell.py @@ -222,7 +222,7 @@ def build_option_parser(self, description, version): type=check_non_negative_int, default=0, help=_("How many times the request to the Neutron server should " - "be retried if it fails.")) + "be retried if it fails. Defaults to 0.")) # FIXME(bklei): this method should come from keystoneauth1 self._append_global_identity_args(parser) @@ -241,12 +241,12 @@ def _append_global_identity_args(self, parser): parser.add_argument( '--os-service-type', metavar='', default=env('OS_NETWORK_SERVICE_TYPE', default='network'), - help=_('Defaults to env[OS_NETWORK_SERVICE_TYPE] or network.')) + help=_('Defaults to env[OS_NETWORK_SERVICE_TYPE] or "network".')) parser.add_argument( '--os-endpoint-type', metavar='', default=env('OS_ENDPOINT_TYPE', default='public'), - help=_('Defaults to env[OS_ENDPOINT_TYPE] or public.')) + help=_('Defaults to env[OS_ENDPOINT_TYPE] or "public".')) # FIXME(bklei): --service-type is deprecated but kept in for # backward compatibility. From d6c78a5d3995c36f4641d462009902c32b70795f Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Tue, 27 Aug 2019 16:27:45 +0900 Subject: [PATCH 031/149] PDF documentation build Change-Id: I0abc5df1dfde23756bc2fd78631141ba685dc6fe Story: 2006099 Task: 35139 --- doc/source/conf.py | 19 +++++++++++++++++++ tox.ini | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/doc/source/conf.py b/doc/source/conf.py index b1c6ceece..294de7129 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -49,6 +49,25 @@ # Output file base name for HTML help builder. htmlhelp_basename = 'neutronclientdoc' +# -- Options for LaTeX output ------------------------------------------------ + +latex_documents = [ + ('index', 'doc-python-neutronclient.tex', + u'python-neutronclient Documentation', + u'Neutron Contributors', 'manual'), +] + +# Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664 +latex_use_xindy = False + +latex_domain_indices = False + +latex_elements = { + 'makeindex': '', + 'printindex': '', + 'preamble': r'\setcounter{tocdepth}{5}', +} + # -- Options for cliff.sphinxext plugin --------------------------------------- autoprogram_cliff_application = 'openstack' diff --git a/tox.ini b/tox.ini index e248ee06d..f9458eaa3 100644 --- a/tox.ini +++ b/tox.ini @@ -58,6 +58,16 @@ basepython = python3 deps = -r{toxinidir}/doc/requirements.txt commands = sphinx-build -W -b html doc/source doc/build/html +[testenv:pdf-docs] +basepython = python3 +envdir = {toxworkdir}/docs +deps = {[testenv:docs]deps} +whitelist_externals = + make +commands = + sphinx-build -W -b latex doc/source doc/build/pdf + make -C doc/build/pdf + [testenv:releasenotes] basepython = python3 deps = -r{toxinidir}/doc/requirements.txt From 1c634ed2c16195e5a2e67400902f01450df30d98 Mon Sep 17 00:00:00 2001 From: Bence Romsics Date: Wed, 7 Aug 2019 16:26:38 +0200 Subject: [PATCH 032/149] Add router add/remove extra routes operations Add methods to the client to call the two new member actions introduced by new Neutron extension: extraroute-atomic. Change-Id: Idb1fa073c2ff31f566b376cfa4f63cf27fecec86 Partial-Bug: #1826396 (rfe) Related-Change: https://review.opendev.org/655680 (spec) --- neutronclient/v2_0/client.py | 10 ++++++++++ .../notes/extraroute-atomic-b11919d8e33b0d92.yaml | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 releasenotes/notes/extraroute-atomic-b11919d8e33b0d92.yaml diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index ed8dbd49d..c338c316e 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -934,6 +934,16 @@ def remove_interface_router(self, router, body=None): return self.put((self.router_path % router) + "/remove_router_interface", body=body) + def add_extra_routes_to_router(self, router, body=None): + """Adds extra routes to the specified router.""" + return self.put((self.router_path % router) + "/add_extraroutes", + body=body) + + def remove_extra_routes_from_router(self, router, body=None): + """Removes extra routes from the specified router.""" + return self.put((self.router_path % router) + "/remove_extraroutes", + body=body) + def add_gateway_router(self, router, body=None): """Adds an external network gateway to the specified router.""" return self.put((self.router_path % router), diff --git a/releasenotes/notes/extraroute-atomic-b11919d8e33b0d92.yaml b/releasenotes/notes/extraroute-atomic-b11919d8e33b0d92.yaml new file mode 100644 index 000000000..fed4a1e10 --- /dev/null +++ b/releasenotes/notes/extraroute-atomic-b11919d8e33b0d92.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + New client methods: ``add_extra_routes_to_router`` and + ``remove_extra_routes_from_router``. From f61cd94e11e30a3e5dcf646e0b0a91e80f7d027b Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Fri, 20 Sep 2019 17:41:48 +0000 Subject: [PATCH 033/149] Update master for stable/train Add file to the reno documentation build to show release notes for stable/train. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/train. Change-Id: I1dd2ee12854ac7a55baa2114230ab42404dea5c1 Sem-Ver: feature --- releasenotes/source/index.rst | 1 + releasenotes/source/train.rst | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/train.rst diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index 446a2a869..f5df8b776 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + train stein rocky queens diff --git a/releasenotes/source/train.rst b/releasenotes/source/train.rst new file mode 100644 index 000000000..583900393 --- /dev/null +++ b/releasenotes/source/train.rst @@ -0,0 +1,6 @@ +========================== +Train Series Release Notes +========================== + +.. release-notes:: + :branch: stable/train From ee08644c5f2424a40c70010dcf0fa2ad84809bfc Mon Sep 17 00:00:00 2001 From: zhanghao2 Date: Tue, 1 Oct 2019 05:19:34 -0400 Subject: [PATCH 034/149] Remove 'public' and 'private' parameters in fwaas_v2 The 'public' and 'private' parameters have been replaced with 'share' and 'no-share' parameters in the Pike version, they can be removed now. Change-Id: I57a2e228ec1cdb6ed259914abc38bdada036d369 --- neutronclient/osc/v2/fwaas/firewallgroup.py | 27 +++---------------- neutronclient/osc/v2/fwaas/firewallpolicy.py | 25 +++-------------- neutronclient/osc/v2/fwaas/firewallrule.py | 25 +++-------------- .../tests/unit/osc/v2/fwaas/common.py | 14 ---------- ...d-private-parameters-d683e7c30ecedc3b.yaml | 6 +++++ 5 files changed, 15 insertions(+), 82 deletions(-) create mode 100644 releasenotes/notes/remove-public-and-private-parameters-d683e7c30ecedc3b.yaml diff --git a/neutronclient/osc/v2/fwaas/firewallgroup.py b/neutronclient/osc/v2/fwaas/firewallgroup.py index fe8ab1188..4287132ea 100644 --- a/neutronclient/osc/v2/fwaas/firewallgroup.py +++ b/neutronclient/osc/v2/fwaas/firewallgroup.py @@ -77,19 +77,6 @@ def _get_common_parser(parser): action='store_true', help=_('Detach egress firewall policy from the firewall group')) shared_group = parser.add_mutually_exclusive_group() - shared_group.add_argument( - '--public', - action='store_true', - help=_('Make the firewall group public, which allows it to be ' - 'used in all projects (as opposed to the default, ' - 'which is to restrict its use to the current project). ' - 'This option is deprecated and would be removed in R release.')) - shared_group.add_argument( - '--private', - action='store_true', - help=_('Restrict use of the firewall group to the ' - 'current project. This option is deprecated ' - 'and would be removed in R release.')) shared_group.add_argument( '--share', @@ -147,9 +134,9 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): cmd_resource=const.CMD_FWP)['id'] elif parsed_args.no_egress_firewall_policy: attrs['egress_firewall_policy_id'] = None - if parsed_args.share or parsed_args.public: + if parsed_args.share: attrs['shared'] = True - if parsed_args.no_share or parsed_args.private: + if parsed_args.no_share: attrs['shared'] = False if parsed_args.enable: attrs['admin_state_up'] = True @@ -349,14 +336,6 @@ def get_parser(self, prog_name): dest='egress_firewall_policy', help=_('Egress firewall policy (name or ID) to delete')) shared_group = parser.add_mutually_exclusive_group() - shared_group.add_argument( - '--public', - action='store_true', - help=_('Make the firewall group public, which allows it to be ' - 'used in all projects (as opposed to the default, ' - 'which is to restrict its use to the current project). ' - 'This option is deprecated and would be removed in R' - ' release.')) shared_group.add_argument( '--share', action='store_true', @@ -375,7 +354,7 @@ def _get_attrs(self, client_manager, parsed_args): attrs['ingress_firewall_policy_id'] = None if parsed_args.egress_firewall_policy: attrs['egress_firewall_policy_id'] = None - if parsed_args.share or parsed_args.public: + if parsed_args.share: attrs['shared'] = False if parsed_args.enable: attrs['admin_state_up'] = False diff --git a/neutronclient/osc/v2/fwaas/firewallpolicy.py b/neutronclient/osc/v2/fwaas/firewallpolicy.py index 2c3d5675e..bd3e60d40 100644 --- a/neutronclient/osc/v2/fwaas/firewallpolicy.py +++ b/neutronclient/osc/v2/fwaas/firewallpolicy.py @@ -80,9 +80,9 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs['name'] = str(parsed_args.name) if parsed_args.description: attrs['description'] = str(parsed_args.description) - if parsed_args.share or parsed_args.public: + if parsed_args.share: attrs['shared'] = True - if parsed_args.no_share or parsed_args.private: + if parsed_args.no_share: attrs['shared'] = False return attrs @@ -107,19 +107,6 @@ def _get_common_parser(parser): help=_('Share the firewall policy to be used in all projects ' '(by default, it is restricted to be used by the ' 'current project).')) - shared_group.add_argument( - '--public', - action='store_true', - help=_('Make the firewall policy public, which allows it to be ' - 'used in all projects (as opposed to the default, which ' - 'is to restrict its use to the current project.) This ' - 'option is deprecated and would be removed in R release.')) - shared_group.add_argument( - '--private', - action='store_true', - help=_( - 'Restrict use of the firewall policy to the current project.' - 'This option is deprecated and would be removed in R release.')) shared_group.add_argument( '--no-share', action='store_true', @@ -403,12 +390,6 @@ def get_parser(self, prog_name): action='store_true', help=_('Restrict use of the firewall policy to the ' 'current project')) - parser.add_argument( - '--public', - action='store_true', - help=_('Restrict use of the firewall policy to the ' - 'current project. This option is deprecated ' - 'and would be removed in R release.')) return parser def _get_attrs(self, client_manager, parsed_args): @@ -428,7 +409,7 @@ def _get_attrs(self, client_manager, parsed_args): attrs[const.FWRS] = [] if parsed_args.audited: attrs['audited'] = False - if parsed_args.share or parsed_args.public: + if parsed_args.share: attrs['shared'] = False return attrs diff --git a/neutronclient/osc/v2/fwaas/firewallrule.py b/neutronclient/osc/v2/fwaas/firewallrule.py index f72beded7..720c4d29a 100644 --- a/neutronclient/osc/v2/fwaas/firewallrule.py +++ b/neutronclient/osc/v2/fwaas/firewallrule.py @@ -117,19 +117,6 @@ def _get_common_parser(parser): action='store_true', help=_('Detach destination port number or range')) shared_group = parser.add_mutually_exclusive_group() - shared_group.add_argument( - '--public', - action='store_true', - help=_('Make the firewall policy public, which allows it to be ' - 'used in all projects (as opposed to the default, ' - 'which is to restrict its use to the current project). ' - 'This option is deprecated and would be removed in R Release')) - shared_group.add_argument( - '--private', - action='store_true', - help=_( - 'Restrict use of the firewall rule to the current project.' - 'This option is deprecated and would be removed in R release.')) shared_group.add_argument( '--share', action='store_true', @@ -212,9 +199,9 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs['enabled'] = True if parsed_args.disable_rule: attrs['enabled'] = False - if parsed_args.share or parsed_args.public: + if parsed_args.share: attrs['shared'] = True - if parsed_args.no_share or parsed_args.private: + if parsed_args.no_share: attrs['shared'] = False if parsed_args.source_firewall_group: attrs['source_firewall_group_id'] = client.find_resource( @@ -416,12 +403,6 @@ def get_parser(self, prog_name): '--share', action='store_true', help=_('Restrict use of the firewall rule to the current project')) - parser.add_argument( - '--public', - action='store_true', - help=_('Restrict use of the firewall rule to the current project. ' - 'This option is deprecated and would be removed in ' - 'R Release.')) parser.add_argument( '--enable-rule', action='store_true', @@ -448,7 +429,7 @@ def _get_attrs(self, client_manager, parsed_args): attrs['destination_ip_address'] = None if parsed_args.destination_port: attrs['destination_port'] = None - if parsed_args.share or parsed_args.public: + if parsed_args.share: attrs['shared'] = False if parsed_args.enable_rule: attrs['enabled'] = False diff --git a/neutronclient/tests/unit/osc/v2/fwaas/common.py b/neutronclient/tests/unit/osc/v2/fwaas/common.py index 8acd51c42..8b497a9ff 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/common.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/common.py @@ -120,20 +120,6 @@ def test_set_shared(self): target, {self.res: {'shared': True}}) self.assertIsNone(result) - def test_set_public(self): - target = self.resource['id'] - arglist = [target, '--public'] - verifylist = [ - (self.res, target), - ('public', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, {self.res: {'shared': True}}) - self.assertIsNone(result) - def test_set_duplicate_shared(self): target = self.resource['id'] arglist = [target, '--share', '--share'] diff --git a/releasenotes/notes/remove-public-and-private-parameters-d683e7c30ecedc3b.yaml b/releasenotes/notes/remove-public-and-private-parameters-d683e7c30ecedc3b.yaml new file mode 100644 index 000000000..d340c1763 --- /dev/null +++ b/releasenotes/notes/remove-public-and-private-parameters-d683e7c30ecedc3b.yaml @@ -0,0 +1,6 @@ +--- +upgrade: + - | + The deprecated options ``--public`` and ``--private`` were + dropped in FWaaS v2 related commands. Use ``--share`` and + ``--no-share`` instead. From 40996e50ea5fbfbaca628cd81a34dd7db694578d Mon Sep 17 00:00:00 2001 From: kangyufei Date: Tue, 22 Oct 2019 14:22:17 +0800 Subject: [PATCH 035/149] Switch to Ussuri jobs Change-Id: I59807606d4865cb2f4d9c6a912f659ea45b3fba8 --- .zuul.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zuul.yaml b/.zuul.yaml index 0210d6406..bc6861a3a 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -3,7 +3,7 @@ - openstack-cover-jobs - openstack-lower-constraints-jobs - openstack-python-jobs - - openstack-python3-train-jobs + - openstack-python3-ussuri-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing From c430ed8950300b9908e470011f2d0f0170fcd369 Mon Sep 17 00:00:00 2001 From: Ghanshyam Mann Date: Sat, 23 Nov 2019 01:56:25 +0000 Subject: [PATCH 036/149] Move grenade neutron-lib job to py3 and in python-neutronclient repo 'legacy-grenade-dsvm-neutron-libs' grenade neutron-lib jobs is present in opensatck-zuul-jobs repo running on python 2. This needs to run on py3 from Ussuri onwards and py2 for stable/branch. python-neutronclient is the only repo which is using this job. py2 version has been kept in opensatck-zuul-jobs and for ussuri onwwards this has been migrated to python-neutronclient repo with py3 version. Change-Id: I165f86e1d05c8830e0b75b5c2db369178a3df7e7 --- .zuul.yaml | 28 +++++++++- .../grenade-dsvm-neutron-libs/post.yaml | 15 ++++++ .../legacy/grenade-dsvm-neutron-libs/run.yaml | 52 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml create mode 100644 playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml diff --git a/.zuul.yaml b/.zuul.yaml index 0210d6406..3bdaf13a0 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -18,7 +18,7 @@ - neutronclient-functional experimental: jobs: - - legacy-grenade-dsvm-neutron-libs: + - neutron-lib-grenade-dsvm: irrelevant-files: - ^(test-|)requirements.txt$ - ^setup.cfg$ @@ -45,3 +45,29 @@ LIBS_FROM_GIT: python-neutronclient devstack_plugins: neutron-vpnaas: https://opendev.org/openstack/neutron-vpnaas + +- job: + name: neutron-lib-grenade-dsvm + # Old name: legacy-grenade-dsvm-neutron-libs + parent: legacy-dsvm-base + run: playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml + post-run: playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml + timeout: 10800 + required-projects: + - openstack/grenade + - openstack/devstack-gate + - openstack/keystoneauth + - openstack/neutron + - openstack/neutron-lib + - openstack/os-client-config + - openstack/python-cinderclient + - openstack/python-glanceclient + - openstack/python-ironicclient + - openstack/python-keystoneclient + - openstack/python-neutronclient + - openstack/python-novaclient + # This is py3 version for ussuri onwards rest all branch needs to be py2 + # version which is present in openstack-zuul-jobs. + # We need to take care of this branch variant and python version while + # migrating these jobs to zuulv3. + branches: ^(?!(stable/(ocata|pike|queens|rocky|stein|train))).*$ diff --git a/playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml b/playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml new file mode 100644 index 000000000..e07f5510a --- /dev/null +++ b/playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml @@ -0,0 +1,15 @@ +- hosts: primary + tasks: + + - name: Copy files from {{ ansible_user_dir }}/workspace/ on node + synchronize: + src: '{{ ansible_user_dir }}/workspace/' + dest: '{{ zuul.executor.log_root }}' + mode: pull + copy_links: true + verify_host: true + rsync_opts: + - --include=/logs/** + - --include=*/ + - --exclude=* + - --prune-empty-dirs diff --git a/playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml b/playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml new file mode 100644 index 000000000..6c600610a --- /dev/null +++ b/playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml @@ -0,0 +1,52 @@ +- hosts: all + name: Autoconverted job legacy-grenade-dsvm-neutron-libs from old job gate-grenade-dsvm-neutron-libs-ubuntu-xenial-nv + tasks: + + - name: Ensure legacy workspace directory + file: + path: '{{ ansible_user_dir }}/workspace' + state: directory + + - shell: + cmd: | + set -e + set -x + cat > clonemap.yaml << EOF + clonemap: + - name: openstack/devstack-gate + dest: devstack-gate + EOF + /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \ + https://opendev.org \ + openstack/devstack-gate + executable: /bin/bash + chdir: '{{ ansible_user_dir }}/workspace' + environment: '{{ zuul | zuul_legacy_vars }}' + + - shell: + cmd: | + set -e + set -x + export PROJECTS="openstack/grenade $PROJECTS" + export DEVSTACK_PROJECT_FROM_GIT="os-client-config" + export DEVSTACK_PROJECT_FROM_GIT+=",keystoneauth" + export DEVSTACK_PROJECT_FROM_GIT+=",python-novaclient" + export DEVSTACK_PROJECT_FROM_GIT+=",python-keystoneclient" + export DEVSTACK_PROJECT_FROM_GIT+=",python-glanceclient" + export DEVSTACK_PROJECT_FROM_GIT+=",python-cinderclient" + export DEVSTACK_PROJECT_FROM_GIT+=",python-neutronclient" + export DEVSTACK_PROJECT_FROM_GIT+=",python-ironicclient" + export PYTHONUNBUFFERED=true + export DEVSTACK_GATE_TEMPEST=1 + export DEVSTACK_GATE_GRENADE=pullup + export DEVSTACK_GATE_USE_PYTHON3=True + export DEVSTACK_GATE_NEUTRON=1 + export BRANCH_OVERRIDE=default + if [ "$BRANCH_OVERRIDE" != "default" ] ; then + export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE + fi + cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh + ./safe-devstack-vm-gate-wrap.sh + executable: /bin/bash + chdir: '{{ ansible_user_dir }}/workspace' + environment: '{{ zuul | zuul_legacy_vars }}' From d5c516a5a288003ca661091152c1a8ebfa527909 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Tue, 17 Dec 2019 14:43:05 +0900 Subject: [PATCH 037/149] Drop python3 hack for XML serializer It was added in https://review.opendev.org/#/c/110947/ to make the XML serializer work in python 3. We dropped the XML serializer support long ago. I believe we can drop it safely. Change-Id: I208de891515cb2cbdde779013ba58f19e36fc55c --- neutronclient/common/serializer.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/neutronclient/common/serializer.py b/neutronclient/common/serializer.py index fdf76774b..98865a6b3 100644 --- a/neutronclient/common/serializer.py +++ b/neutronclient/common/serializer.py @@ -20,10 +20,6 @@ from neutronclient.common import exceptions as exception -if six.PY3: - long = int - - class ActionDispatcher(object): """Maps method name to local methods through action name.""" From 010053df07d7dffad55581c0db9d43256a482280 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Wed, 13 Nov 2019 01:24:29 +0900 Subject: [PATCH 038/149] Drop python 2.7 support We no longer support python 2.7 past Train. Let's stop testings with python 2.7 and drop python 2.7 stuffs. pypy in tox.ini is also dropped too. It is not used for long. Change-Id: I8a07c007a129cd2141085a1a3cc7f81658c42db2 --- .zuul.yaml | 1 - .../notes/drop-python-2.7-f615ebae463b2143.yaml | 5 +++++ setup.cfg | 5 ----- tox.ini | 14 +++----------- 4 files changed, 8 insertions(+), 17 deletions(-) create mode 100644 releasenotes/notes/drop-python-2.7-f615ebae463b2143.yaml diff --git a/.zuul.yaml b/.zuul.yaml index 7d3ff433b..d93813cfc 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -2,7 +2,6 @@ templates: - openstack-cover-jobs - openstack-lower-constraints-jobs - - openstack-python-jobs - openstack-python3-ussuri-jobs - publish-openstack-docs-pti - check-requirements diff --git a/releasenotes/notes/drop-python-2.7-f615ebae463b2143.yaml b/releasenotes/notes/drop-python-2.7-f615ebae463b2143.yaml new file mode 100644 index 000000000..6fb4d22ab --- /dev/null +++ b/releasenotes/notes/drop-python-2.7-f615ebae463b2143.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - | + Python 2.7 support has been dropped. The minimum version of Python now + supported by python-neutronclient is Python 3.6. diff --git a/setup.cfg b/setup.cfg index 0045e57ec..16cfc5aef 100644 --- a/setup.cfg +++ b/setup.cfg @@ -14,8 +14,6 @@ classifier = License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 @@ -457,9 +455,6 @@ neutron.cli.v2 = vpn-ikepolicy-update = neutronclient.neutron.v2_0.vpn.ikepolicy:UpdateIKEPolicy vpn-ikepolicy-delete = neutronclient.neutron.v2_0.vpn.ikepolicy:DeleteIKEPolicy -[wheel] -universal = 1 - [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg diff --git a/tox.ini b/tox.ini index f9458eaa3..fa1f9e209 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,11 @@ [tox] -# py3 first to avoid .testrepository incompatibility -envlist = py37,py27,pypy,pep8 +envlist = py37,pep8 minversion = 2.3.2 skipsdist = True +ignore_basepython_conflict = True [testenv] +basepython = python3 setenv = VIRTUAL_ENV={envdir} LANG=en_US.UTF-8 LANGUAGE=en_US:en @@ -25,24 +26,20 @@ commands = sh -c "find . -type d -name '.?*' -prune -o \ whitelist_externals = sh [testenv:pep8] -basepython = python3 commands = flake8 {[testenv:bandit]commands} distribute = false [testenv:venv] -basepython = python3 commands = {posargs} [testenv:functional] -basepython = python3 setenv = OS_TEST_PATH = ./neutronclient/tests/functional OS_NEUTRONCLIENT_EXEC_DIR = {envdir}/bin [testenv:cover] -basepython = python3 setenv = {[testenv]setenv} PYTHON=coverage run --source neutronclient --parallel-mode @@ -54,12 +51,10 @@ commands = coverage report [testenv:docs] -basepython = python3 deps = -r{toxinidir}/doc/requirements.txt commands = sphinx-build -W -b html doc/source doc/build/html [testenv:pdf-docs] -basepython = python3 envdir = {toxworkdir}/docs deps = {[testenv:docs]deps} whitelist_externals = @@ -69,7 +64,6 @@ commands = make -C doc/build/pdf [testenv:releasenotes] -basepython = python3 deps = -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html @@ -82,13 +76,11 @@ import-order-style = pep8 enable-extensions=H904 [testenv:bandit] -basepython = python3 # B303: blacklist calls: md5, sha1 deps = -r{toxinidir}/test-requirements.txt commands = bandit -r neutronclient -x tests -n5 -s B303 [testenv:lower-constraints] -basepython = python3 deps = -c{toxinidir}/lower-constraints.txt -r{toxinidir}/test-requirements.txt From 91fb009706526ed8d36ca8f2cf57f1763a9af520 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Tue, 17 Dec 2019 16:39:14 +0900 Subject: [PATCH 039/149] Fix pep8 errors with hacking 2.0.0 Change-Id: I4737d4bc4fa116f45e2361eba93f48feae0161a4 --- neutronclient/tests/unit/osc/v2/logging/test_network_log.py | 4 ++-- neutronclient/tests/unit/qos/test_cli20_rule.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/neutronclient/tests/unit/osc/v2/logging/test_network_log.py b/neutronclient/tests/unit/osc/v2/logging/test_network_log.py index 43c0bcbfe..d36453542 100644 --- a/neutronclient/tests/unit/osc/v2/logging/test_network_log.py +++ b/neutronclient/tests/unit/osc/v2/logging/test_network_log.py @@ -139,8 +139,8 @@ def setUp(self): self.mocked = self.neutronclient.create_network_log self.cmd = network_log.CreateNetworkLog(self.app, self.namespace) loggables = { - "loggable_resources": [{"type": RES_TYPE_SG, - "type": RES_TYPE_FWG}] + "loggable_resources": [{"type": RES_TYPE_SG}, + {"type": RES_TYPE_FWG}] } self.neutronclient.list_network_loggable_resources = mock.Mock( return_value=loggables) diff --git a/neutronclient/tests/unit/qos/test_cli20_rule.py b/neutronclient/tests/unit/qos/test_cli20_rule.py index c1da5afef..f77c3c410 100644 --- a/neutronclient/tests/unit/qos/test_cli20_rule.py +++ b/neutronclient/tests/unit/qos/test_cli20_rule.py @@ -33,9 +33,9 @@ def test_list_qos_rule_types(self): # qos_rule_types. resources = 'rule_types' cmd_resources = 'qos_rule_types' - response_contents = [{'type': 'bandwidth_limit', - 'type': 'dscp_marking', - 'type': 'minimum_bandwidth'}] + response_contents = [{'type': 'bandwidth_limit'}, + {'type': 'dscp_marking'}, + {'type': 'minimum_bandwidth'}] cmd = qos_rule.ListQoSRuleTypes(test_cli20.MyApp(sys.stdout), None) From 29043825e7e19b4f32f3998ea95419ad2429cd14 Mon Sep 17 00:00:00 2001 From: liushuobj Date: Fri, 27 Dec 2019 16:35:42 +0800 Subject: [PATCH 040/149] fix a typo Change-Id: I9d82335c37f114aa43f26dec106e7598e776e068 --- releasenotes/notes/relnotes-from-3.0.0-d7306f5af5e3868d.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/relnotes-from-3.0.0-d7306f5af5e3868d.yaml b/releasenotes/notes/relnotes-from-3.0.0-d7306f5af5e3868d.yaml index 012bc7fc2..2bf4d5ab0 100644 --- a/releasenotes/notes/relnotes-from-3.0.0-d7306f5af5e3868d.yaml +++ b/releasenotes/notes/relnotes-from-3.0.0-d7306f5af5e3868d.yaml @@ -2,7 +2,7 @@ features: - Support os-client-config. OS_CLOUD environment variable is used for selecting named cloud configuration. - - Support keystoneauth1 library which brings us better kyestone v3 support. + - Support keystoneauth1 library which brings us better keystone v3 support. - Client command extension now supports a child resource. - New CLI for VPNaaS multiple local subnets. - New CLI for VPNaaS endpoint group API. From a363edd761e2c99bae6d4492d0ca44a404e5d904 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Fri, 10 Jan 2020 18:54:28 +0000 Subject: [PATCH 041/149] Avoid py36 error when printing unicode chars in a stream The IOStream was not able to encode characters out of range 128: "UnicodeEncodeError: 'ascii' codec can't encode characters in position 19-21: ordinal not in range(128)" Change-Id: Ic95396a5cf73c49d332928857dc064819a6d7ea6 Closes-Bug: #1858421 --- neutronclient/tests/unit/test_exceptions.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/neutronclient/tests/unit/test_exceptions.py b/neutronclient/tests/unit/test_exceptions.py index 91742872c..aefc24c66 100644 --- a/neutronclient/tests/unit/test_exceptions.py +++ b/neutronclient/tests/unit/test_exceptions.py @@ -12,7 +12,9 @@ # License for the specific language governing permissions and limitations # under the License. -import fixtures +import sys + +import mock from oslo_utils import encodeutils import six import testtools @@ -30,12 +32,11 @@ class TestException(exceptions.NeutronException): multibyte_unicode_string = u'\uff21\uff22\uff23' e = TestException(reason=multibyte_unicode_string) - fixture = fixtures.StringStream('stdout') - self.useFixture(fixture) - with fixtures.MonkeyPatch('sys.stdout', fixture.stream): + with mock.patch.object(sys, 'stdout') as mock_stdout: print(e) - self.assertEqual('Exception with %s' % multibyte_unicode_string, - fixture.getDetails().get('stdout').as_text()) + + exc_str = 'Exception with %s' % multibyte_unicode_string + mock_stdout.assert_has_calls([mock.call.write(exc_str)]) def test_exception_message_with_encoded_unicode(self): class TestException(exceptions.NeutronException): From 946ac3ed2e9e177eb5c56cc74aadbc091b9292ab Mon Sep 17 00:00:00 2001 From: Jay Faulkner Date: Tue, 7 Jan 2020 11:50:43 -0800 Subject: [PATCH 042/149] Convert exception to string before passing it in Before this change, neutronclient was passing in a raw exception as a kwarg to the ConnectionFailed exception. This caused an exception to be raised in _safe_decode_dict() due to the exception not being a text type. Now, we explicitly convert the raw exception to a string before passing it as a kwarg. Closes-bug: 1859068 Change-Id: I323b3aceec0a937874eabf770fbc82995202f6d6 --- neutronclient/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neutronclient/client.py b/neutronclient/client.py index c5f467668..936d297e2 100644 --- a/neutronclient/client.py +++ b/neutronclient/client.py @@ -104,13 +104,13 @@ def _cs_request(self, *args, **kwargs): try: resp, body = self.request(*args, **kargs) except requests.exceptions.SSLError as e: - raise exceptions.SslCertificateValidationError(reason=e) + raise exceptions.SslCertificateValidationError(reason=str(e)) except Exception as e: # Wrap the low-level connection error (socket timeout, redirect # limit, decompression error, etc) into our custom high-level # connection exception (it is excepted in the upper layers of code) _logger.debug("throwing ConnectionFailed : %s", e) - raise exceptions.ConnectionFailed(reason=e) + raise exceptions.ConnectionFailed(reason=str(e)) utils.http_log_resp(_logger, resp, body) # log request-id for each api call From 59145be07e5df52a7cc0fb84e8da10fe4de6e770 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 6 Feb 2020 10:32:33 +0000 Subject: [PATCH 043/149] Add support for port bindings The port bindings API has been around since Pike but has never been exposed via neutronclient. We still use this in nova so it would be nice to avoid having to create a KSA client manually for this stuff. We don't need to expose things via the UI, just the client itself, so do that. Change-Id: Ied1a057186f0819166df84725b09ded314930a1d Signed-off-by: Stephen Finucane Sem-Ver: feature --- neutronclient/v2_0/client.py | 25 +++++++++++++++++++ .../notes/port-bindings-c3f36bd76ece0a71.yaml | 5 ++++ 2 files changed, 30 insertions(+) create mode 100644 releasenotes/notes/port-bindings-c3f36bd76ece0a71.yaml diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index c338c316e..5fa869840 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -492,6 +492,9 @@ class Client(ClientBase): network_path = "/networks/%s" ports_path = "/ports" port_path = "/ports/%s" + port_bindings_path = "/ports/%s/bindings" + port_binding_path = "/ports/%s/bindings/%s" + port_binding_path_activate = "/ports/%s/bindings/%s/activate" subnets_path = "/subnets" subnet_path = "/subnets/%s" onboard_network_subnets_path = "/subnetpools/%s/onboard_network_subnets" @@ -811,6 +814,28 @@ def delete_port(self, port): """Deletes the specified port.""" return self.delete(self.port_path % (port)) + def create_port_binding(self, port_id, body=None): + """Creates a new port binding.""" + return self.post(self.port_bindings_path % port_id, body=body) + + def delete_port_binding(self, port_id, host_id): + """Deletes the specified port binding.""" + return self.delete(self.port_binding_path % (port_id, host_id)) + + def show_port_binding(self, port_id, host_id, **_params): + """Fetches information for a certain port binding.""" + return self.get(self.port_binding_path % (port_id, host_id), + params=_params) + + def list_port_bindings(self, port_id, retrieve_all=True, **_params): + """Fetches a list of all bindings for a certain port.""" + return self.list('port_bindings', self.port_bindings_path % port_id, + retrieve_all, **_params) + + def activate_port_binding(self, port_id, host_id): + """Activates a port binding.""" + return self.put(self.port_binding_path_activate % (port_id, host_id)) + def list_networks(self, retrieve_all=True, **_params): """Fetches a list of all networks for a project.""" # Pass filters in "params" argument to do_request diff --git a/releasenotes/notes/port-bindings-c3f36bd76ece0a71.yaml b/releasenotes/notes/port-bindings-c3f36bd76ece0a71.yaml new file mode 100644 index 000000000..7d2ef725e --- /dev/null +++ b/releasenotes/notes/port-bindings-c3f36bd76ece0a71.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + New client methods: ``create_port_binding``, ``delete_port_binding``, + ``show_port_binding``, ``list_port_bindings`` and ``activate_port_binding``. From b3fa5e530b71c984d734eeb24a1e26126a486016 Mon Sep 17 00:00:00 2001 From: zhanghao Date: Sat, 25 Jan 2020 04:16:16 -0500 Subject: [PATCH 044/149] Drop lib-forward-testing Change-Id: Ifdce9146e8233e6760ee6c0009338661f90848a2 --- .zuul.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.zuul.yaml b/.zuul.yaml index d93813cfc..b6685df2e 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -5,7 +5,6 @@ - openstack-python3-ussuri-jobs - publish-openstack-docs-pti - check-requirements - - lib-forward-testing - lib-forward-testing-python3 - release-notes-jobs-python3 - openstackclient-plugin-jobs From bb5b9cac6e0fd65bd620d514d29751800575d5cc Mon Sep 17 00:00:00 2001 From: zhanghao Date: Mon, 6 Jan 2020 05:33:53 -0500 Subject: [PATCH 045/149] Replace 'bgp speaker show dragents' with 'bgp dragent list' In order to follow other agent related commands in OSC, it is more appropriate and friendly to replace 'bgp speaker show dragents' with 'bgp dragent list'. this patch uses 'openstack bgp dragent list' to show the list of dragents, and the optional parameter 'bgp-speaker' shows the list of dragents hosting a specific bgp speaker. Change-Id: I9e0703fccf535b1e1a2055ed917336055b7395f5 Closes-Bug: #1858377 --- .../osc/v2/dynamic_routing/bgp_dragent.py | 47 ++++++- .../unit/osc/v2/dynamic_routing/fakes.py | 38 +++++- .../v2/dynamic_routing/test_bgp_dragent.py | 123 ++++++++++++++++++ ...peaker-show-dragents-2fcce99cf6bb5b60.yaml | 10 ++ setup.cfg | 1 + 5 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py create mode 100644 releasenotes/notes/deprecate-bgp-speaker-show-dragents-2fcce99cf6bb5b60.yaml diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py b/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py index f7f1e836b..025022996 100644 --- a/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py +++ b/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py @@ -70,18 +70,25 @@ def take_action(self, parsed_args): class ListDRAgentsHostingBgpSpeaker(command.Lister): - """List dynamic routing agents hosting a BGP speaker""" + """(Deprecated) List dynamic routing agents hosting a BGP speaker + + (Use "bgp dragent list" instead) + """ resource = 'agent' list_columns = ['id', 'host', 'admin_state_up', 'alive'] unknown_parts_flag = False def get_parser(self, prog_name): + self.log.warning("The 'openstack bgp speaker show dragents' CLI is " + "deprecated and will be removed in the future. Use " + "'openstack bgp dragent list' CLI instead.") parser = super(ListDRAgentsHostingBgpSpeaker, self).get_parser(prog_name) parser.add_argument('bgp_speaker', metavar='', - help=_("ID or name of the BGP speaker")) + help=_("List dynamic routing agents hosting a " + "BGP speaker (name or ID)")) return parser def take_action(self, parsed_args): @@ -97,3 +104,39 @@ def take_action(self, parsed_args): (utils.get_dict_properties( s, columns, formatters=_formatters, ) for s in data['agents'])) + + +class ListDRAgent(command.Lister): + """List dynamic routing agents""" + + resource = 'agent' + list_columns = ['id', 'host', 'admin_state_up', 'alive'] + unknown_parts_flag = False + + def get_parser(self, prog_name): + parser = super(ListDRAgent, + self).get_parser(prog_name) + parser.add_argument('--bgp-speaker', + metavar='', + help=_("List dynamic routing agents hosting a " + "BGP speaker (name or ID)")) + return parser + + def take_action(self, parsed_args): + search_opts = {} + client = self.app.client_manager.neutronclient + if parsed_args.bgp_speaker is not None: + search_opts = {} + speaker_id = client.find_resource(constants.BGP_SPEAKER, + parsed_args.bgp_speaker)['id'] + search_opts['bgp_speaker'] = speaker_id + data = client.list_dragents_hosting_bgp_speaker(**search_opts) + else: + attrs = {'agent_type': 'BGP dynamic routing agent'} + data = client.list_agents(**attrs) + headers = ('ID', 'Host', 'State', 'Alive') + columns = ('id', 'host', 'admin_state_up', 'alive') + return (headers, + (utils.get_dict_properties( + s, columns, formatters=_formatters, + ) for s in data['agents'])) diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py index 42acbeefd..d425cd67b 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py @@ -57,7 +57,7 @@ def create_bgp_speakers(attrs=None, count=1): """ bgp_speakers = [] - for i in range(0, count): + for i in range(count): bgp_speaker = FakeBgpSpeaker.create_one_bgp_speaker(attrs) bgp_speakers.append(bgp_speaker) @@ -89,8 +89,42 @@ def create_one_bgp_peer(attrs=None): def create_bgp_peers(attrs=None, count=1): """Create one or multiple fake bgp peers.""" bgp_peers = [] - for i in range(0, count): + for i in range(count): bgp_peer = FakeBgpPeer.create_one_bgp_peer(attrs) bgp_peers.append(bgp_peer) return {'bgp_peers': bgp_peers} + + +class FakeDRAgent(object): + """Fake one or more dynamic routing agents.""" + + @staticmethod + def create_one_dragent(attrs=None): + attrs = attrs or {} + # Set default attributes. + dragent_attrs = { + 'binary': 'neutron-bgp-dragent', + 'admin_state_up': True, + 'alive': True, + 'topic': 'bgp_dragent', + 'host': 'network-' + uuid.uuid4().hex, + 'name': 'bgp-dragent-' + uuid.uuid4().hex, + 'agent_type': 'BGP dynamic routing agent', + 'id': uuid.uuid4().hex, + } + + # Overwrite default attributes. + dragent_attrs.update(attrs) + + return copy.deepcopy(dragent_attrs) + + @staticmethod + def create_dragents(attrs=None, count=1): + """Create one or multiple fake dynamic routing agents.""" + agents = [] + for i in range(count): + agent = FakeDRAgent.create_one_dragent(attrs) + agents.append(agent) + + return {'agents': agents} diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py new file mode 100644 index 000000000..1ec7c41f0 --- /dev/null +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py @@ -0,0 +1,123 @@ +# 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 neutronclient.osc.v2.dynamic_routing import bgp_dragent +from neutronclient.tests.unit.osc.v2.dynamic_routing import fakes + + +class TestAddBgpSpeakerToDRAgent(fakes.TestNeutronDynamicRoutingOSCV2): + _bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() + _bgp_dragent = fakes.FakeDRAgent.create_one_dragent() + _bgp_speaker_id = _bgp_speaker['id'] + _bgp_dragent_id = _bgp_dragent['id'] + + def setUp(self): + super(TestAddBgpSpeakerToDRAgent, self).setUp() + + # Get the command object to test + self.cmd = bgp_dragent.AddBgpSpeakerToDRAgent(self.app, self.namespace) + + def test_add_bgp_speaker_to_dragent(self): + arglist = [ + self._bgp_dragent_id, + self._bgp_speaker_id, + ] + verifylist = [ + ('dragent_id', self._bgp_dragent_id), + ('bgp_speaker', self._bgp_speaker_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch.object(self.neutronclient, + "add_bgp_speaker_to_dragent", + return_value=None): + + result = self.cmd.take_action(parsed_args) + self.neutronclient.add_bgp_speaker_to_dragent.\ + assert_called_once_with( + self._bgp_dragent_id, + {'bgp_speaker_id': self._bgp_speaker_id}) + self.assertIsNone(result) + + +class TestRemoveBgpSpeakerFromDRAgent(fakes.TestNeutronDynamicRoutingOSCV2): + _bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() + _bgp_dragent = fakes.FakeDRAgent.create_one_dragent() + _bgp_speaker_id = _bgp_speaker['id'] + _bgp_dragent_id = _bgp_dragent['id'] + + def setUp(self): + super(TestRemoveBgpSpeakerFromDRAgent, self).setUp() + + # Get the command object to test + self.cmd = bgp_dragent.RemoveBgpSpeakerFromDRAgent( + self.app, self.namespace) + + def test_remove_bgp_speaker_from_dragent(self): + arglist = [ + self._bgp_dragent_id, + self._bgp_speaker_id, + ] + verifylist = [ + ('dragent_id', self._bgp_dragent_id), + ('bgp_speaker', self._bgp_speaker_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch.object(self.neutronclient, + "remove_bgp_speaker_from_dragent", + return_value=None): + result = self.cmd.take_action(parsed_args) + self.neutronclient.remove_bgp_speaker_from_dragent.\ + assert_called_once_with(self._bgp_dragent_id, + self._bgp_speaker_id) + self.assertIsNone(result) + + +class TestListDRAgentsHostingBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): + _bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() + _bgp_speaker_id = _bgp_speaker['id'] + attrs = {'bgp_speaker_id': _bgp_speaker_id} + _bgp_dragents = fakes.FakeDRAgent.create_dragents(attrs) + columns = ('ID', 'Host', 'State', 'Alive') + data = [(_bgp_dragent['id'], + _bgp_dragent['host'], + _bgp_dragent['admin_state_up'], + ':-)' if _bgp_dragent['alive'] else 'XXX') + for _bgp_dragent in _bgp_dragents['agents']] + + def setUp(self): + super(TestListDRAgentsHostingBgpSpeaker, self).setUp() + + # Get the command object to test + self.cmd = bgp_dragent.ListDRAgent(self.app, self.namespace) + + def test_list_dragents_hosting_bgp_speaker(self): + arglist = [ + '--bgp-speaker', self._bgp_speaker_id, + ] + verifylist = [ + ('bgp_speaker', self._bgp_speaker_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch.object(self.neutronclient, + "list_dragents_hosting_bgp_speaker", + return_value=self._bgp_dragents): + columns, data = self.cmd.take_action(parsed_args) + attrs = {'bgp_speaker': self._bgp_speaker_id} + self.neutronclient.list_dragents_hosting_bgp_speaker.\ + assert_called_once_with(**attrs) + self.assertEqual(self.columns, columns) + self.assertListEqual(self.data, list(data)) diff --git a/releasenotes/notes/deprecate-bgp-speaker-show-dragents-2fcce99cf6bb5b60.yaml b/releasenotes/notes/deprecate-bgp-speaker-show-dragents-2fcce99cf6bb5b60.yaml new file mode 100644 index 000000000..6233c6f4f --- /dev/null +++ b/releasenotes/notes/deprecate-bgp-speaker-show-dragents-2fcce99cf6bb5b60.yaml @@ -0,0 +1,10 @@ +--- +deprecations: + - | + The ``openstack bgp speaker show dragents`` CLI is deprecated and + will be removed in the future. Use ``openstack bgp dragent list + --bgp-speaker `` CLI instead. +features: + - | + The ``openstack bgp dragent list`` CLI is added to support showing + the list of dynamic routing agents. diff --git a/setup.cfg b/setup.cfg index 16cfc5aef..d1fb096c2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -70,6 +70,7 @@ openstack.neutronclient.v2 = sfc_service_graph_show = neutronclient.osc.v2.sfc.sfc_service_graph:ShowSfcServiceGraph bgp_dragent_add_speaker = neutronclient.osc.v2.dynamic_routing.bgp_dragent:AddBgpSpeakerToDRAgent + bgp_dragent_list = neutronclient.osc.v2.dynamic_routing.bgp_dragent:ListDRAgent bgp_dragent_remove_speaker = neutronclient.osc.v2.dynamic_routing.bgp_dragent:RemoveBgpSpeakerFromDRAgent bgp_peer_create = neutronclient.osc.v2.dynamic_routing.bgp_peer:CreateBgpPeer bgp_peer_delete = neutronclient.osc.v2.dynamic_routing.bgp_peer:DeleteBgpPeer From ac04e5d415c03f8594e1d3344c51bfe6c9d3a49d Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Sat, 4 Apr 2020 17:05:21 +0200 Subject: [PATCH 046/149] Cleanup py27 support Make a few cleanups: - Remove python 2.7 stanza from setup.py - Add requires on python >= 3.6 to setup.cfg so that pypi and pip know about the requirement - Remove obsolete sections from setup.cfg - Update classifiers - Update requirements, no need for python_version anymore - Remove html_last_updated_fmt from conf.py, this is not needed with openstackdocstheme anymore; update openstackdocstheme requirement Change-Id: I66d7b502349de38bc2b646ed99cf5a41471d81bf --- doc/requirements.txt | 5 ++--- doc/source/conf.py | 1 - lower-constraints.txt | 2 +- releasenotes/source/conf.py | 1 - setup.cfg | 7 +++---- setup.py | 9 --------- 6 files changed, 6 insertions(+), 19 deletions(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index af1aeb8b3..8dc65ed51 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,7 +1,6 @@ # The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -openstackdocstheme>=1.18.1 # Apache-2.0 +openstackdocstheme>=1.32.1 # Apache-2.0 reno>=2.5.0 # Apache-2.0 -sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD -sphinx!=1.6.6,!=1.6.7,>=1.6.2;python_version>='3.4' # BSD +sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD diff --git a/doc/source/conf.py b/doc/source/conf.py index 294de7129..4b4300592 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -16,7 +16,6 @@ repository_name = 'openstack/python-neutronclient' bug_project = 'python-neutronclient' bug_tag = 'doc' -html_last_updated_fmt = '%Y-%m-%d %H:%M' # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/lower-constraints.txt b/lower-constraints.txt index b37c137a0..3a51d5545 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -46,7 +46,7 @@ msgpack-python==0.4.0 munch==2.1.0 netaddr==0.7.18 netifaces==0.10.4 -openstackdocstheme==1.18.1 +openstackdocstheme==1.32.1 openstacksdk==0.11.2 os-client-config==1.28.0 os-service-types==1.2.0 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py index a029757ed..f7ec3924b 100644 --- a/releasenotes/source/conf.py +++ b/releasenotes/source/conf.py @@ -46,7 +46,6 @@ repository_name = 'openstack/python-neutronclient' bug_project = 'python-neutronclient' bug_tag = 'doc' -html_last_updated_fmt = '%Y-%m-%d %H:%M' # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/setup.cfg b/setup.cfg index d1fb096c2..f9a0f431a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,6 +6,7 @@ description-file = author = OpenStack Networking Project author-email = openstack-discuss@lists.openstack.org home-page = https://docs.openstack.org/python-neutronclient/latest/ +python-requires = >=3.6 classifier = Environment :: OpenStack Intended Audience :: Developers @@ -14,6 +15,8 @@ classifier = License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python + Programming Language :: Python :: Implementation :: CPython + Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 @@ -22,10 +25,6 @@ classifier = packages = neutronclient -[global] -setup-hooks = - pbr.hooks.setup_hook - [entry_points] console_scripts = neutron = neutronclient.shell:main diff --git a/setup.py b/setup.py index 566d84432..cd35c3c35 100644 --- a/setup.py +++ b/setup.py @@ -13,17 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) From 91a9dcd94b3565179199edaad9eb367a93010b1e Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Sat, 11 Apr 2020 18:47:39 +0000 Subject: [PATCH 047/149] Update master for stable/ussuri Add file to the reno documentation build to show release notes for stable/ussuri. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/ussuri. Change-Id: Id46b2b493579dcf984e537d81392c792c9d9aeea Sem-Ver: feature --- releasenotes/source/index.rst | 1 + releasenotes/source/ussuri.rst | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/ussuri.rst diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index f5df8b776..ac3d918a3 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + ussuri train stein rocky diff --git a/releasenotes/source/ussuri.rst b/releasenotes/source/ussuri.rst new file mode 100644 index 000000000..e21e50e0c --- /dev/null +++ b/releasenotes/source/ussuri.rst @@ -0,0 +1,6 @@ +=========================== +Ussuri Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/ussuri From ec625d0e93aef69881aaadc2a4b2cea0f5e1dad7 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Sat, 11 Apr 2020 18:47:45 +0000 Subject: [PATCH 048/149] Add Python3 victoria unit tests This is an automatically generated patch to ensure unit testing is in place for all the of the tested runtimes for victoria. See also the PTI in governance [1]. [1]: https://governance.openstack.org/tc/reference/project-testing-interface.html Change-Id: I817e39d2229ffc803fd285d4bedfcad86a450c05 --- .zuul.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zuul.yaml b/.zuul.yaml index b6685df2e..e956eba72 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -2,7 +2,7 @@ templates: - openstack-cover-jobs - openstack-lower-constraints-jobs - - openstack-python3-ussuri-jobs + - openstack-python3-victoria-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing-python3 From 157016ea3c3f6e9804af60dd748919cd3d942092 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 17 Apr 2020 15:46:04 +0200 Subject: [PATCH 049/149] Remove Babel from requirements It's not a runtime dependency (and even oslo.i18n has dropped it). The translation infrastructure installs Babel explicitly. See this mailing list thread for a full reasoning: http://lists.openstack.org/pipermail/openstack-discuss/2020-April/014227.html Keeping Babel in lower-constraints since other projects still pull it. Change-Id: I1c92bd28c3f54368b591b965b5f904c8fda424e0 --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ec2d7af87..5204dc21e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,4 +19,3 @@ python-keystoneclient>=3.8.0 # Apache-2.0 requests>=2.14.2 # Apache-2.0 simplejson>=3.5.1 # MIT six>=1.10.0 # MIT -Babel!=2.4.0,>=2.3.4 # BSD From 19bea622eae7382239f394588a67ab6e4715f7b0 Mon Sep 17 00:00:00 2001 From: Sean McGinnis Date: Fri, 24 Apr 2020 08:23:17 -0500 Subject: [PATCH 050/149] Add py38 package metadata Now that we are running the Victoria tests that include a voting py38, we can now add the Python 3.8 metadata to the package information to reflect that support. Change-Id: I449ba49cd8c2c8c9890b603c298295c56a5df6de Signed-off-by: Sean McGinnis --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index f9a0f431a..70c0d62b9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,6 +20,7 @@ classifier = Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [files] packages = From fdfa615b8edcf1bd2a3c27a4644d88e75e97e3dc Mon Sep 17 00:00:00 2001 From: Sean McGinnis Date: Fri, 24 Apr 2020 10:25:56 -0500 Subject: [PATCH 051/149] Bump default tox env from py37 to py38 Python 3.8 is now our highest level supported python runtime. This updates the default tox target environments to swap out py37 for py38 to make sure local development testing is covering this version. This does not impact zuul jobs in any way, nor prevent local tests against py37. It just changes the default if none is explicitly provided. Change-Id: I026ae0fae10114d9aed8bdb0ae7061b3dc2ff895 Signed-off-by: Sean McGinnis --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index fa1f9e209..c4de1cd1e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py37,pep8 +envlist = py38,pep8 minversion = 2.3.2 skipsdist = True ignore_basepython_conflict = True From 6d9d2e62915edcf6a5796984012ce17e1d87f1c5 Mon Sep 17 00:00:00 2001 From: Ghanshyam Mann Date: Tue, 12 May 2020 19:47:38 -0500 Subject: [PATCH 052/149] Fix hacking min version to 3.0.1 flake8 new release 3.8.0 added new checks and gate pep8 job start failing. hacking 3.0.1 fix the pinning of flake8 to avoid bringing in a new version with new checks. Though it is fixed in latest hacking but 2.0 and 3.0 has cap for flake8 as <4.0.0 which mean flake8 new version 3.9.0 can also break the pep8 job if new check are added. To avoid similar gate break in future, we need to bump the hacking min version. - http://lists.openstack.org/pipermail/openstack-discuss/2020-May/014828.html Change-Id: I5486638526b26ce0710c7b1926e408dd70057a66 --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index a1eb9b1d1..a0d76ed70 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,7 +1,7 @@ # The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -hacking>=1.1.0 # Apache-2.0 +hacking>=3.0.1,<3.1.0 # Apache-2.0 bandit!=1.6.0,>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 From c8d61703c2e74c559b601cf23d1aa59366b32874 Mon Sep 17 00:00:00 2001 From: zhanghao Date: Wed, 13 May 2020 05:04:55 -0400 Subject: [PATCH 053/149] Add aggressive negotiation mode for ikepolicy The phase1 negotiation mode adds support for aggressive mode, which can be selected when creating an ikepolicy. Change-Id: I8148011558094db07b5f9eba70b16cfe6eeaf98f Partial-Bug: #1701413 --- neutronclient/osc/v2/vpnaas/ikepolicy.py | 2 +- .../unit/osc/v2/vpnaas/test_ikepolicy.py | 20 +++++++++++++++++++ ...ive-negotiation-mode-5218b1baff930eb8.yaml | 5 +++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/add-aggressive-negotiation-mode-5218b1baff930eb8.yaml diff --git a/neutronclient/osc/v2/vpnaas/ikepolicy.py b/neutronclient/osc/v2/vpnaas/ikepolicy.py index eb598ead2..73b6402d3 100644 --- a/neutronclient/osc/v2/vpnaas/ikepolicy.py +++ b/neutronclient/osc/v2/vpnaas/ikepolicy.py @@ -64,7 +64,7 @@ def _get_common_parser(parser): help=_('Encryption algorithm')) parser.add_argument( '--phase1-negotiation-mode', - choices=['main'], + choices=['main', 'aggressive'], type=_convert_to_lowercase, help=_('IKE Phase1 negotiation mode')) parser.add_argument( diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py index 24663d6a2..fd621fde5 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py @@ -208,6 +208,10 @@ def test_create_with_all_params(self): def test_create_with_all_params_name(self): self._test_create_with_all_params({'name': 'new_ikepolicy'}) + def test_create_with_all_params_aggressive_mode(self): + self._test_create_with_all_params( + {'phase1_negotiation_mode': 'aggressive'}) + class TestDeleteIKEPolicy(TestIKEPolicy, common.TestDeleteVPNaaS): @@ -292,6 +296,22 @@ def test_set_auth_algorithm_with_sha256(self): target, {self.res: {'auth_algorithm': 'sha256'}}) self.assertIsNone(result) + def test_set_phase1_negotiation_mode_with_aggressive(self): + target = self.resource['id'] + phase1_negotiation_mode = 'aggressive' + arglist = [target, + '--phase1-negotiation-mode', phase1_negotiation_mode] + verifylist = [ + (self.res, target), + ('phase1_negotiation_mode', phase1_negotiation_mode), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + self.mocked.assert_called_once_with( + target, {self.res: {'phase1_negotiation_mode': 'aggressive'}}) + self.assertIsNone(result) + class TestShowIKEPolicy(TestIKEPolicy, common.TestShowVPNaaS): diff --git a/releasenotes/notes/add-aggressive-negotiation-mode-5218b1baff930eb8.yaml b/releasenotes/notes/add-aggressive-negotiation-mode-5218b1baff930eb8.yaml new file mode 100644 index 000000000..ae1b6672f --- /dev/null +++ b/releasenotes/notes/add-aggressive-negotiation-mode-5218b1baff930eb8.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + The ``--phase1-negotiation-mode`` option supports ``aggressive`` mode + in VPNaaS ikepolicy commands. From 85ef7b7108ffe491749b52f9ffccade1e2a66164 Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Mon, 18 May 2020 22:08:18 +0200 Subject: [PATCH 054/149] Switch to newer openstackdocstheme and reno versions Switch to openstackdocstheme 2.2.0 and reno 3.1.0 versions. Using these versions will allow especially: * Linking from HTML to PDF document * Allow parallel building of documents * Fix some rendering problems Update Sphinx version as well. Remove docs requirements from lower-constraints, they are not needed during install or test but only for docs building. openstackdocstheme renames some variables, so follow the renames before the next release removes them. A couple of variables are also not needed anymore, remove them. Set openstackdocs_pdf_link to link to PDF file. Note that the link to the published document only works on docs.openstack.org where the PDF file is placed in the top-level html directory. The site-preview places the PDF in a pdf directory. Set openstackdocs_auto_name to use 'project' as name. Depends-On: https://review.opendev.org/728938 Change-Id: I9e1dcc5c8861ac9d800ed7425b3e3193dd13c546 --- doc/requirements.txt | 6 +++--- doc/source/conf.py | 7 ++++--- lower-constraints.txt | 4 ---- releasenotes/source/conf.py | 11 ++++------- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index 8dc65ed51..76ce5cd3f 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,6 +1,6 @@ # The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -openstackdocstheme>=1.32.1 # Apache-2.0 -reno>=2.5.0 # Apache-2.0 -sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD +openstackdocstheme>=2.2.0 # Apache-2.0 +reno>=3.1.0 # Apache-2.0 +sphinx>=2.0.0,!=2.1.0 # BSD diff --git a/doc/source/conf.py b/doc/source/conf.py index 4b4300592..e3e269e25 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -13,9 +13,10 @@ ] # openstackdocstheme options -repository_name = 'openstack/python-neutronclient' -bug_project = 'python-neutronclient' -bug_tag = 'doc' +openstackdocs_repo_name = 'openstack/python-neutronclient' +openstackdocs_pdf_link = True +openstackdocs_bug_project = 'python-neutronclient' +openstackdocs_bug_tag = 'doc' # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/lower-constraints.txt b/lower-constraints.txt index 3a51d5545..08d37a452 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -46,7 +46,6 @@ msgpack-python==0.4.0 munch==2.1.0 netaddr==0.7.18 netifaces==0.10.4 -openstackdocstheme==1.32.1 openstacksdk==0.11.2 os-client-config==1.28.0 os-service-types==1.2.0 @@ -91,7 +90,6 @@ python-openstackclient==3.12.0 python-subunit==1.0.0 pytz==2013.6 PyYAML==3.12 -reno==2.5.0 repoze.lru==0.7 requests-mock==1.2.0 requests==2.14.2 @@ -101,8 +99,6 @@ Routes==2.3.1 simplejson==3.5.1 six==1.10.0 snowballstemmer==1.2.1 -Sphinx==1.6.2 -sphinxcontrib-websupport==1.0.1 statsd==3.2.1 stestr==2.0.0 stevedore==1.20.0 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py index f7ec3924b..5b075fe21 100644 --- a/releasenotes/source/conf.py +++ b/releasenotes/source/conf.py @@ -43,9 +43,10 @@ ] # openstackdocstheme options -repository_name = 'openstack/python-neutronclient' -bug_project = 'python-neutronclient' -bug_tag = 'doc' +openstackdocs_repo_name = 'openstack/python-neutronclient' +openstackdocs_bug_project = 'python-neutronclient' +openstackdocs_bug_tag = 'doc' +openstackdocs_auto_name = False # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -148,10 +149,6 @@ # directly to the root of the documentation. # html_extra_path = [] -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True From 3cfa54fa56674362ffbbbd3199e6be3c0e4ffbb9 Mon Sep 17 00:00:00 2001 From: zhanghao Date: Thu, 14 May 2020 02:03:50 -0400 Subject: [PATCH 055/149] Remove usage of six With python3.x, classes can use 'metaclass=' instead of 'six.add_metaclass', 'six.iteritems' and 'six.iterkeys' can be replaced by 'items' and 'keys', 'six.moves.urllib.parse' can be replaced by 'urllib.parse', 'six.StringIO' and 'six.moves.cStringIO' can be replaced by 'io.StringIO', 'six.text_type' and 'six.string_type' are just 'str'. Change-Id: I357968c6a1932856b1600f6c191966bc90cbc258 --- lower-constraints.txt | 1 - neutronclient/common/exceptions.py | 2 -- neutronclient/common/serializer.py | 3 +-- neutronclient/common/utils.py | 5 ++--- neutronclient/neutron/v2_0/__init__.py | 16 +++++++--------- neutronclient/neutron/v2_0/lb/pool.py | 5 +---- .../neutron/v2_0/network_ip_availability.py | 3 +-- neutronclient/neutron/v2_0/quota.py | 7 +++---- neutronclient/tests/unit/test_casual_args.py | 5 ++--- neutronclient/tests/unit/test_cli20.py | 16 ++++++++-------- .../tests/unit/test_cli20_securitygroup.py | 4 ++-- neutronclient/tests/unit/test_exceptions.py | 3 +-- neutronclient/tests/unit/test_http.py | 4 +--- neutronclient/tests/unit/test_shell.py | 6 +++--- neutronclient/v2_0/client.py | 5 ++--- requirements.txt | 1 - 16 files changed, 34 insertions(+), 52 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index 08d37a452..48b0056b0 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -97,7 +97,6 @@ requestsexceptions==1.2.0 rfc3986==0.3.1 Routes==2.3.1 simplejson==3.5.1 -six==1.10.0 snowballstemmer==1.2.1 statsd==3.2.1 stestr==2.0.0 diff --git a/neutronclient/common/exceptions.py b/neutronclient/common/exceptions.py index 1040ee120..443f78155 100644 --- a/neutronclient/common/exceptions.py +++ b/neutronclient/common/exceptions.py @@ -14,7 +14,6 @@ # under the License. from oslo_utils import encodeutils -import six from neutronclient._i18n import _ @@ -40,7 +39,6 @@ def _safe_decode_dict(kwargs): return kwargs -@six.python_2_unicode_compatible class NeutronException(Exception): """Base Neutron Exception. diff --git a/neutronclient/common/serializer.py b/neutronclient/common/serializer.py index 98865a6b3..d4c8bbbb6 100644 --- a/neutronclient/common/serializer.py +++ b/neutronclient/common/serializer.py @@ -14,7 +14,6 @@ # under the License. from oslo_serialization import jsonutils -import six from neutronclient._i18n import _ from neutronclient.common import exceptions as exception @@ -48,7 +47,7 @@ class JSONDictSerializer(DictSerializer): def default(self, data): def sanitizer(obj): - return six.text_type(obj) + return str(obj) return jsonutils.dumps(data, default=sanitizer) diff --git a/neutronclient/common/utils.py b/neutronclient/common/utils.py index b61ee3b7a..38274018c 100644 --- a/neutronclient/common/utils.py +++ b/neutronclient/common/utils.py @@ -25,7 +25,6 @@ from oslo_utils import encodeutils from oslo_utils import importutils -import six from neutronclient._i18n import _ from neutronclient.common import exceptions @@ -180,7 +179,7 @@ def http_log_req(_logger, args, kwargs): else: string_parts.append(' %s' % element) - for (key, value) in six.iteritems(kwargs['headers']): + for (key, value) in kwargs['headers'].items(): if key in SENSITIVE_HEADERS: v = value.encode('utf-8') h = hashlib.sha256(v) @@ -205,7 +204,7 @@ def http_log_resp(_logger, resp, body): def _safe_encode_without_obj(data): - if isinstance(data, six.string_types): + if isinstance(data, str): return encodeutils.safe_encode(data) return data diff --git a/neutronclient/neutron/v2_0/__init__.py b/neutronclient/neutron/v2_0/__init__.py index a5b262c93..3a6e086ee 100644 --- a/neutronclient/neutron/v2_0/__init__.py +++ b/neutronclient/neutron/v2_0/__init__.py @@ -25,7 +25,6 @@ from cliff import lister from cliff import show from oslo_serialization import jsonutils -import six from neutronclient._i18n import _ from neutronclient.common import exceptions @@ -261,12 +260,12 @@ def parse_args_to_dict(values_specs): # Populate the parser with arguments _parser = argparse.ArgumentParser(add_help=False) - for opt, optspec in six.iteritems(_options): + for opt, optspec in _options.items(): _parser.add_argument(opt, **optspec) _args = _parser.parse_args(_values_specs) result_dict = {} - for opt in six.iterkeys(_options): + for opt in _options.keys(): _opt = opt.split('--', 2)[1] _opt = _opt.replace('-', '_') _value = getattr(_args, _opt) @@ -285,7 +284,7 @@ def _merge_args(qCmd, parsed_args, _extra_values, value_specs): @param values_specs: the unparsed unknown parts """ temp_values = _extra_values.copy() - for key, value in six.iteritems(temp_values): + for key, value in temp_values.items(): if hasattr(parsed_args, key): arg_value = getattr(parsed_args, key) if arg_value is not None and value is not None: @@ -321,8 +320,7 @@ def __new__(cls, name, bases, cls_dict): name, bases, cls_dict) -@six.add_metaclass(NeutronCommandMeta) -class NeutronCommand(command.Command): +class NeutronCommand(command.Command, metaclass=NeutronCommandMeta): values_specs = [] json_indent = None @@ -363,7 +361,7 @@ def cleanup_output_data(self, data): def format_output_data(self, data): # Modify data to make it more readable if self.resource in data: - for k, v in six.iteritems(data[self.resource]): + for k, v in data[self.resource].items(): if isinstance(v, list): value = '\n'.join(jsonutils.dumps( i, indent=self.json_indent) if isinstance(i, dict) @@ -425,7 +423,7 @@ def take_action(self, parsed_args): file=self.app.stdout) else: info = {'': ''} - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class UpdateCommand(NeutronCommand): @@ -825,6 +823,6 @@ def take_action(self, parsed_args): self.format_output_data(data) resource = data[self.resource] if self.resource in data: - return zip(*sorted(six.iteritems(resource))) + return zip(*sorted(resource.items())) else: return None diff --git a/neutronclient/neutron/v2_0/lb/pool.py b/neutronclient/neutron/v2_0/lb/pool.py index afc0cc13e..5684e8e6a 100644 --- a/neutronclient/neutron/v2_0/lb/pool.py +++ b/neutronclient/neutron/v2_0/lb/pool.py @@ -14,9 +14,6 @@ # under the License. # - -import six - from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 @@ -119,6 +116,6 @@ def take_action(self, parsed_args): self.format_output_data(data) stats = data['stats'] if 'stats' in data: - return zip(*sorted(six.iteritems(stats))) + return zip(*sorted(stats.items())) else: return None diff --git a/neutronclient/neutron/v2_0/network_ip_availability.py b/neutronclient/neutron/v2_0/network_ip_availability.py index d1332a21c..ba7af8f80 100644 --- a/neutronclient/neutron/v2_0/network_ip_availability.py +++ b/neutronclient/neutron/v2_0/network_ip_availability.py @@ -12,7 +12,6 @@ # from cliff import show -import six from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 @@ -68,6 +67,6 @@ def take_action(self, parsed_args): self.format_output_data(data) resource = data[self.resource] if self.resource in data: - return zip(*sorted(six.iteritems(resource))) + return zip(*sorted(resource.items())) else: return None diff --git a/neutronclient/neutron/v2_0/quota.py b/neutronclient/neutron/v2_0/quota.py index 6e7058d8c..1a59ac546 100644 --- a/neutronclient/neutron/v2_0/quota.py +++ b/neutronclient/neutron/v2_0/quota.py @@ -22,7 +22,6 @@ from cliff import lister from cliff import show from oslo_serialization import jsonutils -import six from neutronclient._i18n import _ from neutronclient.common import exceptions @@ -121,7 +120,7 @@ def take_action(self, parsed_args): tenant_id = get_tenant_id(parsed_args, neutron_client) data = self.retrieve_data(tenant_id, neutron_client) if self.resource in data: - return zip(*sorted(six.iteritems(data[self.resource]))) + return zip(*sorted(data[self.resource].items())) return @@ -241,7 +240,7 @@ def take_action(self, parsed_args): tenant_id = get_tenant_id(parsed_args, neutron_client) data = obj_updator(tenant_id, body) if self.resource in data: - for k, v in six.iteritems(data[self.resource]): + for k, v in data[self.resource].items(): if isinstance(v, list): value = "" for _item in v: @@ -254,6 +253,6 @@ def take_action(self, parsed_args): data[self.resource][k] = value elif v is None: data[self.resource][k] = '' - return zip(*sorted(six.iteritems(data[self.resource]))) + return zip(*sorted(data[self.resource].items())) else: return diff --git a/neutronclient/tests/unit/test_casual_args.py b/neutronclient/tests/unit/test_casual_args.py index f2ca03101..cbf061617 100644 --- a/neutronclient/tests/unit/test_casual_args.py +++ b/neutronclient/tests/unit/test_casual_args.py @@ -14,7 +14,6 @@ # under the License. # -import six import testtools from neutronclient.common import exceptions @@ -116,7 +115,7 @@ def test_parse_args_to_dict_bad_type(self): neutronV20.parse_args_to_dict, _specs) self.assertEqual('Invalid value_specs --badtypearg type=badtype val1: ' 'type badtype is not supported', - six.text_type(ex)) + str(ex)) def test_clear_action(self): _specs = ['--anyarg', 'action=clear'] @@ -128,7 +127,7 @@ def test_bad_values_str_without_value(self): ex = self.assertRaises(exceptions.CommandError, neutronV20.parse_args_to_dict, _specs) self.assertEqual('Invalid values_specs --strarg type=str', - six.text_type(ex)) + str(ex)) def test_bad_values_list(self): _specs = ['--listarg', 'list=true', 'type=str'] diff --git a/neutronclient/tests/unit/test_cli20.py b/neutronclient/tests/unit/test_cli20.py index 3a8bb4719..73104b54c 100644 --- a/neutronclient/tests/unit/test_cli20.py +++ b/neutronclient/tests/unit/test_cli20.py @@ -15,16 +15,16 @@ # import contextlib +from io import StringIO import itertools import sys +import urllib.parse as urlparse import mock from oslo_serialization import jsonutils from oslo_utils import encodeutils from oslotest import base import requests -import six -import six.moves.urllib.parse as urlparse import yaml from neutronclient.common import constants @@ -43,7 +43,7 @@ @contextlib.contextmanager def capture_std_streams(): - fake_stdout, fake_stderr = six.StringIO(), six.StringIO() + fake_stdout, fake_stderr = StringIO(), StringIO() stdout, stderr = sys.stdout, sys.stderr try: sys.stdout, sys.stderr = fake_stdout, fake_stderr @@ -125,7 +125,7 @@ def __init__(self, lhs, client): def _com_dict(self, lhs, rhs): if len(lhs) != len(rhs): return False - for key, value in six.iteritems(lhs): + for key, value in lhs.items(): if key not in rhs: return False rhs_value = rhs[key] @@ -743,7 +743,7 @@ def test_do_request_unicode(self): def test_do_request_error_without_response_body(self): params = {'test': 'value'} - expect_query = six.moves.urllib.parse.urlencode(params) + expect_query = urlparse.urlencode(params) self.client.httpclient.auth_token = 'token' resp_headers = {'x-openstack-request-id': REQUEST_ID} resp = (MyResp(400, headers=resp_headers, reason='An error'), '') @@ -772,7 +772,7 @@ def test_do_request_with_long_uri_exception(self): def test_do_request_request_ids(self): params = {'test': 'value'} - expect_query = six.moves.urllib.parse.urlencode(params) + expect_query = urlparse.urlencode(params) self.client.httpclient.auth_token = 'token' body = params expect_body = self.client.serialize(body) @@ -866,7 +866,7 @@ def test_deserialize_without_data(self): def test_update_resource(self): params = {'test': 'value'} - expect_query = six.moves.urllib.parse.urlencode(params) + expect_query = urlparse.urlencode(params) self.client.httpclient.auth_token = 'token' body = params expect_body = self.client.serialize(body) @@ -889,7 +889,7 @@ def test_update_resource(self): def test_update_resource_with_revision_number(self): params = {'test': 'value'} - expect_query = six.moves.urllib.parse.urlencode(params) + expect_query = urlparse.urlencode(params) self.client.httpclient.auth_token = 'token' body = params expect_body = self.client.serialize(body) diff --git a/neutronclient/tests/unit/test_cli20_securitygroup.py b/neutronclient/tests/unit/test_cli20_securitygroup.py index 0f5a240cf..010f7dcae 100644 --- a/neutronclient/tests/unit/test_cli20_securitygroup.py +++ b/neutronclient/tests/unit/test_cli20_securitygroup.py @@ -15,10 +15,10 @@ # under the License. import sys +import urllib.parse as urlparse import mock from oslo_utils import uuidutils -import six from neutronclient.common import exceptions from neutronclient.common import utils @@ -250,7 +250,7 @@ def _build_test_data(self, data, excess=0): resp_str = self.client.serialize({'security_groups': response}) result.append({ - 'filter': six.moves.urllib.parse.urlencode(params, doseq=1), + 'filter': urlparse.urlencode(params, doseq=1), 'response': (test_cli20.MyResp(200), resp_str), }) diff --git a/neutronclient/tests/unit/test_exceptions.py b/neutronclient/tests/unit/test_exceptions.py index aefc24c66..50b2bdbbe 100644 --- a/neutronclient/tests/unit/test_exceptions.py +++ b/neutronclient/tests/unit/test_exceptions.py @@ -16,7 +16,6 @@ import mock from oslo_utils import encodeutils -import six import testtools from neutronclient._i18n import _ @@ -46,4 +45,4 @@ class TestException(exceptions.NeutronException): multibyte_binary = encodeutils.safe_encode(multibyte_string) e = TestException(reason=multibyte_binary) self.assertEqual('Exception with %s' % multibyte_string, - six.text_type(e)) + str(e)) diff --git a/neutronclient/tests/unit/test_http.py b/neutronclient/tests/unit/test_http.py index d76e9bce9..5680d4375 100644 --- a/neutronclient/tests/unit/test_http.py +++ b/neutronclient/tests/unit/test_http.py @@ -19,7 +19,6 @@ import osprofiler.profiler import osprofiler.web from requests_mock.contrib import fixture as mock_fixture -import six import testtools from neutronclient import client @@ -33,8 +32,7 @@ BODY = 'IAMFAKE' -@six.add_metaclass(abc.ABCMeta) -class TestHTTPClientMixin(object): +class TestHTTPClientMixin(object, metaclass=abc.ABCMeta): def setUp(self): super(TestHTTPClientMixin, self).setUp() diff --git a/neutronclient/tests/unit/test_shell.py b/neutronclient/tests/unit/test_shell.py index 0395d6233..86250a139 100644 --- a/neutronclient/tests/unit/test_shell.py +++ b/neutronclient/tests/unit/test_shell.py @@ -14,6 +14,7 @@ # under the License. import argparse +from io import StringIO import logging import os import re @@ -22,7 +23,6 @@ import fixtures from keystoneauth1 import session import mock -import six import testtools from testtools import matchers @@ -75,8 +75,8 @@ def shell(self, argstr, check=False, expected_val=0): clean_env = {} _old_env, os.environ = os.environ, clean_env.copy() try: - sys.stdout = six.moves.cStringIO() - sys.stderr = six.moves.cStringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() _shell = openstack_shell.NeutronShell('2.0') _shell.run(argstr.split()) except SystemExit: diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index 5fa869840..13f90e42d 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -21,12 +21,11 @@ import logging import re import time +import urllib.parse as urlparse import debtcollector.renames from keystoneauth1 import exceptions as ksa_exc import requests -import six.moves.urllib.parse as urlparse -from six import string_types from neutronclient._i18n import _ from neutronclient import client @@ -398,7 +397,7 @@ def _convert_into_with_meta(self, item, resp): if item: if isinstance(item, dict): return _DictWithMeta(item, resp) - elif isinstance(item, string_types): + elif isinstance(item, str): return _StrWithMeta(item, resp) else: return _TupleWithMeta((), resp) diff --git a/requirements.txt b/requirements.txt index 5204dc21e..c1c9c28e3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,4 +18,3 @@ keystoneauth1>=3.4.0 # Apache-2.0 python-keystoneclient>=3.8.0 # Apache-2.0 requests>=2.14.2 # Apache-2.0 simplejson>=3.5.1 # MIT -six>=1.10.0 # MIT From 626970a353c158158173dac0730cf1204fcf2f11 Mon Sep 17 00:00:00 2001 From: elajkat Date: Fri, 8 May 2020 12:17:40 +0200 Subject: [PATCH 056/149] Add segments client code Related-Bug: #1878632 Needed-By: https://review.opendev.org/728904 Change-Id: I85b8e7b3fb84e7e9fd133edffc300a83eeb7c56d --- neutronclient/v2_0/client.py | 25 +++++++++++++++++++ .../notes/segments-8557f5b0caa5ee26.yaml | 5 ++++ 2 files changed, 30 insertions(+) create mode 100644 releasenotes/notes/segments-8557f5b0caa5ee26.yaml diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index 5fa869840..0cc48ea24 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -516,6 +516,8 @@ class Client(ClientBase): security_group_path = "/security-groups/%s" security_group_rules_path = "/security-group-rules" security_group_rule_path = "/security-group-rules/%s" + segments_path = "/segments" + segment_path = "/segments/%s" sfc_flow_classifiers_path = "/sfc/flow_classifiers" sfc_flow_classifier_path = "/sfc/flow_classifiers/%s" @@ -669,6 +671,7 @@ class Client(ClientBase): 'service_definitions': 'service_definition', 'security_groups': 'security_group', 'security_group_rules': 'security_group_rule', + 'segments': 'segment', 'ipsecpolicies': 'ipsecpolicy', 'ikepolicies': 'ikepolicy', 'ipsec_site_connections': 'ipsec_site_connection', @@ -1048,6 +1051,28 @@ def show_security_group_rule(self, security_group_rule, **_params): return self.get(self.security_group_rule_path % (security_group_rule), params=_params) + def create_segment(self, body=None): + """Creates a new segment.""" + return self.post(self.segments_path, body=body) + + def update_segment(self, segment, body=None, revision_number=None): + """Updates a segment.""" + return self._update_resource(self.segment_path % segment, body=body, + revision_number=revision_number) + + def list_segments(self, retrieve_all=True, **_params): + """Fetches a list of all segments for a project.""" + return self.list('segments', self.segments_path, retrieve_all, + **_params) + + def show_segment(self, segment, **_params): + """Fetches information of a certain segment.""" + return self.get(self.segment_path % segment, params=_params) + + def delete_segment(self, segment): + """Deletes the specified segment.""" + return self.delete(self.segment_path % segment) + def list_endpoint_groups(self, retrieve_all=True, **_params): """Fetches a list of all VPN endpoint groups for a project.""" return self.list('endpoint_groups', self.endpoint_groups_path, diff --git a/releasenotes/notes/segments-8557f5b0caa5ee26.yaml b/releasenotes/notes/segments-8557f5b0caa5ee26.yaml new file mode 100644 index 000000000..292adf85e --- /dev/null +++ b/releasenotes/notes/segments-8557f5b0caa5ee26.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + New client methods: ``create_segment``, ``update_segment``, + ``list_segments``, ``show_segment`` and ``delete_segment``. From 4669bcc6280ba7d6776d6bdf6d6d1c34c87298e6 Mon Sep 17 00:00:00 2001 From: Sean McGinnis Date: Sat, 18 Apr 2020 11:58:59 -0500 Subject: [PATCH 057/149] Use unittest.mock instead of third party mock Now that we no longer support py27, we can use the standard library unittest.mock module instead of the third party mock lib. Change-Id: I12e1a2a4a22116cabd09a3b808f871d98e4bd1f2 Signed-off-by: Sean McGinnis --- lower-constraints.txt | 1 - neutronclient/tests/unit/bgp/test_cli20_speaker.py | 2 +- neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py | 2 +- neutronclient/tests/unit/lb/test_cli20_healthmonitor.py | 2 +- neutronclient/tests/unit/lb/test_cli20_pool.py | 2 +- neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py | 2 +- neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py | 2 +- .../tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py | 2 +- .../tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py | 2 +- .../tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py | 2 +- neutronclient/tests/unit/osc/v2/fakes.py | 2 +- neutronclient/tests/unit/osc/v2/fwaas/fakes.py | 2 +- neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py | 2 +- neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py | 2 +- neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py | 2 +- neutronclient/tests/unit/osc/v2/logging/fakes.py | 3 +-- neutronclient/tests/unit/osc/v2/logging/test_network_log.py | 2 +- neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py | 2 +- .../tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py | 2 +- .../unit/osc/v2/networking_bgpvpn/test_resource_association.py | 2 +- .../unit/osc/v2/networking_bgpvpn/test_router_association.py | 2 +- neutronclient/tests/unit/osc/v2/sfc/fakes.py | 2 +- neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py | 2 +- neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py | 2 +- neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py | 2 +- neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py | 2 +- neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py | 2 +- .../unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py | 2 +- neutronclient/tests/unit/osc/v2/trunk/fakes.py | 2 +- neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py | 2 +- neutronclient/tests/unit/osc/v2/vpnaas/fakes.py | 3 +-- neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py | 2 +- neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py | 2 +- .../tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py | 2 +- neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py | 2 +- neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py | 2 +- neutronclient/tests/unit/test_cli20.py | 2 +- neutronclient/tests/unit/test_cli20_address_scope.py | 2 +- neutronclient/tests/unit/test_cli20_agentschedulers.py | 2 +- neutronclient/tests/unit/test_cli20_network.py | 2 +- neutronclient/tests/unit/test_cli20_port.py | 2 +- neutronclient/tests/unit/test_cli20_securitygroup.py | 2 +- neutronclient/tests/unit/test_cli20_subnet.py | 2 +- neutronclient/tests/unit/test_cli20_subnetpool.py | 2 +- neutronclient/tests/unit/test_cli20_tag.py | 2 +- neutronclient/tests/unit/test_client_extension.py | 2 +- neutronclient/tests/unit/test_exceptions.py | 2 +- neutronclient/tests/unit/test_name_or_id.py | 3 ++- neutronclient/tests/unit/test_quota.py | 2 +- neutronclient/tests/unit/test_shell.py | 2 +- test-requirements.txt | 1 - 51 files changed, 50 insertions(+), 53 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index 48b0056b0..8f576fed0 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -39,7 +39,6 @@ kombu==4.0.0 linecache2==1.0.0 MarkupSafe==1.0 mccabe==0.2.1 -mock==2.0.0 monotonic==0.6 mox3==0.20.0 msgpack-python==0.4.0 diff --git a/neutronclient/tests/unit/bgp/test_cli20_speaker.py b/neutronclient/tests/unit/bgp/test_cli20_speaker.py index 72612dc6c..0d9cc60db 100644 --- a/neutronclient/tests/unit/bgp/test_cli20_speaker.py +++ b/neutronclient/tests/unit/bgp/test_cli20_speaker.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.common import exceptions from neutronclient.neutron.v2_0.bgp import speaker as bgp_speaker diff --git a/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py b/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py index 874ec7232..4cadfb2de 100644 --- a/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py +++ b/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.neutron.v2_0.fw import firewallpolicy from neutronclient import shell diff --git a/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py b/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py index 7c4d15c09..61cb1b1a5 100644 --- a/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py +++ b/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.neutron.v2_0.lb import healthmonitor from neutronclient.tests.unit import test_cli20 diff --git a/neutronclient/tests/unit/lb/test_cli20_pool.py b/neutronclient/tests/unit/lb/test_cli20_pool.py index 1106aed92..79bf23df8 100644 --- a/neutronclient/tests/unit/lb/test_cli20_pool.py +++ b/neutronclient/tests/unit/lb/test_cli20_pool.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.neutron.v2_0.lb import pool from neutronclient.tests.unit import test_cli20 diff --git a/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py b/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py index 6db07cc1a..3a6010cee 100644 --- a/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py +++ b/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.neutron.v2_0.lb.v2 import loadbalancer as lb from neutronclient.tests.unit import test_cli20 diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py index d425cd67b..c496a3f66 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py @@ -11,9 +11,9 @@ # under the License. import copy +from unittest import mock import uuid -import mock from neutronclient.tests.unit.osc.v2 import fakes diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py index 1ec7c41f0..7a94b323a 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. # -import mock +from unittest import mock from neutronclient.osc.v2.dynamic_routing import bgp_dragent from neutronclient.tests.unit.osc.v2.dynamic_routing import fakes diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py index ffe69f18d..506c86d93 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. # -import mock +from unittest import mock from neutronclient.osc.v2.dynamic_routing import bgp_peer from neutronclient.tests.unit.osc.v2.dynamic_routing import fakes diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py index dbecf057c..159746875 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. # -import mock +from unittest import mock from neutronclient.osc.v2.dynamic_routing import bgp_speaker from neutronclient.tests.unit.osc.v2.dynamic_routing import fakes diff --git a/neutronclient/tests/unit/osc/v2/fakes.py b/neutronclient/tests/unit/osc/v2/fakes.py index afa81e72d..c7876b645 100644 --- a/neutronclient/tests/unit/osc/v2/fakes.py +++ b/neutronclient/tests/unit/osc/v2/fakes.py @@ -12,9 +12,9 @@ # import argparse +from unittest import mock from cliff import columns as cliff_columns -import mock from osc_lib.tests import utils diff --git a/neutronclient/tests/unit/osc/v2/fwaas/fakes.py b/neutronclient/tests/unit/osc/v2/fwaas/fakes.py index 6475392c4..d0110989b 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/fakes.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/fakes.py @@ -16,8 +16,8 @@ import collections import copy +from unittest import mock -import mock from oslo_utils import uuidutils diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py index cc54d406b..41bfecb2d 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py @@ -16,8 +16,8 @@ import copy import re +from unittest import mock -import mock from osc_lib import exceptions from osc_lib.tests import utils diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py index 316eec887..7eba77483 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py @@ -16,8 +16,8 @@ import copy import re +from unittest import mock -import mock from osc_lib import exceptions from osc_lib.tests import utils diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py index a8b25c304..dac94cb74 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py @@ -16,8 +16,8 @@ import copy import re +from unittest import mock -import mock from osc_lib import exceptions from osc_lib.tests import utils import testtools diff --git a/neutronclient/tests/unit/osc/v2/logging/fakes.py b/neutronclient/tests/unit/osc/v2/logging/fakes.py index 856838fee..a20e3712e 100644 --- a/neutronclient/tests/unit/osc/v2/logging/fakes.py +++ b/neutronclient/tests/unit/osc/v2/logging/fakes.py @@ -16,10 +16,9 @@ import collections import copy +from unittest import mock import uuid -import mock - class FakeLogging(object): diff --git a/neutronclient/tests/unit/osc/v2/logging/test_network_log.py b/neutronclient/tests/unit/osc/v2/logging/test_network_log.py index d36453542..c2e0390ae 100644 --- a/neutronclient/tests/unit/osc/v2/logging/test_network_log.py +++ b/neutronclient/tests/unit/osc/v2/logging/test_network_log.py @@ -15,8 +15,8 @@ # import copy +from unittest import mock -import mock from osc_lib import exceptions from osc_lib.tests import utils import testtools diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py index b3a538f5a..a0b2cb892 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py @@ -15,8 +15,8 @@ # import copy +from unittest import mock -import mock from osc_lib.utils import columns as column_util from neutronclient.osc import utils as nc_osc_utils diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py index 14b6bb1a5..16fb164ae 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py @@ -16,8 +16,8 @@ import copy import operator +from unittest import mock -import mock from osc_lib import exceptions from osc_lib import utils as osc_utils from osc_lib.utils import columns as column_util diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py index 926001742..f8aa95f47 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py @@ -16,8 +16,8 @@ import copy import operator +from unittest import mock -import mock from osc_lib import exceptions from osc_lib import utils as osc_utils from osc_lib.utils import columns as column_util diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py index fb17bdb67..f48424c48 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py @@ -16,8 +16,8 @@ import copy import operator +from unittest import mock -import mock from osc_lib.tests.utils import ParserException from osc_lib import utils as osc_utils from osc_lib.utils import columns as column_util diff --git a/neutronclient/tests/unit/osc/v2/sfc/fakes.py b/neutronclient/tests/unit/osc/v2/sfc/fakes.py index 97861207f..ba07107fd 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/fakes.py +++ b/neutronclient/tests/unit/osc/v2/sfc/fakes.py @@ -15,8 +15,8 @@ import argparse import copy +from unittest import mock -import mock from osc_lib.tests import utils from oslo_utils import uuidutils diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py b/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py index e4672d377..379f72767 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from neutronclient.osc.v2.sfc import sfc_flow_classifier from neutronclient.tests.unit.osc.v2.sfc import fakes diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py b/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py index fbf60303d..da6455230 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from osc_lib import exceptions diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py b/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py index c56781881..8246e35d9 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from neutronclient.osc.v2.sfc import sfc_port_pair from neutronclient.tests.unit.osc.v2.sfc import fakes diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py b/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py index 48cee1ed9..6db21a284 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from neutronclient.osc.v2.sfc import sfc_port_pair_group from neutronclient.tests.unit.osc.v2.sfc import fakes diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py b/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py index da12aa570..a05ed2c72 100644 --- a/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py @@ -11,8 +11,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +from unittest import mock -import mock from osc_lib import exceptions from osc_lib.tests import utils as tests_utils diff --git a/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py b/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py index efd3d1d11..c2ca14044 100644 --- a/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py +++ b/neutronclient/tests/unit/osc/v2/subnet_onboard/test_network_onboard_subnets.py @@ -14,7 +14,7 @@ # under the License. # -import mock +from unittest import mock from neutronclient.osc.v2.subnet_onboard import subnet_onboard from neutronclient.tests.unit.osc.v2 import fakes as test_fakes diff --git a/neutronclient/tests/unit/osc/v2/trunk/fakes.py b/neutronclient/tests/unit/osc/v2/trunk/fakes.py index f7da0dd77..a52aa3097 100644 --- a/neutronclient/tests/unit/osc/v2/trunk/fakes.py +++ b/neutronclient/tests/unit/osc/v2/trunk/fakes.py @@ -11,8 +11,8 @@ # under the License. import copy +from unittest import mock -import mock from oslo_utils import uuidutils diff --git a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py b/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py index 8e9e73c49..dd6799870 100644 --- a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py +++ b/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py @@ -15,8 +15,8 @@ import argparse import copy +from unittest import mock -import mock from mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py b/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py index 7ee7c5d5e..dfad250b3 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py @@ -16,10 +16,9 @@ import collections import copy +from unittest import mock import uuid -import mock - class FakeVPNaaS(object): diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py index cc597e701..9c5dbcce5 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py @@ -15,8 +15,8 @@ # import copy +from unittest import mock -import mock from osc_lib.tests import utils as tests_utils from neutronclient.osc import utils as osc_utils diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py index 24663d6a2..0d2673a99 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py @@ -15,8 +15,8 @@ # import copy +from unittest import mock -import mock from osc_lib.tests import utils as tests_utils from neutronclient.osc import utils as osc_utils diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py index 4d04b641c..96313b459 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py @@ -15,8 +15,8 @@ # import copy +from unittest import mock -import mock from osc_lib.cli import format_columns from osc_lib.tests import utils as tests_utils diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py index 8e56cf3f9..0df98e3f3 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py @@ -15,8 +15,8 @@ # import copy +from unittest import mock -import mock from osc_lib.tests import utils as tests_utils from neutronclient.osc import utils as osc_utils diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py index a9c208e7c..7630eb8e0 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py @@ -15,9 +15,9 @@ # import copy +from unittest import mock import uuid -import mock from neutronclient.osc import utils as osc_utils from neutronclient.osc.v2.vpnaas import vpnservice diff --git a/neutronclient/tests/unit/test_cli20.py b/neutronclient/tests/unit/test_cli20.py index 73104b54c..c2143e168 100644 --- a/neutronclient/tests/unit/test_cli20.py +++ b/neutronclient/tests/unit/test_cli20.py @@ -18,9 +18,9 @@ from io import StringIO import itertools import sys +from unittest import mock import urllib.parse as urlparse -import mock from oslo_serialization import jsonutils from oslo_utils import encodeutils from oslotest import base diff --git a/neutronclient/tests/unit/test_cli20_address_scope.py b/neutronclient/tests/unit/test_cli20_address_scope.py index f58185fd0..902f7e653 100644 --- a/neutronclient/tests/unit/test_cli20_address_scope.py +++ b/neutronclient/tests/unit/test_cli20_address_scope.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.common import exceptions from neutronclient.neutron.v2_0 import address_scope diff --git a/neutronclient/tests/unit/test_cli20_agentschedulers.py b/neutronclient/tests/unit/test_cli20_agentschedulers.py index ddb8dce7d..817909d38 100644 --- a/neutronclient/tests/unit/test_cli20_agentschedulers.py +++ b/neutronclient/tests/unit/test_cli20_agentschedulers.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.neutron.v2_0 import agentscheduler from neutronclient.neutron.v2_0 import network diff --git a/neutronclient/tests/unit/test_cli20_network.py b/neutronclient/tests/unit/test_cli20_network.py index 2f7a46896..b1f69acc8 100644 --- a/neutronclient/tests/unit/test_cli20_network.py +++ b/neutronclient/tests/unit/test_cli20_network.py @@ -15,8 +15,8 @@ import itertools import sys +from unittest import mock -import mock from oslo_serialization import jsonutils from neutronclient.common import exceptions diff --git a/neutronclient/tests/unit/test_cli20_port.py b/neutronclient/tests/unit/test_cli20_port.py index f6fc61783..e1ab411e5 100644 --- a/neutronclient/tests/unit/test_cli20_port.py +++ b/neutronclient/tests/unit/test_cli20_port.py @@ -16,8 +16,8 @@ import itertools import sys +from unittest import mock -import mock from neutronclient.neutron.v2_0 import port from neutronclient import shell diff --git a/neutronclient/tests/unit/test_cli20_securitygroup.py b/neutronclient/tests/unit/test_cli20_securitygroup.py index 010f7dcae..f5ed8ad1e 100644 --- a/neutronclient/tests/unit/test_cli20_securitygroup.py +++ b/neutronclient/tests/unit/test_cli20_securitygroup.py @@ -15,9 +15,9 @@ # under the License. import sys +from unittest import mock import urllib.parse as urlparse -import mock from oslo_utils import uuidutils from neutronclient.common import exceptions diff --git a/neutronclient/tests/unit/test_cli20_subnet.py b/neutronclient/tests/unit/test_cli20_subnet.py index ab37cbdd7..97c2faff0 100644 --- a/neutronclient/tests/unit/test_cli20_subnet.py +++ b/neutronclient/tests/unit/test_cli20_subnet.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.common import exceptions from neutronclient.neutron import v2_0 as neutronV20 diff --git a/neutronclient/tests/unit/test_cli20_subnetpool.py b/neutronclient/tests/unit/test_cli20_subnetpool.py index 89a89b244..fb201683a 100644 --- a/neutronclient/tests/unit/test_cli20_subnetpool.py +++ b/neutronclient/tests/unit/test_cli20_subnetpool.py @@ -15,8 +15,8 @@ # import sys +from unittest import mock -import mock from neutronclient.common import exceptions from neutronclient.neutron.v2_0 import subnetpool diff --git a/neutronclient/tests/unit/test_cli20_tag.py b/neutronclient/tests/unit/test_cli20_tag.py index bb3c451e9..2e23c9dc5 100644 --- a/neutronclient/tests/unit/test_cli20_tag.py +++ b/neutronclient/tests/unit/test_cli20_tag.py @@ -11,8 +11,8 @@ # under the License. import sys +from unittest import mock -import mock from neutronclient.common import exceptions from neutronclient.neutron.v2_0 import network diff --git a/neutronclient/tests/unit/test_client_extension.py b/neutronclient/tests/unit/test_client_extension.py index 7e443a01e..7137ae7b3 100644 --- a/neutronclient/tests/unit/test_client_extension.py +++ b/neutronclient/tests/unit/test_client_extension.py @@ -16,8 +16,8 @@ import inspect import sys +from unittest import mock -import mock from neutronclient.common import extension from neutronclient.neutron.v2_0.contrib import _fox_sockets as fox_sockets diff --git a/neutronclient/tests/unit/test_exceptions.py b/neutronclient/tests/unit/test_exceptions.py index 50b2bdbbe..6e063244c 100644 --- a/neutronclient/tests/unit/test_exceptions.py +++ b/neutronclient/tests/unit/test_exceptions.py @@ -13,8 +13,8 @@ # under the License. import sys +from unittest import mock -import mock from oslo_utils import encodeutils import testtools diff --git a/neutronclient/tests/unit/test_name_or_id.py b/neutronclient/tests/unit/test_name_or_id.py index ee94b24b1..a6a7b9246 100644 --- a/neutronclient/tests/unit/test_name_or_id.py +++ b/neutronclient/tests/unit/test_name_or_id.py @@ -14,7 +14,8 @@ # under the License. # -import mock +from unittest import mock + from oslo_utils import uuidutils import testtools diff --git a/neutronclient/tests/unit/test_quota.py b/neutronclient/tests/unit/test_quota.py index 6192bbb9a..4529287b0 100644 --- a/neutronclient/tests/unit/test_quota.py +++ b/neutronclient/tests/unit/test_quota.py @@ -15,8 +15,8 @@ # under the License. import sys +from unittest import mock -import mock from neutronclient.common import exceptions from neutronclient.neutron.v2_0 import quota as test_quota diff --git a/neutronclient/tests/unit/test_shell.py b/neutronclient/tests/unit/test_shell.py index 86250a139..9dc2faac8 100644 --- a/neutronclient/tests/unit/test_shell.py +++ b/neutronclient/tests/unit/test_shell.py @@ -19,10 +19,10 @@ import os import re import sys +from unittest import mock import fixtures from keystoneauth1 import session -import mock import testtools from testtools import matchers diff --git a/test-requirements.txt b/test-requirements.txt index a0d76ed70..ae1f2e55d 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -7,7 +7,6 @@ bandit!=1.6.0,>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 fixtures>=3.0.0 # Apache-2.0/BSD flake8-import-order==0.12 # LGPLv3 -mock>=2.0.0 # BSD oslotest>=3.2.0 # Apache-2.0 osprofiler>=2.3.0 # Apache-2.0 python-openstackclient>=3.12.0 # Apache-2.0 From 42ebefab3bc9aa6d9721258541f62e96a573d559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Beraud?= Date: Tue, 2 Jun 2020 20:50:34 +0200 Subject: [PATCH 058/149] Stop to use the __future__ module. The __future__ module [1] was used in this context to ensure compatibility between python 2 and python 3. We previously dropped the support of python 2.7 [2] and now we only support python 3 so we don't need to continue to use this module and the imports listed below. Imports commonly used and their related PEPs: - `division` is related to PEP 238 [3] - `print_function` is related to PEP 3105 [4] - `unicode_literals` is related to PEP 3112 [5] - `with_statement` is related to PEP 343 [6] - `absolute_import` is related to PEP 328 [7] [1] https://docs.python.org/3/library/__future__.html [2] https://governance.openstack.org/tc/goals/selected/ussuri/drop-py27.html [3] https://www.python.org/dev/peps/pep-0238 [4] https://www.python.org/dev/peps/pep-3105 [5] https://www.python.org/dev/peps/pep-3112 [6] https://www.python.org/dev/peps/pep-0343 [7] https://www.python.org/dev/peps/pep-0328 Change-Id: I65fb53db889afcf1a947ea61094bfab877853324 --- neutronclient/neutron/v2_0/__init__.py | 2 -- neutronclient/neutron/v2_0/agentscheduler.py | 2 -- neutronclient/neutron/v2_0/auto_allocated_topology.py | 2 -- neutronclient/neutron/v2_0/bgp/dragentscheduler.py | 2 -- neutronclient/neutron/v2_0/bgp/speaker.py | 2 -- neutronclient/neutron/v2_0/flavor/flavor.py | 2 -- neutronclient/neutron/v2_0/floatingip.py | 2 -- neutronclient/neutron/v2_0/fw/firewallpolicy.py | 2 -- neutronclient/neutron/v2_0/lb/healthmonitor.py | 2 -- neutronclient/neutron/v2_0/quota.py | 2 -- neutronclient/neutron/v2_0/router.py | 2 -- neutronclient/osc/v2/fwaas/firewallpolicy.py | 2 -- neutronclient/shell.py | 2 -- 13 files changed, 26 deletions(-) diff --git a/neutronclient/neutron/v2_0/__init__.py b/neutronclient/neutron/v2_0/__init__.py index 3a6e086ee..849a93d9e 100644 --- a/neutronclient/neutron/v2_0/__init__.py +++ b/neutronclient/neutron/v2_0/__init__.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - import abc import argparse import functools diff --git a/neutronclient/neutron/v2_0/agentscheduler.py b/neutronclient/neutron/v2_0/agentscheduler.py index 4476b1dd3..e92b10be1 100644 --- a/neutronclient/neutron/v2_0/agentscheduler.py +++ b/neutronclient/neutron/v2_0/agentscheduler.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron.v2_0 import network diff --git a/neutronclient/neutron/v2_0/auto_allocated_topology.py b/neutronclient/neutron/v2_0/auto_allocated_topology.py index ef0da4325..a24959e16 100644 --- a/neutronclient/neutron/v2_0/auto_allocated_topology.py +++ b/neutronclient/neutron/v2_0/auto_allocated_topology.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - import argparse from cliff import show diff --git a/neutronclient/neutron/v2_0/bgp/dragentscheduler.py b/neutronclient/neutron/v2_0/bgp/dragentscheduler.py index 81ce8f1ec..d1e1de63f 100644 --- a/neutronclient/neutron/v2_0/bgp/dragentscheduler.py +++ b/neutronclient/neutron/v2_0/bgp/dragentscheduler.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron.v2_0.bgp import speaker as bgp_speaker diff --git a/neutronclient/neutron/v2_0/bgp/speaker.py b/neutronclient/neutron/v2_0/bgp/speaker.py index 1a70734e5..c6533e2d9 100644 --- a/neutronclient/neutron/v2_0/bgp/speaker.py +++ b/neutronclient/neutron/v2_0/bgp/speaker.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - from neutronclient._i18n import _ from neutronclient.common import utils from neutronclient.common import validators diff --git a/neutronclient/neutron/v2_0/flavor/flavor.py b/neutronclient/neutron/v2_0/flavor/flavor.py index 3058da656..36a052ef2 100644 --- a/neutronclient/neutron/v2_0/flavor/flavor.py +++ b/neutronclient/neutron/v2_0/flavor/flavor.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from __future__ import print_function - import argparse from neutronclient._i18n import _ diff --git a/neutronclient/neutron/v2_0/floatingip.py b/neutronclient/neutron/v2_0/floatingip.py index 9f0ce089b..5f4ced40a 100644 --- a/neutronclient/neutron/v2_0/floatingip.py +++ b/neutronclient/neutron/v2_0/floatingip.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - import argparse from neutronclient._i18n import _ diff --git a/neutronclient/neutron/v2_0/fw/firewallpolicy.py b/neutronclient/neutron/v2_0/fw/firewallpolicy.py index 0c99948eb..3d9331cd6 100644 --- a/neutronclient/neutron/v2_0/fw/firewallpolicy.py +++ b/neutronclient/neutron/v2_0/fw/firewallpolicy.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - import argparse from neutronclient._i18n import _ diff --git a/neutronclient/neutron/v2_0/lb/healthmonitor.py b/neutronclient/neutron/v2_0/lb/healthmonitor.py index 61cd7df48..33dfbf0bc 100644 --- a/neutronclient/neutron/v2_0/lb/healthmonitor.py +++ b/neutronclient/neutron/v2_0/lb/healthmonitor.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - from neutronclient._i18n import _ from neutronclient.neutron import v2_0 as neutronV20 diff --git a/neutronclient/neutron/v2_0/quota.py b/neutronclient/neutron/v2_0/quota.py index 1a59ac546..a55e29f6d 100644 --- a/neutronclient/neutron/v2_0/quota.py +++ b/neutronclient/neutron/v2_0/quota.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - import abc import argparse diff --git a/neutronclient/neutron/v2_0/router.py b/neutronclient/neutron/v2_0/router.py index ca1c05828..1f78cb85c 100644 --- a/neutronclient/neutron/v2_0/router.py +++ b/neutronclient/neutron/v2_0/router.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - import argparse from oslo_serialization import jsonutils diff --git a/neutronclient/osc/v2/fwaas/firewallpolicy.py b/neutronclient/osc/v2/fwaas/firewallpolicy.py index bd3e60d40..cc6beb54d 100644 --- a/neutronclient/osc/v2/fwaas/firewallpolicy.py +++ b/neutronclient/osc/v2/fwaas/firewallpolicy.py @@ -14,8 +14,6 @@ # under the License. # -from __future__ import print_function - import logging from osc_lib.command import command diff --git a/neutronclient/shell.py b/neutronclient/shell.py index fbc91209f..aed4c8fde 100644 --- a/neutronclient/shell.py +++ b/neutronclient/shell.py @@ -18,8 +18,6 @@ Command-line interface to the Neutron APIs """ -from __future__ import print_function - import argparse import inspect import itertools From f751dd3782d0d674d8e717e7be6d8bc99518b237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Beraud?= Date: Tue, 9 Jun 2020 11:58:23 +0200 Subject: [PATCH 059/149] Use unittest.mock instead of mock The mock third party library was needed for mock support in py2 runtimes. Since we now only support py36 and later, we can use the standard lib unittest.mock module instead. Change-Id: Ia7226d968b8594677fc8dea664b58a80ba193ac5 --- neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py b/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py index dd6799870..1e16c1fa9 100644 --- a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py +++ b/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py @@ -16,8 +16,8 @@ import argparse import copy from unittest import mock +from unittest.mock import call -from mock import call from osc_lib.cli import format_columns from osc_lib import exceptions from osc_lib.tests import utils as tests_utils From ada4229691fb0f6d1b41d2f49633e4f9f5b9ea0b Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 9 Jul 2020 11:41:37 +0100 Subject: [PATCH 060/149] lower-constraints: Drop os-testr, mox3 They're no longer used. Change-Id: Ic8b68f900c2d42a3f5e1508ddde2821cb12b696e Signed-off-by: Stephen Finucane --- lower-constraints.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index 8f576fed0..252a45abc 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -40,7 +40,6 @@ linecache2==1.0.0 MarkupSafe==1.0 mccabe==0.2.1 monotonic==0.6 -mox3==0.20.0 msgpack-python==0.4.0 munch==2.1.0 netaddr==0.7.18 @@ -48,7 +47,6 @@ netifaces==0.10.4 openstacksdk==0.11.2 os-client-config==1.28.0 os-service-types==1.2.0 -os-testr==1.0.0 osc-lib==1.8.0 oslo.concurrency==3.25.0 oslo.config==5.2.0 From d1e5afb3510ef0196b40f8ac632987f44e6c4956 Mon Sep 17 00:00:00 2001 From: Jens Harbott Date: Sun, 12 Jul 2020 21:14:40 +0000 Subject: [PATCH 061/149] Fix description of bgp speaker set arg The name argument for bgp speaker set defines the new name for the speaker, make the description more clear about this. Change-Id: I29a0c87214c3c60084d0541f8b9a7abc72ff987f --- neutronclient/osc/v2/dynamic_routing/bgp_speaker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py b/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py index 5ce8d471e..171d7f45f 100644 --- a/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py +++ b/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py @@ -285,7 +285,7 @@ def get_parser(self, prog_name): ) parser.add_argument( '--name', - help=_("Name of the BGP speaker to update")) + help=_("New name for the BGP speaker")) add_common_arguments(parser) return parser From 097106d8fb557e85a93c696a8d64579034708f39 Mon Sep 17 00:00:00 2001 From: Luigi Toscano Date: Mon, 10 Aug 2020 16:25:36 +0200 Subject: [PATCH 062/149] zuul: native Zuul v3 version of the grenade job Also fix the name according the guidelines. This job should really live inside neutron-lib. Change-Id: I76043ea43efe1c78ba9637876ed6a8b997b6d0ee --- .zuul.yaml | 27 +++++----- .../grenade-dsvm-neutron-libs/post.yaml | 15 ------ .../legacy/grenade-dsvm-neutron-libs/run.yaml | 52 ------------------- 3 files changed, 13 insertions(+), 81 deletions(-) delete mode 100644 playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml delete mode 100644 playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml diff --git a/.zuul.yaml b/.zuul.yaml index e956eba72..7464cb6c6 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -16,7 +16,7 @@ - neutronclient-functional experimental: jobs: - - neutron-lib-grenade-dsvm: + - neutronclient-grenade-neutron-lib: irrelevant-files: - ^(test-|)requirements.txt$ - ^setup.cfg$ @@ -45,15 +45,19 @@ neutron-vpnaas: https://opendev.org/openstack/neutron-vpnaas - job: - name: neutron-lib-grenade-dsvm - # Old name: legacy-grenade-dsvm-neutron-libs - parent: legacy-dsvm-base - run: playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml - post-run: playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml - timeout: 10800 + name: neutronclient-grenade-neutron-lib + parent: grenade + description: | + neutron-lib grenade job. + The version of this job on the current branch is py3 based, + while any branch before ussuri needs to use the py2 version, + which is defined in openstack-zuul-jobs with the old name + (legacy-grenade-dsvm-neutron-libs). + Users of this job needs to pay attention of the version used. + Former names for this job were: + * legacy-grenade-dsvm-neutron-libs + * neutron-lib-grenade-dsvm required-projects: - - openstack/grenade - - openstack/devstack-gate - openstack/keystoneauth - openstack/neutron - openstack/neutron-lib @@ -64,8 +68,3 @@ - openstack/python-keystoneclient - openstack/python-neutronclient - openstack/python-novaclient - # This is py3 version for ussuri onwards rest all branch needs to be py2 - # version which is present in openstack-zuul-jobs. - # We need to take care of this branch variant and python version while - # migrating these jobs to zuulv3. - branches: ^(?!(stable/(ocata|pike|queens|rocky|stein|train))).*$ diff --git a/playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml b/playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml deleted file mode 100644 index e07f5510a..000000000 --- a/playbooks/legacy/grenade-dsvm-neutron-libs/post.yaml +++ /dev/null @@ -1,15 +0,0 @@ -- hosts: primary - tasks: - - - name: Copy files from {{ ansible_user_dir }}/workspace/ on node - synchronize: - src: '{{ ansible_user_dir }}/workspace/' - dest: '{{ zuul.executor.log_root }}' - mode: pull - copy_links: true - verify_host: true - rsync_opts: - - --include=/logs/** - - --include=*/ - - --exclude=* - - --prune-empty-dirs diff --git a/playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml b/playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml deleted file mode 100644 index 6c600610a..000000000 --- a/playbooks/legacy/grenade-dsvm-neutron-libs/run.yaml +++ /dev/null @@ -1,52 +0,0 @@ -- hosts: all - name: Autoconverted job legacy-grenade-dsvm-neutron-libs from old job gate-grenade-dsvm-neutron-libs-ubuntu-xenial-nv - tasks: - - - name: Ensure legacy workspace directory - file: - path: '{{ ansible_user_dir }}/workspace' - state: directory - - - shell: - cmd: | - set -e - set -x - cat > clonemap.yaml << EOF - clonemap: - - name: openstack/devstack-gate - dest: devstack-gate - EOF - /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \ - https://opendev.org \ - openstack/devstack-gate - executable: /bin/bash - chdir: '{{ ansible_user_dir }}/workspace' - environment: '{{ zuul | zuul_legacy_vars }}' - - - shell: - cmd: | - set -e - set -x - export PROJECTS="openstack/grenade $PROJECTS" - export DEVSTACK_PROJECT_FROM_GIT="os-client-config" - export DEVSTACK_PROJECT_FROM_GIT+=",keystoneauth" - export DEVSTACK_PROJECT_FROM_GIT+=",python-novaclient" - export DEVSTACK_PROJECT_FROM_GIT+=",python-keystoneclient" - export DEVSTACK_PROJECT_FROM_GIT+=",python-glanceclient" - export DEVSTACK_PROJECT_FROM_GIT+=",python-cinderclient" - export DEVSTACK_PROJECT_FROM_GIT+=",python-neutronclient" - export DEVSTACK_PROJECT_FROM_GIT+=",python-ironicclient" - export PYTHONUNBUFFERED=true - export DEVSTACK_GATE_TEMPEST=1 - export DEVSTACK_GATE_GRENADE=pullup - export DEVSTACK_GATE_USE_PYTHON3=True - export DEVSTACK_GATE_NEUTRON=1 - export BRANCH_OVERRIDE=default - if [ "$BRANCH_OVERRIDE" != "default" ] ; then - export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE - fi - cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh - ./safe-devstack-vm-gate-wrap.sh - executable: /bin/bash - chdir: '{{ ansible_user_dir }}/workspace' - environment: '{{ zuul | zuul_legacy_vars }}' From ffc9ed82621fc8cc4b820a8a7e87172a6905bf91 Mon Sep 17 00:00:00 2001 From: melissaml Date: Tue, 23 Jun 2020 11:28:53 +0800 Subject: [PATCH 063/149] Remove translation sections from setup.cfg These translation sections are not needed anymore, Babel can generate translation files without them. Change-Id: If20aa86f21807497c5dfefb0f34f771040517c6f --- babel.cfg | 2 -- setup.cfg | 14 -------------- 2 files changed, 16 deletions(-) delete mode 100644 babel.cfg diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index 15cd6cb76..000000000 --- a/babel.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[python: **.py] - diff --git a/setup.cfg b/setup.cfg index 70c0d62b9..ad537f71e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -455,17 +455,3 @@ neutron.cli.v2 = vpn-ikepolicy-create = neutronclient.neutron.v2_0.vpn.ikepolicy:CreateIKEPolicy vpn-ikepolicy-update = neutronclient.neutron.v2_0.vpn.ikepolicy:UpdateIKEPolicy vpn-ikepolicy-delete = neutronclient.neutron.v2_0.vpn.ikepolicy:DeleteIKEPolicy - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext -mapping_file = babel.cfg -output_file = neutronclient/locale/neutronclient.pot - -[compile_catalog] -directory = neutronclient/locale -domain = neutronclient - -[update_catalog] -domain = neutronclient -output_dir = neutronclient/locale -input_file = neutronclient/locale/neutronclient.pot From 9ffa0ac14e3e49c572b4f984620a0e16c15918d9 Mon Sep 17 00:00:00 2001 From: Jens Harbott Date: Tue, 1 Sep 2020 13:51:11 +0200 Subject: [PATCH 064/149] Allow 4byte ASNs in dynamic routing client Neutron-dynamic-routing has the bgp_4byte_asn extension which allows 4byte ASNs to be used, increasing the range of valid AS numbers. Since we cannot easily tell beforehand whether that extension is available, allow for the maximal interval to be used by clients and let the API validate the input. Change-Id: Ib4695272784b4a5ebbcb792cfec82dac3ef6f3cf --- neutronclient/neutron/v2_0/bgp/speaker.py | 2 +- neutronclient/osc/v2/dynamic_routing/constants.py | 2 +- neutronclient/tests/unit/bgp/test_cli20_peer.py | 5 +++-- neutronclient/tests/unit/bgp/test_cli20_speaker.py | 5 +++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/neutronclient/neutron/v2_0/bgp/speaker.py b/neutronclient/neutron/v2_0/bgp/speaker.py index c6533e2d9..6bdbd86f2 100644 --- a/neutronclient/neutron/v2_0/bgp/speaker.py +++ b/neutronclient/neutron/v2_0/bgp/speaker.py @@ -22,7 +22,7 @@ # Allowed BGP Autonomous number range MIN_AS_NUM = 1 -MAX_AS_NUM = 65535 +MAX_AS_NUM = 4294967295 def get_network_id(client, id_or_name): diff --git a/neutronclient/osc/v2/dynamic_routing/constants.py b/neutronclient/osc/v2/dynamic_routing/constants.py index 0dd16b143..8885b42ed 100644 --- a/neutronclient/osc/v2/dynamic_routing/constants.py +++ b/neutronclient/osc/v2/dynamic_routing/constants.py @@ -15,4 +15,4 @@ BGP_PEERS = 'bgp_peers' BGP_PEER = 'bgp_peer' MIN_AS_NUM = 1 -MAX_AS_NUM = 65535 +MAX_AS_NUM = 4294967295 diff --git a/neutronclient/tests/unit/bgp/test_cli20_peer.py b/neutronclient/tests/unit/bgp/test_cli20_peer.py index c89c21b6c..998b0d5e3 100644 --- a/neutronclient/tests/unit/bgp/test_cli20_peer.py +++ b/neutronclient/tests/unit/bgp/test_cli20_peer.py @@ -96,7 +96,7 @@ def test_create_bgp_peer_with_invalid_max_remote_asnum(self): name = 'my-name' my_id = 'my-id' peerip = '1.1.1.1' - remote_asnum = '65536' + remote_asnum = '4294967296' args = [name, '--peer-ip', peerip, '--remote-as', remote_asnum, ] @@ -107,7 +107,8 @@ def test_create_bgp_peer_with_invalid_max_remote_asnum(self): self._test_create_resource, resource, cmd, name, my_id, args, position_names, position_values) - self.assertEqual('remote-as "65536" should be an integer [%s:%s].' % + self.assertEqual('remote-as "4294967296" should be an ' + 'integer [%s:%s].' % (bgp_speaker.MIN_AS_NUM, bgp_speaker.MAX_AS_NUM), str(exc)) diff --git a/neutronclient/tests/unit/bgp/test_cli20_speaker.py b/neutronclient/tests/unit/bgp/test_cli20_speaker.py index 0d9cc60db..5621576d9 100644 --- a/neutronclient/tests/unit/bgp/test_cli20_speaker.py +++ b/neutronclient/tests/unit/bgp/test_cli20_speaker.py @@ -108,7 +108,7 @@ def test_create_bgp_speaker_with_invalid_max_local_asnum(self): None) name = 'my-name' my_id = 'my-id' - local_asnum = '65536' + local_asnum = '4294967296' args = [name, '--local-as', local_asnum] position_names = ['name', 'local_as', ] @@ -117,7 +117,8 @@ def test_create_bgp_speaker_with_invalid_max_local_asnum(self): self._test_create_resource, resource, cmd, name, my_id, args, position_names, position_values) - self.assertEqual('local-as "65536" should be an integer [%s:%s].' % + self.assertEqual('local-as "4294967296" should be an ' + 'integer [%s:%s].' % (bgp_speaker.MIN_AS_NUM, bgp_speaker.MAX_AS_NUM), str(exc)) From 66462874d29e48ec370d400db374c68d153bf94b Mon Sep 17 00:00:00 2001 From: Bernard Cafarelli Date: Thu, 10 Sep 2020 09:41:03 +0200 Subject: [PATCH 065/149] Fix lower-constraints for Focal Bump to versions supporting python 3.8 and with wheels available and sync requirements Change-Id: Ibcd16c9a9f691775af428ec447f4ebf9baea5e86 --- lower-constraints.txt | 10 +++++----- requirements.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index 252a45abc..001f03c83 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -4,12 +4,12 @@ appdirs==1.3.0 asn1crypto==0.23.0 Babel==2.3.4 cachetools==2.0.0 -cffi==1.7.0 -cliff==2.8.0 +cffi==1.14.0 +cliff==3.4.0 cmd2==0.8.0 contextlib2==0.4.0 coverage==4.0 -cryptography==2.1 +cryptography==2.7 debtcollector==1.2.0 decorator==3.4.0 deprecation==1.0 @@ -47,7 +47,7 @@ netifaces==0.10.4 openstacksdk==0.11.2 os-client-config==1.28.0 os-service-types==1.2.0 -osc-lib==1.8.0 +osc-lib==1.12.0 oslo.concurrency==3.25.0 oslo.config==5.2.0 oslo.context==2.19.2 @@ -86,7 +86,7 @@ python-novaclient==9.1.0 python-openstackclient==3.12.0 python-subunit==1.0.0 pytz==2013.6 -PyYAML==3.12 +PyYAML==3.13 repoze.lru==0.7 requests-mock==1.2.0 requests==2.14.2 diff --git a/requirements.txt b/requirements.txt index c1c9c28e3..d10083c26 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,11 +2,11 @@ # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. pbr!=2.1.0,>=2.0.0 # Apache-2.0 -cliff!=2.9.0,>=2.8.0 # Apache-2.0 +cliff>=3.4.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 iso8601>=0.1.11 # MIT netaddr>=0.7.18 # BSD -osc-lib>=1.8.0 # Apache-2.0 +osc-lib>=1.12.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 From 13d2d130dd9d1c52d49d1a75916cb4587eba1152 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Wed, 9 Sep 2020 16:36:40 +0000 Subject: [PATCH 066/149] Update master for stable/victoria Add file to the reno documentation build to show release notes for stable/victoria. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/victoria. Change-Id: I09f54e58239b6c2e77f69bff07bc7fe72ce4690d Sem-Ver: feature --- releasenotes/source/index.rst | 1 + releasenotes/source/victoria.rst | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/victoria.rst diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index ac3d918a3..6dfea69f6 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + victoria ussuri train stein diff --git a/releasenotes/source/victoria.rst b/releasenotes/source/victoria.rst new file mode 100644 index 000000000..4efc7b6f3 --- /dev/null +++ b/releasenotes/source/victoria.rst @@ -0,0 +1,6 @@ +============================= +Victoria Series Release Notes +============================= + +.. release-notes:: + :branch: stable/victoria From b2ebc6cc9b7ec8d1d3293535fac039cdaa266ef1 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Wed, 9 Sep 2020 16:36:43 +0000 Subject: [PATCH 067/149] Add Python3 wallaby unit tests This is an automatically generated patch to ensure unit testing is in place for all the of the tested runtimes for wallaby. See also the PTI in governance [1]. [1]: https://governance.openstack.org/tc/reference/project-testing-interface.html Change-Id: I26b3f45c78c1230a8b7d7faa46b504ac7cd0cc4b --- .zuul.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zuul.yaml b/.zuul.yaml index 7464cb6c6..c30c7b74d 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -2,7 +2,7 @@ templates: - openstack-cover-jobs - openstack-lower-constraints-jobs - - openstack-python3-victoria-jobs + - openstack-python3-wallaby-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing-python3 From 49c8577d8bd1a1a11c8062708478ac69bdcab388 Mon Sep 17 00:00:00 2001 From: likui Date: Mon, 2 Nov 2020 16:01:50 +0800 Subject: [PATCH 068/149] Update requirements URLs in tox config Update the URL to the upper-constraints file to point to the redirect rule on releases.openstack.org so will switch to the correct upper-constraints list automatically when the requirements repository branches. Change-Id: I496dfbc709ecd864f619618252ef5dc992216ca7 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index c4de1cd1e..7c11bfd8d 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ setenv = VIRTUAL_ENV={envdir} PYTHONWARNINGS=default::DeprecationWarning usedevelop = True install_command = pip install {opts} {packages} -deps = -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt} +deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt # Delete bytecodes from normal directories before running tests. From 1a1ee061e8d6d3a9c825819ed426e4f1b2eba80e Mon Sep 17 00:00:00 2001 From: "wu.shiming" Date: Fri, 20 Nov 2020 14:33:23 +0800 Subject: [PATCH 069/149] Dep's should be restricted by tox-constraints Tox trying to install latest versions for building docs which may not be supported by stable and lower branches, so should be restricted by respective version's tox-constraints.txt Change-Id: Iecd29788d1c94fd727072aa5dd7fe5d828dbf174 --- tox.ini | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 7c11bfd8d..a5d8ab120 100644 --- a/tox.ini +++ b/tox.ini @@ -51,7 +51,9 @@ commands = coverage report [testenv:docs] -deps = -r{toxinidir}/doc/requirements.txt +deps = + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -r{toxinidir}/doc/requirements.txt commands = sphinx-build -W -b html doc/source doc/build/html [testenv:pdf-docs] @@ -64,7 +66,9 @@ commands = make -C doc/build/pdf [testenv:releasenotes] -deps = -r{toxinidir}/doc/requirements.txt +deps = + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] From 4963c7ae14743d2542c8334e3175b7827750bb3d Mon Sep 17 00:00:00 2001 From: zhangboye Date: Sun, 3 Jan 2021 16:57:16 +0800 Subject: [PATCH 070/149] remove unicode from code Change-Id: I2521c2ba836b6a332883134112b6f99d996cc4e4 --- doc/source/conf.py | 6 +++--- releasenotes/source/conf.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index e3e269e25..70fd0de2f 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -28,7 +28,7 @@ master_doc = 'index' # General information about the project. -copyright = u'OpenStack Foundation' +copyright = 'OpenStack Foundation' # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True @@ -53,8 +53,8 @@ latex_documents = [ ('index', 'doc-python-neutronclient.tex', - u'python-neutronclient Documentation', - u'Neutron Contributors', 'manual'), + 'python-neutronclient Documentation', + 'Neutron Contributors', 'manual'), ] # Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py index 5b075fe21..498287605 100644 --- a/releasenotes/source/conf.py +++ b/releasenotes/source/conf.py @@ -61,8 +61,8 @@ master_doc = 'index' # General information about the project. -project = u'Neutron Client Release Notes' -copyright = u'2015, Neutron Developers' +project = 'Neutron Client Release Notes' +copyright = '2015, Neutron Developers' # Release notes are version independent. # The full version, including alpha/beta/rc tags. From 3140fe014a181185cef674d78dcdb169bb94783b Mon Sep 17 00:00:00 2001 From: sri harsha mekala Date: Fri, 5 Mar 2021 11:47:09 -0800 Subject: [PATCH 071/149] Support passing mTLS certificate/key to HTTPClient Change-Id: I00065293daf6b2e5d540e056c05f85b82f8bc72c --- neutronclient/client.py | 10 +++++++--- neutronclient/v2_0/client.py | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/neutronclient/client.py b/neutronclient/client.py index 936d297e2..e25f575f3 100644 --- a/neutronclient/client.py +++ b/neutronclient/client.py @@ -61,9 +61,9 @@ def __init__(self, username=None, user_id=None, token=None, region_name=None, timeout=None, endpoint_url=None, insecure=False, endpoint_type='publicURL', - auth_strategy='keystone', ca_cert=None, log_credentials=False, - service_type='network', global_request_id=None, - **kwargs): + auth_strategy='keystone', ca_cert=None, cert=None, + log_credentials=False, service_type='network', + global_request_id=None, **kwargs): self.username = username self.user_id = user_id @@ -82,6 +82,7 @@ def __init__(self, username=None, user_id=None, self.auth_strategy = auth_strategy self.log_credentials = log_credentials self.global_request_id = global_request_id + self.cert = cert if insecure: self.verify_cert = False else: @@ -167,6 +168,7 @@ def request(self, url, method, body=None, headers=None, **kwargs): data=body, headers=headers, verify=self.verify_cert, + cert=self.cert, timeout=self.timeout, **kwargs) @@ -399,6 +401,7 @@ def construct_http_client(username=None, log_credentials=None, auth_strategy='keystone', ca_cert=None, + cert=None, service_type='network', session=None, global_request_id=None, @@ -430,6 +433,7 @@ def construct_http_client(username=None, endpoint_type=endpoint_type, service_type=service_type, ca_cert=ca_cert, + cert=cert, log_credentials=log_credentials, auth_strategy=auth_strategy, global_request_id=global_request_id) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index ff440647c..c264dfd14 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -216,6 +216,10 @@ class ClientBase(object): :param bool log_credentials: Allow for logging of passwords or not. Defaults to False. (optional) :param string ca_cert: SSL CA bundle file to use. (optional) + :param cert: A client certificate to pass to requests. These are of the + same form as requests expects. Either a single filename + containing both the certificate and key or a tuple containing + the path to the certificate then a path to the key. (optional) :param integer retries: How many times idempotent (GET, PUT, DELETE) requests to Neutron server should be retried if they fail (default: 0). From 12373768dadef3bad3eb1a32ff51a355e65d17a0 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 18 Mar 2021 12:56:13 +0000 Subject: [PATCH 072/149] Update master for stable/wallaby Add file to the reno documentation build to show release notes for stable/wallaby. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/wallaby. Sem-Ver: feature Change-Id: I91d4355bb94ac18a80ff215796cd403be870986a --- releasenotes/source/index.rst | 1 + releasenotes/source/wallaby.rst | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/wallaby.rst diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index 6dfea69f6..bfa147dd9 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + wallaby victoria ussuri train diff --git a/releasenotes/source/wallaby.rst b/releasenotes/source/wallaby.rst new file mode 100644 index 000000000..d77b56599 --- /dev/null +++ b/releasenotes/source/wallaby.rst @@ -0,0 +1,6 @@ +============================ +Wallaby Series Release Notes +============================ + +.. release-notes:: + :branch: stable/wallaby From f3756a3d4a816e5096aa2355fc1338effbb13d13 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 18 Mar 2021 12:56:37 +0000 Subject: [PATCH 073/149] Add Python3 xena unit tests This is an automatically generated patch to ensure unit testing is in place for all the of the tested runtimes for xena. See also the PTI in governance [1]. [1]: https://governance.openstack.org/tc/reference/project-testing-interface.html Change-Id: I8475c835838bbd0d84540cef879b4769581ef06d --- .zuul.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zuul.yaml b/.zuul.yaml index c30c7b74d..061a6001e 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -2,7 +2,7 @@ templates: - openstack-cover-jobs - openstack-lower-constraints-jobs - - openstack-python3-wallaby-jobs + - openstack-python3-xena-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing-python3 From d87683b59b8f755890e71fb8a73f537215beb60b Mon Sep 17 00:00:00 2001 From: Elod Illes Date: Fri, 19 Mar 2021 11:28:17 +0100 Subject: [PATCH 074/149] Fix lower constraints This patch updates lower-constraints.txt to eliminate contradictions. keystoneauth1 lower constraint has to be bumped in requirements.txt as another dependency, openstacksdk 0.15.0 depends on keystoneauth1>=3.8.0 dogpile.cache version bumped to 0.6.5 as older version had 'async' as variable name which gives SyntaxError from py37. Change-Id: I31464518cb7f76c0fa5275a4ef52b2a6b634cfa3 --- lower-constraints.txt | 22 +++++++++++----------- requirements.txt | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index 001f03c83..44c70fafc 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -14,18 +14,18 @@ debtcollector==1.2.0 decorator==3.4.0 deprecation==1.0 docutils==0.11 -dogpile.cache==0.6.2 +dogpile.cache==0.6.5 dulwich==0.15.0 eventlet==0.18.2 extras==1.0.0 fasteners==0.7.0 fixtures==3.0.0 flake8-import-order==0.12 -flake8==2.5.5 +flake8==3.6.0 future==0.16.0 futurist==1.2.0 greenlet==0.4.10 -hacking==1.1.0 +hacking==3.0.1 idna==2.6 imagesize==0.7.1 iso8601==0.1.11 @@ -34,21 +34,21 @@ jmespath==0.9.0 jsonpatch==1.16 jsonpointer==1.13 jsonschema==2.6.0 -keystoneauth1==3.4.0 +keystoneauth1==3.8.0 kombu==4.0.0 linecache2==1.0.0 MarkupSafe==1.0 -mccabe==0.2.1 +mccabe==0.6.0 monotonic==0.6 msgpack-python==0.4.0 munch==2.1.0 netaddr==0.7.18 netifaces==0.10.4 -openstacksdk==0.11.2 +openstacksdk==0.15.0 os-client-config==1.28.0 os-service-types==1.2.0 osc-lib==1.12.0 -oslo.concurrency==3.25.0 +oslo.concurrency==3.26.0 oslo.config==5.2.0 oslo.context==2.19.2 oslo.i18n==3.15.3 @@ -69,9 +69,9 @@ pika==0.10.0 positional==1.2.1 prettytable==0.7.2 pyasn1==0.1.8 -pycodestyle==2.3.1 +pycodestyle==2.4.0 pycparser==2.18 -pyflakes==0.8.1 +pyflakes==2.0.0 Pygments==2.2.0 pyinotify==0.9.6 pyOpenSSL==17.1.0 @@ -86,7 +86,7 @@ python-novaclient==9.1.0 python-openstackclient==3.12.0 python-subunit==1.0.0 pytz==2013.6 -PyYAML==3.13 +PyYAML==5.3.1 repoze.lru==0.7 requests-mock==1.2.0 requests==2.14.2 @@ -97,7 +97,7 @@ simplejson==3.5.1 snowballstemmer==1.2.1 statsd==3.2.1 stestr==2.0.0 -stevedore==1.20.0 +stevedore==2.0.1 tempest==17.1.0 tenacity==3.2.1 testscenarios==0.4 diff --git a/requirements.txt b/requirements.txt index d10083c26..b08551ddf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ oslo.log>=3.36.0 # Apache-2.0 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 os-client-config>=1.28.0 # Apache-2.0 -keystoneauth1>=3.4.0 # Apache-2.0 +keystoneauth1>=3.8.0 # Apache-2.0 # keystoneclient is used only by neutronclient.osc.utils # TODO(amotoki): Drop this after osc.utils has no dependency on keystoneclient python-keystoneclient>=3.8.0 # Apache-2.0 From 2c2a1f4de7b6e3a1b8f3e3ff0fc5b23b5f0f4f7a Mon Sep 17 00:00:00 2001 From: likui Date: Mon, 10 May 2021 18:09:17 +0800 Subject: [PATCH 075/149] Replace getargspec with getfullargspec inspect.getargspec() is deprecated since py3 [1] https://docs.python.org/3/library/inspect.html#inspect.getargspec Change-Id: I2ae460a7a7f01d7346d5e51ec6ccb44c22d0c53e --- neutronclient/tests/unit/test_client_extension.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/tests/unit/test_client_extension.py b/neutronclient/tests/unit/test_client_extension.py index 7137ae7b3..871e7a6cb 100644 --- a/neutronclient/tests/unit/test_client_extension.py +++ b/neutronclient/tests/unit/test_client_extension.py @@ -217,5 +217,5 @@ def test_client_methods_have_parent_id_arg(self): self.client.delete_parents_child, self.client.create_parents_child) for method in methods: - argspec = inspect.getargspec(method) + argspec = inspect.getfullargspec(method) self.assertIn("parent_id", argspec.args) From 10227b681f546ef126b8f4ef2e9488c8a1a9f0c0 Mon Sep 17 00:00:00 2001 From: likui Date: Tue, 11 May 2021 17:43:33 +0800 Subject: [PATCH 076/149] setup.cfg: Replace dashes with underscores Setuptools v54.1.0 introduces a warning that the use of dash-separated options in 'setup.cfg' will not be supported in a future version [1]. Get ahead of the issue by replacing the dashes with underscores. Without this, we see 'UserWarning' messages like the following on new enough versions of setuptools: UserWarning: Usage of dash-separated 'description-file' will not be supported in future versions. Please use the underscore name 'description_file' instead [1] https://github.com/pypa/setuptools/commit/a2e9ae4cb Change-Id: I56804844c7438d7a5bffaaa363b9e3d79850c5c2 --- setup.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.cfg b/setup.cfg index ad537f71e..9f06b5c21 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,12 +1,12 @@ [metadata] name = python-neutronclient summary = CLI and Client Library for OpenStack Networking -description-file = +description_file = README.rst author = OpenStack Networking Project -author-email = openstack-discuss@lists.openstack.org -home-page = https://docs.openstack.org/python-neutronclient/latest/ -python-requires = >=3.6 +author_email = openstack-discuss@lists.openstack.org +home_page = https://docs.openstack.org/python-neutronclient/latest/ +python_requires = >=3.6 classifier = Environment :: OpenStack Intended Audience :: Developers From 439e290e95735dfa80b7e0fb193e45470128daec Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Thu, 27 May 2021 14:07:21 +0200 Subject: [PATCH 077/149] Skip metering functional tests when metering extension is not enabled Change-Id: I9e3f41a2be56c1fd5fc3aff9af8e5ff5163087bd --- neutronclient/tests/functional/core/test_readonly_neutron.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/neutronclient/tests/functional/core/test_readonly_neutron.py b/neutronclient/tests/functional/core/test_readonly_neutron.py index 20e1484e5..4fe989711 100644 --- a/neutronclient/tests/functional/core/test_readonly_neutron.py +++ b/neutronclient/tests/functional/core/test_readonly_neutron.py @@ -64,9 +64,13 @@ def test_neutron_floatingip_list(self): self.neutron('floatingip-list') def test_neutron_meter_label_list(self): + if not self.is_extension_enabled('metering'): + self.skipTest('metering is not enabled') self.neutron('meter-label-list') def test_neutron_meter_label_rule_list(self): + if not self.is_extension_enabled('metering'): + self.skipTest('metering is not enabled') self.neutron('meter-label-rule-list') def test_neutron_net_external_list(self): From 76dd26f9fdd35bf922509e587e25a30927517808 Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Thu, 27 May 2021 12:18:50 +0200 Subject: [PATCH 078/149] Set when deprecated neutron client CLI will be removed [1] was the last missing bit in OSC to have feature parity between OpenStack client and Neutronclient CLI tools. So now as [1] is merged we can really deprecate and specify that in Z cycle we will remove neutronclient CLI. This patch changes deprecation message to reflect that. [1] https://review.opendev.org/c/openstack/python-openstackclient/+/768210 Change-Id: Ia68af29ea15bda7330fda1b18416798a0f4cb7a4 --- doc/source/contributor/transition_to_osc.rst | 6 +++--- neutronclient/shell.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/source/contributor/transition_to_osc.rst b/doc/source/contributor/transition_to_osc.rst index b745d2f0c..334f2e57e 100644 --- a/doc/source/contributor/transition_to_osc.rst +++ b/doc/source/contributor/transition_to_osc.rst @@ -91,17 +91,17 @@ Transition Steps * **Done** `Security Group Rule CRUD `_ -6. **In Progress:** OSC continues enhancing its networking support. +6. **Done** OSC continues enhancing its networking support. At this point and when applicable, enhancements to the ``neutron`` CLI must also be made to the ``openstack`` CLI and possibly the OpenStack Python SDK. Users of the neutron client's command extensions should start their transition to the OSC plugin system. See the developer guide section below for more information on this step. -7. **In Progress:** Deprecate the ``neutron`` CLI. Running the CLI after +7. **Done** Deprecate the ``neutron`` CLI. Running the CLI after it has been `deprecated `_ will issue a warning message: - ``neutron CLI is deprecated and will be removed in the future. Use openstack CLI instead.`` + ``neutron CLI is deprecated and will be removed in the Z cycle. Use openstack CLI instead.`` In addition, no new features will be added to the CLI, though fixes to the CLI will be assessed on a case by case basis. diff --git a/neutronclient/shell.py b/neutronclient/shell.py index aed4c8fde..13cd0fa4e 100644 --- a/neutronclient/shell.py +++ b/neutronclient/shell.py @@ -637,7 +637,7 @@ def configure_logging(self): def main(argv=sys.argv[1:]): try: print(_("neutron CLI is deprecated and will be removed " - "in the future. Use openstack CLI instead."), file=sys.stderr) + "in the Z cycle. Use openstack CLI instead."), file=sys.stderr) return NeutronShell(NEUTRON_API_VERSION).run( list(map(encodeutils.safe_decode, argv))) except KeyboardInterrupt: From d6c211c139928fff3e1bcc41f069995892e233fe Mon Sep 17 00:00:00 2001 From: "wu.shiming" Date: Thu, 3 Jun 2021 14:48:16 +0800 Subject: [PATCH 079/149] Changed minversion in tox to 3.18.0 The patch bumps min version of tox to 3.18.0 in order to replace tox's whitelist_externals by allowlist_externals option: https://github.com/tox-dev/tox/blob/master/docs/changelog.rst#v3180-2020-07-23 Change-Id: I83717c5b2661df0d4288699903c38814cefb43d9 --- tox.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tox.ini b/tox.ini index a5d8ab120..8020b358b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = py38,pep8 -minversion = 2.3.2 +minversion = 3.18.0 skipsdist = True ignore_basepython_conflict = True @@ -23,7 +23,7 @@ commands = sh -c "find . -type d -name '.?*' -prune -o \ \( -type d -name '__pycache__' -o -type f -name '*.py[co]' \) \ -print0 | xargs -0 rm -rf" stestr run {posargs} -whitelist_externals = sh +allowlist_externals = sh [testenv:pep8] commands = @@ -59,7 +59,7 @@ commands = sphinx-build -W -b html doc/source doc/build/html [testenv:pdf-docs] envdir = {toxworkdir}/docs deps = {[testenv:docs]deps} -whitelist_externals = +allowlist_externals = make commands = sphinx-build -W -b latex doc/source doc/build/pdf From ae397565be6b734484d9e96c66f13de97762303c Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Wed, 9 Jun 2021 14:35:54 +0900 Subject: [PATCH 080/149] Add a release note on deprecation for removal of neutron CLI Change-Id: I866ade23cd76cf1e44e10eeb15dcc02cc8d0dc66 --- .../neutron-cli-deprecation-398823c87270a296.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 releasenotes/notes/neutron-cli-deprecation-398823c87270a296.yaml diff --git a/releasenotes/notes/neutron-cli-deprecation-398823c87270a296.yaml b/releasenotes/notes/neutron-cli-deprecation-398823c87270a296.yaml new file mode 100644 index 000000000..a8065940e --- /dev/null +++ b/releasenotes/notes/neutron-cli-deprecation-398823c87270a296.yaml @@ -0,0 +1,10 @@ +--- +deprecations: + - | + ``neutron`` CLI will be removed in 'Z' release. + While it has been marked as deprecated for removal for long, + all features in ``neutron`` CLI have been supported in ``openstack`` CLI + (OpenStackClient) as of Xena release and the neutron team plans to + remove it in 'Z' release. Consider using ``openstack`` CLI and + `Mapping Guide `__ + in the OSC documentation would help you. From a1ebfaa7f22e71fb59eea05ff11bbfe5bede41ba Mon Sep 17 00:00:00 2001 From: dengzhaosen Date: Thu, 6 May 2021 09:50:35 +0800 Subject: [PATCH 081/149] Ussuri+ is python3 only and update python to python3 To remove the useless shebang Change-Id: I611c5bc47562f8def9a8623117b7b0655474b555 --- neutronclient/tests/unit/test_cli20_floatingips.py | 1 - neutronclient/tests/unit/test_cli20_securitygroup.py | 1 - neutronclient/tests/unit/test_quota.py | 1 - 3 files changed, 3 deletions(-) diff --git a/neutronclient/tests/unit/test_cli20_floatingips.py b/neutronclient/tests/unit/test_cli20_floatingips.py index 9a1c39863..d77bda6e8 100644 --- a/neutronclient/tests/unit/test_cli20_floatingips.py +++ b/neutronclient/tests/unit/test_cli20_floatingips.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright 2012 Red Hat # All Rights Reserved. # diff --git a/neutronclient/tests/unit/test_cli20_securitygroup.py b/neutronclient/tests/unit/test_cli20_securitygroup.py index f5ed8ad1e..95a578f63 100644 --- a/neutronclient/tests/unit/test_cli20_securitygroup.py +++ b/neutronclient/tests/unit/test_cli20_securitygroup.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright 2012 Red Hat # All Rights Reserved. # diff --git a/neutronclient/tests/unit/test_quota.py b/neutronclient/tests/unit/test_quota.py index 4529287b0..747621de9 100644 --- a/neutronclient/tests/unit/test_quota.py +++ b/neutronclient/tests/unit/test_quota.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright (C) 2013 Yahoo! Inc. # All Rights Reserved. # From 23fb666f923e9fa117ce5744e9abe00d3874d3fc Mon Sep 17 00:00:00 2001 From: elajkat Date: Mon, 26 Jul 2021 14:54:15 +0200 Subject: [PATCH 082/149] tests: change safe_hasattr to hasattr testtools 2.5.0 removed the helper (see [0]) safe_hasattr, and assumes that the hasattr implementation in python reliable enough now. test_neutron_dhcp_agent_list_hosting_net is skipped temporarily as there is no DHCP agent with ML2/OVN. It will be re-enabled [1]. [0] https://github.com/testing-cabal/testtools/blob/2.5.0/NEWS#L31 [1] https://review.opendev.org/c/openstack/python-neutronclient/+/801997 Change-Id: I4fe6fabc4f745e2c9a366e30dbea7e7200151f12 --- neutronclient/tests/functional/core/test_readonly_neutron.py | 2 ++ neutronclient/tests/unit/test_command_meta.py | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/neutronclient/tests/functional/core/test_readonly_neutron.py b/neutronclient/tests/functional/core/test_readonly_neutron.py index 4fe989711..41ee52448 100644 --- a/neutronclient/tests/functional/core/test_readonly_neutron.py +++ b/neutronclient/tests/functional/core/test_readonly_neutron.py @@ -13,6 +13,7 @@ import re from tempest.lib import exceptions +import testtools from neutronclient.tests.functional import base @@ -51,6 +52,7 @@ def test_neutron_ext_list(self): ext = self.parser.listing(self.neutron('ext-list')) self.assertTableStruct(ext, ['alias', 'name']) + @testtools.skip('Skipped until ML2/OVS is enabled') def test_neutron_dhcp_agent_list_hosting_net(self): self.neutron('dhcp-agent-list-hosting-net', params='private') diff --git a/neutronclient/tests/unit/test_command_meta.py b/neutronclient/tests/unit/test_command_meta.py index 184f36680..dedc3dd1c 100644 --- a/neutronclient/tests/unit/test_command_meta.py +++ b/neutronclient/tests/unit/test_command_meta.py @@ -20,7 +20,6 @@ import logging import testtools -from testtools import helpers from neutronclient.neutron import v2_0 as neutronV20 @@ -30,7 +29,7 @@ def test_neutron_command_meta_defines_log(self): class FakeCommand(neutronV20.NeutronCommand): pass - self.assertTrue(helpers.safe_hasattr(FakeCommand, 'log')) + self.assertTrue(hasattr(FakeCommand, 'log')) self.assertIsInstance(FakeCommand.log, logging.getLoggerClass()) self.assertEqual(__name__ + ".FakeCommand", FakeCommand.log.name) @@ -38,5 +37,5 @@ def test_neutron_command_log_defined_explicitly(self): class FakeCommand(neutronV20.NeutronCommand): log = None - self.assertTrue(helpers.safe_hasattr(FakeCommand, 'log')) + self.assertTrue(hasattr(FakeCommand, 'log')) self.assertIsNone(FakeCommand.log) From 2f047b15957308e84dcb72baee3415b8bf5a470a Mon Sep 17 00:00:00 2001 From: Bernard Cafarelli Date: Fri, 23 Jul 2021 11:23:22 +0200 Subject: [PATCH 083/149] Set ML2/OVS backend explicitly for functional job After default backend change to OVN, some client tests related to DHCP or L3 agents are not working fine. Switch the job to ML2/OVS, as it was done in openstack-client in changeset Idf6466a59c6cf96be2f1d53e696f0564584fa233 test_neutron_dhcp_agent_list_hosting_net was skipped temporarily to pass the gate in the parent commit. It is re-enabled now. Change-Id: I91d03d13adcd38d46ba1b042239a290ae2c99ea4 Closes-Bug: #1936965 --- .zuul.yaml | 22 +++++++++++++++++++ .../functional/core/test_readonly_neutron.py | 2 -- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index 061a6001e..58f54dfe6 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -38,9 +38,31 @@ # NOTE: neutronclient.tests.functional.base.ClientTestBase does not # support HTTPS endpoints now, so tls-proxy needs to be disabled. tls-proxy: false + # Disable OVN services + br-ex-tcpdump: false + br-int-flows: false + ovn-controller: false + ovn-northd: false + ovs-vswitchd: false + ovsdb-server: false + q-ovn-metadata-agent: false + # Neutron services + q-agt: true + q-dhcp: true + q-l3: true + q-meta: true + neutron-network-segment-range: true + neutron-segments: true + q-metering: true + q-qos: true + neutron-tag-ports-during-bulk-creation: true + neutron-conntrack-helper: true devstack_localrc: USE_PYTHON3: true LIBS_FROM_GIT: python-neutronclient + Q_AGENT: openvswitch + Q_ML2_TENANT_NETWORK_TYPE: vxlan + Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch devstack_plugins: neutron-vpnaas: https://opendev.org/openstack/neutron-vpnaas diff --git a/neutronclient/tests/functional/core/test_readonly_neutron.py b/neutronclient/tests/functional/core/test_readonly_neutron.py index 41ee52448..4fe989711 100644 --- a/neutronclient/tests/functional/core/test_readonly_neutron.py +++ b/neutronclient/tests/functional/core/test_readonly_neutron.py @@ -13,7 +13,6 @@ import re from tempest.lib import exceptions -import testtools from neutronclient.tests.functional import base @@ -52,7 +51,6 @@ def test_neutron_ext_list(self): ext = self.parser.listing(self.neutron('ext-list')) self.assertTableStruct(ext, ['alias', 'name']) - @testtools.skip('Skipped until ML2/OVS is enabled') def test_neutron_dhcp_agent_list_hosting_net(self): self.neutron('dhcp-agent-list-hosting-net', params='private') From f83108d85874a87e47b51af3eebc9faeeb11faa0 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Mon, 19 Jul 2021 11:44:28 +0900 Subject: [PATCH 084/149] Use yaml.safe_load instead of yaml.load Since PyYAML 5.1, yaml.load without specifying the Loader option is deprecated and shows the following warning. YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details. This change replaces usage of yaml.load by yaml.safe_load, to get rid of that warning message. Change-Id: Ibe25c4aaf3aa7226f28ec60b8a929ecc143face1 --- neutronclient/tests/functional/core/test_cli_formatter.py | 2 +- neutronclient/tests/unit/test_cli20.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/neutronclient/tests/functional/core/test_cli_formatter.py b/neutronclient/tests/functional/core/test_cli_formatter.py index cd133dee1..145ed6c67 100644 --- a/neutronclient/tests/functional/core/test_cli_formatter.py +++ b/neutronclient/tests/functional/core/test_cli_formatter.py @@ -43,7 +43,7 @@ def test_net_create_with_yaml_formatter(self): result = self._create_net('yaml', ['name', 'admin_state_up']) self.assertDictEqual({'name': self.net_name, 'admin_state_up': True}, - yaml.load(result)) + yaml.safe_load(result)) def test_net_create_with_value_formatter(self): # NOTE(amotoki): In 'value' formatter, there is no guarantee diff --git a/neutronclient/tests/unit/test_cli20.py b/neutronclient/tests/unit/test_cli20.py index c2143e168..a067ee893 100644 --- a/neutronclient/tests/unit/test_cli20.py +++ b/neutronclient/tests/unit/test_cli20.py @@ -1159,7 +1159,7 @@ def test_create_resource_json(self): def test_create_resource_yaml(self): self._test_create_resource_with_formatter('yaml') - data = yaml.load(self.fake_stdout.make_string()) + data = yaml.safe_load(self.fake_stdout.make_string()) self.assertEqual('myname', data['name']) self.assertEqual('myid', data['id']) @@ -1184,7 +1184,7 @@ def test_show_resource_json(self): def test_show_resource_yaml(self): self._test_show_resource_with_formatter('yaml') - data = yaml.load(''.join(self.fake_stdout.content)) + data = yaml.safe_load(''.join(self.fake_stdout.content)) self.assertEqual('myname', data['name']) self.assertEqual('myid', data['id']) @@ -1211,5 +1211,5 @@ def test_list_resources_json(self): def test_list_resources_yaml(self): self._test_list_resources_with_formatter('yaml') - data = yaml.load(''.join(self.fake_stdout.content)) + data = yaml.safe_load(''.join(self.fake_stdout.content)) self.assertEqual(['myid1', 'myid2'], [d['id'] for d in data]) From cff9c266c05ebfc13f4917e1646e5dedbe371cc2 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Sun, 5 Sep 2021 00:56:38 +0900 Subject: [PATCH 085/149] Replace deprecated assertDictContainsSubset The method is deprecated since Python 3.2[1] and shows the following DeprecationWarning. /usr/lib/python3.9/unittest/case.py:1134: DeprecationWarning: assertDictContainsSubset is deprecated warnings.warn('assertDictContainsSubset is deprecated', [1] https://docs.python.org/3/whatsnew/3.2.html#unittest Closes-Bug: #1938103 Change-Id: I1d0ee6c77476707a7e4fe4fbf2b979bf34550d05 --- neutronclient/tests/unit/test_shell.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/neutronclient/tests/unit/test_shell.py b/neutronclient/tests/unit/test_shell.py index 9dc2faac8..04e814066 100644 --- a/neutronclient/tests/unit/test_shell.py +++ b/neutronclient/tests/unit/test_shell.py @@ -357,10 +357,10 @@ def test_commands_dict_populated(self): self.useFixture(fixtures.MockPatchObject(openstack_shell, 'COMMANDS', None)) openstack_shell.NeutronShell('2.0') - self.assertDictContainsSubset( + self.assertLessEqual( {'net-create': network.CreateNetwork, 'net-delete': network.DeleteNetwork, 'net-list': network.ListNetwork, 'net-show': network.ShowNetwork, - 'net-update': network.UpdateNetwork}, - openstack_shell.COMMANDS['2.0']) + 'net-update': network.UpdateNetwork}.items(), + openstack_shell.COMMANDS['2.0'].items()) From ee73a48881b9a10938d477f297c75ecac48e0935 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Fri, 10 Sep 2021 14:33:52 +0000 Subject: [PATCH 086/149] Update master for stable/xena Add file to the reno documentation build to show release notes for stable/xena. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/xena. Sem-Ver: feature Change-Id: If1185e64ff9e9c2a622f7a41df3993b3fe414b96 --- releasenotes/source/index.rst | 1 + releasenotes/source/xena.rst | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/xena.rst diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index bfa147dd9..0be3cf0ac 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + xena wallaby victoria ussuri diff --git a/releasenotes/source/xena.rst b/releasenotes/source/xena.rst new file mode 100644 index 000000000..1be85be3e --- /dev/null +++ b/releasenotes/source/xena.rst @@ -0,0 +1,6 @@ +========================= +Xena Series Release Notes +========================= + +.. release-notes:: + :branch: stable/xena From 792ad115b3e266e70932946ed5187691edb061fc Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Fri, 10 Sep 2021 14:33:53 +0000 Subject: [PATCH 087/149] Add Python3 yoga unit tests This is an automatically generated patch to ensure unit testing is in place for all the of the tested runtimes for yoga. See also the PTI in governance [1]. [1]: https://governance.openstack.org/tc/reference/project-testing-interface.html Change-Id: Ib343cb56e2512862d5b23482a9861ba7b3ce6373 --- .zuul.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zuul.yaml b/.zuul.yaml index 58f54dfe6..e16794bcb 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -2,7 +2,7 @@ templates: - openstack-cover-jobs - openstack-lower-constraints-jobs - - openstack-python3-xena-jobs + - openstack-python3-yoga-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing-python3 From 1df1f38a91afd158336044a57f7e4c8e11108a94 Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Tue, 14 Sep 2021 14:24:58 +0200 Subject: [PATCH 088/149] Add support for 'smart-nic' vnic-type The 'smart-nic' vnic_type was added in the Train time frame in I91f63810626ce4e054e358f5de5e46434c4da131. This vnic_type will also be used to support off-path SmartNIC port binding with OVN, and it is expected that the user will create ports with this vnic_type as part of the workflow. As such the client must allow users to interact with this vnic_type and this patch addresses that. Partial-Bug: #1932154 Change-Id: I7f80bb47db7f8608db4d6a646b0f4b0ef6d6fb48 --- neutronclient/neutron/v2_0/port.py | 6 +++--- neutronclient/tests/unit/test_cli20_port.py | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/neutronclient/neutron/v2_0/port.py b/neutronclient/neutron/v2_0/port.py index 0982b049a..3fe73544b 100644 --- a/neutronclient/neutron/v2_0/port.py +++ b/neutronclient/neutron/v2_0/port.py @@ -245,15 +245,15 @@ def add_known_arguments(self, parser): parser.add_argument( '--vnic-type', metavar='', + '| normal | baremetal | smart-nic>', choices=['direct', 'direct-physical', 'macvtap', - 'normal', 'baremetal'], + 'normal', 'baremetal', 'smart-nic'], type=utils.convert_to_lowercase, help=_('VNIC type for this port.')) parser.add_argument( '--vnic_type', choices=['direct', 'direct-physical', 'macvtap', - 'normal', 'baremetal'], + 'normal', 'baremetal', 'smart-nic'], type=utils.convert_to_lowercase, help=argparse.SUPPRESS) parser.add_argument( diff --git a/neutronclient/tests/unit/test_cli20_port.py b/neutronclient/tests/unit/test_cli20_port.py index e1ab411e5..ab7e95655 100644 --- a/neutronclient/tests/unit/test_cli20_port.py +++ b/neutronclient/tests/unit/test_cli20_port.py @@ -214,6 +214,26 @@ def test_create_port_vnic_type_baremetal(self): self._test_create_resource(resource, cmd, name, myid, args, position_names, position_values) + def test_create_port_vnic_type_smart_nic(self): + # Create port: --vnic_type smart-nic netid. + resource = 'port' + cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) + name = 'myname' + myid = 'myid' + netid = 'netid' + args = ['--vnic_type', 'smart-nic', netid] + position_names = ['binding:vnic_type', 'network_id'] + position_values = ['smart-nic', netid] + self._test_create_resource(resource, cmd, name, myid, args, + position_names, position_values) + + # Test dashed options + args = ['--vnic-type', 'smart-nic', netid] + position_names = ['binding:vnic_type', 'network_id'] + position_values = ['smart-nic', netid] + self._test_create_resource(resource, cmd, name, myid, args, + position_names, position_values) + def test_create_port_with_binding_profile(self): resource = 'port' cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) From 3a65712b451d3eed93cbf7eef773d46c49df6358 Mon Sep 17 00:00:00 2001 From: elajkat Date: Thu, 18 Nov 2021 15:00:28 +0100 Subject: [PATCH 089/149] Fix lower-constraints and neutronclient-functional job Change decorator in l-c.txt from 3.4.0 to 4.1.0 add neutron as devstack plugin to neutronclient-functional job. Change-Id: Ib4b98f4e9e70f058ba5c7c43f559ab888edf1a88 --- .zuul.yaml | 1 + lower-constraints.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.zuul.yaml b/.zuul.yaml index e16794bcb..c82467aee 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -64,6 +64,7 @@ Q_ML2_TENANT_NETWORK_TYPE: vxlan Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch devstack_plugins: + neutron: https://opendev.org/openstack/neutron neutron-vpnaas: https://opendev.org/openstack/neutron-vpnaas - job: diff --git a/lower-constraints.txt b/lower-constraints.txt index 44c70fafc..7a7c54b6f 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -11,7 +11,7 @@ contextlib2==0.4.0 coverage==4.0 cryptography==2.7 debtcollector==1.2.0 -decorator==3.4.0 +decorator==4.1.0 deprecation==1.0 docutils==0.11 dogpile.cache==0.6.5 From 3b80135a3d364abfaf3b3ead03bae3348627d1b2 Mon Sep 17 00:00:00 2001 From: Przemyslaw Szczerbik Date: Fri, 1 Oct 2021 10:01:48 +0200 Subject: [PATCH 090/149] Add support for minimum packet rate rule to the client With the introduction of QoS minimum packet rate rule in Neutron, it's important to ensure that tools like Heat support it as well. Unfortunately, Heat still depends on python-neutronclient instead of python-openstackclient. So even though QoS minimum packet rate rule support have been proposed for python-openstackclient [1] and openstacksdk [2], it's still necessary to extend python-neutronclient code. Since Heat uses only the client part, can skip CLI support. [1] https://review.opendev.org/c/openstack/python-openstackclient/+/810559 [2] https://review.opendev.org/c/openstack/openstacksdk/+/810364 Partial-Bug: #1922237 See-Also: https://review.opendev.org/785236 Change-Id: I4f16b963a202a476cd3cd2b69c1dd4e4ee6f0fc7 --- neutronclient/v2_0/client.py | 34 +++++++++++++++++++ .../minimum-packet-rate-34576b8fd98a3034.yaml | 7 ++++ 2 files changed, 41 insertions(+) create mode 100644 releasenotes/notes/minimum-packet-rate-34576b8fd98a3034.yaml diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index c264dfd14..f318f3ce9 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -625,6 +625,10 @@ class Client(ClientBase): "/qos/policies/%s/minimum_bandwidth_rules" qos_minimum_bandwidth_rule_path = \ "/qos/policies/%s/minimum_bandwidth_rules/%s" + qos_minimum_packet_rate_rules_path = \ + "/qos/policies/%s/minimum_packet_rate_rules" + qos_minimum_packet_rate_rule_path = \ + "/qos/policies/%s/minimum_packet_rate_rules/%s" qos_rule_types_path = "/qos/rule-types" qos_rule_type_path = "/qos/rule-types/%s" flavors_path = "/flavors" @@ -709,6 +713,7 @@ class Client(ClientBase): 'policies': 'policy', 'bandwidth_limit_rules': 'bandwidth_limit_rule', 'minimum_bandwidth_rules': 'minimum_bandwidth_rule', + 'minimum_packet_rate_rules': 'minimum_packet_rate_rule', 'rules': 'rule', 'dscp_marking_rules': 'dscp_marking_rule', 'rule_types': 'rule_type', @@ -1982,6 +1987,35 @@ def delete_minimum_bandwidth_rule(self, rule, policy): return self.delete(self.qos_minimum_bandwidth_rule_path % (policy, rule)) + def list_minimum_packet_rate_rules(self, policy_id, retrieve_all=True, + **_params): + """Fetches a list of all minimum packet rate rules for the given policy + + """ + return self.list('minimum_packet_rate_rules', + self.qos_minimum_packet_rate_rules_path % + policy_id, retrieve_all, **_params) + + def show_minimum_packet_rate_rule(self, rule, policy, body=None): + """Fetches information of a certain minimum packet rate rule.""" + return self.get(self.qos_minimum_packet_rate_rule_path % + (policy, rule), body=body) + + def create_minimum_packet_rate_rule(self, policy, body=None): + """Creates a new minimum packet rate rule.""" + return self.post(self.qos_minimum_packet_rate_rules_path % policy, + body=body) + + def update_minimum_packet_rate_rule(self, rule, policy, body=None): + """Updates a minimum packet rate rule.""" + return self.put(self.qos_minimum_packet_rate_rule_path % + (policy, rule), body=body) + + def delete_minimum_packet_rate_rule(self, rule, policy): + """Deletes a minimum packet rate rule.""" + return self.delete(self.qos_minimum_packet_rate_rule_path % + (policy, rule)) + def create_flavor(self, body=None): """Creates a new Neutron service flavor.""" return self.post(self.flavors_path, body=body) diff --git a/releasenotes/notes/minimum-packet-rate-34576b8fd98a3034.yaml b/releasenotes/notes/minimum-packet-rate-34576b8fd98a3034.yaml new file mode 100644 index 000000000..7ce33f65e --- /dev/null +++ b/releasenotes/notes/minimum-packet-rate-34576b8fd98a3034.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Added new client methods for QoS minimum packet rate rule: + ``list_minimum_packet_rate_rules``, ``show_minimum_packet_rate_rule``, + ``create_minimum_packet_rate_rule``, ``update_minimum_packet_rate_rule``, + ``delete_minimum_packet_rate_rule``. From a92d8db81c7f13e46aa64be471de06054379be75 Mon Sep 17 00:00:00 2001 From: LIU Yulong Date: Mon, 22 Nov 2021 15:01:42 +0800 Subject: [PATCH 091/149] Add CURD actions for packet rate limit rule Neutron added new QoS rule [1] for packet rate limit. Neutron fullstack test cases [2] rely on the neutron client to interact with the neutron-server (API), so for new QoS rule `packet rate limit`, we add the needed methods for new cases of the QoS driver testing. [1] https://docs.openstack.org/api-ref/network/v2/index.html#qos-packet-rate-limit-rules [2] https://github.com/openstack/neutron/blob/master/neutron/tests/fullstack/resources/process.py#L24 Change-Id: I0ad236c9e585a25fbd405813ac48898a2df897d2 --- neutronclient/v2_0/client.py | 34 +++++++++++++++++++ .../paket_rate_limit-1266a2a30f18727f.yaml | 7 ++++ 2 files changed, 41 insertions(+) create mode 100644 releasenotes/notes/paket_rate_limit-1266a2a30f18727f.yaml diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index c264dfd14..b64f3e685 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -619,6 +619,10 @@ class Client(ClientBase): qos_policy_path = "/qos/policies/%s" qos_bandwidth_limit_rules_path = "/qos/policies/%s/bandwidth_limit_rules" qos_bandwidth_limit_rule_path = "/qos/policies/%s/bandwidth_limit_rules/%s" + qos_packet_rate_limit_rules_path = \ + "/qos/policies/%s/packet_rate_limit_rules" + qos_packet_rate_limit_rule_path = \ + "/qos/policies/%s/packet_rate_limit_rules/%s" qos_dscp_marking_rules_path = "/qos/policies/%s/dscp_marking_rules" qos_dscp_marking_rule_path = "/qos/policies/%s/dscp_marking_rules/%s" qos_minimum_bandwidth_rules_path = \ @@ -708,6 +712,7 @@ class Client(ClientBase): 'qos_policies': 'qos_policy', 'policies': 'policy', 'bandwidth_limit_rules': 'bandwidth_limit_rule', + 'packet_rate_limit_rules': 'packet_rate_limit_rule', 'minimum_bandwidth_rules': 'minimum_bandwidth_rule', 'rules': 'rule', 'dscp_marking_rules': 'dscp_marking_rule', @@ -1972,6 +1977,35 @@ def create_minimum_bandwidth_rule(self, policy, body=None): return self.post(self.qos_minimum_bandwidth_rules_path % policy, body=body) + def list_packet_rate_limit_rules(self, policy_id, retrieve_all=True, + **_params): + """Fetches a list of all packet rate limit rules for the given policy + + """ + return self.list('packet_rate_limit_rules', + self.qos_packet_rate_limit_rules_path % + policy_id, retrieve_all, **_params) + + def show_packet_rate_limit_rule(self, rule, policy, body=None): + """Fetches information of a certain packet rate limit rule.""" + return self.get(self.qos_packet_rate_limit_rule_path % + (policy, rule), body=body) + + def create_packet_rate_limit_rule(self, policy, body=None): + """Creates a new packet rate limit rule.""" + return self.post(self.qos_packet_rate_limit_rules_path % policy, + body=body) + + def update_packet_rate_limit_rule(self, rule, policy, body=None): + """Updates a packet rate limit rule.""" + return self.put(self.qos_packet_rate_limit_rule_path % + (policy, rule), body=body) + + def delete_packet_rate_limit_rule(self, rule, policy): + """Deletes a packet rate limit rule.""" + return self.delete(self.qos_packet_rate_limit_rule_path % + (policy, rule)) + def update_minimum_bandwidth_rule(self, rule, policy, body=None): """Updates a minimum bandwidth rule.""" return self.put(self.qos_minimum_bandwidth_rule_path % diff --git a/releasenotes/notes/paket_rate_limit-1266a2a30f18727f.yaml b/releasenotes/notes/paket_rate_limit-1266a2a30f18727f.yaml new file mode 100644 index 000000000..9fdfc1e62 --- /dev/null +++ b/releasenotes/notes/paket_rate_limit-1266a2a30f18727f.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Added new client methods for QoS packet rate limit rule: + ``list_packet_rate_limit_rules``, ``show_packet_rate_limit_rule``, + ``create_packet_rate_limit_rule``, ``update_packet_rate_limit_rule``, + ``delete_packet_rate_limit_rule``. From 517bef2c5454dde2eba5cc2194ee857be6be7164 Mon Sep 17 00:00:00 2001 From: dengzhaosen Date: Tue, 21 Dec 2021 17:33:43 +0800 Subject: [PATCH 092/149] Update python testing classifier Yoga testing runtime[1] has been updated to add py39 testing as voting. Unit tests update are handled by the job template change in openstack-zuul-job - https://review.opendev.org/c/openstack/openstack-zuul-jobs/+/820286 this commit updates the classifier in setup.cfg file. [1] https://governance.openstack.org/tc/reference/runtimes/yoga.html Change-Id: Iedb1c345df99ae9be5cce22ab930c6de7a5e7832 --- setup.cfg | 1 + tox.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 9f06b5c21..a1a60d82d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -21,6 +21,7 @@ classifier = Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 [files] packages = diff --git a/tox.ini b/tox.ini index 8020b358b..8e7aa1673 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py38,pep8 +envlist = py39,pep8 minversion = 3.18.0 skipsdist = True ignore_basepython_conflict = True From 28628e8f962c49aa276647ca2b2e71a2be530277 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Thu, 3 Mar 2022 00:24:33 +0000 Subject: [PATCH 093/149] Skip B105 pep8 error: hardcoded passwords Skip B105 pep8 error: * https://bandit.readthedocs.io/en/latest/plugins/b105_hardcoded_password_string.html * https://cwe.mitre.org/data/definitions/259.html Trivial-Fix Change-Id: I8e58da2d88d727018c8d5af5949e34f8c0893c1f --- tox.ini | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 8e7aa1673..9136a0f9e 100644 --- a/tox.ini +++ b/tox.ini @@ -81,8 +81,11 @@ enable-extensions=H904 [testenv:bandit] # B303: blacklist calls: md5, sha1 +# B105: The software contains a hard-coded password, which it uses for its own +# inbound authentication or for outbound communication to external +# components. deps = -r{toxinidir}/test-requirements.txt -commands = bandit -r neutronclient -x tests -n5 -s B303 +commands = bandit -r neutronclient -x tests -n5 -s B303,B105 [testenv:lower-constraints] deps = From 4575bea5a6e80bcbc360f259466a6c4c69364cf0 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 3 Mar 2022 10:52:26 +0000 Subject: [PATCH 094/149] Update master for stable/yoga Add file to the reno documentation build to show release notes for stable/yoga. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/yoga. Sem-Ver: feature Change-Id: I3f709510026817ae2f36d646ca3fe9487637b717 --- releasenotes/source/index.rst | 1 + releasenotes/source/yoga.rst | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/yoga.rst diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index 0be3cf0ac..2a7aeaa06 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + yoga xena wallaby victoria diff --git a/releasenotes/source/yoga.rst b/releasenotes/source/yoga.rst new file mode 100644 index 000000000..7cd5e908a --- /dev/null +++ b/releasenotes/source/yoga.rst @@ -0,0 +1,6 @@ +========================= +Yoga Series Release Notes +========================= + +.. release-notes:: + :branch: stable/yoga From 143db0177acbd5606c34980b865e81f05413a47e Mon Sep 17 00:00:00 2001 From: Ghanshyam Mann Date: Sat, 30 Apr 2022 20:17:09 -0500 Subject: [PATCH 095/149] Drop lower-constraints.txt and its testing As discussed in TC PTG[1] and TC resolution[2], we are dropping the lower-constraints.txt file and its testing. We will keep lower bounds in the requirements.txt file but with a note that these are not tested lower bounds and we try our best to keep them updated. [1] https://etherpad.opendev.org/p/tc-zed-ptg#L326 [2] https://governance.openstack.org/tc/resolutions/20220414-drop-lower-constraints.html#proposal Change-Id: I9a985c439675dc3aa6120a0d9734b8cdeaedccf8 --- .zuul.yaml | 1 - lower-constraints.txt | 111 ------------------------------------------ requirements.txt | 4 ++ tox.ini | 6 --- 4 files changed, 4 insertions(+), 118 deletions(-) delete mode 100644 lower-constraints.txt diff --git a/.zuul.yaml b/.zuul.yaml index c82467aee..b709db00e 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -1,7 +1,6 @@ - project: templates: - openstack-cover-jobs - - openstack-lower-constraints-jobs - openstack-python3-yoga-jobs - publish-openstack-docs-pti - check-requirements diff --git a/lower-constraints.txt b/lower-constraints.txt deleted file mode 100644 index 7a7c54b6f..000000000 --- a/lower-constraints.txt +++ /dev/null @@ -1,111 +0,0 @@ -alabaster==0.7.10 -amqp==2.1.1 -appdirs==1.3.0 -asn1crypto==0.23.0 -Babel==2.3.4 -cachetools==2.0.0 -cffi==1.14.0 -cliff==3.4.0 -cmd2==0.8.0 -contextlib2==0.4.0 -coverage==4.0 -cryptography==2.7 -debtcollector==1.2.0 -decorator==4.1.0 -deprecation==1.0 -docutils==0.11 -dogpile.cache==0.6.5 -dulwich==0.15.0 -eventlet==0.18.2 -extras==1.0.0 -fasteners==0.7.0 -fixtures==3.0.0 -flake8-import-order==0.12 -flake8==3.6.0 -future==0.16.0 -futurist==1.2.0 -greenlet==0.4.10 -hacking==3.0.1 -idna==2.6 -imagesize==0.7.1 -iso8601==0.1.11 -Jinja2==2.10 -jmespath==0.9.0 -jsonpatch==1.16 -jsonpointer==1.13 -jsonschema==2.6.0 -keystoneauth1==3.8.0 -kombu==4.0.0 -linecache2==1.0.0 -MarkupSafe==1.0 -mccabe==0.6.0 -monotonic==0.6 -msgpack-python==0.4.0 -munch==2.1.0 -netaddr==0.7.18 -netifaces==0.10.4 -openstacksdk==0.15.0 -os-client-config==1.28.0 -os-service-types==1.2.0 -osc-lib==1.12.0 -oslo.concurrency==3.26.0 -oslo.config==5.2.0 -oslo.context==2.19.2 -oslo.i18n==3.15.3 -oslo.log==3.36.0 -oslo.messaging==5.29.0 -oslo.middleware==3.31.0 -oslo.serialization==2.18.0 -oslo.service==1.24.0 -oslo.utils==3.33.0 -oslotest==3.2.0 -osprofiler==2.3.0 -paramiko==2.0.0 -Paste==2.0.2 -PasteDeploy==1.5.0 -pbr==2.0.0 -pika-pool==0.1.3 -pika==0.10.0 -positional==1.2.1 -prettytable==0.7.2 -pyasn1==0.1.8 -pycodestyle==2.4.0 -pycparser==2.18 -pyflakes==2.0.0 -Pygments==2.2.0 -pyinotify==0.9.6 -pyOpenSSL==17.1.0 -pyparsing==2.1.0 -pyperclip==1.5.27 -python-cinderclient==3.3.0 -python-dateutil==2.5.3 -python-glanceclient==2.8.0 -python-keystoneclient==3.8.0 -python-mimeparse==1.6.0 -python-novaclient==9.1.0 -python-openstackclient==3.12.0 -python-subunit==1.0.0 -pytz==2013.6 -PyYAML==5.3.1 -repoze.lru==0.7 -requests-mock==1.2.0 -requests==2.14.2 -requestsexceptions==1.2.0 -rfc3986==0.3.1 -Routes==2.3.1 -simplejson==3.5.1 -snowballstemmer==1.2.1 -statsd==3.2.1 -stestr==2.0.0 -stevedore==2.0.1 -tempest==17.1.0 -tenacity==3.2.1 -testscenarios==0.4 -testtools==2.2.0 -traceback2==1.4.0 -unittest2==1.1.0 -urllib3==1.21.1 -vine==1.1.4 -warlock==1.2.0 -WebOb==1.7.1 -wrapt==1.7.0 diff --git a/requirements.txt b/requirements.txt index b08551ddf..b85e6b69a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,7 @@ +# Requirements lower bounds listed here are our best effort to keep them up to +# date but we do not test them so no guarantee of having them all correct. If +# you find any incorrect lower bounds, let us know or propose a fix. + # The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. diff --git a/tox.ini b/tox.ini index 9136a0f9e..bd421721e 100644 --- a/tox.ini +++ b/tox.ini @@ -86,9 +86,3 @@ enable-extensions=H904 # components. deps = -r{toxinidir}/test-requirements.txt commands = bandit -r neutronclient -x tests -n5 -s B303,B105 - -[testenv:lower-constraints] -deps = - -c{toxinidir}/lower-constraints.txt - -r{toxinidir}/test-requirements.txt - -r{toxinidir}/requirements.txt From b720fdaee7cb2bc8d38c63042c0b455cfd2be312 Mon Sep 17 00:00:00 2001 From: Ghanshyam Mann Date: Wed, 11 May 2022 22:25:31 -0500 Subject: [PATCH 096/149] Update python testing as per zed cycle teting runtime In Zed cycle, we have dropped the python 3.6/3.7[1] testing and its support. Add release notes, move py36 jobs to py38|9, and update the python classifier for the same. [1] https://governance.openstack.org/tc/reference/runtimes/zed.html Change-Id: Ibeee0b16ee1ea95f05127563a9cb08ffd0f04e2b --- .zuul.yaml | 2 +- .../notes/drop-python-3-6-and-3-7-73767fa0bbe89a6e.yaml | 5 +++++ setup.cfg | 4 +--- 3 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/drop-python-3-6-and-3-7-73767fa0bbe89a6e.yaml diff --git a/.zuul.yaml b/.zuul.yaml index b709db00e..e7645b60d 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -1,7 +1,7 @@ - project: templates: - openstack-cover-jobs - - openstack-python3-yoga-jobs + - openstack-python3-zed-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing-python3 diff --git a/releasenotes/notes/drop-python-3-6-and-3-7-73767fa0bbe89a6e.yaml b/releasenotes/notes/drop-python-3-6-and-3-7-73767fa0bbe89a6e.yaml new file mode 100644 index 000000000..db420d739 --- /dev/null +++ b/releasenotes/notes/drop-python-3-6-and-3-7-73767fa0bbe89a6e.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - | + Python 3.6 & 3.7 support has been dropped. The minimum version of Python now + supported is Python 3.8. diff --git a/setup.cfg b/setup.cfg index a1a60d82d..5c62570ac 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,7 +6,7 @@ description_file = author = OpenStack Networking Project author_email = openstack-discuss@lists.openstack.org home_page = https://docs.openstack.org/python-neutronclient/latest/ -python_requires = >=3.6 +python_requires = >=3.8 classifier = Environment :: OpenStack Intended Audience :: Developers @@ -18,8 +18,6 @@ classifier = Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 From 7467c710f624aee80de8ef487e5b2c0e78143214 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Date: Wed, 13 Apr 2022 09:32:41 -0300 Subject: [PATCH 097/149] Add support to floating ip port forwarding To extend Horizon to allow users to create port forwarding rules for their floating ips, we need to extend this client to allow it, as Horizon uses this client. This patch is the one of a series of patches to implement floating ip port forwarding with port ranges. The specification is defined in: https://github.com/openstack/neutron-specs/blob/master/specs/wallaby/port-forwarding-port-ranges.rst Implements: blueprint floatingips-portforwarding-ranges Related-Bug: #1885921 Change-Id: I3f616dba5e2ebe301cf6ce4bed8c2e6e4da2da9b --- neutronclient/v2_0/client.py | 28 +++++++++++++++++++ ...-ip-port-forwardings-9dc838a5c5727eb7.yaml | 4 +++ 2 files changed, 32 insertions(+) create mode 100644 releasenotes/notes/add-support-to-floating-ip-port-forwardings-9dc838a5c5727eb7.yaml diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index 93a3af7a3..de0529182 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -515,6 +515,8 @@ class Client(ClientBase): router_path = "/routers/%s" floatingips_path = "/floatingips" floatingip_path = "/floatingips/%s" + port_forwardings_path = "/floatingips/%s/port_forwardings" + port_forwarding_path = "/floatingips/%s/port_forwardings/%s" security_groups_path = "/security-groups" security_group_path = "/security-groups/%s" security_group_rules_path = "/security-group-rules" @@ -1019,6 +1021,32 @@ def delete_floatingip(self, floatingip): """Deletes the specified floatingip.""" return self.delete(self.floatingip_path % (floatingip)) + def show_port_forwarding(self, floatingip, portforwarding): + """Fetches information of a certain portforwarding""" + return self.get(self.port_forwarding_path % (floatingip, + portforwarding)) + + def list_port_forwardings(self, floatingip, retrieve_all=True, **_params): + """Fetches a list of all portforwardings for a floatingip.""" + return self.list('port_forwardings', + self.port_forwardings_path % floatingip, retrieve_all, + **_params) + + def create_port_forwarding(self, floatingip, body=None): + """Creates a new portforwarding.""" + return self.post(self.port_forwardings_path % floatingip, body=body) + + def delete_port_forwarding(self, floatingip, portforwarding): + """Deletes the specified portforwarding.""" + return self.delete(self.port_forwarding_path % (floatingip, + portforwarding)) + + def update_port_forwarding(self, floatingip, portforwarding, body=None): + """Updates a portforwarding.""" + return self.put(self.port_forwarding_path % (floatingip, + portforwarding), + body=body) + def create_security_group(self, body=None): """Creates a new security group.""" return self.post(self.security_groups_path, body=body) diff --git a/releasenotes/notes/add-support-to-floating-ip-port-forwardings-9dc838a5c5727eb7.yaml b/releasenotes/notes/add-support-to-floating-ip-port-forwardings-9dc838a5c5727eb7.yaml new file mode 100644 index 000000000..3ba168ec9 --- /dev/null +++ b/releasenotes/notes/add-support-to-floating-ip-port-forwardings-9dc838a5c5727eb7.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Add support to floating ip port forwarding. \ No newline at end of file From f060429cfcb23b45236865fe1fc7855e3f795dbc Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Fri, 9 Sep 2022 11:48:19 +0000 Subject: [PATCH 098/149] Update master for stable/zed Add file to the reno documentation build to show release notes for stable/zed. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/zed. Sem-Ver: feature Change-Id: Ie6a0efba406cd26606168ce5b6dbc8ee7ae759ed --- releasenotes/source/index.rst | 1 + releasenotes/source/zed.rst | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/zed.rst diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index 2a7aeaa06..f1aa6a943 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + zed yoga xena wallaby diff --git a/releasenotes/source/zed.rst b/releasenotes/source/zed.rst new file mode 100644 index 000000000..9608c05e4 --- /dev/null +++ b/releasenotes/source/zed.rst @@ -0,0 +1,6 @@ +======================== +Zed Series Release Notes +======================== + +.. release-notes:: + :branch: stable/zed From ec84aff516d89817e1434da79579b7fdb03b27ce Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Fri, 9 Sep 2022 11:48:20 +0000 Subject: [PATCH 099/149] Switch to 2023.1 Python3 unit tests and generic template name This is an automatically generated patch to ensure unit testing is in place for all the of the tested runtimes for antelope. Also, updating the template name to generic one. See also the PTI in governance [1]. [1]: https://governance.openstack.org/tc/reference/project-testing-interface.html Change-Id: I026505ff0d277fd4f15329ed26a5cecf1d573f68 --- .zuul.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zuul.yaml b/.zuul.yaml index e7645b60d..7e23f93e8 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -1,7 +1,7 @@ - project: templates: - openstack-cover-jobs - - openstack-python3-zed-jobs + - openstack-python3-jobs - publish-openstack-docs-pti - check-requirements - lib-forward-testing-python3 From f67af3d9be8cb289a78ccc1dceb324abc4767fde Mon Sep 17 00:00:00 2001 From: elajkat Date: Fri, 21 Oct 2022 13:58:12 +0200 Subject: [PATCH 100/149] Add warning and reno for SDK On the 2023.1 (Antelope) PTG we discussed the status of the python binding (SDK) code in python-neutronclient and decided to not allow new features to this repo (see [1]), and make users to use openstacksdk. Let's add a warning log message and a releasenote to make it visible. [1]: https://etherpad.opendev.org/p/neutron-antelope-ptg#L163 Change-Id: I03317179bd0d30a69b91eef6e451b8e40eb28191 --- neutronclient/v2_0/client.py | 3 +++ .../notes/no-new-binding-code-b03c9abbcaf2839e.yaml | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 releasenotes/notes/no-new-binding-code-b03c9abbcaf2839e.yaml diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index de0529182..e670e3f5c 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -250,6 +250,9 @@ class ClientBase(object): def __init__(self, **kwargs): """Initialize a new client for the Neutron v2.0 API.""" super(ClientBase, self).__init__() + _logger.warning("The python binding code in neutronclient will be " + "deprecated in favor of OpenstackSDK, please use " + "that!") self.retries = kwargs.pop('retries', 0) self.raise_errors = kwargs.pop('raise_errors', True) self.httpclient = client.construct_http_client(**kwargs) diff --git a/releasenotes/notes/no-new-binding-code-b03c9abbcaf2839e.yaml b/releasenotes/notes/no-new-binding-code-b03c9abbcaf2839e.yaml new file mode 100644 index 000000000..bc41e7438 --- /dev/null +++ b/releasenotes/notes/no-new-binding-code-b03c9abbcaf2839e.yaml @@ -0,0 +1,7 @@ +--- +prelude: > + Openstack community decided to use one SDK for its services, that is + in ``openstacksdk`` repository. To avoid duplication, sooner or later the + python binding code in ``python-neutronclient`` will be deprecated, and + ``Neutron`` team decided on the ``2023.1 (Antelope)`` PTG to not allow + new features\' bindings implemented here. From 776e360e351c4b0c754fec5ad6308323adb44437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elvira=20Garc=C3=ADa?= Date: Fri, 25 Nov 2022 15:05:50 +0100 Subject: [PATCH 101/149] Fix help sentence in network log create --enable As the documentation states [1], the default in network log objects is to be enabled, not disabled. [1] https://docs.openstack.org/neutron/latest/admin/config-logging.html Change-Id: I13e9d1132fc38104e6e85d9c8442bc7506adc2fd --- neutronclient/osc/v2/logging/network_log.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neutronclient/osc/v2/logging/network_log.py b/neutronclient/osc/v2/logging/network_log.py index df48fc1e5..b3b8204c3 100644 --- a/neutronclient/osc/v2/logging/network_log.py +++ b/neutronclient/osc/v2/logging/network_log.py @@ -58,11 +58,11 @@ def _get_common_parser(parser): enable_group.add_argument( '--enable', action='store_true', - help=_('Enable this log (default is disabled)')) + help=_('Enable this log')) enable_group.add_argument( '--disable', action='store_true', - help=_('Disable this log')) + help=_('Disable this log (default is enabled)')) return parser From 33f1c89a840262ad378bf82fde5b42a07ad271db Mon Sep 17 00:00:00 2001 From: elajkat Date: Fri, 13 Jan 2023 16:22:06 +0100 Subject: [PATCH 102/149] Tox4: add allowlist_externals where necessary With tox4 allowlist_externals is more strictly checked, so fix it where necessary and fix pylint version. Depends-On: https://review.opendev.org/c/zuul/zuul-jobs/+/866943 Related-Bug: #1999558 Change-Id: Id115a436b95b3ede5a1f3102b4bb9e3ade75c970 --- doc/requirements.txt | 1 + tox.ini | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index 76ce5cd3f..718a2395a 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -4,3 +4,4 @@ openstackdocstheme>=2.2.0 # Apache-2.0 reno>=3.1.0 # Apache-2.0 sphinx>=2.0.0,!=2.1.0 # BSD +cliff>=3.4.0 # Apache-2.0 diff --git a/tox.ini b/tox.ini index bd421721e..06f5829f6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] envlist = py39,pep8 minversion = 3.18.0 -skipsdist = True +skipsdist = False ignore_basepython_conflict = True [testenv] @@ -12,18 +12,17 @@ setenv = VIRTUAL_ENV={envdir} LC_ALL=C PYTHONWARNINGS=default::DeprecationWarning usedevelop = True -install_command = pip install {opts} {packages} deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt # Delete bytecodes from normal directories before running tests. # Note that bytecodes in dot directories will not be deleted # to keep bytecodes of python modules installed into virtualenvs. -commands = sh -c "find . -type d -name '.?*' -prune -o \ +commands = bash -c "find . -type d -name '.?*' -prune -o \ \( -type d -name '__pycache__' -o -type f -name '*.py[co]' \) \ -print0 | xargs -0 rm -rf" stestr run {posargs} -allowlist_externals = sh +allowlist_externals = bash [testenv:pep8] commands = From 68cbf56f9ccf9ecd4a53df5c684c2036d78a8612 Mon Sep 17 00:00:00 2001 From: elajkat Date: Fri, 6 Jan 2023 13:10:16 +0100 Subject: [PATCH 103/149] Move network trunk commands from python-neutronclient The depends-on patch adds trunk commands to OSC, as we can long consider trunk operations as core Networking operations. Change-Id: Ie557a5d541cf117d20f3f2b548620a74dbadb383 Depends-On: https://review.opendev.org/c/openstack/python-openstackclient/+/869447 Related-Bug: #1999774 --- doc/source/cli/osc/v2/network-trunk.rst | 16 - neutronclient/osc/v2/trunk/__init__.py | 0 neutronclient/osc/v2/trunk/network_trunk.py | 393 --------- .../tests/unit/osc/v2/trunk/__init__.py | 0 .../tests/unit/osc/v2/trunk/fakes.py | 87 -- .../unit/osc/v2/trunk/test_network_trunk.py | 769 ------------------ setup.cfg | 7 - 7 files changed, 1272 deletions(-) delete mode 100644 doc/source/cli/osc/v2/network-trunk.rst delete mode 100644 neutronclient/osc/v2/trunk/__init__.py delete mode 100644 neutronclient/osc/v2/trunk/network_trunk.py delete mode 100644 neutronclient/tests/unit/osc/v2/trunk/__init__.py delete mode 100644 neutronclient/tests/unit/osc/v2/trunk/fakes.py delete mode 100644 neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py diff --git a/doc/source/cli/osc/v2/network-trunk.rst b/doc/source/cli/osc/v2/network-trunk.rst deleted file mode 100644 index 22144a4ee..000000000 --- a/doc/source/cli/osc/v2/network-trunk.rst +++ /dev/null @@ -1,16 +0,0 @@ -============= -network trunk -============= - -A **network trunk** is a container to group logical ports from different -networks and provide a single trunked vNIC for servers. It consists of -one parent port which is a regular VIF and multiple subports which allow -the server to connect to more networks. - -Network v2 - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: network subport list - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: network trunk * diff --git a/neutronclient/osc/v2/trunk/__init__.py b/neutronclient/osc/v2/trunk/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/osc/v2/trunk/network_trunk.py b/neutronclient/osc/v2/trunk/network_trunk.py deleted file mode 100644 index 26cb52be9..000000000 --- a/neutronclient/osc/v2/trunk/network_trunk.py +++ /dev/null @@ -1,393 +0,0 @@ -# Copyright 2016 ZTE Corporation. -# All Rights Reserved -# -# 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 trunk and subports action implementations""" -import logging - -from osc_lib.cli import format_columns -from osc_lib.cli import parseractions -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils as osc_utils - -from neutronclient._i18n import _ -from neutronclient.osc import utils as nc_osc_utils -from neutronclient.osc.v2 import utils as v2_utils - -LOG = logging.getLogger(__name__) - -TRUNK = 'trunk' -TRUNKS = 'trunks' -SUB_PORTS = 'sub_ports' - - -class CreateNetworkTrunk(command.ShowOne): - """Create a network trunk for a given project""" - - def get_parser(self, prog_name): - parser = super(CreateNetworkTrunk, self).get_parser(prog_name) - parser.add_argument( - 'name', - metavar='', - help=_("Name of the trunk to create") - ) - parser.add_argument( - '--description', - metavar='', - help=_("A description of the trunk") - ) - parser.add_argument( - '--parent-port', - metavar='', - required=True, - help=_("Parent port belonging to this trunk (name or ID)") - ) - parser.add_argument( - '--subport', - metavar='', - action=parseractions.MultiKeyValueAction, dest='add_subports', - optional_keys=['segmentation-id', 'segmentation-type'], - required_keys=['port'], - help=_("Subport to add. Subport is of form " - "\'port=,segmentation-type=,segmentation-ID=\' " - "(--subport) option can be repeated") - ) - admin_group = parser.add_mutually_exclusive_group() - admin_group.add_argument( - '--enable', - action='store_true', - default=True, - help=_("Enable trunk (default)") - ) - admin_group.add_argument( - '--disable', - action='store_true', - help=_("Disable trunk") - ) - nc_osc_utils.add_project_owner_option_to_parser(parser) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - attrs = _get_attrs_for_trunk(self.app.client_manager, - parsed_args) - body = {TRUNK: attrs} - obj = client.create_trunk(body) - columns = _get_columns(obj[TRUNK]) - data = osc_utils.get_dict_properties(obj[TRUNK], columns, - formatters=_formatters) - return columns, data - - -class DeleteNetworkTrunk(command.Command): - """Delete a given network trunk""" - - def get_parser(self, prog_name): - parser = super(DeleteNetworkTrunk, self).get_parser(prog_name) - parser.add_argument( - 'trunk', - metavar="", - nargs="+", - help=_("Trunk(s) to delete (name or ID)") - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - result = 0 - for trunk in parsed_args.trunk: - try: - trunk_id = _get_id(client, trunk, TRUNK) - client.delete_trunk(trunk_id) - except Exception as e: - result += 1 - LOG.error(_("Failed to delete trunk with name " - "or ID '%(trunk)s': %(e)s"), - {'trunk': trunk, 'e': e}) - if result > 0: - total = len(parsed_args.trunk) - msg = (_("%(result)s of %(total)s trunks failed " - "to delete.") % {'result': result, 'total': total}) - raise exceptions.CommandError(msg) - - -class ListNetworkTrunk(command.Lister): - """List all network trunks""" - - def get_parser(self, prog_name): - parser = super(ListNetworkTrunk, self).get_parser(prog_name) - parser.add_argument( - '--long', - action='store_true', - default=False, - help=_("List additional fields in output") - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - data = client.list_trunks() - headers = ( - 'ID', - 'Name', - 'Parent Port', - 'Description' - ) - columns = ( - 'id', - 'name', - 'port_id', - 'description' - ) - if parsed_args.long: - headers += ( - 'Status', - 'State', - 'Created At', - 'Updated At', - ) - columns += ( - 'status', - 'admin_state_up', - 'created_at', - 'updated_at' - ) - return (headers, - (osc_utils.get_dict_properties( - s, columns, - formatters=_formatters, - ) for s in data[TRUNKS])) - - -class SetNetworkTrunk(command.Command): - """Set network trunk properties""" - - def get_parser(self, prog_name): - parser = super(SetNetworkTrunk, self).get_parser(prog_name) - parser.add_argument( - 'trunk', - metavar="", - help=_("Trunk to modify (name or ID)") - ) - parser.add_argument( - '--name', - metavar="", - help=_("Set trunk name") - ) - parser.add_argument( - '--description', - metavar='', - help=_("A description of the trunk") - ) - parser.add_argument( - '--subport', - metavar='', - action=parseractions.MultiKeyValueAction, dest='set_subports', - optional_keys=['segmentation-id', 'segmentation-type'], - required_keys=['port'], - help=_("Subport to add. Subport is of form " - "\'port=,segmentation-type=,segmentation-ID=\'" - "(--subport) option can be repeated") - ) - admin_group = parser.add_mutually_exclusive_group() - admin_group.add_argument( - '--enable', - action='store_true', - help=_("Enable trunk") - ) - admin_group.add_argument( - '--disable', - action='store_true', - help=_("Disable trunk") - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - trunk_id = _get_id(client, parsed_args.trunk, TRUNK) - attrs = _get_attrs_for_trunk(self.app.client_manager, parsed_args) - body = {TRUNK: attrs} - try: - client.update_trunk(trunk_id, body) - except Exception as e: - msg = (_("Failed to set trunk '%(t)s': %(e)s") - % {'t': parsed_args.trunk, 'e': e}) - raise exceptions.CommandError(msg) - if parsed_args.set_subports: - subport_attrs = _get_attrs_for_subports(self.app.client_manager, - parsed_args) - try: - client.trunk_add_subports(trunk_id, subport_attrs) - except Exception as e: - msg = (_("Failed to add subports to trunk '%(t)s': %(e)s") - % {'t': parsed_args.trunk, 'e': e}) - raise exceptions.CommandError(msg) - - -class ShowNetworkTrunk(command.ShowOne): - """Show information of a given network trunk""" - def get_parser(self, prog_name): - parser = super(ShowNetworkTrunk, self).get_parser(prog_name) - parser.add_argument( - 'trunk', - metavar="", - help=_("Trunk to display (name or ID)") - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - trunk_id = _get_id(client, parsed_args.trunk, TRUNK) - obj = client.show_trunk(trunk_id) - columns = _get_columns(obj[TRUNK]) - data = osc_utils.get_dict_properties(obj[TRUNK], columns, - formatters=_formatters) - return columns, data - - -class ListNetworkSubport(command.Lister): - """List all subports for a given network trunk""" - - def get_parser(self, prog_name): - parser = super(ListNetworkSubport, self).get_parser(prog_name) - parser.add_argument( - '--trunk', - required=True, - metavar="", - help=_("List subports belonging to this trunk (name or ID)") - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - trunk_id = _get_id(client, parsed_args.trunk, TRUNK) - data = client.trunk_get_subports(trunk_id) - headers = ('Port', 'Segmentation Type', 'Segmentation ID') - columns = ('port_id', 'segmentation_type', 'segmentation_id') - return (headers, - (osc_utils.get_dict_properties( - s, columns, - ) for s in data[SUB_PORTS])) - - -class UnsetNetworkTrunk(command.Command): - """Unset subports from a given network trunk""" - - def get_parser(self, prog_name): - parser = super(UnsetNetworkTrunk, self).get_parser(prog_name) - parser.add_argument( - 'trunk', - metavar="", - help=_("Unset subports from this trunk (name or ID)") - ) - parser.add_argument( - '--subport', - metavar="", - required=True, - action='append', dest='unset_subports', - help=_("Subport to delete (name or ID of the port) " - "(--subport) option can be repeated") - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - attrs = _get_attrs_for_subports(self.app.client_manager, parsed_args) - trunk_id = _get_id(client, parsed_args.trunk, TRUNK) - client.trunk_remove_subports(trunk_id, attrs) - - -_formatters = { - 'admin_state_up': v2_utils.AdminStateColumn, - 'sub_ports': format_columns.ListDictColumn, -} - - -def _get_columns(item): - return tuple(sorted(list(item.keys()))) - - -def _get_attrs_for_trunk(client_manager, parsed_args): - attrs = {} - if parsed_args.name is not None: - attrs['name'] = str(parsed_args.name) - if parsed_args.description is not None: - attrs['description'] = str(parsed_args.description) - if parsed_args.enable: - attrs['admin_state_up'] = True - if parsed_args.disable: - attrs['admin_state_up'] = False - if 'parent_port' in parsed_args and parsed_args.parent_port is not None: - port_id = _get_id(client_manager.neutronclient, - parsed_args.parent_port, 'port') - attrs['port_id'] = port_id - if 'add_subports' in parsed_args and parsed_args.add_subports is not None: - attrs[SUB_PORTS] = _format_subports(client_manager, - parsed_args.add_subports) - - # "trunk set" command doesn't support setting project. - if 'project' in parsed_args and parsed_args.project is not None: - identity_client = client_manager.identity - project_id = nc_osc_utils.find_project( - identity_client, - parsed_args.project, - parsed_args.project_domain, - ).id - attrs['tenant_id'] = project_id - - return attrs - - -def _format_subports(client_manager, subports): - attrs = [] - for subport in subports: - subport_attrs = {} - if subport.get('port'): - port_id = _get_id(client_manager.neutronclient, - subport['port'], 'port') - subport_attrs['port_id'] = port_id - if subport.get('segmentation-id'): - try: - subport_attrs['segmentation_id'] = int( - subport['segmentation-id']) - except ValueError: - msg = (_("Segmentation-id '%s' is not an integer") % - subport['segmentation-id']) - raise exceptions.CommandError(msg) - if subport.get('segmentation-type'): - subport_attrs['segmentation_type'] = subport['segmentation-type'] - attrs.append(subport_attrs) - return attrs - - -def _get_attrs_for_subports(client_manager, parsed_args): - attrs = {} - if 'set_subports' in parsed_args and parsed_args.set_subports is not None: - attrs[SUB_PORTS] = _format_subports(client_manager, - parsed_args.set_subports) - if ('unset_subports' in parsed_args and - parsed_args.unset_subports is not None): - subports_list = [] - for subport in parsed_args.unset_subports: - port_id = _get_id(client_manager.neutronclient, - subport, 'port') - subports_list.append({'port_id': port_id}) - attrs[SUB_PORTS] = subports_list - return attrs - - -def _get_id(client, id_or_name, resource): - return client.find_resource(resource, str(id_or_name))['id'] diff --git a/neutronclient/tests/unit/osc/v2/trunk/__init__.py b/neutronclient/tests/unit/osc/v2/trunk/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/osc/v2/trunk/fakes.py b/neutronclient/tests/unit/osc/v2/trunk/fakes.py deleted file mode 100644 index a52aa3097..000000000 --- a/neutronclient/tests/unit/osc/v2/trunk/fakes.py +++ /dev/null @@ -1,87 +0,0 @@ -# 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 copy -from unittest import mock - -from oslo_utils import uuidutils - - -class FakeTrunk(object): - """Fake one or more trunks.""" - @staticmethod - def create_one_trunk(attrs=None): - """Create a fake trunk. - - :param Dictionary attrs: - A dictionary with all attributes - :return: - A Dictionary with id, name, description, admin_state_up, port_id, - sub_ports, status and project_id - """ - attrs = attrs or {} - - # Set default attributes. - trunk_attrs = { - 'id': 'trunk-id-' + uuidutils.generate_uuid(dashed=False), - 'name': 'trunk-name-' + uuidutils.generate_uuid(dashed=False), - 'description': '', - 'port_id': 'port-' + uuidutils.generate_uuid(dashed=False), - 'admin_state_up': True, - 'project_id': 'project-id-' + - uuidutils.generate_uuid(dashed=False), - 'status': 'ACTIVE', - 'sub_ports': [{'port_id': 'subport-' + - uuidutils.generate_uuid(dashed=False), - 'segmentation_type': 'vlan', - 'segmentation_id': 100}], - } - - # Overwrite default attributes. - trunk_attrs.update(attrs) - return copy.deepcopy(trunk_attrs) - - @staticmethod - def create_trunks(attrs=None, count=2): - """Create multiple fake trunks. - - :param Dictionary attrs: - A dictionary with all attributes - :param int count: - The number of routers to fake - :return: - A list of dictionaries faking the trunks - """ - trunks = [] - for i in range(0, count): - trunks.append(FakeTrunk.create_one_trunk(attrs)) - - return trunks - - @staticmethod - def get_trunks(trunks=None, count=2): - """Get an iterable Mock object with a list of faked trunks. - - If trunks list is provided, then initialize the Mock object with the - list. Otherwise create one. - - :param List trunks: - A list of FakeResource objects faking trunks - :param int count: - The number of trunks to fake - :return: - An iterable Mock object with side_effect set to a list of faked - trunks - """ - if trunks is None: - trunks = FakeTrunk.create_trunks(count) - return mock.Mock(side_effect=trunks) diff --git a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py b/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py deleted file mode 100644 index 1e16c1fa9..000000000 --- a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py +++ /dev/null @@ -1,769 +0,0 @@ -# Copyright 2016 ZTE Corporation. -# All Rights Reserved -# -# 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 argparse -import copy -from unittest import mock -from unittest.mock import call - -from osc_lib.cli import format_columns -from osc_lib import exceptions -from osc_lib.tests import utils as tests_utils -import testtools - -from neutronclient.osc.v2.trunk import network_trunk as trunk -from neutronclient.osc.v2 import utils as v2_utils -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes -from neutronclient.tests.unit.osc.v2.trunk import fakes - - -def _get_id(client, id_or_name, resource): - return id_or_name - - -class TestCreateNetworkTrunk(test_fakes.TestNeutronClientOSCV2): - # The new trunk created - _trunk = fakes.FakeTrunk.create_one_trunk() - - columns = ( - 'admin_state_up', - 'description', - 'id', - 'name', - 'port_id', - 'project_id', - 'status', - 'sub_ports', - ) - - def get_data(self): - return ( - v2_utils.AdminStateColumn(self._trunk['admin_state_up']), - self._trunk['description'], - self._trunk['id'], - self._trunk['name'], - self._trunk['port_id'], - self._trunk['project_id'], - self._trunk['status'], - format_columns.ListDictColumn(self._trunk['sub_ports']), - ) - - def setUp(self): - super(TestCreateNetworkTrunk, self).setUp() - mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id', - new=_get_id).start() - self.neutronclient.create_trunk = mock.Mock( - return_value={trunk.TRUNK: self._trunk}) - self.data = self.get_data() - - # Get the command object to test - self.cmd = trunk.CreateNetworkTrunk(self.app, self.namespace) - - def test_create_no_options(self): - arglist = [] - verifylist = [] - - self.assertRaises(tests_utils.ParserException, self.check_parser, - self.cmd, arglist, verifylist) - - def test_create_default_options(self): - arglist = [ - "--parent-port", self._trunk['port_id'], - self._trunk['name'], - ] - verifylist = [ - ('parent_port', self._trunk['port_id']), - ('name', self._trunk['name']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - columns, data = (self.cmd.take_action(parsed_args)) - - self.neutronclient.create_trunk.assert_called_once_with({ - trunk.TRUNK: {'name': self._trunk['name'], - 'admin_state_up': self._trunk['admin_state_up'], - 'port_id': self._trunk['port_id']} - }) - self.assertEqual(self.columns, columns) - self.assertItemEqual(self.data, data) - - def test_create_full_options(self): - self._trunk['description'] = 'foo description' - self.data = self.get_data() - subport = self._trunk['sub_ports'][0] - arglist = [ - "--disable", - "--description", self._trunk['description'], - "--parent-port", self._trunk['port_id'], - "--subport", 'port=%(port)s,segmentation-type=%(seg_type)s,' - 'segmentation-id=%(seg_id)s' % { - 'seg_id': subport['segmentation_id'], - 'seg_type': subport['segmentation_type'], - 'port': subport['port_id']}, - self._trunk['name'], - ] - verifylist = [ - ('name', self._trunk['name']), - ('description', self._trunk['description']), - ('parent_port', self._trunk['port_id']), - ('add_subports', [{ - 'port': subport['port_id'], - 'segmentation-id': str(subport['segmentation_id']), - 'segmentation-type': subport['segmentation_type']}]), - ('disable', True), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - columns, data = (self.cmd.take_action(parsed_args)) - - self.neutronclient.create_trunk.assert_called_once_with({ - trunk.TRUNK: {'name': self._trunk['name'], - 'description': self._trunk['description'], - 'admin_state_up': False, - 'sub_ports': [subport], - 'port_id': self._trunk['port_id']} - }) - self.assertEqual(self.columns, columns) - self.assertItemEqual(self.data, data) - - def test_create_trunk_with_subport_invalid_segmentation_id_fail(self): - subport = self._trunk['sub_ports'][0] - arglist = [ - "--parent-port", self._trunk['port_id'], - "--subport", "port=%(port)s,segmentation-type=%(seg_type)s," - "segmentation-id=boom" % { - 'seg_type': subport['segmentation_type'], - 'port': subport['port_id']}, - self._trunk['name'], - ] - verifylist = [ - ('name', self._trunk['name']), - ('parent_port', self._trunk['port_id']), - ('add_subports', [{ - 'port': subport['port_id'], - 'segmentation-id': 'boom', - 'segmentation-type': subport['segmentation_type']}]), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with testtools.ExpectedException(exceptions.CommandError) as e: - self.cmd.take_action(parsed_args) - self.assertEqual("Segmentation-id 'boom' is not an integer", - str(e)) - - def test_create_network_trunk_subports_without_optional_keys(self): - subport = copy.copy(self._trunk['sub_ports'][0]) - # Pop out the segmentation-id and segmentation-type - subport.pop('segmentation_type') - subport.pop('segmentation_id') - arglist = [ - '--parent-port', self._trunk['port_id'], - '--subport', 'port=%(port)s' % {'port': subport['port_id']}, - self._trunk['name'], - ] - verifylist = [ - ('name', self._trunk['name']), - ('parent_port', self._trunk['port_id']), - ('add_subports', [{ - 'port': subport['port_id']}]), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - columns, data = (self.cmd.take_action(parsed_args)) - - self.neutronclient.create_trunk.assert_called_once_with({ - trunk.TRUNK: {'name': self._trunk['name'], - 'admin_state_up': True, - 'sub_ports': [subport], - 'port_id': self._trunk['port_id']} - }) - self.assertEqual(self.columns, columns) - self.assertItemEqual(self.data, data) - - def test_create_network_trunk_subports_without_required_key_fail(self): - subport = self._trunk['sub_ports'][0] - arglist = [ - '--parent-port', self._trunk['port_id'], - '--subport', 'segmentation-type=%(seg_type)s,' - 'segmentation-id=%(seg_id)s' % { - 'seg_id': subport['segmentation_id'], - 'seg_type': subport['segmentation_type']}, - self._trunk['name'], - ] - verifylist = [ - ('name', self._trunk['name']), - ('parent_port', self._trunk['port_id']), - ('add_subports', [{ - 'segmentation-id': str(subport['segmentation_id']), - 'segmentation-type': subport['segmentation_type']}]), - ] - - with testtools.ExpectedException(argparse.ArgumentTypeError): - self.check_parser(self.cmd, arglist, verifylist) - - -class TestDeleteNetworkTrunk(test_fakes.TestNeutronClientOSCV2): - # The trunk to be deleted. - _trunks = fakes.FakeTrunk.create_trunks(count=2) - - def setUp(self): - super(TestDeleteNetworkTrunk, self).setUp() - - mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id', - new=_get_id).start() - self.neutronclient.delete_trunk = mock.Mock(return_value=None) - - # Get the command object to test - self.cmd = trunk.DeleteNetworkTrunk(self.app, self.namespace) - - def test_delete_trunk(self): - arglist = [ - self._trunks[0]['name'], - ] - verifylist = [ - ('trunk', [self._trunks[0]['name']]), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - self.neutronclient.delete_trunk.assert_called_once_with( - self._trunks[0]['name']) - self.assertIsNone(result) - - def test_delete_trunk_multiple(self): - arglist = [] - verifylist = [] - - for t in self._trunks: - arglist.append(t['name']) - verifylist = [ - ('trunk', arglist), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - calls = [] - for t in self._trunks: - calls.append(call(t['name'])) - self.neutronclient.delete_trunk.assert_has_calls(calls) - self.assertIsNone(result) - - def test_delete_trunk_multiple_with_exception(self): - arglist = [ - self._trunks[0]['name'], - 'unexist_trunk', - ] - verifylist = [ - ('trunk', - [self._trunks[0]['name'], 'unexist_trunk']), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - get_mock_result = [self._trunks[0], exceptions.CommandError] - trunk._get_id = ( - mock.Mock(side_effect=get_mock_result) - ) - with testtools.ExpectedException(exceptions.CommandError) as e: - self.cmd.take_action(parsed_args) - self.assertEqual('1 of 2 trunks failed to delete.', str(e)) - self.neutronclient.delete_trunk.assert_called_once_with( - self._trunks[0] - ) - - -class TestShowNetworkTrunk(test_fakes.TestNeutronClientOSCV2): - - # The trunk to set. - _trunk = fakes.FakeTrunk.create_one_trunk() - - columns = ( - 'admin_state_up', - 'description', - 'id', - 'name', - 'port_id', - 'project_id', - 'status', - 'sub_ports', - ) - data = ( - v2_utils.AdminStateColumn(_trunk['admin_state_up']), - _trunk['description'], - _trunk['id'], - _trunk['name'], - _trunk['port_id'], - _trunk['project_id'], - _trunk['status'], - format_columns.ListDictColumn(_trunk['sub_ports']), - ) - - def setUp(self): - super(TestShowNetworkTrunk, self).setUp() - - mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id', - new=_get_id).start() - self.neutronclient.show_trunk = mock.Mock( - return_value={trunk.TRUNK: self._trunk}) - - # Get the command object to test - self.cmd = trunk.ShowNetworkTrunk(self.app, self.namespace) - - def test_show_no_options(self): - arglist = [] - verifylist = [] - - self.assertRaises(tests_utils.ParserException, self.check_parser, - self.cmd, arglist, verifylist) - - def test_show_all_options(self): - arglist = [ - self._trunk['id'], - ] - verifylist = [ - ('trunk', self._trunk['id']), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - columns, data = self.cmd.take_action(parsed_args) - - self.neutronclient.show_trunk.assert_called_once_with( - self._trunk['id']) - self.assertEqual(self.columns, columns) - self.assertItemEqual(self.data, data) - - -class TestListNetworkTrunk(test_fakes.TestNeutronClientOSCV2): - # Create trunks to be listed. - _trunks = fakes.FakeTrunk.create_trunks( - {'created_at': '2001-01-01 00:00:00', - 'updated_at': '2001-01-01 00:00:00'}, count=3) - - columns = ( - 'ID', - 'Name', - 'Parent Port', - 'Description' - ) - columns_long = columns + ( - 'Status', - 'State', - 'Created At', - 'Updated At' - ) - data = [] - for t in _trunks: - data.append(( - t['id'], - t['name'], - t['port_id'], - t['description'] - )) - data_long = [] - for t in _trunks: - data_long.append(( - t['id'], - t['name'], - t['port_id'], - t['description'], - t['status'], - v2_utils.AdminStateColumn(t['admin_state_up']), - '2001-01-01 00:00:00', - '2001-01-01 00:00:00', - )) - - def setUp(self): - super(TestListNetworkTrunk, self).setUp() - mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id', - new=_get_id).start() - self.neutronclient.list_trunks = mock.Mock( - return_value={trunk.TRUNKS: self._trunks}) - - # Get the command object to test - self.cmd = trunk.ListNetworkTrunk(self.app, self.namespace) - - def test_trunk_list_no_option(self): - arglist = [] - verifylist = [] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - columns, data = self.cmd.take_action(parsed_args) - - self.neutronclient.list_trunks.assert_called_once_with() - self.assertEqual(self.columns, columns) - self.assertListItemEqual(self.data, list(data)) - - def test_trunk_list_long(self): - arglist = [ - '--long', - ] - verifylist = [ - ('long', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - columns, data = self.cmd.take_action(parsed_args) - - self.neutronclient.list_trunks.assert_called_once_with() - self.assertEqual(self.columns_long, columns) - self.assertListItemEqual(self.data_long, list(data)) - - -class TestSetNetworkTrunk(test_fakes.TestNeutronClientOSCV2): - # Create trunks to be listed. - _trunk = fakes.FakeTrunk.create_one_trunk() - - columns = ( - 'admin_state_up', - 'id', - 'name', - 'description', - 'port_id', - 'project_id', - 'status', - 'sub_ports', - ) - data = ( - v2_utils.AdminStateColumn(_trunk['admin_state_up']), - _trunk['id'], - _trunk['name'], - _trunk['description'], - _trunk['port_id'], - _trunk['project_id'], - _trunk['status'], - format_columns.ListDictColumn(_trunk['sub_ports']), - ) - - def setUp(self): - super(TestSetNetworkTrunk, self).setUp() - mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id', - new=_get_id).start() - self.neutronclient.update_trunk = mock.Mock( - return_value={trunk.TRUNK: self._trunk}) - self.neutronclient.trunk_add_subports = mock.Mock( - return_value=self._trunk) - - # Get the command object to test - self.cmd = trunk.SetNetworkTrunk(self.app, self.namespace) - - def _test_set_network_trunk_attr(self, attr, value): - arglist = [ - '--%s' % attr, value, - self._trunk[attr], - ] - verifylist = [ - (attr, value), - ('trunk', self._trunk[attr]), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - attrs = { - attr: value, - } - self.neutronclient.update_trunk.assert_called_once_with( - self._trunk[attr], {trunk.TRUNK: attrs}) - self.assertIsNone(result) - - def test_set_network_trunk_name(self): - self._test_set_network_trunk_attr('name', 'trunky') - - def test_test_set_network_trunk_description(self): - self._test_set_network_trunk_attr('description', 'description') - - def test_set_network_trunk_admin_state_up_disable(self): - arglist = [ - '--disable', - self._trunk['name'], - ] - verifylist = [ - ('disable', True), - ('trunk', self._trunk['name']), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - attrs = { - 'admin_state_up': False, - } - self.neutronclient.update_trunk.assert_called_once_with( - self._trunk['name'], {trunk.TRUNK: attrs}) - self.assertIsNone(result) - - def test_set_network_trunk_admin_state_up_enable(self): - arglist = [ - '--enable', - self._trunk['name'], - ] - verifylist = [ - ('enable', True), - ('trunk', self._trunk['name']), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - attrs = { - 'admin_state_up': True, - } - self.neutronclient.update_trunk.assert_called_once_with( - self._trunk['name'], {trunk.TRUNK: attrs}) - self.assertIsNone(result) - - def test_set_network_trunk_nothing(self): - arglist = [self._trunk['name'], ] - verifylist = [('trunk', self._trunk['name']), ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - attrs = {} - self.neutronclient.update_trunk.assert_called_once_with( - self._trunk['name'], {trunk.TRUNK: attrs}) - self.assertIsNone(result) - - def test_set_network_trunk_subports(self): - subport = self._trunk['sub_ports'][0] - arglist = [ - '--subport', 'port=%(port)s,segmentation-type=%(seg_type)s,' - 'segmentation-id=%(seg_id)s' % { - 'seg_id': subport['segmentation_id'], - 'seg_type': subport['segmentation_type'], - 'port': subport['port_id']}, - self._trunk['name'], - ] - verifylist = [ - ('trunk', self._trunk['name']), - ('set_subports', [{ - 'port': subport['port_id'], - 'segmentation-id': str(subport['segmentation_id']), - 'segmentation-type': subport['segmentation_type']}]), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.neutronclient.trunk_add_subports.assert_called_once_with( - self._trunk['name'], {'sub_ports': [subport]} - ) - self.assertIsNone(result) - - def test_set_network_trunk_subports_without_optional_keys(self): - subport = copy.copy(self._trunk['sub_ports'][0]) - # Pop out the segmentation-id and segmentation-type - subport.pop('segmentation_type') - subport.pop('segmentation_id') - arglist = [ - '--subport', 'port=%(port)s' % {'port': subport['port_id']}, - self._trunk['name'], - ] - verifylist = [ - ('trunk', self._trunk['name']), - ('set_subports', [{ - 'port': subport['port_id']}]), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.neutronclient.trunk_add_subports.assert_called_once_with( - self._trunk['name'], {'sub_ports': [subport]} - ) - self.assertIsNone(result) - - def test_set_network_trunk_subports_without_required_key_fail(self): - subport = self._trunk['sub_ports'][0] - arglist = [ - '--subport', 'segmentation-type=%(seg_type)s,' - 'segmentation-id=%(seg_id)s' % { - 'seg_id': subport['segmentation_id'], - 'seg_type': subport['segmentation_type']}, - self._trunk['name'], - ] - verifylist = [ - ('trunk', self._trunk['name']), - ('set_subports', [{ - 'segmentation-id': str(subport['segmentation_id']), - 'segmentation-type': subport['segmentation_type']}]), - ] - - with testtools.ExpectedException(argparse.ArgumentTypeError): - self.check_parser(self.cmd, arglist, verifylist) - - self.neutronclient.trunk_add_subports.assert_not_called() - - def test_set_trunk_attrs_with_exception(self): - arglist = [ - '--name', 'reallylongname', - self._trunk['name'], - ] - verifylist = [ - ('trunk', self._trunk['name']), - ('name', 'reallylongname'), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.neutronclient.update_trunk = ( - mock.Mock(side_effect=exceptions.CommandError) - ) - with testtools.ExpectedException(exceptions.CommandError) as e: - self.cmd.take_action(parsed_args) - self.assertEqual( - "Failed to set trunk '%s': " % self._trunk['name'], - str(e)) - attrs = {'name': 'reallylongname'} - self.neutronclient.update_trunk.assert_called_once_with( - self._trunk['name'], {trunk.TRUNK: attrs}) - self.neutronclient.trunk_add_subports.assert_not_called() - - def test_set_trunk_add_subport_with_exception(self): - arglist = [ - '--subport', 'port=invalid_subport', - self._trunk['name'], - ] - verifylist = [ - ('trunk', self._trunk['name']), - ('set_subports', [{'port': 'invalid_subport'}]), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.neutronclient.trunk_add_subports = ( - mock.Mock(side_effect=exceptions.CommandError) - ) - with testtools.ExpectedException(exceptions.CommandError) as e: - self.cmd.take_action(parsed_args) - self.assertEqual( - "Failed to add subports to trunk '%s': " % self._trunk['name'], - str(e)) - self.neutronclient.update_trunk.assert_called_once_with( - self._trunk['name'], {trunk.TRUNK: {}}) - self.neutronclient.trunk_add_subports.assert_called_once_with( - self._trunk['name'], - {'sub_ports': [{'port_id': 'invalid_subport'}]} - ) - - -class TestListNetworkSubport(test_fakes.TestNeutronClientOSCV2): - - _trunk = fakes.FakeTrunk.create_one_trunk() - _subports = _trunk['sub_ports'] - - columns = ( - 'Port', - 'Segmentation Type', - 'Segmentation ID', - ) - data = [] - for s in _subports: - data.append(( - s['port_id'], - s['segmentation_type'], - s['segmentation_id'], - )) - - def setUp(self): - super(TestListNetworkSubport, self).setUp() - mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id', - new=_get_id).start() - self.neutronclient.trunk_get_subports = mock.Mock( - return_value={trunk.SUB_PORTS: self._subports}) - - # Get the command object to test - self.cmd = trunk.ListNetworkSubport(self.app, self.namespace) - - def test_subport_list(self): - arglist = [ - '--trunk', self._trunk['name'], - ] - verifylist = [ - ('trunk', self._trunk['name']), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - columns, data = self.cmd.take_action(parsed_args) - - self.neutronclient.trunk_get_subports.assert_called_once_with( - self._trunk['name']) - self.assertEqual(self.columns, columns) - self.assertEqual(self.data, list(data)) - - -class TestUnsetNetworkTrunk(test_fakes.TestNeutronClientOSCV2): - - _trunk = fakes.FakeTrunk.create_one_trunk() - - columns = ( - 'admin_state_up', - 'id', - 'name', - 'port_id', - 'project_id', - 'status', - 'sub_ports', - ) - data = ( - v2_utils.AdminStateColumn(_trunk['admin_state_up']), - _trunk['id'], - _trunk['name'], - _trunk['port_id'], - _trunk['project_id'], - _trunk['status'], - format_columns.ListDictColumn(_trunk['sub_ports']), - ) - - def setUp(self): - super(TestUnsetNetworkTrunk, self).setUp() - - mock.patch('neutronclient.osc.v2.trunk.network_trunk._get_id', - new=_get_id).start() - self.neutronclient.trunk_remove_subports = mock.Mock( - return_value=None) - - # Get the command object to test - self.cmd = trunk.UnsetNetworkTrunk(self.app, self.namespace) - - def test_unset_network_trunk_subport(self): - subport = self._trunk['sub_ports'][0] - arglist = [ - "--subport", subport['port_id'], - self._trunk['name'], - ] - verifylist = [ - ('trunk', self._trunk['name']), - ('unset_subports', [subport['port_id']]), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - self.neutronclient.trunk_remove_subports.assert_called_once_with( - self._trunk['name'], - {trunk.SUB_PORTS: [{'port_id': subport['port_id']}]} - ) - self.assertIsNone(result) - - def test_unset_subport_no_arguments_fail(self): - arglist = [ - self._trunk['name'], - ] - verifylist = [ - ('trunk', self._trunk['name']), - ] - self.assertRaises(tests_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) diff --git a/setup.cfg b/setup.cfg index 5c62570ac..432ec682f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,13 +33,6 @@ openstack.cli.extension = neutronclient = neutronclient.osc.plugin openstack.neutronclient.v2 = - network_subport_list = neutronclient.osc.v2.trunk.network_trunk:ListNetworkSubport - network_trunk_create = neutronclient.osc.v2.trunk.network_trunk:CreateNetworkTrunk - network_trunk_delete = neutronclient.osc.v2.trunk.network_trunk:DeleteNetworkTrunk - network_trunk_list = neutronclient.osc.v2.trunk.network_trunk:ListNetworkTrunk - network_trunk_set = neutronclient.osc.v2.trunk.network_trunk:SetNetworkTrunk - network_trunk_show = neutronclient.osc.v2.trunk.network_trunk:ShowNetworkTrunk - network_trunk_unset = neutronclient.osc.v2.trunk.network_trunk:UnsetNetworkTrunk sfc_flow_classifier_create = neutronclient.osc.v2.sfc.sfc_flow_classifier:CreateSfcFlowClassifier sfc_flow_classifier_delete = neutronclient.osc.v2.sfc.sfc_flow_classifier:DeleteSfcFlowClassifier sfc_flow_classifier_list = neutronclient.osc.v2.sfc.sfc_flow_classifier:ListSfcFlowClassifier From 16a2cd127dfa2e44887aee911d248c8d9365efb8 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Tue, 14 Feb 2023 08:27:42 +0100 Subject: [PATCH 104/149] Remove CLI warning message This warning was added in [1]. This patch is partially reverting it but we keep the release note. This warning message could be a bit intrusive for those users still using it. In any case, the recommendation to move to OSC is something already known and publicly requested. [1]https://review.opendev.org/c/openstack/python-neutronclient/+/862371 Change-Id: I0c2fba3e45a9de1eba09efcf8919661a855c7e89 --- neutronclient/v2_0/client.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index e670e3f5c..de0529182 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -250,9 +250,6 @@ class ClientBase(object): def __init__(self, **kwargs): """Initialize a new client for the Neutron v2.0 API.""" super(ClientBase, self).__init__() - _logger.warning("The python binding code in neutronclient will be " - "deprecated in favor of OpenstackSDK, please use " - "that!") self.retries = kwargs.pop('retries', 0) self.raise_errors = kwargs.pop('raise_errors', True) self.httpclient = client.construct_http_client(**kwargs) From 3071dfbd0f8e7c8a297f58b6c038cf461691840e Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 2 Mar 2023 13:26:42 +0000 Subject: [PATCH 105/149] Update master for stable/2023.1 Add file to the reno documentation build to show release notes for stable/2023.1. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/2023.1. Sem-Ver: feature Change-Id: I194c39a2bbfde10c65912835019a8c2f21464569 --- releasenotes/source/2023.1.rst | 6 ++++++ releasenotes/source/index.rst | 1 + 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/2023.1.rst diff --git a/releasenotes/source/2023.1.rst b/releasenotes/source/2023.1.rst new file mode 100644 index 000000000..d1238479b --- /dev/null +++ b/releasenotes/source/2023.1.rst @@ -0,0 +1,6 @@ +=========================== +2023.1 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2023.1 diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index f1aa6a943..5dbb2f331 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + 2023.1 zed yoga xena From 0b271d3b8cd1b28e745dd3d1b066c8dc084ef748 Mon Sep 17 00:00:00 2001 From: elajkat Date: Wed, 21 Dec 2022 14:08:58 +0100 Subject: [PATCH 106/149] OSC: Remove BGP calls to neutronclient With [1] the python binding code in Neutronclient prints warning about future deprecation, change neutron-dynamic-routing osc client code to use totally OpenstackSDK. [1]: https://review.opendev.org/c/openstack/python-neutronclient/+/862371 Related-Bug: #1999774 Depends-On: https://review.opendev.org/c/openstack/openstacksdk/+/869485 Depends-On: https://review.opendev.org/c/openstack/requirements/+/873598 Change-Id: I5dd143e670b70cc42a2ae48fe4bac0cf09416cb5 --- neutronclient/osc/utils.py | 10 ++ .../osc/v2/dynamic_routing/bgp_dragent.py | 89 +++++++++++------- .../osc/v2/dynamic_routing/bgp_peer.py | 38 +++----- .../osc/v2/dynamic_routing/bgp_speaker.py | 92 ++++++++----------- .../unit/osc/v2/dynamic_routing/fakes.py | 31 +++++-- .../v2/dynamic_routing/test_bgp_dragent.py | 30 +++--- .../osc/v2/dynamic_routing/test_bgp_peer.py | 35 ++++--- .../v2/dynamic_routing/test_bgp_speaker.py | 30 +++--- neutronclient/tests/unit/osc/v2/fakes.py | 4 + requirements.txt | 1 + 10 files changed, 192 insertions(+), 168 deletions(-) diff --git a/neutronclient/osc/utils.py b/neutronclient/osc/utils.py index 413ad607c..39b17b640 100644 --- a/neutronclient/osc/utils.py +++ b/neutronclient/osc/utils.py @@ -118,3 +118,13 @@ def _find_identity_resource(identity_client_manager, name_or_id, # The above are borrowed from openstackclient.identity.common. # DO NOT ADD original methods in neutronclient repo to the above area. + + +def _get_columns(item): + column_map = {} + hidden_columns = ['location', 'tenant_id'] + return utils.get_osc_show_columns_for_sdk_resource( + item, + column_map, + hidden_columns + ) diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py b/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py index 025022996..4af2008fe 100644 --- a/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py +++ b/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py @@ -15,7 +15,6 @@ from osc_lib import utils from neutronclient._i18n import _ -from neutronclient.osc.v2.dynamic_routing import constants def _format_alive_state(item): @@ -45,11 +44,9 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - client.add_bgp_speaker_to_dragent( - parsed_args.dragent_id, {'bgp_speaker_id': speaker_id}) + client = self.app.client_manager.network + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker).id + client.add_bgp_speaker_to_dragent(parsed_args.dragent_id, speaker_id) class RemoveBgpSpeakerFromDRAgent(command.Command): @@ -62,9 +59,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] + client = self.app.client_manager.network + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker).id client.remove_bgp_speaker_from_dragent(parsed_args.dragent_id, speaker_id) @@ -92,18 +88,30 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - search_opts = {} - client = self.app.client_manager.neutronclient - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - search_opts['bgp_speaker'] = speaker_id - data = client.list_dragents_hosting_bgp_speaker(**search_opts) - headers = ('ID', 'Host', 'State', 'Alive') - columns = ('id', 'host', 'admin_state_up', 'alive') - return (headers, - (utils.get_dict_properties( - s, columns, formatters=_formatters, - ) for s in data['agents'])) + client = self.app.client_manager.network + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker).id + data = client.get_bgp_dragents_hosting_speaker(speaker_id) + columns = ( + 'id', + 'agent_type', + 'host', + 'availability_zone', + 'is_alive', + 'is_admin_state_up', + 'binary' + ) + column_headers = ( + 'ID', + 'Agent Type', + 'Host', + 'Availability Zone', + 'Alive', + 'State', + 'Binary' + ) + return (column_headers, + (utils.get_item_properties( + s, columns,) for s in data)) class ListDRAgent(command.Lister): @@ -123,20 +131,31 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - search_opts = {} - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network if parsed_args.bgp_speaker is not None: - search_opts = {} - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - search_opts['bgp_speaker'] = speaker_id - data = client.list_dragents_hosting_bgp_speaker(**search_opts) + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker).id + data = client.get_bgp_dragents_hosting_speaker(speaker_id) else: attrs = {'agent_type': 'BGP dynamic routing agent'} - data = client.list_agents(**attrs) - headers = ('ID', 'Host', 'State', 'Alive') - columns = ('id', 'host', 'admin_state_up', 'alive') - return (headers, - (utils.get_dict_properties( - s, columns, formatters=_formatters, - ) for s in data['agents'])) + data = client.agents(**attrs) + columns = ( + 'id', + 'agent_type', + 'host', + 'availability_zone', + 'is_alive', + 'is_admin_state_up', + 'binary' + ) + column_headers = ( + 'ID', + 'Agent Type', + 'Host', + 'Availability Zone', + 'Alive', + 'State', + 'Binary' + ) + return (column_headers, + (utils.get_item_properties( + s, columns,) for s in data)) diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_peer.py b/neutronclient/osc/v2/dynamic_routing/bgp_peer.py index c8e602ebb..0610a3ac0 100644 --- a/neutronclient/osc/v2/dynamic_routing/bgp_peer.py +++ b/neutronclient/osc/v2/dynamic_routing/bgp_peer.py @@ -13,7 +13,6 @@ from osc_lib.command import command from osc_lib import utils -from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.common import exceptions @@ -96,11 +95,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_attrs(self.app.client_manager, parsed_args) - body = {constants.BGP_PEER: attrs} - obj = client.create_bgp_peer(body)[constants.BGP_PEER] - columns, display_columns = column_util.get_columns(obj) + obj = client.create_bgp_peer(**attrs) + display_columns, columns = nc_osc_utils._get_columns(obj) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -118,9 +116,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGP_PEER, - parsed_args.bgp_peer)['id'] + client = self.app.client_manager.network + id = client.find_bgp_peer(parsed_args.bgp_peer)['id'] client.delete_bgp_peer(id) @@ -128,13 +125,11 @@ class ListBgpPeer(command.Lister): _description = _("List BGP peers") def take_action(self, parsed_args): - data = self.app.client_manager.neutronclient.list_bgp_peers() + data = self.app.client_manager.network.bgp_peers(retrieve_all=True) headers = ('ID', 'Name', 'Peer IP', 'Remote AS') columns = ('id', 'name', 'peer_ip', 'remote_as') return (headers, - (utils.get_dict_properties( - s, columns, - ) for s in data[constants.BGP_PEERS])) + (utils.get_dict_properties(s, columns,) for s in data)) class SetBgpPeer(command.Command): @@ -158,13 +153,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGP_PEER, - parsed_args.bgp_peer)['id'] + client = self.app.client_manager.network + id = client.find_bgp_peer(parsed_args.bgp_peer)['id'] attrs = _get_attrs(self.app.client_manager, parsed_args) - body = {} - body[constants.BGP_PEER] = attrs - client.update_bgp_peer(id, body) + client.update_bgp_peer(id, **attrs) class ShowBgpPeer(command.ShowOne): @@ -180,10 +172,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGP_PEER, - parsed_args.bgp_peer)['id'] - obj = client.show_bgp_peer(id)[constants.BGP_PEER] - columns, display_columns = column_util.get_columns(obj) + client = self.app.client_manager.network + id = client.find_bgp_peer(parsed_args.bgp_peer, + ignore_missing=False).id + obj = client.get_bgp_peer(id) + display_columns, columns = nc_osc_utils._get_columns(obj) data = utils.get_dict_properties(obj, columns) return display_columns, data diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py b/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py index 171d7f45f..76d8340b9 100644 --- a/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py +++ b/neutronclient/osc/v2/dynamic_routing/bgp_speaker.py @@ -13,7 +13,6 @@ from osc_lib.command import command from osc_lib import utils -from osc_lib.utils import columns as column_util from neutronclient._i18n import _ from neutronclient.osc import utils as nc_osc_utils @@ -87,12 +86,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - net_id = client.find_resource('network', - parsed_args.network)['id'] - client.add_network_to_bgp_speaker(speaker_id, {'network_id': net_id}) + client = self.app.client_manager.network + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker, + ignore_missing=False).id + net_id = client.find_network(parsed_args.network, + ignore_missing=False).id + client.add_gateway_network_to_speaker(speaker_id, net_id) class AddPeerToSpeaker(command.Command): @@ -111,12 +110,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - peer_id = client.find_resource(constants.BGP_PEER, - parsed_args.bgp_peer)['id'] - client.add_peer_to_bgp_speaker(speaker_id, {'bgp_peer_id': peer_id}) + client = self.app.client_manager.network + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] + peer_id = client.find_bgp_peer(parsed_args.bgp_peer)['id'] + client.add_bgp_peer_to_speaker(speaker_id, peer_id) class CreateBgpSpeaker(command.ShowOne): @@ -145,12 +142,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_attrs(self.app.client_manager, parsed_args) - body = {} - body[constants.BGP_SPEAKER] = attrs - obj = client.create_bgp_speaker(body)[constants.BGP_SPEAKER] - columns, display_columns = column_util.get_columns(obj) + obj = client.create_bgp_speaker(**attrs) + display_columns, columns = nc_osc_utils._get_columns(obj) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -168,9 +163,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] + client = self.app.client_manager.network + id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] client.delete_bgp_speaker(id) @@ -186,16 +180,16 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network if parsed_args.agent is not None: - data = client.list_bgp_speaker_on_dragent(parsed_args.agent) + data = client.get_bgp_speakers_hosted_by_dragent(parsed_args.agent) else: - data = client.list_bgp_speakers() + data = client.bgp_speakers(retrieve_all=True) headers = ('ID', 'Name', 'Local AS', 'IP Version') columns = ('id', 'name', 'local_as', 'ip_version') return (headers, (utils.get_dict_properties(s, columns) - for s in data[constants.BGP_SPEAKERS])) + for s in data)) class ListRoutesAdvertisedBySpeaker(command.Lister): @@ -211,10 +205,9 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - data = client.list_route_advertised_from_bgp_speaker(speaker_id) + client = self.app.client_manager.network + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] + data = client.get_advertised_routes_of_speaker(speaker_id) headers = ('Destination', 'Nexthop') columns = ('destination', 'next_hop') return (headers, (utils.get_dict_properties(s, columns) @@ -237,13 +230,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - net_id = client.find_resource('network', - parsed_args.network)['id'] - client.remove_network_from_bgp_speaker(speaker_id, - {'network_id': net_id}) + client = self.app.client_manager.network + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] + net_id = client.find_network(parsed_args.network)['id'] + client.remove_gateway_network_from_speaker(speaker_id, net_id) class RemovePeerFromSpeaker(command.Command): @@ -262,13 +252,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - speaker_id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - peer_id = client.find_resource(constants.BGP_PEER, - parsed_args.bgp_peer)['id'] - client.remove_peer_from_bgp_speaker(speaker_id, - {'bgp_peer_id': peer_id}) + client = self.app.client_manager.network + speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] + peer_id = client.find_bgp_peer(parsed_args.bgp_peer)['id'] + client.remove_bgp_peer_from_speaker(speaker_id, peer_id) class SetBgpSpeaker(command.Command): @@ -290,13 +277,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] + client = self.app.client_manager.network + id = client.find_bgp_speaker(parsed_args.bgp_speaker)['id'] attrs = _get_attrs(self.app.client_manager, parsed_args) - body = {} - body[constants.BGP_SPEAKER] = attrs - client.update_bgp_speaker(id, body) + client.update_bgp_speaker(id, **attrs) class ShowBgpSpeaker(command.ShowOne): @@ -312,10 +296,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGP_SPEAKER, - parsed_args.bgp_speaker)['id'] - obj = client.show_bgp_speaker(id)[constants.BGP_SPEAKER] - columns, display_columns = column_util.get_columns(obj) + client = self.app.client_manager.network + id = client.find_bgp_speaker(parsed_args.bgp_speaker, + ignore_missing=False).id + obj = client.get_bgp_speaker(id) + display_columns, columns = nc_osc_utils._get_columns(obj) data = utils.get_dict_properties(obj, columns) return display_columns, data diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py index c496a3f66..188f06871 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/fakes.py @@ -10,10 +10,12 @@ # License for the specific language governing permissions and limitations # under the License. -import copy from unittest import mock import uuid +from openstack.network.v2 import agent as _agent +from openstack.network.v2 import bgp_peer as _bgp_peer +from openstack.network.v2 import bgp_speaker as _bgp_speaker from neutronclient.tests.unit.osc.v2 import fakes @@ -26,6 +28,17 @@ def setUp(self): cmd_resource=None, parent_id=None, fields=None: {'id': name_or_id}) + self.networkclient.find_bgp_speaker = mock.Mock( + side_effect=lambda name_or_id, project_id=None, + cmd_resource=None, parent_id=None, fields=None, + ignore_missing=False: + _bgp_speaker.BgpSpeaker(id=name_or_id)) + self.networkclient.find_bgp_peer = mock.Mock( + side_effect=lambda name_or_id, project_id=None, + cmd_resource=None, parent_id=None, fields=None, + ignore_missing=False: + _bgp_peer.BgpPeer(id=name_or_id)) + class FakeBgpSpeaker(object): """Fake one or more bgp speakers.""" @@ -48,8 +61,9 @@ def create_one_bgp_speaker(attrs=None): # Overwrite default attributes. bgp_speaker_attrs.update(attrs) + ret_bgp_speaker = _bgp_speaker.BgpSpeaker(**bgp_speaker_attrs) - return copy.deepcopy(bgp_speaker_attrs) + return ret_bgp_speaker @staticmethod def create_bgp_speakers(attrs=None, count=1): @@ -61,7 +75,7 @@ def create_bgp_speakers(attrs=None, count=1): bgp_speaker = FakeBgpSpeaker.create_one_bgp_speaker(attrs) bgp_speakers.append(bgp_speaker) - return {'bgp_speakers': bgp_speakers} + return bgp_speakers class FakeBgpPeer(object): @@ -82,8 +96,9 @@ def create_one_bgp_peer(attrs=None): # Overwrite default attributes. bgp_peer_attrs.update(attrs) + ret_bgp_peer = _bgp_peer.BgpPeer(**bgp_peer_attrs) - return copy.deepcopy(bgp_peer_attrs) + return ret_bgp_peer @staticmethod def create_bgp_peers(attrs=None, count=1): @@ -93,7 +108,7 @@ def create_bgp_peers(attrs=None, count=1): bgp_peer = FakeBgpPeer.create_one_bgp_peer(attrs) bgp_peers.append(bgp_peer) - return {'bgp_peers': bgp_peers} + return bgp_peers class FakeDRAgent(object): @@ -106,6 +121,7 @@ def create_one_dragent(attrs=None): dragent_attrs = { 'binary': 'neutron-bgp-dragent', 'admin_state_up': True, + 'availability_zone': None, 'alive': True, 'topic': 'bgp_dragent', 'host': 'network-' + uuid.uuid4().hex, @@ -116,8 +132,7 @@ def create_one_dragent(attrs=None): # Overwrite default attributes. dragent_attrs.update(attrs) - - return copy.deepcopy(dragent_attrs) + return _agent.Agent(**dragent_attrs) @staticmethod def create_dragents(attrs=None, count=1): @@ -127,4 +142,4 @@ def create_dragents(attrs=None, count=1): agent = FakeDRAgent.create_one_dragent(attrs) agents.append(agent) - return {'agents': agents} + return agents diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py index 7a94b323a..89ba20d93 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py @@ -39,15 +39,14 @@ def test_add_bgp_speaker_to_dragent(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch.object(self.neutronclient, + with mock.patch.object(self.networkclient, "add_bgp_speaker_to_dragent", return_value=None): result = self.cmd.take_action(parsed_args) - self.neutronclient.add_bgp_speaker_to_dragent.\ + self.networkclient.add_bgp_speaker_to_dragent.\ assert_called_once_with( - self._bgp_dragent_id, - {'bgp_speaker_id': self._bgp_speaker_id}) + self._bgp_dragent_id, self._bgp_speaker_id) self.assertIsNone(result) @@ -75,11 +74,11 @@ def test_remove_bgp_speaker_from_dragent(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch.object(self.neutronclient, + with mock.patch.object(self.networkclient, "remove_bgp_speaker_from_dragent", return_value=None): result = self.cmd.take_action(parsed_args) - self.neutronclient.remove_bgp_speaker_from_dragent.\ + self.networkclient.remove_bgp_speaker_from_dragent.\ assert_called_once_with(self._bgp_dragent_id, self._bgp_speaker_id) self.assertIsNone(result) @@ -90,12 +89,16 @@ class TestListDRAgentsHostingBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_speaker_id = _bgp_speaker['id'] attrs = {'bgp_speaker_id': _bgp_speaker_id} _bgp_dragents = fakes.FakeDRAgent.create_dragents(attrs) - columns = ('ID', 'Host', 'State', 'Alive') + columns = ('ID', 'Agent Type', 'Host', 'Availability Zone', + 'Alive', 'State', 'Binary') data = [(_bgp_dragent['id'], + _bgp_dragent['agent_type'], _bgp_dragent['host'], + _bgp_dragent['availability_zone'], _bgp_dragent['admin_state_up'], - ':-)' if _bgp_dragent['alive'] else 'XXX') - for _bgp_dragent in _bgp_dragents['agents']] + _bgp_dragent['alive'], + _bgp_dragent['binary'],) + for _bgp_dragent in _bgp_dragents] def setUp(self): super(TestListDRAgentsHostingBgpSpeaker, self).setUp() @@ -112,12 +115,11 @@ def test_list_dragents_hosting_bgp_speaker(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch.object(self.neutronclient, - "list_dragents_hosting_bgp_speaker", + with mock.patch.object(self.networkclient, + "get_bgp_dragents_hosting_speaker", return_value=self._bgp_dragents): columns, data = self.cmd.take_action(parsed_args) - attrs = {'bgp_speaker': self._bgp_speaker_id} - self.neutronclient.list_dragents_hosting_bgp_speaker.\ - assert_called_once_with(**attrs) + self.networkclient.get_bgp_dragents_hosting_speaker.\ + assert_called_once_with(self._bgp_speaker_id) self.assertEqual(self.columns, columns) self.assertListEqual(self.data, list(data)) diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py index 506c86d93..73b6bf7ab 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_peer.py @@ -20,7 +20,7 @@ class TestListBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_peers = fakes.FakeBgpPeer.create_bgp_peers(count=1) columns = ('ID', 'Name', 'Peer IP', 'Remote AS') data = [] - for _bgp_peer in _bgp_peers['bgp_peers']: + for _bgp_peer in _bgp_peers: data.append(( _bgp_peer['id'], _bgp_peer['name'], @@ -30,7 +30,7 @@ class TestListBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): def setUp(self): super(TestListBgpPeer, self).setUp() - self.neutronclient.list_bgp_peers = mock.Mock( + self.networkclient.bgp_peers = mock.Mock( return_value=self._bgp_peers ) @@ -41,7 +41,8 @@ def test_bgp_peer_list(self): parsed_args = self.check_parser(self.cmd, [], []) columns, data = self.cmd.take_action(parsed_args) - self.neutronclient.list_bgp_peers.assert_called_once_with() + self.networkclient.bgp_peers.assert_called_once_with( + retrieve_all=True) self.assertEqual(self.columns, columns) self.assertEqual(self.data, list(data)) @@ -53,7 +54,7 @@ class TestDeleteBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): def setUp(self): super(TestDeleteBgpPeer, self).setUp() - self.neutronclient.delete_bgp_peer = mock.Mock(return_value=None) + self.networkclient.delete_bgp_peer = mock.Mock(return_value=None) self.cmd = bgp_peer.DeleteBgpPeer(self.app, self.namespace) @@ -68,7 +69,7 @@ def test_delete_bgp_peer(self): result = self.cmd.take_action(parsed_args) - self.neutronclient.delete_bgp_peer.assert_called_once_with( + self.networkclient.delete_bgp_peer.assert_called_once_with( self._bgp_peer['name']) self.assertIsNone(result) @@ -80,31 +81,30 @@ class TestShowBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): _one_bgp_peer['id'], _one_bgp_peer['name'], _one_bgp_peer['peer_ip'], + _one_bgp_peer['tenant_id'], _one_bgp_peer['remote_as'], - _one_bgp_peer['tenant_id'] ) - _bgp_peer = {'bgp_peer': _one_bgp_peer} + _bgp_peer = _one_bgp_peer _bgp_peer_name = _one_bgp_peer['name'] columns = ( 'auth_type', 'id', 'name', 'peer_ip', + 'project_id', 'remote_as', - 'tenant_id' ) def setUp(self): super(TestShowBgpPeer, self).setUp() - self.neutronclient.show_bgp_peer = mock.Mock( + self.networkclient.get_bgp_peer = mock.Mock( return_value=self._bgp_peer ) - bgp_peer.get_bgp_peer_id = mock.Mock(return_value=self._bgp_peer_name) # Get the command object to test self.cmd = bgp_peer.ShowBgpPeer(self.app, self.namespace) - def test_bgp_peer_list(self): + def test_bgp_peer_show(self): arglist = [ self._bgp_peer_name, ] @@ -114,7 +114,7 @@ def test_bgp_peer_list(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) data = self.cmd.take_action(parsed_args) - self.neutronclient.show_bgp_peer.assert_called_once_with( + self.networkclient.get_bgp_peer.assert_called_once_with( self._bgp_peer_name) self.assertEqual(self.columns, data[0]) self.assertEqual(self.data, data[1]) @@ -126,7 +126,7 @@ class TestSetBgpPeer(fakes.TestNeutronDynamicRoutingOSCV2): def setUp(self): super(TestSetBgpPeer, self).setUp() - self.neutronclient.update_bgp_peer = mock.Mock(return_value=None) + self.networkclient.update_bgp_peer = mock.Mock(return_value=None) bgp_peer.get_bgp_peer_id = mock.Mock(return_value=self._bgp_peer_name) self.cmd = bgp_peer.SetBgpPeer(self.app, self.namespace) @@ -144,10 +144,7 @@ def test_set_bgp_peer(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'bgp_peer': { - 'name': 'noob', - 'password': None} - } - self.neutronclient.update_bgp_peer.assert_called_once_with( - self._bgp_peer_name, attrs) + attrs = {'name': 'noob', 'password': None} + self.networkclient.update_bgp_peer.assert_called_once_with( + self._bgp_peer_name, **attrs) self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py index 159746875..c5e42e588 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_speaker.py @@ -20,7 +20,7 @@ class TestListBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): _bgp_speakers = fakes.FakeBgpSpeaker.create_bgp_speakers() columns = ('ID', 'Name', 'Local AS', 'IP Version') data = [] - for _bgp_speaker in _bgp_speakers['bgp_speakers']: + for _bgp_speaker in _bgp_speakers: data.append(( _bgp_speaker['id'], _bgp_speaker['name'], @@ -30,7 +30,7 @@ class TestListBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): def setUp(self): super(TestListBgpSpeaker, self).setUp() - self.neutronclient.list_bgp_speakers = mock.Mock( + self.networkclient.bgp_speakers = mock.Mock( return_value=self._bgp_speakers ) @@ -41,7 +41,9 @@ def test_bgp_speaker_list(self): parsed_args = self.check_parser(self.cmd, [], []) columns, data = self.cmd.take_action(parsed_args) - self.neutronclient.list_bgp_speakers.assert_called_once_with() + self.networkclient.bgp_speakers.assert_called_once_with( + retrieve_all=True) + self.assertEqual(self.columns, columns) self.assertEqual(self.data, list(data)) @@ -53,7 +55,7 @@ class TestDeleteBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): def setUp(self): super(TestDeleteBgpSpeaker, self).setUp() - self.neutronclient.delete_bgp_speaker = mock.Mock(return_value=None) + self.networkclient.delete_bgp_speaker = mock.Mock(return_value=None) self.cmd = bgp_speaker.DeleteBgpSpeaker(self.app, self.namespace) @@ -68,7 +70,7 @@ def test_delete_bgp_speaker(self): result = self.cmd.take_action(parsed_args) - self.neutronclient.delete_bgp_speaker.assert_called_once_with( + self.networkclient.delete_bgp_speaker.assert_called_once_with( self._bgp_speaker['name']) self.assertIsNone(result) @@ -86,7 +88,7 @@ class TestShowBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): _one_bgp_speaker['peers'], _one_bgp_speaker['tenant_id'] ) - _bgp_speaker = {'bgp_speaker': _one_bgp_speaker} + _bgp_speaker = _one_bgp_speaker _bgp_speaker_name = _one_bgp_speaker['name'] columns = ( 'advertise_floating_ip_host_routes', @@ -97,13 +99,13 @@ class TestShowBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): 'name', 'networks', 'peers', - 'tenant_id' + 'project_id' ) def setUp(self): super(TestShowBgpSpeaker, self).setUp() - self.neutronclient.show_bgp_speaker = mock.Mock( + self.networkclient.get_bgp_speaker = mock.Mock( return_value=self._bgp_speaker ) # Get the command object to test @@ -119,7 +121,7 @@ def test_bgp_speaker_show(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) data = self.cmd.take_action(parsed_args) - self.neutronclient.show_bgp_speaker.assert_called_once_with( + self.networkclient.get_bgp_speaker.assert_called_once_with( self._bgp_speaker_name) self.assertEqual(self.columns, data[0]) self.assertEqual(self.data, data[1]) @@ -131,7 +133,7 @@ class TestSetBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): def setUp(self): super(TestSetBgpSpeaker, self).setUp() - self.neutronclient.update_bgp_speaker = mock.Mock( + self.networkclient.update_bgp_speaker = mock.Mock( return_value=None) self.cmd = bgp_speaker.SetBgpSpeaker(self.app, self.namespace) @@ -149,9 +151,7 @@ def test_set_bgp_speaker(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'bgp_speaker': { - 'name': 'noob'} - } - self.neutronclient.update_bgp_speaker.assert_called_once_with( - self._bgp_speaker_name, attrs) + attrs = {'name': 'noob'} + self.networkclient.update_bgp_speaker.assert_called_once_with( + self._bgp_speaker_name, **attrs) self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/fakes.py b/neutronclient/tests/unit/osc/v2/fakes.py index c7876b645..7fec7347c 100644 --- a/neutronclient/tests/unit/osc/v2/fakes.py +++ b/neutronclient/tests/unit/osc/v2/fakes.py @@ -26,6 +26,10 @@ def setUp(self): self.app.client_manager.session = mock.Mock() self.app.client_manager.neutronclient = mock.Mock() self.neutronclient = self.app.client_manager.neutronclient + + self.app.client_manager.network = mock.Mock() + self.networkclient = self.app.client_manager.network + self.addCleanup(mock.patch.stopall) # TODO(amotoki): Move this to osc_lib diff --git a/requirements.txt b/requirements.txt index b85e6b69a..2e9e22d08 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ cliff>=3.4.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 iso8601>=0.1.11 # MIT netaddr>=0.7.18 # BSD +openstacksdk>=1.0.0 # Apache-2.0 osc-lib>=1.12.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 From 52653c95e050437b27492404649e42d01b79732b Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Tue, 11 Apr 2023 13:12:45 +0200 Subject: [PATCH 107/149] Remove the CLI code from the Neutron client. This project no longer provides CLI support. All code has been removed. Please use openstack CLI instead This patch removes entry point for neutron CLI too, bash completion script and CLI related functional and unit tests but it still keeps neutronclient/neutron/v2_0 module as this is used by e.g. Nova. Co-Authored-By: Slawek Kaplonski Closes-Bug: #2003861 Change-Id: I5b6c735d1ff931d7991a42b262e7faa47b75edeb --- .zuul.yaml | 52 - README.rst | 3 +- doc/source/cli/index.rst | 14 +- doc/source/cli/neutron-reference.rst | 48 - doc/source/cli/neutron.rst | 412 ------ .../contributor/cli_option_guideline.rst | 263 ---- .../contributor/client_command_extensions.rst | 97 -- doc/source/contributor/index.rst | 2 - doc/source/contributor/transition_to_osc.rst | 32 +- doc/source/index.rst | 10 +- neutron_test.sh | 165 --- neutronclient/shell.py | 654 --------- neutronclient/tests/functional/__init__.py | 0 .../tests/functional/adv-svcs/__init__.py | 0 .../adv-svcs/test_readonly_neutron_fwaas.py | 42 - .../adv-svcs/test_readonly_neutron_vpn.py | 57 - neutronclient/tests/functional/base.py | 80 -- .../tests/functional/core/__init__.py | 0 .../functional/core/test_cli_formatter.py | 59 - .../tests/functional/core/test_clientlib.py | 61 - .../tests/functional/core/test_common.py | 33 - .../tests/functional/core/test_purge.py | 174 --- .../functional/core/test_readonly_neutron.py | 136 -- .../functional/core/test_subnet_create.py | 36 - neutronclient/tests/functional/hooks/fwaas | 2 - .../tests/functional/hooks/gate_hook.sh | 42 - .../tests/functional/hooks/post_test_hook.sh | 68 - neutronclient/tests/functional/hooks/vpnaas | 1 - neutronclient/tests/unit/bgp/__init__.py | 0 .../unit/bgp/test_cli20_dragentscheduler.py | 66 - .../tests/unit/bgp/test_cli20_peer.py | 224 --- .../tests/unit/bgp/test_cli20_speaker.py | 273 ---- neutronclient/tests/unit/flavor/__init__.py | 0 .../tests/unit/flavor/test_cli20_flavor.py | 154 --- .../unit/flavor/test_cli20_flavor_profile.py | 122 -- neutronclient/tests/unit/fw/__init__.py | 0 .../tests/unit/fw/test_cli20_firewall.py | 170 --- .../unit/fw/test_cli20_firewallpolicy.py | 228 ---- .../tests/unit/fw/test_cli20_firewallrule.py | 251 ---- neutronclient/tests/unit/lb/__init__.py | 0 .../tests/unit/lb/test_cli20_healthmonitor.py | 202 --- .../tests/unit/lb/test_cli20_member.py | 118 -- .../tests/unit/lb/test_cli20_pool.py | 166 --- neutronclient/tests/unit/lb/test_cli20_vip.py | 206 --- neutronclient/tests/unit/lb/v2/__init__.py | 0 .../unit/lb/v2/test_cli20_healthmonitor.py | 175 --- .../tests/unit/lb/v2/test_cli20_l7policy.py | 260 ---- .../tests/unit/lb/v2/test_cli20_l7rule.py | 210 --- .../tests/unit/lb/v2/test_cli20_listener.py | 194 --- .../unit/lb/v2/test_cli20_loadbalancer.py | 213 --- .../tests/unit/lb/v2/test_cli20_member.py | 171 --- .../tests/unit/lb/v2/test_cli20_pool.py | 202 --- neutronclient/tests/unit/qos/__init__.py | 0 .../qos/test_cli20_bandwidth_limit_rule.py | 137 -- .../unit/qos/test_cli20_dscp_marking_rule.py | 91 -- .../qos/test_cli20_minimum_bandwidth_rule.py | 143 -- .../tests/unit/qos/test_cli20_policy.py | 192 --- .../tests/unit/qos/test_cli20_rule.py | 44 - .../unit/test_auto_allocated_topology.py | 76 -- neutronclient/tests/unit/test_cli20.py | 1215 ----------------- .../tests/unit/test_cli20_address_scope.py | 175 --- neutronclient/tests/unit/test_cli20_agents.py | 97 -- .../tests/unit/test_cli20_agentschedulers.py | 209 --- neutronclient/tests/unit/test_cli20_az.py | 31 - .../tests/unit/test_cli20_extensions.py | 45 - .../tests/unit/test_cli20_floatingips.py | 193 --- .../tests/unit/test_cli20_metering.py | 99 -- .../tests/unit/test_cli20_network.py | 698 ---------- .../test_cli20_network_ip_availability.py | 54 - neutronclient/tests/unit/test_cli20_port.py | 794 ----------- neutronclient/tests/unit/test_cli20_purge.py | 100 -- neutronclient/tests/unit/test_cli20_rbac.py | 134 -- neutronclient/tests/unit/test_cli20_router.py | 434 ------ .../tests/unit/test_cli20_securitygroup.py | 657 --------- .../tests/unit/test_cli20_servicetype.py | 55 - neutronclient/tests/unit/test_cli20_subnet.py | 687 ---------- .../tests/unit/test_cli20_subnetpool.py | 208 --- neutronclient/tests/unit/test_cli20_tag.py | 131 -- .../tests/unit/test_client_extension.py | 221 --- neutronclient/tests/unit/test_name_or_id.py | 244 ---- neutronclient/tests/unit/test_quota.py | 99 -- neutronclient/tests/unit/test_shell.py | 366 ----- neutronclient/tests/unit/vpn/__init__.py | 0 .../unit/vpn/test_cli20_endpoint_group.py | 145 -- .../tests/unit/vpn/test_cli20_ikepolicy.py | 241 ---- .../vpn/test_cli20_ipsec_site_connection.py | 342 ----- .../tests/unit/vpn/test_cli20_ipsecpolicy.py | 249 ---- .../tests/unit/vpn/test_cli20_vpnservice.py | 157 --- neutronclient/tests/unit/vpn/test_utils.py | 130 -- .../remove-cli-code-53969e9aa927e530.yaml | 12 + setup.cfg | 287 ---- tools/neutron.bash_completion | 27 - tox.ini | 5 - 93 files changed, 22 insertions(+), 15350 deletions(-) delete mode 100644 doc/source/cli/neutron-reference.rst delete mode 100644 doc/source/cli/neutron.rst delete mode 100644 doc/source/contributor/cli_option_guideline.rst delete mode 100644 doc/source/contributor/client_command_extensions.rst delete mode 100755 neutron_test.sh delete mode 100644 neutronclient/shell.py delete mode 100644 neutronclient/tests/functional/__init__.py delete mode 100644 neutronclient/tests/functional/adv-svcs/__init__.py delete mode 100644 neutronclient/tests/functional/adv-svcs/test_readonly_neutron_fwaas.py delete mode 100644 neutronclient/tests/functional/adv-svcs/test_readonly_neutron_vpn.py delete mode 100644 neutronclient/tests/functional/base.py delete mode 100644 neutronclient/tests/functional/core/__init__.py delete mode 100644 neutronclient/tests/functional/core/test_cli_formatter.py delete mode 100644 neutronclient/tests/functional/core/test_clientlib.py delete mode 100644 neutronclient/tests/functional/core/test_common.py delete mode 100644 neutronclient/tests/functional/core/test_purge.py delete mode 100644 neutronclient/tests/functional/core/test_readonly_neutron.py delete mode 100644 neutronclient/tests/functional/core/test_subnet_create.py delete mode 100644 neutronclient/tests/functional/hooks/fwaas delete mode 100755 neutronclient/tests/functional/hooks/gate_hook.sh delete mode 100755 neutronclient/tests/functional/hooks/post_test_hook.sh delete mode 100644 neutronclient/tests/functional/hooks/vpnaas delete mode 100644 neutronclient/tests/unit/bgp/__init__.py delete mode 100644 neutronclient/tests/unit/bgp/test_cli20_dragentscheduler.py delete mode 100644 neutronclient/tests/unit/bgp/test_cli20_peer.py delete mode 100644 neutronclient/tests/unit/bgp/test_cli20_speaker.py delete mode 100644 neutronclient/tests/unit/flavor/__init__.py delete mode 100644 neutronclient/tests/unit/flavor/test_cli20_flavor.py delete mode 100644 neutronclient/tests/unit/flavor/test_cli20_flavor_profile.py delete mode 100644 neutronclient/tests/unit/fw/__init__.py delete mode 100644 neutronclient/tests/unit/fw/test_cli20_firewall.py delete mode 100644 neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py delete mode 100644 neutronclient/tests/unit/fw/test_cli20_firewallrule.py delete mode 100644 neutronclient/tests/unit/lb/__init__.py delete mode 100644 neutronclient/tests/unit/lb/test_cli20_healthmonitor.py delete mode 100644 neutronclient/tests/unit/lb/test_cli20_member.py delete mode 100644 neutronclient/tests/unit/lb/test_cli20_pool.py delete mode 100644 neutronclient/tests/unit/lb/test_cli20_vip.py delete mode 100644 neutronclient/tests/unit/lb/v2/__init__.py delete mode 100644 neutronclient/tests/unit/lb/v2/test_cli20_healthmonitor.py delete mode 100644 neutronclient/tests/unit/lb/v2/test_cli20_l7policy.py delete mode 100644 neutronclient/tests/unit/lb/v2/test_cli20_l7rule.py delete mode 100644 neutronclient/tests/unit/lb/v2/test_cli20_listener.py delete mode 100644 neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py delete mode 100644 neutronclient/tests/unit/lb/v2/test_cli20_member.py delete mode 100644 neutronclient/tests/unit/lb/v2/test_cli20_pool.py delete mode 100644 neutronclient/tests/unit/qos/__init__.py delete mode 100644 neutronclient/tests/unit/qos/test_cli20_bandwidth_limit_rule.py delete mode 100644 neutronclient/tests/unit/qos/test_cli20_dscp_marking_rule.py delete mode 100644 neutronclient/tests/unit/qos/test_cli20_minimum_bandwidth_rule.py delete mode 100644 neutronclient/tests/unit/qos/test_cli20_policy.py delete mode 100644 neutronclient/tests/unit/qos/test_cli20_rule.py delete mode 100644 neutronclient/tests/unit/test_auto_allocated_topology.py delete mode 100644 neutronclient/tests/unit/test_cli20.py delete mode 100644 neutronclient/tests/unit/test_cli20_address_scope.py delete mode 100644 neutronclient/tests/unit/test_cli20_agents.py delete mode 100644 neutronclient/tests/unit/test_cli20_agentschedulers.py delete mode 100644 neutronclient/tests/unit/test_cli20_az.py delete mode 100644 neutronclient/tests/unit/test_cli20_extensions.py delete mode 100644 neutronclient/tests/unit/test_cli20_floatingips.py delete mode 100644 neutronclient/tests/unit/test_cli20_metering.py delete mode 100644 neutronclient/tests/unit/test_cli20_network.py delete mode 100644 neutronclient/tests/unit/test_cli20_network_ip_availability.py delete mode 100644 neutronclient/tests/unit/test_cli20_port.py delete mode 100644 neutronclient/tests/unit/test_cli20_purge.py delete mode 100644 neutronclient/tests/unit/test_cli20_rbac.py delete mode 100644 neutronclient/tests/unit/test_cli20_router.py delete mode 100644 neutronclient/tests/unit/test_cli20_securitygroup.py delete mode 100644 neutronclient/tests/unit/test_cli20_servicetype.py delete mode 100644 neutronclient/tests/unit/test_cli20_subnet.py delete mode 100644 neutronclient/tests/unit/test_cli20_subnetpool.py delete mode 100644 neutronclient/tests/unit/test_cli20_tag.py delete mode 100644 neutronclient/tests/unit/test_client_extension.py delete mode 100644 neutronclient/tests/unit/test_name_or_id.py delete mode 100644 neutronclient/tests/unit/test_quota.py delete mode 100644 neutronclient/tests/unit/test_shell.py delete mode 100644 neutronclient/tests/unit/vpn/__init__.py delete mode 100644 neutronclient/tests/unit/vpn/test_cli20_endpoint_group.py delete mode 100644 neutronclient/tests/unit/vpn/test_cli20_ikepolicy.py delete mode 100644 neutronclient/tests/unit/vpn/test_cli20_ipsec_site_connection.py delete mode 100644 neutronclient/tests/unit/vpn/test_cli20_ipsecpolicy.py delete mode 100644 neutronclient/tests/unit/vpn/test_cli20_vpnservice.py delete mode 100644 neutronclient/tests/unit/vpn/test_utils.py create mode 100644 releasenotes/notes/remove-cli-code-53969e9aa927e530.yaml delete mode 100644 tools/neutron.bash_completion diff --git a/.zuul.yaml b/.zuul.yaml index 7e23f93e8..0bbe8f4dc 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -7,12 +7,6 @@ - lib-forward-testing-python3 - release-notes-jobs-python3 - openstackclient-plugin-jobs - check: - jobs: - - neutronclient-functional - gate: - jobs: - - neutronclient-functional experimental: jobs: - neutronclient-grenade-neutron-lib: @@ -20,52 +14,6 @@ - ^(test-|)requirements.txt$ - ^setup.cfg$ -- job: - name: neutronclient-functional - parent: devstack-tox-functional - irrelevant-files: - - ^.*\.rst$ - - ^doc/.*$ - - ^releasenotes/.*$ - required-projects: - - openstack/python-neutronclient - - openstack/neutron - - openstack/neutron-vpnaas - vars: - tox_envlist: functional - devstack_services: - # NOTE: neutronclient.tests.functional.base.ClientTestBase does not - # support HTTPS endpoints now, so tls-proxy needs to be disabled. - tls-proxy: false - # Disable OVN services - br-ex-tcpdump: false - br-int-flows: false - ovn-controller: false - ovn-northd: false - ovs-vswitchd: false - ovsdb-server: false - q-ovn-metadata-agent: false - # Neutron services - q-agt: true - q-dhcp: true - q-l3: true - q-meta: true - neutron-network-segment-range: true - neutron-segments: true - q-metering: true - q-qos: true - neutron-tag-ports-during-bulk-creation: true - neutron-conntrack-helper: true - devstack_localrc: - USE_PYTHON3: true - LIBS_FROM_GIT: python-neutronclient - Q_AGENT: openvswitch - Q_ML2_TENANT_NETWORK_TYPE: vxlan - Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch - devstack_plugins: - neutron: https://opendev.org/openstack/neutron - neutron-vpnaas: https://opendev.org/openstack/neutron-vpnaas - - job: name: neutronclient-grenade-neutron-lib parent: grenade diff --git a/README.rst b/README.rst index 6f57c698c..a5e5300d6 100644 --- a/README.rst +++ b/README.rst @@ -15,8 +15,7 @@ Python bindings to the Neutron API :alt: Latest Version This is a client library for Neutron built on the Neutron API. It -provides a Python API (the ``neutronclient`` module) and a command-line tool -(``neutron``). +provides a Python API (the ``neutronclient`` module). * License: Apache License, Version 2.0 * `PyPi`_ - package installation diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index 0a7d54d9f..4b1f4720a 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -24,10 +24,9 @@ Using CLI ========= -There are two CLIs which support the Networking API: -`OpenStackClient (OSC) +There is `OpenStackClient (OSC) `__ -and :doc:`neutron CLI ` (deprecated). +which support the Networking API OpenStackClient --------------- @@ -49,15 +48,8 @@ neutron CLI .. warning:: - neutron CLI is now deprecated and will be removed in the future. - Use openstack CLI instead. See `openstack CLI command list + neutron CLI is removed. Use openstack CLI instead. See `openstack CLI command list `__ and :doc:`its extensions for advanced networking services `. The command mapping from neutron CLI to openstack CLI is available `here `__. - -.. toctree:: - :maxdepth: 2 - - neutron CLI guide - neutron CLI reference diff --git a/doc/source/cli/neutron-reference.rst b/doc/source/cli/neutron-reference.rst deleted file mode 100644 index d6640ea0d..000000000 --- a/doc/source/cli/neutron-reference.rst +++ /dev/null @@ -1,48 +0,0 @@ -.. - 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. - - - Convention for heading levels in Neutron devref: - ======= Heading 0 (reserved for the title in a document) - ------- Heading 1 - ~~~~~~~ Heading 2 - +++++++ Heading 3 - ''''''' Heading 4 - (Avoid deeper levels because they do not render well.) - -===================== -neutron CLI reference -===================== - -.. warning:: - - neutron CLI is now deprecated and will be removed in the future. - Use openstack CLI instead. See `openstack CLI command list - `__ - and :doc:`its extensions for advanced networking services `. - The command mapping from neutron CLI to openstack CLI is available - `here `__. - -neutron usage -------------- - -.. autoprogram-cliff:: neutronclient.shell.NeutronShell - :application: neutron - :arguments: 2.0 - -neutron API v2.0 commands -------------------------- - -.. autoprogram-cliff:: neutron.cli.v2 - :application: neutron - diff --git a/doc/source/cli/neutron.rst b/doc/source/cli/neutron.rst deleted file mode 100644 index 7ca652771..000000000 --- a/doc/source/cli/neutron.rst +++ /dev/null @@ -1,412 +0,0 @@ -.. - 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. - - - Convention for heading levels in Neutron devref: - ======= Heading 0 (reserved for the title in a document) - ------- Heading 1 - ~~~~~~~ Heading 2 - +++++++ Heading 3 - ''''''' Heading 4 - (Avoid deeper levels because they do not render well.) - -Using neutron CLI -================= - -The **neutron** shell utility interacts with OpenStack Networking API from the -command-line. It supports the entire features of OpenStack Networking API. - -.. warning:: - - neutron CLI is now deprecated and will be removed in the future. - Use openstack CLI instead. See `openstack CLI command list - `__ - and :doc:`its extensions for advanced networking services `. - The command mapping from neutron CLI to openstack CLI is available - `here `__. - -Basic Usage ------------ - -In order to use the CLI, you must provide your OpenStack username, password, -project, domain information for both user and project, and auth endpoint. Use -the corresponding configuration options (``--os-username``, ``--os-password``, -``--os-project-name``, ``--os-user-domain-id``, ``os-project-domain-id``, and -``--os-auth-url``), but it is easier to set them in environment variables. - -.. code-block:: shell - - export OS_USERNAME=user - export OS_PASSWORD=pass - export OS_PROJECT_NAME=project - export OS_USER_DOMAIN_ID=default - export OS_PROJECT_DOMAIN_ID=default - export OS_AUTH_URL=http://auth.example.com:5000/v3 - -If you are using Identity v2.0 API (DEPRECATED), you don't need to pass domain -information. - -.. code-block:: shell - - export OS_USERNAME=user - export OS_PASSWORD=pass - export OS_TENANT_NAME=tenant - export OS_AUTH_URL=http://auth.example.com:5000/v2.0 - -Once you've configured your authentication parameters, you can run **neutron** -commands. All commands take the form of: - -.. code-block:: none - - neutron [arguments...] - -Run **neutron help** to get a full list of all possible commands, and run -**neutron help ** to get detailed help for that command. - -Using with os-client-config -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -`os-client-config `_ -provides more convenient way to manage a collection of client configurations -and you can easily switch multiple OpenStack-based configurations. - -To use os-client-config, you first need to prepare -``~/.config/openstack/clouds.yaml`` like the following. - -.. code-block:: yaml - - clouds: - devstack: - auth: - auth_url: http://auth.example.com:5000 - password: your-secret - project_domain_id: default - project_name: demo - user_domain_id: default - username: demo - identity_api_version: '3' - region_name: RegionOne - devstack-admin: - auth: - auth_url: http://auth.example.com:35357 - password: another-secret - project_domain_id: default - project_name: admin - user_domain_id: default - username: admin - identity_api_version: '3' - region_name: RegionOne - -Then, you need to specify a configuration name defined in the above clouds.yaml. - -.. code-block:: shell - - export OS_CLOUD=devstack - -For more detail information, see the -`os-client-config `_ -documentation. - -Using with keystone token -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The command-line tool will attempt to re-authenticate using your provided -credentials for every request. You can override this behavior by manually -supplying an auth token using ``--os-url`` and ``--os-auth-token``. You can -alternatively set these environment variables. - -.. code-block:: shell - - export OS_URL=http://neutron.example.org:9696/ - export OS_TOKEN=3bcc3d3a03f44e3d8377f9247b0ad155 - -Using noauth mode -~~~~~~~~~~~~~~~~~ - -If neutron server does not require authentication, besides these two arguments -or environment variables (We can use any value as token.), we need manually -supply ``--os-auth-strategy`` or set the environment variable. - -.. code-block:: shell - - export OS_AUTH_STRATEGY=noauth - -Display options ---------------- - -Filtering -~~~~~~~~~ - -Neutron API supports filtering in the listing operation. -**neutron** CLI supports this feature too. - -To specify a filter in ``*-list`` command, you need to pass a pair of an -attribute name and an expected value with the format of ``-- ``. -The example below retrieves ports owned by compute instances. - -.. code-block:: console - - $ neutron port-list --device_owner network:dhcp - +--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------------------------------+ - | id | name | mac_address | fixed_ips | - +--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------------------------------+ - | 8953d683-29ad-4be3-b73f-060727c7849b | | fa:16:3e:4b:9e:0a | {"subnet_id": "6b832dfe-f271-443c-abad-629961414a73", "ip_address": "10.0.0.2"} | - | | | | {"subnet_id": "cdcc616b-0cff-482f-96f5-06fc63d21247", "ip_address": "fd12:877c:1d66:0:f816:3eff:fe4b:9e0a"} | - +--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------------------------------+ - -You can also specify multiple filters. -The example below retrieves security group rules applied to IPv4 traffic -which belongs to a security group bfa493f9-2b03-46d2-8399-b9b038a53bc1. - -.. code-block:: console - - $ neutron security-group-rule-list --security-group-id bfa493f9-2b03-46d2-8399-b9b038a53bc1 --ethertype IPv4 - +--------------------------------------+----------------+-----------+-----------+---------------+-----------------+ - | id | security_group | direction | ethertype | protocol/port | remote | - +--------------------------------------+----------------+-----------+-----------+---------------+-----------------+ - | 65489805-0400-4bce-9bd9-16a81952263c | default | egress | IPv4 | any | any | - | 9429f336-4947-4643-bbd9-24528cc65648 | default | ingress | IPv4 | any | default (group) | - +--------------------------------------+----------------+-----------+-----------+---------------+-----------------+ - -.. note:: - - Looking up UUID from name is not supported when specifying a filter. - You need to use UUID to specify a specific resource. - -.. note:: - - Filtering for dictionary or list attributes is not supported. - -Changing displayed columns -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you want displayed columns in a list operation, ``-c`` option can be used. -``-c`` can be specified multiple times and the column order will be same as -the order of ``-c`` options. - -.. code-block:: console - - $ neutron port-list -c id -c device_owner -c fixed_ips - +--------------------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------+ - | id | device_owner | fixed_ips | - +--------------------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------+ - | 41ca1b9b-4bbd-4aa8-bcaa-31d3d5704205 | network:router_interface | {"subnet_id": "6b832dfe-f271-443c-abad-629961414a73", "ip_address": "10.0.0.1"} | - | 8953d683-29ad-4be3-b73f-060727c7849b | network:dhcp | {"subnet_id": "6b832dfe-f271-443c-abad-629961414a73", "ip_address": "10.0.0.2"} | - | | | {"subnet_id": "cdcc616b-0cff-482f-96f5-06fc63d21247", "ip_address": "fd12:877c:1d66:0:f816:3eff:fe4b:9e0a"} | - | a9da29f8-4504-4526-a5ce-cd3624fbd173 | neutron:LOADBALANCER | {"subnet_id": "6b832dfe-f271-443c-abad-629961414a73", "ip_address": "10.0.0.3"} | - | | | {"subnet_id": "cdcc616b-0cff-482f-96f5-06fc63d21247", "ip_address": "fd12:877c:1d66:0:f816:3eff:feb1:ab71"} | - | d6a1ff96-0a99-416f-a4d6-65d9614cf64e | compute:nova | {"subnet_id": "6b832dfe-f271-443c-abad-629961414a73", "ip_address": "10.0.0.4"} | - | | | {"subnet_id": "cdcc616b-0cff-482f-96f5-06fc63d21247", "ip_address": "fd12:877c:1d66:0:f816:3eff:fe2c:348e"} | - | f4789225-26d0-409f-8047-82d2c7a87a95 | network:router_interface | {"subnet_id": "cdcc616b-0cff-482f-96f5-06fc63d21247", "ip_address": "fd12:877c:1d66::1"} | - +--------------------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------+ - -.. _cli_extra_arguments: - -Extra arguments for create/update operation -------------------------------------------- - -**neutron** CLI has a mechanism called the *extra arguments* for ``*-create`` -and ``*-update`` commands. It allows users to specify a set of *unknown -options* which are not defined as options and not shown in the help text. -**Unknown options MUST be placed at the end of the command line.** -*unknown options* will be directly passed to the API layer. By this mechanism, -you can pass an attribute which is not defined in the upstream **neutron** -CLI. For example, when you are developing a new feature which add a new -attribute to an existing resource, it is useful because we can test your -feature without changing the existing neutron CLI. - -For example, if you run the following command:: - - neutron resource-update --key1 value1 --key2 value2 - -where ``resource`` is some resource name and ``--key1`` and ``--key2`` are -unknown options, then the following JSON will be sent to the neutron API:: - - PUT /v2.0/resources/ - - { - "resource": { - "key2": "value2", - "key1": "value1" - } - } - -Key interpretation -~~~~~~~~~~~~~~~~~~ - -This means an option name (``--key1`` in this case) must be one of valid -resources of a corresponding resource. An option name ``--foo_bar`` is -recognized as an attribute name ``foo_bar``. ``--foo-bar`` is also interpreted -as an attribute name ``foo_bar``. - -Value interpretation -~~~~~~~~~~~~~~~~~~~~ - -By default, if the number of values is 1, the option value is interpreted as a -string and is passed to the API layer as specified in a command-line. - -If the number of values is greater than 1, the option value is interpreted as a -list and the result in the API layer will be same as when specifying a list as -described below. - - neutron resource-update --key1 val1 val2 val3 --key2 val4 - -In the above example, a value of ``key1`` is interpreted as -``["val1", "val2", "val3"]`` and a value of ``key2`` is interpreted -as ``val4``. - -The extra argument mechanism supports more complex value like a list or a dict. - -Specify a list value -++++++++++++++++++++ - -A command-line:: - - neutron resource-update --key list=true val1 val2 val3 - -will send the following in the API layer:: - - { - "key": [ - "val1", - "val2", - "val3" - ] - } - -.. note:: - - If you want to specify a list value, it is recommended to specify - ``list=true``. When ``list=true`` is specified, specified values are - interpreted as a list even regardless of the number of values. - - If ``list=true`` is not specified, specified values are interpreted - depends on the number of values how. If the number of values is more than 2, - the specified values are interpreted as a list. If 1, the value - is interpreted as a string. - -Specify a dict value -++++++++++++++++++++ - -A command-line:: - - neutron resource-update --key type=dict key1=val1,key2=val2,key3=val3 - -will send the following in the API layer:: - - { - "key": { - "key1": "val1", - "key2": "val2", - "key3": "val3" - } - } - -.. note:: - - ``type=bool True/False`` and ``type=int 10`` are also supported. - -Specify a list of dicts -+++++++++++++++++++++++ - -A command-line:: - - neutron resource-update --key type=dict list=true key1=val1 key2=val2 key3=val3 - -will send the following in the API layer:: - - { - "key": [ - {"key1": "val1"}, - {"key2": "val2"}, - {"key3": "val3"} - ] - } - -Passing None as a value -~~~~~~~~~~~~~~~~~~~~~~~ - -There is a case where we would like to pass ``None`` (``null`` in JSON) -in the API layer. To do this:: - - neutron resource-update --key action=clear - -The following body will be in the API layer:: - - {"key": null} - -.. note:: - - If ``action=clear`` is specified, ``list=true`` or ``type=dict`` is ignored. - It means when ``action=clear`` is specified ``None`` is always sent. - -Debugging ---------- - -Display API-level communication -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``-v`` (or ``--verbose``, ``--debug``) option displays a detail interaction -with your neutron server. It is useful to debug what happens in the API level. - -Here is an sample output of ``net-show`` command. - -The first line show what parameters are recognized by neutronclient. -It is sometimes useful to check if command-line parameters you specify are recognized properly. - -.. code-block:: console - - $ neutron -v net-show mynetwork - DEBUG: neutronclient.neutron.v2_0.network.ShowNetwork get_data(Namespace(columns=[], fields=[], formatter='table', id=u'mynetwork', max_width=0, noindent=False, prefix='', request_format='json', show_details=False, variables=[])) - -Next, neutronclient sends an authentication request to keystone to get a token -which is used in further operations. - -.. code-block:: console - - DEBUG: keystoneauth.session REQ: curl -g -i -X GET http://172.16.18.47:5000 -H "Accept: application/json" -H "User-Agent: keystoneauth1" - DEBUG: keystoneauth.session RESP: [300] Content-Length: 593 Vary: X-Auth-Token Keep-Alive: timeout=5, max=100 Server: Apache/2.4.7 (Ubuntu) Connection: Keep-Alive Date: Fri, 27 Nov 2015 20:10:54 GMT Content-Type: application/json - RESP BODY: {"versions": {"values": [{"status": "stable", "updated": "2015-03-30T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v3+json"}], "id": "v3.4", "links": [{"href": "http://172.16.18.47:5000/v3/", "rel": "self"}]}, {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{"href": "http://172.16.18.47:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}]}} - - DEBUG: keystoneauth.identity.v3.base Making authentication request to http://172.16.18.47:5000/v3/auth/tokens - -Neutronclient looks up a network ID corresponding to a given network name. - -.. code-block:: console - - DEBUG: keystoneauth.session REQ: curl -g -i -X GET http://172.16.18.47:9696/v2.0/networks.json?fields=id&name=mynetwork -H "User-Agent: python-neutronclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}39300e7398d53a02afd183f13cb6afaef95ec4e5" - DEBUG: keystoneauth.session RESP: [200] Date: Fri, 27 Nov 2015 20:10:55 GMT Connection: keep-alive Content-Type: application/json; charset=UTF-8 Content-Length: 62 X-Openstack-Request-Id: req-ccebf6e4-4f52-4874-a1ab-5499abcba378 - RESP BODY: {"networks": [{"id": "3698d3c7-d581-443e-bf86-53c4e3a738f7"}]} - -Finally, neutronclient retrieves a detail of a given network using the resolved ID. - -.. code-block:: console - - DEBUG: keystoneauth.session REQ: curl -g -i -X GET http://172.16.18.47:9696/v2.0/networks/3698d3c7-d581-443e-bf86-53c4e3a738f7.json -H "User-Agent: python-neutronclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}39300e7398d53a02afd183f13cb6afaef95ec4e5" - DEBUG: keystoneauth.session RESP: [200] Date: Fri, 27 Nov 2015 20:10:55 GMT Connection: keep-alive Content-Type: application/json; charset=UTF-8 Content-Length: 272 X-Openstack-Request-Id: req-261add00-d6d3-4ea7-becc-105b60ac7369 - RESP BODY: {"network": {"status": "ACTIVE", "subnets": [], "name": "mynetwork", "admin_state_up": true, "tenant_id": "8f0ebf767043483a987736c8c684178d", "mtu": 0, "router:external": false, "shared": false, "port_security_enabled": true, "id": "3698d3c7-d581-443e-bf86-53c4e3a738f7"}} - - +-----------------------+--------------------------------------+ - | Field | Value | - +-----------------------+--------------------------------------+ - | admin_state_up | True | - | id | 3698d3c7-d581-443e-bf86-53c4e3a738f7 | - | mtu | 0 | - | name | mynetwork | - | port_security_enabled | True | - | router:external | False | - | shared | False | - | status | ACTIVE | - | subnets | | - | tenant_id | 8f0ebf767043483a987736c8c684178d | - +-----------------------+--------------------------------------+ diff --git a/doc/source/contributor/cli_option_guideline.rst b/doc/source/contributor/cli_option_guideline.rst deleted file mode 100644 index 49a840525..000000000 --- a/doc/source/contributor/cli_option_guideline.rst +++ /dev/null @@ -1,263 +0,0 @@ -.. - 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. - - - Convention for heading levels in Neutron devref: - ======= Heading 0 (reserved for the title in a document) - ------- Heading 1 - ~~~~~~~ Heading 2 - +++++++ Heading 3 - ''''''' Heading 4 - (Avoid deeper levels because they do not render well.) - -CLI Option Guideline -==================== - -This document describes the conventions of neutron CLI options. - -General conventions -------------------- - -#. Option names should be delimited by a hyphen instead of a underscore. - This is the common guidelines across all OpenStack CLIs. - - * Good: ``--ip-version`` - * Not Good: ``--ip_version`` - -#. Use at least one required option for ``*-create`` command. If all options - are optional, we typically use ``name`` field as a required option. - -#. When you need to specify an ID of a resource, it is better to provide - another way to specify the resource like ``name`` or other reasonable field. - -#. If an attribute name in API is ``foo_id``, the corresponding option - should be ``--foo`` instead of ``--foo-id``. - - * It is because we usually support ID and ``name`` to specify a resource. - -#. Do not use ``nargs='?'`` without a special reason. - - * The behavior of ``nargs='?'`` option for python argparse is - bit tricky and may lead to unexpected option parsing different - from the help message. The detail is described in the - :ref:`Background section ` below. - -#. (option) Avoid using positional options as much as possible. - - * Positional arguments should be limited to attributes which will - be required in the long future. - -#. We honor existing options and should keep compatibilities when adding or - changing options. - -Options for boolean value -------------------------- - -Use the form of ``--option-name {True|False}``. - -* For a new option, it is recommended. -* It is suggested to use ``common.utils.add_boolean_argument`` in an - implementation. It allows ``true``/``false`` in addition to ``True``/``False``. -* For existing options, migration to the recommended form is not necessarily - required. All backward-compatibility should be kept without reasonable - reasons. - -Options for dict value ----------------------- - -Some API attributes take a dictionary. - -``--foo key1=val1,key2=val2`` is usually used. - -This means ``{"key1": "val1", "key2": "val2"}`` is passed in the API layer. - -Examples: - -* ``--host-route destination=CIDR,nexthop=IP_ADDR`` for a subnet -* ``--fixed-ip subnet_id=SUBNET,ip_address=IP_ADDR`` for a port. - -Options for list value ----------------------- - -Some attributes take a list. - -In this case, we usually use: - -* Define an option per element (Use a singular form as an option name) -* Allow to specify the option multiple times - -For Example, **port-create** has ``--security-group`` option. -``--security-group SG1 --security-group SG2`` generates -``{"security_groups: ["SG1", "SG2"]}`` in the API layer. - -This convention applies to a case of a list of dict. -``--allocation-pool`` and ``--host-route`` for a subnet are examples. - -Compatibility with extra arguments ----------------------------------- - -*extra arguments* supports various types of option specifications. -At least the following patterns needs to be considered when defining -a new option. For more detail, see :ref:`cli_extra_arguments`. - -* Normal options with value -* Boolean options : ``--foo True``, ``--bar=False`` -* List options : ``--bars list=true val1 val2``, ``--bars val1 val2`` -* Dict options : ``--foo type=dict key1=va1,key2=val2`` -* List of Dict options : ``--bars list=true type=dict key1=val1,key2=val2 key3=val3,key4=val4`` -* ``action=clear`` - -For normal options with value, there are four patterns to specify an option -as extra arguments. - -* ``--admin-state-up True`` (a space between option name and value) -* ``--admin-state-up=True`` (= between option name and value) -* ``--admin_state_up True`` (underscore is used as delimiter) -* ``--admin_state_up=True`` (underscore is used as delimiter) - -.. _background: - -Background ----------- - -There are a lot of opinions on which form of options are better or not. -This section tries to capture the reason of the current choice. - -Use at least one required option -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As a convention, **neutron** CLI requires one required argument. - -If all options are optional in the API level and we have ``name`` field, -we usually use ``name`` as a required parameter. -Requiring at least one argument has the following benefits: - -* If we run ``neutron *-create`` without a required argument, we will have a - brief help message without detail option help. It is convenient. -* We can avoid miss operation by just hitting ``neutron *-create``. - Requiring at least one parameter is a good balance. - -Even though we can change this convention to allow to create a resource -without ``name`` field, it will bring confusions to existing users. - -There may be opinion that it is inconsistent with API level requirement -or Horizon behavior, but even if neutron CLI requires ``name`` field -there is no bad impact on regular users. Considering possible confusion -if we change it, it looks better to keep it as-is. - -Options for Boolean value -~~~~~~~~~~~~~~~~~~~~~~~~~ - -* ``--enable-foo``/``--disable-foo`` or similar patterns (including - ``--admin-state-down``) is not suggested because we need two exclusive - options for one attribute in REST API. It is meaningless. - -* It is not recommended to have an option only to specify non-default value. - For example, we have ``--shared`` or ``--admin-state-down`` options for - net-create. This form only works for ``*-create`` and does not work for - ``*-update``. It leads to having different options for ``*-create`` and - ``*-update``. - -* A flag option like ``--enable-dhcp`` (without value) also has a problem when - considering the compatibility with *extra argument*. We can specify - ``-enable-dhcp True/False`` or ``--enable-dhcp=True/False`` in the *extra - argument* mechanism. If we introduce ``--enable-dhcp`` (without value), - the form of ``-enable-dhcp True/False`` cannot be used now. - This is another reason we don't use a flag style option for a boolean parameter. - -.. _background-nargs: - -Avoid using nargs in positional or optional arguments -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The behavior of ``nargs='?'`` option for python argparse is bit tricky. -When we use ``nargs='?'`` and if the order of command-line options is -changed then the command-line parser may fail to parse the arguments -correctly. Two examples of such failures are provided below. - -Example 1: -This example shows how the actual behavior can differ from the provided -help message. In the below block, help message at ``[5]`` says ``--bb CC`` -is a valid format but the argument parsing for the same format fails at ``[7]``. - -.. code-block:: console - - In [1]: import argparse - In [2]: parser = argparse.ArgumentParser() - In [3]: parser.add_argument('--bb', nargs='?') - In [4]: parser.add_argument('cc') - - In [5]: parser.print_help() - usage: ipython [-h] [--bb [BB]] cc - - positional arguments: - cc - - optional arguments: - -h, --help show this help message and exit - --bb [BB] - - In [6]: parser.parse_args('--bb 1 X'.split()) - Out[6]: Namespace(bb='1', cc='X') - - In [7]: parser.parse_args('--bb X'.split()) - usage: ipython [-h] [--bb [BB]] cc - ipython: error: too few arguments - An exception has occurred, use %tb to see the full traceback. - - SystemExit: 2 - - -Example 2: -This example shows how fragile ``nargs='?'`` can be when user specifies -options in different order from the help message. - -.. code-block:: console - - In [1]: import argparse - In [2]: parser = argparse.ArgumentParser() - In [3]: parser.add_argument('--a', help='option a') - In [4]: parser.add_argument('--b', help='option b') - In [5]: parser.add_argument('x', help='positional arg X') - In [6]: parser.add_argument('y', nargs='?', help='positional arg Y') - In [7]: parser.print_help() - usage: ipython [-h] [--a A] [--b B] x [y] - - positional arguments: - x positional arg X - y positional arg Y - - optional arguments: - -h, --help show this help message and exit - --a A option a - --b B option b - - In [8]: parser.parse_args('--a 1 --b 2 X Y'.split()) - Out[8]: Namespace(a='1', b='2', x='X', y='Y') - - In [9]: parser.parse_args('X Y --a 1 --b 2'.split()) - Out[9]: Namespace(a='1', b='2', x='X', y='Y') - - In [10]: parser.parse_args('X --a 1 --b 2 Y'.split()) - usage: ipython [-h] [--a A] [--b B] x [y] - ipython: error: unrecognized arguments: Y - An exception has occurred, use %tb to see the full traceback. - - SystemExit: 2 - - To exit: use 'exit', 'quit', or Ctrl-D. - To exit: use 'exit', 'quit', or Ctrl-D. - -Note: Most CLI users don't care about the order of the command-line -options. Hence, such fragile behavior should be avoided. - diff --git a/doc/source/contributor/client_command_extensions.rst b/doc/source/contributor/client_command_extensions.rst deleted file mode 100644 index 4b74cdf77..000000000 --- a/doc/source/contributor/client_command_extensions.rst +++ /dev/null @@ -1,97 +0,0 @@ -.. - 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. - - - Convention for heading levels in Neutron devref: - ======= Heading 0 (reserved for the title in a document) - ------- Heading 1 - ~~~~~~~ Heading 2 - +++++++ Heading 3 - ''''''' Heading 4 - (Avoid deeper levels because they do not render well.) - -Client command extension support -================================= - -The client command extension adds support for extending the neutron client while -considering ease of creation. -Extensions strongly conform to preexisting neutron commands (/neutron/v2_0/). - -A sample extension can be seen at: -neutronclient/neutron/v2_0/contrib/_fox_sockets.py - -Minimum requirements from an extension --------------------------------------- - -* NeutronClientExtension subclasses must have a shell_command class variable - if the command is to be available to the CLI (shell.py) - - Example: neutronclient.neutron.v2_0.contrib._fox_sockets.FoxInSocketsList - -Minimum requirements to use canonical neutron CRUD commands framework ----------------------------------------------------------------------- - -Neutron commands are cliff commands, commands in extension can use their -own way to finish their tasks. But if they want to make use of the canonical -neutron CRUD commands framework, the extension should: - -* have a class that subclasses NeutronClientExtension to provide the - requisite resource name, version support, and resource collection and - object paths for a resource the commands will process. - - Example: neutronclient.neutron.v2_0.contrib._fox_sockets.FoxInSocket - -* have a class that subclasses from the ClientExtensionList to provide - resource object list function. This is because most commands - need the list function to get object ID via - neutronclient.neutron.v2_0.__init__.find_resource_by_id. - - Example: neutronclient.neutron.v2_0.contrib._fox_sockets.FoxInSocketsList - -* if needed, subclass ClientExtensionUpdate to implement update of the resource - object. - - Example: neutronclient.neutron.v2_0.contrib._fox_sockets.FoxInSocketsUpdate - -* if needed, subclass ClientExtensionDelete to implement deletion of the resource - object. - - Example: neutronclient.neutron.v2_0.contrib._fox_sockets.FoxInSocketsDelete - -* if needed, subclass ClientExtensionShow to get the detail of the resource - object. - - Example: neutronclient.neutron.v2_0.contrib._fox_sockets.FoxInSocketsShow - -Precedence of command loading ------------------------------- - -* hard coded commands are loaded first -* external commands (installed in the environment) are loaded then - -Commands that have the same name will be overwritten by commands that are -loaded later. To change the execution of a command for your particular -extension you only need to override the execute method. - -Currently this extension support is limited to top-level resources. -Parent/child relationships may be added if desired. - -neutronclient.extension entry_point ------------------------------------ - -To activate the commands in a specific extension module, add an entry in -setup.cfg under neutronclient.extension. For example:: - - [entry_points] - neutronclient.extension = - fox_sockets = neutronclient.neutron.v2_0.contrib._fox_sockets diff --git a/doc/source/contributor/index.rst b/doc/source/contributor/index.rst index f2150b0e0..fae3f6b82 100644 --- a/doc/source/contributor/index.rst +++ b/doc/source/contributor/index.rst @@ -31,6 +31,4 @@ OpenStack client. .. toctree:: :maxdepth: 2 - client_command_extensions - cli_option_guideline transition_to_osc diff --git a/doc/source/contributor/transition_to_osc.rst b/doc/source/contributor/transition_to_osc.rst index 334f2e57e..9bb952902 100644 --- a/doc/source/contributor/transition_to_osc.rst +++ b/doc/source/contributor/transition_to_osc.rst @@ -105,7 +105,7 @@ Transition Steps In addition, no new features will be added to the CLI, though fixes to the CLI will be assessed on a case by case basis. -8. **Not Started:** Remove the ``neutron`` CLI after two deprecation cycles +8. **Done** Remove the ``neutron`` CLI after two deprecation cycles once the criteria below have been met. * The networking support provide by the ``openstack`` CLI is functionally @@ -122,32 +122,8 @@ Transition Steps Developer Guide --------------- -The ``neutron`` CLI version 6.x, without extensions, supports over 200 -commands while the ``openstack`` CLI version 3.3.0 supports over 70 -networking commands. Of the 70 commands, some do not have all of the options -or arguments of their ``neutron`` CLI equivalent. With this large functional -gap, a few critical questions for developers during this transition are "Which -CLI do I change?", "Where does my CLI belong?", and "Which Python library do I change?" -The answer depends on the state of a command and the state of the overall transition. -Details are outlined in the tables below. Early stages of the transition will require -dual maintenance. - -**Which CLI do I change?** - -+----------------------+------------------------+-------------------------------------------------+ -| ``neutron`` Command | ``openstack`` Command | CLI to Change | -+======================+========================+=================================================+ -| Exists | Doesn't Exist | ``neutron`` | -+----------------------+------------------------+-------------------------------------------------+ -| Exists | In Progress | ``neutron`` and ``openstack`` | -| | | (update related blueprint or bug) | -+----------------------+------------------------+-------------------------------------------------+ -| Exists | Exists | ``openstack`` | -| | | (assumes command parity resulting in | -| | | ``neutron`` being deprecated) | -+----------------------+------------------------+-------------------------------------------------+ -| Doesn't Exist | Doesn't Exist | ``openstack`` | -+----------------------+------------------------+-------------------------------------------------+ +The ``neutron`` CLI tool is now removed and all new CLI changes should be done +in the ``OpenStackClient (OSC)`` and, if needed, also in the ``OpenStack SDK``. **Where does my CLI belong?** @@ -186,8 +162,6 @@ is not required as the neutronclient is already deprecated on its own. +=================================================+===============================================+ | python-openstackclient | openstacksdk | +-------------------------------------------------+-----------------------------------------------+ -| python-neutronclient | python-neutronclient | -+-------------------------------------------------+-----------------------------------------------+ | Other | Applicable project owning network resource | +-------------------------------------------------+-----------------------------------------------+ diff --git a/doc/source/index.rst b/doc/source/index.rst index 64ad45ab4..c36d482ed 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -24,15 +24,11 @@ python-neutronclient documentation ================================== This is a client for OpenStack Networking API. It provides -:doc:`Python API bindings ` (the neutronclient module) and -:doc:`command-line interface (CLI) `. +:doc:`Python API bindings ` (the neutronclient module). -There are two CLIs which support the Networking API: -:doc:`neutron CLI ` and +There is `OpenStack Client (OSC) `__. -OpenStack Client provides the basic network commands and -python-neutronclient provides extensions (aka OSC plugins) -for advanced networking services. +CLI which support the Networking API. User Documentation ------------------ diff --git a/neutron_test.sh b/neutron_test.sh deleted file mode 100755 index d6dc75409..000000000 --- a/neutron_test.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/bash -set -x -function die() { - local exitcode=$? - set +o xtrace - echo $@ - cleanup - exit $exitcode -} - -net_name=mynet1 -subnet_name=mysubnet1 -port_name=myport1 -function cleanup() { - echo Removing test port, subnet and net... - neutron port-delete $port_name - neutron subnet-delete $subnet_name - neutron net-delete $net_name -} - -noauth_tenant_id=me -if [ "$1" == "noauth" ]; then - NOAUTH="--tenant_id $noauth_tenant_id" -else - NOAUTH= -fi - -echo "NOTE: User should be admin in order to perform all operations." -sleep 3 - -# test the CRUD of network -network=$net_name -neutron net-create $NOAUTH $network || die "fail to create network $network" -temp=`neutron net-list -- --name $network --fields id | wc -l` -echo $temp -if [ $temp -ne 5 ]; then - die "networks with name $network is not unique or found" -fi -network_id=`neutron net-list -- --name $network --fields id | tail -n 2 | head -n 1 | cut -d' ' -f 2` -echo "ID of network with name $network is $network_id" - -neutron net-show $network || die "fail to show network $network" -neutron net-show $network_id || die "fail to show network $network_id" - -neutron net-update $network --admin_state_up False || die "fail to update network $network" -neutron net-update $network_id --admin_state_up True || die "fail to update network $network_id" - -neutron net-list -c id -- --id fakeid || die "fail to list networks with column selection on empty list" - -# test the CRUD of subnet -subnet=$subnet_name -cidr=10.0.1.0/24 -neutron subnet-create $NOAUTH $network $cidr --name $subnet || die "fail to create subnet $subnet" -tempsubnet=`neutron subnet-list -- --name $subnet --fields id | wc -l` -echo $tempsubnet -if [ $tempsubnet -ne 5 ]; then - die "subnets with name $subnet is not unique or found" -fi -subnet_id=`neutron subnet-list -- --name $subnet --fields id | tail -n 2 | head -n 1 | cut -d' ' -f 2` -echo "ID of subnet with name $subnet is $subnet_id" -neutron subnet-show $subnet || die "fail to show subnet $subnet" -neutron subnet-show $subnet_id || die "fail to show subnet $subnet_id" - -neutron subnet-update $subnet --dns_nameservers list=true 1.1.1.11 1.1.1.12 || die "fail to update subnet $subnet" -neutron subnet-update $subnet_id --dns_nameservers list=true 2.2.2.21 2.2.2.22 || die "fail to update subnet $subnet_id" - -# test the crud of ports -port=$port_name -neutron port-create $NOAUTH $network --name $port || die "fail to create port $port" -tempport=`neutron port-list -- --name $port --fields id | wc -l` -echo $tempport -if [ $tempport -ne 5 ]; then - die "ports with name $port is not unique or found" -fi -port_id=`neutron port-list -- --name $port --fields id | tail -n 2 | head -n 1 | cut -d' ' -f 2` -echo "ID of port with name $port is $port_id" -neutron port-show $port || die "fail to show port $port" -neutron port-show $port_id || die "fail to show port $port_id" -neutron port-update $port --device_id deviceid1 || die "fail to update port $port" -neutron port-update $port_id --device_id deviceid2 || die "fail to update port $port_id" -neutron port-update $port_id --allowed-address-pair ip_address=1.1.1.11,mac_address=10:00:00:00:00:00 --allowed-address-pair ip_address=1.1.1.12,mac_address=10:00:00:00:00:01 || die "fail to update port $port_id --allowed-address-pair" -neutron port-show $port || die "fail to show port $port" -neutron port-show $port_id || die "fail to show port $port_id" -neutron port-update $port_id --no-allowed-address-pairs || die "fail to update port $port_id --no-allowed-address-pairs" -neutron port-show $port || die "fail to show port $port" -neutron port-show $port_id || die "fail to show port $port_id" -neutron port-delete $port_id - -# test the create port with allowed-address-pairs -port=$port_name -neutron port-create $NOAUTH $network --name $port -- --allowed-address-pairs type=dict list=true ip_address=1.1.1.11,mac_address=10:00:00:00:00:00 ip_address=1.1.1.12,mac_address=10:00:00:00:00:01 || die "fail to create port $port" -tempport=`neutron port-list -- --name $port --fields id | wc -l` -echo $tempport -if [ $tempport -ne 5 ]; then - die "ports with name $port is not unique or found" -fi -port_id=`neutron port-list -- --name $port --fields id | tail -n 2 | head -n 1 | cut -d' ' -f 2` -echo "ID of port with name $port is $port_id" -neutron port-show $port || die "fail to show port $port" -neutron port-show $port_id || die "fail to show port $port_id" -neutron port-update $port_id --no-allowed-address-pairs || die "fail to update port $port_id --no-allowed-address-pairs" -neutron port-show $port_id - -# test quota commands RUD -DEFAULT_NETWORKS=10 -DEFAULT_PORTS=50 -tenant_id=tenant_a -tenant_id_b=tenant_b -neutron quota-update --tenant_id $tenant_id --network 30 || die "fail to update quota for tenant $tenant_id" -neutron quota-update --tenant_id $tenant_id_b --network 20 || die "fail to update quota for tenant $tenant_id" -networks=`neutron quota-list -c network -c tenant_id | grep $tenant_id | awk '{print $2}'` -if [ $networks -ne 30 ]; then - die "networks quota should be 30" -fi -networks=`neutron quota-list -c network -c tenant_id | grep $tenant_id_b | awk '{print $2}'` -if [ $networks -ne 20 ]; then - die "networks quota should be 20" -fi -networks=`neutron quota-show --tenant_id $tenant_id | grep network | awk -F'|' '{print $3}'` -if [ $networks -ne 30 ]; then - die "networks quota should be 30" -fi -neutron quota-delete --tenant_id $tenant_id || die "fail to delete quota for tenant $tenant_id" -networks=`neutron quota-show --tenant_id $tenant_id | grep network | awk -F'|' '{print $3}'` -if [ $networks -ne $DEFAULT_NETWORKS ]; then - die "networks quota should be $DEFAULT_NETWORKS" -fi -# update self -if [ "t$NOAUTH" = "t" ]; then - # with auth - neutron quota-update --port 99 || die "fail to update quota for self" - ports=`neutron quota-show | grep port | awk -F'|' '{print $3}'` - if [ $ports -ne 99 ]; then - die "ports quota should be 99" - fi - - ports=`neutron quota-list -c port | grep 99 | awk '{print $2}'` - if [ $ports -ne 99 ]; then - die "ports quota should be 99" - fi - neutron quota-delete || die "fail to delete quota for tenant self" - ports=`neutron quota-show | grep port | awk -F'|' '{print $3}'` - if [ $ports -ne $DEFAULT_PORTS ]; then - die "ports quota should be $DEFAULT_PORTS" - fi -else - # without auth - neutron quota-update --port 100 - if [ $? -eq 0 ]; then - die "without valid context on server, quota update command should fail." - fi - neutron quota-show - if [ $? -eq 0 ]; then - die "without valid context on server, quota show command should fail." - fi - neutron quota-delete - if [ $? -eq 0 ]; then - die "without valid context on server, quota delete command should fail." - fi - neutron quota-list || die "fail to update quota for self" -fi - -cleanup -echo "Success! :)" - diff --git a/neutronclient/shell.py b/neutronclient/shell.py deleted file mode 100644 index 13cd0fa4e..000000000 --- a/neutronclient/shell.py +++ /dev/null @@ -1,654 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# 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. -# - -""" -Command-line interface to the Neutron APIs -""" - -import argparse -import inspect -import itertools -import logging -import os -import sys - -from keystoneauth1 import session -import os_client_config -from oslo_utils import encodeutils -from oslo_utils import netutils - -from cliff import app -from cliff import command -from cliff import commandmanager - -from neutronclient._i18n import _ -from neutronclient.common import clientmanager -from neutronclient.common import exceptions as exc -from neutronclient.common import extension as client_extension -from neutronclient.neutron.v2_0 import subnet -from neutronclient.version import __version__ - - -VERSION = '2.0' -NEUTRON_API_VERSION = '2.0' - -NAMESPACE_MAP = {NEUTRON_API_VERSION: 'neutron.cli.v2'} - - -def run_command(cmd, cmd_parser, sub_argv): - _argv = sub_argv - index = -1 - values_specs = [] - if '--' in sub_argv: - index = sub_argv.index('--') - _argv = sub_argv[:index] - values_specs = sub_argv[index:] - known_args, _values_specs = cmd_parser.parse_known_args(_argv) - if(isinstance(cmd, subnet.CreateSubnet) and not known_args.cidr): - cidr = get_first_valid_cidr(_values_specs) - if cidr: - known_args.cidr = cidr - _values_specs.remove(cidr) - cmd.values_specs = (index == -1 and _values_specs or values_specs) - return cmd.run(known_args) - - -def get_first_valid_cidr(value_specs): - # Bug 1442771, argparse does not allow optional positional parameter - # to be separated from previous positional parameter. - # When cidr was separated from network, the value will not be able - # to be parsed into known_args, but saved to _values_specs instead. - for value in value_specs: - if netutils.is_valid_cidr(value): - return value - - -def env(*_vars, **kwargs): - """Search for the first defined of possibly many env vars. - - Returns the first environment variable defined in vars, or - returns the default defined in kwargs. - - """ - for v in _vars: - value = os.environ.get(v, None) - if value: - return value - return kwargs.get('default', '') - - -def check_non_negative_int(value): - try: - value = int(value) - except ValueError: - raise argparse.ArgumentTypeError(_("invalid int value: %r") % value) - if value < 0: - raise argparse.ArgumentTypeError(_("input value %d is negative") % - value) - return value - - -COMMANDS = {} - - -# NOTE(amotoki): This is only to provide compatibility -# to existing neutron CLI extensions. See bug 1706573 for detail. -def _set_commands_dict_for_compat(apiversion, command_manager): - global COMMANDS - COMMANDS = {apiversion: dict((cmd, command_manager.find_command([cmd])[0]) - for cmd in command_manager.commands)} - - -class BashCompletionCommand(command.Command): - """Prints all of the commands and options for bash-completion.""" - - def take_action(self, parsed_args): - pass - - -class HelpAction(argparse.Action): - """Print help message including sub-commands - - Provide a custom action so the -h and --help options - to the main app will print a list of the commands. - - The commands are determined by checking the CommandManager - instance, passed in as the "default" value for the action. - """ - def __call__(self, parser, namespace, values, option_string=None): - outputs = [] - max_len = 0 - app = self.default - parser.print_help(app.stdout) - app.stdout.write(_('\nCommands for API v%s:\n') % app.api_version) - command_manager = app.command_manager - for name, ep in sorted(command_manager): - factory = ep.load() - cmd = factory(self, None) - one_liner = cmd.get_description().split('\n')[0] - outputs.append((name, one_liner)) - max_len = max(len(name), max_len) - for (name, one_liner) in outputs: - app.stdout.write(' %s %s\n' % (name.ljust(max_len), one_liner)) - sys.exit(0) - - -class NeutronShell(app.App): - - # verbose logging levels - WARNING_LEVEL = 0 - INFO_LEVEL = 1 - DEBUG_LEVEL = 2 - CONSOLE_MESSAGE_FORMAT = '%(message)s' - DEBUG_MESSAGE_FORMAT = '%(levelname)s: %(name)s %(message)s' - log = logging.getLogger(__name__) - - def __init__(self, apiversion): - namespace = NAMESPACE_MAP[apiversion] - description = (__doc__.strip() + - " (neutron CLI version: %s)" % __version__) - super(NeutronShell, self).__init__( - description=description, - version=VERSION, - command_manager=commandmanager.CommandManager(namespace), ) - - self._register_extensions(VERSION) - - # Pop the 'complete' to correct the outputs of 'neutron help'. - self.command_manager.commands.pop('complete') - - # This is instantiated in initialize_app() only when using - # password flow auth - self.auth_client = None - self.api_version = apiversion - - _set_commands_dict_for_compat(apiversion, self.command_manager) - - def build_option_parser(self, description, version): - """Return an argparse option parser for this application. - - Subclasses may override this method to extend - the parser with more global options. - - :param description: full description of the application - :paramtype description: str - :param version: version number for the application - :paramtype version: str - """ - parser = argparse.ArgumentParser( - description=description, - add_help=False, ) - parser.add_argument( - '--version', - action='version', - version=__version__, ) - parser.add_argument( - '-v', '--verbose', '--debug', - action='count', - dest='verbose_level', - default=self.DEFAULT_VERBOSE_LEVEL, - help=_('Increase verbosity of output and show tracebacks on' - ' errors. You can repeat this option.')) - parser.add_argument( - '-q', '--quiet', - action='store_const', - dest='verbose_level', - const=0, - help=_('Suppress output except warnings and errors.')) - parser.add_argument( - '-h', '--help', - action=HelpAction, - nargs=0, - default=self, # tricky - help=_("Show this help message and exit.")) - parser.add_argument( - '-r', '--retries', - metavar="NUM", - type=check_non_negative_int, - default=0, - help=_("How many times the request to the Neutron server should " - "be retried if it fails. Defaults to 0.")) - # FIXME(bklei): this method should come from keystoneauth1 - self._append_global_identity_args(parser) - - return parser - - def _append_global_identity_args(self, parser): - # FIXME(bklei): these are global identity (Keystone) arguments which - # should be consistent and shared by all service clients. Therefore, - # they should be provided by keystoneauth1. We will need to - # refactor this code once this functionality is available in - # keystoneauth1. - # - # Note: At that time we'll need to decide if we can just abandon - # the deprecated args (--service-type and --endpoint-type). - - parser.add_argument( - '--os-service-type', metavar='', - default=env('OS_NETWORK_SERVICE_TYPE', default='network'), - help=_('Defaults to env[OS_NETWORK_SERVICE_TYPE] or "network".')) - - parser.add_argument( - '--os-endpoint-type', metavar='', - default=env('OS_ENDPOINT_TYPE', default='public'), - help=_('Defaults to env[OS_ENDPOINT_TYPE] or "public".')) - - # FIXME(bklei): --service-type is deprecated but kept in for - # backward compatibility. - parser.add_argument( - '--service-type', metavar='', - default=env('OS_NETWORK_SERVICE_TYPE', default='network'), - help=_('DEPRECATED! Use --os-service-type.')) - - # FIXME(bklei): --endpoint-type is deprecated but kept in for - # backward compatibility. - parser.add_argument( - '--endpoint-type', metavar='', - default=env('OS_ENDPOINT_TYPE', default='public'), - help=_('DEPRECATED! Use --os-endpoint-type.')) - - parser.add_argument( - '--os-auth-strategy', metavar='', - default=env('OS_AUTH_STRATEGY', default='keystone'), - help=_('DEPRECATED! Only keystone is supported.')) - - parser.add_argument( - '--os_auth_strategy', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-cloud', metavar='', - help=_('Defaults to env[OS_CLOUD].')) - - parser.add_argument( - '--os-auth-url', metavar='', - help=_('Authentication URL, defaults to env[OS_AUTH_URL].')) - parser.add_argument( - '--os_auth_url', - help=argparse.SUPPRESS) - - project_name_group = parser.add_mutually_exclusive_group() - project_name_group.add_argument( - '--os-tenant-name', metavar='', - help=_('Authentication tenant name, defaults to ' - 'env[OS_TENANT_NAME].')) - project_name_group.add_argument( - '--os-project-name', - metavar='', - help=_('Another way to specify tenant name. ' - 'This option is mutually exclusive with ' - ' --os-tenant-name. ' - 'Defaults to env[OS_PROJECT_NAME].')) - - parser.add_argument( - '--os_tenant_name', - help=argparse.SUPPRESS) - - project_id_group = parser.add_mutually_exclusive_group() - project_id_group.add_argument( - '--os-tenant-id', metavar='', - help=_('Authentication tenant ID, defaults to ' - 'env[OS_TENANT_ID].')) - project_id_group.add_argument( - '--os-project-id', - metavar='', - help=_('Another way to specify tenant ID. ' - 'This option is mutually exclusive with ' - ' --os-tenant-id. ' - 'Defaults to env[OS_PROJECT_ID].')) - - parser.add_argument( - '--os-username', metavar='', - help=_('Authentication username, defaults to env[OS_USERNAME].')) - parser.add_argument( - '--os_username', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-id', metavar='', - help=_('Authentication user ID (Env: OS_USER_ID)')) - - parser.add_argument( - '--os_user_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-domain-id', - metavar='', - help=_('OpenStack user domain ID. ' - 'Defaults to env[OS_USER_DOMAIN_ID].')) - - parser.add_argument( - '--os_user_domain_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-domain-name', - metavar='', - help=_('OpenStack user domain name. ' - 'Defaults to env[OS_USER_DOMAIN_NAME].')) - - parser.add_argument( - '--os_user_domain_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os_project_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os_project_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-project-domain-id', - metavar='', - help=_('Defaults to env[OS_PROJECT_DOMAIN_ID].')) - - parser.add_argument( - '--os-project-domain-name', - metavar='', - help=_('Defaults to env[OS_PROJECT_DOMAIN_NAME].')) - - parser.add_argument( - '--os-cert', - metavar='', - help=_("Path of certificate file to use in SSL " - "connection. This file can optionally be " - "prepended with the private key. Defaults " - "to env[OS_CERT].")) - - parser.add_argument( - '--os-cacert', - metavar='', - help=_("Specify a CA bundle file to use in " - "verifying a TLS (https) server certificate. " - "Defaults to env[OS_CACERT].")) - - parser.add_argument( - '--os-key', - metavar='', - help=_("Path of client key to use in SSL " - "connection. This option is not necessary " - "if your key is prepended to your certificate " - "file. Defaults to env[OS_KEY].")) - - parser.add_argument( - '--os-password', metavar='', - help=_('Authentication password, defaults to env[OS_PASSWORD].')) - parser.add_argument( - '--os_password', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-region-name', metavar='', - help=_('Authentication region name, defaults to ' - 'env[OS_REGION_NAME].')) - parser.add_argument( - '--os_region_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-token', metavar='', - help=_('Authentication token, defaults to env[OS_TOKEN].')) - parser.add_argument( - '--os_token', - help=argparse.SUPPRESS) - - parser.add_argument( - '--http-timeout', metavar='', - default=env('OS_NETWORK_TIMEOUT', default=None), type=float, - help=_('Timeout in seconds to wait for an HTTP response. Defaults ' - 'to env[OS_NETWORK_TIMEOUT] or None if not specified.')) - - parser.add_argument( - '--os-url', metavar='', - help=_('Defaults to env[OS_URL].')) - parser.add_argument( - '--os_url', - help=argparse.SUPPRESS) - - parser.add_argument( - '--insecure', - action='store_true', - default=env('NEUTRONCLIENT_INSECURE', default=False), - help=_("Explicitly allow neutronclient to perform \"insecure\" " - "SSL (https) requests. The server's certificate will " - "not be verified against any certificate authorities. " - "This option should be used with caution.")) - - def _bash_completion(self): - """Prints all of the commands and options for bash-completion.""" - commands = set() - options = set() - for option, _action in self.parser._option_string_actions.items(): - options.add(option) - for _name, _command in self.command_manager: - commands.add(_name) - cmd_factory = _command.load() - cmd = cmd_factory(self, None) - cmd_parser = cmd.get_parser('') - for option, _action in cmd_parser._option_string_actions.items(): - options.add(option) - print(' '.join(commands | options)) - - def _register_extensions(self, version): - for name, module in itertools.chain( - client_extension._discover_via_entry_points()): - self._extend_shell_commands(name, module, version) - - def _extend_shell_commands(self, name, module, version): - classes = inspect.getmembers(module, inspect.isclass) - for cls_name, cls in classes: - if (issubclass(cls, client_extension.NeutronClientExtension) and - hasattr(cls, 'shell_command')): - cmd = cls.shell_command - if hasattr(cls, 'versions'): - if version not in cls.versions: - continue - try: - name_prefix = "[%s]" % name - cls.__doc__ = ("%s %s" % (name_prefix, cls.__doc__) if - cls.__doc__ else name_prefix) - self.command_manager.add_command(cmd, cls) - except TypeError: - pass - - def run(self, argv): - """Equivalent to the main program for the application. - - :param argv: input arguments and options - :paramtype argv: list of str - """ - try: - index = 0 - command_pos = -1 - help_pos = -1 - help_command_pos = -1 - for arg in argv: - if arg == 'bash-completion' and help_command_pos == -1: - self._bash_completion() - return 0 - if arg in ('-h', '--help'): - if help_pos == -1: - help_pos = index - # self.command_manager.commands contains 'help', - # so we need to check this first. - elif arg == 'help': - if help_command_pos == -1: - help_command_pos = index - elif arg in self.command_manager.commands: - if command_pos == -1: - command_pos = index - index = index + 1 - if command_pos > -1 and help_pos > command_pos: - argv = ['help', argv[command_pos]] - if help_command_pos > -1 and command_pos == -1: - argv[help_command_pos] = '--help' - self.options, remainder = self.parser.parse_known_args(argv) - self.configure_logging() - self.interactive_mode = not remainder - self.initialize_app(remainder) - except Exception as err: - if self.options.verbose_level >= self.DEBUG_LEVEL: - self.log.exception(err) - raise - else: - self.log.error(err) - return 1 - if self.interactive_mode: - _argv = [sys.argv[0]] - sys.argv = _argv - return self.interact() - return self.run_subcommand(remainder) - - def run_subcommand(self, argv): - subcommand = self.command_manager.find_command(argv) - cmd_factory, cmd_name, sub_argv = subcommand - cmd = cmd_factory(self, self.options) - try: - self.prepare_to_run_command(cmd) - full_name = (cmd_name - if self.interactive_mode - else ' '.join([self.NAME, cmd_name]) - ) - cmd_parser = cmd.get_parser(full_name) - return run_command(cmd, cmd_parser, sub_argv) - except SystemExit: - print(_("Try 'neutron help %s' for more information.") % - cmd_name, file=sys.stderr) - raise - except Exception as e: - if self.options.verbose_level >= self.DEBUG_LEVEL: - self.log.exception("%s", e) - raise - self.log.error("%s", e) - return 1 - - def authenticate_user(self): - """Confirm user authentication - - Make sure the user has provided all of the authentication - info we need. - """ - cloud_config = os_client_config.OpenStackConfig().get_one_cloud( - cloud=self.options.os_cloud, argparse=self.options, - network_api_version=self.api_version, - verify=not self.options.insecure) - verify, cert = cloud_config.get_requests_verify_args() - - # TODO(singhj): Remove dependancy on HTTPClient - # for the case of token-endpoint authentication - - # When using token-endpoint authentication legacy - # HTTPClient will be used, otherwise SessionClient - # will be used. - if self.options.os_token and self.options.os_url: - auth = None - auth_session = None - else: - auth = cloud_config.get_auth() - - auth_session = session.Session( - auth=auth, verify=verify, cert=cert, - timeout=self.options.http_timeout) - - interface = self.options.os_endpoint_type or self.endpoint_type - if interface.endswith('URL'): - interface = interface[:-3] - self.client_manager = clientmanager.ClientManager( - retries=self.options.retries, - raise_errors=False, - session=auth_session, - url=self.options.os_url, - token=self.options.os_token, - region_name=cloud_config.get_region_name(), - api_version=cloud_config.get_api_version('network'), - service_type=cloud_config.get_service_type('network'), - service_name=cloud_config.get_service_name('network'), - endpoint_type=interface, - auth=auth, - insecure=not verify, - log_credentials=True) - return - - def initialize_app(self, argv): - """Global app init bits: - - * set up API versions - * validate authentication info - """ - - super(NeutronShell, self).initialize_app(argv) - - # If the user is not asking for help, make sure they - # have given us auth. - cmd_name = None - if argv: - cmd_info = self.command_manager.find_command(argv) - cmd_factory, cmd_name, sub_argv = cmd_info - if self.interactive_mode or cmd_name != 'help': - self.authenticate_user() - - def configure_logging(self): - """Create logging handlers for any log output.""" - root_logger = logging.getLogger('') - - # Set up logging to a file - root_logger.setLevel(logging.DEBUG) - - # Send higher-level messages to the console via stderr - console = logging.StreamHandler(self.stderr) - console_level = {self.WARNING_LEVEL: logging.WARNING, - self.INFO_LEVEL: logging.INFO, - self.DEBUG_LEVEL: logging.DEBUG, - }.get(self.options.verbose_level, logging.DEBUG) - # The default log level is INFO, in this situation, set the - # log level of the console to WARNING, to avoid displaying - # useless messages. This equals using "--quiet" - if console_level == logging.INFO: - console.setLevel(logging.WARNING) - else: - console.setLevel(console_level) - if logging.DEBUG == console_level: - formatter = logging.Formatter(self.DEBUG_MESSAGE_FORMAT) - else: - formatter = logging.Formatter(self.CONSOLE_MESSAGE_FORMAT) - logging.getLogger('iso8601.iso8601').setLevel(logging.WARNING) - logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING) - console.setFormatter(formatter) - root_logger.addHandler(console) - return - - -def main(argv=sys.argv[1:]): - try: - print(_("neutron CLI is deprecated and will be removed " - "in the Z cycle. Use openstack CLI instead."), file=sys.stderr) - return NeutronShell(NEUTRON_API_VERSION).run( - list(map(encodeutils.safe_decode, argv))) - except KeyboardInterrupt: - print(_("... terminating neutron client"), file=sys.stderr) - return 130 - except exc.NeutronClientException: - return 1 - except Exception as e: - print(e) - return 1 - - -if __name__ == "__main__": - sys.exit(main(sys.argv[1:])) diff --git a/neutronclient/tests/functional/__init__.py b/neutronclient/tests/functional/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/functional/adv-svcs/__init__.py b/neutronclient/tests/functional/adv-svcs/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/functional/adv-svcs/test_readonly_neutron_fwaas.py b/neutronclient/tests/functional/adv-svcs/test_readonly_neutron_fwaas.py deleted file mode 100644 index 9cec62571..000000000 --- a/neutronclient/tests/functional/adv-svcs/test_readonly_neutron_fwaas.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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. - -from neutronclient.tests.functional import base - - -class SimpleReadOnlyNeutronFwv1ClientTest(base.ClientTestBase): - - """Tests for FWaaS v1 based client commands that are read only""" - - def setUp(self): - super(SimpleReadOnlyNeutronFwv1ClientTest, self).setUp() - if not self.is_extension_enabled('fwaas'): - self.skipTest('FWaaS is not enabled') - - def test_neutron_firewall_list(self): - firewall_list = self.parser.listing(self.neutron - ('firewall-list')) - self.assertTableStruct(firewall_list, ['id', 'name', - 'firewall_policy_id']) - - def test_neutron_firewall_policy_list(self): - firewall_policy = self.parser.listing(self.neutron - ('firewall-policy-list')) - self.assertTableStruct(firewall_policy, ['id', 'name', - 'firewall_rules']) - - def test_neutron_firewall_rule_list(self): - firewall_rule = self.parser.listing(self.neutron - ('firewall-rule-list')) - self.assertTableStruct(firewall_rule, ['id', 'name', - 'firewall_policy_id', - 'summary', 'enabled']) diff --git a/neutronclient/tests/functional/adv-svcs/test_readonly_neutron_vpn.py b/neutronclient/tests/functional/adv-svcs/test_readonly_neutron_vpn.py deleted file mode 100644 index 6e3b6cdcb..000000000 --- a/neutronclient/tests/functional/adv-svcs/test_readonly_neutron_vpn.py +++ /dev/null @@ -1,57 +0,0 @@ -# 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. - -from neutronclient.tests.functional import base - - -class SimpleReadOnlyNeutronVpnClientTest(base.ClientTestBase): - - """Tests for vpn based client commands that are read only - - This is a first pass at a simple read only python-neutronclient test. - This only exercises vpn based client commands that are read only. - This should test commands: - * as a regular user - * as a admin user - * with and without optional parameters - * initially just check return codes, and later test command outputs - """ - def setUp(self): - super(SimpleReadOnlyNeutronVpnClientTest, self).setUp() - if not self.is_extension_enabled('vpnaas'): - self.skipTest('VPNaaS is not enabled') - - def test_neutron_vpn_ikepolicy_list(self): - ikepolicy = self.parser.listing(self.neutron('vpn-ikepolicy-list')) - self.assertTableStruct(ikepolicy, ['id', 'name', - 'auth_algorithm', - 'encryption_algorithm', - 'ike_version', 'pfs']) - - def test_neutron_vpn_ipsecpolicy_list(self): - ipsecpolicy = self.parser.listing(self.neutron('vpn-ipsecpolicy-list')) - self.assertTableStruct(ipsecpolicy, ['id', 'name', - 'auth_algorithm', - 'encryption_algorithm', - 'pfs']) - - def test_neutron_vpn_service_list(self): - vpn_list = self.parser.listing(self.neutron('vpn-service-list')) - self.assertTableStruct(vpn_list, ['id', 'name', - 'router_id', 'status']) - - def test_neutron_ipsec_site_connection_list(self): - ipsec_site = self.parser.listing(self.neutron - ('ipsec-site-connection-list')) - self.assertTableStruct(ipsec_site, ['id', 'name', - 'peer_address', - 'auth_mode', 'status']) diff --git a/neutronclient/tests/functional/base.py b/neutronclient/tests/functional/base.py deleted file mode 100644 index 655c6c4f8..000000000 --- a/neutronclient/tests/functional/base.py +++ /dev/null @@ -1,80 +0,0 @@ -# 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 os - -import os_client_config -from tempest.lib.cli import base - - -def credentials(cloud='devstack-admin'): - """Retrieves credentials to run functional tests - - Credentials are either read via os-client-config from the environment - or from a config file ('clouds.yaml'). Environment variables override - those from the config file. - - devstack produces a clouds.yaml with two named clouds - one named - 'devstack' which has user privs and one named 'devstack-admin' which - has admin privs. This function will default to getting the devstack-admin - cloud as that is the current expected behavior. - """ - return get_cloud_config(cloud=cloud).get_auth_args() - - -def get_cloud_config(cloud='devstack-admin'): - return os_client_config.OpenStackConfig().get_one_cloud(cloud=cloud) - - -class ClientTestBase(base.ClientTestBase): - """This is a first pass at a simple read only python-neutronclient test. - - This only exercises client commands that are read only. - This should test commands: - * as a regular user - * as an admin user - * with and without optional parameters - * initially just check return codes, and later test command outputs - - """ - - def _get_clients_from_os_cloud_config(self, cloud='devstack-admin'): - creds = credentials(cloud) - cli_dir = os.environ.get( - 'OS_NEUTRONCLIENT_EXEC_DIR', - os.path.join(os.path.abspath('.'), '.tox/functional/bin')) - - return base.CLIClient( - username=creds['username'], - password=creds['password'], - tenant_name=creds['project_name'], - project_domain_id=creds['project_domain_id'], - user_domain_id=creds['user_domain_id'], - uri=creds['auth_url'], - cli_dir=cli_dir) - - def _get_clients(self): - return self._get_clients_from_os_cloud_config() - - def neutron(self, *args, **kwargs): - return self.clients.neutron(*args, **kwargs) - - def neutron_non_admin(self, *args, **kwargs): - if not hasattr(self, '_non_admin_clients'): - self._non_admin_clients = self._get_clients_from_os_cloud_config( - cloud='devstack') - return self._non_admin_clients.neutron(*args, **kwargs) - - def is_extension_enabled(self, extension_alias): - extensions = self.parser.listing(self.neutron('ext-list')) - aliases = [e['alias'] for e in extensions] - return extension_alias in aliases diff --git a/neutronclient/tests/functional/core/__init__.py b/neutronclient/tests/functional/core/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/functional/core/test_cli_formatter.py b/neutronclient/tests/functional/core/test_cli_formatter.py deleted file mode 100644 index 145ed6c67..000000000 --- a/neutronclient/tests/functional/core/test_cli_formatter.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2016 NEC Corporation -# -# 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. - -from oslo_serialization import jsonutils -from oslo_utils import uuidutils -import yaml - -from neutronclient.tests.functional import base - - -class TestCLIFormatter(base.ClientTestBase): - - def setUp(self): - super(TestCLIFormatter, self).setUp() - self.net_name = 'net-%s' % uuidutils.generate_uuid() - self.addCleanup(self.neutron, 'net-delete %s' % self.net_name) - - def _create_net(self, fmt, col_attrs): - params = ['-c %s' % attr for attr in col_attrs] - params.append('-f %s' % fmt) - params.append(self.net_name) - param_string = ' '.join(params) - return self.neutron('net-create', params=param_string) - - def test_net_create_with_json_formatter(self): - result = self._create_net('json', ['name', 'admin_state_up']) - self.assertDictEqual({'name': self.net_name, - 'admin_state_up': True}, - jsonutils.loads(result)) - - def test_net_create_with_yaml_formatter(self): - result = self._create_net('yaml', ['name', 'admin_state_up']) - self.assertDictEqual({'name': self.net_name, - 'admin_state_up': True}, - yaml.safe_load(result)) - - def test_net_create_with_value_formatter(self): - # NOTE(amotoki): In 'value' formatter, there is no guarantee - # in the order of attribute, so we use one attribute in this test. - result = self._create_net('value', ['name']) - self.assertEqual(self.net_name, result.strip()) - - def test_net_create_with_shell_formatter(self): - result = self._create_net('shell', ['name', 'admin_state_up']) - result_lines = set(result.strip().split('\n')) - self.assertSetEqual(set(['name="%s"' % self.net_name, - 'admin_state_up="True"']), - result_lines) diff --git a/neutronclient/tests/functional/core/test_clientlib.py b/neutronclient/tests/functional/core/test_clientlib.py deleted file mode 100644 index 66be8c68b..000000000 --- a/neutronclient/tests/functional/core/test_clientlib.py +++ /dev/null @@ -1,61 +0,0 @@ -# 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. - -from keystoneauth1 import session -from oslo_utils import uuidutils -from tempest.lib import base -import testtools - -from neutronclient.common import exceptions -from neutronclient.tests.functional import base as func_base -from neutronclient.v2_0 import client as v2_client - - -class LibraryTestCase(base.BaseTestCase): - - def setUp(self): - super(LibraryTestCase, self).setUp() - self.client = self._get_client() - - def _get_client(self): - cloud_config = func_base.get_cloud_config() - keystone_auth = cloud_config.get_auth() - (verify, cert) = cloud_config.get_requests_verify_args() - - ks_session = session.Session( - auth=keystone_auth, - verify=verify, - cert=cert) - return v2_client.Client(session=ks_session) - - def test_list_network(self): - nets = self.client.list_networks() - self.assertIsInstance(nets['networks'], list) - - def test_post_put_delete_network(self): - name = uuidutils.generate_uuid() - net = self.client.create_network({'network': {'name': name}}) - net_id = net['network']['id'] - self.assertEqual(name, net['network']['name']) - name2 = uuidutils.generate_uuid() - net = self.client.update_network(net_id, {'network': {'name': name2}}) - self.assertEqual(name2, net['network']['name']) - self.client.delete_network(net_id) - with testtools.ExpectedException(exceptions.NetworkNotFoundClient): - self.client.show_network(net_id) - - def test_get_auth_ref(self): - # Call some API call to ensure the client is authenticated. - self.client.list_networks() - auth_ref = self.client.httpclient.get_auth_ref() - self.assertIsNotNone(auth_ref) - self.assertIsNotNone(auth_ref.role_names) diff --git a/neutronclient/tests/functional/core/test_common.py b/neutronclient/tests/functional/core/test_common.py deleted file mode 100644 index 6bdadf96f..000000000 --- a/neutronclient/tests/functional/core/test_common.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2016 NEC Corporation -# -# 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. - -from neutronclient.tests.functional import base - - -class CLICommonFeatureTest(base.ClientTestBase): - - def test_tenant_id_shown_in_list_by_admin(self): - nets = self.parser.table(self.neutron('net-list')) - self.assertIn('tenant_id', nets['headers']) - - def test_tenant_id_not_shown_in_list_with_columns(self): - nets = self.parser.table(self.neutron('net-list -c id -c name')) - self.assertNotIn('tenant_id', nets['headers']) - self.assertListEqual(['id', 'name'], nets['headers']) - - def test_tenant_id_not_shown_in_list_by_non_admin(self): - output = self.neutron_non_admin('net-list') - self.assertNotIn('tenant_id', self.parser.table(output)['headers']) - self.assertTableStruct(self.parser.listing(output), - ['id', 'name']) diff --git a/neutronclient/tests/functional/core/test_purge.py b/neutronclient/tests/functional/core/test_purge.py deleted file mode 100644 index 33b8af44c..000000000 --- a/neutronclient/tests/functional/core/test_purge.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright 2016 Cisco Systems -# All Rights Reserved -# -# 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. - -from neutronclient.tests.functional import base - -from tempest.lib import exceptions - - -class PurgeNeutronClientCLITest(base.ClientTestBase): - - def _safe_cleanup(self, delete_command): - try: - self.neutron(delete_command) - except exceptions.CommandFailed: - # This resource was already purged successfully - pass - - def _create_subnet(self, name, tenant_id, cidr): - params = ('%(name)s --name %(name)s --tenant-id %(tenant)s ' - '%(cidr)s' % {'name': name, - 'tenant': tenant_id, - 'cidr': cidr}) - subnet = self.parser.listing(self.neutron('subnet-create', - params=params)) - for row in subnet: - if row['Field'] == 'id': - return row['Value'] - - def _create_router(self, name, tenant_id): - params = ('%(name)s --tenant_id %(tenant)s' % {'name': name, - 'tenant': tenant_id}) - router = self.parser.listing(self.neutron('router-create', - params=params)) - for row in router: - if row['Field'] == 'id': - return row['Value'] - - def _create_floatingip(self, network, tenant_id): - params = ('%(network)s --tenant-id %(tenant)s' % - {'network': network, 'tenant': tenant_id}) - floatingip = self.parser.listing(self.neutron('floatingip-create', - params=params)) - for row in floatingip: - if row['Field'] == 'id': - return row['Value'] - - def _create_resources(self, name, tenant_id, shared_tenant_id=None): - # If no shared_tenant_id is provided, create the resources for the - # current tenant to test that they will be deleted when not in use. - if not shared_tenant_id: - shared_tenant_id = tenant_id - - self.neutron('net-create', - params=('%(name)s --router:external True ' - '--tenant-id %(tenant)s' % {'name': name, - 'tenant': tenant_id})) - self.addCleanup(self._safe_cleanup, 'net-delete %s' % name) - - self.neutron('net-create', - params=('%(name)s-shared --shared ' - '--tenant-id %(tenant)s' % - {'name': name, 'tenant': shared_tenant_id})) - self.addCleanup(self._safe_cleanup, - 'net-delete %s-shared' % name) - - subnet = self._create_subnet(name, tenant_id, '192.168.71.0/24') - self.addCleanup(self._safe_cleanup, 'subnet-delete %s' % name) - - subnet = self._create_subnet('%s-shared' % name, tenant_id, - '192.168.81.0/24') - self.addCleanup(self._safe_cleanup, 'subnet-delete %s-shared' % name) - - router = self._create_router(name, tenant_id) - self.addCleanup(self._safe_cleanup, 'router-delete %s' % name) - - self.neutron('router-interface-add', - params=('%(router)s %(subnet)s ' - '--tenant-id %(tenant)s' % {'router': router, - 'subnet': subnet, - 'tenant': tenant_id})) - - self.neutron('port-create', - params=('%(name)s --name %(name)s ' - '--tenant-id %(tenant)s' % {'name': name, - 'tenant': tenant_id})) - self.addCleanup(self._safe_cleanup, 'port-delete %s' % name) - - self.neutron('port-create', - params=('%(name)s-shared --name %(name)s-shared ' - '--tenant-id %(tenant)s' % {'name': name, - 'tenant': tenant_id})) - self.addCleanup(self._safe_cleanup, 'port-delete %s-shared' % name) - - self.neutron('security-group-create', - params=('%(name)s --tenant-id %(tenant)s' % - {'name': name, 'tenant': tenant_id})) - self.addCleanup(self._safe_cleanup, 'security-group-delete %s' % name) - - floatingip = self._create_floatingip(name, tenant_id) - self.addCleanup(self._safe_cleanup, ('floatingip-delete ' - '%s' % floatingip)) - return floatingip - - def _verify_deletion(self, resources, resource_type): - purged = True - no_purge_purged = True - router_interface_owners = ['network:router_interface', - 'network:router_interface_distributed'] - for row in resources: - if resource_type == 'port' and row.get('id', None): - port = self.parser.listing(self.neutron('port-show', - params=row['id'])) - port_dict = {} - for row in port: - port_dict[row['Field']] = row['Value'] - if port_dict['device_owner'] in router_interface_owners: - if port_dict['tenant_id'] == 'purge-tenant': - purged = False - elif port_dict['tenant_id'] == 'no-purge-tenant': - no_purge_purged = False - if not purged or not no_purge_purged: - self.addCleanup(self.neutron, - ('router-interface-delete %(router)s ' - 'port=%(port)s' % - {'router': port_dict['device_id'], - 'port': port_dict['id']})) - if (row.get('name') == 'purge-me' or - row.get('id') == self.purge_floatingip): - purged = False - elif ('no-purge' in row.get('name', '') or - row.get('id') == self.no_purge_floatingip): - no_purge_purged = False - - if not purged: - self.fail('%s not deleted by neutron purge' % resource_type) - - if no_purge_purged: - self.fail('%s owned by another tenant incorrectly deleted ' - 'by neutron purge' % resource_type) - - def test_purge(self): - self.purge_floatingip = self._create_resources('purge-me', - 'purge-tenant') - self.no_purge_floatingip = self._create_resources('no-purge', - 'no-purge-tenant', - 'purge-tenant') - - purge_output = self.neutron('purge', params='purge-tenant').strip() - if not purge_output: - self.fail('Purge command did not return feedback') - - networks = self.parser.listing(self.neutron('net-list')) - subnets = self.parser.listing(self.neutron('subnet-list')) - routers = self.parser.listing(self.neutron('router-list')) - ports = self.parser.listing(self.neutron('port-list')) - floatingips = self.parser.listing(self.neutron('floatingip-list')) - - self._verify_deletion(networks, 'network') - self._verify_deletion(subnets, 'subnet') - self._verify_deletion(ports, 'port') - self._verify_deletion(routers, 'router') - self._verify_deletion(floatingips, 'floatingip') diff --git a/neutronclient/tests/functional/core/test_readonly_neutron.py b/neutronclient/tests/functional/core/test_readonly_neutron.py deleted file mode 100644 index 4fe989711..000000000 --- a/neutronclient/tests/functional/core/test_readonly_neutron.py +++ /dev/null @@ -1,136 +0,0 @@ -# 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 re - -from tempest.lib import exceptions - -from neutronclient.tests.functional import base - - -class SimpleReadOnlyNeutronClientTest(base.ClientTestBase): - - """This is a first pass at a simple read only python-neutronclient test. - - This only exercises client commands that are read only. - This should test commands: - * as a regular user - * as a admin user - * with and without optional parameters - * initially just check return codes, and later test command outputs - """ - - def test_admin_fake_action(self): - self.assertRaises(exceptions.CommandFailed, - self.neutron, - 'this-does-neutron-exist') - - # NOTE(mestery): Commands in order listed in 'neutron help' - - # Optional arguments: - - def test_neutron_fake_action(self): - self.assertRaises(exceptions.CommandFailed, - self.neutron, - 'this-does-not-exist') - - def test_neutron_net_list(self): - net_list = self.parser.listing(self.neutron('net-list')) - self.assertTableStruct(net_list, ['id', 'name', 'subnets']) - - def test_neutron_ext_list(self): - ext = self.parser.listing(self.neutron('ext-list')) - self.assertTableStruct(ext, ['alias', 'name']) - - def test_neutron_dhcp_agent_list_hosting_net(self): - self.neutron('dhcp-agent-list-hosting-net', - params='private') - - def test_neutron_agent_list(self): - agents = self.parser.listing(self.neutron('agent-list')) - field_names = ['id', 'agent_type', 'host', 'alive', 'admin_state_up'] - self.assertTableStruct(agents, field_names) - - def test_neutron_floatingip_list(self): - self.neutron('floatingip-list') - - def test_neutron_meter_label_list(self): - if not self.is_extension_enabled('metering'): - self.skipTest('metering is not enabled') - self.neutron('meter-label-list') - - def test_neutron_meter_label_rule_list(self): - if not self.is_extension_enabled('metering'): - self.skipTest('metering is not enabled') - self.neutron('meter-label-rule-list') - - def test_neutron_net_external_list(self): - net_ext_list = self.parser.listing(self.neutron('net-external-list')) - self.assertTableStruct(net_ext_list, ['id', 'name', 'subnets']) - - def test_neutron_port_list(self): - port_list = self.parser.listing(self.neutron('port-list')) - self.assertTableStruct(port_list, ['id', 'name', 'mac_address', - 'fixed_ips']) - - def test_neutron_quota_list(self): - self.neutron('quota-list') - - def test_neutron_router_list(self): - router_list = self.parser.listing(self.neutron('router-list')) - self.assertTableStruct(router_list, ['id', 'name', - 'external_gateway_info']) - - def test_neutron_security_group_list(self): - security_grp = self.parser.listing(self.neutron('security-group-list')) - self.assertTableStruct(security_grp, ['id', 'name', - 'security_group_rules']) - - def test_neutron_security_group_rule_list(self): - security_grp = self.parser.listing(self.neutron - ('security-group-rule-list')) - self.assertTableStruct(security_grp, ['id', 'security_group', - 'direction', 'ethertype', - 'port/protocol', 'remote']) - - def test_neutron_subnet_list(self): - subnet_list = self.parser.listing(self.neutron('subnet-list')) - self.assertTableStruct(subnet_list, ['id', 'name', 'cidr', - 'allocation_pools']) - - def test_neutron_help(self): - help_text = self.neutron('help') - lines = help_text.split('\n') - self.assertFirstLineStartsWith(lines, 'usage: neutron') - - commands = [] - cmds_start = lines.index('Commands for API v2.0:') - command_pattern = re.compile(r'^ {2}([a-z0-9\-\_]+)') - for line in lines[cmds_start:]: - match = command_pattern.match(line) - if match: - commands.append(match.group(1)) - commands = set(commands) - wanted_commands = set(('net-create', 'subnet-list', 'port-delete', - 'router-show', 'agent-update', 'help')) - self.assertFalse(wanted_commands - commands) - - # Optional arguments: - - def test_neutron_version(self): - self.neutron('', flags='--version') - - def test_neutron_debug_net_list(self): - self.neutron('net-list', flags='--debug') - - def test_neutron_quiet_net_list(self): - self.neutron('net-list', flags='--quiet') diff --git a/neutronclient/tests/functional/core/test_subnet_create.py b/neutronclient/tests/functional/core/test_subnet_create.py deleted file mode 100644 index ed7f390b8..000000000 --- a/neutronclient/tests/functional/core/test_subnet_create.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2015 Hewlett-Packard Development Company, L.P -# -# 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. - -from neutronclient.tests.functional import base - - -class SubnetCreateNeutronClientCLITest(base.ClientTestBase): - - def test_create_subnet_net_name_first(self): - self.neutron('net-create', params='netwrk-1') - self.addCleanup(self.neutron, 'net-delete netwrk-1') - self.neutron('subnet-create netwrk-1', - params='--name fake --gateway 192.168.51.1 ' - '192.168.51.0/24') - self.addCleanup(self.neutron, 'subnet-delete fake') - subnet_list = self.parser.listing(self.neutron('subnet-list')) - self.assertTableStruct(subnet_list, ['id', 'name', 'cidr', - 'allocation_pools']) - found = False - for row in subnet_list: - if row.get('name') == 'fake': - found = True - break - if not found: - self.fail('Created subnet not found in list') diff --git a/neutronclient/tests/functional/hooks/fwaas b/neutronclient/tests/functional/hooks/fwaas deleted file mode 100644 index d9fc704ef..000000000 --- a/neutronclient/tests/functional/hooks/fwaas +++ /dev/null @@ -1,2 +0,0 @@ -enable_plugin neutron-fwaas https://opendev.org/openstack/neutron-fwaas -enable_service q-fwaas diff --git a/neutronclient/tests/functional/hooks/gate_hook.sh b/neutronclient/tests/functional/hooks/gate_hook.sh deleted file mode 100755 index c1721d88d..000000000 --- a/neutronclient/tests/functional/hooks/gate_hook.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -VENV=${1:-"functional"} - -GATE_DEST=$BASE/new -NEUTRONCLIENT_PATH=$GATE_DEST/python-neutronclient -GATE_HOOKS=$NEUTRONCLIENT_PATH/neutronclient/tests/functional/hooks -DEVSTACK_PATH=$GATE_DEST/devstack -LOCAL_CONF=$DEVSTACK_PATH/late-local.conf -DSCONF=/tmp/devstack-tools/bin/dsconf - -# Install devstack-tools used to produce local.conf; we can't rely on -# test-requirements.txt because the gate hook is triggered before neutronclient -# is installed -sudo -H pip install virtualenv -virtualenv /tmp/devstack-tools -/tmp/devstack-tools/bin/pip install -U devstack-tools==0.4.0 - -# Inject config from hook into localrc -function load_rc_hook { - local hook="$1" - local tmpfile - local config - tmpfile=$(tempfile) - config=$(cat $GATE_HOOKS/$hook) - echo "[[local|localrc]]" > $tmpfile - $DSCONF setlc_raw $tmpfile "$config" - $DSCONF merge_lc $LOCAL_CONF $tmpfile - rm -f $tmpfile -} - - -if [ "$VENV" == "functional-adv-svcs" ] -then - load_rc_hook fwaas - load_rc_hook vpnaas -fi - -export DEVSTACK_LOCALCONF=$(cat $LOCAL_CONF) -$BASE/new/devstack-gate/devstack-vm-gate.sh diff --git a/neutronclient/tests/functional/hooks/post_test_hook.sh b/neutronclient/tests/functional/hooks/post_test_hook.sh deleted file mode 100755 index d62d13911..000000000 --- a/neutronclient/tests/functional/hooks/post_test_hook.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash -xe - -# 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. - -# This script is executed inside post_test_hook function in devstack gate. - -SCRIPTS_DIR="/usr/os-testr-env/bin/" - -function generate_test_logs { - local path="$1" - # Compress all $path/*.txt files and move the directories holding those - # files to /opt/stack/logs. Files with .log suffix have their - # suffix changed to .txt (so browsers will know to open the compressed - # files and not download them). - if [ -d "$path" ] - then - sudo find $path -iname "*.log" -type f -exec mv {} {}.txt \; -exec gzip -9 {}.txt \; - sudo mv $path/* /opt/stack/logs/ - fi -} - -function generate_testr_results { - # Give job user rights to access tox logs - sudo -H -u $USER chmod o+rw . - sudo -H -u $USER chmod o+rw -R .stestr - if [ -f ".stestr/0" ] ; then - .tox/$VENV/bin/subunit-1to2 < .stestr/0 > ./stestr.subunit - $SCRIPTS_DIR/subunit2html ./stestr.subunit testr_results.html - gzip -9 ./stestr.subunit - gzip -9 ./testr_results.html - sudo mv ./*.gz /opt/stack/logs/ - fi - - if [ "$venv" == "functional" ] || [ "$venv" == "functional-adv-svcs" ] - then - generate_test_logs "/tmp/${venv}-logs" - fi -} - -export NEUTRONCLIENT_DIR="$BASE/new/python-neutronclient" - -sudo chown -R $USER:stack $NEUTRONCLIENT_DIR - -# Go to the neutronclient dir -cd $NEUTRONCLIENT_DIR - -# Run tests -VENV=${1:-"functional"} -echo "Running neutronclient functional test suite" -set +e -# Preserve env for OS_ credentials -sudo -E -H -u $USER tox -e $VENV -EXIT_CODE=$? -set -e - -# Collect and parse result -generate_testr_results -exit $EXIT_CODE diff --git a/neutronclient/tests/functional/hooks/vpnaas b/neutronclient/tests/functional/hooks/vpnaas deleted file mode 100644 index 8b94b37b0..000000000 --- a/neutronclient/tests/functional/hooks/vpnaas +++ /dev/null @@ -1 +0,0 @@ -enable_plugin neutron-vpnaas https://opendev.org/openstack/neutron-vpnaas diff --git a/neutronclient/tests/unit/bgp/__init__.py b/neutronclient/tests/unit/bgp/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/bgp/test_cli20_dragentscheduler.py b/neutronclient/tests/unit/bgp/test_cli20_dragentscheduler.py deleted file mode 100644 index cbe85d92f..000000000 --- a/neutronclient/tests/unit/bgp/test_cli20_dragentscheduler.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2016 Huawei Technologies India Pvt. Ltd. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.bgp import dragentscheduler as bgp_drsched -from neutronclient.tests.unit import test_cli20 -from neutronclient.tests.unit import test_cli20_agentschedulers as test_as - - -BGP_DRAGENT_ID = 'bgp_dragent_id1' -BGP_SPEAKER = 'bgp_speaker_id1' - - -class CLITestV20DRAgentScheduler(test_as.CLITestV20AgentScheduler): - - def test_add_bgp_speaker_to_dragent(self): - resource = 'agent' - cmd = bgp_drsched.AddBGPSpeakerToDRAgent( - test_cli20.MyApp(sys.stdout), None) - args = (BGP_DRAGENT_ID, BGP_SPEAKER) - body = {'bgp_speaker_id': BGP_SPEAKER} - result = {'bgp_speaker_id': 'bgp_speaker_id', } - self._test_add_to_agent(resource, cmd, args, - self.client.BGP_DRINSTANCES, - body, result) - - def test_remove_bgp_speaker_from_dragent(self): - resource = 'agent' - cmd = bgp_drsched.RemoveBGPSpeakerFromDRAgent( - test_cli20.MyApp(sys.stdout), None) - args = (BGP_DRAGENT_ID, BGP_SPEAKER) - self._test_remove_from_agent(resource, cmd, args, - self.client.BGP_DRINSTANCES) - - def test_list_bgp_speakers_on_dragent(self): - resources = 'bgp_speakers' - cmd = bgp_drsched.ListBGPSpeakersOnDRAgent( - test_cli20.MyApp(sys.stdout), None) - path = ((self.client.agent_path + self.client.BGP_DRINSTANCES) % - BGP_DRAGENT_ID) - self._test_list_resources(resources, cmd, base_args=[BGP_DRAGENT_ID], - path=path) - - def test_list_dragents_hosting_bgp_speaker(self): - resources = 'agent' - cmd = bgp_drsched.ListDRAgentsHostingBGPSpeaker( - test_cli20.MyApp(sys.stdout), None) - path = ((self.client.bgp_speaker_path + self.client.BGP_DRAGENTS) % - BGP_DRAGENT_ID) - contents = {self.id_field: 'myid1', 'alive': True} - self._test_list_resources(resources, cmd, base_args=[BGP_DRAGENT_ID], - path=path, response_contents=contents) diff --git a/neutronclient/tests/unit/bgp/test_cli20_peer.py b/neutronclient/tests/unit/bgp/test_cli20_peer.py deleted file mode 100644 index 998b0d5e3..000000000 --- a/neutronclient/tests/unit/bgp/test_cli20_peer.py +++ /dev/null @@ -1,224 +0,0 @@ -# Copyright 2016 Huawei Technologies India Pvt. Ltd. -# All Rights Reserved -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.bgp import peer as bgp_peer -from neutronclient.neutron.v2_0.bgp import speaker as bgp_speaker -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20BGPPeerJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['bgp_peer'] - - def test_create_bgp_peer_with_mandatory_params(self): - # Create BGP peer with mandatory params. - resource = 'bgp_peer' - cmd = bgp_peer.CreatePeer(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - peerip = '1.1.1.1' - remote_asnum = '1' - args = [name, - '--peer-ip', peerip, - '--remote-as', remote_asnum, ] - position_names = ['name', 'peer_ip', 'remote_as', - 'auth_type'] - position_values = [name, peerip, remote_asnum, 'none'] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_bgp_peer_with_all_params(self): - # Create BGP peer with all params. - resource = 'bgp_peer' - cmd = bgp_peer.CreatePeer(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - peerip = '1.1.1.1' - remote_asnum = '65535' - authType = 'md5' - password = 'abc' - args = [name, - '--peer-ip', peerip, - '--remote-as', remote_asnum, - '--auth-type', authType, - '--password', password] - position_names = ['name', 'peer_ip', 'remote_as', - 'auth_type', 'password'] - position_values = [name, peerip, remote_asnum, authType, password] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_bgp_peer_with_invalid_min_remote_asnum(self): - # Create BGP peer with invalid minimum remote-asnum. - resource = 'bgp_peer' - cmd = bgp_peer.CreatePeer(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - peerip = '1.1.1.1' - remote_asnum = '0' - args = [name, - '--peer-ip', peerip, - '--remote-as', remote_asnum, ] - position_names = ['name', 'peer_ip', 'remote_as', ] - position_values = [name, peerip, remote_asnum, ] - exc = self.assertRaises(exceptions.CommandError, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - self.assertEqual('remote-as "0" should be an integer [%s:%s].' % - (bgp_speaker.MIN_AS_NUM, bgp_speaker.MAX_AS_NUM), - str(exc)) - - def test_create_bgp_peer_with_invalid_max_remote_asnum(self): - # Create BGP peer with invalid maximum remote-asnum. - resource = 'bgp_peer' - cmd = bgp_peer.CreatePeer(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - peerip = '1.1.1.1' - remote_asnum = '4294967296' - args = [name, - '--peer-ip', peerip, - '--remote-as', remote_asnum, ] - position_names = ['name', 'peer_ip', 'remote_as', - 'auth_type', 'password'] - position_values = [name, peerip, remote_asnum, 'none', ''] - exc = self.assertRaises(exceptions.CommandError, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - self.assertEqual('remote-as "4294967296" should be an ' - 'integer [%s:%s].' % - (bgp_speaker.MIN_AS_NUM, bgp_speaker.MAX_AS_NUM), - str(exc)) - - def test_create_authenticated_bgp_peer_without_authtype(self): - # Create authenticated BGP peer without auth-type. - resource = 'bgp_peer' - cmd = bgp_peer.CreatePeer(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - peerip = '1.1.1.1' - remote_asnum = '2048' - password = 'abc' - args = [name, - '--peer-ip', peerip, - '--remote-as', remote_asnum, - '--password', password] - position_names = ['name', 'peer_ip', 'remote_as', 'password'] - position_values = [name, peerip, remote_asnum, password] - exc = self.assertRaises(exceptions.CommandError, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - self.assertEqual('Must provide auth-type if password is specified.', - str(exc)) - - def test_create_authenticated_bgp_peer_without_password(self): - # Create authenticated BGP peer without password. - resource = 'bgp_peer' - cmd = bgp_peer.CreatePeer(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - peerip = '1.1.1.1' - remote_asnum = '2048' - authType = 'md5' - args = [name, - '--peer-ip', peerip, - '--remote-as', remote_asnum, - '--auth-type', authType] - position_names = ['name', 'peer_ip', 'remote_as', 'auth_type'] - position_values = [name, peerip, remote_asnum, authType] - exc = self.assertRaises(exceptions.CommandError, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - self.assertEqual('Must provide password if auth-type is specified.', - str(exc)) - - def test_update_bgp_peer(self): - # Update BGP peer: - # myid --advertise-tenant-networks True - # --advertise-floating-ip-host-routes False - resource = 'bgp_peer' - cmd = bgp_peer.UpdatePeer(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'new-name', - '--password', 'abc'], - {'name': 'new-name', 'password': 'abc'}) - - def test_update_bgp_peer_exception(self): - # Update BGP peer: myid. - resource = 'bgp_peer' - cmd = bgp_peer.UpdatePeer(test_cli20.MyApp(sys.stdout), - None) - self.assertRaises(exceptions.CommandError, - self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - - def test_list_bgp_peer(self): - # List all BGP peers. - resources = "bgp_peers" - cmd = bgp_peer.ListPeers(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - # TODO(Vikram): Add test_list_bgp_peer_pagination - - def test_list_bgp_peer_sort(self): - # sorted list: bgp-peer-list --sort-key name --sort-key id - # --sort-key asc --sort-key desc - resources = "bgp_peers" - cmd = bgp_peer.ListPeers(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_bgp_peer_limit(self): - # size (1000) limited list: bgp-peer-list -P. - resources = "bgp_peers" - cmd = bgp_peer.ListPeers(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_bgp_peer(self): - # Show BGP peer: --fields id --fields name myid. - resource = 'bgp_peer' - cmd = bgp_peer.ShowPeer(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_delete_bgp_peer(self): - # Delete BGP peer: bgp_peer_id. - resource = 'bgp_peer' - cmd = bgp_peer.DeletePeer(test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) diff --git a/neutronclient/tests/unit/bgp/test_cli20_speaker.py b/neutronclient/tests/unit/bgp/test_cli20_speaker.py deleted file mode 100644 index 5621576d9..000000000 --- a/neutronclient/tests/unit/bgp/test_cli20_speaker.py +++ /dev/null @@ -1,273 +0,0 @@ -# Copyright 2016 Huawei Technologies India Pvt. Ltd. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.bgp import speaker as bgp_speaker -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20BGPSpeakerJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['bgp_speaker'] - - def test_create_bgp_speaker_with_minimal_options(self): - # Create BGP Speaker with mandatory params. - resource = 'bgp_speaker' - cmd = bgp_speaker.CreateSpeaker(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - local_asnum = '1' - args = [name, '--local-as', local_asnum, ] - position_names = ['name', 'local_as', 'ip_version'] - position_values = [name, local_asnum, 4] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_ipv4_bgp_speaker_with_all_params(self): - # Create BGP Speaker with all params. - resource = 'bgp_speaker' - cmd = bgp_speaker.CreateSpeaker(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - local_asnum = '1' - args = [name, - '--local-as', local_asnum, - '--ip-version', '4', - '--advertise-floating-ip-host-routes', 'True', - '--advertise-tenant-networks', 'True'] - position_names = ['name', 'local_as', 'ip_version', - 'advertise_floating_ip_host_routes', - 'advertise_tenant_networks'] - position_values = [name, local_asnum, 4, 'True', 'True'] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_ipv6_bgp_speaker_with_all_params(self): - # Create BGP Speaker with all params. - resource = 'bgp_speaker' - cmd = bgp_speaker.CreateSpeaker(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - local_asnum = '65535' - args = [name, - '--local-as', local_asnum, - '--ip-version', '6', - '--advertise-floating-ip-host-routes', 'True', - '--advertise-tenant-networks', 'True'] - position_names = ['name', 'local_as', 'ip_version', - 'advertise_floating_ip_host_routes', - 'advertise_tenant_networks'] - position_values = [name, local_asnum, 6, 'True', 'True'] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_bgp_speaker_with_invalid_min_local_asnum(self): - # Create BGP Speaker with invalid minimum local-asnum. - resource = 'bgp_speaker' - cmd = bgp_speaker.CreateSpeaker(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - local_asnum = '0' - args = [name, - '--local-as', local_asnum] - position_names = ['name', 'local_as'] - position_values = [name, local_asnum] - exc = self.assertRaises(exceptions.CommandError, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - self.assertEqual('local-as "0" should be an integer [%s:%s].' % - (bgp_speaker.MIN_AS_NUM, bgp_speaker.MAX_AS_NUM), - str(exc)) - - def test_create_bgp_speaker_with_invalid_max_local_asnum(self): - # Create BGP Speaker with invalid maximum local-asnum. - resource = 'bgp_speaker' - cmd = bgp_speaker.CreateSpeaker(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - my_id = 'my-id' - local_asnum = '4294967296' - args = [name, - '--local-as', local_asnum] - position_names = ['name', 'local_as', ] - position_values = [name, local_asnum, ] - exc = self.assertRaises(exceptions.CommandError, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - self.assertEqual('local-as "4294967296" should be an ' - 'integer [%s:%s].' % - (bgp_speaker.MIN_AS_NUM, bgp_speaker.MAX_AS_NUM), - str(exc)) - - def test_update_bgp_speaker(self): - # Update BGP Speaker: - # myid --advertise-tenant-networks True - # --advertise-floating-ip-host-routes False - resource = 'bgp_speaker' - cmd = bgp_speaker.UpdateSpeaker(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', - '--name', 'new-name', - '--advertise-tenant-networks', 'True', - '--advertise-floating-ip-host-routes', - 'False'], - {'name': 'new-name', - 'advertise_tenant_networks': 'True', - 'advertise_floating_ip_host_routes': - 'False'}) - - def test_update_bgp_speaker_exception(self): - # Update BGP Speaker: myid. - resource = 'bgp_speaker' - cmd = bgp_speaker.UpdateSpeaker(test_cli20.MyApp(sys.stdout), - None) - self.assertRaises(exceptions.CommandError, - self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - - def test_list_bgp_speaker(self): - # List all BGP Speakers. - resources = "bgp_speakers" - cmd = bgp_speaker.ListSpeakers(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - @mock.patch.object(bgp_speaker.ListSpeakers, "extend_list") - def test_list_bgp_speaker_pagination(self, mock_extend_list): - # List all BGP Speakers with pagination support. - cmd = bgp_speaker.ListSpeakers(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination("bgp_speakers", - cmd) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def test_list_bgp_speaker_sort(self): - # sorted list: bgp-speaker-list --sort-key name --sort-key id - # --sort-key asc --sort-key desc - resources = "bgp_speakers" - cmd = bgp_speaker.ListSpeakers(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_bgp_speaker_limit(self): - # size (1000) limited list: bgp-speaker-list -P. - resources = "bgp_speakers" - cmd = bgp_speaker.ListSpeakers(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_bgp_speaker(self): - # Show BGP Speaker: --fields id --fields name myid. - resource = 'bgp_speaker' - cmd = bgp_speaker.ShowSpeaker(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_delete_bgp_speaker(self): - # Delete BGP Speaker: bgp_speaker_id. - resource = 'bgp_speaker' - cmd = bgp_speaker.DeleteSpeaker(test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def _test_add_remove_peer(self, action, cmd, args): - """Add or Remove BGP Peer to/from a BGP Speaker.""" - resource = 'bgp_speaker' - subcmd = '%s_bgp_peer' % action - body = {'bgp_peer_id': 'peerid'} - if action == 'add': - retval = {'bgp_peer': 'peerid'} - retval = self.client.serialize(retval) - expected_code = 200 - else: - retval = None - expected_code = 204 - self._test_update_resource_action(resource, cmd, 'myid', - subcmd, args, body, expected_code, - retval) - - def test_add_peer_to_bgp_speaker(self): - # Add peer to BGP speaker: myid peer_id=peerid - cmd = bgp_speaker.AddPeerToSpeaker(test_cli20.MyApp(sys.stdout), - None) - args = ['myid', 'peerid'] - self._test_add_remove_peer('add', cmd, args) - - def test_remove_peer_from_bgp_speaker(self): - # Remove peer from BGP speaker: myid peer_id=peerid - cmd = bgp_speaker.RemovePeerFromSpeaker(test_cli20.MyApp(sys.stdout), - None) - args = ['myid', 'peerid'] - self._test_add_remove_peer('remove', cmd, args) - - def _test_add_remove_network(self, action, cmd, args): - # Add or Remove network to/from a BGP Speaker. - resource = 'bgp_speaker' - subcmd = '%s_gateway_network' % action - body = {'network_id': 'netid'} - if action == 'add': - retval = {'network': 'netid'} - retval = self.client.serialize(retval) - expected_code = 200 - else: - retval = None - expected_code = 204 - self._test_update_resource_action(resource, cmd, 'myid', - subcmd, args, body, expected_code, - retval) - - def test_add_network_to_bgp_speaker(self): - # Add peer to BGP speaker: myid network_id=netid - cmd = bgp_speaker.AddNetworkToSpeaker(test_cli20.MyApp(sys.stdout), - None) - args = ['myid', 'netid'] - self._test_add_remove_network('add', cmd, args) - - def test_remove_network_from_bgp_speaker(self): - # Remove network from BGP speaker: myid network_id=netid - cmd = bgp_speaker.RemoveNetworkFromSpeaker( - test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'netid'] - self._test_add_remove_network('remove', cmd, args) - - def test_list_routes_advertised_by_a_bgp_speaker(self): - # Retrieve advertised route list - resources = 'advertised_routes' - cmd = bgp_speaker.ListRoutesAdvertisedBySpeaker( - test_cli20.MyApp(sys.stdout), None) - bs_id = 'bgp_speaker_id1' - path = ((self.client.bgp_speaker_path + '/get_advertised_routes') % - bs_id) - self._test_list_resources(resources, cmd, base_args=[bs_id], - path=path) diff --git a/neutronclient/tests/unit/flavor/__init__.py b/neutronclient/tests/unit/flavor/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/flavor/test_cli20_flavor.py b/neutronclient/tests/unit/flavor/test_cli20_flavor.py deleted file mode 100644 index 22bd8bb9b..000000000 --- a/neutronclient/tests/unit/flavor/test_cli20_flavor.py +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.flavor import flavor -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FlavorJSON(test_cli20.CLITestV20Base): - - def setUp(self): - """Prepare test environment.""" - super(CLITestV20FlavorJSON, self).setUp(plurals={'flavors': 'flavor'}) - self.register_non_admin_status_resource('flavor') - self.register_non_admin_status_resource('service_profile') - - def test_create_flavor_with_missing_params(self): - """Create test flavor with missing parameters.""" - resource = 'flavor' - cmd = flavor.CreateFlavor( - test_cli20.MyApp(sys.stdout), None) - name = 'Test flavor' - myid = 'myid' - position_names = [] - position_values = [] - args = [] - self.assertRaises( - SystemExit, self._test_create_resource, - resource, cmd, name, myid, args, position_names, position_values) - - def test_create_flavor_with_mandatory_params(self): - """Create test flavor with minimal parameters.""" - resource = 'flavor' - cmd = flavor.CreateFlavor( - test_cli20.MyApp(sys.stdout), None) - name = 'Test flavor' - myid = 'myid' - service_type = 'DUMMY' - # Defaults are returned in body - position_names = ['name', 'service_type'] - position_values = [name, service_type] - args = [name, service_type] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_flavor_with_optional_params(self): - """Create test flavor including optional parameters.""" - resource = 'flavor' - cmd = flavor.CreateFlavor( - test_cli20.MyApp(sys.stdout), None) - name = 'Test flavor' - myid = 'myid' - service_type = 'DUMMY' - description = 'Test description' - position_names = ['name', 'service_type', 'description', 'enabled'] - position_values = [name, service_type, description, 'False'] - args = [name, service_type, - '--description', description, - '--enabled=False'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_delete_flavor(self): - """Delete flavor.""" - resource = 'flavor' - cmd = flavor.DeleteFlavor(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_list_flavors(self): - """List flavors test.""" - resources = 'flavors' - cmd = flavor.ListFlavor( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_flavors_with_pagination(self): - """List flavors test with pagination.""" - resources = 'flavors' - cmd = flavor.ListFlavor( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_flavors_with_sort(self): - """List flavors test with sorting by name and id.""" - resources = 'flavors' - cmd = flavor.ListFlavor( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_show_flavor(self): - """Show flavor test.""" - resource = 'flavor' - cmd = flavor.ShowFlavor( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_update_flavor_with_name(self): - """Update flavor test.""" - resource = 'flavor' - cmd = flavor.UpdateFlavor( - test_cli20.MyApp(sys.stdout), None) - newname = 'Test New Name' - newdescription = 'New Description' - args = ['--name', newname, - '--description', newdescription, - '--enabled', 'False', self.test_id] - self._test_update_resource(resource, cmd, self.test_id, args, - {'name': newname, - 'description': newdescription, - 'enabled': 'False'}) - - def test_associate_flavor(self): - """Associate flavor test.""" - resource = 'service_profile' - cmd = flavor.AssociateFlavor(test_cli20.MyApp(sys.stdout), None) - flavor_id = 'flavor-id' - profile_id = 'profile-id' - name = '' - args = [flavor_id, profile_id] - position_names = ['id'] - position_values = [profile_id] - self._test_create_resource(resource, cmd, name, profile_id, args, - position_names, position_values, - cmd_resource='flavor_profile_binding', - parent_id=flavor_id) - - def test_disassociate_flavor(self): - """Disassociate flavor test.""" - resource = 'flavor_profile_binding' - cmd = flavor.DisassociateFlavor(test_cli20.MyApp(sys.stdout), None) - flavor_id = 'flavor-id' - profile_id = 'profile-id' - args = [flavor_id, profile_id] - self._test_delete_resource(resource, cmd, profile_id, args, - parent_id=flavor_id) diff --git a/neutronclient/tests/unit/flavor/test_cli20_flavor_profile.py b/neutronclient/tests/unit/flavor/test_cli20_flavor_profile.py deleted file mode 100644 index d13090297..000000000 --- a/neutronclient/tests/unit/flavor/test_cli20_flavor_profile.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.flavor import flavor_profile -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FlavorProfileJSON(test_cli20.CLITestV20Base): - - def setUp(self): - """Prepare test environment.""" - super(CLITestV20FlavorProfileJSON, self).setUp( - plurals={'service_profiles': 'service_profile'}) - self.register_non_admin_status_resource('service_profile') - - def test_create_flavor_profile_with_mandatory_params(self): - """Create test flavor profile test.""" - resource = 'service_profile' - cmd = flavor_profile.CreateFlavorProfile( - test_cli20.MyApp(sys.stdout), None) - name = '' - description = 'Test flavor profile' - myid = 'myid' - metainfo = "{'a':'b'}" - # Defaults are returned in body - position_names = ['description', 'metainfo'] - position_values = [description, metainfo] - args = ['--description', description, '--metainfo', metainfo] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_flavor_profile_with_optional_params(self): - """Create test flavor profile disabled test.""" - resource = 'service_profile' - cmd = flavor_profile.CreateFlavorProfile( - test_cli20.MyApp(sys.stdout), None) - name = '' - description = 'Test flavor profile - disabled' - myid = 'myid' - driver = 'mydriver' - metainfo = "{'a':'b'}" - position_names = ['description', 'driver', 'metainfo', 'enabled'] - position_values = [description, driver, metainfo, 'False'] - args = ['--description', description, '--driver', driver, - '--metainfo', metainfo, '--enabled=False'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_flavor_profiles(self): - """List flavor profiles test.""" - resources = 'service_profiles' - cmd = flavor_profile.ListFlavorProfile( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_flavor_profiles_with_pagination(self): - """List flavor profiles test with pagination.""" - resources = 'service_profiles' - cmd = flavor_profile.ListFlavorProfile( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_flavor_profiles_with_sort(self): - """List flavor profiles test with sort by description.""" - resources = 'service_profiles' - cmd = flavor_profile.ListFlavorProfile( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["description"], - sort_dir=["asc"]) - - def test_show_flavor_profile(self): - """Show flavor profile test.""" - resource = 'service_profile' - cmd = flavor_profile.ShowFlavorProfile( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_update_flavor_profile(self): - """Update flavor profile test.""" - resource = 'service_profile' - cmd = flavor_profile.UpdateFlavorProfile( - test_cli20.MyApp(sys.stdout), None) - newdescription = 'Test new description' - newdriver = 'NewDriver' - newmetainfo = "{'c':'d'}" - newenabled = "False" - args = ['--description', newdescription, - '--driver', newdriver, - '--metainfo', newmetainfo, - '--enabled', newenabled, - self.test_id] - self._test_update_resource(resource, cmd, self.test_id, args, - {'description': newdescription, - 'driver': newdriver, - 'metainfo': newmetainfo, - 'enabled': newenabled}) - - def test_delete_flavor_profile(self): - """Delete flavor profile.""" - resource = 'service_profile' - cmd = flavor_profile.DeleteFlavorProfile(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) diff --git a/neutronclient/tests/unit/fw/__init__.py b/neutronclient/tests/unit/fw/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/fw/test_cli20_firewall.py b/neutronclient/tests/unit/fw/test_cli20_firewall.py deleted file mode 100644 index f9a2deebf..000000000 --- a/neutronclient/tests/unit/fw/test_cli20_firewall.py +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright 2013 Big Switch Networks Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.fw import firewall -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FirewallJSON(test_cli20.CLITestV20Base): - - def test_create_firewall_with_mandatory_params(self): - # firewall-create with mandatory (none) params. - resource = 'firewall' - cmd = firewall.CreateFirewall(test_cli20.MyApp(sys.stdout), None) - name = '' - tenant_id = 'my-tenant' - my_id = 'my-id' - policy_id = 'my-policy-id' - args = ['--tenant-id', tenant_id, policy_id, ] - position_names = ['firewall_policy_id', ] - position_values = [policy_id, ] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - admin_state_up=True, tenant_id=tenant_id) - - def test_create_firewall_with_all_params(self): - # firewall-create with all params set. - resource = 'firewall' - cmd = firewall.CreateFirewall(test_cli20.MyApp(sys.stdout), None) - name = 'my-name' - description = 'my-desc' - policy_id = 'my-policy-id' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--description', description, - '--admin-state-down', - '--tenant-id', tenant_id, - policy_id] - position_names = ['firewall_policy_id', ] - position_values = [policy_id, ] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - description=description, - admin_state_up=False, - tenant_id=tenant_id) - - def test_create_firewall_with_routers(self): - resource = 'firewall' - cmd = firewall.CreateFirewall(test_cli20.MyApp(sys.stdout), None) - name = 'my-name' - policy_id = 'my-policy-id' - my_id = 'my-id' - args = ['--router', 'fake-id', '--router', 'fake-name', policy_id] - router_ids = ['fake-id', 'fake-name'] - position_names = ['firewall_policy_id', 'router_ids'] - position_values = [policy_id, router_ids] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_list_firewalls(self): - # firewall-list. - resources = "firewalls" - cmd = firewall.ListFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_firewalls_pagination(self): - # firewall-list with pagination. - resources = "firewalls" - cmd = firewall.ListFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_firewalls_sort(self): - # sorted list: firewall-list --sort-key name --sort-key id - # --sort-key asc --sort-key desc - resources = "firewalls" - cmd = firewall.ListFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_firewalls_limit(self): - # size (1000) limited list: firewall-list -P. - resources = "firewalls" - cmd = firewall.ListFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_firewall_id(self): - # firewall-show test_id. - resource = 'firewall' - cmd = firewall.ShowFirewall(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_firewall_id_name(self): - # firewall-show. - resource = 'firewall' - cmd = firewall.ShowFirewall(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_firewall(self): - # firewall-update myid --name newname --tags a b. - resource = 'firewall' - cmd = firewall.UpdateFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_update_firewall_using_policy_name(self): - # firewall-update myid --policy newpolicy. - resource = 'firewall' - cmd = firewall.UpdateFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--policy', 'newpolicy'], - {'firewall_policy_id': 'newpolicy'}) - - def test_update_firewall_with_routers(self): - resource = 'firewall' - cmd = firewall.UpdateFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource( - resource, cmd, 'myid', - ['myid', '--router', 'fake-id', '--router', 'fake-name'], - {'router_ids': ['fake-id', 'fake-name']}) - - def test_update_firewall_with_no_routers(self): - resource = 'firewall' - cmd = firewall.UpdateFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource( - resource, cmd, 'myid', - ['myid', '--no-routers'], {'router_ids': []}) - - def test_update_firewall_with_bad_router_options(self): - resource = 'firewall' - cmd = firewall.UpdateFirewall(test_cli20.MyApp(sys.stdout), None) - self.assertRaises( - SystemExit, - self._test_update_resource, - resource, cmd, 'myid', - ['myid', '--no-routers', '--router', 'fake-id'], {}) - - def test_delete_firewall(self): - # firewall-delete my-id. - resource = 'firewall' - cmd = firewall.DeleteFirewall(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_update_firewall_admin_state(self): - # firewall-update myid --admin-state-up True. - resource = 'firewall' - cmd = firewall.UpdateFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--admin-state-up', 'True'], - {'admin_state_up': 'True'}) diff --git a/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py b/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py deleted file mode 100644 index 4cadfb2de..000000000 --- a/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright 2013 Big Switch Networks Inc. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.neutron.v2_0.fw import firewallpolicy -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FirewallPolicyJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20FirewallPolicyJSON, self).setUp() - - def test_create_firewall_policy_with_mandatory_params(self): - # firewall-policy-create with mandatory (none) params only. - resource = 'firewall_policy' - cmd = firewallpolicy.CreateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - tenant_id = 'my-tenant' - name = 'my-name' - my_id = 'myid' - args = ['--tenant-id', tenant_id, - '--admin-state_up', - name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - admin_state_up=True, tenant_id=tenant_id) - - def test_create_firewall_policy_with_all_params(self): - # firewall-policy-create with rule param of misc format. - resource = 'firewall_policy' - cmd = firewallpolicy.CreateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - description = 'my-desc' - firewall_rules_res = ['rule_id1', 'rule_id2'] - tenant_id = 'my-tenant' - my_id = 'myid' - position_names = ['name', ] - position_values = [name, ] - - # check for both str and unicode format firewall_rules_arg - for firewall_rules_arg in ['rule_id1 rule_id2', u'rule_id1 rule_id2']: - args = ['--description', description, - '--shared', - '--firewall-rules', firewall_rules_arg, - '--audited', - '--tenant-id', tenant_id, - '--admin-state_up', - name] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - description=description, shared=True, - firewall_rules=firewall_rules_res, - audited=True, admin_state_up=True, - tenant_id=tenant_id) - - def test_list_firewall_policies(self): - # firewall-policy-list. - resources = "firewall_policies" - cmd = firewallpolicy.ListFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_firewall_policies_pagination(self): - # firewall-policy-list.""" - resources = "firewall_policies" - cmd = firewallpolicy.ListFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_firewall_policies_sort(self): - # sorted list: firewall-policy-list --sort-key name --sort-key id - # --sort-key asc --sort-key desc - resources = "firewall_policies" - cmd = firewallpolicy.ListFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_firewall_policies_limit(self): - # size (1000) limited list: firewall-policy-list -P. - resources = "firewall_policies" - cmd = firewallpolicy.ListFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_firewall_policy_id(self): - # firewall-policy-show test_id. - resource = 'firewall_policy' - cmd = firewallpolicy.ShowFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_firewall_policy_id_name(self): - # firewall-policy-show. - resource = 'firewall_policy' - cmd = firewallpolicy.ShowFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_firewall_policy(self): - # firewall-policy-update myid --name newname. - resource = 'firewall_policy' - cmd = firewallpolicy.UpdateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_update_firewall_policy_with_rules(self): - # firewall-policy-update myid --firewall-rules "rule1 rule2". - resource = 'firewall_policy' - cmd = firewallpolicy.UpdateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - firewall_rules_arg = u'rule_id3 rule_id4' - firewall_rules_res = ['rule_id3', 'rule_id4'] - self._test_update_resource( - resource, cmd, 'myid', - ['myid', '--firewall-rules', firewall_rules_arg], - {'firewall_rules': firewall_rules_res, }) - - def test_delete_firewall_policy(self): - # firewall-policy-delete my-id. - resource = 'firewall_policy' - cmd = firewallpolicy.DeleteFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - my_id = 'myid1' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_insert_firewall_rule(self): - # firewall-policy-insert-rule myid newruleid --insert-before ruleAid - # --insert-after ruleBid - resource = 'firewall_policy' - cmd = firewallpolicy.FirewallPolicyInsertRule( - test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - args = ['myid', 'newrule', - '--insert-before', 'rule2', - '--insert-after', 'rule1'] - extrafields = {'firewall_rule_id': 'newrule', - 'insert_before': 'rule2', - 'insert_after': 'rule1'} - - body = extrafields - path = getattr(self.client, resource + "_insert_path") - cmd_parser = cmd.get_parser(resource + "_insert_rule") - resp = (test_cli20.MyResp(204), None) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - shell.run_command(cmd, cmd_parser, args) - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), 4) - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path % myid), - self.client), - 'PUT', body=test_cli20.MyComparator(body, self.client), - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - def test_remove_firewall_rule(self): - # firewall-policy-remove-rule myid ruleid - resource = 'firewall_policy' - cmd = firewallpolicy.FirewallPolicyRemoveRule( - test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - args = ['myid', 'removerule'] - extrafields = {'firewall_rule_id': 'removerule', } - - body = extrafields - path = getattr(self.client, resource + "_remove_path") - cmd_parser = cmd.get_parser(resource + "_remove_rule") - resp = (test_cli20.MyResp(204), None) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - shell.run_command(cmd, cmd_parser, args) - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), 2) - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path % myid), - self.client), - 'PUT', body=test_cli20.MyComparator(body, self.client), - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - def test_update_firewall_policy_name_shared_audited(self): - # firewall-policy-update myid --name newname2 --shared --audited - resource = 'firewall_policy' - cmd = firewallpolicy.UpdateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname2', - '--shared', 'True', '--audited', 'True'], - {'name': 'newname2', - 'shared': 'True', 'audited': 'True'}) diff --git a/neutronclient/tests/unit/fw/test_cli20_firewallrule.py b/neutronclient/tests/unit/fw/test_cli20_firewallrule.py deleted file mode 100644 index 50fabca8e..000000000 --- a/neutronclient/tests/unit/fw/test_cli20_firewallrule.py +++ /dev/null @@ -1,251 +0,0 @@ -# Copyright 2013 Big Switch Networks Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.fw import firewallrule -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FirewallRuleJSON(test_cli20.CLITestV20Base): - - def _test_create_firewall_rule_with_mandatory_params(self, enabled): - # firewall-rule-create with mandatory (none) params only. - resource = 'firewall_rule' - cmd = firewallrule.CreateFirewallRule(test_cli20.MyApp(sys.stdout), - None) - tenant_id = 'my-tenant' - name = '' - my_id = 'myid' - protocol = 'tcp' - action = 'allow' - ip_version = 4 - args = ['--tenant-id', tenant_id, - '--admin-state-up', - '--protocol', protocol, - '--action', action, - '--enabled', enabled] - position_names = [] - position_values = [] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - protocol=protocol, action=action, - enabled=enabled, tenant_id=tenant_id, - ip_version=ip_version) - - def test_create_enabled_firewall_rule_with_mandatory_params_lcase(self): - self._test_create_firewall_rule_with_mandatory_params(enabled='true') - - def test_create_disabled_firewall_rule_with_mandatory_params_lcase(self): - self._test_create_firewall_rule_with_mandatory_params(enabled='false') - - def test_create_enabled_firewall_rule_with_mandatory_params(self): - self._test_create_firewall_rule_with_mandatory_params(enabled='True') - - def test_create_disabled_firewall_rule_with_mandatory_params(self): - self._test_create_firewall_rule_with_mandatory_params(enabled='False') - - def _setup_create_firewall_rule_with_all_params( - self, protocol='tcp', protocol_cli=None, - action='allow', action_cli=None, ip_version='4'): - # firewall-rule-create with all params set. - resource = 'firewall_rule' - cmd = firewallrule.CreateFirewallRule(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - description = 'my-desc' - source_ip = '192.168.1.0/24' - destination_ip = '192.168.2.0/24' - source_port = '0:65535' - destination_port = '0:65535' - tenant_id = 'my-tenant' - my_id = 'myid' - enabled = 'True' - args = ['--description', description, - '--shared', - '--protocol', protocol_cli or protocol, - '--ip-version', ip_version, - '--source-ip-address', source_ip, - '--destination-ip-address', destination_ip, - '--source-port', source_port, - '--destination-port', destination_port, - '--action', action_cli or action, - '--enabled', enabled, - '--admin-state-up', - '--tenant-id', tenant_id] - position_names = [] - position_values = [] - if protocol == 'any': - protocol = None - if ip_version == '4' or ip_version == '6': - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - description=description, shared=True, - protocol=protocol, - ip_version=int(ip_version), - source_ip_address=source_ip, - destination_ip_address=destination_ip, - source_port=source_port, - destination_port=destination_port, - action=action, enabled='True', - tenant_id=tenant_id) - else: - self.assertRaises(SystemExit, self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values, - ip_version=int(ip_version), - source_ip_address=source_ip, - destination_ip_address=destination_ip, - source_port=source_port, - destination_port=destination_port, - action=action, enabled='True', - tenant_id=tenant_id) - - def test_create_firewall_rule_with_all_params(self): - self._setup_create_firewall_rule_with_all_params() - - def test_create_firewall_rule_with_proto_any(self): - self._setup_create_firewall_rule_with_all_params(protocol='any') - - def test_create_firewall_rule_with_IP_version_6(self): - self._setup_create_firewall_rule_with_all_params(ip_version='6') - - def test_create_firewall_rule_with_invalid_IP_version(self): - self._setup_create_firewall_rule_with_all_params(ip_version='5') - - def test_create_firewall_rule_with_proto_action_upper_capitalized(self): - for protocol in ('TCP', 'Tcp', 'ANY', 'AnY'): - self._setup_create_firewall_rule_with_all_params( - protocol=protocol.lower(), - protocol_cli=protocol) - for action in ('Allow', 'DENY', 'reject'): - self._setup_create_firewall_rule_with_all_params( - action=action.lower(), - action_cli=action) - - def test_list_firewall_rules(self): - # firewall-rule-list. - resources = "firewall_rules" - cmd = firewallrule.ListFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_firewall_rules_pagination(self): - # firewall-rule-list. - resources = "firewall_rules" - cmd = firewallrule.ListFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_firewall_rules_sort(self): - # firewall-rule-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "firewall_rules" - cmd = firewallrule.ListFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_firewall_rules_limit(self): - # firewall-rule-list -P.""" - resources = "firewall_rules" - cmd = firewallrule.ListFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_firewall_rule_id(self): - # firewall-rule-show test_id. - resource = 'firewall_rule' - cmd = firewallrule.ShowFirewallRule(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_firewall_rule_id_name(self): - # firewall-rule-show. - resource = 'firewall_rule' - cmd = firewallrule.ShowFirewallRule(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_firewall_rule(self): - # firewall-rule-update myid --name newname. - resource = 'firewall_rule' - cmd = firewallrule.UpdateFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - # firewall-rule-update myid --protocol any. - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--protocol', 'any'], - {'protocol': None, }) - - # firewall-rule-update myid --description any - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--description', 'any'], - {'description': 'any', }) - - # firewall-rule-update myid --source_ip_address 192.192.192.192 - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--source_ip_address', - '192.192.192.192'], - {'source_ip_address': '192.192.192.192', }) - - # firewall-rule-update myid --source_port 32767 - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--source_port', '32767'], - {'source_port': '32767', }) - - # firewall-rule-update myid --destination_ip_address 0.1.0.1 - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--destination_ip_address', - '0.1.0.1'], - {'destination_ip_address': '0.1.0.1', }) - - # firewall-rule-update myid --destination_port 65432 - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--destination_port', - '65432'], - {'destination_port': '65432', }) - - # firewall-rule-update myid --enabled False - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--enabled', 'False'], - {'enabled': 'False', }) - - # firewall-rule-update myid --action reject - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--action', 'reject'], - {'action': 'reject', }) - - # firewall-rule-update myid --shared false - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--shared', 'false'], - {'shared': 'false', }) - - def test_delete_firewall_rule(self): - # firewall-rule-delete my-id. - resource = 'firewall_rule' - cmd = firewallrule.DeleteFirewallRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'myid1' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) diff --git a/neutronclient/tests/unit/lb/__init__.py b/neutronclient/tests/unit/lb/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py b/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py deleted file mode 100644 index 61cb1b1a5..000000000 --- a/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py +++ /dev/null @@ -1,202 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.neutron.v2_0.lb import healthmonitor -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbHealthmonitorJSON(test_cli20.CLITestV20Base): - def test_create_healthmonitor_with_mandatory_params(self): - # lb-healthmonitor-create with mandatory params only. - resource = 'health_monitor' - cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - admin_state_up = False - delay = '60' - max_retries = '2' - timeout = '10' - type = 'TCP' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--admin-state-down', - '--delay', delay, - '--max-retries', max_retries, - '--timeout', timeout, - '--type', type, - '--tenant-id', tenant_id] - position_names = ['admin_state_up', 'delay', 'max_retries', 'timeout', - 'type', 'tenant_id'] - position_values = [admin_state_up, delay, max_retries, timeout, type, - tenant_id] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values) - - def test_create_healthmonitor_with_all_params(self): - # lb-healthmonitor-create with all params set. - resource = 'health_monitor' - cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - admin_state_up = False - delay = '60' - expected_codes = '200-202,204' - http_method = 'HEAD' - max_retries = '2' - timeout = '10' - type = 'TCP' - tenant_id = 'my-tenant' - url_path = '/health' - my_id = 'my-id' - args = ['--admin-state-down', - '--delay', delay, - '--expected-codes', expected_codes, - '--http-method', http_method, - '--max-retries', max_retries, - '--timeout', timeout, - '--type', type, - '--tenant-id', tenant_id, - '--url-path', url_path] - position_names = ['admin_state_up', 'delay', - 'expected_codes', 'http_method', - 'max_retries', 'timeout', - 'type', 'tenant_id', 'url_path'] - position_values = [admin_state_up, delay, - expected_codes, http_method, - max_retries, timeout, - type, tenant_id, url_path] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values) - - def test_list_healthmonitors(self): - # lb-healthmonitor-list. - resources = "health_monitors" - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_healthmonitors_pagination(self): - # lb-healthmonitor-list. - resources = "health_monitors" - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_healthmonitors_sort(self): - # lb-healthmonitor-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "health_monitors" - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_healthmonitors_limit(self): - # lb-healthmonitor-list -P. - resources = "health_monitors" - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_healthmonitor_id(self): - # lb-healthmonitor-show test_id. - resource = 'health_monitor' - cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_update_health_monitor(self): - # lb-healthmonitor-update myid --name myname --tags a b. - resource = 'health_monitor' - cmd = healthmonitor.UpdateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--timeout', '5'], - {'timeout': '5', }) - - def test_delete_healthmonitor(self): - # lb-healthmonitor-delete my-id.""" - resource = 'health_monitor' - cmd = healthmonitor.DeleteHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_associate_healthmonitor(self): - cmd = healthmonitor.AssociateHealthMonitor( - test_cli20.MyApp(sys.stdout), - None) - resource = 'health_monitor' - health_monitor_id = 'hm-id' - pool_id = 'p_id' - args = [health_monitor_id, pool_id] - - body = {resource: {'id': health_monitor_id}} - result = {resource: {'id': health_monitor_id}, } - result_str = self.client.serialize(result) - - path = getattr(self.client, - "associate_pool_health_monitors_path") % pool_id - return_tup = (test_cli20.MyResp(200), result_str) - cmd_parser = cmd.get_parser('test_' + resource) - parsed_args = cmd_parser.parse_args(args) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=return_tup) as mock_request: - cmd.run(parsed_args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.end_url(path), 'POST', - body=test_cli20.MyComparator(body, self.client), - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - def test_disassociate_healthmonitor(self): - cmd = healthmonitor.DisassociateHealthMonitor( - test_cli20.MyApp(sys.stdout), - None) - resource = 'health_monitor' - health_monitor_id = 'hm-id' - pool_id = 'p_id' - args = [health_monitor_id, pool_id] - - path = (getattr(self.client, - "disassociate_pool_health_monitors_path") % - {'pool': pool_id, 'health_monitor': health_monitor_id}) - return_tup = (test_cli20.MyResp(204), None) - cmd_parser = cmd.get_parser('test_' + resource) - parsed_args = cmd_parser.parse_args(args) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=return_tup) as mock_request: - cmd.run(parsed_args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.end_url(path), 'DELETE', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) diff --git a/neutronclient/tests/unit/lb/test_cli20_member.py b/neutronclient/tests/unit/lb/test_cli20_member.py deleted file mode 100644 index 8ce2a0f09..000000000 --- a/neutronclient/tests/unit/lb/test_cli20_member.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.lb import member -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbMemberJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20LbMemberJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_member(self): - # lb-member-create with mandatory params only. - resource = 'member' - cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) - address = '10.0.0.1' - port = '8080' - tenant_id = 'my-tenant' - my_id = 'my-id' - pool_id = 'pool-id' - args = ['--address', address, '--protocol-port', port, - '--tenant-id', tenant_id, pool_id] - position_names = ['address', 'protocol_port', 'tenant_id', 'pool_id', - 'admin_state_up'] - position_values = [address, port, tenant_id, pool_id, True] - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values, - admin_state_up=None) - - def test_create_member_all_params(self): - # lb-member-create with all available params. - resource = 'member' - cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) - address = '10.0.0.1' - admin_state_up = False - port = '8080' - weight = '1' - tenant_id = 'my-tenant' - my_id = 'my-id' - pool_id = 'pool-id' - args = ['--address', address, '--admin-state-down', - '--protocol-port', port, '--weight', weight, - '--tenant-id', tenant_id, pool_id] - position_names = [ - 'address', 'admin_state_up', 'protocol_port', 'weight', - 'tenant_id', 'pool_id' - ] - position_values = [address, admin_state_up, port, weight, - tenant_id, pool_id] - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values, - admin_state_up=None) - - def test_list_members(self): - # lb-member-list. - resources = "members" - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_members_pagination(self): - # lb-member-list. - resources = "members" - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_members_sort(self): - # lb-member-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "members" - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_members_limit(self): - # lb-member-list -P. - resources = "members" - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_member_id(self): - # lb-member-show test_id. - resource = 'member' - cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_update_member(self): - # lb-member-update myid --name myname --tags a b. - resource = 'member' - cmd = member.UpdateMember(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--tags', 'a', 'b'], - {'name': 'myname', 'tags': ['a', 'b'], }) - - def test_delete_member(self): - # lb-member-delete my-id. - resource = 'member' - cmd = member.DeleteMember(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) diff --git a/neutronclient/tests/unit/lb/test_cli20_pool.py b/neutronclient/tests/unit/lb/test_cli20_pool.py deleted file mode 100644 index 79bf23df8..000000000 --- a/neutronclient/tests/unit/lb/test_cli20_pool.py +++ /dev/null @@ -1,166 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.neutron.v2_0.lb import pool -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbPoolJSON(test_cli20.CLITestV20Base): - - def test_create_pool_with_mandatory_params(self): - # lb-pool-create with mandatory params only. - resource = 'pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - name = 'my-name' - lb_method = 'ROUND_ROBIN' - protocol = 'HTTP' - subnet_id = 'subnet-id' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--lb-method', lb_method, - '--name', name, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id] - position_names = ['admin_state_up', 'lb_method', 'name', - 'protocol', 'subnet_id', 'tenant_id'] - position_values = [True, lb_method, name, - protocol, subnet_id, tenant_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_pool_with_all_params(self): - # lb-pool-create with all params set. - resource = 'pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - name = 'my-name' - description = 'my-desc' - lb_method = 'ROUND_ROBIN' - protocol = 'HTTP' - subnet_id = 'subnet-id' - tenant_id = 'my-tenant' - my_id = 'my-id' - provider = 'lbaas' - args = ['--admin-state-down', - '--description', description, - '--lb-method', lb_method, - '--name', name, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id, - '--provider', provider] - position_names = ['admin_state_up', 'description', 'lb_method', 'name', - 'protocol', 'subnet_id', 'tenant_id', 'provider'] - position_values = [False, description, lb_method, name, - protocol, subnet_id, tenant_id, provider] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_list_pools(self): - # lb-pool-list. - resources = "pools" - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_pools_pagination(self): - # lb-pool-list. - resources = "pools" - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_pools_sort(self): - # lb-pool-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "pools" - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_pools_limit(self): - # lb-pool-list -P. - resources = "pools" - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_pool_id(self): - # lb-pool-show test_id. - resource = 'pool' - cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_pool_id_name(self): - # lb-pool-show. - resource = 'pool' - cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_pool(self): - # lb-pool-update myid --name newname --tags a b. - resource = 'pool' - cmd = pool.UpdatePool(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_delete_pool(self): - # lb-pool-delete my-id. - resource = 'pool' - cmd = pool.DeletePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_retrieve_pool_stats(self): - # lb-pool-stats test_id. - resource = 'pool' - cmd = pool.RetrievePoolStats(test_cli20.MyApp(sys.stdout), None) - my_id = self.test_id - fields = ['bytes_in', 'bytes_out'] - args = ['--fields', 'bytes_in', '--fields', 'bytes_out', my_id] - - query = "&".join(["fields=%s" % field for field in fields]) - expected_res = {'stats': {'bytes_in': '1234', 'bytes_out': '4321'}} - resstr = self.client.serialize(expected_res) - path = getattr(self.client, "pool_path_stats") - return_tup = (test_cli20.MyResp(200), resstr) - - cmd_parser = cmd.get_parser("test_" + resource) - parsed_args = cmd_parser.parse_args(args) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=return_tup) as mock_request: - cmd.run(parsed_args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), 2) - mock_request.assert_called_once_with( - test_cli20.end_url(path % my_id, query), 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - _str = self.fake_stdout.make_string() - self.assertIn('bytes_in', _str) - self.assertIn('bytes_out', _str) diff --git a/neutronclient/tests/unit/lb/test_cli20_vip.py b/neutronclient/tests/unit/lb/test_cli20_vip.py deleted file mode 100644 index b08de447e..000000000 --- a/neutronclient/tests/unit/lb/test_cli20_vip.py +++ /dev/null @@ -1,206 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.lb import vip -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbVipJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20LbVipJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_vip_with_mandatory_params(self): - # lb-vip-create with all mandatory params. - resource = 'vip' - cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) - pool_id = 'my-pool-id' - name = 'my-name' - subnet_id = 'subnet-id' - protocol_port = '1000' - protocol = 'TCP' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--name', name, - '--protocol-port', protocol_port, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id, - pool_id] - position_names = ['pool_id', 'name', 'protocol_port', 'protocol', - 'subnet_id', 'tenant_id'] - position_values = [pool_id, name, protocol_port, protocol, - subnet_id, tenant_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - admin_state_up=True) - - def test_create_vip_with_all_params(self): - # lb-vip-create with all params. - resource = 'vip' - cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) - pool_id = 'my-pool-id' - name = 'my-name' - description = 'my-desc' - address = '10.0.0.2' - admin_state = False - connection_limit = '1000' - subnet_id = 'subnet-id' - protocol_port = '80' - protocol = 'TCP' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--name', name, - '--description', description, - '--address', address, - '--admin-state-down', - '--connection-limit', connection_limit, - '--protocol-port', protocol_port, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id, - pool_id] - position_names = ['pool_id', 'name', 'description', 'address', - 'admin_state_up', 'connection_limit', - 'protocol_port', 'protocol', 'subnet_id', - 'tenant_id'] - position_values = [pool_id, name, description, address, - admin_state, connection_limit, protocol_port, - protocol, subnet_id, - tenant_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_vip_with_session_persistence_params(self): - # lb-vip-create with mandatory and session-persistence params. - resource = 'vip' - cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) - pool_id = 'my-pool-id' - name = 'my-name' - subnet_id = 'subnet-id' - protocol_port = '1000' - protocol = 'TCP' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--name', name, - '--protocol-port', protocol_port, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id, - pool_id, - '--session-persistence', 'type=dict', - 'type=cookie,cookie_name=pie', - '--optional-param', 'any'] - position_names = ['pool_id', 'name', 'protocol_port', 'protocol', - 'subnet_id', 'tenant_id', 'optional_param'] - position_values = [pool_id, name, protocol_port, protocol, - subnet_id, tenant_id, 'any'] - extra_body = { - 'session_persistence': { - 'type': 'cookie', - 'cookie_name': 'pie', - }, - } - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - admin_state_up=True, extra_body=extra_body) - - def test_list_vips(self): - # lb-vip-list. - resources = "vips" - cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_vips_pagination(self): - # lb-vip-list. - resources = "vips" - cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_vips_sort(self): - # lb-vip-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "vips" - cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_vips_limit(self): - # lb-vip-list -P. - resources = "vips" - cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_vip_id(self): - # lb-vip-show test_id. - resource = 'vip' - cmd = vip.ShowVip(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_vip_id_name(self): - # lb-vip-show. - resource = 'vip' - cmd = vip.ShowVip(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_vip(self): - # lb-vip-update myid --name myname --tags a b. - resource = 'vip' - cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--tags', 'a', 'b'], - {'name': 'myname', 'tags': ['a', 'b'], }) - - def test_update_vip_with_session_persistence(self): - resource = 'vip' - cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) - body = { - 'session_persistence': { - 'type': 'source', - }, - } - args = ['myid', '--session-persistence', 'type=dict', - 'type=source'] - self._test_update_resource(resource, cmd, 'myid', args, body) - - def test_update_vip_with_session_persistence_and_name(self): - resource = 'vip' - cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) - body = { - 'name': 'newname', - 'session_persistence': { - 'type': 'cookie', - 'cookie_name': 'pie', - }, - } - args = ['myid', '--name', 'newname', - '--session-persistence', 'type=dict', - 'type=cookie,cookie_name=pie'] - self._test_update_resource(resource, cmd, 'myid', args, body) - - def test_delete_vip(self): - # lb-vip-delete my-id. - resource = 'vip' - cmd = vip.DeleteVip(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) diff --git a/neutronclient/tests/unit/lb/v2/__init__.py b/neutronclient/tests/unit/lb/v2/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/lb/v2/test_cli20_healthmonitor.py b/neutronclient/tests/unit/lb/v2/test_cli20_healthmonitor.py deleted file mode 100644 index 945ac18e3..000000000 --- a/neutronclient/tests/unit/lb/v2/test_cli20_healthmonitor.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.lb.v2 import healthmonitor -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbHealthMonitorJSON(test_cli20.CLITestV20Base): - - def test_create_healthmonitor_with_mandatory_params(self): - # lbaas-healthmonitor-create with mandatory params only. - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - type = 'PING' - max_retries = '3' - delay = '10' - timeout = '60' - pool = 'pool1' - args = ['--type', type, '--max-retries', max_retries, - '--delay', delay, '--timeout', timeout, '--pool', pool] - position_names = ['type', 'max_retries', 'delay', 'timeout', 'pool_id'] - position_values = [type, max_retries, delay, timeout, pool] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_healthmonitor_with_all_params(self): - # lbaas-healthmonitor-create with all params set. - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - type = 'PING' - max_retries = '3' - delay = '10' - timeout = '60' - http_method = 'GET' - expected_codes = '201' - url_path = '/somepath' - pool = 'pool1' - name = 'healthmonitor1' - args = ['--admin-state-down', '--http-method', http_method, - '--expected-codes', expected_codes, '--url-path', url_path, - '--type', type, '--max-retries', max_retries, - '--delay', delay, '--timeout', timeout, '--pool', pool, - '--name', name] - position_names = ['admin_state_up', 'http_method', 'expected_codes', - 'url_path', 'type', 'max_retries', 'delay', - 'timeout', 'pool_id', 'name'] - position_values = [False, http_method, expected_codes, url_path, - type, max_retries, delay, timeout, pool, name] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_list_healthmonitors(self): - # lbaas-healthmonitor-list. - resources = 'healthmonitors' - cmd_resources = 'lbaas_healthmonitors' - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_healthmonitors_pagination(self): - # lbaas-healthmonitor-list with pagination. - resources = 'healthmonitors' - cmd_resources = 'lbaas_healthmonitors' - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd, - cmd_resources=cmd_resources) - - def test_list_healthmonitors_sort(self): - # lbaas-healthmonitor-list --sort-key id --sort-key asc. - resources = 'healthmonitors' - cmd_resources = 'lbaas_healthmonitors' - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_healthmonitors_limit(self): - # lbaas-healthmonitor-list -P. - resources = 'healthmonitors' - cmd_resources = 'lbaas_healthmonitors' - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000, - cmd_resources=cmd_resources) - - def test_show_healthmonitor_id(self): - # lbaas-healthmonitor-show test_id. - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource) - - def test_show_healthmonitor_id_name(self): - # lbaas-healthmonitor-show. - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource) - - def _test_update_hm(self, args, expected_values): - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - my_id = 'myid' - cmd = healthmonitor.UpdateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - args.insert(0, my_id) - self._test_update_resource(resource, cmd, my_id, - args, - expected_values, - cmd_resource=cmd_resource) - - def test_update_healthmonitor(self): - # lbaas-healthmonitor-update myid --name newname. - self._test_update_hm(['--name', 'newname'], {'name': 'newname', }) - # lbaas-healthmonitor-update myid --delay 10. - self._test_update_hm(['--delay', '10'], {'delay': '10'}) - # lbaas-healthmonitor-update myid --timeout 5. - self._test_update_hm(['--timeout', '5'], {'timeout': '5', }) - # lbaas-healthmonitor-update myid --delay 10. - self._test_update_hm(['--http-method', 'OPTIONS'], - {'http_method': 'OPTIONS'}) - # lbaas-healthmonitor-update myid --url-path /test/string . - self._test_update_hm(['--url-path', '/test/string'], - {'url_path': '/test/string', }) - # lbaas-healthmonitor-update myid --max-retries 5 - self._test_update_hm(['--max-retries', '5'], {'max_retries': '5'}) - # lbaas-healthmonitor-update myid --expected-codes 201 - self._test_update_hm(['--expected-codes', '201'], - {'expected_codes': '201'}) - # lbaas-healthmonitor-update myid --admin-state-up False - self._test_update_hm(['--admin-state-up', 'False'], - {'admin_state_up': 'False'}) - - def test_delete_healthmonitor(self): - # lbaas-healthmonitor-delete my-id. - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.DeleteHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource) diff --git a/neutronclient/tests/unit/lb/v2/test_cli20_l7policy.py b/neutronclient/tests/unit/lb/v2/test_cli20_l7policy.py deleted file mode 100644 index 71869315b..000000000 --- a/neutronclient/tests/unit/lb/v2/test_cli20_l7policy.py +++ /dev/null @@ -1,260 +0,0 @@ -# Copyright 2016 Radware LTD. -# All Rights Reserved -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.lb.v2 import l7policy -from neutronclient.tests.unit import test_cli20 - -"""Structure for mapping cli and api arguments - -The structure maps cli arguments and a list of its -api argument name, default cli value and default api value. -It helps to make tests more general for different argument types. -""" -args_conf = { - 'name': ['name', 'test_policy', 'test_policy'], - 'description': ['description', 'test policy', 'test policy'], - 'listener': ['listener_id', 'test_listener', 'test_listener'], - 'admin-state-up': ['admin_state_up', True, True], - 'admin-state-down': ['admin_state_up', None, False], - 'action': ['action', 'REJECT', 'REJECT'], - 'redirect-url': ['redirect_url', 'http://url', 'http://url'], - 'redirect-pool': ['redirect_pool_id', 'test_pool', 'test_pool'], - 'position': ['position', '1', 1]} - - -class CLITestV20LbL7PolicyJSON(test_cli20.CLITestV20Base): - - def _get_test_args(self, *args, **kwargs): - """Function for generically building testing arguments""" - cli_args = [] - api_args = {} - for arg in args: - cli_args.append('--' + arg) - if not args_conf[arg][1]: - pass - elif arg in kwargs: - cli_args.append(str(kwargs[arg])) - else: - cli_args.append(args_conf[arg][1]) - - if arg in kwargs: - api_args[args_conf[arg][0]] = kwargs[arg] - else: - api_args[args_conf[arg][0]] = args_conf[arg][2] - - return cli_args, api_args - - def _test_create_policy(self, *args, **kwargs): - resource = 'l7policy' - cmd_resource = 'lbaas_l7policy' - cmd = l7policy.CreateL7Policy(test_cli20.MyApp(sys.stdout), None) - cli_args, api_args = self._get_test_args(*args, **kwargs) - position_names = list(api_args.keys()) - position_values = list(api_args.values()) - self._test_create_resource(resource, cmd, None, 'test_id', - cli_args, position_names, position_values, - cmd_resource=cmd_resource) - - def _test_update_policy(self, *args, **kwargs): - resource = 'l7policy' - cmd_resource = 'lbaas_l7policy' - cmd = l7policy.UpdateL7Policy(test_cli20.MyApp(sys.stdout), None) - cli_args, api_args = self._get_test_args(*args, **kwargs) - cli_args.append('test_id') - self._test_update_resource(resource, cmd, 'test_id', - cli_args, api_args, - cmd_resource=cmd_resource) - - def test_create_policy_with_mandatory_params(self): - # lbaas-l7policy-create with mandatory params only. - self._test_create_policy('action', 'listener') - - def test_create_policy_with_all_params(self): - # lbaas-l7policy-create REJECT policy. - self._test_create_policy('name', 'description', - 'action', 'listener', - 'position') - - def test_create_disabled_policy(self): - # lbaas-l7policy-create disabled REJECT policy. - self._test_create_policy('action', 'listener', 'admin-state-down') - - def test_create_url_redirect_policy(self): - # lbaas-l7policy-create REDIRECT_TO_URL policy. - self._test_create_policy('name', 'description', - 'action', 'listener', - 'redirect-url', - action='REDIRECT_TO_URL') - - def test_create_url_redirect_policy_no_url(self): - # lbaas-l7policy-create REDIRECT_TO_URL policy without url argument. - self.assertRaises(exceptions.CommandError, - self._test_create_policy, - 'name', 'description', - 'action', 'listener', - action='REDIRECT_TO_URL') - - def test_create_pool_redirect_policy(self): - # lbaas-l7policy-create REDIRECT_TO_POOL policy. - self._test_create_policy('name', 'description', - 'action', 'listener', - 'redirect-pool', - action='REDIRECT_TO_POOL') - - def test_create_pool_redirect_policy_no_pool(self): - # lbaas-l7policy-create REDIRECT_TO_POOL policy without pool argument. - self.assertRaises(exceptions.CommandError, - self._test_create_policy, - 'name', 'description', - 'action', 'listener', - action='REDIRECT_TO_POOL') - - def test_create_reject_policy_with_url(self): - # lbaas-l7policy-create REJECT policy while specifying url argument. - self.assertRaises(exceptions.CommandError, - self._test_create_policy, - 'action', 'listener', - 'redirect-url') - - def test_create_reject_policy_with_pool(self): - # lbaas-l7policy-create REJECT policy while specifying pool argument. - self.assertRaises(exceptions.CommandError, - self._test_create_policy, - 'action', 'listener', - 'redirect-pool') - - def test_create_pool_redirect_policy_with_url(self): - # lbaas-l7policy-create REDIRECT_TO_POOL policy with url argument. - self.assertRaises(exceptions.CommandError, - self._test_create_policy, - 'action', 'listener', - 'redirect-pool', 'redirect-url', - action='REDIRECT_TO_POOL') - - def test_create_url_redirect_policy_with_pool(self): - # lbaas-l7policy-create REDIRECT_TO_URL policy with pool argument. - self.assertRaises(exceptions.CommandError, - self._test_create_policy, - 'action', 'listener', - 'redirect-pool', 'redirect-url', - action='REDIRECT_TO_URL') - - def test_list_policies(self): - # lbaas-l7policy-list. - - resources = 'l7policies' - cmd_resources = 'lbaas_l7policies' - cmd = l7policy.ListL7Policy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_policies_pagination(self): - # lbaas-l7policy-list with pagination. - - resources = 'l7policies' - cmd_resources = 'lbaas_l7policies' - cmd = l7policy.ListL7Policy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination( - resources, cmd, cmd_resources=cmd_resources) - - def test_list_policies_sort(self): - # lbaas-l7policy-list --sort-key id --sort-key asc. - - resources = 'l7policies' - cmd_resources = 'lbaas_l7policies' - cmd = l7policy.ListL7Policy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources( - resources, cmd, True, cmd_resources=cmd_resources) - - def test_list_policies_limit(self): - # lbaas-l7policy-list -P. - - resources = 'l7policies' - cmd_resources = 'lbaas_l7policies' - cmd = l7policy.ListL7Policy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources( - resources, cmd, page_size=1000, cmd_resources=cmd_resources) - - def test_show_policy_id(self): - # lbaas-l7policy-show test_id. - - resource = 'l7policy' - cmd_resource = 'lbaas_l7policy' - cmd = l7policy.ShowL7Policy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'test_id', self.test_id] - self._test_show_resource( - resource, cmd, self.test_id, args, - ['test_id'], cmd_resource=cmd_resource) - - def test_show_policy_id_name(self): - # lbaas-l7policy-show. - - resource = 'l7policy' - cmd_resource = 'lbaas_l7policy' - cmd = l7policy.ShowL7Policy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'test_id', '--fields', 'name', self.test_id] - self._test_show_resource( - resource, cmd, self.test_id, args, - ['test_id', 'name'], cmd_resource=cmd_resource) - - def test_disable_policy(self): - # lbaas-l7policy-update test_id --admin-state-up False. - - self._test_update_policy('admin-state-up', - **{'admin-state-up': 'False'}) - - def test_update_policy_name_and_description(self): - # lbaas-l7policy-update test_id --name other --description other_desc. - - self._test_update_policy('name', 'description', - name='name', - description='other desc') - - def test_update_pool_redirect_policy(self): - # lbaas-l7policy-update test_id --action REDIRECT_TO_POOL - # --redirect-pool id. - - self._test_update_policy('action', 'redirect-pool', - **{'action': 'REDIRECT_TO_POOL', - 'redirect-pool': 'id'}) - - def test_update_url_redirect_policy(self): - # lbaas-l7policy-update test_id --action REDIRECT_TO_URL - # --redirect-url http://other_url. - - self._test_update_policy('action', 'redirect-url', - **{'action': 'REDIRECT_TO_URL', - 'redirect-url': 'http://other_url'}) - - def test_update_policy_position(self): - # lbaas-l7policy-update test_id --position 2. - - self._test_update_policy('position', - position=2) - - def test_delete_policy(self): - # lbaas-l7policy-delete test_id. - - resource = 'l7policy' - cmd_resource = 'lbaas_l7policy' - cmd = l7policy.DeleteL7Policy(test_cli20.MyApp(sys.stdout), None) - test_id = 'test_id' - args = [test_id] - self._test_delete_resource(resource, cmd, test_id, args, - cmd_resource=cmd_resource) diff --git a/neutronclient/tests/unit/lb/v2/test_cli20_l7rule.py b/neutronclient/tests/unit/lb/v2/test_cli20_l7rule.py deleted file mode 100644 index 54830542d..000000000 --- a/neutronclient/tests/unit/lb/v2/test_cli20_l7rule.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2016 Radware LTD. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.lb.v2 import l7rule -from neutronclient.tests.unit import test_cli20 - - -"""Structure for mapping cli and api arguments - -The structure maps cli arguments and a list of its -api argument name, default cli value and default api value. -It helps to make tests more general for different argument types. -""" -args_conf = { - 'admin-state-up': ['admin_state_up', True, True], - 'admin-state-down': ['admin_state_up', None, False], - 'type': ['type', 'HOST_NAME', 'HOST_NAME'], - 'compare-type': ['compare_type', 'EQUAL_TO', 'EQUAL_TO'], - 'invert-compare': ['invert', None, True], - 'key': ['key', 'key', 'key'], - 'value': ['value', 'value', 'value']} - - -class CLITestV20LbL7RuleJSON(test_cli20.CLITestV20Base): - - def _get_test_args(self, *args, **kwargs): - """Function for generically building testing arguments""" - cli_args = [] - api_args = {} - for arg in args: - cli_args.append('--' + arg) - if not args_conf[arg][1]: - pass - elif arg in kwargs: - cli_args.append(str(kwargs[arg])) - else: - cli_args.append(args_conf[arg][1]) - - if arg in kwargs: - api_args[args_conf[arg][0]] = kwargs[arg] - else: - api_args[args_conf[arg][0]] = args_conf[arg][2] - - if 'invert' not in api_args: - api_args['invert'] = False - return cli_args, api_args - - def _test_create_rule(self, *args, **kwargs): - resource = 'rule' - cmd_resource = 'lbaas_l7rule' - cmd = l7rule.CreateL7Rule(test_cli20.MyApp(sys.stdout), None) - cli_args, api_args = self._get_test_args(*args, **kwargs) - position_names = list(api_args.keys()) - position_values = list(api_args.values()) - cli_args.append('test_policy') - self._test_create_resource(resource, cmd, None, 'test_id', - cli_args, position_names, position_values, - cmd_resource=cmd_resource, - parent_id='test_policy') - - def _test_update_rule(self, *args, **kwargs): - resource = 'rule' - cmd_resource = 'lbaas_l7rule' - cmd = l7rule.UpdateL7Rule(test_cli20.MyApp(sys.stdout), None) - cli_args, api_args = self._get_test_args(*args, **kwargs) - cli_args.append('test_id') - cli_args.append('test_policy') - self._test_update_resource(resource, cmd, 'test_id', - cli_args, api_args, - cmd_resource=cmd_resource, - parent_id='test_policy') - - def test_create_rule_with_mandatory_params(self): - # lbaas-l7rule-create with mandatory params only. - - self._test_create_rule('type', 'compare-type', - 'value') - - def test_create_disabled_rule(self): - # lbaas-l7rule-create disabled rule. - - self._test_create_rule('type', 'compare-type', - 'value', 'admin-state-down') - - def test_create_rule_with_all_params(self): - # lbaas-l7rule-create with all params set. - - self._test_create_rule('type', 'compare-type', - 'invert-compare', 'key', 'value', - type='HEADER', compare_type='CONTAINS', - key='other_key', value='other_value') - - def test_create_rule_with_inverted_compare(self): - # lbaas-l7rule-create with invertted compare type. - - self._test_create_rule('type', 'compare-type', - 'invert-compare', 'value') - - def test_list_rules(self): - # lbaas-l7rule-list. - - resources = 'rules' - cmd_resources = 'lbaas_l7rules' - cmd = l7rule.ListL7Rule(test_cli20.MyApp(sys.stdout), None) - - policy_id = 'policy_id' - self._test_list_resources(resources, cmd, True, - base_args=[policy_id], - cmd_resources=cmd_resources, - parent_id=policy_id, - query="l7policy_id=%s" % policy_id) - - def test_list_rules_pagination(self): - # lbaas-l7rule-list with pagination. - - resources = 'rules' - cmd_resources = 'lbaas_l7rules' - cmd = l7rule.ListL7Rule(test_cli20.MyApp(sys.stdout), None) - policy_id = 'policy_id' - self._test_list_resources_with_pagination( - resources, cmd, base_args=[policy_id], - cmd_resources=cmd_resources, parent_id=policy_id, - query="l7policy_id=%s" % policy_id) - - def test_list_rules_sort(self): - # lbaas-l7rule-list --sort-key id --sort-key asc. - - resources = 'rules' - cmd_resources = 'lbaas_l7rules' - cmd = l7rule.ListL7Rule(test_cli20.MyApp(sys.stdout), None) - policy_id = 'policy_id' - self._test_list_resources( - resources, cmd, True, base_args=[policy_id], - cmd_resources=cmd_resources, parent_id=policy_id, - query="l7policy_id=%s" % policy_id) - - def test_list_rules_limit(self): - # lbaas-l7rule-list -P. - - resources = 'rules' - cmd_resources = 'lbaas_l7rules' - cmd = l7rule.ListL7Rule(test_cli20.MyApp(sys.stdout), None) - policy_id = 'policy_id' - self._test_list_resources(resources, cmd, page_size=1000, - base_args=[policy_id], - cmd_resources=cmd_resources, - parent_id=policy_id, - query="l7policy_id=%s" % policy_id) - - def test_show_rule_id(self): - # lbaas-l7rule-show test_id. - - resource = 'rule' - cmd_resource = 'lbaas_l7rule' - policy_id = 'policy_id' - cmd = l7rule.ShowL7Rule(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id, policy_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource, - parent_id=policy_id) - - def test_update_rule_type(self): - # lbaas-l7rule-update test_id --type HEADER test_policy - - self._test_update_rule('type', type='HEADER') - - def test_update_rule_compare_type(self): - # lbaas-l7rule-update test_id --compare-type CONTAINS test_policy. - - self._test_update_rule('compare-type', - **{'compare-type': 'CONTAINS'}) - - def test_update_rule_inverted_compare_type(self): - # lbaas-l7rule-update test_id --invert-compare test_policy. - - self._test_update_rule('invert-compare') - - def test_update_rule_key_value(self): - # lbaas-l7rule-update test_id --key other --value other test_policy. - - self._test_update_rule('key', 'value', - key='other', value='other') - - def test_delete_rule(self): - # lbaas-l7rule-delete test_id policy_id. - - resource = 'rule' - cmd_resource = 'lbaas_l7rule' - policy_id = 'policy_id' - test_id = 'test_id' - cmd = l7rule.DeleteL7Rule(test_cli20.MyApp(sys.stdout), None) - args = [test_id, policy_id] - self._test_delete_resource(resource, cmd, test_id, args, - cmd_resource=cmd_resource, - parent_id=policy_id) diff --git a/neutronclient/tests/unit/lb/v2/test_cli20_listener.py b/neutronclient/tests/unit/lb/v2/test_cli20_listener.py deleted file mode 100644 index 3993ea7f7..000000000 --- a/neutronclient/tests/unit/lb/v2/test_cli20_listener.py +++ /dev/null @@ -1,194 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.lb.v2 import listener -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbListenerJSON(test_cli20.CLITestV20Base): - - def test_create_listener_with_loadbalancer(self): - # lbaas-listener-create with --loadbalancer - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - loadbalancer_id = 'loadbalancer' - protocol = 'TCP' - protocol_port = '80' - args = ['--protocol', protocol, '--protocol-port', protocol_port, - '--loadbalancer', loadbalancer_id] - position_names = ['protocol', 'protocol_port', 'loadbalancer_id'] - position_values = [protocol, protocol_port, loadbalancer_id, - True] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_listener_with_default_pool(self): - # lbaas-listener-create with --default-pool and no --loadbalancer. - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - default_pool_id = 'default-pool' - protocol = 'TCP' - protocol_port = '80' - args = ['--protocol', protocol, '--protocol-port', protocol_port, - '--default-pool', default_pool_id] - position_names = ['protocol', 'protocol_port', 'default_pool_id'] - position_values = [protocol, protocol_port, default_pool_id, - True] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_listener_with_no_loadbalancer_or_default_pool(self): - # lbaas-listener-create without --default-pool or --loadbalancer. - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - protocol = 'TCP' - protocol_port = '80' - args = ['--protocol', protocol, '--protocol-port', protocol_port] - position_names = ['protocol', 'protocol_port'] - position_values = [protocol, protocol_port, True] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource, - no_api_call=True, - expected_exception=exceptions.CommandError) - - def test_create_listener_with_all_params(self): - # lbaas-listener-create with all params set. - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - loadbalancer = 'loadbalancer' - default_pool_id = 'default-pool' - protocol = 'TCP' - protocol_port = '80' - connection_limit = 10 - def_tls_cont_ref = '11111' - args = ['--admin-state-down', - '--protocol', protocol, '--protocol-port', protocol_port, - '--loadbalancer', loadbalancer, - '--default-pool', default_pool_id, - '--default-tls-container-ref', def_tls_cont_ref, - '--sni-container-refs', '1111', '2222', '3333', - '--connection-limit', '10'] - position_names = ['admin_state_up', - 'protocol', 'protocol_port', 'loadbalancer_id', - 'default_pool_id', - 'default_tls_container_ref', 'sni_container_refs', - 'connection_limit'] - position_values = [False, protocol, protocol_port, loadbalancer, - default_pool_id, - def_tls_cont_ref, ['1111', '2222', '3333'], - connection_limit] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_list_listeners(self): - # lbaas-listener-list. - resources = 'listeners' - cmd_resources = 'lbaas_listeners' - cmd = listener.ListListener(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_listeners_pagination(self): - # lbaas-listener-list with pagination. - resources = 'listeners' - cmd_resources = 'lbaas_listeners' - cmd = listener.ListListener(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd, - cmd_resources=cmd_resources) - - def test_list_listeners_sort(self): - # lbaas-listener-list --sort-key id --sort-key asc. - resources = 'listeners' - cmd_resources = 'lbaas_listeners' - cmd = listener.ListListener(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_listeners_limit(self): - # lbaas-listener-list -P. - resources = 'listeners' - cmd_resources = 'lbaas_listeners' - cmd = listener.ListListener(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000, - cmd_resources=cmd_resources) - - def test_show_listener_id(self): - # lbaas-listener-show test_id. - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.ShowListener(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource) - - def test_show_listener_id_name(self): - # lbaas-listener-show. - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.ShowListener(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource) - - def _test_update_listener(self, args, expected_values): - resource = 'listener' - cmd_resource = 'lbaas_listener' - my_id = 'myid' - args.insert(0, my_id) - cmd = listener.UpdateListener(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, my_id, - args, expected_values, - cmd_resource=cmd_resource) - - def test_update_listener(self): - # lbaas-listener-update myid --name newname. - self._test_update_listener(['--name', 'newname'], - {'name': 'newname', }) - # lbaas-listener-update myid --description check. - self._test_update_listener(['--description', 'check'], - {'description': 'check', }) - # lbaas-listener-update myid --connection-limit -1 - self._test_update_listener(['--connection-limit', '-1'], - {'connection_limit': -1, }) - # lbaas-listener-update myid --admin-state-up False. - self._test_update_listener(['--admin-state-up', 'False'], - {'admin_state_up': 'False', }) - - def test_delete_listener(self): - # lbaas-listener-delete my-id. - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.DeleteListener(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource) diff --git a/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py b/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py deleted file mode 100644 index 3a6010cee..000000000 --- a/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py +++ /dev/null @@ -1,213 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.neutron.v2_0.lb.v2 import loadbalancer as lb -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbLoadBalancerJSON(test_cli20.CLITestV20Base): - - def test_create_loadbalancer_with_mandatory_params(self): - # lbaas-loadbalancer-create with mandatory params only. - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.CreateLoadBalancer(test_cli20.MyApp(sys.stdout), None) - name = 'lbaas-loadbalancer-name' - vip_subnet_id = 'vip-subnet' - my_id = 'my-id' - args = [vip_subnet_id] - position_names = ['vip_subnet_id'] - position_values = [vip_subnet_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_loadbalancer_with_all_params(self): - # lbaas-loadbalancer-create with all params set. - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.CreateLoadBalancer(test_cli20.MyApp(sys.stdout), None) - name = 'lbaas-loadbalancer-name' - description = 'lbaas-loadbalancer-desc' - flavor_id = 'lbaas-loadbalancer-flavor' - vip_subnet_id = 'vip-subnet' - my_id = 'my-id' - args = ['--admin-state-down', '--description', description, - '--name', name, '--flavor', flavor_id, vip_subnet_id] - position_names = ['admin_state_up', 'description', 'name', - 'flavor_id', 'vip_subnet_id'] - position_values = [False, description, name, flavor_id, vip_subnet_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_list_loadbalancers(self): - # lbaas-loadbalancer-list. - resources = 'loadbalancers' - cmd_resources = 'lbaas_loadbalancers' - cmd = lb.ListLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_loadbalancers_pagination(self): - # lbaas-loadbalancer-list with pagination. - resources = 'loadbalancers' - cmd_resources = 'lbaas_loadbalancers' - cmd = lb.ListLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd, - cmd_resources=cmd_resources) - - def test_list_loadbalancers_sort(self): - # lbaas-loadbalancer-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = 'loadbalancers' - cmd_resources = 'lbaas_loadbalancers' - cmd = lb.ListLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"], - cmd_resources=cmd_resources) - - def test_list_loadbalancers_limit(self): - # lbaas-loadbalancer-list -P. - resources = 'loadbalancers' - cmd_resources = 'lbaas_loadbalancers' - cmd = lb.ListLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000, - cmd_resources=cmd_resources) - - def test_show_loadbalancer_id(self): - # lbaas-loadbalancer-loadbalancer-show test_id. - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.ShowLoadBalancer(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource) - - def test_show_loadbalancer_id_name(self): - # lbaas-loadbalancer-loadbalancer-show. - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.ShowLoadBalancer(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource) - - def _test_update_lb(self, args, expected_values): - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - my_id = 'myid' - args.insert(0, my_id) - cmd = lb.UpdateLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, my_id, - args, expected_values, - cmd_resource=cmd_resource) - - def test_update_loadbalancer(self): - # lbaas-loadbalancer-update myid --name newname. - self._test_update_lb(['--name', 'newname'], {'name': 'newname', }) - # lbaas-loadbalancer-update myid --description check. - self._test_update_lb(['--description', 'check'], - {'description': 'check', }) - # lbaas-loadbalancer-update myid --admin-state-up False. - self._test_update_lb(['--admin-state-up', 'False'], - {'admin_state_up': 'False', }) - - def test_delete_loadbalancer(self): - # lbaas-loadbalancer-loadbalancer-delete my-id. - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.DeleteLoadBalancer(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource) - - def test_retrieve_loadbalancer_stats(self): - # lbaas-loadbalancer-stats test_id. - resource = 'loadbalancer' - cmd = lb.RetrieveLoadBalancerStats(test_cli20.MyApp(sys.stdout), None) - my_id = self.test_id - fields = ['bytes_in', 'bytes_out'] - args = ['--fields', 'bytes_in', '--fields', 'bytes_out', my_id] - - query = "&".join(["fields=%s" % field for field in fields]) - expected_res = {'stats': {'bytes_in': '1234', 'bytes_out': '4321'}} - resstr = self.client.serialize(expected_res) - path = getattr(self.client, "lbaas_loadbalancer_path_stats") - return_tup = (test_cli20.MyResp(200), resstr) - - cmd_parser = cmd.get_parser("test_" + resource) - parsed_args = cmd_parser.parse_args(args) - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=return_tup) as mock_request: - cmd.run(parsed_args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), 2) - mock_request.assert_called_once_with( - test_cli20.end_url(path % my_id, query), 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - _str = self.fake_stdout.make_string() - self.assertIn('bytes_in', _str) - self.assertIn('1234', _str) - self.assertIn('bytes_out', _str) - self.assertIn('4321', _str) - - def test_get_loadbalancer_statuses(self): - # lbaas-loadbalancer-status test_id. - resource = 'loadbalancer' - cmd = lb.RetrieveLoadBalancerStatus(test_cli20.MyApp(sys.stdout), None) - my_id = self.test_id - args = [my_id] - - expected_res = {'statuses': {'operating_status': 'ONLINE', - 'provisioning_status': 'ACTIVE'}} - - resstr = self.client.serialize(expected_res) - - path = getattr(self.client, "lbaas_loadbalancer_path_status") - return_tup = (test_cli20.MyResp(200), resstr) - - cmd_parser = cmd.get_parser("test_" + resource) - parsed_args = cmd_parser.parse_args(args) - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=return_tup) as mock_request: - cmd.run(parsed_args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.end_url(path % my_id), 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - _str = self.fake_stdout.make_string() - self.assertIn('operating_status', _str) - self.assertIn('ONLINE', _str) - self.assertIn('provisioning_status', _str) - self.assertIn('ACTIVE', _str) diff --git a/neutronclient/tests/unit/lb/v2/test_cli20_member.py b/neutronclient/tests/unit/lb/v2/test_cli20_member.py deleted file mode 100644 index 057da4254..000000000 --- a/neutronclient/tests/unit/lb/v2/test_cli20_member.py +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.lb.v2 import member -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbMemberJSON(test_cli20.CLITestV20Base): - - def test_create_member_with_mandatory_params(self): - # lbaas-member-create with mandatory params only. - resource = 'member' - cmd_resource = 'lbaas_member' - cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - address = '10.1.1.1' - protocol_port = '80' - pool_id = 'pool-id' - subnet_id = 'subnet-id' - args = ['--address', address, '--protocol-port', protocol_port, - '--subnet', subnet_id, pool_id] - position_names = ['admin_state_up', 'address', - 'protocol_port', 'subnet_id'] - position_values = [True, address, protocol_port, subnet_id] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource, - parent_id=pool_id) - - def test_create_member_with_all_params(self): - # lbaas-member-create with all params set. - resource = 'member' - cmd_resource = 'lbaas_member' - cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - address = '10.1.1.1' - protocol_port = '80' - pool_id = 'pool-id' - subnet_id = 'subnet-id' - weight = '100' - name = 'member1' - args = ['--address', address, '--protocol-port', protocol_port, - '--subnet', subnet_id, pool_id, '--weight', weight, - '--admin-state-down', '--name', name] - position_names = ['admin_state_up', 'address', 'protocol_port', - 'subnet_id', 'weight', 'name'] - position_values = [False, address, protocol_port, - subnet_id, weight, name] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - cmd_resource=cmd_resource, - parent_id=pool_id) - - def test_list_members(self): - # lbaas-member-list. - resources = 'members' - cmd_resources = 'lbaas_members' - pool_id = 'pool-id' - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, base_args=[pool_id], - cmd_resources=cmd_resources, - parent_id=pool_id, - query="pool_id=%s" % pool_id) - - def test_list_members_pagination(self): - # lbaas-member-list with pagination. - resources = 'members' - cmd_resources = 'lbaas_members' - pool_id = 'pool-id' - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd, - base_args=[pool_id], - cmd_resources=cmd_resources, - parent_id=pool_id, - query="pool_id=%s" % pool_id) - - def test_list_members_sort(self): - # lbaas-member-list --sort-key id --sort-key asc. - resources = 'members' - cmd_resources = 'lbaas_members' - pool_id = 'pool-id' - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, base_args=[pool_id], - cmd_resources=cmd_resources, - parent_id=pool_id, - query="pool_id=%s" % pool_id) - - def test_list_members_limit(self): - # lbaas-member-list -P. - resources = 'members' - cmd_resources = 'lbaas_members' - pool_id = 'pool-id' - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000, - base_args=[pool_id], - cmd_resources=cmd_resources, - parent_id=pool_id, - query="pool_id=%s" % pool_id) - - def test_show_member_id(self): - # lbaas-member-show test_id. - resource = 'member' - cmd_resource = 'lbaas_member' - pool_id = 'pool-id' - cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id, pool_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource, parent_id=pool_id) - - def test_show_member_id_name(self): - # lbaas-member-show. - resource = 'member' - cmd_resource = 'lbaas_member' - pool_id = 'pool-id' - cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id, pool_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource, parent_id=pool_id) - - def test_update_member(self): - # lbaas-member-update myid --name newname. - resource = 'member' - cmd_resource = 'lbaas_member' - my_id = 'my-id' - pool_id = 'pool-id' - args = [my_id, pool_id, '--name', 'newname'] - cmd = member.UpdateMember(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, my_id, args, - {'name': 'newname', }, - cmd_resource=cmd_resource, - parent_id=pool_id) - # lbaas-member-update myid --weight 100. - args = [my_id, pool_id, '--weight', '100'] - self._test_update_resource(resource, cmd, my_id, args, - {'weight': '100', }, - cmd_resource=cmd_resource, - parent_id=pool_id) - # lbaas-member-update myid --admin-state-up False - args = [my_id, pool_id, '--admin-state-up', 'False'] - self._test_update_resource(resource, cmd, my_id, args, - {'admin_state_up': 'False', }, - cmd_resource=cmd_resource, - parent_id=pool_id) - - def test_delete_member(self): - # lbaas-member-delete my-id. - resource = 'member' - cmd_resource = 'lbaas_member' - cmd = member.DeleteMember(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - pool_id = 'pool-id' - args = [my_id, pool_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource, - parent_id=pool_id) diff --git a/neutronclient/tests/unit/lb/v2/test_cli20_pool.py b/neutronclient/tests/unit/lb/v2/test_cli20_pool.py deleted file mode 100644 index 8c1f428a3..000000000 --- a/neutronclient/tests/unit/lb/v2/test_cli20_pool.py +++ /dev/null @@ -1,202 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.lb.v2 import pool -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbPoolJSON(test_cli20.CLITestV20Base): - - def test_create_pool_with_listener(self): - # lbaas-pool-create with listener - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - lb_algorithm = 'ROUND_ROBIN' - listener = 'listener' - protocol = 'TCP' - args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol, - '--listener', listener] - position_names = ['admin_state_up', 'lb_algorithm', 'protocol', - 'listener_id'] - position_values = [True, lb_algorithm, protocol, listener] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_pool_with_loadbalancer_no_listener(self): - """lbaas-pool-create with loadbalancer, no listener.""" - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - lb_algorithm = 'ROUND_ROBIN' - loadbalancer = 'loadbalancer' - protocol = 'TCP' - args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol, - '--loadbalancer', loadbalancer] - position_names = ['admin_state_up', 'lb_algorithm', 'protocol', - 'loadbalancer_id'] - position_values = [True, lb_algorithm, protocol, loadbalancer] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_pool_with_no_listener_or_loadbalancer(self): - """lbaas-pool-create with no listener or loadbalancer.""" - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - lb_algorithm = 'ROUND_ROBIN' - protocol = 'TCP' - args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol] - position_names = ['admin_state_up', 'lb_algorithm', 'protocol'] - position_values = [True, lb_algorithm, protocol] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource, - no_api_call=True, - expected_exception=exceptions.CommandError) - - def test_create_pool_with_all_params(self): - # lbaas-pool-create with all params set. - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - lb_algorithm = 'ROUND_ROBIN' - listener = 'listener' - loadbalancer = 'loadbalancer' - protocol = 'TCP' - description = 'description' - session_persistence_str = 'type=APP_COOKIE,cookie_name=1234' - session_persistence = {'type': 'APP_COOKIE', - 'cookie_name': '1234'} - name = 'my-pool' - args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol, - '--description', description, '--session-persistence', - session_persistence_str, '--admin-state-down', '--name', name, - '--listener', listener, '--loadbalancer', loadbalancer] - position_names = ['lb_algorithm', 'protocol', 'description', - 'session_persistence', 'admin_state_up', 'name', - 'listener_id', 'loadbalancer_id'] - position_values = [lb_algorithm, protocol, description, - session_persistence, False, name, listener, - loadbalancer] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_list_pools(self): - # lbaas-pool-list. - resources = 'pools' - cmd_resources = 'lbaas_pools' - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_pools_pagination(self): - # lbaas-pool-list with pagination. - resources = 'pools' - cmd_resources = 'lbaas_pools' - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd, - cmd_resources=cmd_resources) - - def test_list_pools_sort(self): - # lbaas-pool-list --sort-key id --sort-key asc. - resources = 'pools' - cmd_resources = 'lbaas_pools' - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_pools_limit(self): - # lbaas-pool-list -P. - resources = 'pools' - cmd_resources = 'lbaas_pools' - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000, - cmd_resources=cmd_resources) - - def test_show_pool_id(self): - # lbaas-pool-show test_id. - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource) - - def test_show_pool_id_name(self): - # lbaas-pool-show. - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource) - - def test_update_pool(self): - # lbaas-pool-update myid --name newname --description SuperPool - # --lb-algorithm SOURCE_IP --admin-state-up - # --session-persistence type=dict,type=HTTP_COOKIE,cookie_name=pie - - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.UpdatePool(test_cli20.MyApp(sys.stdout), None) - args = ['myid', '--name', 'newname', - '--description', 'SuperPool', '--lb-algorithm', "SOURCE_IP", - '--admin-state-up', 'True', - '--session-persistence', 'type=dict,' - 'type=HTTP_COOKIE,cookie_name=pie'] - body = {'name': 'newname', - "description": "SuperPool", - "lb_algorithm": "SOURCE_IP", - "admin_state_up": 'True', - 'session_persistence': { - 'type': 'HTTP_COOKIE', - 'cookie_name': 'pie', - }, } - self._test_update_resource(resource, cmd, 'myid', args, body, - cmd_resource=cmd_resource) - # lbaas-pool-update myid --name Name - # --no-session-persistence - - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.UpdatePool(test_cli20.MyApp(sys.stdout), None) - args = ['myid', '--name', 'Name', '--no-session-persistence'] - body = {'name': "Name", - "session_persistence": None, } - self._test_update_resource(resource, cmd, 'myid', args, body, - cmd_resource=cmd_resource) - - def test_delete_pool(self): - # lbaas-pool-delete my-id. - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.DeletePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource) diff --git a/neutronclient/tests/unit/qos/__init__.py b/neutronclient/tests/unit/qos/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/qos/test_cli20_bandwidth_limit_rule.py b/neutronclient/tests/unit/qos/test_cli20_bandwidth_limit_rule.py deleted file mode 100644 index 8d4380a81..000000000 --- a/neutronclient/tests/unit/qos/test_cli20_bandwidth_limit_rule.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2015 Huawei Technologies India Pvt Ltd. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.qos import bandwidth_limit_rule as bw_rule -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20QoSBandwidthLimitRuleJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['bandwidth_limit_rule'] - - def setUp(self): - super(CLITestV20QoSBandwidthLimitRuleJSON, self).setUp() - self.res = 'bandwidth_limit_rule' - self.cmd_res = 'qos_bandwidth_limit_rule' - self.ress = self.res + 's' - self.cmd_ress = self.cmd_res + 's' - - def test_create_bandwidth_limit_rule_with_max_kbps(self): - cmd = bw_rule.CreateQoSBandwidthLimitRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - max_kbps = '1337' - policy_id = 'policy_id' - args = ['--max-kbps', max_kbps, policy_id] - position_names = ['max_kbps'] - position_values = [max_kbps] - self._test_create_resource(self.res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_create_bandwidth_limit_rule_with_max_burst_kbps(self): - cmd = bw_rule.CreateQoSBandwidthLimitRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - max_burst_kbps = '1337' - policy_id = 'policy_id' - args = ['--max-burst-kbps', max_burst_kbps, policy_id] - position_names = ['max_burst_kbps'] - position_values = [max_burst_kbps] - self._test_create_resource(self.res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_create_bandwidth_limit_rule_with_all_params(self): - cmd = bw_rule.CreateQoSBandwidthLimitRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - max_kbps = '1337' - max_burst_kbps = '1337' - policy_id = 'policy_id' - args = ['--max-kbps', max_kbps, - '--max-burst-kbps', max_burst_kbps, - policy_id] - position_names = ['max_kbps', 'max_burst_kbps'] - position_values = [max_kbps, max_burst_kbps] - self._test_create_resource(self.res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_update_bandwidth_limit_rule_with_max_kbps(self): - cmd = bw_rule.UpdateQoSBandwidthLimitRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - max_kbps = '1337' - policy_id = 'policy_id' - args = ['--max-kbps', max_kbps, my_id, policy_id] - self._test_update_resource(self.res, cmd, my_id, args, - {'max_kbps': max_kbps, }, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_update_bandwidth_limit_rule_with_max_burst_kbps(self): - cmd = bw_rule.UpdateQoSBandwidthLimitRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - max_burst_kbps = '1337' - policy_id = 'policy_id' - args = ['--max-burst-kbps', max_burst_kbps, - my_id, policy_id] - self._test_update_resource(self.res, cmd, my_id, args, - {'max_burst_kbps': max_burst_kbps}, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_update_bandwidth_limit_rule_with_all_params(self): - cmd = bw_rule.UpdateQoSBandwidthLimitRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - max_kbps = '1337' - max_burst_kbps = '1337' - policy_id = 'policy_id' - args = ['--max-kbps', max_kbps, - '--max-burst-kbps', max_burst_kbps, - my_id, policy_id] - self._test_update_resource(self.res, cmd, my_id, args, - {'max_kbps': max_kbps, - 'max_burst_kbps': max_burst_kbps}, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_delete_bandwidth_limit_rule(self): - cmd = bw_rule.DeleteQoSBandwidthLimitRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - policy_id = 'policy_id' - args = [my_id, policy_id] - self._test_delete_resource(self.res, cmd, my_id, args, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_show_bandwidth_limit_rule(self): - cmd = bw_rule.ShowQoSBandwidthLimitRule(test_cli20.MyApp(sys.stdout), - None) - policy_id = 'policy_id' - args = ['--fields', 'id', self.test_id, policy_id] - self._test_show_resource(self.res, cmd, self.test_id, args, - ['id'], cmd_resource=self.cmd_res, - parent_id=policy_id) diff --git a/neutronclient/tests/unit/qos/test_cli20_dscp_marking_rule.py b/neutronclient/tests/unit/qos/test_cli20_dscp_marking_rule.py deleted file mode 100644 index 881b2f373..000000000 --- a/neutronclient/tests/unit/qos/test_cli20_dscp_marking_rule.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright 2016 Comcast Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.qos import dscp_marking_rule as dscp_rule -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20QoSDscpMarkingRuleJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['dscp_marking_rule'] - - def setUp(self): - super(CLITestV20QoSDscpMarkingRuleJSON, self).setUp() - self.dscp_res = 'dscp_marking_rule' - self.dscp_cmd_res = 'qos_dscp_marking_rule' - self.dscp_ress = self.dscp_res + 's' - self.dscp_cmd_ress = self.dscp_cmd_res + 's' - - def test_create_dscp_marking_rule_with_dscp_mark(self): - cmd = dscp_rule.CreateQoSDscpMarkingRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - policy_id = 'policy_id' - position_names = ['dscp_mark'] - valid_dscp_marks = ['0', '56'] - invalid_dscp_marks = ['-1', '19', '42', '44', '57', '58'] - for dscp_mark in valid_dscp_marks: - args = ['--dscp-mark', dscp_mark, policy_id] - position_values = [dscp_mark] - self._test_create_resource(self.dscp_res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.dscp_cmd_res, - parent_id=policy_id) - for dscp_mark in invalid_dscp_marks: - args = ['--dscp-mark', dscp_mark, policy_id] - position_values = [dscp_mark] - self._test_create_resource( - self.dscp_res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.dscp_cmd_res, - parent_id=policy_id, - no_api_call=True, - expected_exception=exceptions.CommandError) - - def test_update_dscp_marking_rule_with_dscp_mark(self): - cmd = dscp_rule.UpdateQoSDscpMarkingRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - dscp_mark = '56' - policy_id = 'policy_id' - args = ['--dscp-mark', dscp_mark, - my_id, policy_id] - self._test_update_resource(self.dscp_res, cmd, my_id, args, - {'dscp_mark': dscp_mark}, - cmd_resource=self.dscp_cmd_res, - parent_id=policy_id) - - def test_delete_dscp_marking_rule(self): - cmd = dscp_rule.DeleteQoSDscpMarkingRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - policy_id = 'policy_id' - args = [my_id, policy_id] - self._test_delete_resource(self.dscp_res, cmd, my_id, args, - cmd_resource=self.dscp_cmd_res, - parent_id=policy_id) - - def test_show_dscp_marking_rule(self): - cmd = dscp_rule.ShowQoSDscpMarkingRule(test_cli20.MyApp(sys.stdout), - None) - policy_id = 'policy_id' - args = ['--fields', 'id', self.test_id, policy_id] - self._test_show_resource(self.dscp_res, cmd, self.test_id, args, - ['id'], cmd_resource=self.dscp_cmd_res, - parent_id=policy_id) diff --git a/neutronclient/tests/unit/qos/test_cli20_minimum_bandwidth_rule.py b/neutronclient/tests/unit/qos/test_cli20_minimum_bandwidth_rule.py deleted file mode 100644 index 39dccd614..000000000 --- a/neutronclient/tests/unit/qos/test_cli20_minimum_bandwidth_rule.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright (c) 2016 Intel Corporation. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.qos import minimum_bandwidth_rule as bw_rule -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20QoSMinimumBandwidthRuleJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['minimum_bandwidth_rule'] - - def setUp(self): - super(CLITestV20QoSMinimumBandwidthRuleJSON, self).setUp() - self.res = 'minimum_bandwidth_rule' - self.cmd_res = 'qos_minimum_bandwidth_rule' - self.ress = self.res + 's' - self.cmd_ress = self.cmd_res + 's' - - def test_create_minimum_bandwidth_rule_min_kbps_only(self): - cmd = bw_rule.CreateQoSMinimumBandwidthRule( - test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - min_kbps = '1500' - policy_id = 'policy_id' - args = ['--min-kbps', min_kbps, - policy_id] - position_names = ['min_kbps'] - position_values = [min_kbps] - self.assertRaises(SystemExit, self._test_create_resource, - self.res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.cmd_res, - parent_id=policy_id, - no_api_call=True) - - def test_create_minimum_bandwidth_rule_direction_only(self): - cmd = bw_rule.CreateQoSMinimumBandwidthRule( - test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - direction = 'egress' - policy_id = 'policy_id' - args = ['--direction', direction, - policy_id] - position_names = ['direction'] - position_values = [direction] - self.assertRaises(SystemExit, self._test_create_resource, - self.res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.cmd_res, - parent_id=policy_id, - no_api_call=True) - - def test_create_minimum_bandwidth_rule_none(self): - cmd = bw_rule.CreateQoSMinimumBandwidthRule( - test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - policy_id = 'policy_id' - args = [policy_id] - position_names = [] - position_values = [] - self.assertRaises(SystemExit, self._test_create_resource, - self.res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.cmd_res, - parent_id=policy_id, - no_api_call=True) - - def test_create_minimum_bandwidth_rule_all(self): - cmd = bw_rule.CreateQoSMinimumBandwidthRule( - test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - min_kbps = '1500' - direction = 'egress' - policy_id = 'policy_id' - args = ['--min-kbps', min_kbps, - '--direction', direction, - policy_id] - position_names = ['direction', 'min_kbps'] - position_values = [direction, min_kbps] - self._test_create_resource(self.res, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_update_minimum_bandwidth_rule(self): - cmd = bw_rule.UpdateQoSMinimumBandwidthRule( - test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - min_kbps = '1200' - direction = 'egress' - policy_id = 'policy_id' - args = ['--min-kbps', min_kbps, - '--direction', direction, - my_id, policy_id] - self._test_update_resource(self.res, cmd, my_id, args, - {'min_kbps': min_kbps, - 'direction': direction}, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_delete_minimum_bandwidth_rule(self): - cmd = bw_rule.DeleteQoSMinimumBandwidthRule( - test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - policy_id = 'policy_id' - args = [my_id, policy_id] - self._test_delete_resource(self.res, cmd, my_id, args, - cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_show_minimum_bandwidth_rule(self): - cmd = bw_rule.ShowQoSMinimumBandwidthRule( - test_cli20.MyApp(sys.stdout), None) - policy_id = 'policy_id' - args = [self.test_id, policy_id] - self._test_show_resource(self.res, cmd, self.test_id, args, - [], cmd_resource=self.cmd_res, - parent_id=policy_id) - - def test_list_minimum_bandwidth_rule(self): - cmd = bw_rule.ListQoSMinimumBandwidthRules( - test_cli20.MyApp(sys.stdout), None) - policy_id = 'policy_id' - args = [policy_id] - contents = [{'name': 'rule1', 'min-kbps': 1000, 'direction': 'egress'}] - self._test_list_resources(self.ress, cmd, parent_id=policy_id, - cmd_resources=self.cmd_ress, - base_args=args, response_contents=contents) diff --git a/neutronclient/tests/unit/qos/test_cli20_policy.py b/neutronclient/tests/unit/qos/test_cli20_policy.py deleted file mode 100644 index b1db866e4..000000000 --- a/neutronclient/tests/unit/qos/test_cli20_policy.py +++ /dev/null @@ -1,192 +0,0 @@ -# Copyright 2015 Huawei Technologies India Pvt Ltd. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.qos import policy as policy -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20QoSPolicyJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['policy'] - - def setUp(self): - super(CLITestV20QoSPolicyJSON, self).setUp() - self.res = 'policy' - self.cmd_res = 'qos_policy' - self.ress = "policies" - self.cmd_ress = 'qos_policies' - - def test_create_policy_with_only_keyattributes(self): - # Create qos policy abc. - cmd = policy.CreateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - name = 'abc' - args = [name] - position_names = ['name'] - position_values = [name] - self._test_create_resource(self.res, cmd, name, myid, args, - position_names, position_values, - cmd_resource=self.cmd_res) - - def test_create_policy_with_description(self): - # Create qos policy xyz --description abc. - cmd = policy.CreateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - name = 'abc' - description = 'policy_abc' - args = [name, '--description', description] - position_names = ['name', 'description'] - position_values = [name, description] - self._test_create_resource(self.res, cmd, name, myid, args, - position_names, position_values, - cmd_resource=self.cmd_res) - - def test_create_policy_with_shared(self): - # Create qos policy abc shared across tenants - cmd = policy.CreateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - name = 'abc' - description = 'policy_abc' - args = [name, '--description', description, '--shared'] - position_names = ['name', 'description', 'shared'] - position_values = [name, description, True] - self._test_create_resource(self.res, cmd, name, myid, args, - position_names, position_values, - cmd_resource=self.cmd_res) - - def test_create_policy_with_unicode(self): - # Create qos policy u'\u7f51\u7edc'. - cmd = policy.CreateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - name = u'\u7f51\u7edc' - description = u'\u7f51\u7edc' - args = [name, '--description', description] - position_names = ['name', 'description'] - position_values = [name, description] - self._test_create_resource(self.res, cmd, name, myid, args, - position_names, position_values, - cmd_resource=self.cmd_res) - - def test_update_policy(self): - # policy-update myid --name newname. - cmd = policy.UpdateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(self.res, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }, - cmd_resource=self.cmd_res) - - def test_update_policy_description(self): - # policy-update myid --name newname --description newdesc - cmd = policy.UpdateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(self.res, cmd, 'myid', - ['myid', '--description', 'newdesc'], - {'description': 'newdesc', }, - cmd_resource=self.cmd_res) - - def test_update_policy_to_shared(self): - # policy-update myid --shared - cmd = policy.UpdateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(self.res, cmd, 'myid', - ['myid', '--shared'], - {'shared': True, }, - cmd_resource=self.cmd_res) - - def test_update_policy_to_no_shared(self): - # policy-update myid --no-shared - cmd = policy.UpdateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(self.res, cmd, 'myid', - ['myid', '--no-shared'], - {'shared': False, }, - cmd_resource=self.cmd_res) - - def test_update_policy_to_shared_no_shared_together(self): - # policy-update myid --shared --no-shared - cmd = policy.UpdateQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self.assertRaises( - SystemExit, - self._test_update_resource, - self.res, cmd, 'myid', - ['myid', '--shared', '--no-shared'], {}, - cmd_resource=self.cmd_res - ) - - def test_list_policies(self): - # qos-policy-list. - cmd = policy.ListQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(self.ress, cmd, True, - cmd_resources=self.cmd_ress) - - def test_list_policies_pagination(self): - # qos-policy-list for pagination. - cmd = policy.ListQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(self.ress, cmd, - cmd_resources=self.cmd_ress) - - def test_list_policies_sort(self): - # sorted list: qos-policy-list --sort-key name --sort-key id - # --sort-key asc --sort-key desc - cmd = policy.ListQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(self.ress, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"], - cmd_resources=self.cmd_ress) - - def test_list_policies_limit(self): - # size (1000) limited list: qos-policy-list -P. - cmd = policy.ListQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(self.ress, cmd, page_size=1000, - cmd_resources=self.cmd_ress) - - def test_show_policy_id(self): - # qos-policy-show test_id. - cmd = policy.ShowQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(self.res, cmd, self.test_id, args, - ['id'], cmd_resource=self.cmd_res) - - def test_show_policy_name(self): - # qos-policy-show. - cmd = policy.ShowQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(self.res, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=self.cmd_res) - - def test_delete_policy(self): - # qos-policy-delete my-id. - cmd = policy.DeleteQoSPolicy(test_cli20.MyApp(sys.stdout), - None) - my_id = 'myid1' - args = [my_id] - self._test_delete_resource(self.res, cmd, my_id, args, - cmd_resource=self.cmd_res) diff --git a/neutronclient/tests/unit/qos/test_cli20_rule.py b/neutronclient/tests/unit/qos/test_cli20_rule.py deleted file mode 100644 index f77c3c410..000000000 --- a/neutronclient/tests/unit/qos/test_cli20_rule.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2015 Huawei Technologies India Pvt Ltd. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0.qos import rule as qos_rule -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20QoSRuleJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['bandwidth_limit_rule', - 'dscp_marking_rule', - 'minimum_bandwidth_rule'] - - def setUp(self): - super(CLITestV20QoSRuleJSON, self).setUp() - - def test_list_qos_rule_types(self): - # qos_rule_types. - resources = 'rule_types' - cmd_resources = 'qos_rule_types' - response_contents = [{'type': 'bandwidth_limit'}, - {'type': 'dscp_marking'}, - {'type': 'minimum_bandwidth'}] - - cmd = qos_rule.ListQoSRuleTypes(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True, - response_contents=response_contents, - cmd_resources=cmd_resources) diff --git a/neutronclient/tests/unit/test_auto_allocated_topology.py b/neutronclient/tests/unit/test_auto_allocated_topology.py deleted file mode 100644 index e2f7e5b13..000000000 --- a/neutronclient/tests/unit/test_auto_allocated_topology.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright 2016 IBM -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0 import auto_allocated_topology as aat -from neutronclient.tests.unit import test_cli20 - - -class TestAutoAllocatedTopologyJSON(test_cli20.CLITestV20Base): - - def test_show_auto_allocated_topology_arg(self): - resource = 'auto_allocated_topology' - cmd = aat.ShowAutoAllocatedTopology(test_cli20.MyApp(sys.stdout), None) - args = ['--tenant-id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args) - - def test_show_auto_allocated_topology_posarg(self): - resource = 'auto_allocated_topology' - cmd = aat.ShowAutoAllocatedTopology(test_cli20.MyApp(sys.stdout), None) - args = ['some-tenant'] - self._test_show_resource(resource, cmd, "some-tenant", args) - - def test_show_auto_allocated_topology_no_arg(self): - resource = 'auto_allocated_topology' - cmd = aat.ShowAutoAllocatedTopology(test_cli20.MyApp(sys.stdout), None) - args = [] - self._test_show_resource(resource, cmd, "None", args) - - def test_show_auto_allocated_topology_dry_run_as_tenant(self): - resource = 'auto_allocated_topology' - cmd = aat.ShowAutoAllocatedTopology(test_cli20.MyApp(sys.stdout), None) - args = ['--dry-run'] - self._test_show_resource(resource, cmd, "None", args, - fields=('dry-run',)) - - def test_show_auto_allocated_topology_dry_run_as_admin(self): - resource = 'auto_allocated_topology' - cmd = aat.ShowAutoAllocatedTopology(test_cli20.MyApp(sys.stdout), None) - args = ['--dry-run', 'some-tenant'] - self._test_show_resource(resource, cmd, "some-tenant", args, - fields=('dry-run',)) - - def test_delete_auto_allocated_topology_arg(self): - resource = 'auto_allocated_topology' - cmd = aat.DeleteAutoAllocatedTopology(test_cli20.MyApp(sys.stdout), - None) - args = ['--tenant-id', self.test_id] - self._test_delete_resource(resource, cmd, self.test_id, args) - - def test_delete_auto_allocated_topology_posarg(self): - resource = 'auto_allocated_topology' - cmd = aat.DeleteAutoAllocatedTopology(test_cli20.MyApp(sys.stdout), - None) - args = ['some-tenant'] - self._test_delete_resource(resource, cmd, "some-tenant", args) - - def test_delete_auto_allocated_topology_no_arg(self): - resource = 'auto_allocated_topology' - cmd = aat.DeleteAutoAllocatedTopology(test_cli20.MyApp(sys.stdout), - None) - args = [] - self._test_delete_resource(resource, cmd, "None", args) diff --git a/neutronclient/tests/unit/test_cli20.py b/neutronclient/tests/unit/test_cli20.py deleted file mode 100644 index a067ee893..000000000 --- a/neutronclient/tests/unit/test_cli20.py +++ /dev/null @@ -1,1215 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# 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 contextlib -from io import StringIO -import itertools -import sys -from unittest import mock -import urllib.parse as urlparse - -from oslo_serialization import jsonutils -from oslo_utils import encodeutils -from oslotest import base -import requests -import yaml - -from neutronclient.common import constants -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.neutron import v2_0 as neutronV2_0 -from neutronclient.neutron.v2_0 import network -from neutronclient import shell -from neutronclient.v2_0 import client - -API_VERSION = "2.0" -TOKEN = 'testtoken' -ENDURL = 'localurl' -REQUEST_ID = 'test_request_id' - - -@contextlib.contextmanager -def capture_std_streams(): - fake_stdout, fake_stderr = StringIO(), StringIO() - stdout, stderr = sys.stdout, sys.stderr - try: - sys.stdout, sys.stderr = fake_stdout, fake_stderr - yield fake_stdout, fake_stderr - finally: - sys.stdout, sys.stderr = stdout, stderr - - -class FakeStdout(object): - - def __init__(self): - self.content = [] - - def write(self, text): - self.content.append(text) - - def make_string(self): - result = '' - for line in self.content: - result += encodeutils.safe_decode(line, 'utf-8') - return result - - -class MyRequest(requests.Request): - def __init__(self, method=None): - self.method = method - - -class MyResp(requests.Response): - def __init__(self, status_code, headers=None, reason=None, - request=None, url=None): - self.status_code = status_code - self.headers = headers or {} - self.reason = reason - self.request = request or MyRequest() - self.url = url - - -class MyApp(object): - def __init__(self, _stdout): - self.stdout = _stdout - - -def end_url(path, query=None): - _url_str = ENDURL + "/v" + API_VERSION + path - return query and _url_str + "?" + query or _url_str - - -class MyUrlComparator(object): - def __init__(self, lhs, client): - self.lhs = lhs - self.client = client - - def __eq__(self, rhs): - lhsp = urlparse.urlparse(self.lhs) - rhsp = urlparse.urlparse(rhs) - - lhs_qs = urlparse.parse_qsl(lhsp.query) - rhs_qs = urlparse.parse_qsl(rhsp.query) - - return (lhsp.scheme == rhsp.scheme and - lhsp.netloc == rhsp.netloc and - lhsp.path == rhsp.path and - len(lhs_qs) == len(rhs_qs) and - set(lhs_qs) == set(rhs_qs)) - - def __str__(self): - return self.lhs - - def __repr__(self): - return str(self) - - -class MyComparator(object): - def __init__(self, lhs, client): - self.lhs = lhs - self.client = client - - def _com_dict(self, lhs, rhs): - if len(lhs) != len(rhs): - return False - for key, value in lhs.items(): - if key not in rhs: - return False - rhs_value = rhs[key] - if not self._com(value, rhs_value): - return False - return True - - def _com_list(self, lhs, rhs): - if len(lhs) != len(rhs): - return False - for lhs_value in lhs: - if lhs_value not in rhs: - return False - return True - - def _com(self, lhs, rhs): - if lhs is None: - return rhs is None - if isinstance(lhs, dict): - if not isinstance(rhs, dict): - return False - return self._com_dict(lhs, rhs) - if isinstance(lhs, list): - if not isinstance(rhs, list): - return False - return self._com_list(lhs, rhs) - if isinstance(lhs, tuple): - if not isinstance(rhs, tuple): - return False - return self._com_list(lhs, rhs) - return lhs == rhs - - def __eq__(self, rhs): - if self.client: - rhs = self.client.deserialize(rhs, 200) - return self._com(self.lhs, rhs) - - def __repr__(self): - if self.client: - return self.client.serialize(self.lhs) - return str(self.lhs) - - -class ContainsKeyValue(object): - """Checks whether key/value pair(s) are included in a dict parameter. - - This class just checks whether specifid key/value pairs passed in - __init__() are included in a dict parameter. The comparison does not - fail even if other key/value pair(s) exists in a target dict. - """ - - def __init__(self, expected): - self._expected = expected - - def __eq__(self, other): - if not isinstance(other, dict): - return False - for key, value in self._expected.items(): - if key not in other: - return False - if other[key] != value: - return False - return True - - def __repr__(self): - return ('<%s (expected: %s)>' % - (self.__class__.__name__, self._expected)) - - -class IsA(object): - """Checks whether the parameter is of specific type.""" - - def __init__(self, expected_type): - self._expected_type = expected_type - - def __eq__(self, other): - return isinstance(other, self._expected_type) - - def __repr__(self): - return ('<%s (expected: %s)>' % - (self.__class__.__name__, self._expected_type)) - - -class CLITestV20Base(base.BaseTestCase): - - test_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' - id_field = 'id' - - non_admin_status_resources = [] - - def _find_resourceid(self, client, resource, name_or_id, - cmd_resource=None, parent_id=None): - return name_or_id - - def setUp(self, plurals=None): - """Prepare the test environment.""" - super(CLITestV20Base, self).setUp() - client.Client.EXTED_PLURALS.update(constants.PLURALS) - if plurals is not None: - client.Client.EXTED_PLURALS.update(plurals) - self.metadata = {'plurals': client.Client.EXTED_PLURALS} - self.endurl = ENDURL - self.fake_stdout = FakeStdout() - - self.addCleanup(mock.patch.stopall) - mock.patch('sys.stdout', new=self.fake_stdout).start() - mock.patch('neutronclient.neutron.v2_0.find_resourceid_by_name_or_id', - new=self._find_resourceid).start() - mock.patch('neutronclient.neutron.v2_0.find_resourceid_by_id', - new=self._find_resourceid).start() - - self.client = client.Client(token=TOKEN, endpoint_url=self.endurl) - - def register_non_admin_status_resource(self, resource_name): - # TODO(amotoki): - # It is recommended to define - # "non_admin_status_resources in each test class rather than - # using register_non_admin_status_resource method. - - # If we change self.non_admin_status_resources like this, - # we need to ensure this should be an instance variable - # to avoid changing the class variable. - if (id(self.non_admin_status_resources) == - id(self.__class__.non_admin_status_resources)): - self.non_admin_status_resources = (self.__class__. - non_admin_status_resources[:]) - self.non_admin_status_resources.append(resource_name) - - def _test_create_resource(self, resource, cmd, name, myid, args, - position_names, position_values, - tenant_id=None, tags=None, admin_state_up=True, - extra_body=None, cmd_resource=None, - parent_id=None, no_api_call=False, - expected_exception=None, - **kwargs): - if not cmd_resource: - cmd_resource = resource - if (resource in self.non_admin_status_resources): - body = {resource: {}, } - else: - body = {resource: {'admin_state_up': admin_state_up, }, } - if tenant_id: - body[resource].update({'tenant_id': tenant_id}) - if tags: - body[resource].update({'tags': tags}) - if extra_body: - body[resource].update(extra_body) - body[resource].update(kwargs) - - for i in range(len(position_names)): - body[resource].update({position_names[i]: position_values[i]}) - ress = {resource: - {self.id_field: myid}, } - if name: - ress[resource].update({'name': name}) - resstr = self.client.serialize(ress) - # url method body - resource_plural = self.client.get_resource_plural(cmd_resource) - path = getattr(self.client, resource_plural + "_path") - if parent_id: - path = path % parent_id - mock_body = MyComparator(body, self.client) - - cmd_parser = cmd.get_parser('create_' + resource) - resp = (MyResp(200), resstr) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - if expected_exception: - self.assertRaises(expected_exception, - shell.run_command, cmd, cmd_parser, args) - else: - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - if not no_api_call: - mock_request.assert_called_once_with( - end_url(path), 'POST', - body=mock_body, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})) - if not expected_exception: - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - if name: - self.assertIn(name, _str) - - def _test_list_columns(self, cmd, resources, - resources_out, args=('-f', 'json'), - cmd_resources=None, parent_id=None): - if not cmd_resources: - cmd_resources = resources - - resstr = self.client.serialize(resources_out) - - path = getattr(self.client, cmd_resources + "_path") - if parent_id: - path = path % parent_id - cmd_parser = cmd.get_parser("list_" + cmd_resources) - resp = (MyResp(200), resstr) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - mock_request.assert_called_once_with( - end_url(path), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})) - - def _test_list_resources(self, resources, cmd, detail=False, tags=(), - fields_1=(), fields_2=(), page_size=None, - sort_key=(), sort_dir=(), response_contents=None, - base_args=None, path=None, cmd_resources=None, - parent_id=None, output_format=None, query=""): - if not cmd_resources: - cmd_resources = resources - if response_contents is None: - contents = [{self.id_field: 'myid1', }, - {self.id_field: 'myid2', }, ] - else: - contents = response_contents - reses = {resources: contents} - resstr = self.client.serialize(reses) - # url method body - args = base_args if base_args is not None else [] - if detail: - args.append('-D') - if fields_1: - for field in fields_1: - args.append('--fields') - args.append(field) - - if tags: - args.append('--') - args.append("--tag") - for tag in tags: - args.append(tag) - tag_query = urlparse.urlencode( - {'tag': encodeutils.safe_encode(tag)}) - if query: - query += "&" + tag_query - else: - query = tag_query - if (not tags) and fields_2: - args.append('--') - if fields_2: - args.append("--fields") - for field in fields_2: - args.append(field) - if detail: - query = query and query + '&verbose=True' or 'verbose=True' - for field in itertools.chain(fields_1, fields_2): - if query: - query += "&fields=" + field - else: - query = "fields=" + field - if page_size: - args.append("--page-size") - args.append(str(page_size)) - if query: - query += "&limit=%s" % page_size - else: - query = "limit=%s" % page_size - if sort_key: - for key in sort_key: - args.append('--sort-key') - args.append(key) - if query: - query += '&' - query += 'sort_key=%s' % key - if sort_dir: - len_diff = len(sort_key) - len(sort_dir) - if len_diff > 0: - sort_dir = tuple(sort_dir) + ('asc',) * len_diff - elif len_diff < 0: - sort_dir = sort_dir[:len(sort_key)] - for dir in sort_dir: - args.append('--sort-dir') - args.append(dir) - if query: - query += '&' - query += 'sort_dir=%s' % dir - if path is None: - path = getattr(self.client, cmd_resources + "_path") - if parent_id: - path = path % parent_id - if output_format: - args.append('-f') - args.append(output_format) - cmd_parser = cmd.get_parser("list_" + cmd_resources) - resp = (MyResp(200), resstr) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - mock_request.assert_called_once_with( - MyUrlComparator(end_url(path, query), self.client), - 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})) - _str = self.fake_stdout.make_string() - if response_contents is None: - self.assertIn('myid1', _str) - return _str - - def _test_list_resources_with_pagination(self, resources, cmd, - base_args=None, - cmd_resources=None, - parent_id=None, query=""): - if not cmd_resources: - cmd_resources = resources - - path = getattr(self.client, cmd_resources + "_path") - if parent_id: - path = path % parent_id - fake_query = "marker=myid2&limit=2" - reses1 = {resources: [{'id': 'myid1', }, - {'id': 'myid2', }], - '%s_links' % resources: [{'href': end_url(path, fake_query), - 'rel': 'next'}]} - reses2 = {resources: [{'id': 'myid3', }, - {'id': 'myid4', }]} - resstr1 = self.client.serialize(reses1) - resstr2 = self.client.serialize(reses2) - cmd_parser = cmd.get_parser("list_" + cmd_resources) - args = base_args if base_args is not None else [] - mock_request_calls = [ - mock.call( - end_url(path, query), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})), - mock.call( - MyUrlComparator(end_url(path, fake_query), - self.client), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN}))] - mock_request_resp = [(MyResp(200), resstr1), (MyResp(200), resstr2)] - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, - "request") as mock_request: - mock_request.side_effect = mock_request_resp - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - self.assertEqual(2, mock_request.call_count) - mock_request.assert_has_calls(mock_request_calls) - - def _test_update_resource(self, resource, cmd, myid, args, extrafields, - cmd_resource=None, parent_id=None): - if not cmd_resource: - cmd_resource = resource - - body = {resource: extrafields} - path = getattr(self.client, cmd_resource + "_path") - if parent_id: - path = path % (parent_id, myid) - else: - path = path % myid - mock_body = MyComparator(body, self.client) - - cmd_parser = cmd.get_parser("update_" + cmd_resource) - resp = (MyResp(204), None) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - mock_request.assert_called_once_with( - MyUrlComparator(end_url(path), self.client), - 'PUT', - body=mock_body, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})) - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - - def _test_show_resource(self, resource, cmd, myid, args, fields=(), - cmd_resource=None, parent_id=None): - if not cmd_resource: - cmd_resource = resource - - query = "&".join(["fields=%s" % field for field in fields]) - expected_res = {resource: - {self.id_field: myid, - 'name': 'myname', }, } - resstr = self.client.serialize(expected_res) - path = getattr(self.client, cmd_resource + "_path") - if parent_id: - path = path % (parent_id, myid) - else: - path = path % myid - cmd_parser = cmd.get_parser("show_" + cmd_resource) - resp = (MyResp(200), resstr) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - mock_request.assert_called_once_with( - end_url(path, query), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})) - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - self.assertIn('myname', _str) - - def _test_set_path_and_delete(self, path, parent_id, myid, - mock_request_calls, mock_request_returns, - delete_fail=False): - return_val = 404 if delete_fail else 204 - if parent_id: - path = path % (parent_id, myid) - else: - path = path % (myid) - mock_request_returns.append((MyResp(return_val), None)) - mock_request_calls.append(mock.call( - end_url(path), 'DELETE', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN}))) - - def _test_delete_resource(self, resource, cmd, myid, args, - cmd_resource=None, parent_id=None, - extra_id=None, delete_fail=False): - mock_request_calls = [] - mock_request_returns = [] - if not cmd_resource: - cmd_resource = resource - path = getattr(self.client, cmd_resource + "_path") - self._test_set_path_and_delete(path, parent_id, myid, - mock_request_calls, - mock_request_returns) - # extra_id is used to test for bulk_delete - if extra_id: - self._test_set_path_and_delete(path, parent_id, extra_id, - mock_request_calls, - mock_request_returns, - delete_fail) - cmd_parser = cmd.get_parser("delete_" + cmd_resource) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, - "request") as mock_request: - mock_request.side_effect = mock_request_returns - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - mock_request.assert_has_calls(mock_request_calls) - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - if extra_id: - self.assertIn(extra_id, _str) - - def _test_update_resource_action(self, resource, cmd, myid, action, args, - body, expected_code=200, retval=None, - cmd_resource=None): - if not cmd_resource: - cmd_resource = resource - path = getattr(self.client, cmd_resource + "_path") - path_action = '%s/%s' % (myid, action) - cmd_parser = cmd.get_parser("update_" + cmd_resource) - resp = (MyResp(expected_code), retval) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - mock_request.assert_called_once_with( - end_url(path % path_action), 'PUT', - body=MyComparator(body, self.client), - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})) - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - - def assert_mock_multiple_calls_with_same_arguments( - self, mocked_method, expected_call, count): - if count is None: - self.assertLessEqual(1, mocked_method.call_count) - else: - self.assertEqual(count, mocked_method.call_count) - mocked_method.assert_has_calls( - [expected_call] * mocked_method.call_count) - - -class TestListCommand(neutronV2_0.ListCommand): - resource = 'test_resource' - filter_attrs = [ - 'name', - 'admin_state_up', - {'name': 'foo', 'help': 'non-boolean attribute foo'}, - {'name': 'bar', 'help': 'boolean attribute bar', - 'boolean': True}, - {'name': 'baz', 'help': 'integer attribute baz', - 'argparse_kwargs': {'choices': ['baz1', 'baz2']}}, - ] - - -class ListCommandTestCase(CLITestV20Base): - - def setUp(self): - super(ListCommandTestCase, self).setUp() - self.client.extend_list('test_resources', '/test_resources', None) - setattr(self.client, 'test_resources_path', '/test_resources') - - def _test_list_resources_filter_params(self, base_args='', query=''): - resources = 'test_resources' - cmd = TestListCommand(MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - base_args=base_args.split(), - query=query) - - def _test_list_resources_with_arg_error(self, base_args=''): - resources = 'test_resources' - cmd = TestListCommand(MyApp(sys.stdout), None) - # argparse parse error leads to SystemExit - self.assertRaises(SystemExit, - self._test_list_resources, - resources, cmd, - base_args=base_args.split()) - - def test_list_resources_without_filter(self): - self._test_list_resources_filter_params() - - def test_list_resources_use_default_filter(self): - self._test_list_resources_filter_params( - base_args='--name val1 --admin-state-up False', - query='name=val1&admin_state_up=False') - - def test_list_resources_use_custom_filter(self): - self._test_list_resources_filter_params( - base_args='--foo FOO --bar True', - query='foo=FOO&bar=True') - - def test_list_resources_boolean_check_default_filter(self): - self._test_list_resources_filter_params( - base_args='--admin-state-up True', query='admin_state_up=True') - self._test_list_resources_filter_params( - base_args='--admin-state-up False', query='admin_state_up=False') - self._test_list_resources_with_arg_error( - base_args='--admin-state-up non-true-false') - - def test_list_resources_boolean_check_custom_filter(self): - self._test_list_resources_filter_params( - base_args='--bar True', query='bar=True') - self._test_list_resources_filter_params( - base_args='--bar False', query='bar=False') - self._test_list_resources_with_arg_error( - base_args='--bar non-true-false') - - def test_list_resources_argparse_kwargs(self): - self._test_list_resources_filter_params( - base_args='--baz baz1', query='baz=baz1') - self._test_list_resources_filter_params( - base_args='--baz baz2', query='baz=baz2') - self._test_list_resources_with_arg_error( - base_args='--bar non-choice') - - -class ClientV2TestJson(CLITestV20Base): - def test_do_request_unicode(self): - unicode_text = u'\u7f51\u7edc' - # url with unicode - action = u'/test' - expected_action = action - # query string with unicode - params = {'test': unicode_text} - expect_query = urlparse.urlencode(utils.safe_encode_dict(params)) - # request body with unicode - body = params - expect_body = self.client.serialize(body) - self.client.httpclient.auth_token = encodeutils.safe_encode( - unicode_text) - expected_auth_token = encodeutils.safe_encode(unicode_text) - resp_headers = {'x-openstack-request-id': REQUEST_ID} - resp = (MyResp(200, resp_headers), expect_body) - - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - result = self.client.do_request('PUT', action, body=body, - params=params) - - mock_request.assert_called_once_with( - end_url(expected_action, query=expect_query), - 'PUT', body=expect_body, - headers=ContainsKeyValue({'X-Auth-Token': expected_auth_token})) - # test response with unicode - self.assertEqual(body, result) - - def test_do_request_error_without_response_body(self): - params = {'test': 'value'} - expect_query = urlparse.urlencode(params) - self.client.httpclient.auth_token = 'token' - resp_headers = {'x-openstack-request-id': REQUEST_ID} - resp = (MyResp(400, headers=resp_headers, reason='An error'), '') - - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - error = self.assertRaises(exceptions.NeutronClientException, - self.client.do_request, 'PUT', '/test', - body='', params=params) - - mock_request.assert_called_once_with( - MyUrlComparator(end_url('/test', query=expect_query), self.client), - 'PUT', body='', - headers=ContainsKeyValue({'X-Auth-Token': 'token'})) - expected_error = "An error\nNeutron server returns " \ - "request_ids: %s" % [REQUEST_ID] - self.assertEqual(expected_error, str(error)) - - def test_do_request_with_long_uri_exception(self): - long_string = 'x' * 8200 # 8200 > MAX_URI_LEN:8192 - params = {'id': long_string} - exception = self.assertRaises(exceptions.RequestURITooLong, - self.client.do_request, - 'GET', '/test', body='', params=params) - self.assertNotEqual(0, exception.excess) - - def test_do_request_request_ids(self): - params = {'test': 'value'} - expect_query = urlparse.urlencode(params) - self.client.httpclient.auth_token = 'token' - body = params - expect_body = self.client.serialize(body) - resp_headers = {'x-openstack-request-id': REQUEST_ID} - resp = (MyResp(200, resp_headers), expect_body) - - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - result = self.client.do_request('PUT', '/test', body=body, - params=params) - - mock_request.assert_called_once_with( - MyUrlComparator(end_url('/test', query=expect_query), self.client), - 'PUT', body=expect_body, - headers=ContainsKeyValue({'X-Auth-Token': 'token'})) - - self.assertEqual(body, result) - self.assertEqual([REQUEST_ID], result.request_ids) - - def test_list_request_ids_with_retrieve_all_true(self): - path = '/test' - resources = 'tests' - fake_query = "marker=myid2&limit=2" - reses1 = {resources: [{'id': 'myid1', }, - {'id': 'myid2', }], - '%s_links' % resources: [{'href': end_url(path, fake_query), - 'rel': 'next'}]} - reses2 = {resources: [{'id': 'myid3', }, - {'id': 'myid4', }]} - resstr1 = self.client.serialize(reses1) - resstr2 = self.client.serialize(reses2) - resp_headers = {'x-openstack-request-id': REQUEST_ID} - resp = [(MyResp(200, resp_headers), resstr1), - (MyResp(200, resp_headers), resstr2)] - with mock.patch.object(self.client.httpclient, "request", - side_effect=resp) as mock_request: - result = self.client.list(resources, path) - - self.assertEqual(2, mock_request.call_count) - mock_request.assert_has_calls([ - mock.call( - end_url(path, ""), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})), - mock.call( - MyUrlComparator(end_url(path, fake_query), - self.client), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN}))]) - - self.assertEqual([REQUEST_ID, REQUEST_ID], result.request_ids) - - def test_list_request_ids_with_retrieve_all_false(self): - path = '/test' - resources = 'tests' - fake_query = "marker=myid2&limit=2" - reses1 = {resources: [{'id': 'myid1', }, - {'id': 'myid2', }], - '%s_links' % resources: [{'href': end_url(path, fake_query), - 'rel': 'next'}]} - reses2 = {resources: [{'id': 'myid3', }, - {'id': 'myid4', }]} - resstr1 = self.client.serialize(reses1) - resstr2 = self.client.serialize(reses2) - resp_headers = {'x-openstack-request-id': REQUEST_ID} - resp = [(MyResp(200, resp_headers), resstr1), - (MyResp(200, resp_headers), resstr2)] - with mock.patch.object(self.client.httpclient, "request", - side_effect=resp) as mock_request: - result = self.client.list(resources, path, retrieve_all=False) - next(result) - self.assertEqual([REQUEST_ID], result.request_ids) - next(result) - self.assertEqual([REQUEST_ID, REQUEST_ID], result.request_ids) - - self.assertEqual(2, mock_request.call_count) - mock_request.assert_has_calls([ - mock.call( - end_url(path, ""), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN})), - mock.call( - MyUrlComparator(end_url(path, fake_query), self.client), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': TOKEN}))]) - - def test_deserialize_without_data(self): - data = u'' - result = self.client.deserialize(data, 200) - self.assertEqual(data, result) - - def test_update_resource(self): - params = {'test': 'value'} - expect_query = urlparse.urlencode(params) - self.client.httpclient.auth_token = 'token' - body = params - expect_body = self.client.serialize(body) - resp_headers = {'x-openstack-request-id': REQUEST_ID} - resp = (MyResp(200, resp_headers), expect_body) - - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - result = self.client._update_resource('/test', body=body, - params=params) - - mock_request.assert_called_once_with( - MyUrlComparator(end_url('/test', query=expect_query), self.client), - 'PUT', body=expect_body, - headers=ContainsKeyValue({'X-Auth-Token': 'token'})) - self.assertNotIn('If-Match', mock_request.call_args[1]['headers']) - - self.assertEqual(body, result) - self.assertEqual([REQUEST_ID], result.request_ids) - - def test_update_resource_with_revision_number(self): - params = {'test': 'value'} - expect_query = urlparse.urlencode(params) - self.client.httpclient.auth_token = 'token' - body = params - expect_body = self.client.serialize(body) - resp_headers = {'x-openstack-request-id': REQUEST_ID} - resp = (MyResp(200, resp_headers), expect_body) - - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - result = self.client._update_resource('/test', body=body, - params=params, - revision_number=1) - - mock_request.assert_called_once_with( - MyUrlComparator(end_url('/test', query=expect_query), self.client), - 'PUT', body=expect_body, - headers=ContainsKeyValue( - {'X-Auth-Token': 'token', 'If-Match': 'revision_number=1'})) - - self.assertEqual(body, result) - self.assertEqual([REQUEST_ID], result.request_ids) - - -class CLITestV20ExceptionHandler(CLITestV20Base): - - def _test_exception_handler_v20( - self, expected_exception, status_code, expected_msg, - error_type=None, error_msg=None, error_detail=None, - request_id=None, error_content=None): - - resp = MyResp(status_code, {'x-openstack-request-id': request_id}) - if request_id is not None: - expected_msg += "\nNeutron server returns " \ - "request_ids: %s" % [request_id] - if error_content is None: - error_content = {'NeutronError': {'type': error_type, - 'message': error_msg, - 'detail': error_detail}} - expected_content = self.client._convert_into_with_meta(error_content, - resp) - - e = self.assertRaises(expected_exception, - client.exception_handler_v20, - status_code, expected_content) - self.assertEqual(status_code, e.status_code) - self.assertEqual(expected_exception.__name__, - e.__class__.__name__) - - if expected_msg is None: - if error_detail: - expected_msg = '\n'.join([error_msg, error_detail]) - else: - expected_msg = error_msg - self.assertEqual(expected_msg, e.message) - - def test_exception_handler_v20_ip_address_in_use(self): - err_msg = ('Unable to complete operation for network ' - 'fake-network-uuid. The IP address fake-ip is in use.') - self._test_exception_handler_v20( - exceptions.IpAddressInUseClient, 409, err_msg, - 'IpAddressInUse', err_msg, '', REQUEST_ID) - - def test_exception_handler_v20_neutron_known_error(self): - known_error_map = [ - ('NetworkNotFound', exceptions.NetworkNotFoundClient, 404), - ('PortNotFound', exceptions.PortNotFoundClient, 404), - ('NetworkInUse', exceptions.NetworkInUseClient, 409), - ('PortInUse', exceptions.PortInUseClient, 409), - ('StateInvalid', exceptions.StateInvalidClient, 400), - ('IpAddressInUse', exceptions.IpAddressInUseClient, 409), - ('IpAddressGenerationFailure', - exceptions.IpAddressGenerationFailureClient, 409), - ('MacAddressInUse', exceptions.MacAddressInUseClient, 409), - ('ExternalIpAddressExhausted', - exceptions.ExternalIpAddressExhaustedClient, 400), - ('OverQuota', exceptions.OverQuotaClient, 409), - ('InvalidIpForNetwork', exceptions.InvalidIpForNetworkClient, 400), - ('InvalidIpForSubnet', exceptions.InvalidIpForSubnetClient, 400), - ('IpAddressAlreadyAllocated', - exceptions.IpAddressAlreadyAllocatedClient, 400), - ] - - error_msg = 'dummy exception message' - error_detail = 'sample detail' - for server_exc, client_exc, status_code in known_error_map: - self._test_exception_handler_v20( - client_exc, status_code, - error_msg + '\n' + error_detail, - server_exc, error_msg, error_detail, REQUEST_ID) - - def test_exception_handler_v20_neutron_known_error_without_detail(self): - error_msg = 'Network not found' - error_detail = '' - self._test_exception_handler_v20( - exceptions.NetworkNotFoundClient, 404, - error_msg, - 'NetworkNotFound', error_msg, error_detail, REQUEST_ID) - - def test_exception_handler_v20_unknown_error_to_per_code_exception(self): - for status_code, client_exc in exceptions.HTTP_EXCEPTION_MAP.items(): - error_msg = 'Unknown error' - error_detail = 'This is detail' - self._test_exception_handler_v20( - client_exc, status_code, - error_msg + '\n' + error_detail, - 'UnknownError', error_msg, error_detail, [REQUEST_ID]) - - def test_exception_handler_v20_neutron_unknown_status_code(self): - error_msg = 'Unknown error' - error_detail = 'This is detail' - self._test_exception_handler_v20( - exceptions.NeutronClientException, 501, - error_msg + '\n' + error_detail, - 'UnknownError', error_msg, error_detail, REQUEST_ID) - - def test_exception_handler_v20_bad_neutron_error(self): - for status_code, client_exc in exceptions.HTTP_EXCEPTION_MAP.items(): - error_content = {'NeutronError': {'unknown_key': 'UNKNOWN'}} - self._test_exception_handler_v20( - client_exc, status_code, - expected_msg="{'unknown_key': 'UNKNOWN'}", - error_content=error_content, - request_id=REQUEST_ID) - - def test_exception_handler_v20_error_dict_contains_message(self): - error_content = {'message': 'This is an error message'} - for status_code, client_exc in exceptions.HTTP_EXCEPTION_MAP.items(): - self._test_exception_handler_v20( - client_exc, status_code, - expected_msg='This is an error message', - error_content=error_content, - request_id=REQUEST_ID) - - def test_exception_handler_v20_error_dict_not_contain_message(self): - # 599 is not contained in HTTP_EXCEPTION_MAP. - error_content = {'error': 'This is an error message'} - expected_msg = '%s-%s' % (599, error_content) - self._test_exception_handler_v20( - exceptions.NeutronClientException, 599, - expected_msg=expected_msg, - request_id=None, - error_content=error_content) - - def test_exception_handler_v20_default_fallback(self): - # 599 is not contained in HTTP_EXCEPTION_MAP. - error_content = 'This is an error message' - expected_msg = '%s-%s' % (599, error_content) - self._test_exception_handler_v20( - exceptions.NeutronClientException, 599, - expected_msg=expected_msg, - request_id=None, - error_content=error_content) - - def test_exception_status(self): - e = exceptions.BadRequest() - self.assertEqual(400, e.status_code) - - e = exceptions.BadRequest(status_code=499) - self.assertEqual(499, e.status_code) - - # SslCertificateValidationError has no explicit status_code, - # but should have a 'safe' defined fallback. - e = exceptions.SslCertificateValidationError() - self.assertIsNotNone(e.status_code) - - e = exceptions.SslCertificateValidationError(status_code=599) - self.assertEqual(599, e.status_code) - - def test_connection_failed(self): - self.client.httpclient.auth_token = 'token' - excp = requests.exceptions.ConnectionError('Connection refused') - - with mock.patch.object(self.client.httpclient, "request", - side_effect=excp) as mock_request: - error = self.assertRaises(exceptions.ConnectionFailed, - self.client.get, '/test') - - mock_request.assert_called_once_with( - end_url('/test'), 'GET', - body=None, - headers=ContainsKeyValue({'X-Auth-Token': 'token'})) - # NB: ConnectionFailed has no explicit status_code, so this - # tests that there is a fallback defined. - self.assertIsNotNone(error.status_code) - - -class DictWithMetaTest(base.BaseTestCase): - - def test_dict_with_meta(self): - body = {'test': 'value'} - resp = MyResp(200, {'x-openstack-request-id': REQUEST_ID}) - obj = client._DictWithMeta(body, resp) - self.assertEqual(body, obj) - - # Check request_ids attribute is added to obj - self.assertTrue(hasattr(obj, 'request_ids')) - self.assertEqual([REQUEST_ID], obj.request_ids) - - -class TupleWithMetaTest(base.BaseTestCase): - - def test_tuple_with_meta(self): - body = ('test', 'value') - resp = MyResp(200, {'x-openstack-request-id': REQUEST_ID}) - obj = client._TupleWithMeta(body, resp) - self.assertEqual(body, obj) - - # Check request_ids attribute is added to obj - self.assertTrue(hasattr(obj, 'request_ids')) - self.assertEqual([REQUEST_ID], obj.request_ids) - - -class StrWithMetaTest(base.BaseTestCase): - - def test_str_with_meta(self): - body = "test_string" - resp = MyResp(200, {'x-openstack-request-id': REQUEST_ID}) - obj = client._StrWithMeta(body, resp) - self.assertEqual(body, obj) - - # Check request_ids attribute is added to obj - self.assertTrue(hasattr(obj, 'request_ids')) - self.assertEqual([REQUEST_ID], obj.request_ids) - - -class GeneratorWithMetaTest(base.BaseTestCase): - - body = {'test': 'value'} - resp = MyResp(200, {'x-openstack-request-id': REQUEST_ID}) - - def _pagination(self, collection, path, **params): - obj = client._DictWithMeta(self.body, self.resp) - yield obj - - def test_generator(self): - obj = client._GeneratorWithMeta(self._pagination, 'test_collection', - 'test_path', test_args='test_args') - self.assertEqual(self.body, next(obj)) - - self.assertTrue(hasattr(obj, 'request_ids')) - self.assertEqual([REQUEST_ID], obj.request_ids) - - -class CLITestV20OutputFormatter(CLITestV20Base): - - def _test_create_resource_with_formatter(self, fmt): - resource = 'network' - cmd = network.CreateNetwork(MyApp(sys.stdout), None) - args = ['-f', fmt, 'myname'] - position_names = ['name'] - position_values = ['myname'] - self._test_create_resource(resource, cmd, 'myname', 'myid', args, - position_names, position_values) - - def test_create_resource_table(self): - self._test_create_resource_with_formatter('table') - print(self.fake_stdout.content) - # table data is contains in the third element. - data = self.fake_stdout.content[2].split('\n') - self.assertTrue(any(' id ' in d for d in data)) - self.assertTrue(any(' name ' in d for d in data)) - - def test_create_resource_json(self): - self._test_create_resource_with_formatter('json') - data = jsonutils.loads(self.fake_stdout.make_string()) - self.assertEqual('myname', data['name']) - self.assertEqual('myid', data['id']) - - def test_create_resource_yaml(self): - self._test_create_resource_with_formatter('yaml') - data = yaml.safe_load(self.fake_stdout.make_string()) - self.assertEqual('myname', data['name']) - self.assertEqual('myid', data['id']) - - def _test_show_resource_with_formatter(self, fmt): - resource = 'network' - cmd = network.ShowNetwork(MyApp(sys.stdout), None) - args = ['-f', fmt, '-F', 'id', '-F', 'name', 'myid'] - self._test_show_resource(resource, cmd, 'myid', - args, ['id', 'name']) - - def test_show_resource_table(self): - self._test_show_resource_with_formatter('table') - data = self.fake_stdout.content[0].split('\n') - self.assertTrue(any(' id ' in d for d in data)) - self.assertTrue(any(' name ' in d for d in data)) - - def test_show_resource_json(self): - self._test_show_resource_with_formatter('json') - data = jsonutils.loads(''.join(self.fake_stdout.content)) - self.assertEqual('myname', data['name']) - self.assertEqual('myid', data['id']) - - def test_show_resource_yaml(self): - self._test_show_resource_with_formatter('yaml') - data = yaml.safe_load(''.join(self.fake_stdout.content)) - self.assertEqual('myname', data['name']) - self.assertEqual('myid', data['id']) - - @mock.patch.object(network.ListNetwork, "extend_list") - def _test_list_resources_with_formatter(self, fmt, mock_extend_list): - resources = 'networks' - cmd = network.ListNetwork(MyApp(sys.stdout), None) - # ListNetwork has its own extend_list, so we need to stub out it - # to avoid an extra API call. - self._test_list_resources(resources, cmd, output_format=fmt) - mock_extend_list.assert_called_once_with(IsA(list), mock.ANY) - - def test_list_resources_table(self): - self._test_list_resources_with_formatter('table') - data = self.fake_stdout.content[0].split('\n') - self.assertTrue(any(' id ' in d for d in data)) - self.assertTrue(any(' myid1 ' in d for d in data)) - self.assertTrue(any(' myid2 ' in d for d in data)) - - def test_list_resources_json(self): - self._test_list_resources_with_formatter('json') - data = jsonutils.loads(''.join(self.fake_stdout.content)) - self.assertEqual(['myid1', 'myid2'], [d['id'] for d in data]) - - def test_list_resources_yaml(self): - self._test_list_resources_with_formatter('yaml') - data = yaml.safe_load(''.join(self.fake_stdout.content)) - self.assertEqual(['myid1', 'myid2'], [d['id'] for d in data]) diff --git a/neutronclient/tests/unit/test_cli20_address_scope.py b/neutronclient/tests/unit/test_cli20_address_scope.py deleted file mode 100644 index 902f7e653..000000000 --- a/neutronclient/tests/unit/test_cli20_address_scope.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright 2015 Huawei Technologies India Pvt. Ltd. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import address_scope -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20AddressScopeJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['address_scope'] - - def setUp(self): - super(CLITestV20AddressScopeJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_address_scope_with_minimum_option_ipv4(self): - """Create address_scope: foo-address-scope with minimum option.""" - resource = 'address_scope' - cmd = address_scope.CreateAddressScope( - test_cli20.MyApp(sys.stdout), None) - name = 'foo-address-scope' - myid = 'myid' - args = [name, '4'] - position_names = ['name', 'ip_version'] - position_values = [name, 4] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_address_scope_with_minimum_option_ipv6(self): - """Create address_scope: foo-address-scope with minimum option.""" - resource = 'address_scope' - cmd = address_scope.CreateAddressScope( - test_cli20.MyApp(sys.stdout), None) - name = 'foo-address-scope' - myid = 'myid' - args = [name, '6'] - position_names = ['name', 'ip_version'] - position_values = [name, 6] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_address_scope_with_minimum_option_bad_ip_version(self): - """Create address_scope: foo-address-scope with minimum option.""" - resource = 'address_scope' - cmd = address_scope.CreateAddressScope( - test_cli20.MyApp(sys.stdout), None) - name = 'foo-address-scope' - myid = 'myid' - args = [name, '5'] - position_names = ['name', 'ip_version'] - position_values = [name, 5] - self.assertRaises(SystemExit, self._test_create_resource, - resource, cmd, name, myid, args, position_names, - position_values) - - def test_create_address_scope_with_all_option(self): - # Create address_scope: foo-address-scope with all options. - resource = 'address_scope' - cmd = address_scope.CreateAddressScope( - test_cli20.MyApp(sys.stdout), None) - name = 'foo-address-scope' - myid = 'myid' - args = [name, '4', '--shared'] - position_names = ['name', 'ip_version', 'shared'] - position_values = [name, 4, True] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_address_scope_with_unicode(self): - # Create address_scope: u'\u7f51\u7edc'. - resource = 'address_scope' - cmd = address_scope.CreateAddressScope( - test_cli20.MyApp(sys.stdout), None) - name = u'\u7f51\u7edc' - ip_version = u'4' - myid = 'myid' - args = [name, ip_version] - position_names = ['name', 'ip_version'] - position_values = [name, 4] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_update_address_scope_exception(self): - # Update address_scope (Negative) : myid. - resource = 'address_scope' - cmd = address_scope.UpdateAddressScope( - test_cli20.MyApp(sys.stdout), None) - self.assertRaises(exceptions.CommandError, self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - - def test_update_address_scope(self): - # Update address_scope: myid --name newname-address-scope. - resource = 'address_scope' - cmd = address_scope.UpdateAddressScope( - test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname-address-scope'], - {'name': 'newname-address-scope'} - ) - # Update address_scope: myid --shared - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--shared', 'True'], - {'shared': "True"} - ) - - def test_list_address_scope(self): - # address_scope-list. - resources = "address_scopes" - cmd = address_scope.ListAddressScope(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - @mock.patch.object(address_scope.ListAddressScope, "extend_list") - def test_list_address_scope_pagination(self, mock_extend_list): - # address_scope-list. - cmd = address_scope.ListAddressScope(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination("address_scopes", - cmd) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def test_list_address_scope_sort(self): - # sorted list: - # address_scope-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "address_scopes" - cmd = address_scope.ListAddressScope(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id", "ip_version"], - sort_dir=["asc", "desc"]) - - def test_list_address_scope_limit(self): - # size (1000) limited list: address_scope-list -P. - resources = "address_scopes" - cmd = address_scope.ListAddressScope(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_address_scope(self): - # Show address_scope: --fields id --fields name myid. - resource = 'address_scope' - cmd = address_scope.ShowAddressScope( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id, - '--fields', 'ip_version', '6'] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name', 'ip_version']) - - def test_delete_address_scope(self): - # Delete address_scope: address_scope_id. - resource = 'address_scope' - cmd = address_scope.DeleteAddressScope( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) diff --git a/neutronclient/tests/unit/test_cli20_agents.py b/neutronclient/tests/unit/test_cli20_agents.py deleted file mode 100644 index 7641d2741..000000000 --- a/neutronclient/tests/unit/test_cli20_agents.py +++ /dev/null @@ -1,97 +0,0 @@ -# All Rights Reserved -# -# 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 sys - -from oslo_serialization import jsonutils - -from neutronclient.neutron.v2_0 import agent -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Agent(test_cli20.CLITestV20Base): - def test_list_agents(self): - contents = {'agents': [{'id': 'myname', 'agent_type': 'mytype', - 'alive': True}]} - args = ['-f', 'json'] - resources = "agents" - - cmd = agent.ListAgent(test_cli20.MyApp(sys.stdout), None) - self._test_list_columns(cmd, resources, contents, args) - _str = self.fake_stdout.make_string() - - returned_agents = jsonutils.loads(_str) - self.assertEqual(1, len(returned_agents)) - ag = returned_agents[0] - self.assertEqual(3, len(ag)) - self.assertIn("alive", ag.keys()) - - def test_list_agents_field(self): - contents = {'agents': [{'alive': True}]} - args = ['-f', 'json'] - resources = "agents" - smile = ':-)' - - cmd = agent.ListAgent(test_cli20.MyApp(sys.stdout), None) - self._test_list_columns(cmd, resources, contents, args) - _str = self.fake_stdout.make_string() - - returned_agents = jsonutils.loads(_str) - self.assertEqual(1, len(returned_agents)) - ag = returned_agents[0] - self.assertEqual(1, len(ag)) - self.assertIn("alive", ag.keys()) - self.assertIn(smile, ag.values()) - - def test_list_agents_zone_field(self): - contents = {'agents': [{'availability_zone': 'myzone'}]} - args = ['-f', 'json'] - resources = "agents" - - cmd = agent.ListAgent(test_cli20.MyApp(sys.stdout), None) - self._test_list_columns(cmd, resources, contents, args) - _str = self.fake_stdout.make_string() - - returned_agents = jsonutils.loads(_str) - self.assertEqual(1, len(returned_agents)) - ag = returned_agents[0] - self.assertEqual(1, len(ag)) - self.assertIn("availability_zone", ag.keys()) - self.assertIn('myzone', ag.values()) - - def test_update_agent(self): - # agent-update myid --admin-state-down --description mydescr. - resource = 'agent' - cmd = agent.UpdateAgent(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource( - resource, cmd, 'myid', - ['myid', '--admin-state-down', '--description', 'mydescr'], - {'description': 'mydescr', 'admin_state_up': False} - ) - - def test_show_agent(self): - # Show agent: --field id --field binary myid. - resource = 'agent' - cmd = agent.ShowAgent(test_cli20.MyApp(sys.stdout), None) - args = ['--field', 'id', '--field', 'binary', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'binary']) - - def test_delete_agent(self): - # Delete agent: myid. - resource = 'agent' - cmd = agent.DeleteAgent(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) diff --git a/neutronclient/tests/unit/test_cli20_agentschedulers.py b/neutronclient/tests/unit/test_cli20_agentschedulers.py deleted file mode 100644 index 817909d38..000000000 --- a/neutronclient/tests/unit/test_cli20_agentschedulers.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.neutron.v2_0 import agentscheduler -from neutronclient.neutron.v2_0 import network -from neutronclient.tests.unit import test_cli20 - - -AGENT_ID = 'agent_id1' -NETWORK_ID = 'net_id1' -ROUTER_ID = 'router_id1' - - -class CLITestV20AgentScheduler(test_cli20.CLITestV20Base): - def _test_add_to_agent(self, resource, cmd, cmd_args, destination, - body, result): - path = ((self.client.agent_path + destination) % - cmd_args[0]) - - result_str = self.client.serialize(result) - return_tup = (test_cli20.MyResp(200), result_str) - - cmd_parser = cmd.get_parser('test_' + resource) - parsed_args = cmd_parser.parse_args(cmd_args) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=return_tup) as mock_request: - cmd.run(parsed_args) - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.end_url(path), 'POST', - body=test_cli20.MyComparator(body, self.client), - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - def _test_remove_from_agent(self, resource, cmd, cmd_args, destination): - path = ((self.client.agent_path + destination + '/%s') % - cmd_args) - - return_tup = (test_cli20.MyResp(204), None) - cmd_parser = cmd.get_parser('test_' + resource) - parsed_args = cmd_parser.parse_args(cmd_args) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=return_tup) as mock_request: - cmd.run(parsed_args) - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.end_url(path), 'DELETE', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - -class CLITestV20DHCPAgentScheduler(CLITestV20AgentScheduler): - - def test_add_network_to_agent(self): - resource = 'agent' - cmd = agentscheduler.AddNetworkToDhcpAgent( - test_cli20.MyApp(sys.stdout), None) - args = (AGENT_ID, NETWORK_ID) - body = {'network_id': NETWORK_ID} - result = {'network_id': 'net_id', } - self._test_add_to_agent(resource, cmd, args, self.client.DHCP_NETS, - body, result) - - def test_remove_network_from_agent(self): - resource = 'agent' - cmd = agentscheduler.RemoveNetworkFromDhcpAgent( - test_cli20.MyApp(sys.stdout), None) - args = (AGENT_ID, NETWORK_ID) - self._test_remove_from_agent(resource, cmd, args, - self.client.DHCP_NETS) - - @mock.patch.object(network.ListNetwork, "extend_list") - def test_list_networks_on_agent(self, mock_extend_list): - resources = 'networks' - cmd = agentscheduler.ListNetworksOnDhcpAgent( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.agent_path + self.client.DHCP_NETS) % - agent_id) - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def test_list_agents_hosting_network(self): - resources = 'agent' - cmd = agentscheduler.ListDhcpAgentsHostingNetwork( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.network_path + self.client.DHCP_AGENTS) % - agent_id) - contents = {self.id_field: 'myid1', 'alive': True} - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path, response_contents=contents) - - -class CLITestV20L3AgentScheduler(CLITestV20AgentScheduler): - - def test_add_router_to_agent(self): - resource = 'agent' - cmd = agentscheduler.AddRouterToL3Agent( - test_cli20.MyApp(sys.stdout), None) - args = (AGENT_ID, ROUTER_ID) - body = {'router_id': ROUTER_ID} - result = {'network_id': 'net_id', } - self._test_add_to_agent(resource, cmd, args, self.client.L3_ROUTERS, - body, result) - - def test_remove_router_from_agent(self): - resource = 'agent' - cmd = agentscheduler.RemoveRouterFromL3Agent( - test_cli20.MyApp(sys.stdout), None) - args = (AGENT_ID, ROUTER_ID) - self._test_remove_from_agent(resource, cmd, args, - self.client.L3_ROUTERS) - - def test_list_routers_on_agent(self): - resources = 'router' - cmd = agentscheduler.ListRoutersOnL3Agent( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.agent_path + self.client.L3_ROUTERS) % - agent_id) - contents = {self.id_field: 'myid1', 'name': 'my_name'} - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path, response_contents=contents) - - def test_list_agents_hosting_router(self): - resources = 'agent' - cmd = agentscheduler.ListL3AgentsHostingRouter( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.router_path + self.client.L3_AGENTS) % - agent_id) - contents = {self.id_field: 'myid1', 'alive': True} - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path, response_contents=contents) - - -class CLITestV20LBaaSAgentScheduler(test_cli20.CLITestV20Base): - - def test_list_pools_on_agent(self): - resources = 'pools' - cmd = agentscheduler.ListPoolsOnLbaasAgent( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.agent_path + self.client.LOADBALANCER_POOLS) % - agent_id) - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path) - - def test_get_lbaas_agent_hosting_pool(self): - resources = 'agent' - cmd = agentscheduler.GetLbaasAgentHostingPool( - test_cli20.MyApp(sys.stdout), None) - pool_id = 'pool_id1' - path = ((self.client.pool_path + self.client.LOADBALANCER_AGENT) % - pool_id) - contents = {self.id_field: 'myid1', 'alive': True} - self._test_list_resources(resources, cmd, base_args=[pool_id], - path=path, response_contents=contents) - - -class CLITestV20LBaaSV2AgentScheduler(test_cli20.CLITestV20Base): - - def test_list_loadbalancers_on_agent(self): - resources = 'loadbalancers' - cmd = agentscheduler.ListLoadBalancersOnLbaasAgent( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.agent_path + self.client.AGENT_LOADBALANCERS) % - agent_id) - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path) - - def test_get_lbaas_agent_hosting_pool(self): - resources = 'agent' - cmd = agentscheduler.GetLbaasAgentHostingLoadBalancer( - test_cli20.MyApp(sys.stdout), None) - lb_id = 'lb_id1' - path = ((self.client.lbaas_loadbalancer_path + - self.client.LOADBALANCER_HOSTING_AGENT) % lb_id) - contents = {self.id_field: 'myid1', 'alive': True} - self._test_list_resources(resources, cmd, base_args=[lb_id], - path=path, response_contents=contents) diff --git a/neutronclient/tests/unit/test_cli20_az.py b/neutronclient/tests/unit/test_cli20_az.py deleted file mode 100644 index cb127c529..000000000 --- a/neutronclient/tests/unit/test_cli20_az.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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 sys - -from neutronclient.neutron.v2_0 import availability_zone as az -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Agent(test_cli20.CLITestV20Base): - def test_list_agents(self): - contents = {'availability_zones': [{'name': 'zone1', - 'resource': 'network', - 'state': 'available'}, - {'name': 'zone2', - 'resource': 'router', - 'state': 'unavailable'}]} - args = ['-f', 'json'] - resources = "availability_zones" - - cmd = az.ListAvailabilityZone(test_cli20.MyApp(sys.stdout), None) - self._test_list_columns(cmd, resources, contents, args) diff --git a/neutronclient/tests/unit/test_cli20_extensions.py b/neutronclient/tests/unit/test_cli20_extensions.py deleted file mode 100644 index cc2913747..000000000 --- a/neutronclient/tests/unit/test_cli20_extensions.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2013 NEC Corporation -# All Rights Reserved. -# -# 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 sys - -from neutronclient.neutron.v2_0 import extension -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Extension(test_cli20.CLITestV20Base): - id_field = 'alias' - - def test_list_extensions(self): - resources = 'extensions' - cmd = extension.ListExt(test_cli20.MyApp(sys.stdout), None) - contents = [{'alias': 'ext1', 'name': 'name1', 'other': 'other1'}, - {'alias': 'ext2', 'name': 'name2', 'other': 'other2'}] - ret = self._test_list_resources(resources, cmd, - response_contents=contents) - ret_words = set(ret.split()) - # Check only the default columns are shown. - self.assertIn('name', ret_words) - self.assertIn('alias', ret_words) - self.assertNotIn('other', ret_words) - - def test_show_extension(self): - # -F option does not work for ext-show at the moment, so -F option - # is not passed in the commandline args as other tests do. - resource = 'extension' - cmd = extension.ShowExt(test_cli20.MyApp(sys.stdout), None) - args = [self.test_id] - ext_alias = self.test_id - self._test_show_resource(resource, cmd, ext_alias, args, fields=[]) diff --git a/neutronclient/tests/unit/test_cli20_floatingips.py b/neutronclient/tests/unit/test_cli20_floatingips.py deleted file mode 100644 index d77bda6e8..000000000 --- a/neutronclient/tests/unit/test_cli20_floatingips.py +++ /dev/null @@ -1,193 +0,0 @@ -# Copyright 2012 Red Hat -# All Rights Reserved. -# -# 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 sys - -from neutronclient.neutron.v2_0 import floatingip as fip -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FloatingIpsJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['floatingip'] - - def test_create_floatingip(self): - # Create floatingip: fip1. - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - args = [name, '--description', 'floats like a butterfly'] - position_names = ['floating_network_id'] - position_values = [name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - description='floats like a butterfly') - - def test_create_floatingip_and_port(self): - # Create floatingip: fip1. - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - pid = 'mypid' - args = [name, '--port_id', pid] - position_names = ['floating_network_id', 'port_id'] - position_values = [name, pid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = [name, '--port-id', pid] - position_names = ['floating_network_id', 'port_id'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_floatingip_and_port_and_address(self): - # Create floatingip: fip1 with a given port and address. - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - pid = 'mypid' - addr = '10.0.0.99' - args = [name, '--port_id', pid, '--fixed_ip_address', addr] - position_names = ['floating_network_id', 'port_id', 'fixed_ip_address'] - position_values = [name, pid, addr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - # Test dashed options - args = [name, '--port-id', pid, '--fixed-ip-address', addr] - position_names = ['floating_network_id', 'port_id', 'fixed_ip_address'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_floatingip_with_ip_address_of_floating_ip(self): - # Create floatingip: fip1 with a given IP address of floating IP. - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - addr = '10.0.0.99' - - args = [name, '--floating-ip-address', addr] - position_values = [name, addr] - position_names = ['floating_network_id', 'floating_ip_address'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_floatingip_with_subnet_id(self): - # Create floatingip: fip1 on a given subnet id. - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - subnet_id = 'mysubnetid' - - args = [name, '--subnet', subnet_id] - position_values = [name, subnet_id] - position_names = ['floating_network_id', 'subnet_id'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_floatingip_with_subnet_id_and_port(self): - # Create floatingip: fip1 on a given subnet id and port. - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - pid = 'mypid' - subnet_id = 'mysubnetid' - - args = [name, '--subnet', subnet_id, '--port-id', pid] - position_values = [name, subnet_id, pid] - position_names = ['floating_network_id', 'subnet_id', 'port_id'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_floatingip_with_dns_name_and_dns_domain(self): - # Create floatingip: fip1 with dns name and dns domain. - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - dns_name_name = 'my-floatingip' - dns_domain_name = 'my-domain.org.' - args = [name, '--dns-name', dns_name_name, '--dns-domain', - dns_domain_name] - position_names = ['floating_network_id', 'dns_name', 'dns_domain'] - position_values = [name, dns_name_name, dns_domain_name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_floatingips(self): - # list floatingips: -D. - resources = 'floatingips' - cmd = fip.ListFloatingIP(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_floatingips_pagination(self): - resources = 'floatingips' - cmd = fip.ListFloatingIP(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_floatingips_sort(self): - # list floatingips: - # --sort-key name --sort-key id --sort-key asc --sort-key desc - resources = 'floatingips' - cmd = fip.ListFloatingIP(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_floatingips_limit(self): - # list floatingips: -P. - resources = 'floatingips' - cmd = fip.ListFloatingIP(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_delete_floatingip(self): - # Delete floatingip: fip1. - resource = 'floatingip' - cmd = fip.DeleteFloatingIP(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_floatingip(self): - # Show floatingip: --fields id. - resource = 'floatingip' - cmd = fip.ShowFloatingIP(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def test_disassociate_ip(self): - # Disassociate floating IP: myid. - resource = 'floatingip' - cmd = fip.DisassociateFloatingIP(test_cli20.MyApp(sys.stdout), None) - args = ['myid'] - self._test_update_resource(resource, cmd, 'myid', - args, {"port_id": None} - ) - - def test_associate_ip(self): - # Associate floating IP: myid portid. - resource = 'floatingip' - cmd = fip.AssociateFloatingIP(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'portid'] - self._test_update_resource(resource, cmd, 'myid', - args, {"port_id": "portid"} - ) diff --git a/neutronclient/tests/unit/test_cli20_metering.py b/neutronclient/tests/unit/test_cli20_metering.py deleted file mode 100644 index 9ecf04734..000000000 --- a/neutronclient/tests/unit/test_cli20_metering.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (C) 2013 eNovance SAS -# -# 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 sys - -from neutronclient.neutron.v2_0 import metering -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20MeteringJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['metering_label', 'metering_label_rule'] - - def test_create_metering_label(self): - # Create a metering label. - resource = 'metering_label' - cmd = metering.CreateMeteringLabel( - test_cli20.MyApp(sys.stdout), None) - name = 'my label' - myid = 'myid' - description = 'my description' - args = [name, '--description', description, '--shared'] - position_names = ['name', 'description', 'shared'] - position_values = [name, description, True] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_metering_labels(self): - resources = "metering_labels" - cmd = metering.ListMeteringLabel( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd) - - def test_delete_metering_label(self): - # Delete a metering label. - resource = 'metering_label' - cmd = metering.DeleteMeteringLabel( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_metering_label(self): - resource = 'metering_label' - cmd = metering.ShowMeteringLabel( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def test_create_metering_label_rule(self): - resource = 'metering_label_rule' - cmd = metering.CreateMeteringLabelRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - metering_label_id = 'aaa' - remote_ip_prefix = '10.0.0.0/24' - direction = 'ingress' - args = [metering_label_id, remote_ip_prefix, '--direction', direction, - '--excluded'] - position_names = ['metering_label_id', 'remote_ip_prefix', 'direction', - 'excluded'] - position_values = [metering_label_id, remote_ip_prefix, - direction, True] - self._test_create_resource(resource, cmd, metering_label_id, - myid, args, position_names, position_values) - - def test_list_metering_label_rules(self): - resources = "metering_label_rules" - cmd = metering.ListMeteringLabelRule( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd) - - def test_delete_metering_label_rule(self): - resource = 'metering_label_rule' - cmd = metering.DeleteMeteringLabelRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_metering_label_rule(self): - resource = 'metering_label_rule' - cmd = metering.ShowMeteringLabelRule( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) diff --git a/neutronclient/tests/unit/test_cli20_network.py b/neutronclient/tests/unit/test_cli20_network.py deleted file mode 100644 index b1f69acc8..000000000 --- a/neutronclient/tests/unit/test_cli20_network.py +++ /dev/null @@ -1,698 +0,0 @@ -# All Rights Reserved -# -# 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 itertools -import sys -from unittest import mock - -from oslo_serialization import jsonutils - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import network -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20CreateNetworkJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20CreateNetworkJSON, self).setUp(plurals={'tags': 'tag'}) - - def _test_create_network(self, **kwargs): - cmd = network.CreateNetwork(test_cli20.MyApp(sys.stdout), None) - resource = kwargs.pop('resource', 'network') - - name = kwargs.pop('name', 'myname') - myid = kwargs.pop('myid', 'myid') - args = kwargs.pop('args', [name, ]) - position_names = kwargs.pop('position_names', ['name', ]) - position_values = kwargs.pop('position_values', [name, ]) - - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - **kwargs) - - def test_create_network(self): - # Create net: myname. - self._test_create_network() - - def test_create_network_with_unicode(self): - # Create net: u'\u7f51\u7edc'. - self._test_create_network(name=u'\u7f51\u7edc') - - def test_create_network_description(self): - # Create net: --tenant_id tenantid myname. - name = 'myname' - args = ['--description', 'Nice network', name] - self._test_create_network(name=name, - args=args, - description='Nice network') - - def test_create_network_tenant_underscore(self): - # Create net: --tenant_id tenantid myname. - name = 'myname' - args = ['--tenant_id', 'tenantid', name] - self._test_create_network(name=name, args=args, tenant_id="tenantid") - - def test_create_network_tenant_dash(self): - # Test dashed options - # Create net: --tenant_id tenantid myname. - name = 'myname' - args = ['--tenant-id', 'tenantid', name] - self._test_create_network(name=name, args=args, tenant_id="tenantid") - - def test_create_network_provider_args(self): - # Create net: with --provider arguments. - # Test --provider attributes before network name - name = 'myname' - args = ['--provider:network_type', 'vlan', - '--provider:physical_network', 'physnet1', - '--provider:segmentation_id', '400', name] - position_names = ['provider:network_type', - 'provider:physical_network', - 'provider:segmentation_id', 'name'] - position_values = ['vlan', 'physnet1', '400', name] - self._test_create_network(name=name, - args=args, - position_names=position_names, - position_values=position_values) - - def test_create_network_tags(self): - # Create net: myname --tags a b. - name = 'myname' - args = [name, '--tags', 'a', 'b'] - self._test_create_network(name=name, args=args, tags=['a', 'b']) - - def test_create_network_state_underscore(self): - # Create net: --admin_state_down myname. - name = 'myname' - args = ['--admin_state_down', name, ] - self._test_create_network(name=name, args=args, admin_state_up=False) - - def test_create_network_state_dash(self): - # Test dashed options - name = 'myname' - args = ['--admin-state-down', name, ] - self._test_create_network(name=name, args=args, admin_state_up=False) - - def test_create_network_vlan_transparent(self): - # Create net: myname --vlan-transparent True. - name = 'myname' - args = ['--vlan-transparent', 'True', name] - self._test_create_network(name=name, - args=args, - vlan_transparent='True') - - def test_create_network_with_qos_policy(self): - # Create net: --qos-policy mypolicy. - name = 'myname' - qos_policy_name = 'mypolicy' - args = [name, '--qos-policy', qos_policy_name] - position_names = ['name', 'qos_policy_id'] - position_values = [name, qos_policy_name] - self._test_create_network(name=name, - args=args, - position_names=position_names, - position_values=position_values) - - def test_create_network_with_az_hint(self): - # Create net: --availability-zone-hint zone1 - # --availability-zone-hint zone2. - name = 'myname' - args = ['--availability-zone-hint', 'zone1', - '--availability-zone-hint', 'zone2', name] - position_names = ['availability_zone_hints', 'name'] - position_values = [['zone1', 'zone2'], name] - self._test_create_network(name=name, - args=args, - position_names=position_names, - position_values=position_values) - - def test_create_network_with_dns_domain(self): - # Create net: --dns-domain my-domain.org. - name = 'myname' - dns_domain_name = 'my-domain.org.' - args = [name, '--dns-domain', dns_domain_name] - position_names = ['name', 'dns_domain'] - position_values = [name, dns_domain_name] - self._test_create_network(name=name, - args=args, - position_names=position_names, - position_values=position_values) - - -class CLITestV20ListNetworkJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20ListNetworkJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_list_nets_empty_with_column(self): - resources = "networks" - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - reses = {resources: []} - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - # url method body - query = "id=myfakeid" - args = ['-c', 'id', '--', '--id', 'myfakeid'] - path = getattr(self.client, resources + "_path") - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request, \ - mock.patch.object(network.ListNetwork, "extend_list", - return_value=None) as mock_extend_list: - cmd_parser = cmd.get_parser("list_" + resources) - shell.run_command(cmd, cmd_parser, args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator(test_cli20.end_url(path, query), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - _str = self.fake_stdout.make_string() - self.assertEqual('\n', _str) - - def _test_list_networks(self, cmd, detail=False, tags=(), - fields_1=(), fields_2=(), page_size=None, - sort_key=(), sort_dir=(), base_args=None, - query=''): - resources = "networks" - with mock.patch.object(network.ListNetwork, "extend_list", - return_value=None) as mock_extend_list: - self._test_list_resources(resources, cmd, detail, tags, - fields_1, fields_2, page_size=page_size, - sort_key=sort_key, sort_dir=sort_dir, - base_args=base_args, query=query) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def test_list_nets_pagination(self): - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - with mock.patch.object(network.ListNetwork, "extend_list", - return_value=None) as mock_extend_list: - self._test_list_resources_with_pagination("networks", cmd) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def test_list_nets_sort(self): - # list nets: - # --sort-key name --sort-key id --sort-dir asc --sort-dir desc - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, sort_key=['name', 'id'], - sort_dir=['asc', 'desc']) - - def test_list_nets_sort_with_keys_more_than_dirs(self): - # list nets: --sort-key name --sort-key id --sort-dir desc - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, sort_key=['name', 'id'], - sort_dir=['desc']) - - def test_list_nets_sort_with_dirs_more_than_keys(self): - # list nets: --sort-key name --sort-dir desc --sort-dir asc - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, sort_key=['name'], - sort_dir=['desc', 'asc']) - - def test_list_nets_limit(self): - # list nets: -P. - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, page_size=1000) - - def test_list_nets_detail(self): - # list nets: -D. - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, True) - - def test_list_nets_tags(self): - # List nets: -- --tags a b. - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, tags=['a', 'b']) - - def test_list_nets_tags_with_unicode(self): - # List nets: -- --tags u'\u7f51\u7edc'. - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, tags=[u'\u7f51\u7edc']) - - def test_list_nets_detail_tags(self): - # List nets: -D -- --tags a b. - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, detail=True, tags=['a', 'b']) - - def _test_list_nets_extend_subnets(self, data, expected): - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - nets_path = getattr(self.client, 'networks_path') - subnets_path = getattr(self.client, 'subnets_path') - nets_query = '' - filters = '' - for n in data: - for s in n['subnets']: - filters = filters + "&id=%s" % s - subnets_query = 'fields=id&fields=cidr' + filters - with mock.patch.object(cmd, 'get_client', - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, - "request") as mock_request: - resp1 = (test_cli20.MyResp(200), - self.client.serialize({'networks': data})) - resp2 = (test_cli20.MyResp(200), - self.client.serialize({'subnets': [ - {'id': 'mysubid1', 'cidr': '192.168.1.0/24'}, - {'id': 'mysubid2', 'cidr': '172.16.0.0/24'}, - {'id': 'mysubid3', 'cidr': '10.1.1.0/24'}]})) - mock_request.side_effect = [resp1, resp2] - args = [] - cmd_parser = cmd.get_parser('list_networks') - parsed_args = cmd_parser.parse_args(args) - result = cmd.take_action(parsed_args) - - mock_get_client.assert_called_with() - self.assertEqual(2, mock_request.call_count) - mock_request.assert_has_calls([ - mock.call( - test_cli20.MyUrlComparator( - test_cli20.end_url(nets_path, nets_query), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})), - mock.call( - test_cli20.MyUrlComparator( - test_cli20.end_url(subnets_path, subnets_query), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN}))]) - _result = [x for x in result[1]] - self.assertEqual(len(expected), len(_result)) - for res, exp in zip(_result, expected): - self.assertEqual(len(exp), len(res)) - for obsrvd, expctd in zip(res, exp): - self.assertEqual(expctd, obsrvd) - - def test_list_nets_extend_subnets(self): - data = [{'id': 'netid1', 'name': 'net1', 'subnets': ['mysubid1']}, - {'id': 'netid2', 'name': 'net2', 'subnets': ['mysubid2', - 'mysubid3']}] - # id, name, subnets - expected = [('netid1', 'net1', 'mysubid1 192.168.1.0/24'), - ('netid2', 'net2', - 'mysubid2 172.16.0.0/24\nmysubid3 10.1.1.0/24')] - self._test_list_nets_extend_subnets(data, expected) - - def test_list_nets_extend_subnets_no_subnet(self): - data = [{'id': 'netid1', 'name': 'net1', 'subnets': ['mysubid1']}, - {'id': 'netid2', 'name': 'net2', 'subnets': ['mysubid4']}] - # id, name, subnets - expected = [('netid1', 'net1', 'mysubid1 192.168.1.0/24'), - ('netid2', 'net2', 'mysubid4 ')] - self._test_list_nets_extend_subnets(data, expected) - - def test_list_nets_fields(self): - # List nets: --fields a --fields b -- --fields c d. - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, - fields_1=['a', 'b'], fields_2=['c', 'd']) - - def _test_list_nets_columns(self, cmd, returned_body, - args=('-f', 'json')): - resources = 'networks' - with mock.patch.object(network.ListNetwork, "extend_list", - return_value=None) as mock_extend_list: - self._test_list_columns(cmd, resources, returned_body, args=args) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def test_list_nets_defined_column(self): - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - returned_body = {"networks": [{"name": "buildname3", - "id": "id3", - "tenant_id": "tenant_3", - "subnets": []}]} - self._test_list_nets_columns(cmd, returned_body, - args=['-f', 'json', '-c', 'id']) - _str = self.fake_stdout.make_string() - returned_networks = jsonutils.loads(_str) - self.assertEqual(1, len(returned_networks)) - net = returned_networks[0] - self.assertEqual(1, len(net)) - self.assertIn("id", net.keys()) - - def test_list_nets_with_default_column(self): - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - returned_body = {"networks": [{"name": "buildname3", - "id": "id3", - "tenant_id": "tenant_3", - "subnets": []}]} - self._test_list_nets_columns(cmd, returned_body) - _str = self.fake_stdout.make_string() - returned_networks = jsonutils.loads(_str) - self.assertEqual(1, len(returned_networks)) - net = returned_networks[0] - self.assertEqual(3, len(net)) - self.assertEqual(0, len(set(net) ^ set(cmd.list_columns))) - - def test_list_external_nets_empty_with_column(self): - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - reses = {resources: []} - resstr = self.client.serialize(reses) - # url method body - query = "router%3Aexternal=True&id=myfakeid" - args = ['-c', 'id', '--', '--id', 'myfakeid'] - path = getattr(self.client, resources + "_path") - resp = (test_cli20.MyResp(200), resstr) - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request, \ - mock.patch.object(network.ListNetwork, "extend_list", - return_value=None) as mock_extend_list: - cmd_parser = cmd.get_parser("list_" + resources) - shell.run_command(cmd, cmd_parser, args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query), self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - _str = self.fake_stdout.make_string() - self.assertEqual('\n', _str) - - def _test_list_external_nets(self, resources, cmd, - detail=False, tags=(), - fields_1=(), fields_2=()): - reses = {resources: [{'id': 'myid1', }, - {'id': 'myid2', }, ], } - - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - - # url method body - query = "" - args = detail and ['-D', ] or [] - if fields_1: - for field in fields_1: - args.append('--fields') - args.append(field) - if tags: - args.append('--') - args.append("--tag") - for tag in tags: - args.append(tag) - if (not tags) and fields_2: - args.append('--') - if fields_2: - args.append("--fields") - for field in fields_2: - args.append(field) - for field in itertools.chain(fields_1, fields_2): - if query: - query += "&fields=" + field - else: - query = "fields=" + field - if query: - query += '&router%3Aexternal=True' - else: - query += 'router%3Aexternal=True' - for tag in tags: - if query: - query += "&tag=" + tag - else: - query = "tag=" + tag - if detail: - query = query and query + '&verbose=True' or 'verbose=True' - path = getattr(self.client, resources + "_path") - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request, \ - mock.patch.object(network.ListNetwork, "extend_list", - return_value=None) as mock_extend_list: - cmd_parser = cmd.get_parser("list_" + resources) - shell.run_command(cmd, cmd_parser, args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query), self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - _str = self.fake_stdout.make_string() - - self.assertIn('myid1', _str) - - def test_list_external_nets_detail(self): - # list external nets: -D. - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_external_nets(resources, cmd, True) - - def test_list_external_nets_tags(self): - # List external nets: -- --tags a b. - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_external_nets(resources, - cmd, tags=['a', 'b']) - - def test_list_external_nets_detail_tags(self): - # List external nets: -D -- --tags a b. - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_external_nets(resources, cmd, - detail=True, tags=['a', 'b']) - - def test_list_external_nets_fields(self): - # List external nets: --fields a --fields b -- --fields c d. - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_external_nets(resources, cmd, - fields_1=['a', 'b'], - fields_2=['c', 'd']) - - def test_list_shared_networks(self): - # list nets : --shared False - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, base_args='--shared False'.split(), - query='shared=False') - - -class CLITestV20UpdateNetworkJSON(test_cli20.CLITestV20Base): - def test_update_network_exception(self): - # Update net: myid. - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self.assertRaises(exceptions.CommandError, self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - - def test_update_network(self): - # Update net: myid --name myname --tags a b. - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--tags', 'a', 'b', '--description', - 'This network takes the scenic route'], - {'name': 'myname', 'tags': ['a', 'b'], - 'description': 'This network takes the ' - 'scenic route'}) - - def test_update_network_with_unicode(self): - # Update net: myid --name u'\u7f51\u7edc' --tags a b. - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', u'\u7f51\u7edc', - '--tags', 'a', 'b'], - {'name': u'\u7f51\u7edc', - 'tags': ['a', 'b'], } - ) - - def test_update_network_with_qos_policy(self): - # Update net: myid --qos-policy mypolicy. - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--qos-policy', 'mypolicy'], - {'qos_policy_id': 'mypolicy', }) - - def test_update_network_with_no_qos_policy(self): - # Update net: myid --no-qos-policy. - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--no-qos-policy'], - {'qos_policy_id': None, }) - - def test_update_network_with_dns_domain(self): - # Update net: myid --dns-domain my-domain.org. - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--dns-domain', 'my-domain.org.'], - {'dns_domain': 'my-domain.org.', }) - - def test_update_network_with_no_dns_domain(self): - # Update net: myid --no-dns-domain - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--no-dns-domain'], - {'dns_domain': "", }) - - -class CLITestV20ShowNetworkJSON(test_cli20.CLITestV20Base): - def test_show_network(self): - # Show net: --fields id --fields name myid. - resource = 'network' - cmd = network.ShowNetwork(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - -class CLITestV20DeleteNetworkJSON(test_cli20.CLITestV20Base): - def test_delete_network(self): - # Delete net: myid. - resource = 'network' - cmd = network.DeleteNetwork(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_bulk_delete_network(self): - # Delete net: myid1 myid2. - resource = 'network' - cmd = network.DeleteNetwork(test_cli20.MyApp(sys.stdout), None) - myid1 = 'myid1' - myid2 = 'myid2' - args = [myid1, myid2] - self._test_delete_resource(resource, cmd, myid1, args, extra_id=myid2) - - def test_bulk_delete_network_fail(self): - # Delete net: myid1 myid2. - resource = 'network' - cmd = network.DeleteNetwork(test_cli20.MyApp(sys.stdout), None) - myid1 = 'myid1' - myid2 = 'myid2' - args = [myid1, myid2] - self.assertRaises(exceptions.NeutronCLIError, - self._test_delete_resource, - resource, cmd, myid1, args, extra_id=myid2, - delete_fail=True) - - -class CLITestV20ExtendListNetworkJSON(test_cli20.CLITestV20Base): - def _build_test_data(self, data): - subnet_ids = [] - response = [] - filters = "" - for n in data: - if 'subnets' in n: - subnet_ids.extend(n['subnets']) - for subnet_id in n['subnets']: - filters = "%s&id=%s" % (filters, subnet_id) - response.append({'id': subnet_id, - 'cidr': '192.168.0.0/16'}) - resp_str = self.client.serialize({'subnets': response}) - resp = (test_cli20.MyResp(200), resp_str) - return filters, resp - - def test_extend_list(self): - data = [{'id': 'netid%d' % i, 'name': 'net%d' % i, - 'subnets': ['mysubid%d' % i]} - for i in range(10)] - filters, response = self._build_test_data(data) - path = getattr(self.client, 'subnets_path') - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=response) as mock_request: - known_args, _vs = cmd.get_parser('create_subnets')\ - .parse_known_args() - cmd.extend_list(data, known_args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator(test_cli20.end_url( - path, 'fields=id&fields=cidr' + filters), self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - def test_extend_list_exceed_max_uri_len(self): - data = [{'id': 'netid%d' % i, 'name': 'net%d' % i, - 'subnets': ['mysubid%d' % i]} - for i in range(10)] - # Since in pagination we add &marker= (44 symbols), total change - # is 45 symbols. Single subnet takes 40 symbols (id=&). - # Because of it marker will take more space than single subnet filter, - # and we expect neutron to send last 2 subnets in separate response. - filters1, response1 = self._build_test_data(data[:len(data) - 2]) - filters2, response2 = self._build_test_data(data[len(data) - 2:]) - path = getattr(self.client, 'subnets_path') - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, - "request") as mock_request, \ - mock.patch.object(self.client.httpclient, "_check_uri_length", - return_value=None) as mock_check_uri_length: - # 1 char of extra URI len will cause a split in 2 requests - mock_check_uri_length.side_effect = [ - exceptions.RequestURITooLong(excess=1), None, None] - mock_request.side_effect = [response1, response2] - known_args, _vs = cmd.get_parser('create_subnets')\ - .parse_known_args() - cmd.extend_list(data, known_args) - - mock_get_client.assert_called_once_with() - self.assertEqual(2, mock_request.call_count) - mock_request.assert_has_calls([ - mock.call( - test_cli20.MyUrlComparator( - test_cli20.end_url( - path, 'fields=id&fields=cidr%s' % filters1), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})), - mock.call( - test_cli20.MyUrlComparator( - test_cli20.end_url( - path, 'fields=id&fields=cidr%s' % filters2), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN}))]) diff --git a/neutronclient/tests/unit/test_cli20_network_ip_availability.py b/neutronclient/tests/unit/test_cli20_network_ip_availability.py deleted file mode 100644 index eb325a8f6..000000000 --- a/neutronclient/tests/unit/test_cli20_network_ip_availability.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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 sys - -from neutronclient.neutron.v2_0 import network_ip_availability -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20NetworkIPAvailability(test_cli20.CLITestV20Base): - - id_field = 'network_id' - - def _test_list_network_ip_availability(self, args, query): - resources = "network_ip_availabilities" - cmd = network_ip_availability.ListIpAvailability(test_cli20.MyApp - (sys.stdout), None) - self._test_list_resources(resources, cmd, - base_args=args, - query=query) - - def test_list_network_ip_availability(self): - self._test_list_network_ip_availability(args=None, - query='ip_version=4') - - def test_list_network_ip_availability_ipv6(self): - self._test_list_network_ip_availability( - args=['--ip-version', '6'], query='ip_version=6') - - def test_list_network_ip_availability_net_id_and_ipv4(self): - self._test_list_network_ip_availability( - args=['--ip-version', '4', '--network-id', 'myid'], - query='ip_version=4&network_id=myid') - - def test_list_network_ip_availability_net_name_and_tenant_id(self): - self._test_list_network_ip_availability( - args=['--network-name', 'foo', '--tenant-id', 'mytenant'], - query='network_name=foo&tenant_id=mytenant&ip_version=4') - - def test_show_network_ip_availability(self): - resource = "network_ip_availability" - cmd = network_ip_availability.ShowIpAvailability( - test_cli20.MyApp(sys.stdout), None) - self._test_show_resource(resource, cmd, self.test_id, - args=[self.test_id]) diff --git a/neutronclient/tests/unit/test_cli20_port.py b/neutronclient/tests/unit/test_cli20_port.py deleted file mode 100644 index ab7e95655..000000000 --- a/neutronclient/tests/unit/test_cli20_port.py +++ /dev/null @@ -1,794 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# 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 itertools -import sys -from unittest import mock - - -from neutronclient.neutron.v2_0 import port -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20PortJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20PortJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_port(self): - # Create port: netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = [netid, '--description', 'DESC'] - position_names = ['network_id'] - position_values = [] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - description='DESC') - - def test_create_port_extra_dhcp_opts_args(self): - # Create port: netid --extra_dhcp_opt. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - extra_dhcp_opts = [{'opt_name': 'bootfile-name', - 'opt_value': 'pxelinux.0'}, - {'opt_name': 'tftp-server', - 'opt_value': '123.123.123.123'}, - {'opt_name': 'server-ip-address', - 'opt_value': '123.123.123.45'}] - args = [netid] - for dhcp_opt in extra_dhcp_opts: - args += ['--extra-dhcp-opt', - ('opt_name=%(opt_name)s,opt_value=%(opt_value)s' % - dhcp_opt)] - position_names = ['network_id', 'extra_dhcp_opts'] - position_values = [netid, extra_dhcp_opts] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_extra_dhcp_opts_args_ip_version(self): - # Create port: netid --extra_dhcp_opt. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - extra_dhcp_opts = [{'opt_name': 'bootfile-name', - 'opt_value': 'pxelinux.0', - 'ip_version': "4"}, - {'opt_name': 'tftp-server', - 'opt_value': '2001:192:168::1', - 'ip_version': "6"}, - {'opt_name': 'server-ip-address', - 'opt_value': '123.123.123.45', - 'ip_version': "4"}] - args = [netid] - for dhcp_opt in extra_dhcp_opts: - args += ['--extra-dhcp-opt', - ('opt_name=%(opt_name)s,opt_value=%(opt_value)s,' - 'ip_version=%(ip_version)s' % - dhcp_opt)] - position_names = ['network_id', 'extra_dhcp_opts'] - position_values = [netid, extra_dhcp_opts] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_full(self): - # Create port: --mac_address mac --device_id deviceid netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--mac_address', 'mac', '--device_id', 'deviceid', netid] - position_names = ['network_id', 'mac_address', 'device_id'] - position_values = [netid, 'mac', 'deviceid'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--mac-address', 'mac', '--device-id', 'deviceid', netid] - position_names = ['network_id', 'mac_address', 'device_id'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_vnic_type_normal(self): - # Create port: --vnic_type normal netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--vnic_type', 'normal', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['normal', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--vnic-type', 'normal', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['normal', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_vnic_type_direct(self): - # Create port: --vnic_type direct netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--vnic_type', 'direct', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['direct', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--vnic-type', 'direct', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['direct', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_vnic_type_direct_physical(self): - # Create port: --vnic_type direct-physical netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--vnic_type', 'direct-physical', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['direct-physical', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--vnic-type', 'direct-physical', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['direct-physical', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_vnic_type_macvtap(self): - # Create port: --vnic_type macvtap netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--vnic_type', 'macvtap', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['macvtap', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--vnic-type', 'macvtap', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['macvtap', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_vnic_type_baremetal(self): - # Create port: --vnic_type baremetal netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--vnic_type', 'baremetal', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['baremetal', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--vnic-type', 'baremetal', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['baremetal', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_vnic_type_smart_nic(self): - # Create port: --vnic_type smart-nic netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--vnic_type', 'smart-nic', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['smart-nic', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--vnic-type', 'smart-nic', netid] - position_names = ['binding:vnic_type', 'network_id'] - position_values = ['smart-nic', netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_with_binding_profile(self): - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--binding_profile', '{"foo":"bar"}', netid] - position_names = ['binding:profile', 'network_id'] - position_values = [{'foo': 'bar'}, netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--binding-profile', '{"foo":"bar"}', netid] - position_names = ['binding:profile', 'network_id'] - position_values = [{'foo': 'bar'}, netid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_tenant(self): - # Create port: --tenant_id tenantid netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--tenant_id', 'tenantid', netid, ] - position_names = ['network_id'] - position_values = [] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - # Test dashed options - args = ['--tenant-id', 'tenantid', netid, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_port_tags(self): - # Create port: netid mac_address device_id --tags a b. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = [netid, '--tags', 'a', 'b'] - position_names = ['network_id'] - position_values = [] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tags=['a', 'b']) - - def test_create_port_secgroup(self): - # Create port: --security-group sg1_id netid. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--security-group', 'sg1_id', netid] - position_names = ['network_id', 'security_groups'] - position_values = [netid, ['sg1_id']] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_secgroups(self): - # Create port: netid - # The are --security-group sg1_id - # --security-group sg2_id - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--security-group', 'sg1_id', - '--security-group', 'sg2_id', - netid] - position_names = ['network_id', 'security_groups'] - position_values = [netid, ['sg1_id', 'sg2_id']] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_secgroup_off(self): - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--no-security-groups', netid] - position_names = ['network_id', 'security_groups'] - position_values = [netid, []] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_secgroups_list(self): - # Create port: netid - # The are --security-groups list=true sg_id1 sg_id2 - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = [netid, '--security-groups', 'list=true', 'sg_id1', 'sg_id2'] - position_names = ['network_id', 'security_groups'] - position_values = [netid, ['sg_id1', 'sg_id2']] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_with_qos_policy(self): - # Create port: --qos-policy mypolicy. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - qos_policy_name = 'mypolicy' - args = [netid, '--qos-policy', qos_policy_name] - position_names = ['network_id', 'qos_policy_id'] - position_values = [netid, qos_policy_name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_with_dns_name(self): - # Create port: --dns-name my-port. - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - dns_name_name = 'my-port' - args = [netid, '--dns-name', dns_name_name] - position_names = ['network_id', 'dns_name'] - position_values = [netid, dns_name_name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_with_allowed_address_pair_ipaddr(self): - # Create port: - # --allowed-address-pair ip_address=addr0 - # --allowed-address-pair ip_address=addr1 - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - pairs = [{'ip_address': '123.123.123.123'}, - {'ip_address': '123.123.123.45'}] - args = [netid, - '--allowed-address-pair', - 'ip_address=123.123.123.123', - '--allowed-address-pair', - 'ip_address=123.123.123.45'] - position_names = ['network_id', 'allowed_address_pairs'] - position_values = [netid, pairs] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_with_allowed_address_pair(self): - # Create port: - # --allowed-address-pair ip_address=addr0,mac_address=mac0 - # --allowed-address-pair ip_address=addr1,mac_address=mac1 - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - pairs = [{'ip_address': '123.123.123.123', - 'mac_address': '10:00:00:00:00:00'}, - {'ip_address': '123.123.123.45', - 'mac_address': '10:00:00:00:00:01'}] - args = [netid, - '--allowed-address-pair', - 'ip_address=123.123.123.123,mac_address=10:00:00:00:00:00', - '--allowed-address-pair', - 'ip_address=123.123.123.45,mac_address=10:00:00:00:00:01'] - position_names = ['network_id', 'allowed_address_pairs'] - position_values = [netid, pairs] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_ports(self): - # List ports: -D. - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_ports_pagination(self): - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_ports_sort(self): - # list ports: - # --sort-key name --sort-key id --sort-key asc --sort-key desc - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_ports_limit(self): - # list ports: -P. - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_list_ports_tags(self): - # List ports: -- --tags a b. - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, tags=['a', 'b']) - - def test_list_ports_detail_tags(self): - # List ports: -D -- --tags a b. - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, detail=True, tags=['a', 'b']) - - def test_list_ports_fields(self): - # List ports: --fields a --fields b -- --fields c d. - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - fields_1=['a', 'b'], fields_2=['c', 'd']) - - def test_list_ports_with_fixed_ips_in_csv(self): - # List ports: -f csv. - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - fixed_ips = [{"subnet_id": "30422057-d6df-4c90-8314-aefb5e326666", - "ip_address": "10.0.0.12"}, - {"subnet_id": "30422057-d6df-4c90-8314-aefb5e326666", - "ip_address": "10.0.0.4"}] - contents = [{'name': 'name1', 'fixed_ips': fixed_ips}] - self._test_list_resources(resources, cmd, True, - response_contents=contents, - output_format='csv') - - def _test_list_router_port(self, resources, cmd, - myid, detail=False, tags=(), - fields_1=(), fields_2=()): - reses = {resources: [{'id': 'myid1', }, - {'id': 'myid2', }, ], } - - resstr = self.client.serialize(reses) - # url method body - query = "" - args = detail and ['-D', ] or [] - - if fields_1: - for field in fields_1: - args.append('--fields') - args.append(field) - args.append(myid) - if tags: - args.append('--') - args.append("--tag") - for tag in tags: - args.append(tag) - if (not tags) and fields_2: - args.append('--') - if fields_2: - args.append("--fields") - for field in fields_2: - args.append(field) - for field in itertools.chain(fields_1, fields_2): - if query: - query += "&fields=" + field - else: - query = "fields=" + field - - for tag in tags: - if query: - query += "&tag=" + tag - else: - query = "tag=" + tag - if detail: - query = query and query + '&verbose=True' or 'verbose=True' - query = query and query + '&device_id=%s' or 'device_id=%s' - path = getattr(self.client, resources + "_path") - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=(test_cli20.MyResp(200), - resstr)) as mock_request: - cmd_parser = cmd.get_parser("list_" + resources) - shell.run_command(cmd, cmd_parser, args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), 2) - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query % myid), self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - _str = self.fake_stdout.make_string() - - self.assertIn('myid1', _str) - - def test_list_router_ports(self): - # List router ports: -D. - resources = "ports" - cmd = port.ListRouterPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_router_port(resources, cmd, - self.test_id, True) - - def test_list_router_ports_tags(self): - # List router ports: -- --tags a b. - resources = "ports" - cmd = port.ListRouterPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_router_port(resources, cmd, - self.test_id, tags=['a', 'b']) - - def test_list_router_ports_detail_tags(self): - # List router ports: -D -- --tags a b. - resources = "ports" - cmd = port.ListRouterPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_router_port(resources, cmd, self.test_id, - detail=True, tags=['a', 'b']) - - def test_list_router_ports_fields(self): - # List ports: --fields a --fields b -- --fields c d. - resources = "ports" - cmd = port.ListRouterPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_router_port(resources, cmd, self.test_id, - fields_1=['a', 'b'], - fields_2=['c', 'd']) - - def test_update_port(self): - # Update port: myid --name myname --admin-state-up False --tags a b. - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--admin-state-up', 'False', - '--description', 'garbage', - '--tags', 'a', 'b'], - {'name': 'myname', - 'admin_state_up': 'False', - 'description': 'garbage', - 'tags': ['a', 'b'], }) - - def test_update_port_secgroup(self): - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = ['--security-group', 'sg1_id', myid] - updatefields = {'security_groups': ['sg1_id']} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_port_secgroups(self): - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = ['--security-group', 'sg1_id', - '--security-group', 'sg2_id', - myid] - updatefields = {'security_groups': ['sg1_id', 'sg2_id']} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_port_extra_dhcp_opts(self): - # Update port: myid --extra_dhcp_opt. - resource = 'port' - myid = 'myid' - args = [myid, - '--extra-dhcp-opt', - "opt_name=bootfile-name,opt_value=pxelinux.0", - '--extra-dhcp-opt', - "opt_name=tftp-server,opt_value=123.123.123.123", - '--extra-dhcp-opt', - "opt_name=server-ip-address,opt_value=123.123.123.45" - ] - updatedfields = {'extra_dhcp_opts': [{'opt_name': 'bootfile-name', - 'opt_value': 'pxelinux.0'}, - {'opt_name': 'tftp-server', - 'opt_value': '123.123.123.123'}, - {'opt_name': 'server-ip-address', - 'opt_value': '123.123.123.45'}]} - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, myid, args, updatedfields) - - def test_update_port_fixed_ip(self): - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - subnet_id = 'subnet_id' - ip_addr = '123.123.123.123' - args = [myid, - '--fixed-ip', - "subnet_id=%(subnet_id)s,ip_address=%(ip_addr)s" % - {'subnet_id': subnet_id, - 'ip_addr': ip_addr}] - updated_fields = {"fixed_ips": [{'subnet_id': subnet_id, - 'ip_address': ip_addr}]} - self._test_update_resource(resource, cmd, myid, args, updated_fields) - - def test_update_port_device_id_device_owner(self): - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = ['--device-id', 'dev_id', '--device-owner', 'fake', myid] - updatefields = {'device_id': 'dev_id', - 'device_owner': 'fake'} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_port_extra_dhcp_opts_ip_version(self): - # Update port: myid --extra_dhcp_opt. - resource = 'port' - myid = 'myid' - args = [myid, - '--extra-dhcp-opt', - "opt_name=bootfile-name,opt_value=pxelinux.0,ip_version=4", - '--extra-dhcp-opt', - "opt_name=tftp-server,opt_value=2001:192:168::1,ip_version=6", - '--extra-dhcp-opt', - "opt_name=server-ip-address,opt_value=null,ip_version=4" - ] - updatedfields = {'extra_dhcp_opts': [{'opt_name': 'bootfile-name', - 'opt_value': 'pxelinux.0', - 'ip_version': '4'}, - {'opt_name': 'tftp-server', - 'opt_value': '2001:192:168::1', - 'ip_version': '6'}, - {'opt_name': 'server-ip-address', - 'opt_value': None, - 'ip_version': '4'}]} - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, myid, args, updatedfields) - - def test_update_port_with_qos_policy(self): - # Update port: myid --qos-policy mypolicy. - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--qos-policy', 'mypolicy'], - {'qos_policy_id': 'mypolicy', }) - - def test_update_port_with_no_qos_policy(self): - # Update port: myid --no-qos-policy. - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--no-qos-policy'], - {'qos_policy_id': None, }) - - def test_update_port_with_dns_name(self): - # Update port: myid --dns-name my-port. - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--dns-name', 'my-port'], - {'dns_name': 'my-port', }) - - def test_update_port_with_no_dns_name(self): - # Update port: myid --no-dns-name - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--no-dns-name'], - {'dns_name': "", }) - - def test_delete_extra_dhcp_opts_from_port(self): - resource = 'port' - myid = 'myid' - args = [myid, - '--extra-dhcp-opt', - "opt_name=bootfile-name,opt_value=null", - '--extra-dhcp-opt', - "opt_name=tftp-server,opt_value=123.123.123.123", - '--extra-dhcp-opt', - "opt_name=server-ip-address,opt_value=123.123.123.45" - ] - # the client code will change the null to None and send to server, - # where its interpreted as delete the DHCP option on the port. - updatedfields = {'extra_dhcp_opts': [{'opt_name': 'bootfile-name', - 'opt_value': None}, - {'opt_name': 'tftp-server', - 'opt_value': '123.123.123.123'}, - {'opt_name': 'server-ip-address', - 'opt_value': '123.123.123.45'}]} - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, myid, args, updatedfields) - - def test_update_port_security_group_off(self): - # Update port: --no-security-groups myid. - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['--no-security-groups', 'myid'], - {'security_groups': []}) - - def test_update_port_allowed_address_pair_ipaddr(self): - # Update port(ip_address only): - # --allowed-address-pairs ip_address=addr0 - # --allowed-address-pairs ip_address=addr1 - import sys - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - pairs = [{'ip_address': '123.123.123.123'}, - {'ip_address': '123.123.123.45'}] - args = [myid, - '--allowed-address-pair', - 'ip_address=123.123.123.123', - '--allowed-address-pair', - 'ip_address=123.123.123.45'] - updatefields = {'allowed_address_pairs': pairs} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_port_allowed_address_pair(self): - # Update port: - # --allowed-address-pair ip_address=addr0,mac_address=mac0 - # --allowed-address-pair ip_address_addr1,mac_address=mac1 - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - pairs = [{'ip_address': '123.123.123.123', - 'mac_address': '10:00:00:00:00:00'}, - {'ip_address': '123.123.123.45', - 'mac_address': '10:00:00:00:00:01'}] - args = [myid, - '--allowed-address-pair', - 'ip_address=123.123.123.123,mac_address=10:00:00:00:00:00', - '--allowed-address-pair', - 'ip_address=123.123.123.45,mac_address=10:00:00:00:00:01'] - updatefields = {'allowed_address_pairs': pairs} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_port_allowed_address_pairs_off(self): - # Update port: --no-allowed-address-pairs. - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['--no-allowed-address-pairs', 'myid'], - {'allowed_address_pairs': []}) - - def test_show_port(self): - # Show port: --fields id --fields name myid. - resource = 'port' - cmd = port.ShowPort(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_delete_port(self): - # Delete port: myid. - resource = 'port' - cmd = port.DeletePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) diff --git a/neutronclient/tests/unit/test_cli20_purge.py b/neutronclient/tests/unit/test_cli20_purge.py deleted file mode 100644 index 9bfd91c53..000000000 --- a/neutronclient/tests/unit/test_cli20_purge.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2016 Cisco Systems -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0 import purge -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Purge(test_cli20.CLITestV20Base): - - def setUp(self): - super(CLITestV20Purge, self).setUp() - self.resource_types = ['floatingip', 'port', 'router', - 'network', 'security_group'] - - def _generate_resources_dict(self, value=0): - resources_dict = {} - resources_dict['true'] = value - for resource_type in self.resource_types: - resources_dict[resource_type] = value - return resources_dict - - def _verify_suffix(self, resources, message): - for resource, value in resources.items(): - if value > 0: - suffix = list('%(value)d %(resource)s' % - {'value': value, 'resource': resource}) - if value != 1: - suffix.append('s') - suffix = ''.join(suffix) - self.assertIn(suffix, message) - else: - self.assertNotIn(resource, message) - - def _verify_message(self, message, deleted, failed): - message = message.split('.') - success_prefix = "Deleted " - failure_prefix = "The following resources could not be deleted: " - if not deleted['true']: - for msg in message: - self.assertNotIn(success_prefix, msg) - message = message[0] - if not failed['true']: - expected = 'Tenant has no supported resources' - self.assertEqual(expected, message) - else: - self.assertIn(failure_prefix, message) - self._verify_suffix(failed, message) - else: - resources_deleted = message[0] - self.assertIn(success_prefix, resources_deleted) - self._verify_suffix(deleted, resources_deleted) - if failed['true']: - resources_failed = message[1] - self.assertIn(failure_prefix, resources_failed) - self._verify_suffix(failed, resources_failed) - else: - for msg in message: - self.assertNotIn(failure_prefix, msg) - - def _verify_result(self, my_purge, deleted, failed): - message = my_purge._build_message(deleted, failed, failed['true']) - self._verify_message(message, deleted, failed) - - def test_build_message(self): - my_purge = purge.Purge(test_cli20.MyApp(sys.stdout), None) - - # Verify message when tenant has no supported resources - deleted = self._generate_resources_dict() - failed = self._generate_resources_dict() - self._verify_result(my_purge, deleted, failed) - - # Verify message when tenant has supported resources, - # and they are all deleteable - deleted = self._generate_resources_dict(1) - self._verify_result(my_purge, deleted, failed) - - # Verify message when tenant has supported resources, - # and some are not deleteable - failed = self._generate_resources_dict(1) - self._verify_result(my_purge, deleted, failed) - - # Verify message when tenant has supported resources, - # and all are not deleteable - deleted = self._generate_resources_dict() - self._verify_result(my_purge, deleted, failed) diff --git a/neutronclient/tests/unit/test_cli20_rbac.py b/neutronclient/tests/unit/test_cli20_rbac.py deleted file mode 100644 index ca89df6f9..000000000 --- a/neutronclient/tests/unit/test_cli20_rbac.py +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright 2015 Huawei Technologies India Pvt Ltd. -# All Rights Reserved -# -# 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 sys - -import testscenarios - -from neutronclient.neutron.v2_0 import rbac -from neutronclient.tests.unit import test_cli20 - -load_tests = testscenarios.load_tests_apply_scenarios - - -class CLITestV20RBACBaseJSON(test_cli20.CLITestV20Base): - non_admin_status_resources = ['rbac_policy'] - - scenarios = [ - ('network rbac objects', - {'object_type_name': 'network', 'object_type_val': 'network'}), - ('qos policy rbac objects', - {'object_type_name': 'qos-policy', 'object_type_val': 'qos_policy'}), - ] - - def test_create_rbac_policy_with_mandatory_params(self): - # Create rbac: rbac_object --type --action - # access_as_shared - resource = 'rbac_policy' - cmd = rbac.CreateRBACPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'rbac_object' - myid = 'myid' - args = [name, '--type', self.object_type_name, - '--action', 'access_as_shared'] - position_names = ['object_id', 'object_type', - 'target_tenant', 'action'] - position_values = [name, self.object_type_val, '*', - 'access_as_shared'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_rbac_policy_with_all_params(self): - # Create rbac: rbac_object --type - # --target-tenant tenant_id --action access_as_external - resource = 'rbac_policy' - cmd = rbac.CreateRBACPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'rbac_object' - myid = 'myid' - args = [name, '--type', self.object_type_name, - '--target-tenant', 'tenant_id', - '--action', 'access_as_external'] - position_names = ['object_id', 'object_type', - 'target_tenant', 'action'] - position_values = [name, self.object_type_val, 'tenant_id', - 'access_as_external'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_rbac_policy_with_unicode(self): - # Create rbac policy u'\u7f51\u7edc'. - resource = 'rbac_policy' - cmd = rbac.CreateRBACPolicy(test_cli20.MyApp(sys.stdout), None) - name = u'\u7f51\u7edc' - myid = 'myid' - args = [name, '--type', self.object_type_name, - '--target-tenant', 'tenant_id', - '--action', 'access_as_external'] - position_names = ['object_id', 'object_type', - 'target_tenant', 'action'] - position_values = [name, self.object_type_val, 'tenant_id', - 'access_as_external'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_update_rbac_policy(self): - # rbac-update --target-tenant . - resource = 'rbac_policy' - cmd = rbac.UpdateRBACPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--target-tenant', 'tenant_id'], - {'target_tenant': 'tenant_id', }) - - def test_delete_rbac_policy(self): - # rbac-delete my-id. - resource = 'rbac_policy' - cmd = rbac.DeleteRBACPolicy(test_cli20.MyApp(sys.stdout), None) - my_id = 'myid1' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_list_rbac_policies(self): - # rbac-list. - resources = "rbac_policies" - cmd = rbac.ListRBACPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_rbac_policies_pagination(self): - # rbac-list with pagination. - resources = "rbac_policies" - cmd = rbac.ListRBACPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_rbac_policies_sort(self): - # sorted list: - # rbac-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "rbac_policies" - cmd = rbac.ListRBACPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_rbac_policies_limit(self): - # size (1000) limited list: rbac-list -P. - resources = "rbac_policies" - cmd = rbac.ListRBACPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_rbac_policy(self): - # rbac-show test_id. - resource = 'rbac_policy' - cmd = rbac.ShowRBACPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) diff --git a/neutronclient/tests/unit/test_cli20_router.py b/neutronclient/tests/unit/test_cli20_router.py deleted file mode 100644 index ba267f77e..000000000 --- a/neutronclient/tests/unit/test_cli20_router.py +++ /dev/null @@ -1,434 +0,0 @@ -# Copyright 2012 VMware, Inc -# All Rights Reserved -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import router -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20RouterJSON(test_cli20.CLITestV20Base): - def test_create_router(self): - # Create router: router1. - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'router1' - myid = 'myid' - args = [name, '--description', 'rooter'] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - description='rooter') - - def test_create_router_flavor(self): - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'router1' - myid = 'myid' - flavor = 'router-flavor' - args = [name, '--flavor', flavor] - position_names = ['name', ] - position_values = [name, flavor] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - flavor_id='router-flavor') - - def test_create_router_tenant(self): - # Create router: --tenant_id tenantid myname. - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = ['--tenant_id', 'tenantid', name] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_router_admin_state(self): - # Create router: --admin_state_down myname. - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = ['--admin_state_down', name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - admin_state_up=False) - - def _create_router_distributed_or_ha(self, distributed=None, ha=None): - # Create router: --distributed distributed --ha ha myname. - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = [] - if distributed is not None: - args += ['--distributed', str(distributed)] - if ha is not None: - args += ['--ha', str(ha)] - args.append(name) - position_names = ['name', ] - position_values = [name, ] - expected = {} - if distributed is not None: - expected['distributed'] = str(distributed) - if ha is not None: - expected['ha'] = str(ha) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - **expected) - - def test_create_router_distributed_True(self): - # Create router: --distributed=True. - self._create_router_distributed_or_ha(distributed='True') - - def test_create_router_ha_with_True(self): - self._create_router_distributed_or_ha(ha='True') - - def test_create_router_ha_with_true(self): - self._create_router_distributed_or_ha(ha='true') - - def test_create_router_ha_with_False(self): - self._create_router_distributed_or_ha(ha='False') - - def test_create_router_ha_with_false(self): - self._create_router_distributed_or_ha(ha='false') - - def test_create_router_distributed_False(self): - # Create router: --distributed=False. - self._create_router_distributed_or_ha(distributed='False') - - def test_create_router_distributed_true(self): - # Create router: --distributed=true. - self._create_router_distributed_or_ha(distributed='true') - - def test_create_router_distributed_false(self): - # Create router: --distributed=false. - self._create_router_distributed_or_ha(distributed='false') - - def test_create_router_with_az_hint(self): - # Create router: --availability-zone-hint zone1 - # --availability-zone-hint zone2. - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = ['--availability-zone-hint', 'zone1', - '--availability-zone-hint', 'zone2', name] - position_names = ['availability_zone_hints', 'name'] - position_values = [['zone1', 'zone2'], name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_routers_detail(self): - # list routers: -D. - resources = "routers" - cmd = router.ListRouter(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_routers_pagination(self): - resources = "routers" - cmd = router.ListRouter(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_routers_sort(self): - # list routers: - # --sort-key name --sort-key id --sort-key asc --sort-key desc - resources = "routers" - cmd = router.ListRouter(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_routers_limit(self): - # list routers: -P. - resources = "routers" - cmd = router.ListRouter(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_update_router_exception(self): - # Update router: myid. - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - self.assertRaises(exceptions.CommandError, self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - - def test_update_router(self): - # Update router: myid --name myname --tags a b. - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--description', ':D'], - {'name': 'myname', 'description': ':D'}) - - def test_update_router_admin_state(self): - # Update router: myid --admin-state-up . - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--admin-state-up', 'True'], - {'admin_state_up': 'True'} - ) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--admin-state-up', 'true'], - {'admin_state_up': 'true'} - ) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--admin-state-up', 'False'], - {'admin_state_up': 'False'} - ) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--admin-state-up', 'false'], - {'admin_state_up': 'false'} - ) - - def test_update_router_distributed(self): - # Update router: myid --distributed . - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--distributed', 'True'], - {'distributed': 'True'} - ) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--distributed', 'true'], - {'distributed': 'true'} - ) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--distributed', 'False'], - {'distributed': 'False'} - ) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--distributed', 'false'], - {'distributed': 'false'} - ) - - def test_update_router_no_routes(self): - # Update router: myid --no-routes - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--no-routes'], - {'routes': None}) - - def test_update_router_add_route(self): - # Update router: myid --route destination=10.0.3.0/24,nexthop=10.0.0.10 - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid, - '--route', - 'destination=10.0.3.0/24,nexthop=10.0.0.10'] - routes = [{'destination': '10.0.3.0/24', - 'nexthop': '10.0.0.10'}] - updatefields = {'routes': routes} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_router_add_routes(self): - # Update router: myid --route destination=10.0.3.0/24,nexthop=10.0.0.10 - # --route destination=fd7a:1d63:2063::/64, - # nexthop=fd7a:1d63:2063:0:f816:3eff:fe0e:a697 - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid, - '--route', - 'destination=10.0.3.0/24,nexthop=10.0.0.10', - '--route', - 'destination=fd7a:1d63:2063::/64,' - 'nexthop=fd7a:1d63:2063:0:f816:3eff:fe0e:a697'] - routes = [{'destination': '10.0.3.0/24', - 'nexthop': '10.0.0.10'}, - {'destination': 'fd7a:1d63:2063::/64', - 'nexthop': 'fd7a:1d63:2063:0:f816:3eff:fe0e:a697'}] - updatefields = {'routes': routes} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_router_no_routes_with_add_route(self): - # Update router: --no-routes with --route - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid, - '--no-routes', - '--route', - 'destination=10.0.3.0/24,nexthop=10.0.0.10'] - exception = self.assertRaises(SystemExit, - self._test_update_resource, - resource, cmd, myid, args, None) - self.assertEqual(2, exception.code) - - def test_delete_router(self): - # Delete router: myid. - resource = 'router' - cmd = router.DeleteRouter(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_router(self): - # Show router: myid. - resource = 'router' - cmd = router.ShowRouter(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def _test_add_remove_interface(self, action, mode, cmd, args): - resource = 'router' - subcmd = '%s_router_interface' % action - if mode == 'port': - body = {'port_id': 'portid'} - else: - body = {'subnet_id': 'subnetid'} - if action == 'add': - retval = {'subnet_id': 'subnetid', 'port_id': 'portid'} - retval = self.client.serialize(retval) - expected_code = 200 - else: - retval = None - expected_code = 204 - self._test_update_resource_action(resource, cmd, 'myid', - subcmd, args, - body, expected_code, retval) - - def test_add_interface_compat(self): - # Add interface to router: myid subnetid. - cmd = router.AddInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'subnetid'] - self._test_add_remove_interface('add', 'subnet', cmd, args) - - def test_add_interface_by_subnet(self): - # Add interface to router: myid subnet=subnetid. - cmd = router.AddInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'subnet=subnetid'] - self._test_add_remove_interface('add', 'subnet', cmd, args) - - def test_add_interface_by_port(self): - # Add interface to router: myid port=portid. - cmd = router.AddInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'port=portid'] - self._test_add_remove_interface('add', 'port', cmd, args) - - def test_del_interface_compat(self): - # Delete interface from router: myid subnetid. - cmd = router.RemoveInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'subnetid'] - self._test_add_remove_interface('remove', 'subnet', cmd, args) - - def test_del_interface_by_subnet(self): - # Delete interface from router: myid subnet=subnetid. - cmd = router.RemoveInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'subnet=subnetid'] - self._test_add_remove_interface('remove', 'subnet', cmd, args) - - def test_del_interface_by_port(self): - # Delete interface from router: myid port=portid. - cmd = router.RemoveInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'port=portid'] - self._test_add_remove_interface('remove', 'port', cmd, args) - - def test_set_gateway(self): - # Set external gateway for router: myid externalid. - resource = 'router' - cmd = router.SetGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'externalid'] - self._test_update_resource(resource, cmd, 'myid', - args, - {"external_gateway_info": - {"network_id": "externalid"}} - ) - - def test_set_gateway_enable_snat(self): - # enable external gateway for router: myid externalid. - resource = 'router' - cmd = router.SetGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'externalid', '--enable-snat'] - self._test_update_resource(resource, cmd, 'myid', - args, - {"external_gateway_info": - {"network_id": "externalid", - "enable_snat": True}} - ) - - def test_set_gateway_disable_snat(self): - # set external gateway for router: myid externalid. - resource = 'router' - cmd = router.SetGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'externalid', '--disable-snat'] - self._test_update_resource(resource, cmd, 'myid', - args, - {"external_gateway_info": - {"network_id": "externalid", - "enable_snat": False}} - ) - - def test_set_gateway_external_ip(self): - # set external gateway for router: myid externalid --fixed-ip ... - resource = 'router' - cmd = router.SetGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'externalid', '--fixed-ip', 'ip_address=10.0.0.2'] - self._test_update_resource(resource, cmd, 'myid', - args, - {"external_gateway_info": - {"network_id": "externalid", - "external_fixed_ips": [ - {"ip_address": "10.0.0.2"}]}} - ) - - def test_set_gateway_external_subnet(self): - # set external gateway for router: myid externalid --fixed-ip ... - resource = 'router' - cmd = router.SetGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'externalid', '--fixed-ip', 'subnet_id=mysubnet'] - self._test_update_resource(resource, cmd, 'myid', - args, - {"external_gateway_info": - {"network_id": "externalid", - "external_fixed_ips": [ - {"subnet_id": "mysubnet"}]}} - ) - - def test_set_gateway_external_ip_and_subnet(self): - # set external gateway for router: myid externalid --fixed-ip ... - resource = 'router' - cmd = router.SetGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'externalid', '--fixed-ip', - 'ip_address=10.0.0.2,subnet_id=mysubnet'] - self._test_update_resource(resource, cmd, 'myid', - args, - {"external_gateway_info": - {"network_id": "externalid", - "external_fixed_ips": [ - {"subnet_id": "mysubnet", - "ip_address": "10.0.0.2"}]}} - ) - - def test_remove_gateway(self): - # Remove external gateway from router: externalid. - resource = 'router' - cmd = router.RemoveGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['externalid'] - self._test_update_resource(resource, cmd, 'externalid', - args, {"external_gateway_info": {}} - ) diff --git a/neutronclient/tests/unit/test_cli20_securitygroup.py b/neutronclient/tests/unit/test_cli20_securitygroup.py deleted file mode 100644 index 95a578f63..000000000 --- a/neutronclient/tests/unit/test_cli20_securitygroup.py +++ /dev/null @@ -1,657 +0,0 @@ -# Copyright 2012 Red Hat -# All Rights Reserved. -# -# 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 sys -from unittest import mock -import urllib.parse as urlparse - -from oslo_utils import uuidutils - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.neutron.v2_0 import securitygroup -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20SecurityGroupsJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['security_group', 'security_group_rule'] - - def test_create_security_group(self): - # Create security group: webservers. - resource = 'security_group' - cmd = securitygroup.CreateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - name = 'webservers' - myid = 'myid' - args = [name, ] - position_names = ['name'] - position_values = [name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_security_group_tenant(self): - # Create security group: webservers. - resource = 'security_group' - cmd = securitygroup.CreateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - name = 'webservers' - description = 'my webservers' - myid = 'myid' - args = ['--tenant_id', 'tenant_id', '--description', description, name] - position_names = ['name', 'description'] - position_values = [name, description] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenant_id') - - def test_create_security_group_with_description(self): - # Create security group: webservers. - resource = 'security_group' - cmd = securitygroup.CreateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - name = 'webservers' - description = 'my webservers' - myid = 'myid' - args = [name, '--description', description] - position_names = ['name', 'description'] - position_values = [name, description] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_security_groups(self): - resources = "security_groups" - cmd = securitygroup.ListSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_security_groups_pagination(self): - resources = "security_groups" - cmd = securitygroup.ListSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_security_groups_sort(self): - resources = "security_groups" - cmd = securitygroup.ListSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_security_groups_limit(self): - resources = "security_groups" - cmd = securitygroup.ListSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_security_group_id(self): - resource = 'security_group' - cmd = securitygroup.ShowSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def test_show_security_group_id_name(self): - resource = 'security_group' - cmd = securitygroup.ShowSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_delete_security_group(self): - # Delete security group: myid. - resource = 'security_group' - cmd = securitygroup.DeleteSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_update_security_group(self): - # Update security group: myid --name myname --description desc. - resource = 'security_group' - cmd = securitygroup.UpdateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--description', 'mydescription'], - {'name': 'myname', - 'description': 'mydescription'} - ) - - def test_update_security_group_with_unicode(self): - resource = 'security_group' - cmd = securitygroup.UpdateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', u'\u7f51\u7edc', - '--description', u'\u7f51\u7edc'], - {'name': u'\u7f51\u7edc', - 'description': u'\u7f51\u7edc'} - ) - - def test_create_security_group_rule_full(self): - # Create security group rule. - resource = 'security_group_rule' - cmd = securitygroup.CreateSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - direction = 'ingress' - ethertype = 'IPv4' - protocol = 'tcp' - port_range_min = '22' - port_range_max = '22' - remote_ip_prefix = '10.0.0.0/24' - security_group_id = '1' - remote_group_id = '1' - args = ['--remote_ip_prefix', remote_ip_prefix, '--direction', - direction, '--ethertype', ethertype, '--protocol', protocol, - '--port_range_min', port_range_min, '--port_range_max', - port_range_max, '--remote_group_id', remote_group_id, - security_group_id, '--description', 'PCI policy 1421912'] - position_names = ['remote_ip_prefix', 'direction', 'ethertype', - 'protocol', 'port_range_min', 'port_range_max', - 'remote_group_id', 'security_group_id'] - position_values = [remote_ip_prefix, direction, ethertype, protocol, - port_range_min, port_range_max, remote_group_id, - security_group_id] - self._test_create_resource(resource, cmd, None, myid, args, - position_names, position_values, - description='PCI policy 1421912') - - def test_create_security_group_rule_with_integer_protocol_value(self): - resource = 'security_group_rule' - cmd = securitygroup.CreateSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - direction = 'ingress' - ethertype = 'IPv4' - protocol = '2' - port_range_min = '22' - port_range_max = '22' - remote_ip_prefix = '10.0.0.0/24' - security_group_id = '1' - remote_group_id = '1' - args = ['--remote_ip_prefix', remote_ip_prefix, '--direction', - direction, '--ethertype', ethertype, '--protocol', protocol, - '--port_range_min', port_range_min, '--port_range_max', - port_range_max, '--remote_group_id', remote_group_id, - security_group_id] - position_names = ['remote_ip_prefix', 'direction', 'ethertype', - 'protocol', 'port_range_min', 'port_range_max', - 'remote_group_id', 'security_group_id'] - position_values = [remote_ip_prefix, direction, ethertype, protocol, - port_range_min, port_range_max, remote_group_id, - security_group_id] - self._test_create_resource(resource, cmd, None, myid, args, - position_names, position_values) - - def test_delete_security_group_rule(self): - # Delete security group rule: myid. - resource = 'security_group_rule' - cmd = securitygroup.DeleteSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - @mock.patch.object(securitygroup.ListSecurityGroupRule, "extend_list") - def test_list_security_group_rules(self, mock_extend_list): - resources = "security_group_rules" - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def _build_test_data(self, data, excess=0): - # Length of a query filter on security group rule id - # in these testcases, id='secgroupid%02d' (with len(id)=12) - sec_group_id_filter_len = 12 - - response = [] - replace_rules = {'security_group_id': 'security_group', - 'remote_group_id': 'remote_group'} - - search_opts = {'fields': ['id', 'name']} - sec_group_ids = set() - for rule in data: - for key in replace_rules: - if rule.get(key): - sec_group_ids.add(rule[key]) - response.append({'id': rule[key], 'name': 'default'}) - sec_group_ids = list(sec_group_ids) - - result = [] - - sec_group_count = len(sec_group_ids) - max_size = ((sec_group_id_filter_len * sec_group_count) - excess) - chunk_size = max_size // sec_group_id_filter_len - - for i in range(0, sec_group_count, chunk_size): - search_opts['id'] = sec_group_ids[i: i + chunk_size] - params = utils.safe_encode_dict(search_opts) - resp_str = self.client.serialize({'security_groups': response}) - - result.append({ - 'filter': urlparse.urlencode(params, doseq=1), - 'response': (test_cli20.MyResp(200), resp_str), - }) - - return result - - def test_extend_list(self): - data = [{'name': 'default', - 'remote_group_id': 'remgroupid%02d' % i} - for i in range(10)] - data.append({'name': 'default', 'remote_group_id': None}) - resources = "security_groups" - - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - - path = getattr(self.client, resources + '_path') - responses = self._build_test_data(data) - known_args, _vs = cmd.get_parser( - 'list' + resources).parse_known_args() - resp = responses[0]['response'] - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - cmd.extend_list(data, known_args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator(test_cli20.end_url( - path, responses[0]['filter']), self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - def test_extend_list_exceed_max_uri_len(self): - data = [{'name': 'default', - 'security_group_id': 'secgroupid%02d' % i, - 'remote_group_id': 'remgroupid%02d' % i} - for i in range(10)] - data.append({'name': 'default', - 'security_group_id': 'secgroupid10', - 'remote_group_id': None}) - resources = "security_groups" - - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - path = getattr(self.client, resources + '_path') - responses = self._build_test_data(data, excess=1) - - known_args, _vs = cmd.get_parser( - 'list' + resources).parse_known_args() - mock_request_side_effects = [] - mock_request_calls = [] - mock_check_uri_side_effects = [exceptions.RequestURITooLong(excess=1)] - mock_check_uri_calls = [mock.call(mock.ANY)] - for item in responses: - mock_request_side_effects.append(item['response']) - mock_request_calls.append(mock.call( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, item['filter']), self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN}))) - mock_check_uri_side_effects.append(None) - mock_check_uri_calls.append(mock.call(mock.ANY)) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, - "request") as mock_request, \ - mock.patch.object(self.client.httpclient, - "_check_uri_length") as mock_check_uri: - mock_request.side_effect = mock_request_side_effects - mock_check_uri.side_effect = mock_check_uri_side_effects - cmd.extend_list(data, known_args) - - mock_get_client.assert_called_once_with() - mock_request.assert_has_calls(mock_request_calls) - mock_check_uri.assert_has_calls(mock_check_uri_calls) - self.assertEqual(len(mock_request_calls), mock_request.call_count) - self.assertEqual(len(mock_check_uri_calls), mock_check_uri.call_count) - - @mock.patch.object(securitygroup.ListSecurityGroupRule, "extend_list") - def test_list_security_group_rules_pagination(self, mock_extend_list): - resources = "security_group_rules" - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - @mock.patch.object(securitygroup.ListSecurityGroupRule, "extend_list") - def test_list_security_group_rules_sort(self, mock_extend_list): - resources = "security_group_rules" - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - @mock.patch.object(securitygroup.ListSecurityGroupRule, "extend_list") - def test_list_security_group_rules_limit(self, mock_extend_list): - resources = "security_group_rules" - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def test_show_security_group_rule(self): - resource = 'security_group_rule' - cmd = securitygroup.ShowSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def _test_list_security_group_rules_extend(self, api_data, expected, - args=(), conv=True, - query_fields=None): - def setup_list_stub(resources, data, query, mock_calls, mock_returns): - reses = {resources: data} - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, resources + '_path') - mock_calls.append(mock.call( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN}))) - mock_returns.append(resp) - - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - query = '' - if query_fields: - query = '&'.join(['fields=' + f for f in query_fields]) - mock_request_calls = [] - mock_request_returns = [] - setup_list_stub('security_group_rules', api_data, query, - mock_request_calls, mock_request_returns) - if conv: - sec_ids = set() - for n in api_data: - sec_ids.add(n['security_group_id']) - if n.get('remote_group_id'): - sec_ids.add(n['remote_group_id']) - filters = '' - for id in sec_ids: - filters = filters + "&id=%s" % id - setup_list_stub('security_groups', - [{'id': 'myid1', 'name': 'group1'}, - {'id': 'myid2', 'name': 'group2'}, - {'id': 'myid3', 'name': 'group3'}], - 'fields=id&fields=name' + filters, - mock_request_calls, - mock_request_returns) - - cmd_parser = cmd.get_parser('list_security_group_rules') - parsed_args = cmd_parser.parse_args(args) - - with mock.patch.object(cmd, "get_client", - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, - "request") as mock_request: - mock_request.side_effect = mock_request_returns - result = cmd.take_action(parsed_args) - - self.assert_mock_multiple_calls_with_same_arguments( - mock_get_client, mock.call(), None) - mock_request.assert_has_calls(mock_request_calls) - self.assertEqual(len(mock_request_calls), mock_request.call_count) - self.assertEqual(expected['cols'], result[0]) - # Check data - _result = [x for x in result[1]] - self.assertEqual(len(expected['data']), len(_result)) - for res, exp in zip(_result, expected['data']): - self.assertEqual(len(exp), len(res)) - self.assertEqual(exp, res) - - def _test_list_security_group_rules_extend_sg_name( - self, expected_mode=None, args=(), conv=True, query_field=False): - if query_field: - field_filters = ['id', 'security_group_id', - 'remote_ip_prefix', 'remote_group_id'] - else: - field_filters = None - - data = [self._prepare_rule(rule_id='ruleid1', sg_id='myid1', - remote_group_id='myid1', - filters=field_filters), - self._prepare_rule(rule_id='ruleid2', sg_id='myid2', - remote_group_id='myid3', - filters=field_filters), - self._prepare_rule(rule_id='ruleid3', sg_id='myid2', - remote_group_id='myid2', - filters=field_filters), - ] - - if expected_mode == 'noconv': - expected = {'cols': ['id', 'security_group_id', 'remote_group_id'], - 'data': [('ruleid1', 'myid1', 'myid1'), - ('ruleid2', 'myid2', 'myid3'), - ('ruleid3', 'myid2', 'myid2')]} - elif expected_mode == 'remote_group_id': - expected = {'cols': ['id', 'security_group', 'remote_group'], - 'data': [('ruleid1', 'group1', 'group1'), - ('ruleid2', 'group2', 'group3'), - ('ruleid3', 'group2', 'group2')]} - else: - expected = {'cols': ['id', 'security_group', 'remote'], - 'data': [('ruleid1', 'group1', 'group1 (group)'), - ('ruleid2', 'group2', 'group3 (group)'), - ('ruleid3', 'group2', 'group2 (group)')]} - - self._test_list_security_group_rules_extend( - data, expected, args=args, conv=conv, query_fields=field_filters) - - def test_list_security_group_rules_extend_remote_sg_name(self): - args = '-c id -c security_group -c remote'.split() - self._test_list_security_group_rules_extend_sg_name(args=args) - - def test_list_security_group_rules_extend_sg_name_noconv(self): - args = '--no-nameconv -c id -c security_group_id -c remote_group_id' - args = args.split() - self._test_list_security_group_rules_extend_sg_name( - expected_mode='noconv', args=args, conv=False) - - def test_list_security_group_rules_extend_sg_name_with_columns(self): - args = '-c id -c security_group_id -c remote_group_id'.split() - self._test_list_security_group_rules_extend_sg_name( - expected_mode='remote_group_id', args=args) - - def test_list_security_group_rules_extend_sg_name_with_columns_no_id(self): - args = '-c id -c security_group -c remote_group'.split() - self._test_list_security_group_rules_extend_sg_name( - expected_mode='remote_group_id', args=args) - - def test_list_security_group_rules_extend_sg_name_with_fields(self): - # NOTE: remote_ip_prefix is required to show "remote" column - args = ('-F id -F security_group_id ' - '-F remote_ip_prefix -F remote_group_id').split() - self._test_list_security_group_rules_extend_sg_name( - args=args, query_field=True) - - def test_list_security_group_rules_extend_sg_name_with_fields_no_id(self): - # NOTE: remote_ip_prefix is required to show "remote" column - args = ('-F id -F security_group ' - '-F remote_ip_prefix -F remote_group').split() - self._test_list_security_group_rules_extend_sg_name(args=args, - query_field=True) - - def test_list_security_group_rules_extend_remote(self): - args = '-c id -c security_group -c remote'.split() - - data = [self._prepare_rule(rule_id='ruleid1', sg_id='myid1', - remote_ip_prefix='172.16.18.0/24'), - self._prepare_rule(rule_id='ruleid2', sg_id='myid2', - remote_ip_prefix='172.16.20.0/24'), - self._prepare_rule(rule_id='ruleid3', sg_id='myid2', - remote_group_id='myid3')] - expected = {'cols': ['id', 'security_group', 'remote'], - 'data': [('ruleid1', 'group1', '172.16.18.0/24 (CIDR)'), - ('ruleid2', 'group2', '172.16.20.0/24 (CIDR)'), - ('ruleid3', 'group2', 'group3 (group)')]} - self._test_list_security_group_rules_extend(data, expected, args) - - def test_list_security_group_rules_extend_proto_port(self): - data = [self._prepare_rule(rule_id='ruleid1', sg_id='myid1', - protocol='tcp', - port_range_min=22, port_range_max=22), - self._prepare_rule(rule_id='ruleid2', sg_id='myid2', - direction='egress', ethertype='IPv6', - protocol='udp', - port_range_min=80, port_range_max=81), - self._prepare_rule(rule_id='ruleid3', sg_id='myid2', - protocol='icmp', - remote_ip_prefix='10.2.0.0/16')] - expected = { - 'cols': ['id', 'security_group', 'direction', 'ethertype', - 'port/protocol', 'remote'], - 'data': [ - ('ruleid1', 'group1', 'ingress', 'IPv4', '22/tcp', 'any'), - ('ruleid2', 'group2', 'egress', 'IPv6', '80-81/udp', 'any'), - ('ruleid3', 'group2', 'ingress', 'IPv4', 'icmp', - '10.2.0.0/16 (CIDR)') - ]} - self._test_list_security_group_rules_extend(data, expected) - - def _prepare_rule(self, rule_id=None, sg_id=None, tenant_id=None, - direction=None, ethertype=None, - protocol=None, port_range_min=None, port_range_max=None, - remote_ip_prefix=None, remote_group_id=None, - filters=None): - rule = {'id': rule_id or uuidutils.generate_uuid(), - 'tenant_id': tenant_id or uuidutils.generate_uuid(), - 'security_group_id': sg_id or uuidutils.generate_uuid(), - 'direction': direction or 'ingress', - 'ethertype': ethertype or 'IPv4', - 'protocol': protocol, - 'port_range_min': port_range_min, - 'port_range_max': port_range_max, - 'remote_ip_prefix': remote_ip_prefix, - 'remote_group_id': remote_group_id} - if filters: - return dict([(k, v) for k, v in rule.items() if k in filters]) - else: - return rule - - def test__get_remote_both_unspecified(self): - sg_rule = self._prepare_rule(remote_ip_prefix=None, - remote_group_id=None) - self.assertIsNone(securitygroup._get_remote(sg_rule)) - - def test__get_remote_remote_ip_prefix_specified(self): - sg_rule = self._prepare_rule(remote_ip_prefix='172.16.18.0/24') - self.assertEqual('172.16.18.0/24 (CIDR)', - securitygroup._get_remote(sg_rule)) - - def test__get_remote_remote_group_specified(self): - sg_rule = self._prepare_rule(remote_group_id='sg_id1') - self.assertEqual('sg_id1 (group)', securitygroup._get_remote(sg_rule)) - - def test__get_protocol_port_all_none(self): - sg_rule = self._prepare_rule() - self.assertIsNone(securitygroup._get_protocol_port(sg_rule)) - - def test__get_protocol_port_tcp_all_port(self): - sg_rule = self._prepare_rule(protocol='tcp') - self.assertEqual('tcp', securitygroup._get_protocol_port(sg_rule)) - - def test__get_protocol_port_tcp_one_port(self): - sg_rule = self._prepare_rule(protocol='tcp', - port_range_min=22, port_range_max=22) - self.assertEqual('22/tcp', securitygroup._get_protocol_port(sg_rule)) - - def test__get_protocol_port_tcp_port_range(self): - sg_rule = self._prepare_rule(protocol='tcp', - port_range_min=5000, port_range_max=5010) - self.assertEqual('5000-5010/tcp', - securitygroup._get_protocol_port(sg_rule)) - - def test__get_protocol_port_udp_all_port(self): - sg_rule = self._prepare_rule(protocol='udp') - self.assertEqual('udp', securitygroup._get_protocol_port(sg_rule)) - - def test__get_protocol_port_udp_one_port(self): - sg_rule = self._prepare_rule(protocol='udp', - port_range_min=22, port_range_max=22) - self.assertEqual('22/udp', securitygroup._get_protocol_port(sg_rule)) - - def test__get_protocol_port_udp_port_range(self): - sg_rule = self._prepare_rule(protocol='udp', - port_range_min=5000, port_range_max=5010) - self.assertEqual('5000-5010/udp', - securitygroup._get_protocol_port(sg_rule)) - - def test__get_protocol_port_icmp_all(self): - sg_rule = self._prepare_rule(protocol='icmp') - self.assertEqual('icmp', securitygroup._get_protocol_port(sg_rule)) - - def test_get_ethertype_for_protocol_icmpv6(self): - self.assertEqual('IPv6', - securitygroup.generate_default_ethertype('icmpv6')) - - def test_get_ethertype_for_protocol_icmp(self): - self.assertEqual('IPv4', - securitygroup.generate_default_ethertype('icmp')) - - def test__get_protocol_port_udp_code_type(self): - sg_rule = self._prepare_rule(protocol='icmp', - port_range_min=1, port_range_max=8) - self.assertEqual('icmp (type:1, code:8)', - securitygroup._get_protocol_port(sg_rule)) - - def test__format_sg_rules(self): - rules = [self._prepare_rule(), - self._prepare_rule(protocol='tcp', port_range_min=80, - port_range_max=80), - self._prepare_rule(remote_ip_prefix='192.168.1.0/24'), - self._prepare_rule(remote_group_id='group1'), - self._prepare_rule(protocol='tcp', - remote_ip_prefix='10.1.1.0/24'), - self._prepare_rule(direction='egress'), - self._prepare_rule(direction='egress', ethertype='IPv6'), - ] - sg = {'security_group_rules': rules} - expected_data = ['ingress, IPv4', - 'ingress, IPv4, 80/tcp', - 'ingress, IPv4, remote_ip_prefix: 192.168.1.0/24', - 'ingress, IPv4, remote_group_id: group1', - 'ingress, IPv4, tcp, remote_ip_prefix: 10.1.1.0/24', - 'egress, IPv4', - 'egress, IPv6', - ] - expected = '\n'.join(sorted(expected_data)) - self.assertEqual(expected, securitygroup._format_sg_rules(sg)) diff --git a/neutronclient/tests/unit/test_cli20_servicetype.py b/neutronclient/tests/unit/test_cli20_servicetype.py deleted file mode 100644 index ec9a663fa..000000000 --- a/neutronclient/tests/unit/test_cli20_servicetype.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# 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 sys - -from neutronclient.neutron.v2_0 import servicetype -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20ServiceProvidersJSON(test_cli20.CLITestV20Base): - id_field = "name" - - def setUp(self): - super(CLITestV20ServiceProvidersJSON, self).setUp( - plurals={'tags': 'tag'} - ) - - def test_list_service_providers(self): - resources = "service_providers" - cmd = servicetype.ListServiceProvider(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_service_providers_pagination(self): - resources = "service_providers" - cmd = servicetype.ListServiceProvider(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_service_providers_sort(self): - resources = "service_providers" - cmd = servicetype.ListServiceProvider(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name"], - sort_dir=["asc", "desc"]) - - def test_list_service_providers_limit(self): - resources = "service_providers" - cmd = servicetype.ListServiceProvider(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) diff --git a/neutronclient/tests/unit/test_cli20_subnet.py b/neutronclient/tests/unit/test_cli20_subnet.py deleted file mode 100644 index 97c2faff0..000000000 --- a/neutronclient/tests/unit/test_cli20_subnet.py +++ /dev/null @@ -1,687 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.common import exceptions -from neutronclient.neutron import v2_0 as neutronV20 -from neutronclient.neutron.v2_0 import subnet -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20SubnetJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['subnet'] - - def setUp(self): - super(CLITestV20SubnetJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_subnet(self): - # Create subnet: --gateway gateway netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = '10.10.10.0/24' - gateway = 'gatewayvalue' - args = ['--gateway', gateway, netid, cidr, '--description', 'cave'] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, gateway] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - description='cave') - - def test_create_subnet_network_cidr_seperated(self): - # For positional value, network_id and cidr can be separated. - # Create subnet: --gateway gateway netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = '10.10.10.0/24' - gateway = 'gatewayvalue' - args = [netid, '--gateway', gateway, cidr] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, gateway] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_subnet_with_no_gateway(self): - # Create subnet: --no-gateway netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - args = ['--no-gateway', netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, None] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_subnet_with_segment(self): - # Create subnet: --segment segment netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = '10.10.10.0/24' - segment = 'segment' - args = ['--segment', segment, netid, cidr, - '--description', 'cave'] - position_names = ['ip_version', 'network_id', 'cidr', 'segment_id'] - position_values = [4, netid, cidr, segment] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - description='cave') - - def test_create_subnet_with_bad_gateway_option(self): - # Create sbunet: --no-gateway netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - gateway = 'gatewayvalue' - args = ['--gateway', gateway, '--no-gateway', netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, None] - self.assertRaises( - SystemExit, self._test_create_resource, - resource, cmd, name, myid, args, position_names, position_values) - - def _test_create_resource_and_catch_command_error(self, should_fail, - *args): - if should_fail: - params = {'no_api_call': True, - 'expected_exception': exceptions.CommandError} - else: - params = {} - self._test_create_resource(*args, **params) - - def test_create_subnet_with_enable_and_disable_dhcp(self): - # Create subnet: --enable-dhcp and --disable-dhcp. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - position_names = ['ip_version', 'network_id', 'cidr', 'enable_dhcp'] - # enable_dhcp value is appended later inside the loop - position_values = [4, netid, cidr] - for enable_dhcp_arg, should_fail in ( - ('--enable-dhcp=False', False), - ('--enable-dhcp=True', True), - ('--enable-dhcp', True) - ): - tested_args = [enable_dhcp_arg, '--disable-dhcp'] - args = tested_args + [netid, cidr] - pos_values = position_values + [should_fail] - self._test_create_resource_and_catch_command_error( - should_fail, - resource, cmd, name, myid, args, position_names, pos_values) - - def test_create_subnet_with_multiple_enable_dhcp(self): - # Create subnet with multiple --enable-dhcp arguments passed. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - position_names = ['ip_version', 'network_id', 'cidr', 'enable_dhcp'] - # enable_dhcp value is appended later inside the loop - position_values = [4, netid, cidr] - - _ = 'UNUSED_MARKER' - for tested_args, should_fail, pos_value in ( - (['--enable-dhcp', '--enable-dhcp=True'], False, True), - (['--enable-dhcp', '--enable-dhcp=False'], True, _), - (['--enable-dhcp=False', '--enable-dhcp'], True, _), - (['--enable-dhcp=True', '--enable-dhcp=False'], True, _), - (['--enable-dhcp=False', '--enable-dhcp=True'], True, _) - ): - args = tested_args + [netid, cidr] - pos_values = position_values + [pos_value] - self._test_create_resource_and_catch_command_error( - should_fail, - resource, cmd, name, myid, args, position_names, pos_values) - - def test_create_subnet_tenant(self): - # Create subnet: --tenant_id tenantid netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr'] - position_values = [4, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_tags(self): - # Create subnet: netid cidr --tags a b. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = [netid, cidr, '--tags', 'a', 'b'] - position_names = ['ip_version', 'network_id', 'cidr'] - position_values = [4, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tags=['a', 'b']) - - def test_create_subnet_allocation_pool(self): - # Create subnet: --tenant_id tenantid netid cidr. - # The is --allocation_pool start=1.1.1.10,end=1.1.1.20 - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--allocation_pool', 'start=1.1.1.10,end=1.1.1.20', - netid, cidr] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pool = [{'start': '1.1.1.10', 'end': '1.1.1.20'}] - position_values = [4, pool, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_allocation_pools(self): - # Create subnet: --tenant-id tenantid netid cidr. - # The are --allocation_pool start=1.1.1.10,end=1.1.1.20 and - # --allocation_pool start=1.1.1.30,end=1.1.1.40 - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--allocation_pool', 'start=1.1.1.10,end=1.1.1.20', - '--allocation_pool', 'start=1.1.1.30,end=1.1.1.40', - netid, cidr] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pools = [{'start': '1.1.1.10', 'end': '1.1.1.20'}, - {'start': '1.1.1.30', 'end': '1.1.1.40'}] - position_values = [4, pools, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_host_route(self): - # Create subnet: --tenant_id tenantid netid cidr. - # The is - # --host-route destination=172.16.1.0/24,nexthop=1.1.1.20 - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--host-route', 'destination=172.16.1.0/24,nexthop=1.1.1.20', - netid, cidr] - position_names = ['ip_version', 'host_routes', 'network_id', - 'cidr'] - route = [{'destination': '172.16.1.0/24', 'nexthop': '1.1.1.20'}] - position_values = [4, route, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_host_routes(self): - # Create subnet: --tenant-id tenantid netid cidr. - # The are - # --host-route destination=172.16.1.0/24,nexthop=1.1.1.20 and - # --host-route destination=172.17.7.0/24,nexthop=1.1.1.40 - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--host-route', 'destination=172.16.1.0/24,nexthop=1.1.1.20', - '--host-route', 'destination=172.17.7.0/24,nexthop=1.1.1.40', - netid, cidr] - position_names = ['ip_version', 'host_routes', 'network_id', - 'cidr'] - routes = [{'destination': '172.16.1.0/24', 'nexthop': '1.1.1.20'}, - {'destination': '172.17.7.0/24', 'nexthop': '1.1.1.40'}] - position_values = [4, routes, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_dns_nameservers(self): - # Create subnet: --tenant-id tenantid netid cidr. - # The are - # --dns-nameserver 1.1.1.20 and --dns-nameserver 1.1.1.40 - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--dns-nameserver', '1.1.1.20', - '--dns-nameserver', '1.1.1.40', - netid, cidr] - position_names = ['ip_version', 'dns_nameservers', 'network_id', - 'cidr'] - nameservers = ['1.1.1.20', '1.1.1.40'] - position_values = [4, nameservers, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_use_default_subnetpool(self): - # Create subnet: --tenant-id tenantid --use-default-subnetpool \ - # netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--use-default-subnetpool', - netid, cidr] - position_names = ['ip_version', 'use_default_subnetpool', 'network_id', - 'cidr'] - position_values = [4, True, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_disable_dhcp(self): - # Create subnet: --tenant-id tenantid --disable-dhcp netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--disable-dhcp', - netid, cidr] - position_names = ['ip_version', 'enable_dhcp', 'network_id', - 'cidr'] - position_values = [4, False, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_merge_single_plurar(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--allocation-pool', 'start=1.1.1.10,end=1.1.1.20', - netid, cidr, - '--allocation-pools', 'list=true', 'type=dict', - 'start=1.1.1.30,end=1.1.1.40'] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pools = [{'start': '1.1.1.10', 'end': '1.1.1.20'}, - {'start': '1.1.1.30', 'end': '1.1.1.40'}] - position_values = [4, pools, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_merge_plurar(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - netid, cidr, - '--allocation-pools', 'list=true', 'type=dict', - 'start=1.1.1.30,end=1.1.1.40'] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pools = [{'start': '1.1.1.30', 'end': '1.1.1.40'}] - position_values = [4, pools, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_merge_single_single(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--allocation-pool', 'start=1.1.1.10,end=1.1.1.20', - netid, cidr, - '--allocation-pool', - 'start=1.1.1.30,end=1.1.1.40'] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pools = [{'start': '1.1.1.10', 'end': '1.1.1.20'}, - {'start': '1.1.1.30', 'end': '1.1.1.40'}] - position_values = [4, pools, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_max_v4_cidr(self): - # Create subnet: --gateway gateway netid cidr. - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = '192.168.0.1/32' - gateway = 'gatewayvalue' - args = ['--gateway', gateway, netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, gateway] - with mock.patch.object(cmd.log, 'warning') as mock_warning: - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - mock_warning.assert_called_once_with(mock.ANY, - {'ip': 4, 'cidr': '/32'}) - - def test_create_subnet_with_ipv6_ra_mode(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '6', - '--ipv6-ra-mode', 'dhcpv6-stateful', - netid, cidr] - position_names = ['ip_version', 'ipv6_ra_mode', - 'network_id', 'cidr'] - position_values = [6, 'dhcpv6-stateful', netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_ipv6_address_mode(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '6', - '--ipv6-address-mode', 'dhcpv6-stateful', - netid, cidr] - position_names = ['ip_version', 'ipv6_address_mode', - 'network_id', 'cidr'] - position_values = [6, 'dhcpv6-stateful', netid, cidr] - - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_ipv6_modes(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '6', - '--ipv6-address-mode', 'slaac', - '--ipv6-ra-mode', 'slaac', - netid, cidr] - position_names = ['ip_version', 'ipv6_address_mode', - 'ipv6_ra_mode', 'network_id', 'cidr'] - position_values = [6, 'slaac', 'slaac', netid, cidr] - - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_ipv6_ra_mode_ipv4(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '4', - '--ipv6-ra-mode', 'slaac', - netid, cidr] - position_names = ['ip_version', 'ipv6_ra_mode', - 'network_id', 'cidr'] - position_values = [4, None, netid, cidr] - self._test_create_resource( - resource, cmd, name, myid, args, position_names, - position_values, tenant_id='tenantid', - no_api_call=True, expected_exception=exceptions.CommandError) - - def test_create_subnet_with_ipv6_address_mode_ipv4(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '4', - '--ipv6-address-mode', 'slaac', - netid, cidr] - position_names = ['ip_version', 'ipv6_address_mode', - 'network_id', 'cidr'] - position_values = [4, None, netid, cidr] - self._test_create_resource( - resource, cmd, name, myid, args, position_names, - position_values, tenant_id='tenantid', - no_api_call=True, expected_exception=exceptions.CommandError) - - @mock.patch.object(neutronV20, 'find_resource_by_name_or_id') - def test_create_subnet_with_subnetpool_ipv6_and_ip_ver_ignored( - self, mock_find_resource): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--tenant_id', 'tenantid', - '--ip-version', '4', - '--subnetpool', 'subnetpool_id', - netid] - position_names = ['ip_version', 'network_id', 'subnetpool_id'] - position_values = [6, netid, 'subnetpool_id'] - mock_find_resource.return_value = { - 'id': 'subnetpool_id', 'ip_version': 6} - self._test_create_resource( - resource, cmd, name, myid, args, position_names, - position_values, tenant_id='tenantid') - mock_find_resource.assert_called_once_with( - self.client, 'subnetpool', 'subnetpool_id') - - @mock.patch.object(neutronV20, 'find_resource_by_name_or_id') - def test_create_subnet_with_subnetpool_ipv4_with_cidr_wildcard( - self, mock_find_resource): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrwildcard' - args = ['--tenant_id', 'tenantid', - '--ip-version', '4', - '--ipv6-address-mode', 'slaac', - '--subnetpool', 'subnetpool_id', - netid, cidr] - position_names = ['ip_version', 'ipv6_address_mode', - 'network_id', 'subnetpool_id', 'cidr'] - position_values = [4, None, netid, 'subnetpool_id', cidr] - mock_find_resource.return_value = {'id': 'subnetpool_id', - 'ip_version': 4} - self._test_create_resource( - resource, cmd, name, myid, args, position_names, - position_values, tenant_id='tenantid', - no_api_call=True, expected_exception=exceptions.CommandError) - mock_find_resource.assert_called_once_with( - self.client, 'subnetpool', 'subnetpool_id') - - @mock.patch.object(neutronV20, 'find_resource_by_name_or_id') - def test_create_subnet_with_subnetpool_ipv4_with_prefixlen( - self, mock_find_resource): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--tenant_id', 'tenantid', - '--ip-version', '4', - '--ipv6-address-mode', 'slaac', - '--subnetpool', 'subnetpool_id', - '--prefixlen', '31', - netid] - position_names = ['ip_version', 'ipv6_address_mode', - 'network_id', 'subnetpool_id'] - position_values = [4, None, netid, 'subnetpool_id'] - mock_find_resource.return_value = {'id': 'subnetpool_id', - 'ip_version': 4} - self._test_create_resource( - resource, cmd, name, myid, args, position_names, - position_values, tenant_id='tenantid', - no_api_call=True, expected_exception=exceptions.CommandError) - mock_find_resource.assert_called_once_with( - self.client, 'subnetpool', 'subnetpool_id') - - def test_list_subnets_detail(self): - # List subnets: -D. - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_subnets_tags(self): - # List subnets: -- --tags a b. - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, tags=['a', 'b']) - - def test_list_subnets_detail_tags(self): - # List subnets: -D -- --tags a b. - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, detail=True, tags=['a', 'b']) - - def test_list_subnets_fields(self): - # List subnets: --fields a --fields b -- --fields c d. - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - fields_1=['a', 'b'], fields_2=['c', 'd']) - - def test_list_subnets_pagination(self): - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_subnets_sort(self): - # List subnets: --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_subnets_limit(self): - # List subnets: -P. - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_update_subnet(self): - # Update subnet: myid --name myname --tags a b. - resource = 'subnet' - cmd = subnet.UpdateSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--description', 'cavern', - '--tags', 'a', 'b'], - {'name': 'myname', 'tags': ['a', 'b'], - 'description': 'cavern'}) - - def test_update_subnet_allocation_pools(self): - # Update subnet: myid --name myname --tags a b. - resource = 'subnet' - cmd = subnet.UpdateSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--allocation-pool', - 'start=1.2.0.2,end=1.2.0.127'], - {'allocation_pools': [{'start': '1.2.0.2', - 'end': '1.2.0.127'}]} - ) - - def test_update_subnet_enable_disable_dhcp(self): - # Update sbunet: --enable-dhcp and --disable-dhcp. - resource = 'subnet' - cmd = subnet.UpdateSubnet(test_cli20.MyApp(sys.stdout), None) - self.assertRaises(exceptions.CommandError, - self._test_update_resource, - resource, cmd, 'myid', - ['myid', '--name', 'myname', '--enable-dhcp', - '--disable-dhcp'], {'name': 'myname', }) - - def test_show_subnet(self): - # Show subnet: --fields id --fields name myid. - resource = 'subnet' - cmd = subnet.ShowSubnet(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_delete_subnet(self): - # Delete subnet: subnetid. - resource = 'subnet' - cmd = subnet.DeleteSubnet(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) diff --git a/neutronclient/tests/unit/test_cli20_subnetpool.py b/neutronclient/tests/unit/test_cli20_subnetpool.py deleted file mode 100644 index fb201683a..000000000 --- a/neutronclient/tests/unit/test_cli20_subnetpool.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright 2015 OpenStack Foundation. -# All Rights Reserved -# -# 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 sys -from unittest import mock - - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import subnetpool -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20SubnetPoolJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['subnetpool'] - - def setUp(self): - super(CLITestV20SubnetPoolJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_subnetpool_with_options(self): - # Create subnetpool: myname. - resource = 'subnetpool' - cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - min_prefixlen = 30 - prefix1 = '10.11.12.0/24' - prefix2 = '12.11.13.0/24' - args = [name, '--min-prefixlen', str(min_prefixlen), - '--pool-prefix', prefix1, '--pool-prefix', prefix2, - '--shared', '--description', 'public pool', - '--tenant-id', 'tenantid'] - position_names = ['name', 'min_prefixlen', 'prefixes', 'shared', - 'tenant_id'] - position_values = [name, min_prefixlen, [prefix1, prefix2], True, - 'tenantid'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - description='public pool') - - def test_create_subnetpool_only_with_required_options(self): - # Create subnetpool: myname. - resource = 'subnetpool' - cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - min_prefixlen = 30 - prefix1 = '10.11.12.0/24' - prefix2 = '12.11.13.0/24' - args = [name, '--min-prefixlen', str(min_prefixlen), - '--pool-prefix', prefix1, '--pool-prefix', prefix2] - position_names = ['name', 'min_prefixlen', 'prefixes'] - position_values = [name, min_prefixlen, [prefix1, prefix2]] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_subnetpool_with_is_default(self, default='false'): - # Create subnetpool: myname. - resource = 'subnetpool' - cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - min_prefixlen = 30 - prefix1 = '10.11.12.0/24' - prefix2 = '12.11.13.0/24' - args = [name, '--min-prefixlen', str(min_prefixlen), - '--pool-prefix', prefix1, '--pool-prefix', prefix2, - '--is-default', default] - position_names = ['name', 'min_prefixlen', 'prefixes', 'is_default'] - position_values = [name, min_prefixlen, [prefix1, prefix2], default] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_subnetpool_default(self): - self.test_create_subnetpool_with_is_default(default='true') - - def test_create_subnetpool_with_unicode(self): - # Create subnetpool: u'\u7f51\u7edc'. - resource = 'subnetpool' - cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None) - name = u'\u7f51\u7edc' - myid = 'myid' - min_prefixlen = 30 - prefixes = '10.11.12.0/24' - args = [name, '--min-prefixlen', str(min_prefixlen), - '--pool-prefix', prefixes] - position_names = ['name', 'min_prefixlen', 'prefixes'] - position_values = [name, min_prefixlen, [prefixes]] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_subnetpool_with_addrscope(self): - # Create subnetpool: myname in addrscope: foo-address-scope - resource = 'subnetpool' - cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - min_prefixlen = 30 - prefix1 = '11.11.11.0/24' - prefix2 = '12.12.12.0/24' - address_scope = 'foo-address-scope' - args = [name, '--min-prefixlen', str(min_prefixlen), - '--pool-prefix', prefix1, '--pool-prefix', prefix2, - '--address-scope', address_scope] - position_names = ['name', 'min_prefixlen', 'prefixes', - 'address_scope_id'] - position_values = [name, min_prefixlen, [prefix1, prefix2], - address_scope] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_subnetpool_no_poolprefix(self): - # Should raise an error because --pool-prefix is required - resource = 'subnetpool' - cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = [name] - position_names = ['name'] - position_values = [name] - self.assertRaises(SystemExit, self._test_create_resource, resource, - cmd, name, myid, args, position_names, - position_values) - - @mock.patch.object(subnetpool.ListSubnetPool, "extend_list") - def test_list_subnetpool_pagination(self, mock_extend_list): - cmd = subnetpool.ListSubnetPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination("subnetpools", cmd) - mock_extend_list.assert_called_once_with(test_cli20.IsA(list), - mock.ANY) - - def test_list_subnetpools_sort(self): - # List subnetpools: - # --sort-key name --sort-key id --sort-key asc --sort-key desc - resources = "subnetpools" - cmd = subnetpool.ListSubnetPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_subnetpools_limit(self): - # List subnetpools: -P. - resources = "subnetpools" - cmd = subnetpool.ListSubnetPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_update_subnetpool_exception(self): - # Update subnetpool: myid. - resource = 'subnetpool' - cmd = subnetpool.UpdateSubnetPool(test_cli20.MyApp(sys.stdout), None) - self.assertRaises(exceptions.CommandError, self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - - def test_update_subnetpool(self): - # Update subnetpool: myid --name myname. - resource = 'subnetpool' - cmd = subnetpool.UpdateSubnetPool(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--description', ':)'], - {'name': 'myname', 'description': ':)'}) - - def test_update_subnetpool_with_address_scope(self): - # Update subnetpool: myid --address-scope newscope. - resource = 'subnetpool' - cmd = subnetpool.UpdateSubnetPool(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--address-scope', 'newscope'], - {'address_scope_id': 'newscope'} - ) - - def test_update_subnetpool_with_no_address_scope(self): - # Update subnetpool: myid --no-address-scope. - resource = 'subnetpool' - cmd = subnetpool.UpdateSubnetPool(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--no-address-scope'], - {'address_scope_id': None} - ) - - def test_show_subnetpool(self): - # Show subnetpool: --fields id --fields name myid. - resource = 'subnetpool' - cmd = subnetpool.ShowSubnetPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_delete_subnetpool(self): - # Delete subnetpool: subnetpoolid. - resource = 'subnetpool' - cmd = subnetpool.DeleteSubnetPool(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) diff --git a/neutronclient/tests/unit/test_cli20_tag.py b/neutronclient/tests/unit/test_cli20_tag.py deleted file mode 100644 index 2e23c9dc5..000000000 --- a/neutronclient/tests/unit/test_cli20_tag.py +++ /dev/null @@ -1,131 +0,0 @@ -# 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 sys -from unittest import mock - - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import network -from neutronclient.neutron.v2_0 import tag -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Tag(test_cli20.CLITestV20Base): - def _test_tag_operation(self, cmd, path, method, args, prog_name, - body=None): - with mock.patch.object(cmd, 'get_client', - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, 'request', - return_value=(test_cli20.MyResp(204), None) - ) as mock_request: - if body: - body = test_cli20.MyComparator(body, self.client) - cmd_parser = cmd.get_parser(prog_name) - shell.run_command(cmd, cmd_parser, args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator(test_cli20.end_url(path), self.client), - method, body=body, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - def _test_tags_query(self, cmd, resources, args, query): - path = getattr(self.client, resources + "_path") - res = {resources: [{'id': 'myid'}]} - resstr = self.client.serialize(res) - with mock.patch.object(cmd, 'get_client', - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, 'request', - return_value=(test_cli20.MyResp(200), resstr) - ) as mock_request: - cmd_parser = cmd.get_parser("list_networks") - shell.run_command(cmd, cmd_parser, args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator(test_cli20.end_url(path, query), - self.client), - 'GET', body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - _str = self.fake_stdout.make_string() - self.assertIn('myid', _str) - - def _make_tag_path(self, resource, resource_id, tag): - path = getattr(self.client, "tag_path") - resource_plural = self.client.get_resource_plural(resource) - return path % (resource_plural, resource_id, tag) - - def _make_tags_path(self, resource, resource_id): - path = getattr(self.client, "tags_path") - resource_plural = self.client.get_resource_plural(resource) - return path % (resource_plural, resource_id) - - def test_add_tag(self): - cmd = tag.AddTag(test_cli20.MyApp(sys.stdout), None) - path = self._make_tag_path('network', 'myid', 'red') - args = ['--resource-type', 'network', '--resource', 'myid', - '--tag', 'red'] - self._test_tag_operation(cmd, path, 'PUT', args, "tag-add") - - def test_add_tag_empty_tag(self): - cmd = tag.AddTag(test_cli20.MyApp(sys.stdout), None) - path = self._make_tag_path('network', 'myid', '') - args = ['--resource-type', 'network', '--resource', 'myid', - '--tag', ''] - self.assertRaises(exceptions.CommandError, self._test_tag_operation, - cmd, path, 'PUT', args, "tag-add") - - def test_replace_tag(self): - cmd = tag.ReplaceTag(test_cli20.MyApp(sys.stdout), None) - path = self._make_tags_path('network', 'myid') - args = ['--resource-type', 'network', '--resource', 'myid', - '--tag', 'red', '--tag', 'blue'] - body = {'tags': ['red', 'blue']} - self._test_tag_operation(cmd, path, 'PUT', args, "tag-replace", - body=body) - - def test_remove_tag(self): - cmd = tag.RemoveTag(test_cli20.MyApp(sys.stdout), None) - path = self._make_tag_path('network', 'myid', 'red') - args = ['--resource-type', 'network', '--resource', 'myid', - '--tag', 'red'] - self._test_tag_operation(cmd, path, 'DELETE', args, "tag-remove") - - def test_remove_tag_all(self): - cmd = tag.RemoveTag(test_cli20.MyApp(sys.stdout), None) - path = self._make_tags_path('network', 'myid') - args = ['--resource-type', 'network', '--resource', 'myid', - '--all'] - self._test_tag_operation(cmd, path, 'DELETE', args, "tag-remove") - - def test_no_tag_nor_all(self): - cmd = tag.RemoveTag(test_cli20.MyApp(sys.stdout), None) - path = self._make_tags_path('network', 'myid') - args = ['--resource-type', 'network', '--resource', 'myid'] - self.assertRaises(exceptions.CommandError, self._test_tag_operation, - cmd, path, 'DELETE', args, "tag-remove") - - def test_tags_query(self): - # This test examines that '-' in the tag related filters - # is not converted to '_'. - resources = 'networks' - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - with mock.patch.object(network.ListNetwork, 'extend_list'): - args = ['--not-tags', 'red,blue', '--tags-any', 'green', - '--not-tags-any', 'black'] - query = "not-tags=red,blue&tags-any=green¬-tags-any=black" - self._test_tags_query(cmd, resources, args, query) diff --git a/neutronclient/tests/unit/test_client_extension.py b/neutronclient/tests/unit/test_client_extension.py deleted file mode 100644 index 871e7a6cb..000000000 --- a/neutronclient/tests/unit/test_client_extension.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright 2015 Rackspace Hosting Inc. -# All Rights Reserved -# -# 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 inspect -import sys -from unittest import mock - - -from neutronclient.common import extension -from neutronclient.neutron.v2_0.contrib import _fox_sockets as fox_sockets -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20ExtensionJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['fox_socket'] - - def setUp(self): - # need to mock before super because extensions loaded on instantiation - self._mock_extension_loading() - super(CLITestV20ExtensionJSON, self).setUp(plurals={'tags': 'tag'}) - - def _mock_extension_loading(self): - ext_pkg = 'neutronclient.common.extension' - contrib = mock.patch(ext_pkg + '._discover_via_entry_points').start() - contrib.return_value = [("_fox_sockets", fox_sockets)] - return contrib - - def test_ext_cmd_loaded(self): - neutron_shell = shell.NeutronShell('2.0') - ext_cmd = {'fox-sockets-list': fox_sockets.FoxInSocketsList, - 'fox-sockets-create': fox_sockets.FoxInSocketsCreate, - 'fox-sockets-update': fox_sockets.FoxInSocketsUpdate, - 'fox-sockets-delete': fox_sockets.FoxInSocketsDelete, - 'fox-sockets-show': fox_sockets.FoxInSocketsShow} - for cmd_name, cmd_class in ext_cmd.items(): - found = neutron_shell.command_manager.find_command([cmd_name]) - self.assertEqual(cmd_class, found[0]) - - def test_ext_cmd_help_doc_with_extension_name(self): - neutron_shell = shell.NeutronShell('2.0') - ext_cmd = {'fox-sockets-list': fox_sockets.FoxInSocketsList, - 'fox-sockets-create': fox_sockets.FoxInSocketsCreate, - 'fox-sockets-update': fox_sockets.FoxInSocketsUpdate, - 'fox-sockets-delete': fox_sockets.FoxInSocketsDelete, - 'fox-sockets-show': fox_sockets.FoxInSocketsShow} - for cmd_name, cmd_class in ext_cmd.items(): - found = neutron_shell.command_manager.find_command([cmd_name]) - found_factory = found[0] - self.assertEqual(cmd_class, found_factory) - self.assertTrue(found_factory.__doc__.startswith("[_fox_sockets]")) - - def test_delete_fox_socket(self): - # Delete fox socket: myid. - resource = 'fox_socket' - cmd = fox_sockets.FoxInSocketsDelete(test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_update_fox_socket(self): - # Update fox_socket: myid --name myname. - resource = 'fox_socket' - cmd = fox_sockets.FoxInSocketsUpdate(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname'], - {'name': 'myname'}) - - def test_create_fox_socket(self): - # Create fox_socket: myname. - resource = 'fox_socket' - cmd = fox_sockets.FoxInSocketsCreate(test_cli20.MyApp(sys.stdout), - None) - name = 'myname' - myid = 'myid' - args = [name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_fox_sockets(self): - # List fox_sockets. - resources = 'fox_sockets' - cmd = fox_sockets.FoxInSocketsList(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_fox_pagination(self): - resources = 'fox_sockets' - cmd = fox_sockets.FoxInSocketsList(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_show_fox_socket(self): - # Show fox_socket: --fields id --fields name myid. - resource = 'fox_socket' - cmd = fox_sockets.FoxInSocketsShow(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - -class CLITestV20ExtensionJSONAlternatePlurals(test_cli20.CLITestV20Base): - class IPAddress(extension.NeutronClientExtension): - resource = 'ip_address' - resource_plural = '%ses' % resource - object_path = '/%s' % resource_plural - resource_path = '/%s/%%s' % resource_plural - versions = ['2.0'] - - class IPAddressesList(extension.ClientExtensionList, IPAddress): - shell_command = 'ip-address-list' - - def setUp(self): - # need to mock before super because extensions loaded on instantiation - self._mock_extension_loading() - super(CLITestV20ExtensionJSONAlternatePlurals, self).setUp() - - def _mock_extension_loading(self): - ext_pkg = 'neutronclient.common.extension' - contrib = mock.patch(ext_pkg + '._discover_via_entry_points').start() - ip_address = mock.Mock() - ip_address.IPAddress = self.IPAddress - ip_address.IPAddressesList = self.IPAddressesList - contrib.return_value = [("ip_address", ip_address)] - return contrib - - def test_ext_cmd_loaded(self): - neutron_shell = shell.NeutronShell('2.0') - ext_cmd = {'ip-address-list': self.IPAddressesList} - for cmd_name, cmd_class in ext_cmd.items(): - found = neutron_shell.command_manager.find_command([cmd_name]) - self.assertEqual(cmd_class, found[0]) - - def test_list_ip_addresses(self): - # List ip_addresses. - resources = 'ip_addresses' - cmd = self.IPAddressesList(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - -class CLITestV20ExtensionJSONChildResource(test_cli20.CLITestV20Base): - class Child(extension.NeutronClientExtension): - parent_resource = 'parents' - child_resource = 'child' - resource = '%s_%s' % (parent_resource, child_resource) - resource_plural = '%sren' % resource - child_resource_plural = '%ren' % child_resource - object_path = '/%s/%%s/%s' % (parent_resource, child_resource_plural) - resource_path = '/%s/%%s/%s/%%s' % (parent_resource, - child_resource_plural) - versions = ['2.0'] - - class ChildrenList(extension.ClientExtensionList, Child): - shell_command = 'parent-child-list' - - class ChildShow(extension.ClientExtensionShow, Child): - shell_command = 'parent-child-show' - - class ChildUpdate(extension.ClientExtensionUpdate, Child): - shell_command = 'parent-child-update' - - class ChildDelete(extension.ClientExtensionDelete, Child): - shell_command = 'parent-child-delete' - - class ChildCreate(extension.ClientExtensionCreate, Child): - shell_command = 'parent-child-create' - - def setUp(self): - # need to mock before super because extensions loaded on instantiation - self._mock_extension_loading() - super(CLITestV20ExtensionJSONChildResource, self).setUp() - - def _mock_extension_loading(self): - ext_pkg = 'neutronclient.common.extension' - contrib = mock.patch(ext_pkg + '._discover_via_entry_points').start() - child = mock.Mock() - child.Child = self.Child - child.ChildrenList = self.ChildrenList - child.ChildShow = self.ChildShow - child.ChildUpdate = self.ChildUpdate - child.ChildDelete = self.ChildDelete - child.ChildCreate = self.ChildCreate - contrib.return_value = [("child", child)] - return contrib - - def test_ext_cmd_loaded(self): - neutron_shell = shell.NeutronShell('2.0') - ext_cmd = {'parent-child-list': self.ChildrenList, - 'parent-child-show': self.ChildShow, - 'parent-child-update': self.ChildUpdate, - 'parent-child-delete': self.ChildDelete, - 'parent-child-create': self.ChildCreate} - for cmd_name, cmd_class in ext_cmd.items(): - found = neutron_shell.command_manager.find_command([cmd_name]) - self.assertEqual(cmd_class, found[0]) - - def test_client_methods_have_parent_id_arg(self): - methods = (self.client.list_parents_children, - self.client.show_parents_child, - self.client.update_parents_child, - self.client.delete_parents_child, - self.client.create_parents_child) - for method in methods: - argspec = inspect.getfullargspec(method) - self.assertIn("parent_id", argspec.args) diff --git a/neutronclient/tests/unit/test_name_or_id.py b/neutronclient/tests/unit/test_name_or_id.py deleted file mode 100644 index a6a7b9246..000000000 --- a/neutronclient/tests/unit/test_name_or_id.py +++ /dev/null @@ -1,244 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# 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. -# - -from unittest import mock - -from oslo_utils import uuidutils -import testtools - -from neutronclient.common import exceptions -from neutronclient.neutron import v2_0 as neutronV20 -from neutronclient.tests.unit import test_cli20 -from neutronclient.v2_0 import client - - -class CLITestNameorID(testtools.TestCase): - - def setUp(self): - """Prepare the test environment.""" - super(CLITestNameorID, self).setUp() - self.endurl = test_cli20.ENDURL - self.client = client.Client(token=test_cli20.TOKEN, - endpoint_url=self.endurl) - - def test_get_id_from_id(self): - _id = uuidutils.generate_uuid() - reses = {'networks': [{'id': _id, }, ], } - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, "networks_path") - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - returned_id = neutronV20.find_resourceid_by_name_or_id( - self.client, 'network', _id) - - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&id=" + _id), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - self.assertEqual(_id, returned_id) - - def test_get_id_from_id_then_name_empty(self): - _id = uuidutils.generate_uuid() - reses = {'networks': [{'id': _id, }, ], } - resstr = self.client.serialize(reses) - resstr1 = self.client.serialize({'networks': []}) - path = getattr(self.client, "networks_path") - with mock.patch.object(self.client.httpclient, - "request") as mock_request: - mock_request.side_effect = [(test_cli20.MyResp(200), resstr1), - (test_cli20.MyResp(200), resstr)] - returned_id = neutronV20.find_resourceid_by_name_or_id( - self.client, 'network', _id) - - self.assertEqual(2, mock_request.call_count) - mock_request.assert_has_calls([ - mock.call( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&id=" + _id), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})), - mock.call( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=" + _id), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN}))]) - self.assertEqual(_id, returned_id) - - def test_get_id_from_name(self): - name = 'myname' - _id = uuidutils.generate_uuid() - reses = {'networks': [{'id': _id, }, ], } - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, "networks_path") - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - returned_id = neutronV20.find_resourceid_by_name_or_id( - self.client, 'network', name) - - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=" + name), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - self.assertEqual(_id, returned_id) - - def test_get_id_from_name_multiple(self): - name = 'myname' - reses = {'networks': [{'id': uuidutils.generate_uuid()}, - {'id': uuidutils.generate_uuid()}]} - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, "networks_path") - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - exception = self.assertRaises( - exceptions.NeutronClientNoUniqueMatch, - neutronV20.find_resourceid_by_name_or_id, - self.client, 'network', name) - - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=" + name), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - self.assertIn('Multiple', exception.message) - - def test_get_id_from_name_notfound(self): - name = 'myname' - reses = {'networks': []} - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, "networks_path") - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - exception = self.assertRaises( - exceptions.NotFound, - neutronV20.find_resourceid_by_name_or_id, - self.client, 'network', name) - - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=" + name), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - self.assertIn('Unable to find', exception.message) - self.assertEqual(404, exception.status_code) - - def test_get_id_from_name_multiple_with_project(self): - name = 'web_server' - project = uuidutils.generate_uuid() - expect_id = uuidutils.generate_uuid() - reses = {'security_groups': - [{'id': expect_id, 'tenant_id': project}]} - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, "security_groups_path") - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - observed_id = neutronV20.find_resourceid_by_name_or_id( - self.client, 'security_group', name, project) - - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=%s&tenant_id=%s" % - (name, project)), self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - self.assertEqual(expect_id, observed_id) - - def test_get_id_from_name_multiple_with_project_not_found(self): - name = 'web_server' - project = uuidutils.generate_uuid() - resstr_notfound = self.client.serialize({'security_groups': []}) - resp = (test_cli20.MyResp(200), resstr_notfound) - path = getattr(self.client, "security_groups_path") - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - exc = self.assertRaises(exceptions.NotFound, - neutronV20.find_resourceid_by_name_or_id, - self.client, 'security_group', name, - project) - - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=%s&tenant_id=%s" % - (name, project)), self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - self.assertIn('Unable to find', exc.message) - self.assertEqual(404, exc.status_code) - - def _test_get_resource_by_id(self, id_only=False): - _id = uuidutils.generate_uuid() - net = {'id': _id, 'name': 'test'} - reses = {'networks': [net], } - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, "networks_path") - if id_only: - query_params = "fields=id&id=%s" % _id - else: - query_params = "id=%s" % _id - with mock.patch.object(self.client.httpclient, "request", - return_value=resp) as mock_request: - if id_only: - returned_id = neutronV20.find_resourceid_by_id( - self.client, 'network', _id) - self.assertEqual(_id, returned_id) - else: - result = neutronV20.find_resource_by_id( - self.client, 'network', _id) - self.assertEqual(net, result) - - mock_request.assert_called_once_with( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query_params), - self.client), - 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - - def test_get_resource_by_id(self): - self._test_get_resource_by_id(id_only=False) - - def test_get_resourceid_by_id(self): - self._test_get_resource_by_id(id_only=True) diff --git a/neutronclient/tests/unit/test_quota.py b/neutronclient/tests/unit/test_quota.py deleted file mode 100644 index 747621de9..000000000 --- a/neutronclient/tests/unit/test_quota.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (C) 2013 Yahoo! Inc. -# All Rights Reserved. -# -# 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 sys -from unittest import mock - - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import quota as test_quota -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Quota(test_cli20.CLITestV20Base): - def test_show_quota(self): - resource = 'quota' - cmd = test_quota.ShowQuota( - test_cli20.MyApp(sys.stdout), None) - args = ['--tenant-id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args) - - def test_update_quota(self): - resource = 'quota' - cmd = test_quota.UpdateQuota( - test_cli20.MyApp(sys.stdout), None) - args = ['--tenant-id', self.test_id, '--network', 'test'] - self.assertRaises( - exceptions.CommandError, self._test_update_resource, - resource, cmd, self.test_id, args=args, - extrafields={'network': 'new'}) - - def test_delete_quota_get_parser(self): - cmd = test_cli20.MyApp(sys.stdout) - test_quota.DeleteQuota(cmd, None).get_parser(cmd) - - def test_show_quota_positional(self): - resource = 'quota' - cmd = test_quota.ShowQuota( - test_cli20.MyApp(sys.stdout), None) - args = [self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args) - - def test_update_quota_positional(self): - resource = 'quota' - cmd = test_quota.UpdateQuota( - test_cli20.MyApp(sys.stdout), None) - args = [self.test_id, '--network', 'test'] - self.assertRaises( - exceptions.CommandError, self._test_update_resource, - resource, cmd, self.test_id, args=args, - extrafields={'network': 'new'}) - - def test_show_quota_default(self): - resource = 'quota' - cmd = test_quota.ShowQuotaDefault( - test_cli20.MyApp(sys.stdout), None) - args = ['--tenant-id', self.test_id] - expected_res = {'quota': {'port': 50, 'network': 10, 'subnet': 10}} - resstr = self.client.serialize(expected_res) - path = getattr(self.client, "quota_default_path") - return_tup = (test_cli20.MyResp(200), resstr) - with mock.patch.object(cmd, 'get_client', - return_value=self.client) as mock_get_client, \ - mock.patch.object(self.client.httpclient, 'request', - return_value=return_tup) as mock_request: - cmd_parser = cmd.get_parser("test_" + resource) - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - - mock_get_client.assert_called_once_with() - mock_request.assert_called_once_with( - test_cli20.end_url(path % self.test_id), 'GET', - body=None, - headers=test_cli20.ContainsKeyValue( - {'X-Auth-Token': test_cli20.TOKEN})) - _str = self.fake_stdout.make_string() - self.assertIn('network', _str) - self.assertIn('subnet', _str) - self.assertIn('port', _str) - self.assertNotIn('subnetpool', _str) - - def test_update_quota_noargs(self): - resource = 'quota' - cmd = test_quota.UpdateQuota(test_cli20.MyApp(sys.stdout), None) - args = [self.test_id] - self.assertRaises(exceptions.CommandError, self._test_update_resource, - resource, cmd, self.test_id, args=args, - extrafields=None) diff --git a/neutronclient/tests/unit/test_shell.py b/neutronclient/tests/unit/test_shell.py deleted file mode 100644 index 04e814066..000000000 --- a/neutronclient/tests/unit/test_shell.py +++ /dev/null @@ -1,366 +0,0 @@ -# Copyright (C) 2013 Yahoo! Inc. -# All Rights Reserved. -# -# 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 argparse -from io import StringIO -import logging -import os -import re -import sys -from unittest import mock - -import fixtures -from keystoneauth1 import session -import testtools -from testtools import matchers - -from neutronclient.common import clientmanager -from neutronclient.neutron.v2_0 import network -from neutronclient import shell as openstack_shell - - -DEFAULT_USERNAME = 'username' -DEFAULT_PASSWORD = 'password' -DEFAULT_TENANT_ID = 'tenant_id' -DEFAULT_TENANT_NAME = 'tenant_name' -DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/' -DEFAULT_TOKEN = '3bcc3d3a03f44e3d8377f9247b0ad155' -DEFAULT_URL = 'http://quantum.example.org:9696/' -DEFAULT_REGION = 'regionOne' -DEFAULT_ENDPOINT_TYPE = 'public' -DEFAULT_API_VERSION = '2.0' -DEFAULT_SERVICE_TYPE = 'network' -DEFAULT_SERVICE_NAME = 'neutron' -DEFAULT_RETRIES = 3 -DEFAULT_TIMEOUT = 3.0 - - -class ShellTest(testtools.TestCase): - - FAKE_ENV = { - 'OS_USERNAME': DEFAULT_USERNAME, - 'OS_PASSWORD': DEFAULT_PASSWORD, - 'OS_TENANT_ID': DEFAULT_TENANT_ID, - 'OS_TENANT_NAME': DEFAULT_TENANT_NAME, - 'OS_AUTH_URL': DEFAULT_AUTH_URL, - 'OS_REGION_NAME': None, - 'HTTP_PROXY': None, - 'http_proxy': None, - } - - # Patch os.environ to avoid required auth info. - def setUp(self): - super(ShellTest, self).setUp() - for var in self.FAKE_ENV: - self.useFixture( - fixtures.EnvironmentVariable( - var, self.FAKE_ENV[var])) - - def shell(self, argstr, check=False, expected_val=0): - # expected_val is the expected return value after executing - # the command in NeutronShell - orig = (sys.stdout, sys.stderr) - clean_env = {} - _old_env, os.environ = os.environ, clean_env.copy() - try: - sys.stdout = StringIO() - sys.stderr = StringIO() - _shell = openstack_shell.NeutronShell('2.0') - _shell.run(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(expected_val, exc_value.code) - finally: - stdout = sys.stdout.getvalue() - stderr = sys.stderr.getvalue() - sys.stdout.close() - sys.stderr.close() - sys.stdout, sys.stderr = orig - os.environ = _old_env - return stdout, stderr - - def test_run_unknown_command(self): - self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) - stdout, stderr = self.shell('fake', check=True) - self.assertFalse(stdout) - self.assertIn("Unknown command ['fake']", stderr.strip()) - - def test_help(self): - required = 'usage:' - help_text, stderr = self.shell('help') - self.assertThat( - help_text, - matchers.MatchesRegex(required)) - - def test_bash_completion(self): - required = '.*os_user_domain_id.*' - bash_completion, stderr = self.shell('bash-completion') - self.assertThat( - bash_completion, - matchers.MatchesRegex(required)) - - def test_help_on_subcommand(self): - required = [ - '.*?^usage: .* quota-list'] - stdout, stderr = self.shell('help quota-list') - for r in required: - self.assertThat( - stdout, - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_help_command(self): - required = 'usage:' - help_text, stderr = self.shell('help network-create') - self.assertThat( - help_text, - matchers.MatchesRegex(required)) - - def test_bash_completion_in_outputs_of_help_command(self): - help_text, stderr = self.shell('help') - completion_cmd = "bash-completion" - completion_help_str = ("Prints all of the commands and options " - "for bash-completion.") - self.assertIn(completion_cmd, help_text) - self.assertIn(completion_help_str, help_text) - - def test_bash_completion_command(self): - # just check we have some output - required = [ - '.*--tenant_id', - '.*help', - '.*--dns-nameserver'] - help_text, stderr = self.shell('neutron bash-completion') - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_build_option_parser(self): - neutron_shell = openstack_shell.NeutronShell('2.0') - result = neutron_shell.build_option_parser('descr', '2.0') - self.assertIsInstance(result, argparse.ArgumentParser) - - @mock.patch.object(openstack_shell.NeutronShell, 'run') - def test_main_with_unicode(self, fake_shell): - unicode_text = u'\u7f51\u7edc' - argv = ['net-list', unicode_text, unicode_text] - fake_shell.return_value = 0 - ret = openstack_shell.main(argv=argv) - fake_shell.assert_called_once_with([u'net-list', unicode_text, - unicode_text]) - self.assertEqual(0, ret) - - def test_endpoint_option(self): - shell = openstack_shell.NeutronShell('2.0') - parser = shell.build_option_parser('descr', '2.0') - - # Neither $OS_ENDPOINT_TYPE nor --os-endpoint-type - namespace = parser.parse_args([]) - self.assertEqual('public', namespace.os_endpoint_type) - - # --endpoint-type but not $OS_ENDPOINT_TYPE - namespace = parser.parse_args(['--os-endpoint-type=admin']) - self.assertEqual('admin', namespace.os_endpoint_type) - - def test_endpoint_environment_variable(self): - fixture = fixtures.EnvironmentVariable("OS_ENDPOINT_TYPE", - "public") - self.useFixture(fixture) - - shell = openstack_shell.NeutronShell('2.0') - parser = shell.build_option_parser('descr', '2.0') - - # $OS_ENDPOINT_TYPE but not --endpoint-type - namespace = parser.parse_args([]) - self.assertEqual("public", namespace.os_endpoint_type) - - # --endpoint-type and $OS_ENDPOINT_TYPE - namespace = parser.parse_args(['--endpoint-type=admin']) - self.assertEqual('admin', namespace.endpoint_type) - - def test_timeout_option(self): - shell = openstack_shell.NeutronShell('2.0') - parser = shell.build_option_parser('descr', '2.0') - - # Neither $OS_ENDPOINT_TYPE nor --endpoint-type - namespace = parser.parse_args([]) - self.assertIsNone(namespace.http_timeout) - - # --endpoint-type but not $OS_ENDPOINT_TYPE - namespace = parser.parse_args(['--http-timeout=50']) - self.assertEqual(50, namespace.http_timeout) - - def test_timeout_environment_variable(self): - fixture = fixtures.EnvironmentVariable("OS_NETWORK_TIMEOUT", - "50") - self.useFixture(fixture) - - shell = openstack_shell.NeutronShell('2.0') - parser = shell.build_option_parser('descr', '2.0') - - namespace = parser.parse_args([]) - self.assertEqual(50, namespace.http_timeout) - - def test_run_incomplete_command(self): - self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) - cmd = ( - '--os-username test --os-password test --os-project-id test ' - '--os-auth-strategy keystone --os-auth-url ' - '%s port-create' % - DEFAULT_AUTH_URL) - stdout, stderr = self.shell(cmd, check=True, expected_val=2) - search_str = "Try 'neutron help port-create' for more information" - self.assertTrue(any(search_str in string for string - in stderr.split('\n'))) - - def _test_authenticate_user(self, expect_verify, expect_insecure, - **options): - base_options = {'os_cloud': None, - 'http_timeout': DEFAULT_TIMEOUT, - 'region_name': DEFAULT_REGION, - 'network_service_name': DEFAULT_SERVICE_NAME, - 'neutron_service_type': DEFAULT_SERVICE_TYPE} - - options.update(base_options) - if options.get('os_token'): - options.update({'auth_type': 'token'}) - options.update({'os_token': 'token', 'os_url': 'url'}) - else: - options.update({'os_token': None, 'os_url': None}) - - with mock.patch.object(openstack_shell.NeutronShell, - 'run_subcommand'), \ - mock.patch.object(session, 'Session') as session_mock, \ - mock.patch.object(clientmanager, 'ClientManager') as cmgr_mock: - - shell = openstack_shell.NeutronShell(DEFAULT_API_VERSION) - shell.options = mock.Mock(spec=options.keys()) - for k, v in options.items(): - setattr(shell.options, k, v) - shell.options.os_endpoint_type = DEFAULT_ENDPOINT_TYPE - shell.options.retries = DEFAULT_RETRIES - - if not (options.get('os_token') and options.get('os_url')): - auth = mock.ANY - auth_session = mock.sentinel.session - session_mock.return_value = auth_session - else: - auth = None - auth_session = None - - shell.authenticate_user() - - if not (options.get('os_token') and options.get('os_url')): - session_mock.assert_called_once_with( - auth=mock.ANY, verify=expect_verify, - cert=options.get('cert'), - timeout=DEFAULT_TIMEOUT) - else: - self.assertFalse(session_mock.called) - - cmgr_mock.assert_called_once_with( - retries=DEFAULT_RETRIES, - raise_errors=False, - session=auth_session, - url=options.get('os_url'), - token=options.get('os_token'), - region_name=DEFAULT_REGION, - api_version=DEFAULT_API_VERSION, - service_type=DEFAULT_SERVICE_TYPE, - service_name=DEFAULT_SERVICE_NAME, - endpoint_type=DEFAULT_ENDPOINT_TYPE, - auth=auth, - insecure=expect_insecure, - log_credentials=True) - - def test_authenticate_secure_with_cacert_with_cert(self): - self._test_authenticate_user( - insecure=False, cacert='cacert', cert='cert', - expect_verify='cacert', expect_insecure=False) - - def test_authenticate_secure_with_cacert_with_cert_with_token(self): - self._test_authenticate_user( - os_token='token', - insecure=False, cacert='cacert', cert='cert', - expect_verify='cacert', expect_insecure=False) - - def test_authenticate_insecure_with_cacert_with_cert(self): - self._test_authenticate_user( - insecure=True, cacert='cacert', cert='cert', - expect_verify=False, expect_insecure=True) - - def test_authenticate_insecure_with_cacert_with_cert_with_token(self): - self._test_authenticate_user( - os_token='token', - insecure=True, cacert='cacert', cert='cert', - expect_verify=False, expect_insecure=True) - - def test_authenticate_secure_without_cacert_with_cert(self): - self._test_authenticate_user( - insecure=False, cert='cert', - expect_verify=True, expect_insecure=False) - - def test_authenticate_secure_without_cacert_with_cert_with_token(self): - self._test_authenticate_user( - os_token='token', - insecure=False, cert='cert', - expect_verify=True, expect_insecure=False) - - def test_authenticate_insecure_without_cacert_with_cert(self): - self._test_authenticate_user( - insecure=True, cert='cert', - expect_verify=False, expect_insecure=True) - - def test_authenticate_insecure_without_cacert_with_cert_with_token(self): - self._test_authenticate_user( - os_token='token', - insecure=True, cert='cert', - expect_verify=False, expect_insecure=True) - - def test_authenticate_secure_with_cacert_without_cert(self): - self._test_authenticate_user( - insecure=False, cacert='cacert', - expect_verify='cacert', expect_insecure=False) - - def test_authenticate_secure_with_cacert_without_cert_with_token(self): - self._test_authenticate_user( - os_token='token', - insecure=False, cacert='cacert', - expect_verify='cacert', expect_insecure=False) - - def test_authenticate_insecure_with_cacert_without_cert(self): - self._test_authenticate_user( - insecure=True, cacert='cacert', - expect_verify=False, expect_insecure=True) - - def test_authenticate_insecure_with_cacert_without_cert_with_token(self): - self._test_authenticate_user( - os_token='token', - insecure=True, cacert='cacert', - expect_verify=False, expect_insecure=True) - - def test_commands_dict_populated(self): - # neutron.shell.COMMANDS is populated once NeutronShell is initialized. - # To check COMMANDS during NeutronShell initialization, - # reset COMMANDS to some dummy value before calling NeutronShell(). - self.useFixture(fixtures.MockPatchObject(openstack_shell, - 'COMMANDS', None)) - openstack_shell.NeutronShell('2.0') - self.assertLessEqual( - {'net-create': network.CreateNetwork, - 'net-delete': network.DeleteNetwork, - 'net-list': network.ListNetwork, - 'net-show': network.ShowNetwork, - 'net-update': network.UpdateNetwork}.items(), - openstack_shell.COMMANDS['2.0'].items()) diff --git a/neutronclient/tests/unit/vpn/__init__.py b/neutronclient/tests/unit/vpn/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/vpn/test_cli20_endpoint_group.py b/neutronclient/tests/unit/vpn/test_cli20_endpoint_group.py deleted file mode 100644 index f43da906b..000000000 --- a/neutronclient/tests/unit/vpn/test_cli20_endpoint_group.py +++ /dev/null @@ -1,145 +0,0 @@ -# (c) Copyright 2015 Cisco Systems, Inc. -# All Rights Reserved. -# -# 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 sys - -from neutronclient.neutron.v2_0.vpn import endpoint_group -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20VpnEndpointGroupJSON(test_cli20.CLITestV20Base): - - def setUp(self): - super(CLITestV20VpnEndpointGroupJSON, self).setUp() - self.register_non_admin_status_resource('endpoint_group') - - def test_create_endpoint_group_with_cidrs(self): - # vpn-endpoint-group-create with CIDR endpoints.""" - resource = 'endpoint_group' - cmd = endpoint_group.CreateEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - tenant_id = 'mytenant-id' - my_id = 'my-id' - name = 'my-endpoint-group' - description = 'my endpoint group' - endpoint_type = 'cidr' - endpoints = ['10.0.0.0/24', '20.0.0.0/24'] - - args = ['--name', name, - '--description', description, - '--tenant-id', tenant_id, - '--type', endpoint_type, - '--value', '10.0.0.0/24', - '--value', '20.0.0.0/24'] - - position_names = ['name', 'description', 'tenant_id', - 'type', 'endpoints'] - - position_values = [name, description, tenant_id, - endpoint_type, endpoints] - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_endpoint_group_with_subnets(self): - # vpn-endpoint-group-create with subnet endpoints.""" - resource = 'endpoint_group' - cmd = endpoint_group.CreateEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - tenant_id = 'mytenant-id' - my_id = 'my-id' - endpoint_type = 'subnet' - subnet = 'subnet-id' - endpoints = [subnet] - - args = ['--type', endpoint_type, - '--value', subnet, - '--tenant-id', tenant_id] - - position_names = ['type', 'endpoints', 'tenant_id'] - - position_values = [endpoint_type, endpoints, tenant_id] - - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values) - - def test_list_endpoint_group(self): - # vpn-endpoint-group-list. - resources = "endpoint_groups" - cmd = endpoint_group.ListEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_endpoint_group_pagination(self): - # vpn-endpoint-group-list. - resources = "endpoint_groups" - cmd = endpoint_group.ListEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_endpoint_group_sort(self): - # vpn-endpoint-group-list --sort-key name --sort-key id - # --sort-key asc --sort-key desc - resources = "endpoint_groups" - cmd = endpoint_group.ListEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_endpoint_group_limit(self): - # vpn-endpoint-group-list -P. - resources = "endpoint_groups" - cmd = endpoint_group.ListEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_endpoint_group_id(self): - # vpn-endpoint-group-show test_id. - resource = 'endpoint_group' - cmd = endpoint_group.ShowEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_endpoint_group_id_name(self): - # vpn-endpoint-group-show. - resource = 'endpoint_group' - cmd = endpoint_group.ShowEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_endpoint_group(self): - # vpn-endpoint-group-update myid --name newname --description newdesc. - resource = 'endpoint_group' - cmd = endpoint_group.UpdateEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname', - '--description', 'newdesc'], - {'name': 'newname', - 'description': 'newdesc'}) - - def test_delete_endpoint_group(self): - # vpn-endpoint-group-delete my-id. - resource = 'endpoint_group' - cmd = endpoint_group.DeleteEndpointGroup(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) diff --git a/neutronclient/tests/unit/vpn/test_cli20_ikepolicy.py b/neutronclient/tests/unit/vpn/test_cli20_ikepolicy.py deleted file mode 100644 index 33e326cab..000000000 --- a/neutronclient/tests/unit/vpn/test_cli20_ikepolicy.py +++ /dev/null @@ -1,241 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.vpn import ikepolicy -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20VpnIkePolicyJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['ikepolicy'] - - def _test_create_ikepolicy_all_params(self, auth='sha1', - expected_exc=None): - # vpn-ikepolicy-create all params. - resource = 'ikepolicy' - cmd = ikepolicy.CreateIKEPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ikepolicy1' - description = 'my-ike-policy' - auth_algorithm = auth - encryption_algorithm = 'aes-256' - ike_version = 'v1' - phase1_negotiation_mode = 'main' - pfs = 'group5' - tenant_id = 'my-tenant' - my_id = 'my-id' - lifetime = 'units=seconds,value=20000' - - args = [name, - '--description', description, - '--tenant-id', tenant_id, - '--auth-algorithm', auth_algorithm, - '--encryption-algorithm', encryption_algorithm, - '--ike-version', ike_version, - '--phase1-negotiation-mode', phase1_negotiation_mode, - '--lifetime', lifetime, - '--pfs', pfs] - - position_names = ['name', 'description', - 'auth_algorithm', 'encryption_algorithm', - 'phase1_negotiation_mode', - 'ike_version', 'pfs', - 'tenant_id'] - - position_values = [name, description, - auth_algorithm, encryption_algorithm, - phase1_negotiation_mode, ike_version, pfs, - tenant_id] - extra_body = { - 'lifetime': { - 'units': 'seconds', - 'value': 20000, - }, - } - - if not expected_exc: - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - else: - self.assertRaises( - expected_exc, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - - def test_create_ikepolicy_all_params(self): - self._test_create_ikepolicy_all_params() - - def test_create_ikepolicy_auth_sha256(self): - self._test_create_ikepolicy_all_params(auth='sha256') - - def test_create_ikepolicy_auth_sha384(self): - self._test_create_ikepolicy_all_params(auth='sha384') - - def test_create_ikepolicy_auth_sha512(self): - self._test_create_ikepolicy_all_params(auth='sha512') - - def test_create_ikepolicy_invalid_auth(self): - self._test_create_ikepolicy_all_params(auth='invalid', - expected_exc=SystemExit) - - def test_create_ikepolicy_with_limited_params(self): - # vpn-ikepolicy-create with limited params. - resource = 'ikepolicy' - cmd = ikepolicy.CreateIKEPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ikepolicy1' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-128' - ike_version = 'v1' - phase1_negotiation_mode = 'main' - pfs = 'group5' - tenant_id = 'my-tenant' - my_id = 'my-id' - - args = [name, - '--tenant-id', tenant_id] - - position_names = ['name', - 'auth_algorithm', 'encryption_algorithm', - 'phase1_negotiation_mode', - 'ike_version', 'pfs', - 'tenant_id'] - - position_values = [name, - auth_algorithm, encryption_algorithm, - phase1_negotiation_mode, - ike_version, pfs, - tenant_id] - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def _test_lifetime_values(self, lifetime, expected_exc=None): - resource = 'ikepolicy' - cmd = ikepolicy.CreateIKEPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ikepolicy1' - description = 'my-ike-policy' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-256' - ike_version = 'v1' - phase1_negotiation_mode = 'main' - pfs = 'group5' - tenant_id = 'my-tenant' - my_id = 'my-id' - - args = [name, - '--description', description, - '--tenant-id', tenant_id, - '--auth-algorithm', auth_algorithm, - '--encryption-algorithm', encryption_algorithm, - '--ike-version', ike_version, - '--phase1-negotiation-mode', phase1_negotiation_mode, - '--lifetime', lifetime, - '--pfs', pfs] - - position_names = ['name', 'description', - 'auth_algorithm', 'encryption_algorithm', - 'phase1_negotiation_mode', - 'ike_version', 'pfs', - 'tenant_id'] - - position_values = [name, description, - auth_algorithm, encryption_algorithm, - phase1_negotiation_mode, ike_version, pfs, - tenant_id] - if not expected_exc: - expected_exc = exceptions.CommandError - self.assertRaises( - expected_exc, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_ikepolicy_with_invalid_lifetime_keys(self): - lifetime = 'uts=seconds,val=20000' - self._test_lifetime_values(lifetime, expected_exc=SystemExit) - - def test_create_ikepolicy_with_invalid_lifetime_value(self): - lifetime = 'units=seconds,value=-1' - self._test_lifetime_values(lifetime) - - def test_list_ikepolicy(self): - # vpn-ikepolicy-list. - resources = "ikepolicies" - cmd = ikepolicy.ListIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_ikepolicy_pagination(self): - # vpn-ikepolicy-list. - resources = "ikepolicies" - cmd = ikepolicy.ListIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_ikepolicy_sort(self): - # vpn-ikepolicy-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "ikepolicies" - cmd = ikepolicy.ListIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_ikepolicy_limit(self): - # vpn-ikepolicy-list -P. - resources = "ikepolicies" - cmd = ikepolicy.ListIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_ikepolicy_id(self): - # vpn-ikepolicy-show ikepolicy_id. - resource = 'ikepolicy' - cmd = ikepolicy.ShowIKEPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_ikepolicy_id_name(self): - # vpn-ikepolicy-show. - resource = 'ikepolicy' - cmd = ikepolicy.ShowIKEPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_ikepolicy(self): - # vpn-ikepolicy-update myid --name newname --tags a b. - resource = 'ikepolicy' - cmd = ikepolicy.UpdateIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - # vpn-ikepolicy-update myid --pfs group2 --ike-version v2. - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--pfs', 'group2', - '--ike-version', 'v2'], - {'pfs': 'group2', - 'ike_version': 'v2'}) - - def test_delete_ikepolicy(self): - # vpn-ikepolicy-delete my-id. - resource = 'ikepolicy' - cmd = ikepolicy.DeleteIKEPolicy(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) diff --git a/neutronclient/tests/unit/vpn/test_cli20_ipsec_site_connection.py b/neutronclient/tests/unit/vpn/test_cli20_ipsec_site_connection.py deleted file mode 100644 index cbab15cb8..000000000 --- a/neutronclient/tests/unit/vpn/test_cli20_ipsec_site_connection.py +++ /dev/null @@ -1,342 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.vpn import ipsec_site_connection -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20IPsecSiteConnectionJSON(test_cli20.CLITestV20Base): - - # TODO(pcm): Remove, once peer-cidr is deprecated completely - def test_create_ipsec_site_connection_all_params_using_peer_cidrs(self): - # ipsecsite-connection-create all params using peer CIDRs. - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.CreateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - tenant_id = 'mytenant_id' - name = 'connection1' - my_id = 'my_id' - peer_address = '192.168.2.10' - peer_id = '192.168.2.10' - psk = 'abcd' - mtu = '1500' - initiator = 'bi-directional' - vpnservice_id = 'vpnservice_id' - ikepolicy_id = 'ikepolicy_id' - ipsecpolicy_id = 'ipsecpolicy_id' - peer_cidrs = ['192.168.3.0/24', '192.168.2.0/24'] - admin_state = True - description = 'my-vpn-connection' - dpd = 'action=restart,interval=30,timeout=120' - - args = ['--tenant-id', tenant_id, - '--peer-address', peer_address, '--peer-id', peer_id, - '--psk', psk, '--initiator', initiator, - '--vpnservice-id', vpnservice_id, - '--ikepolicy-id', ikepolicy_id, '--name', name, - '--ipsecpolicy-id', ipsecpolicy_id, '--mtu', mtu, - '--description', description, - '--peer-cidr', '192.168.3.0/24', - '--peer-cidr', '192.168.2.0/24', - '--dpd', dpd] - - position_names = ['name', 'tenant_id', 'admin_state_up', - 'peer_address', 'peer_id', 'peer_cidrs', - 'psk', 'mtu', 'initiator', 'description', - 'vpnservice_id', 'ikepolicy_id', - 'ipsecpolicy_id'] - - position_values = [name, tenant_id, admin_state, peer_address, - peer_id, peer_cidrs, psk, mtu, - initiator, description, - vpnservice_id, ikepolicy_id, ipsecpolicy_id] - extra_body = { - 'dpd': { - 'action': 'restart', - 'interval': 30, - 'timeout': 120, - }, - } - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - - def test_create_ipsec_site_conn_all_params(self): - # ipsecsite-connection-create all params using endpoint groups. - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.CreateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - tenant_id = 'mytenant_id' - name = 'connection1' - my_id = 'my_id' - peer_address = '192.168.2.10' - peer_id = '192.168.2.10' - psk = 'abcd' - mtu = '1500' - initiator = 'bi-directional' - vpnservice_id = 'vpnservice_id' - ikepolicy_id = 'ikepolicy_id' - ipsecpolicy_id = 'ipsecpolicy_id' - local_ep_group = 'local-epg' - peer_ep_group = 'peer-epg' - admin_state = True - description = 'my-vpn-connection' - dpd = 'action=restart,interval=30,timeout=120' - - args = ['--tenant-id', tenant_id, - '--peer-address', peer_address, '--peer-id', peer_id, - '--psk', psk, '--initiator', initiator, - '--vpnservice-id', vpnservice_id, - '--ikepolicy-id', ikepolicy_id, '--name', name, - '--ipsecpolicy-id', ipsecpolicy_id, '--mtu', mtu, - '--description', description, - '--local-ep-group', local_ep_group, - '--peer-ep-group', peer_ep_group, - '--dpd', dpd] - - position_names = ['name', 'tenant_id', 'admin_state_up', - 'peer_address', 'peer_id', 'psk', 'mtu', - 'local_ep_group_id', 'peer_ep_group_id', - 'initiator', 'description', - 'vpnservice_id', 'ikepolicy_id', - 'ipsecpolicy_id'] - - position_values = [name, tenant_id, admin_state, peer_address, - peer_id, psk, mtu, local_ep_group, - peer_ep_group, initiator, description, - vpnservice_id, ikepolicy_id, ipsecpolicy_id] - extra_body = { - 'dpd': { - 'action': 'restart', - 'interval': 30, - 'timeout': 120, - }, - } - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - - def test_create_ipsec_site_connection_with_limited_params(self): - # ipsecsite-connection-create with limited params. - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.CreateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - tenant_id = 'mytenant_id' - my_id = 'my_id' - peer_address = '192.168.2.10' - peer_id = '192.168.2.10' - psk = 'abcd' - mtu = '1500' - initiator = 'bi-directional' - vpnservice_id = 'vpnservice_id' - ikepolicy_id = 'ikepolicy_id' - ipsecpolicy_id = 'ipsecpolicy_id' - local_ep_group = 'local-epg' - peer_ep_group = 'peer-epg' - admin_state = True - - args = ['--tenant-id', tenant_id, - '--peer-address', peer_address, - '--peer-id', peer_id, - '--psk', psk, - '--vpnservice-id', vpnservice_id, - '--ikepolicy-id', ikepolicy_id, - '--ipsecpolicy-id', ipsecpolicy_id, - '--local-ep-group', local_ep_group, - '--peer-ep-group', peer_ep_group] - - position_names = ['tenant_id', 'admin_state_up', - 'peer_address', 'peer_id', - 'local_ep_group_id', 'peer_ep_group_id', - 'psk', 'mtu', 'initiator', - 'vpnservice_id', 'ikepolicy_id', - 'ipsecpolicy_id'] - - position_values = [tenant_id, admin_state, peer_address, peer_id, - local_ep_group, peer_ep_group, psk, mtu, initiator, - vpnservice_id, ikepolicy_id, ipsecpolicy_id] - - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values) - - def _test_create_failure(self, additional_args=None, expected_exc=None): - # Helper to test failure of IPSec site-to-site creation failure. - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.CreateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - tenant_id = 'mytenant_id' - my_id = 'my_id' - peer_address = '192.168.2.10' - peer_id = '192.168.2.10' - psk = 'abcd' - mtu = '1500' - initiator = 'bi-directional' - vpnservice_id = 'vpnservice_id' - ikepolicy_id = 'ikepolicy_id' - ipsecpolicy_id = 'ipsecpolicy_id' - admin_state = True - - args = ['--tenant-id', tenant_id, - '--peer-address', peer_address, - '--peer-id', peer_id, - '--psk', psk, - '--vpnservice-id', vpnservice_id, - '--ikepolicy-id', ikepolicy_id, - '--ipsecpolicy-id', ipsecpolicy_id] - if additional_args is not None: - args += additional_args - position_names = ['tenant_id', 'admin_state_up', 'peer_address', - 'peer_id', 'psk', 'mtu', 'initiator', - 'local_ep_group_id', 'peer_ep_group_id', - 'vpnservice_id', 'ikepolicy_id', 'ipsecpolicy_id'] - - position_values = [tenant_id, admin_state, peer_address, peer_id, psk, - mtu, initiator, None, None, vpnservice_id, - ikepolicy_id, ipsecpolicy_id] - if not expected_exc: - expected_exc = exceptions.CommandError - self.assertRaises(expected_exc, - self._test_create_resource, - resource, cmd, None, my_id, args, - position_names, position_values) - - def test_fail_create_with_invalid_mtu(self): - # ipsecsite-connection-create with invalid dpd values. - bad_mtu = ['--mtu', '67'] - self._test_create_failure(bad_mtu) - - def test_fail_create_with_invalid_dpd_keys(self): - bad_dpd_key = ['--dpd', 'act=restart,interval=30,time=120'] - self._test_create_failure(bad_dpd_key, SystemExit) - - def test_fail_create_with_invalid_dpd_values(self): - bad_dpd_values = ['--dpd', 'action=hold,interval=30,timeout=-1'] - self._test_create_failure(bad_dpd_values) - - def test_fail_create_missing_endpoint_groups_or_cidr(self): - # Must provide either endpoint groups or peer cidrs. - self._test_create_failure() - - def test_fail_create_missing_peer_endpoint_group(self): - # Fails if dont have both endpoint groups - missing peer. - self._test_create_failure(['--local-ep-group', 'local-epg']) - - def test_fail_create_missing_local_endpoint_group(self): - # Fails if dont have both endpoint groups - missing local. - self._test_create_failure(['--peer-ep-group', 'peer-epg']) - - def test_fail_create_when_both_endpoints_and_peer_cidr(self): - # Cannot intermix endpoint groups and peer CIDRs for create. - additional_args = ['--local-ep-group', 'local-epg', - '--peer-ep-group', 'peer-epg', - '--peer-cidr', '10.2.0.0/24'] - self._test_create_failure(additional_args) - - def test_list_ipsec_site_connection(self): - # ipsecsite-connection-list. - resources = "ipsec_site_connections" - cmd = ipsec_site_connection.ListIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_list_resources(resources, cmd, True) - - def test_list_ipsec_site_connection_pagination(self): - # ipsecsite-connection-list. - resources = "ipsec_site_connections" - cmd = ipsec_site_connection.ListIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_ipsec_site_connection_sort(self): - # ipsecsite-connection-list. - # --sort-key name --sort-key id --sort-key asc --sort-key desc - resources = "ipsec_site_connections" - cmd = ipsec_site_connection.ListIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_ipsec_site_connection_limit(self): - # ipsecsite-connection-list -P. - resources = "ipsec_site_connections" - cmd = ipsec_site_connection.ListIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_delete_ipsec_site_connection(self): - # ipsecsite-connection-delete my-id. - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.DeleteIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_update_ipsec_site_connection(self): - # ipsecsite-connection-update myid --name Branch-new --tags a b. - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.UpdateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'Branch-new', - '--tags', 'a', 'b'], - {'name': 'Branch-new', - 'tags': ['a', 'b'], }) - # ipsecsite-connection-update myid --mtu 69 --initiator response-only - # --peer-id '192.168.2.11' --peer-ep-group 'update-grp' - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--mtu', '69', - '--initiator', 'response-only', - '--peer-id', '192.168.2.11', - '--peer-ep-group', 'update-grp'], - {'mtu': '69', - 'initiator': 'response-only', - 'peer_id': '192.168.2.11', - 'peer_ep_group_id': 'update-grp', },) - - def test_show_ipsec_site_connection_id(self): - # ipsecsite-connection-show test_id.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.ShowIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_ipsec_site_connection_id_name(self): - # ipsecsite-connection-show.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.ShowIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) diff --git a/neutronclient/tests/unit/vpn/test_cli20_ipsecpolicy.py b/neutronclient/tests/unit/vpn/test_cli20_ipsecpolicy.py deleted file mode 100644 index 8c7df4a6f..000000000 --- a/neutronclient/tests/unit/vpn/test_cli20_ipsecpolicy.py +++ /dev/null @@ -1,249 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# 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 sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.vpn import ipsecpolicy -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20VpnIpsecPolicyJSON(test_cli20.CLITestV20Base): - - non_admin_status_resources = ['ipsecpolicy'] - - def _test_create_ipsecpolicy_all_params(self, auth='sha1', - expected_exc=None): - # vpn-ipsecpolicy-create all params with dashes. - resource = 'ipsecpolicy' - cmd = ipsecpolicy.CreateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ipsecpolicy1' - description = 'first-ipsecpolicy1' - auth_algorithm = auth - encryption_algorithm = 'aes-256' - encapsulation_mode = 'tunnel' - pfs = 'group5' - transform_protocol = 'ah' - tenant_id = 'my-tenant' - my_id = 'my-id' - lifetime = 'units=seconds,value=20000' - - args = [name, - '--description', description, - '--tenant-id', tenant_id, - '--auth-algorithm', auth_algorithm, - '--encryption-algorithm', encryption_algorithm, - '--transform-protocol', transform_protocol, - '--encapsulation-mode', encapsulation_mode, - '--lifetime', lifetime, - '--pfs', pfs] - - position_names = ['name', 'auth_algorithm', 'encryption_algorithm', - 'encapsulation_mode', 'description', - 'transform_protocol', 'pfs', - 'tenant_id'] - - position_values = [name, auth_algorithm, encryption_algorithm, - encapsulation_mode, description, - transform_protocol, pfs, - tenant_id] - extra_body = { - 'lifetime': { - 'units': 'seconds', - 'value': 20000, - }, - } - - if not expected_exc: - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - else: - self.assertRaises( - expected_exc, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - - def test_create_ipsecpolicy_all_params(self): - self._test_create_ipsecpolicy_all_params() - - def test_create_ipsecpolicy_auth_sha256(self): - self._test_create_ipsecpolicy_all_params(auth='sha256') - - def test_create_ipsecpolicy_auth_sha384(self): - self._test_create_ipsecpolicy_all_params(auth='sha384') - - def test_create_ipsecpolicy_auth_sha512(self): - self._test_create_ipsecpolicy_all_params(auth='sha512') - - def test_create_ipsecpolicy_invalid_auth(self): - self._test_create_ipsecpolicy_all_params(auth='invalid', - expected_exc=SystemExit) - - def test_create_ipsecpolicy_with_limited_params(self): - # vpn-ipsecpolicy-create with limited params. - resource = 'ipsecpolicy' - cmd = ipsecpolicy.CreateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ipsecpolicy1' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-128' - encapsulation_mode = 'tunnel' - pfs = 'group5' - transform_protocol = 'esp' - tenant_id = 'my-tenant' - my_id = 'my-id' - - args = [name, - '--tenant-id', tenant_id] - - position_names = ['name', 'auth_algorithm', 'encryption_algorithm', - 'encapsulation_mode', - 'transform_protocol', 'pfs', - 'tenant_id'] - - position_values = [name, auth_algorithm, encryption_algorithm, - encapsulation_mode, - transform_protocol, pfs, - tenant_id] - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def _test_lifetime_values(self, lifetime, expected_exc=None): - resource = 'ipsecpolicy' - cmd = ipsecpolicy.CreateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ipsecpolicy1' - description = 'my-ipsec-policy' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-256' - ike_version = 'v1' - phase1_negotiation_mode = 'main' - pfs = 'group5' - tenant_id = 'my-tenant' - my_id = 'my-id' - - args = [name, - '--description', description, - '--tenant-id', tenant_id, - '--auth-algorithm', auth_algorithm, - '--encryption-algorithm', encryption_algorithm, - '--ike-version', ike_version, - '--phase1-negotiation-mode', phase1_negotiation_mode, - '--lifetime', lifetime, - '--pfs', pfs] - - position_names = ['name', 'description', - 'auth_algorithm', 'encryption_algorithm', - 'phase1_negotiation_mode', - 'ike_version', 'pfs', - 'tenant_id'] - - position_values = [name, description, - auth_algorithm, encryption_algorithm, - phase1_negotiation_mode, ike_version, pfs, - tenant_id] - if not expected_exc: - expected_exc = exceptions.CommandError - self.assertRaises( - expected_exc, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_ipsecpolicy_with_invalid_lifetime_keys(self): - lifetime = 'uts=seconds,val=20000' - self._test_lifetime_values(lifetime, SystemExit) - - def test_create_ipsecpolicy_with_invalid_lifetime_units(self): - lifetime = 'units=minutes,value=600' - self._test_lifetime_values(lifetime) - - def test_create_ipsecpolicy_with_invalid_lifetime_value(self): - lifetime = 'units=seconds,value=0' - self._test_lifetime_values(lifetime) - - def test_list_ipsecpolicy(self): - # vpn-ipsecpolicy-list. - resources = "ipsecpolicies" - cmd = ipsecpolicy.ListIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_ipsecpolicy_pagination(self): - # vpn-ipsecpolicy-list. - resources = "ipsecpolicies" - cmd = ipsecpolicy.ListIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_ipsecpolicy_sort(self): - # vpn-ipsecpolicy-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "ipsecpolicies" - cmd = ipsecpolicy.ListIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_ipsecpolicy_limit(self): - # vpn-ipsecpolicy-list -P. - resources = "ipsecpolicies" - cmd = ipsecpolicy.ListIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_ipsecpolicy_id(self): - # vpn-ipsecpolicy-show ipsecpolicy_id. - resource = 'ipsecpolicy' - cmd = ipsecpolicy.ShowIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_ipsecpolicy_id_name(self): - # vpn-ipsecpolicy-show. - resource = 'ipsecpolicy' - cmd = ipsecpolicy.ShowIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_ipsecpolicy_name(self): - # vpn-ipsecpolicy-update myid --name newname --tags a b. - resource = 'ipsecpolicy' - cmd = ipsecpolicy.UpdateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_update_ipsecpolicy_other_params(self): - # vpn-ipsecpolicy-update myid --transform-protocol esp - # --pfs group14 --encapsulation-mode transport - resource = 'ipsecpolicy' - cmd = ipsecpolicy.UpdateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--transform-protocol', 'esp', - '--pfs', 'group14', - '--encapsulation-mode', 'transport'], - {'transform_protocol': 'esp', - 'pfs': 'group14', - 'encapsulation_mode': 'transport', }) - - def test_delete_ipsecpolicy(self): - # vpn-ipsecpolicy-delete my-id. - resource = 'ipsecpolicy' - cmd = ipsecpolicy.DeleteIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) diff --git a/neutronclient/tests/unit/vpn/test_cli20_vpnservice.py b/neutronclient/tests/unit/vpn/test_cli20_vpnservice.py deleted file mode 100644 index 3c4def84d..000000000 --- a/neutronclient/tests/unit/vpn/test_cli20_vpnservice.py +++ /dev/null @@ -1,157 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# 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 sys - -from neutronclient.neutron.v2_0.vpn import vpnservice -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20VpnServiceJSON(test_cli20.CLITestV20Base): - - def test_create_vpnservice_all_params(self): - # vpn-service-create all params. - resource = 'vpnservice' - cmd = vpnservice.CreateVPNService(test_cli20.MyApp(sys.stdout), None) - subnet = 'mysubnet-id' - router = 'myrouter-id' - tenant_id = 'mytenant-id' - my_id = 'my-id' - name = 'myvpnservice' - description = 'my-vpn-service' - admin_state = True - - args = ['--name', name, - '--description', description, - router, - subnet, - '--tenant-id', tenant_id] - - position_names = ['admin_state_up', 'name', 'description', - 'subnet_id', 'router_id', - 'tenant_id'] - - position_values = [admin_state, name, description, - subnet, router, tenant_id] - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_vpnservice_with_limited_params(self): - # vpn-service-create with limited params. - resource = 'vpnservice' - cmd = vpnservice.CreateVPNService(test_cli20.MyApp(sys.stdout), None) - subnet = 'mysubnet-id' - router = 'myrouter-id' - tenant_id = 'mytenant-id' - my_id = 'my-id' - admin_state = True - - args = [router, - subnet, - '--tenant-id', tenant_id] - - position_names = ['admin_state_up', - 'subnet_id', 'router_id', - 'tenant_id'] - - position_values = [admin_state, subnet, router, tenant_id] - - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values) - - def test_create_vpnservice_without_subnet(self): - # vpn-service-create with no subnet provided. - resource = 'vpnservice' - cmd = vpnservice.CreateVPNService(test_cli20.MyApp(sys.stdout), None) - router = 'myrouter-id' - tenant_id = 'mytenant-id' - my_id = 'my-id' - admin_state = True - - args = [router, - '--tenant-id', tenant_id] - - position_names = ['admin_state_up', - 'subnet_id', 'router_id', - 'tenant_id'] - - position_values = [admin_state, None, router, tenant_id] - - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values) - - def test_list_vpnservice(self): - # vpn-service-list. - resources = "vpnservices" - cmd = vpnservice.ListVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_vpnservice_pagination(self): - # vpn-service-list. - resources = "vpnservices" - cmd = vpnservice.ListVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_vpnservice_sort(self): - # vpn-service-list --sort-key name --sort-key id --sort-key asc - # --sort-key desc - resources = "vpnservices" - cmd = vpnservice.ListVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_vpnservice_limit(self): - # vpn-service-list -P. - resources = "vpnservices" - cmd = vpnservice.ListVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_vpnservice_id(self): - # vpn-service-show test_id. - resource = 'vpnservice' - cmd = vpnservice.ShowVPNService(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_vpnservice_id_name(self): - # vpn-service-show.""" - resource = 'vpnservice' - cmd = vpnservice.ShowVPNService(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_vpnservice(self): - # vpn-service-update myid --name newname --tags a b. - resource = 'vpnservice' - cmd = vpnservice.UpdateVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - # vpn-service-update myid --admin-state-up False - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--admin-state-up', 'False'], - {'admin_state_up': 'False', }) - - def test_delete_vpnservice(self): - # vpn-service-delete my-id. - resource = 'vpnservice' - cmd = vpnservice.DeleteVPNService(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) diff --git a/neutronclient/tests/unit/vpn/test_utils.py b/neutronclient/tests/unit/vpn/test_utils.py deleted file mode 100644 index c39f7ceb5..000000000 --- a/neutronclient/tests/unit/vpn/test_utils.py +++ /dev/null @@ -1,130 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# 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 - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.neutron.v2_0.vpn import utils as vpn_utils - - -class TestVPNUtils(testtools.TestCase): - - def test_validate_lifetime_dictionary_seconds(self): - input_str = utils.str2dict("units=seconds,value=3600") - self.assertIsNone(vpn_utils.validate_lifetime_dict(input_str)) - - def test_validate_dpd_dictionary_action_hold(self): - input_str = utils.str2dict("action=hold,interval=30,timeout=120") - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_dpd_dictionary_action_restart(self): - input_str = utils.str2dict("action=restart,interval=30,timeout=120") - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_dpd_dictionary_action_restart_by_peer(self): - input_str = utils.str2dict( - "action=restart-by-peer,interval=30,timeout=120" - ) - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_dpd_dictionary_action_clear(self): - input_str = utils.str2dict('action=clear,interval=30,timeout=120') - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_dpd_dictionary_action_disabled(self): - input_str = utils.str2dict('action=disabled,interval=30,timeout=120') - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_lifetime_dictionary_invalid_unit_key(self): - input_str = utils.str2dict('ut=seconds,value=3600') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_invalid_unit_key_value(self): - input_str = utils.str2dict('units=seconds,val=3600') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_unsupported_units(self): - input_str = utils.str2dict('units=minutes,value=3600') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_invalid_empty_unit(self): - input_str = utils.str2dict('units=,value=3600') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_under_minimum_integer_value(self): - input_str = utils.str2dict('units=seconds,value=59') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_negative_integer_value(self): - input_str = utils.str2dict('units=seconds,value=-1') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_empty_value(self): - input_str = utils.str2dict('units=seconds,value=') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_dpd_dictionary_invalid_key_action(self): - input_str = utils.str2dict('act=hold,interval=30,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_invalid_key_interval(self): - input_str = utils.str2dict('action=hold,int=30,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_invalid_key_timeout(self): - input_str = utils.str2dict('action=hold,interval=30,tiut=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_unsupported_action(self): - input_str = utils.str2dict('action=bye-bye,interval=30,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_empty_action(self): - input_str = utils.str2dict('action=,interval=30,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_empty_interval(self): - input_str = utils.str2dict('action=hold,interval=,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_negative_interval_value(self): - input_str = utils.str2dict('action=hold,interval=-1,timeout=120') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_dpd_dictionary_zero_timeout(self): - input_str = utils.str2dict('action=hold,interval=30,timeout=0') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_empty_timeout(self): - input_str = utils.str2dict('action=hold,interval=30,timeout=') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_negative_timeout_value(self): - input_str = utils.str2dict('action=hold,interval=30,timeout=-1') - self._test_validate_lifetime_negative_test_case(input_str) - - def _test_validate_lifetime_negative_test_case(self, input_str): - """Generic handler for negative lifetime tests.""" - self.assertRaises(exceptions.CommandError, - vpn_utils.validate_lifetime_dict, - (input_str)) - - def _test_validate_dpd_negative_test_case(self, input_str): - """Generic handler for negative lifetime tests.""" - self.assertRaises(exceptions.CommandError, - vpn_utils.validate_lifetime_dict, - (input_str)) diff --git a/releasenotes/notes/remove-cli-code-53969e9aa927e530.yaml b/releasenotes/notes/remove-cli-code-53969e9aa927e530.yaml new file mode 100644 index 000000000..92ab5423c --- /dev/null +++ b/releasenotes/notes/remove-cli-code-53969e9aa927e530.yaml @@ -0,0 +1,12 @@ +prelude: > + | + This new version of ``python-neutronclient`` does not include the + command line interface code. The "neutron" script is no longer + supported. This project only contains the OpenStack Client bindings + that are currently being moved to OpenStack SDK + _. +deprecations: + - | + This project no longer provides CLI support. All code has been removed. + Please use openstack CLI instead. See `openstack CLI command list + `_. diff --git a/setup.cfg b/setup.cfg index 432ec682f..3bab0a176 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,9 +26,6 @@ packages = neutronclient [entry_points] -console_scripts = - neutron = neutronclient.shell:main - openstack.cli.extension = neutronclient = neutronclient.osc.plugin @@ -163,287 +160,3 @@ openstack.neutronclient.v2 = vpn_ipsec_site_connection_show = neutronclient.osc.v2.vpnaas.ipsec_site_connection:ShowIPsecSiteConnection network_onboard_subnets = neutronclient.osc.v2.subnet_onboard.subnet_onboard:NetworkOnboardSubnets - -neutron.cli.v2 = - bash-completion = neutronclient.shell:BashCompletionCommand - - net-list = neutronclient.neutron.v2_0.network:ListNetwork - net-external-list = neutronclient.neutron.v2_0.network:ListExternalNetwork - net-show = neutronclient.neutron.v2_0.network:ShowNetwork - net-create = neutronclient.neutron.v2_0.network:CreateNetwork - net-delete = neutronclient.neutron.v2_0.network:DeleteNetwork - net-update = neutronclient.neutron.v2_0.network:UpdateNetwork - - subnet-list = neutronclient.neutron.v2_0.subnet:ListSubnet - subnet-show = neutronclient.neutron.v2_0.subnet:ShowSubnet - subnet-create = neutronclient.neutron.v2_0.subnet:CreateSubnet - subnet-delete = neutronclient.neutron.v2_0.subnet:DeleteSubnet - subnet-update = neutronclient.neutron.v2_0.subnet:UpdateSubnet - - subnetpool-list = neutronclient.neutron.v2_0.subnetpool:ListSubnetPool - subnetpool-show = neutronclient.neutron.v2_0.subnetpool:ShowSubnetPool - subnetpool-create = neutronclient.neutron.v2_0.subnetpool:CreateSubnetPool - subnetpool-delete = neutronclient.neutron.v2_0.subnetpool:DeleteSubnetPool - subnetpool-update = neutronclient.neutron.v2_0.subnetpool:UpdateSubnetPool - - port-list = neutronclient.neutron.v2_0.port:ListPort - port-show = neutronclient.neutron.v2_0.port:ShowPort - port-create = neutronclient.neutron.v2_0.port:CreatePort - port-delete = neutronclient.neutron.v2_0.port:DeletePort - port-update = neutronclient.neutron.v2_0.port:UpdatePort - - purge = neutronclient.neutron.v2_0.purge:Purge - - quota-list = neutronclient.neutron.v2_0.quota:ListQuota - quota-show = neutronclient.neutron.v2_0.quota:ShowQuota - quota-default-show = neutronclient.neutron.v2_0.quota:ShowQuotaDefault - quota-delete = neutronclient.neutron.v2_0.quota:DeleteQuota - quota-update = neutronclient.neutron.v2_0.quota:UpdateQuota - - ext-list = neutronclient.neutron.v2_0.extension:ListExt - ext-show = neutronclient.neutron.v2_0.extension:ShowExt - - router-list = neutronclient.neutron.v2_0.router:ListRouter - router-port-list = neutronclient.neutron.v2_0.port:ListRouterPort - router-show = neutronclient.neutron.v2_0.router:ShowRouter - router-create = neutronclient.neutron.v2_0.router:CreateRouter - router-delete = neutronclient.neutron.v2_0.router:DeleteRouter - router-update = neutronclient.neutron.v2_0.router:UpdateRouter - router-interface-add = neutronclient.neutron.v2_0.router:AddInterfaceRouter - router-interface-delete = neutronclient.neutron.v2_0.router:RemoveInterfaceRouter - router-gateway-set = neutronclient.neutron.v2_0.router:SetGatewayRouter - router-gateway-clear = neutronclient.neutron.v2_0.router:RemoveGatewayRouter - - floatingip-list = neutronclient.neutron.v2_0.floatingip:ListFloatingIP - floatingip-show = neutronclient.neutron.v2_0.floatingip:ShowFloatingIP - floatingip-create = neutronclient.neutron.v2_0.floatingip:CreateFloatingIP - floatingip-delete = neutronclient.neutron.v2_0.floatingip:DeleteFloatingIP - floatingip-associate = neutronclient.neutron.v2_0.floatingip:AssociateFloatingIP - floatingip-disassociate = neutronclient.neutron.v2_0.floatingip:DisassociateFloatingIP - - security-group-list = neutronclient.neutron.v2_0.securitygroup:ListSecurityGroup - security-group-show = neutronclient.neutron.v2_0.securitygroup:ShowSecurityGroup - security-group-create = neutronclient.neutron.v2_0.securitygroup:CreateSecurityGroup - security-group-delete = neutronclient.neutron.v2_0.securitygroup:DeleteSecurityGroup - security-group-update = neutronclient.neutron.v2_0.securitygroup:UpdateSecurityGroup - security-group-rule-list = neutronclient.neutron.v2_0.securitygroup:ListSecurityGroupRule - security-group-rule-show = neutronclient.neutron.v2_0.securitygroup:ShowSecurityGroupRule - security-group-rule-create = neutronclient.neutron.v2_0.securitygroup:CreateSecurityGroupRule - security-group-rule-delete = neutronclient.neutron.v2_0.securitygroup:DeleteSecurityGroupRule - - agent-list = neutronclient.neutron.v2_0.agent:ListAgent - agent-show = neutronclient.neutron.v2_0.agent:ShowAgent - agent-delete = neutronclient.neutron.v2_0.agent:DeleteAgent - agent-update = neutronclient.neutron.v2_0.agent:UpdateAgent - - dhcp-agent-network-add = neutronclient.neutron.v2_0.agentscheduler:AddNetworkToDhcpAgent - dhcp-agent-network-remove = neutronclient.neutron.v2_0.agentscheduler:RemoveNetworkFromDhcpAgent - net-list-on-dhcp-agent = neutronclient.neutron.v2_0.agentscheduler:ListNetworksOnDhcpAgent - dhcp-agent-list-hosting-net = neutronclient.neutron.v2_0.agentscheduler:ListDhcpAgentsHostingNetwork - - l3-agent-router-add = neutronclient.neutron.v2_0.agentscheduler:AddRouterToL3Agent - l3-agent-router-remove = neutronclient.neutron.v2_0.agentscheduler:RemoveRouterFromL3Agent - router-list-on-l3-agent = neutronclient.neutron.v2_0.agentscheduler:ListRoutersOnL3Agent - l3-agent-list-hosting-router = neutronclient.neutron.v2_0.agentscheduler:ListL3AgentsHostingRouter - - lb-pool-list-on-agent = neutronclient.neutron.v2_0.agentscheduler:ListPoolsOnLbaasAgent - lb-agent-hosting-pool = neutronclient.neutron.v2_0.agentscheduler:GetLbaasAgentHostingPool - - lbaas-loadbalancer-list-on-agent = neutronclient.neutron.v2_0.agentscheduler:ListLoadBalancersOnLbaasAgent - lbaas-agent-hosting-loadbalancer = neutronclient.neutron.v2_0.agentscheduler:GetLbaasAgentHostingLoadBalancer - - service-provider-list = neutronclient.neutron.v2_0.servicetype:ListServiceProvider - - rbac-create = neutronclient.neutron.v2_0.rbac:CreateRBACPolicy - rbac-update = neutronclient.neutron.v2_0.rbac:UpdateRBACPolicy - rbac-list = neutronclient.neutron.v2_0.rbac:ListRBACPolicy - rbac-show = neutronclient.neutron.v2_0.rbac:ShowRBACPolicy - rbac-delete = neutronclient.neutron.v2_0.rbac:DeleteRBACPolicy - - address-scope-list = neutronclient.neutron.v2_0.address_scope:ListAddressScope - address-scope-show = neutronclient.neutron.v2_0.address_scope:ShowAddressScope - address-scope-create = neutronclient.neutron.v2_0.address_scope:CreateAddressScope - address-scope-delete = neutronclient.neutron.v2_0.address_scope:DeleteAddressScope - address-scope-update = neutronclient.neutron.v2_0.address_scope:UpdateAddressScope - - availability-zone-list = neutronclient.neutron.v2_0.availability_zone:ListAvailabilityZone - - auto-allocated-topology-show = neutronclient.neutron.v2_0.auto_allocated_topology:ShowAutoAllocatedTopology - auto-allocated-topology-delete = neutronclient.neutron.v2_0.auto_allocated_topology:DeleteAutoAllocatedTopology - - net-ip-availability-list = neutronclient.neutron.v2_0.network_ip_availability:ListIpAvailability - net-ip-availability-show = neutronclient.neutron.v2_0.network_ip_availability:ShowIpAvailability - - tag-add = neutronclient.neutron.v2_0.tag:AddTag - tag-replace = neutronclient.neutron.v2_0.tag:ReplaceTag - tag-remove = neutronclient.neutron.v2_0.tag:RemoveTag - - qos-policy-list = neutronclient.neutron.v2_0.qos.policy:ListQoSPolicy - qos-policy-show = neutronclient.neutron.v2_0.qos.policy:ShowQoSPolicy - qos-policy-create = neutronclient.neutron.v2_0.qos.policy:CreateQoSPolicy - qos-policy-update = neutronclient.neutron.v2_0.qos.policy:UpdateQoSPolicy - qos-policy-delete = neutronclient.neutron.v2_0.qos.policy:DeleteQoSPolicy - qos-bandwidth-limit-rule-create = neutronclient.neutron.v2_0.qos.bandwidth_limit_rule:CreateQoSBandwidthLimitRule - qos-bandwidth-limit-rule-show = neutronclient.neutron.v2_0.qos.bandwidth_limit_rule:ShowQoSBandwidthLimitRule - qos-bandwidth-limit-rule-list = neutronclient.neutron.v2_0.qos.bandwidth_limit_rule:ListQoSBandwidthLimitRules - qos-bandwidth-limit-rule-update = neutronclient.neutron.v2_0.qos.bandwidth_limit_rule:UpdateQoSBandwidthLimitRule - qos-bandwidth-limit-rule-delete = neutronclient.neutron.v2_0.qos.bandwidth_limit_rule:DeleteQoSBandwidthLimitRule - qos-dscp-marking-rule-create = neutronclient.neutron.v2_0.qos.dscp_marking_rule:CreateQoSDscpMarkingRule - qos-dscp-marking-rule-show = neutronclient.neutron.v2_0.qos.dscp_marking_rule:ShowQoSDscpMarkingRule - qos-dscp-marking-rule-list = neutronclient.neutron.v2_0.qos.dscp_marking_rule:ListQoSDscpMarkingRules - qos-dscp-marking-rule-update = neutronclient.neutron.v2_0.qos.dscp_marking_rule:UpdateQoSDscpMarkingRule - qos-dscp-marking-rule-delete = neutronclient.neutron.v2_0.qos.dscp_marking_rule:DeleteQoSDscpMarkingRule - qos-minimum-bandwidth-rule-create = neutronclient.neutron.v2_0.qos.minimum_bandwidth_rule:CreateQoSMinimumBandwidthRule - qos-minimum-bandwidth-rule-show = neutronclient.neutron.v2_0.qos.minimum_bandwidth_rule:ShowQoSMinimumBandwidthRule - qos-minimum-bandwidth-rule-list = neutronclient.neutron.v2_0.qos.minimum_bandwidth_rule:ListQoSMinimumBandwidthRules - qos-minimum-bandwidth-rule-update = neutronclient.neutron.v2_0.qos.minimum_bandwidth_rule:UpdateQoSMinimumBandwidthRule - qos-minimum-bandwidth-rule-delete = neutronclient.neutron.v2_0.qos.minimum_bandwidth_rule:DeleteQoSMinimumBandwidthRule - qos-available-rule-types = neutronclient.neutron.v2_0.qos.rule:ListQoSRuleTypes - - flavor-list = neutronclient.neutron.v2_0.flavor.flavor:ListFlavor - flavor-show = neutronclient.neutron.v2_0.flavor.flavor:ShowFlavor - flavor-create = neutronclient.neutron.v2_0.flavor.flavor:CreateFlavor - flavor-delete = neutronclient.neutron.v2_0.flavor.flavor:DeleteFlavor - flavor-update = neutronclient.neutron.v2_0.flavor.flavor:UpdateFlavor - flavor-associate = neutronclient.neutron.v2_0.flavor.flavor:AssociateFlavor - flavor-disassociate = neutronclient.neutron.v2_0.flavor.flavor:DisassociateFlavor - flavor-profile-list = neutronclient.neutron.v2_0.flavor.flavor_profile:ListFlavorProfile - flavor-profile-show = neutronclient.neutron.v2_0.flavor.flavor_profile:ShowFlavorProfile - flavor-profile-create = neutronclient.neutron.v2_0.flavor.flavor_profile:CreateFlavorProfile - flavor-profile-delete = neutronclient.neutron.v2_0.flavor.flavor_profile:DeleteFlavorProfile - flavor-profile-update = neutronclient.neutron.v2_0.flavor.flavor_profile:UpdateFlavorProfile - - meter-label-create = neutronclient.neutron.v2_0.metering:CreateMeteringLabel - meter-label-list = neutronclient.neutron.v2_0.metering:ListMeteringLabel - meter-label-show = neutronclient.neutron.v2_0.metering:ShowMeteringLabel - meter-label-delete = neutronclient.neutron.v2_0.metering:DeleteMeteringLabel - meter-label-rule-create = neutronclient.neutron.v2_0.metering:CreateMeteringLabelRule - meter-label-rule-list = neutronclient.neutron.v2_0.metering:ListMeteringLabelRule - meter-label-rule-show = neutronclient.neutron.v2_0.metering:ShowMeteringLabelRule - meter-label-rule-delete = neutronclient.neutron.v2_0.metering:DeleteMeteringLabelRule - - firewall-rule-list = neutronclient.neutron.v2_0.fw.firewallrule:ListFirewallRule - firewall-rule-show = neutronclient.neutron.v2_0.fw.firewallrule:ShowFirewallRule - firewall-rule-create = neutronclient.neutron.v2_0.fw.firewallrule:CreateFirewallRule - firewall-rule-update = neutronclient.neutron.v2_0.fw.firewallrule:UpdateFirewallRule - firewall-rule-delete = neutronclient.neutron.v2_0.fw.firewallrule:DeleteFirewallRule - firewall-policy-list = neutronclient.neutron.v2_0.fw.firewallpolicy:ListFirewallPolicy - firewall-policy-show = neutronclient.neutron.v2_0.fw.firewallpolicy:ShowFirewallPolicy - firewall-policy-create = neutronclient.neutron.v2_0.fw.firewallpolicy:CreateFirewallPolicy - firewall-policy-update = neutronclient.neutron.v2_0.fw.firewallpolicy:UpdateFirewallPolicy - firewall-policy-delete = neutronclient.neutron.v2_0.fw.firewallpolicy:DeleteFirewallPolicy - firewall-policy-insert-rule = neutronclient.neutron.v2_0.fw.firewallpolicy:FirewallPolicyInsertRule - firewall-policy-remove-rule = neutronclient.neutron.v2_0.fw.firewallpolicy:FirewallPolicyRemoveRule - firewall-list = neutronclient.neutron.v2_0.fw.firewall:ListFirewall - firewall-show = neutronclient.neutron.v2_0.fw.firewall:ShowFirewall - firewall-create = neutronclient.neutron.v2_0.fw.firewall:CreateFirewall - firewall-update = neutronclient.neutron.v2_0.fw.firewall:UpdateFirewall - firewall-delete = neutronclient.neutron.v2_0.fw.firewall:DeleteFirewall - - bgp-dragent-speaker-add = neutronclient.neutron.v2_0.bgp.dragentscheduler:AddBGPSpeakerToDRAgent - bgp-dragent-speaker-remove = neutronclient.neutron.v2_0.bgp.dragentscheduler:RemoveBGPSpeakerFromDRAgent - bgp-speaker-list-on-dragent = neutronclient.neutron.v2_0.bgp.dragentscheduler:ListBGPSpeakersOnDRAgent - bgp-dragent-list-hosting-speaker = neutronclient.neutron.v2_0.bgp.dragentscheduler:ListDRAgentsHostingBGPSpeaker - bgp-speaker-list = neutronclient.neutron.v2_0.bgp.speaker:ListSpeakers - bgp-speaker-advertiseroute-list = neutronclient.neutron.v2_0.bgp.speaker:ListRoutesAdvertisedBySpeaker - bgp-speaker-show = neutronclient.neutron.v2_0.bgp.speaker:ShowSpeaker - bgp-speaker-create = neutronclient.neutron.v2_0.bgp.speaker:CreateSpeaker - bgp-speaker-update = neutronclient.neutron.v2_0.bgp.speaker:UpdateSpeaker - bgp-speaker-delete = neutronclient.neutron.v2_0.bgp.speaker:DeleteSpeaker - bgp-speaker-peer-add = neutronclient.neutron.v2_0.bgp.speaker:AddPeerToSpeaker - bgp-speaker-peer-remove = neutronclient.neutron.v2_0.bgp.speaker:RemovePeerFromSpeaker - bgp-speaker-network-add = neutronclient.neutron.v2_0.bgp.speaker:AddNetworkToSpeaker - bgp-speaker-network-remove = neutronclient.neutron.v2_0.bgp.speaker:RemoveNetworkFromSpeaker - bgp-peer-list = neutronclient.neutron.v2_0.bgp.peer:ListPeers - bgp-peer-show = neutronclient.neutron.v2_0.bgp.peer:ShowPeer - bgp-peer-create = neutronclient.neutron.v2_0.bgp.peer:CreatePeer - bgp-peer-update = neutronclient.neutron.v2_0.bgp.peer:UpdatePeer - bgp-peer-delete = neutronclient.neutron.v2_0.bgp.peer:DeletePeer - - lbaas-loadbalancer-list = neutronclient.neutron.v2_0.lb.v2.loadbalancer:ListLoadBalancer - lbaas-loadbalancer-show = neutronclient.neutron.v2_0.lb.v2.loadbalancer:ShowLoadBalancer - lbaas-loadbalancer-create = neutronclient.neutron.v2_0.lb.v2.loadbalancer:CreateLoadBalancer - lbaas-loadbalancer-update = neutronclient.neutron.v2_0.lb.v2.loadbalancer:UpdateLoadBalancer - lbaas-loadbalancer-delete = neutronclient.neutron.v2_0.lb.v2.loadbalancer:DeleteLoadBalancer - lbaas-loadbalancer-stats = neutronclient.neutron.v2_0.lb.v2.loadbalancer:RetrieveLoadBalancerStats - lbaas-loadbalancer-status = neutronclient.neutron.v2_0.lb.v2.loadbalancer:RetrieveLoadBalancerStatus - lbaas-listener-list = neutronclient.neutron.v2_0.lb.v2.listener:ListListener - lbaas-listener-show = neutronclient.neutron.v2_0.lb.v2.listener:ShowListener - lbaas-listener-create = neutronclient.neutron.v2_0.lb.v2.listener:CreateListener - lbaas-listener-update = neutronclient.neutron.v2_0.lb.v2.listener:UpdateListener - lbaas-listener-delete = neutronclient.neutron.v2_0.lb.v2.listener:DeleteListener - lbaas-l7policy-list = neutronclient.neutron.v2_0.lb.v2.l7policy:ListL7Policy - lbaas-l7policy-show = neutronclient.neutron.v2_0.lb.v2.l7policy:ShowL7Policy - lbaas-l7policy-create = neutronclient.neutron.v2_0.lb.v2.l7policy:CreateL7Policy - lbaas-l7policy-update = neutronclient.neutron.v2_0.lb.v2.l7policy:UpdateL7Policy - lbaas-l7policy-delete = neutronclient.neutron.v2_0.lb.v2.l7policy:DeleteL7Policy - lbaas-l7rule-list = neutronclient.neutron.v2_0.lb.v2.l7rule:ListL7Rule - lbaas-l7rule-show = neutronclient.neutron.v2_0.lb.v2.l7rule:ShowL7Rule - lbaas-l7rule-create = neutronclient.neutron.v2_0.lb.v2.l7rule:CreateL7Rule - lbaas-l7rule-update = neutronclient.neutron.v2_0.lb.v2.l7rule:UpdateL7Rule - lbaas-l7rule-delete = neutronclient.neutron.v2_0.lb.v2.l7rule:DeleteL7Rule - lbaas-pool-list = neutronclient.neutron.v2_0.lb.v2.pool:ListPool - lbaas-pool-show = neutronclient.neutron.v2_0.lb.v2.pool:ShowPool - lbaas-pool-create = neutronclient.neutron.v2_0.lb.v2.pool:CreatePool - lbaas-pool-update = neutronclient.neutron.v2_0.lb.v2.pool:UpdatePool - lbaas-pool-delete = neutronclient.neutron.v2_0.lb.v2.pool:DeletePool - lbaas-healthmonitor-list = neutronclient.neutron.v2_0.lb.v2.healthmonitor:ListHealthMonitor - lbaas-healthmonitor-show = neutronclient.neutron.v2_0.lb.v2.healthmonitor:ShowHealthMonitor - lbaas-healthmonitor-create = neutronclient.neutron.v2_0.lb.v2.healthmonitor:CreateHealthMonitor - lbaas-healthmonitor-update = neutronclient.neutron.v2_0.lb.v2.healthmonitor:UpdateHealthMonitor - lbaas-healthmonitor-delete = neutronclient.neutron.v2_0.lb.v2.healthmonitor:DeleteHealthMonitor - lbaas-member-list = neutronclient.neutron.v2_0.lb.v2.member:ListMember - lbaas-member-show = neutronclient.neutron.v2_0.lb.v2.member:ShowMember - lbaas-member-create = neutronclient.neutron.v2_0.lb.v2.member:CreateMember - lbaas-member-update = neutronclient.neutron.v2_0.lb.v2.member:UpdateMember - lbaas-member-delete = neutronclient.neutron.v2_0.lb.v2.member:DeleteMember - - lb-vip-list = neutronclient.neutron.v2_0.lb.vip:ListVip - lb-vip-show = neutronclient.neutron.v2_0.lb.vip:ShowVip - lb-vip-create = neutronclient.neutron.v2_0.lb.vip:CreateVip - lb-vip-update = neutronclient.neutron.v2_0.lb.vip:UpdateVip - lb-vip-delete = neutronclient.neutron.v2_0.lb.vip:DeleteVip - lb-pool-list = neutronclient.neutron.v2_0.lb.pool:ListPool - lb-pool-show = neutronclient.neutron.v2_0.lb.pool:ShowPool - lb-pool-create = neutronclient.neutron.v2_0.lb.pool:CreatePool - lb-pool-update = neutronclient.neutron.v2_0.lb.pool:UpdatePool - lb-pool-delete = neutronclient.neutron.v2_0.lb.pool:DeletePool - lb-pool-stats = neutronclient.neutron.v2_0.lb.pool:RetrievePoolStats - lb-member-list = neutronclient.neutron.v2_0.lb.member:ListMember - lb-member-show = neutronclient.neutron.v2_0.lb.member:ShowMember - lb-member-create = neutronclient.neutron.v2_0.lb.member:CreateMember - lb-member-update = neutronclient.neutron.v2_0.lb.member:UpdateMember - lb-member-delete = neutronclient.neutron.v2_0.lb.member:DeleteMember - lb-healthmonitor-list = neutronclient.neutron.v2_0.lb.healthmonitor:ListHealthMonitor - lb-healthmonitor-show = neutronclient.neutron.v2_0.lb.healthmonitor:ShowHealthMonitor - lb-healthmonitor-create = neutronclient.neutron.v2_0.lb.healthmonitor:CreateHealthMonitor - lb-healthmonitor-update = neutronclient.neutron.v2_0.lb.healthmonitor:UpdateHealthMonitor - lb-healthmonitor-delete = neutronclient.neutron.v2_0.lb.healthmonitor:DeleteHealthMonitor - lb-healthmonitor-associate = neutronclient.neutron.v2_0.lb.healthmonitor:AssociateHealthMonitor - lb-healthmonitor-disassociate = neutronclient.neutron.v2_0.lb.healthmonitor:DisassociateHealthMonitor - - ipsec-site-connection-list = neutronclient.neutron.v2_0.vpn.ipsec_site_connection:ListIPsecSiteConnection - ipsec-site-connection-show = neutronclient.neutron.v2_0.vpn.ipsec_site_connection:ShowIPsecSiteConnection - ipsec-site-connection-create = neutronclient.neutron.v2_0.vpn.ipsec_site_connection:CreateIPsecSiteConnection - ipsec-site-connection-update = neutronclient.neutron.v2_0.vpn.ipsec_site_connection:UpdateIPsecSiteConnection - ipsec-site-connection-delete = neutronclient.neutron.v2_0.vpn.ipsec_site_connection:DeleteIPsecSiteConnection - vpn-endpoint-group-list = neutronclient.neutron.v2_0.vpn.endpoint_group:ListEndpointGroup - vpn-endpoint-group-show = neutronclient.neutron.v2_0.vpn.endpoint_group:ShowEndpointGroup - vpn-endpoint-group-create = neutronclient.neutron.v2_0.vpn.endpoint_group:CreateEndpointGroup - vpn-endpoint-group-update = neutronclient.neutron.v2_0.vpn.endpoint_group:UpdateEndpointGroup - vpn-endpoint-group-delete = neutronclient.neutron.v2_0.vpn.endpoint_group:DeleteEndpointGroup - vpn-service-list = neutronclient.neutron.v2_0.vpn.vpnservice:ListVPNService - vpn-service-show = neutronclient.neutron.v2_0.vpn.vpnservice:ShowVPNService - vpn-service-create = neutronclient.neutron.v2_0.vpn.vpnservice:CreateVPNService - vpn-service-update = neutronclient.neutron.v2_0.vpn.vpnservice:UpdateVPNService - vpn-service-delete = neutronclient.neutron.v2_0.vpn.vpnservice:DeleteVPNService - vpn-ipsecpolicy-list = neutronclient.neutron.v2_0.vpn.ipsecpolicy:ListIPsecPolicy - vpn-ipsecpolicy-show = neutronclient.neutron.v2_0.vpn.ipsecpolicy:ShowIPsecPolicy - vpn-ipsecpolicy-create = neutronclient.neutron.v2_0.vpn.ipsecpolicy:CreateIPsecPolicy - vpn-ipsecpolicy-update = neutronclient.neutron.v2_0.vpn.ipsecpolicy:UpdateIPsecPolicy - vpn-ipsecpolicy-delete = neutronclient.neutron.v2_0.vpn.ipsecpolicy:DeleteIPsecPolicy - vpn-ikepolicy-list = neutronclient.neutron.v2_0.vpn.ikepolicy:ListIKEPolicy - vpn-ikepolicy-show = neutronclient.neutron.v2_0.vpn.ikepolicy:ShowIKEPolicy - vpn-ikepolicy-create = neutronclient.neutron.v2_0.vpn.ikepolicy:CreateIKEPolicy - vpn-ikepolicy-update = neutronclient.neutron.v2_0.vpn.ikepolicy:UpdateIKEPolicy - vpn-ikepolicy-delete = neutronclient.neutron.v2_0.vpn.ikepolicy:DeleteIKEPolicy diff --git a/tools/neutron.bash_completion b/tools/neutron.bash_completion deleted file mode 100644 index 15ed41776..000000000 --- a/tools/neutron.bash_completion +++ /dev/null @@ -1,27 +0,0 @@ -_neutron_opts="" # lazy init -_neutron_flags="" # lazy init -_neutron_opts_exp="" # lazy init -_neutron() -{ - local cur prev nbc cflags - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - - if [ "x$_neutron_opts" == "x" ] ; then - nbc="`neutron bash-completion`" - _neutron_opts="`echo "$nbc" | sed -e "s/--[a-z0-9_-]*//g" -e "s/[ ][ ]*/ /g"`" - _neutron_flags="`echo " $nbc" | sed -e "s/ [^-][^-][a-z0-9_-]*//g" -e "s/[ ][ ]*/ /g"`" - _neutron_opts_exp="`echo "$_neutron_opts" | sed -e "s/[ ]/|/g"`" - fi - - if [[ " ${COMP_WORDS[@]} " =~ " "($_neutron_opts_exp)" " && "$prev" != "help" ]] ; then - COMPLETION_CACHE=~/.neutronclient/*/*-cache - cflags="$_neutron_flags "$(cat $COMPLETION_CACHE 2> /dev/null | tr '\n' ' ') - COMPREPLY=($(compgen -W "${cflags}" -- ${cur})) - else - COMPREPLY=($(compgen -W "${_neutron_opts}" -- ${cur})) - fi - return 0 -} -complete -F _neutron neutron diff --git a/tox.ini b/tox.ini index 06f5829f6..afdf530e2 100644 --- a/tox.ini +++ b/tox.ini @@ -33,11 +33,6 @@ distribute = false [testenv:venv] commands = {posargs} -[testenv:functional] -setenv = - OS_TEST_PATH = ./neutronclient/tests/functional - OS_NEUTRONCLIENT_EXEC_DIR = {envdir}/bin - [testenv:cover] setenv = {[testenv]setenv} From 79c7de463051a5ac832dd26057b5e3710f5ea19a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 17 May 2023 13:03:51 +0100 Subject: [PATCH 108/149] Remove 'bgp speaker show dragents' This has been deprecated for ages and generates an annoying warning when building OSC docs. Time to cull it. Change-Id: I76e4c7ab742d0bf27fecfda8fab41035618a4e24 Signed-off-by: Stephen Finucane --- doc/source/cli/osc/v2/bgp-dynamic-routing.rst | 3 -- .../osc/v2/dynamic_routing/bgp_dragent.py | 49 ------------------- .../v2/dynamic_routing/test_bgp_dragent.py | 41 ---------------- ...peaker-show-dragents-0a0db4b72b2feffc.yaml | 6 +++ setup.cfg | 1 - 5 files changed, 6 insertions(+), 94 deletions(-) create mode 100644 releasenotes/notes/remove-bgp-speaker-show-dragents-0a0db4b72b2feffc.yaml diff --git a/doc/source/cli/osc/v2/bgp-dynamic-routing.rst b/doc/source/cli/osc/v2/bgp-dynamic-routing.rst index 6d712809f..c86bb45ee 100644 --- a/doc/source/cli/osc/v2/bgp-dynamic-routing.rst +++ b/doc/source/cli/osc/v2/bgp-dynamic-routing.rst @@ -25,9 +25,6 @@ Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker show -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgp speaker show dragents - .. autoprogram-cliff:: openstack.neutronclient.v2 :command: bgp speaker add network diff --git a/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py b/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py index 4af2008fe..91dc2a75b 100644 --- a/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py +++ b/neutronclient/osc/v2/dynamic_routing/bgp_dragent.py @@ -65,55 +65,6 @@ def take_action(self, parsed_args): speaker_id) -class ListDRAgentsHostingBgpSpeaker(command.Lister): - """(Deprecated) List dynamic routing agents hosting a BGP speaker - - (Use "bgp dragent list" instead) - """ - - resource = 'agent' - list_columns = ['id', 'host', 'admin_state_up', 'alive'] - unknown_parts_flag = False - - def get_parser(self, prog_name): - self.log.warning("The 'openstack bgp speaker show dragents' CLI is " - "deprecated and will be removed in the future. Use " - "'openstack bgp dragent list' CLI instead.") - parser = super(ListDRAgentsHostingBgpSpeaker, - self).get_parser(prog_name) - parser.add_argument('bgp_speaker', - metavar='', - help=_("List dynamic routing agents hosting a " - "BGP speaker (name or ID)")) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - speaker_id = client.find_bgp_speaker(parsed_args.bgp_speaker).id - data = client.get_bgp_dragents_hosting_speaker(speaker_id) - columns = ( - 'id', - 'agent_type', - 'host', - 'availability_zone', - 'is_alive', - 'is_admin_state_up', - 'binary' - ) - column_headers = ( - 'ID', - 'Agent Type', - 'Host', - 'Availability Zone', - 'Alive', - 'State', - 'Binary' - ) - return (column_headers, - (utils.get_item_properties( - s, columns,) for s in data)) - - class ListDRAgent(command.Lister): """List dynamic routing agents""" diff --git a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py index 89ba20d93..6842cbbd1 100644 --- a/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py +++ b/neutronclient/tests/unit/osc/v2/dynamic_routing/test_bgp_dragent.py @@ -82,44 +82,3 @@ def test_remove_bgp_speaker_from_dragent(self): assert_called_once_with(self._bgp_dragent_id, self._bgp_speaker_id) self.assertIsNone(result) - - -class TestListDRAgentsHostingBgpSpeaker(fakes.TestNeutronDynamicRoutingOSCV2): - _bgp_speaker = fakes.FakeBgpSpeaker.create_one_bgp_speaker() - _bgp_speaker_id = _bgp_speaker['id'] - attrs = {'bgp_speaker_id': _bgp_speaker_id} - _bgp_dragents = fakes.FakeDRAgent.create_dragents(attrs) - columns = ('ID', 'Agent Type', 'Host', 'Availability Zone', - 'Alive', 'State', 'Binary') - data = [(_bgp_dragent['id'], - _bgp_dragent['agent_type'], - _bgp_dragent['host'], - _bgp_dragent['availability_zone'], - _bgp_dragent['admin_state_up'], - _bgp_dragent['alive'], - _bgp_dragent['binary'],) - for _bgp_dragent in _bgp_dragents] - - def setUp(self): - super(TestListDRAgentsHostingBgpSpeaker, self).setUp() - - # Get the command object to test - self.cmd = bgp_dragent.ListDRAgent(self.app, self.namespace) - - def test_list_dragents_hosting_bgp_speaker(self): - arglist = [ - '--bgp-speaker', self._bgp_speaker_id, - ] - verifylist = [ - ('bgp_speaker', self._bgp_speaker_id), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - with mock.patch.object(self.networkclient, - "get_bgp_dragents_hosting_speaker", - return_value=self._bgp_dragents): - columns, data = self.cmd.take_action(parsed_args) - self.networkclient.get_bgp_dragents_hosting_speaker.\ - assert_called_once_with(self._bgp_speaker_id) - self.assertEqual(self.columns, columns) - self.assertListEqual(self.data, list(data)) diff --git a/releasenotes/notes/remove-bgp-speaker-show-dragents-0a0db4b72b2feffc.yaml b/releasenotes/notes/remove-bgp-speaker-show-dragents-0a0db4b72b2feffc.yaml new file mode 100644 index 000000000..5d4fdda2c --- /dev/null +++ b/releasenotes/notes/remove-bgp-speaker-show-dragents-0a0db4b72b2feffc.yaml @@ -0,0 +1,6 @@ +--- +upgrade: + - | + The ``openstack bgp speaker show dragents`` CLI is removed. It was + deprecated in the 7.1.0 release (Ussuri). Use ``openstack bgp dragent list + --bgp-speaker `` CLI instead. diff --git a/setup.cfg b/setup.cfg index 3bab0a176..7af675d1d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -76,7 +76,6 @@ openstack.neutronclient.v2 = bgp_speaker_remove_peer = neutronclient.osc.v2.dynamic_routing.bgp_speaker:RemovePeerFromSpeaker bgp_speaker_set = neutronclient.osc.v2.dynamic_routing.bgp_speaker:SetBgpSpeaker bgp_speaker_show = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ShowBgpSpeaker - bgp_speaker_show_dragents = neutronclient.osc.v2.dynamic_routing.bgp_dragent:ListDRAgentsHostingBgpSpeaker firewall_group_create = neutronclient.osc.v2.fwaas.firewallgroup:CreateFirewallGroup firewall_group_delete = neutronclient.osc.v2.fwaas.firewallgroup:DeleteFirewallGroup From d4124aed1ff260eb108b0433cc54625d93ead0d3 Mon Sep 17 00:00:00 2001 From: elajkat Date: Tue, 28 Feb 2023 10:06:23 +0100 Subject: [PATCH 109/149] OSC: Remove BGPVPN calls to neutronclient With [1] the python binding code in Neutronclient prints warning about future deprecation, change networking-bgpvpn osc client code to use totally OpenstackSDK. [1]: https://review.opendev.org/c/openstack/python-neutronclient/+/862371 Change-Id: Iae1378ffabda3d30257e35a6148e205a9f495eb5 Related-Bug: #1999774 Depends-On: https://review.opendev.org/c/openstack/openstacksdk/+/875530 --- .../osc/v2/networking_bgpvpn/bgpvpn.py | 42 ++-- .../v2/networking_bgpvpn/port_association.py | 13 +- .../networking_bgpvpn/resource_association.py | 77 +++---- .../networking_bgpvpn/router_association.py | 5 +- .../unit/osc/v2/networking_bgpvpn/fakes.py | 212 ++++++++++-------- .../osc/v2/networking_bgpvpn/test_bgpvpn.py | 160 +++++++------ .../test_resource_association.py | 131 ++++++----- .../test_router_association.py | 105 ++++----- requirements.txt | 2 +- 9 files changed, 390 insertions(+), 357 deletions(-) diff --git a/neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py b/neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py index 58c9e8a43..cf4c69d66 100644 --- a/neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py +++ b/neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py @@ -25,13 +25,12 @@ from neutronclient._i18n import _ from neutronclient.osc import utils as nc_osc_utils -from neutronclient.osc.v2.networking_bgpvpn import constants LOG = logging.getLogger(__name__) _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), + ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('name', 'Name', column_util.LIST_BOTH), ('type', 'Type', column_util.LIST_BOTH), ('route_targets', 'Route Targets', column_util.LIST_LONG_ONLY), @@ -166,7 +165,7 @@ def _args2body(client_manager, id, action, args): args.purge_export_target and args.purge_route_distinguisher) and (args.route_targets or args.import_targets or args.export_targets or args.route_distinguishers)): - bgpvpn = client_manager.neutronclient.show_bgpvpn(id)['bgpvpn'] + bgpvpn = client_manager.network.get_bgpvpn(id) attrs = {} @@ -221,7 +220,7 @@ def _args2body(client_manager, id, action, args): set(bgpvpn['route_distinguishers']) - set(args.route_distinguishers)) - return {constants.BGPVPN: attrs} + return attrs class CreateBgpvpn(command.ShowOne): @@ -241,7 +240,7 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = {} if parsed_args.name is not None: attrs['name'] = str(parsed_args.name) @@ -266,9 +265,8 @@ def take_action(self, parsed_args): parsed_args.project_domain, ).id attrs['tenant_id'] = project_id - body = {constants.BGPVPN: attrs} - obj = client.create_bgpvpn(body)[constants.BGPVPN] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_bgpvpn(**attrs) + display_columns, columns = nc_osc_utils._get_columns(obj) data = osc_utils.get_dict_properties(obj, columns, formatters=_formatters) return display_columns, data @@ -288,10 +286,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGPVPN, parsed_args.bgpvpn)['id'] + client = self.app.client_manager.network + id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] body = _args2body(self.app.client_manager, id, 'set', parsed_args) - client.update_bgpvpn(id, body) + client.update_bgpvpn(id, **body) class UnsetBgpvpn(command.Command): @@ -308,10 +306,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGPVPN, parsed_args.bgpvpn)['id'] + client = self.app.client_manager.network + id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] body = _args2body(self.app.client_manager, id, 'unset', parsed_args) - client.update_bgpvpn(id, body) + client.update_bgpvpn(id, **body) class DeleteBgpvpn(command.Command): @@ -328,11 +326,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network fails = 0 for id_or_name in parsed_args.bgpvpns: try: - id = client.find_resource(constants.BGPVPN, id_or_name)['id'] + id = client.find_bgpvpn(id_or_name)['id'] client.delete_bgpvpn(id) LOG.warning("BGP VPN %(id)s deleted", {'id': id}) except Exception as e: @@ -368,7 +366,7 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network params = {} if parsed_args.project is not None: project_id = nc_osc_utils.find_project( @@ -379,7 +377,7 @@ def take_action(self, parsed_args): params['tenant_id'] = project_id if parsed_args.property: params.update(parsed_args.property) - objs = client.list_bgpvpns(**params)[constants.BGPVPNS] + objs = client.bgpvpns(**params) headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (osc_utils.get_dict_properties( @@ -399,10 +397,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = client.find_resource(constants.BGPVPN, parsed_args.bgpvpn)['id'] - obj = client.show_bgpvpn(id)[constants.BGPVPN] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] + obj = client.get_bgpvpn(id) + display_columns, columns = nc_osc_utils._get_columns(obj) data = osc_utils.get_dict_properties(obj, columns, formatters=_formatters) return display_columns, data diff --git a/neutronclient/osc/v2/networking_bgpvpn/port_association.py b/neutronclient/osc/v2/networking_bgpvpn/port_association.py index abf82ab72..24cd2d207 100644 --- a/neutronclient/osc/v2/networking_bgpvpn/port_association.py +++ b/neutronclient/osc/v2/networking_bgpvpn/port_association.py @@ -108,6 +108,7 @@ def _transform_resource(self, data): LOG.warning("Unknown route type %s (%s).", route['type'], route) data.pop('routes', None) + return data def _get_common_parser(self, parser): """Adds to parser arguments common to create, set and unset commands. @@ -201,15 +202,13 @@ def _get_common_parser(self, parser): ) def _args2body(self, bgpvpn_id, args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = {} if self._action != 'create': - assoc = client.find_resource_by_id( - self._resource, + assoc = client.find_bgpvpn_port_association( args.resource_association_id, - cmd_resource='bgpvpn_%s_assoc' % self._assoc_res_name, - parent_id=bgpvpn_id) + bgpvpn_id=bgpvpn_id) else: assoc = {'routes': []} @@ -248,7 +247,7 @@ def _args2body(self, bgpvpn_id, args): else: routes = args.bgpvpn_routes args_bgpvpn_routes = { - client.find_resource(constants.BGPVPN, r['bgpvpn'])['id']: + client.find_bgpvpn(r['bgpvpn']).id: r.get('local_pref') for r in routes } @@ -281,7 +280,7 @@ def _args2body(self, bgpvpn_id, args): route['local_pref'] = int(local_pref) attrs.setdefault('routes', []).append(route) - return {self._resource: attrs} + return attrs class CreateBgpvpnPortAssoc(BgpvpnPortAssoc, diff --git a/neutronclient/osc/v2/networking_bgpvpn/resource_association.py b/neutronclient/osc/v2/networking_bgpvpn/resource_association.py index 96c559b24..f5a0804dc 100644 --- a/neutronclient/osc/v2/networking_bgpvpn/resource_association.py +++ b/neutronclient/osc/v2/networking_bgpvpn/resource_association.py @@ -24,7 +24,6 @@ from neutronclient._i18n import _ from neutronclient.osc import utils as nc_osc_utils -from neutronclient.osc.v2.networking_bgpvpn import constants LOG = logging.getLogger(__name__) @@ -56,35 +55,32 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network create_method = getattr( - client, 'create_bgpvpn_%s_assoc' % self._assoc_res_name) - bgpvpn = client.find_resource(constants.BGPVPN, parsed_args.bgpvpn) - assoc_res = client.find_resource(self._assoc_res_name, - parsed_args.resource) - body = { - self._resource: { - '%s_id' % self._assoc_res_name: assoc_res['id'], - }, - } + client, 'create_bgpvpn_%s_association' % self._assoc_res_name) + bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) + find_res_method = getattr( + client, 'find_%s' % self._assoc_res_name) + assoc_res = find_res_method(parsed_args.resource) + body = {'%s_id' % self._assoc_res_name: assoc_res['id']} if 'project' in parsed_args and parsed_args.project is not None: project_id = nc_osc_utils.find_project( self.app.client_manager.identity, parsed_args.project, parsed_args.project_domain, ).id - body[self._resource]['tenant_id'] = project_id + body['tenant_id'] = project_id arg2body = getattr(self, '_args2body', None) if callable(arg2body): - body[self._resource].update( - arg2body(bgpvpn['id'], parsed_args)[self._resource]) + body.update( + arg2body(bgpvpn['id'], parsed_args)) - obj = create_method(bgpvpn['id'], body)[self._resource] + obj = create_method(bgpvpn['id'], **body) transform = getattr(self, '_transform_resource', None) if callable(transform): transform(obj) - columns, display_columns = column_util.get_columns(obj, self._attr_map) + display_columns, columns = nc_osc_utils._get_columns(obj) data = osc_utils.get_dict_properties(obj, columns, formatters=self._formatters) return display_columns, data @@ -116,15 +112,15 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network update_method = getattr( - client, 'update_bgpvpn_%s_assoc' % self._assoc_res_name) - bgpvpn = client.find_resource(constants.BGPVPN, parsed_args.bgpvpn) + client, 'update_bgpvpn_%s_association' % self._assoc_res_name) + bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) arg2body = getattr(self, '_args2body', None) if callable(arg2body): body = arg2body(bgpvpn['id'], parsed_args) update_method(bgpvpn['id'], parsed_args.resource_association_id, - body) + **body) class UnsetBgpvpnResAssoc(SetBgpvpnResAssoc): @@ -153,10 +149,10 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network delete_method = getattr( - client, 'delete_bgpvpn_%s_assoc' % self._assoc_res_name) - bgpvpn = client.find_resource(constants.BGPVPN, parsed_args.bgpvpn) + client, 'delete_bgpvpn_%s_association' % self._assoc_res_name) + bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) fails = 0 for id in parsed_args.resource_association_ids: try: @@ -206,22 +202,27 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network list_method = getattr(client, - 'list_bgpvpn_%s_assocs' % self._assoc_res_name) - bgpvpn = client.find_resource(constants.BGPVPN, parsed_args.bgpvpn) + 'bgpvpn_%s_associations' % self._assoc_res_name) + bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) params = {} if parsed_args.property: params.update(parsed_args.property) objs = list_method(bgpvpn['id'], - retrieve_all=True, **params)[self._resource_plural] + retrieve_all=True, **params) transform = getattr(self, '_transform_resource', None) + transformed_objs = [] if callable(transform): - [transform(obj) for obj in objs] + for obj in objs: + transformed_objs.append(transform(obj)) + else: + transformed_objs = list(objs) headers, columns = column_util.get_column_definitions( self._attr_map, long_listing=parsed_args.long) return (headers, (osc_utils.get_dict_properties( - s, columns, formatters=self._formatters) for s in objs)) + s, columns, formatters=self._formatters) + for s in transformed_objs)) class ShowBgpvpnResAssoc(command.ShowOne): @@ -243,20 +244,16 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - show_method = getattr(client, - 'show_bgpvpn_%s_assoc' % self._assoc_res_name) - bgpvpn = client.find_resource(constants.BGPVPN, parsed_args.bgpvpn) - assoc = client.find_resource_by_id( - self._resource, - parsed_args.resource_association_id, - cmd_resource='bgpvpn_%s_assoc' % self._assoc_res_name, - parent_id=bgpvpn['id']) - obj = show_method(bgpvpn['id'], assoc['id'])[self._resource] + client = self.app.client_manager.network + show_method = getattr( + client, 'get_bgpvpn_%s_association' % self._assoc_res_name) + bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) + obj = show_method(bgpvpn['id'], + parsed_args.resource_association_id) transform = getattr(self, '_transform_resource', None) if callable(transform): transform(obj) - columns, display_columns = column_util.get_columns(obj, self._attr_map) + display_columns, columns = nc_osc_utils._get_columns(obj) data = osc_utils.get_dict_properties(obj, columns, formatters=self._formatters) return display_columns, data diff --git a/neutronclient/osc/v2/networking_bgpvpn/router_association.py b/neutronclient/osc/v2/networking_bgpvpn/router_association.py index c382f1621..f4cdde09c 100644 --- a/neutronclient/osc/v2/networking_bgpvpn/router_association.py +++ b/neutronclient/osc/v2/networking_bgpvpn/router_association.py @@ -75,14 +75,13 @@ def _get_common_parser(self, parser): ) def _args2body(self, _, args): - attrs = {} - + attrs = {'advertise_extra_routes': False} if args.advertise_extra_routes: attrs['advertise_extra_routes'] = self._action != 'unset' elif args.no_advertise_extra_routes: attrs['advertise_extra_routes'] = self._action == 'unset' - return {self._resource: attrs} + return attrs class CreateBgpvpnRouterAssoc(BgpvpnRouterAssoc, CreateBgpvpnResAssoc): diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py index a0b2cb892..0a2c3fe9c 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py @@ -17,10 +17,11 @@ import copy from unittest import mock +from openstack.network.v2 import bgpvpn as _bgpvpn +from openstack import resource as sdk_resource from osc_lib.utils import columns as column_util from neutronclient.osc import utils as nc_osc_utils -from neutronclient.osc.v2.networking_bgpvpn import constants from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ CreateBgpvpnResAssoc from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ @@ -61,50 +62,45 @@ def setUp(self): side_effect=lambda _, name_or_id, __: mock.Mock(id=name_or_id)) -class FakeBgpvpn(object): - """Fake BGP VPN with attributes.""" - - @staticmethod - def create_one_bgpvpn(attrs=None): - """Create a fake BGP VPN.""" - - attrs = attrs or {} - - # Set default attributes. - bgpvpn_attrs = { - 'id': 'fake_bgpvpn_id', - 'tenant_id': _FAKE_PROJECT_ID, - 'name': '', - 'type': 'l3', - 'route_targets': [], - 'import_targets': [], - 'export_targets': [], - 'route_distinguishers': [], - 'networks': [], - 'routers': [], - 'ports': [], - 'vni': 100, - 'local_pref': 777, - } +def create_one_bgpvpn(attrs=None): + """Create a fake BGP VPN.""" + + attrs = attrs or {} - # Overwrite default attributes. - bgpvpn_attrs.update(attrs) + # Set default attributes. + bgpvpn_attrs = { + 'id': 'fake_bgpvpn_id', + 'tenant_id': _FAKE_PROJECT_ID, + 'name': '', + 'type': 'l3', + 'route_targets': [], + 'import_targets': [], + 'export_targets': [], + 'route_distinguishers': [], + 'networks': [], + 'routers': [], + 'ports': [], + 'vni': 100, + 'local_pref': 777, + } - return copy.deepcopy(bgpvpn_attrs) + # Overwrite default attributes. + bgpvpn_attrs.update(attrs) + return _bgpvpn.BgpVpn(**bgpvpn_attrs) - @staticmethod - def create_bgpvpns(attrs=None, count=1): - """Create multiple fake BGP VPN.""" - bgpvpns = [] - for i in range(0, count): - if attrs is None: - attrs = {'id': 'fake_id%d' % i} - elif getattr(attrs, 'id', None) is None: - attrs['id'] = 'fake_id%d' % i - bgpvpns.append(FakeBgpvpn.create_one_bgpvpn(attrs)) +def create_bgpvpns(attrs=None, count=1): + """Create multiple fake BGP VPN.""" - return {constants.BGPVPNS: bgpvpns} + bgpvpns = [] + for i in range(0, count): + if attrs is None: + attrs = {'id': 'fake_id%d' % i} + elif getattr(attrs, 'id', None) is None: + attrs['id'] = 'fake_id%d' % i + bgpvpns.append(create_one_bgpvpn(attrs)) + + return bgpvpns class BgpvpnFakeAssoc(object): @@ -114,9 +110,10 @@ class BgpvpnFakeAssoc(object): _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), column_util.LIST_BOTH), + ('name', 'Name', column_util.LIST_BOTH), + ('project_id', 'Project ID', column_util.LIST_BOTH), ) _formatters = {} @@ -152,11 +149,12 @@ class BgpvpnFakeRouterAssoc(object): _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), column_util.LIST_BOTH), ('advertise_extra_routes', 'Advertise extra routes', column_util.LIST_LONG_ONLY), + ('name', 'Name', column_util.LIST_BOTH), + ('project_id', 'Project ID', column_util.LIST_BOTH), ) _formatters = {} @@ -174,71 +172,99 @@ class ShowBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, ShowBgpvpnRouterAssoc): pass -class FakeResource(object): - """Fake resource with minimal attributes.""" +class FakeResource(sdk_resource.Resource): + resource_key = 'fakeresource' + resources_key = 'fakeresources' + base_path = '/bgpvpn/fakeresources' - @staticmethod - def create_one_resource(attrs=None): - """Create a fake resource.""" + _allow_unknown_attrs_in_body = True - attrs = attrs or {} + # capabilities + allow_create = True + allow_fetch = True + allow_commit = True + allow_delete = True + allow_list = True - # Set default attributes. - res_attrs = { - 'id': 'fake_resource_id', - 'tenant_id': _FAKE_PROJECT_ID, - } + id = sdk_resource.Body('id') + tenant_id = sdk_resource.Body('tenant_id', deprecated=True) + project_id = sdk_resource.Body('project_id', alias='tenant_id') + + +class FakeResoureAssociation(sdk_resource.Resource): + resource_key = 'fakeresourceassociation' + resources_key = 'fakeresourceassociations' + base_path = '/bgpvpn/fakeresourceassociations' + + _allow_unknown_attrs_in_body = True + + # capabilities + allow_create = True + allow_fetch = True + allow_commit = True + allow_delete = True + allow_list = True + + id = sdk_resource.Body('id') + tenant_id = sdk_resource.Body('tenant_id', deprecated=True) + project_id = sdk_resource.Body('project_id', alias='tenant_id') + + +def create_one_resource(attrs=None): + """Create a fake resource.""" + attrs = attrs or {} + + # Set default attributes. + res_attrs = { + 'id': 'fake_resource_id', + 'tenant_id': _FAKE_PROJECT_ID, + } + + # Overwrite default attributes. + res_attrs.update(attrs) + return FakeResource(**res_attrs) + + +def create_resources(attrs=None, count=1): + """Create multiple fake resources.""" + + resources = [] + for i in range(0, count): + if attrs is None: + attrs = {'id': 'fake_id%d' % i} + elif getattr(attrs, 'id', None) is None: + attrs['id'] = 'fake_id%d' % i + resources.append(create_one_resource(attrs)) - # Overwrite default attributes. - res_attrs.update(attrs) - return copy.deepcopy(res_attrs) + return resources - @staticmethod - def create_resources(attrs=None, count=1): - """Create multiple fake resources.""" - resources = [] - for i in range(0, count): - if attrs is None: - attrs = {'id': 'fake_id%d' % i} - elif getattr(attrs, 'id', None) is None: - attrs['id'] = 'fake_id%d' % i - resources.append(FakeResource.create_one_resource(attrs)) +def create_one_resource_association(resource, attrs=None): + """Create a fake resource association.""" - return {'%ss' % BgpvpnFakeAssoc._assoc_res_name: resources} + attrs = attrs or {} + res_assoc_attrs = { + 'id': 'fake_association_id', + 'tenant_id': resource['tenant_id'], + 'fake_resource_id': resource['id'], + } -class FakeResAssoc(object): - """Fake resource association with minimal attributes.""" + # Overwrite default attributes. + res_assoc_attrs.update(attrs) + return FakeResoureAssociation(**res_assoc_attrs) - @staticmethod - def create_one_resource_association(resource, attrs=None): - """Create a fake resource association.""" - attrs = attrs or {} +def create_resource_associations(resources): + """Create multiple fake resource associations.""" + res_assocs = [] + for idx, resource in enumerate(resources): res_assoc_attrs = { - 'id': 'fake_association_id', + 'id': 'fake_association_id%d' % idx, 'tenant_id': resource['tenant_id'], 'fake_resource_id': resource['id'], } + res_assocs.append(copy.deepcopy(res_assoc_attrs)) - # Overwrite default attributes. - res_assoc_attrs.update(attrs) - return copy.deepcopy(res_assoc_attrs) - - @staticmethod - def create_resource_associations(resources): - """Create multiple fake resource associations.""" - - res_assocs = [] - for idx, resource in enumerate( - resources['%ss' % BgpvpnFakeAssoc._assoc_res_name]): - res_assoc_attrs = { - 'id': 'fake_association_id%d' % idx, - 'tenant_id': resource['tenant_id'], - 'fake_resource_id': resource['id'], - } - res_assocs.append(copy.deepcopy(res_assoc_attrs)) - - return {BgpvpnFakeAssoc._resource_plural: res_assocs} + return res_assocs diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py index 16fb164ae..3f1632027 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py @@ -23,7 +23,6 @@ from osc_lib.utils import columns as column_util from neutronclient.osc.v2.networking_bgpvpn import bgpvpn -from neutronclient.osc.v2.networking_bgpvpn import constants from neutronclient.tests.unit.osc.v2.networking_bgpvpn import fakes @@ -55,9 +54,9 @@ def setUp(self): self.cmd = bgpvpn.CreateBgpvpn(self.app, self.namespace) def test_create_bgpvpn_with_no_args(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - self.neutronclient.create_bgpvpn = mock.Mock( - return_value={constants.BGPVPN: fake_bgpvpn}) + fake_bgpvpn = fakes.create_one_bgpvpn() + self.networkclient.create_bgpvpn = mock.Mock( + return_value=fake_bgpvpn) arglist = [] verifylist = [ ('project', None), @@ -75,10 +74,10 @@ def test_create_bgpvpn_with_no_args(self): cols, data = self.cmd.take_action(parsed_args) - self.neutronclient.create_bgpvpn.assert_called_once_with( - {constants.BGPVPN: {'type': 'l3'}}) - self.assertEqual(sorted_headers, cols) - self.assertItemEqual(_get_data(fake_bgpvpn), data) + self.networkclient.create_bgpvpn.assert_called_once_with( + **{'type': 'l3'}) + + self.assertEqual(sorted(sorted_columns), sorted(cols)) def test_create_bgpvpn_with_all_args(self): attrs = { @@ -92,9 +91,9 @@ def test_create_bgpvpn_with_all_args(self): 'export_targets': ['fake_ert1', 'fake_ert2', 'fake_ert3'], 'route_distinguishers': ['fake_rd1', 'fake_rd2', 'fake_rd3'], } - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn(attrs) - self.neutronclient.create_bgpvpn = mock.Mock( - return_value={constants.BGPVPN: fake_bgpvpn}) + fake_bgpvpn = fakes.create_one_bgpvpn(attrs) + self.networkclient.create_bgpvpn = mock.Mock( + return_value=fake_bgpvpn) arglist = [ '--project', fake_bgpvpn['tenant_id'], '--name', fake_bgpvpn['name'], @@ -126,21 +125,18 @@ def test_create_bgpvpn_with_all_args(self): cols, data = self.cmd.take_action(parsed_args) - fake_bgpvpn_call = copy.deepcopy(fake_bgpvpn) - fake_bgpvpn_call.pop('id') - fake_bgpvpn_call.pop('networks') - fake_bgpvpn_call.pop('routers') - fake_bgpvpn_call.pop('ports') + fake_bgpvpn_call = copy.deepcopy(attrs) - self.neutronclient.create_bgpvpn.assert_called_once_with( - {constants.BGPVPN: fake_bgpvpn_call}) - self.assertEqual(sorted_headers, cols) - self.assertItemEqual(_get_data(fake_bgpvpn), data) + self.networkclient.create_bgpvpn.assert_called_once_with( + **fake_bgpvpn_call) + self.assertEqual(sorted(sorted_columns), sorted(cols)) class TestSetBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestSetBgpvpn, self).setUp() + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = bgpvpn.SetBgpvpn(self.app, self.namespace) def test_set_bgpvpn(self): @@ -150,10 +146,10 @@ def test_set_bgpvpn(self): 'export_targets': ['set_ert1', 'set_ert2', 'set_ert3'], 'route_distinguishers': ['set_rd1', 'set_rd2', 'set_rd3'], } - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn(attrs) - self.neutronclient.show_bgpvpn = mock.Mock( - return_value={constants.BGPVPN: fake_bgpvpn}) - self.neutronclient.update_bgpvpn = mock.Mock() + fake_bgpvpn = fakes.create_one_bgpvpn(attrs) + self.networkclient.get_bgpvpn = mock.Mock( + return_value=fake_bgpvpn) + self.networkclient.update_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], '--name', 'set_name', @@ -190,14 +186,14 @@ def test_set_bgpvpn(self): 'route_distinguishers': list( set(fake_bgpvpn['route_distinguishers']) | set(['set_rd1'])), } - self.neutronclient.update_bgpvpn.assert_called_once_with( - fake_bgpvpn['id'], {constants.BGPVPN: attrs}) + self.networkclient.update_bgpvpn.assert_called_once_with( + fake_bgpvpn['id'], **attrs) self.assertIsNone(result) def test_set_bgpvpn_with_purge_list(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - self.neutronclient.show_bgpvpn = mock.Mock( - return_value={constants.BGPVPN: fake_bgpvpn}) + fake_bgpvpn = fakes.create_one_bgpvpn() + self.networkclient.get_bgpvpn = mock.Mock( + return_value=fake_bgpvpn) self.neutronclient.update_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], @@ -232,14 +228,16 @@ def test_set_bgpvpn_with_purge_list(self): 'export_targets': [], 'route_distinguishers': [], } - self.neutronclient.update_bgpvpn.assert_called_once_with( - fake_bgpvpn['id'], {constants.BGPVPN: attrs}) + self.networkclient.update_bgpvpn.assert_called_once_with( + fake_bgpvpn['id'], **attrs) self.assertIsNone(result) class TestUnsetBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestUnsetBgpvpn, self).setUp() + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = bgpvpn.UnsetBgpvpn(self.app, self.namespace) def test_unset_bgpvpn(self): @@ -249,10 +247,10 @@ def test_unset_bgpvpn(self): 'export_targets': ['unset_ert1', 'unset_ert2', 'unset_ert3'], 'route_distinguishers': ['unset_rd1', 'unset_rd2', 'unset_rd3'], } - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn(attrs) - self.neutronclient.show_bgpvpn = mock.Mock( - return_value={constants.BGPVPN: fake_bgpvpn}) - self.neutronclient.update_bgpvpn = mock.Mock() + fake_bgpvpn = fakes.create_one_bgpvpn(attrs) + self.networkclient.get_bgpvpn = mock.Mock( + return_value=fake_bgpvpn) + self.networkclient.update_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], '--route-target', 'unset_rt1', @@ -286,14 +284,14 @@ def test_unset_bgpvpn(self): 'route_distinguishers': list( set(fake_bgpvpn['route_distinguishers']) - set(['unset_rd1'])), } - self.neutronclient.update_bgpvpn.assert_called_once_with( - fake_bgpvpn['id'], {constants.BGPVPN: attrs}) + self.networkclient.update_bgpvpn.assert_called_once_with( + fake_bgpvpn['id'], **attrs) self.assertIsNone(result) def test_unset_bgpvpn_with_purge_list(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - self.neutronclient.show_bgpvpn = mock.Mock( - return_value={constants.BGPVPN: fake_bgpvpn}) + fake_bgpvpn = fakes.create_one_bgpvpn() + self.networkclient.show_bgpvpn = mock.Mock( + return_value=fake_bgpvpn) self.neutronclient.update_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], @@ -328,21 +326,21 @@ def test_unset_bgpvpn_with_purge_list(self): 'export_targets': [], 'route_distinguishers': [], } - self.neutronclient.update_bgpvpn.assert_called_once_with( - fake_bgpvpn['id'], {constants.BGPVPN: attrs}) + self.networkclient.update_bgpvpn.assert_called_once_with( + fake_bgpvpn['id'], **attrs) self.assertIsNone(result) class TestDeleteBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestDeleteBgpvpn, self).setUp() - self.neutronclient.find_resource = mock.Mock( - side_effect=lambda _, name_or_id: {'id': name_or_id}) + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = bgpvpn.DeleteBgpvpn(self.app, self.namespace) def test_delete_one_bgpvpn(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - self.neutronclient.delete_bgpvpn = mock.Mock() + fake_bgpvpn = fakes.create_one_bgpvpn() + self.networkclient.delete_bgpvpn = mock.Mock() arglist = [ fake_bgpvpn['id'], ] @@ -354,15 +352,14 @@ def test_delete_one_bgpvpn(self): result = self.cmd.take_action(parsed_args) - self.neutronclient.delete_bgpvpn.assert_called_once_with( + self.networkclient.delete_bgpvpn.assert_called_once_with( fake_bgpvpn['id']) self.assertIsNone(result) def test_delete_multi_bpgvpn(self): - fake_bgpvpns = fakes.FakeBgpvpn.create_bgpvpns(count=3) - fake_bgpvpn_ids = [fake_bgpvpn['id'] for fake_bgpvpn in - fake_bgpvpns[constants.BGPVPNS]] - self.neutronclient.delete_bgpvpn = mock.Mock() + fake_bgpvpns = fakes.create_bgpvpns(count=3) + fake_bgpvpn_ids = [fake_bgpvpn['id'] for fake_bgpvpn in fake_bgpvpns] + self.networkclient.delete_bgpvpn = mock.Mock() arglist = fake_bgpvpn_ids verifylist = [ ('bgpvpns', fake_bgpvpn_ids), @@ -372,20 +369,19 @@ def test_delete_multi_bpgvpn(self): result = self.cmd.take_action(parsed_args) - self.neutronclient.delete_bgpvpn.assert_has_calls( + self.networkclient.delete_bgpvpn.assert_has_calls( [mock.call(id) for id in fake_bgpvpn_ids]) self.assertIsNone(result) def test_delete_multi_bpgvpn_with_unknown(self): count = 3 - fake_bgpvpns = fakes.FakeBgpvpn.create_bgpvpns(count=count) - fake_bgpvpn_ids = [fake_bgpvpn['id'] for fake_bgpvpn in - fake_bgpvpns[constants.BGPVPNS]] + fake_bgpvpns = fakes.create_bgpvpns(count=count) + fake_bgpvpn_ids = [fake_bgpvpn['id'] for fake_bgpvpn in fake_bgpvpns] def raise_unknonw_resource(resource_path, name_or_id): if str(count - 2) in name_or_id: raise Exception() - self.neutronclient.delete_bgpvpn = mock.Mock( + self.networkclient.delete_bgpvpn = mock.Mock( side_effect=raise_unknonw_resource) arglist = fake_bgpvpn_ids verifylist = [ @@ -397,7 +393,7 @@ def raise_unknonw_resource(resource_path, name_or_id): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) - self.neutronclient.delete_bgpvpn.assert_has_calls( + self.networkclient.delete_bgpvpn.assert_has_calls( [mock.call(id) for id in fake_bgpvpn_ids]) @@ -408,8 +404,8 @@ def setUp(self): def test_list_all_bgpvpn(self): count = 3 - fake_bgpvpns = fakes.FakeBgpvpn.create_bgpvpns(count=count) - self.neutronclient.list_bgpvpns = mock.Mock(return_value=fake_bgpvpns) + fake_bgpvpns = fakes.create_bgpvpns(count=count) + self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) arglist = [] verifylist = [] @@ -417,17 +413,17 @@ def test_list_all_bgpvpn(self): headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.list_bgpvpns.assert_called_once() + self.networkclient.bgpvpns.assert_called_once() self.assertEqual(headers, list(headers_short)) self.assertListItemEqual( list(data), [_get_data(fake_bgpvpn, columns_short) for fake_bgpvpn - in fake_bgpvpns[constants.BGPVPNS]]) + in fake_bgpvpns]) def test_list_all_bgpvpn_long_mode(self): count = 3 - fake_bgpvpns = fakes.FakeBgpvpn.create_bgpvpns(count=count) - self.neutronclient.list_bgpvpns = mock.Mock(return_value=fake_bgpvpns) + fake_bgpvpns = fakes.create_bgpvpns(count=count) + self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) arglist = [ '--long', ] @@ -439,20 +435,20 @@ def test_list_all_bgpvpn_long_mode(self): headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.list_bgpvpns.assert_called_once() + self.networkclient.bgpvpns.assert_called_once() self.assertEqual(headers, list(headers_long)) self.assertListItemEqual( list(data), [_get_data(fake_bgpvpn, columns_long) for fake_bgpvpn - in fake_bgpvpns[constants.BGPVPNS]]) + in fake_bgpvpns]) def test_list_project_bgpvpn(self): count = 3 project_id = 'list_fake_project_id' attrs = {'tenant_id': project_id} - fake_bgpvpns = fakes.FakeBgpvpn.create_bgpvpns(count=count, - attrs=attrs) - self.neutronclient.list_bgpvpns = mock.Mock(return_value=fake_bgpvpns) + fake_bgpvpns = fakes.create_bgpvpns(count=count, + attrs=attrs) + self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) arglist = [ '--project', project_id, ] @@ -464,24 +460,23 @@ def test_list_project_bgpvpn(self): headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.list_bgpvpns.assert_called_once_with( + self.networkclient.bgpvpns.assert_called_once_with( tenant_id=project_id) self.assertEqual(headers, list(headers_short)) self.assertListItemEqual( list(data), [_get_data(fake_bgpvpn, columns_short) for fake_bgpvpn - in fake_bgpvpns[constants.BGPVPNS]]) + in fake_bgpvpns]) def test_list_bgpvpn_with_filters(self): count = 3 name = 'fake_id0' layer_type = 'l2' attrs = {'type': layer_type} - fake_bgpvpns = fakes.FakeBgpvpn.create_bgpvpns(count=count, - attrs=attrs) - returned_bgpvpn = fake_bgpvpns[constants.BGPVPNS][0] - self.neutronclient.list_bgpvpns = mock.Mock( - return_value={constants.BGPVPNS: [returned_bgpvpn]}) + fake_bgpvpns = fakes.create_bgpvpns(count=count, + attrs=attrs) + returned_bgpvpn = fake_bgpvpns[0] + self.networkclient.bgpvpns = mock.Mock(return_value=[returned_bgpvpn]) arglist = [ '--property', 'name=%s' % name, '--property', 'type=%s' % layer_type, @@ -494,7 +489,7 @@ def test_list_bgpvpn_with_filters(self): headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.list_bgpvpns.assert_called_once_with( + self.networkclient.bgpvpns.assert_called_once_with( name=name, type=layer_type) self.assertEqual(headers, list(headers_short)) @@ -506,11 +501,13 @@ class TestShowBgpvpn(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestShowBgpvpn, self).setUp() self.cmd = bgpvpn.ShowBgpvpn(self.app, self.namespace) + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) def test_show_bgpvpn(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - self.neutronclient.show_bgpvpn = mock.Mock( - return_value={constants.BGPVPN: fake_bgpvpn}) + fake_bgpvpn = fakes.create_one_bgpvpn() + self.networkclient.get_bgpvpn = mock.Mock( + return_value=fake_bgpvpn) arglist = [ fake_bgpvpn['id'], ] @@ -522,7 +519,6 @@ def test_show_bgpvpn(self): headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.show_bgpvpn.assert_called_once_with( + self.networkclient.get_bgpvpn.assert_called_once_with( fake_bgpvpn['id']) - self.assertEqual(sorted_headers, headers) - self.assertItemEqual(_get_data(fake_bgpvpn), data) + self.assertEqual(sorted(sorted_columns), sorted(headers)) diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py index f8aa95f47..1bdca4db5 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py @@ -14,7 +14,6 @@ # under the License. # -import copy import operator from unittest import mock @@ -55,15 +54,21 @@ def _get_data(attrs, columns=sorted_columns): class TestCreateResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestCreateResAssoc, self).setUp() + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) + self.networkclient.find_fake_resource = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = fakes.CreateBgpvpnFakeResAssoc(self.app, self.namespace) def test_create_resource_association(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_one_resource() - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_one_resource() + fake_res_assoc = fakes.create_one_resource_association( fake_res) - self.neutronclient.create_bgpvpn_fake_resource_assoc = mock.Mock( - return_value={fakes.BgpvpnFakeAssoc._resource: fake_res_assoc}) + self.networkclient.create_bgpvpn_fake_resource_association = mock.Mock( + return_value=fake_res_assoc) + self.networkclient.find_bgpvpn_fake_resource_association = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) arglist = [ fake_bgpvpn['id'], fake_res['id'], @@ -79,14 +84,16 @@ def test_create_resource_association(self): cols, data = self.cmd.take_action(parsed_args) - fake_res_assoc_call = copy.deepcopy(fake_res_assoc) - fake_res_assoc_call.pop('id') + fake_res_assoc_call = { + 'fake_resource_id': 'fake_resource_id', + 'tenant_id': 'fake_project_id' + } - self.neutronclient.create_bgpvpn_fake_resource_assoc.\ + self.networkclient.create_bgpvpn_fake_resource_association.\ assert_called_once_with( fake_bgpvpn['id'], - {fakes.BgpvpnFakeAssoc._resource: fake_res_assoc_call}) - self.assertEqual(sorted_headers, cols) + **fake_res_assoc_call) + self.assertEqual(sorted_columns, cols) self.assertEqual(_get_data(fake_res_assoc), data) @@ -96,11 +103,11 @@ def setUp(self): self.cmd = fakes.SetBgpvpnFakeResAssoc(self.app, self.namespace) def test_set_resource_association(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_one_resource() - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_one_resource() + fake_res_assoc = fakes.create_one_resource_association( fake_res) - self.neutronclient.update_bgpvpn_fake_resource_assoc = mock.Mock( + self.networkclient.update_bgpvpn_fake_resource_assoc = mock.Mock( return_value={fakes.BgpvpnFakeAssoc._resource: fake_res_assoc}) arglist = [ fake_res_assoc['id'], @@ -115,7 +122,7 @@ def test_set_resource_association(self): result = self.cmd.take_action(parsed_args) - self.neutronclient.update_bgpvpn_fake_resource_assoc.\ + self.networkclient.update_bgpvpn_fake_resource_assoc.\ assert_not_called() self.assertIsNone(result) @@ -123,14 +130,17 @@ def test_set_resource_association(self): class TestDeleteResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestDeleteResAssoc, self).setUp() + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = fakes.DeleteBgpvpnFakeResAssoc(self.app, self.namespace) def test_delete_one_association(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_one_resource() - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_one_resource() + fake_res_assoc = fakes.create_one_resource_association( fake_res) - self.neutronclient.delete_bgpvpn_fake_resource_assoc = mock.Mock() + self.networkclient.delete_bgpvpn_fake_resource_association = \ + mock.Mock() arglist = [ fake_res_assoc['id'], fake_bgpvpn['id'], @@ -144,21 +154,21 @@ def test_delete_one_association(self): result = self.cmd.take_action(parsed_args) - self.neutronclient.delete_bgpvpn_fake_resource_assoc.\ + self.networkclient.delete_bgpvpn_fake_resource_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) self.assertIsNone(result) def test_delete_multi_bpgvpn(self): count = 3 - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_resources(count=count) - fake_res_assocs = fakes.FakeResAssoc.create_resource_associations( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_resources(count=count) + fake_res_assocs = fakes.create_resource_associations( fake_res) fake_res_assoc_ids = [ - fake_res_assoc['id'] for fake_res_assoc in - fake_res_assocs[fakes.BgpvpnFakeAssoc._resource_plural] + fake_res_assoc['id'] for fake_res_assoc in fake_res_assocs ] - self.neutronclient.delete_bgpvpn_fake_resource_assoc = mock.Mock() + self.networkclient.delete_bgpvpn_fake_resource_association = \ + mock.Mock() arglist = \ fake_res_assoc_ids + [ fake_bgpvpn['id'] @@ -172,25 +182,26 @@ def test_delete_multi_bpgvpn(self): result = self.cmd.take_action(parsed_args) - self.neutronclient.delete_bgpvpn_fake_resource_assoc.assert_has_calls( - [mock.call(fake_bgpvpn['id'], id) for id in fake_res_assoc_ids]) + self.networkclient.delete_bgpvpn_fake_resource_association.\ + assert_has_calls([ + mock.call( + fake_bgpvpn['id'], id) for id in fake_res_assoc_ids]) self.assertIsNone(result) def test_delete_multi_bpgvpn_with_unknown(self): count = 3 - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_resources(count=count) - fake_res_assocs = fakes.FakeResAssoc.create_resource_associations( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_resources(count=count) + fake_res_assocs = fakes.create_resource_associations( fake_res) fake_res_assoc_ids = [ - fake_res_assoc['id'] for fake_res_assoc in - fake_res_assocs[fakes.BgpvpnFakeAssoc._resource_plural] + fake_res_assoc['id'] for fake_res_assoc in fake_res_assocs ] def raise_unknonw_resource(resource_path, name_or_id): if str(count - 2) in name_or_id: raise Exception() - self.neutronclient.delete_bgpvpn_fake_resource_assoc = mock.Mock( + self.networkclient.delete_bgpvpn_fake_resource_association = mock.Mock( side_effect=raise_unknonw_resource) arglist = \ fake_res_assoc_ids + [ @@ -206,22 +217,26 @@ def raise_unknonw_resource(resource_path, name_or_id): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) - self.neutronclient.delete_bgpvpn_fake_resource_assoc.assert_has_calls( - [mock.call(fake_bgpvpn['id'], id) for id in fake_res_assoc_ids]) + self.networkclient.delete_bgpvpn_fake_resource_association.\ + assert_has_calls([ + mock.call(fake_bgpvpn['id'], id) for id in fake_res_assoc_ids] + ) class TestListResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestListResAssoc, self).setUp() + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = fakes.ListBgpvpnFakeResAssoc(self.app, self.namespace) def test_list_bgpvpn_associations(self): count = 3 - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_resources(count=count) - fake_res_assocs = fakes.FakeResAssoc.create_resource_associations( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_resources(count=count) + fake_res_assocs = fakes.create_resource_associations( fake_res) - self.neutronclient.list_bgpvpn_fake_resource_assocs = mock.Mock( + self.networkclient.bgpvpn_fake_resource_associations = mock.Mock( return_value=fake_res_assocs) arglist = [ fake_bgpvpn['id'], @@ -234,21 +249,21 @@ def test_list_bgpvpn_associations(self): headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.list_bgpvpn_fake_resource_assocs.\ + self.networkclient.bgpvpn_fake_resource_associations.\ assert_called_once_with(fake_bgpvpn['id'], retrieve_all=True) self.assertEqual(headers, list(headers_short)) self.assertEqual( list(data), [_get_data(fake_res_assoc, columns_short) for fake_res_assoc - in fake_res_assocs[fakes.BgpvpnFakeAssoc._resource_plural]]) + in fake_res_assocs]) def test_list_bgpvpn_associations_long_mode(self): count = 3 - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_resources(count=count) - fake_res_assocs = fakes.FakeResAssoc.create_resource_associations( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_resources(count=count) + fake_res_assocs = fakes.create_resource_associations( fake_res) - self.neutronclient.list_bgpvpn_fake_resource_assocs = mock.Mock( + self.networkclient.bgpvpn_fake_resource_associations = mock.Mock( return_value=fake_res_assocs) arglist = [ '--long', @@ -263,27 +278,29 @@ def test_list_bgpvpn_associations_long_mode(self): headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.list_bgpvpn_fake_resource_assocs.\ + self.networkclient.bgpvpn_fake_resource_associations.\ assert_called_once_with(fake_bgpvpn['id'], retrieve_all=True) self.assertEqual(headers, list(headers_long)) self.assertEqual( list(data), [_get_data(fake_res_assoc, columns_long) for fake_res_assoc - in fake_res_assocs[fakes.BgpvpnFakeAssoc._resource_plural]]) + in fake_res_assocs]) class TestShowResAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestShowResAssoc, self).setUp() + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) self.cmd = fakes.ShowBgpvpnFakeResAssoc(self.app, self.namespace) def test_show_resource_association(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_one_resource() - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_one_resource() + fake_res_assoc = fakes.create_one_resource_association( fake_res) - self.neutronclient.show_bgpvpn_fake_resource_assoc = mock.Mock( - return_value={fakes.BgpvpnFakeAssoc._resource: fake_res_assoc}) + self.networkclient.get_bgpvpn_fake_resource_association = mock.Mock( + return_value=fake_res_assoc) arglist = [ fake_res_assoc['id'], fake_bgpvpn['id'], @@ -295,9 +312,9 @@ def test_show_resource_association(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) + columns, data = self.cmd.take_action(parsed_args) - self.neutronclient.show_bgpvpn_fake_resource_assoc.\ + self.networkclient.get_bgpvpn_fake_resource_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) - self.assertEqual(sorted_headers, headers) + self.assertEqual(sorted_columns, columns) self.assertEqual(data, _get_data(fake_res_assoc)) diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py index f48424c48..5adf77ca3 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py @@ -14,7 +14,6 @@ # under the License. # -import copy import operator from unittest import mock @@ -56,8 +55,12 @@ class TestCreateRouterAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestCreateRouterAssoc, self).setUp() self.cmd = fakes.CreateBgpvpnFakeRouterAssoc(self.app, self.namespace) - self.fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - self.fake_router = fakes.FakeResource.create_one_resource() + self.fake_bgpvpn = fakes.create_one_bgpvpn() + self.fake_router = fakes.create_one_resource() + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) + self.networkclient.find_fake_resource = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) def _build_args(self, param=None): arglist_base = [ @@ -89,20 +92,26 @@ def _exec_create_router_association( cols, data = self.cmd.take_action(parsed_args) - fake_res_assoc_call = copy.deepcopy(fake_res_assoc) - fake_res_assoc_call.pop('id') + fake_res_assoc_call = { + 'fake_resource_id': 'fake_resource_id', + 'tenant_id': 'fake_project_id' + } + for key, value in verifylist: + if value not in fake_res_assoc_call.values(): + fake_res_assoc_call[key] = value + fake_res_assoc_call.pop('bgpvpn') - self.neutronclient.create_bgpvpn_fake_resource_assoc.\ + self.networkclient.create_bgpvpn_fake_resource_association.\ assert_called_once_with( self.fake_bgpvpn['id'], - {fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc_call}) + **fake_res_assoc_call) return cols, data - def test_create_router_association(self): - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + def test_create_router_associationx(self): + fake_res_assoc = fakes.create_one_resource_association( self.fake_router) - self.neutronclient.create_bgpvpn_fake_resource_assoc = mock.Mock( + self.networkclient.create_bgpvpn_fake_resource_association = mock.Mock( return_value={ fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc, 'advertise_extra_routes': True}) @@ -116,37 +125,35 @@ def test_create_router_association(self): fake_res_assoc, arglist, verifylist) def test_create_router_association_advertise(self): - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': True}) - self.neutronclient.create_bgpvpn_fake_resource_assoc = mock.Mock( - return_value={ - fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc}) + self.networkclient.create_bgpvpn_fake_resource_association = mock.Mock( + return_value=fake_res_assoc) arglist = self._build_args('--advertise_extra_routes') verifylist = self._build_verify_list(('advertise_extra_routes', True)) cols, data = self._exec_create_router_association( fake_res_assoc, arglist, verifylist) - self.assertEqual(sorted_headers, cols) + self.assertEqual(sorted_columns, cols) self.assertEqual(_get_data(fake_res_assoc), data) def test_create_router_association_no_advertise(self): - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': False}) - self.neutronclient.create_bgpvpn_fake_resource_assoc = mock.Mock( - return_value={ - fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc}) + self.networkclient.create_bgpvpn_fake_resource_association = mock.Mock( + return_value=fake_res_assoc) arglist = self._build_args('--no-advertise_extra_routes') verifylist = self._build_verify_list(('advertise_extra_routes', False)) cols, data = self._exec_create_router_association( fake_res_assoc, arglist, verifylist) - self.assertEqual(sorted_headers, cols) + self.assertEqual(sorted_columns, cols) self.assertEqual(_get_data(fake_res_assoc), data) def test_create_router_association_advertise_fault(self): @@ -172,8 +179,10 @@ class TestSetRouterAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestSetRouterAssoc, self).setUp() self.cmd = fakes.SetBgpvpnFakeRouterAssoc(self.app, self.namespace) - self.fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - self.fake_router = fakes.FakeResource.create_one_resource() + self.fake_bgpvpn = fakes.create_one_bgpvpn() + self.fake_router = fakes.create_one_resource() + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) def _build_args(self, fake_res_assoc, param=None): arglist_base = [ @@ -197,10 +206,11 @@ def _build_verify_list(self, fake_res_assoc, param=None): return verifylist def test_set_router_association_no_advertise(self): - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': True}) - self.neutronclient.update_bgpvpn_fake_resource_assoc = mock.Mock() + self.networkclient.update_bgpvpn_fake_resource_association = \ + mock.Mock() arglist = self._build_args( fake_res_assoc, @@ -213,25 +223,20 @@ def test_set_router_association_no_advertise(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - fake_res_assoc_call = copy.deepcopy(fake_res_assoc) - fake_res_assoc_call.pop('id') - - self.neutronclient.update_bgpvpn_fake_resource_assoc.\ + self.networkclient.update_bgpvpn_fake_resource_association.\ assert_called_once_with( self.fake_bgpvpn['id'], fake_res_assoc['id'], - { - fakes.BgpvpnFakeRouterAssoc._resource: { - 'advertise_extra_routes': False - } - }) + **{'advertise_extra_routes': False} + ) self.assertIsNone(result) def test_set_router_association_advertise(self): - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': False}) - self.neutronclient.update_bgpvpn_fake_resource_assoc = mock.Mock() + self.networkclient.update_bgpvpn_fake_resource_association = \ + mock.Mock() arglist = self._build_args( fake_res_assoc, @@ -244,18 +249,12 @@ def test_set_router_association_advertise(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - fake_res_assoc_call = copy.deepcopy(fake_res_assoc) - fake_res_assoc_call.pop('id') - - self.neutronclient.update_bgpvpn_fake_resource_assoc.\ + self.networkclient.update_bgpvpn_fake_resource_association.\ assert_called_once_with( self.fake_bgpvpn['id'], fake_res_assoc['id'], - { - fakes.BgpvpnFakeRouterAssoc._resource: { - 'advertise_extra_routes': True - } - }) + **{'advertise_extra_routes': True} + ) self.assertIsNone(result) @@ -263,15 +262,17 @@ class TestShowRouterAssoc(fakes.TestNeutronClientBgpvpn): def setUp(self): super(TestShowRouterAssoc, self).setUp() self.cmd = fakes.ShowBgpvpnFakeRouterAssoc(self.app, self.namespace) + self.networkclient.find_bgpvpn = mock.Mock( + side_effect=lambda name_or_id: {'id': name_or_id}) def test_show_router_association(self): - fake_bgpvpn = fakes.FakeBgpvpn.create_one_bgpvpn() - fake_res = fakes.FakeResource.create_one_resource() - fake_res_assoc = fakes.FakeResAssoc.create_one_resource_association( + fake_bgpvpn = fakes.create_one_bgpvpn() + fake_res = fakes.create_one_resource() + fake_res_assoc = fakes.create_one_resource_association( fake_res, {'advertise_extra_routes': True}) - self.neutronclient.show_bgpvpn_fake_resource_assoc = mock.Mock( - return_value={fakes.BgpvpnFakeAssoc._resource: fake_res_assoc}) + self.networkclient.get_bgpvpn_fake_resource_association = mock.Mock( + return_value=fake_res_assoc) arglist = [ fake_res_assoc['id'], fake_bgpvpn['id'], @@ -283,9 +284,9 @@ def test_show_router_association(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) + cols, data = self.cmd.take_action(parsed_args) - self.neutronclient.show_bgpvpn_fake_resource_assoc.\ + self.networkclient.get_bgpvpn_fake_resource_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) - self.assertEqual(sorted_headers, headers) + self.assertEqual(sorted_columns, cols) self.assertEqual(data, _get_data(fake_res_assoc)) diff --git a/requirements.txt b/requirements.txt index 2e9e22d08..3ed2768cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ cliff>=3.4.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 iso8601>=0.1.11 # MIT netaddr>=0.7.18 # BSD -openstacksdk>=1.0.0 # Apache-2.0 +openstacksdk>=1.0.2 # Apache-2.0 osc-lib>=1.12.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 From 4ed299ad39f93cbf78f6be8a94d47d389c36f73c Mon Sep 17 00:00:00 2001 From: elajkat Date: Wed, 24 May 2023 13:23:01 +0200 Subject: [PATCH 110/149] BGPVPN: make resource_association method calls logic simpler This is a FUP based on the following comment: https://review.opendev.org/c/openstack/python-neutronclient/+/875728/comment/c2f44683_82cffdbc/ Change-Id: I84fe4bb45d24c2f4a7a0246e2b9fb50354a715e0 Related-Bug: #1999774 --- .../networking_bgpvpn/resource_association.py | 60 +++++++++++++------ .../test_resource_association.py | 32 +++++----- .../test_router_association.py | 22 +++---- 3 files changed, 69 insertions(+), 45 deletions(-) diff --git a/neutronclient/osc/v2/networking_bgpvpn/resource_association.py b/neutronclient/osc/v2/networking_bgpvpn/resource_association.py index f5a0804dc..925ee517a 100644 --- a/neutronclient/osc/v2/networking_bgpvpn/resource_association.py +++ b/neutronclient/osc/v2/networking_bgpvpn/resource_association.py @@ -24,6 +24,7 @@ from neutronclient._i18n import _ from neutronclient.osc import utils as nc_osc_utils +from neutronclient.osc.v2.networking_bgpvpn import constants LOG = logging.getLogger(__name__) @@ -56,8 +57,6 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network - create_method = getattr( - client, 'create_bgpvpn_%s_association' % self._assoc_res_name) bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) find_res_method = getattr( client, 'find_%s' % self._assoc_res_name) @@ -76,7 +75,14 @@ def take_action(self, parsed_args): body.update( arg2body(bgpvpn['id'], parsed_args)) - obj = create_method(bgpvpn['id'], **body) + if self._assoc_res_name == constants.NETWORK_ASSOC: + obj = client.create_bgpvpn_network_association( + bgpvpn['id'], **body) + elif self._assoc_res_name == constants.PORT_ASSOCS: + obj = client.create_bgpvpn_port_association(bgpvpn['id'], **body) + else: + obj = client.create_bgpvpn_router_association( + bgpvpn['id'], **body) transform = getattr(self, '_transform_resource', None) if callable(transform): transform(obj) @@ -113,14 +119,19 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network - update_method = getattr( - client, 'update_bgpvpn_%s_association' % self._assoc_res_name) bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) arg2body = getattr(self, '_args2body', None) if callable(arg2body): body = arg2body(bgpvpn['id'], parsed_args) - update_method(bgpvpn['id'], parsed_args.resource_association_id, - **body) + if self._assoc_res_name == constants.NETWORK_ASSOC: + client.update_bgpvpn_network_association( + bgpvpn['id'], parsed_args.resource_association_id, **body) + elif self._assoc_res_name == constants.PORT_ASSOCS: + client.update_bgpvpn_port_association( + bgpvpn['id'], parsed_args.resource_association_id, **body) + else: + client.update_bgpvpn_router_association( + bgpvpn['id'], parsed_args.resource_association_id, **body) class UnsetBgpvpnResAssoc(SetBgpvpnResAssoc): @@ -150,13 +161,16 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network - delete_method = getattr( - client, 'delete_bgpvpn_%s_association' % self._assoc_res_name) bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) fails = 0 for id in parsed_args.resource_association_ids: try: - delete_method(bgpvpn['id'], id) + if self._assoc_res_name == constants.NETWORK_ASSOC: + client.delete_bgpvpn_network_association(bgpvpn['id'], id) + elif self._assoc_res_name == constants.PORT_ASSOCS: + client.delete_bgpvpn_port_association(bgpvpn['id'], id) + else: + client.delete_bgpvpn_router_association(bgpvpn['id'], id) LOG.warning( "%(assoc_res_name)s association %(id)s deleted", {'assoc_res_name': self._assoc_res_name.capitalize(), @@ -203,14 +217,19 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network - list_method = getattr(client, - 'bgpvpn_%s_associations' % self._assoc_res_name) bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) params = {} if parsed_args.property: params.update(parsed_args.property) - objs = list_method(bgpvpn['id'], - retrieve_all=True, **params) + if self._assoc_res_name == constants.NETWORK_ASSOC: + objs = client.bgpvpn_network_associations( + bgpvpn['id'], retrieve_all=True, **params) + elif self._assoc_res_name == constants.PORT_ASSOCS: + objs = client.bgpvpn_port_associations( + bgpvpn['id'], retrieve_all=True, **params) + else: + objs = client.bgpvpn_router_associations( + bgpvpn['id'], retrieve_all=True, **params) transform = getattr(self, '_transform_resource', None) transformed_objs = [] if callable(transform): @@ -245,11 +264,16 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network - show_method = getattr( - client, 'get_bgpvpn_%s_association' % self._assoc_res_name) bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) - obj = show_method(bgpvpn['id'], - parsed_args.resource_association_id) + if self._assoc_res_name == constants.NETWORK_ASSOC: + obj = client.get_bgpvpn_network_association( + bgpvpn['id'], parsed_args.resource_association_id) + elif self._assoc_res_name == constants.PORT_ASSOCS: + obj = client.get_bgpvpn_port_association( + bgpvpn['id'], parsed_args.resource_association_id) + else: + obj = client.get_bgpvpn_router_association( + bgpvpn['id'], parsed_args.resource_association_id) transform = getattr(self, '_transform_resource', None) if callable(transform): transform(obj) diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py index 1bdca4db5..c5c478ab4 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py @@ -65,7 +65,7 @@ def test_create_resource_association(self): fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res) - self.networkclient.create_bgpvpn_fake_resource_association = mock.Mock( + self.networkclient.create_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) self.networkclient.find_bgpvpn_fake_resource_association = mock.Mock( side_effect=lambda name_or_id: {'id': name_or_id}) @@ -89,7 +89,7 @@ def test_create_resource_association(self): 'tenant_id': 'fake_project_id' } - self.networkclient.create_bgpvpn_fake_resource_association.\ + self.networkclient.create_bgpvpn_router_association.\ assert_called_once_with( fake_bgpvpn['id'], **fake_res_assoc_call) @@ -107,7 +107,7 @@ def test_set_resource_association(self): fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res) - self.networkclient.update_bgpvpn_fake_resource_assoc = mock.Mock( + self.networkclient.update_bgpvpn_router_association = mock.Mock( return_value={fakes.BgpvpnFakeAssoc._resource: fake_res_assoc}) arglist = [ fake_res_assoc['id'], @@ -122,7 +122,7 @@ def test_set_resource_association(self): result = self.cmd.take_action(parsed_args) - self.networkclient.update_bgpvpn_fake_resource_assoc.\ + self.networkclient.update_bgpvpn_router_association.\ assert_not_called() self.assertIsNone(result) @@ -139,7 +139,7 @@ def test_delete_one_association(self): fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res) - self.networkclient.delete_bgpvpn_fake_resource_association = \ + self.networkclient.delete_bgpvpn_router_association = \ mock.Mock() arglist = [ fake_res_assoc['id'], @@ -154,7 +154,7 @@ def test_delete_one_association(self): result = self.cmd.take_action(parsed_args) - self.networkclient.delete_bgpvpn_fake_resource_association.\ + self.networkclient.delete_bgpvpn_router_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) self.assertIsNone(result) @@ -167,7 +167,7 @@ def test_delete_multi_bpgvpn(self): fake_res_assoc_ids = [ fake_res_assoc['id'] for fake_res_assoc in fake_res_assocs ] - self.networkclient.delete_bgpvpn_fake_resource_association = \ + self.networkclient.delete_bgpvpn_router_association = \ mock.Mock() arglist = \ fake_res_assoc_ids + [ @@ -182,7 +182,7 @@ def test_delete_multi_bpgvpn(self): result = self.cmd.take_action(parsed_args) - self.networkclient.delete_bgpvpn_fake_resource_association.\ + self.networkclient.delete_bgpvpn_router_association.\ assert_has_calls([ mock.call( fake_bgpvpn['id'], id) for id in fake_res_assoc_ids]) @@ -201,7 +201,7 @@ def test_delete_multi_bpgvpn_with_unknown(self): def raise_unknonw_resource(resource_path, name_or_id): if str(count - 2) in name_or_id: raise Exception() - self.networkclient.delete_bgpvpn_fake_resource_association = mock.Mock( + self.networkclient.delete_bgpvpn_router_association = mock.Mock( side_effect=raise_unknonw_resource) arglist = \ fake_res_assoc_ids + [ @@ -217,7 +217,7 @@ def raise_unknonw_resource(resource_path, name_or_id): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) - self.networkclient.delete_bgpvpn_fake_resource_association.\ + self.networkclient.delete_bgpvpn_router_association.\ assert_has_calls([ mock.call(fake_bgpvpn['id'], id) for id in fake_res_assoc_ids] ) @@ -236,7 +236,7 @@ def test_list_bgpvpn_associations(self): fake_res = fakes.create_resources(count=count) fake_res_assocs = fakes.create_resource_associations( fake_res) - self.networkclient.bgpvpn_fake_resource_associations = mock.Mock( + self.networkclient.bgpvpn_router_associations = mock.Mock( return_value=fake_res_assocs) arglist = [ fake_bgpvpn['id'], @@ -249,7 +249,7 @@ def test_list_bgpvpn_associations(self): headers, data = self.cmd.take_action(parsed_args) - self.networkclient.bgpvpn_fake_resource_associations.\ + self.networkclient.bgpvpn_router_associations.\ assert_called_once_with(fake_bgpvpn['id'], retrieve_all=True) self.assertEqual(headers, list(headers_short)) self.assertEqual( @@ -263,7 +263,7 @@ def test_list_bgpvpn_associations_long_mode(self): fake_res = fakes.create_resources(count=count) fake_res_assocs = fakes.create_resource_associations( fake_res) - self.networkclient.bgpvpn_fake_resource_associations = mock.Mock( + self.networkclient.bgpvpn_router_associations = mock.Mock( return_value=fake_res_assocs) arglist = [ '--long', @@ -278,7 +278,7 @@ def test_list_bgpvpn_associations_long_mode(self): headers, data = self.cmd.take_action(parsed_args) - self.networkclient.bgpvpn_fake_resource_associations.\ + self.networkclient.bgpvpn_router_associations.\ assert_called_once_with(fake_bgpvpn['id'], retrieve_all=True) self.assertEqual(headers, list(headers_long)) self.assertEqual( @@ -299,7 +299,7 @@ def test_show_resource_association(self): fake_res = fakes.create_one_resource() fake_res_assoc = fakes.create_one_resource_association( fake_res) - self.networkclient.get_bgpvpn_fake_resource_association = mock.Mock( + self.networkclient.get_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) arglist = [ fake_res_assoc['id'], @@ -314,7 +314,7 @@ def test_show_resource_association(self): columns, data = self.cmd.take_action(parsed_args) - self.networkclient.get_bgpvpn_fake_resource_association.\ + self.networkclient.get_bgpvpn_router_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) self.assertEqual(sorted_columns, columns) self.assertEqual(data, _get_data(fake_res_assoc)) diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py index 5adf77ca3..71c174288 100644 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py +++ b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py @@ -101,17 +101,17 @@ def _exec_create_router_association( fake_res_assoc_call[key] = value fake_res_assoc_call.pop('bgpvpn') - self.networkclient.create_bgpvpn_fake_resource_association.\ + self.networkclient.create_bgpvpn_router_association.\ assert_called_once_with( self.fake_bgpvpn['id'], **fake_res_assoc_call) return cols, data - def test_create_router_associationx(self): + def test_create_router_association(self): fake_res_assoc = fakes.create_one_resource_association( self.fake_router) - self.networkclient.create_bgpvpn_fake_resource_association = mock.Mock( + self.networkclient.create_bgpvpn_router_association = mock.Mock( return_value={ fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc, 'advertise_extra_routes': True}) @@ -129,7 +129,7 @@ def test_create_router_association_advertise(self): self.fake_router, {'advertise_extra_routes': True}) - self.networkclient.create_bgpvpn_fake_resource_association = mock.Mock( + self.networkclient.create_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) arglist = self._build_args('--advertise_extra_routes') @@ -145,7 +145,7 @@ def test_create_router_association_no_advertise(self): self.fake_router, {'advertise_extra_routes': False}) - self.networkclient.create_bgpvpn_fake_resource_association = mock.Mock( + self.networkclient.create_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) arglist = self._build_args('--no-advertise_extra_routes') @@ -209,7 +209,7 @@ def test_set_router_association_no_advertise(self): fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': True}) - self.networkclient.update_bgpvpn_fake_resource_association = \ + self.networkclient.update_bgpvpn_router_association = \ mock.Mock() arglist = self._build_args( @@ -223,7 +223,7 @@ def test_set_router_association_no_advertise(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.networkclient.update_bgpvpn_fake_resource_association.\ + self.networkclient.update_bgpvpn_router_association.\ assert_called_once_with( self.fake_bgpvpn['id'], fake_res_assoc['id'], @@ -235,7 +235,7 @@ def test_set_router_association_advertise(self): fake_res_assoc = fakes.create_one_resource_association( self.fake_router, {'advertise_extra_routes': False}) - self.networkclient.update_bgpvpn_fake_resource_association = \ + self.networkclient.update_bgpvpn_router_association = \ mock.Mock() arglist = self._build_args( @@ -249,7 +249,7 @@ def test_set_router_association_advertise(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.networkclient.update_bgpvpn_fake_resource_association.\ + self.networkclient.update_bgpvpn_router_association.\ assert_called_once_with( self.fake_bgpvpn['id'], fake_res_assoc['id'], @@ -271,7 +271,7 @@ def test_show_router_association(self): fake_res_assoc = fakes.create_one_resource_association( fake_res, {'advertise_extra_routes': True}) - self.networkclient.get_bgpvpn_fake_resource_association = mock.Mock( + self.networkclient.get_bgpvpn_router_association = mock.Mock( return_value=fake_res_assoc) arglist = [ fake_res_assoc['id'], @@ -286,7 +286,7 @@ def test_show_router_association(self): cols, data = self.cmd.take_action(parsed_args) - self.networkclient.get_bgpvpn_fake_resource_association.\ + self.networkclient.get_bgpvpn_router_association.\ assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) self.assertEqual(sorted_columns, cols) self.assertEqual(data, _get_data(fake_res_assoc)) From fccfe8c3e588f910a56fc0473504b021b2855e05 Mon Sep 17 00:00:00 2001 From: elajkat Date: Mon, 17 Apr 2023 13:19:31 +0200 Subject: [PATCH 111/149] OSC: Remove FWAAS V2 calls to neutronclient Bump SDK min version to 1.5.0. Depends-On: https://review.opendev.org/c/openstack/openstacksdk/+/883859 Related-Bug: #1999774 Change-Id: I1588ffa8035c2a4f558c6d3a630287542c718be4 --- neutronclient/osc/v2/fwaas/firewallgroup.py | 103 ++++---- neutronclient/osc/v2/fwaas/firewallpolicy.py | 118 ++++----- neutronclient/osc/v2/fwaas/firewallrule.py | 86 +++--- .../tests/unit/osc/v2/fwaas/common.py | 59 ++--- .../tests/unit/osc/v2/fwaas/fakes.py | 21 +- .../unit/osc/v2/fwaas/test_firewallgroup.py | 217 +++++++-------- .../unit/osc/v2/fwaas/test_firewallpolicy.py | 247 ++++++++---------- .../unit/osc/v2/fwaas/test_firewallrule.py | 185 ++++++------- requirements.txt | 2 +- 9 files changed, 525 insertions(+), 513 deletions(-) diff --git a/neutronclient/osc/v2/fwaas/firewallgroup.py b/neutronclient/osc/v2/fwaas/firewallgroup.py index 4287132ea..723e295fb 100644 --- a/neutronclient/osc/v2/fwaas/firewallgroup.py +++ b/neutronclient/osc/v2/fwaas/firewallgroup.py @@ -32,6 +32,20 @@ 'admin_state_up': v2_utils.AdminStateColumn, } +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'ingress_firewall_policy_id': 'Ingress Policy ID', + 'egress_firewall_policy_id': 'Egress Policy ID', + 'description': 'Description', + 'status': 'Status', + 'ports': 'Ports', + 'admin_state_up': 'State', + 'shared': 'Shared', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), @@ -103,7 +117,7 @@ def _get_common_parser(parser): def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} - client = client_manager.neutronclient + client = client_manager.network if is_create: if 'project' in parsed_args and parsed_args.project is not None: @@ -114,24 +128,20 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): ).id if (parsed_args.ingress_firewall_policy and parsed_args.no_ingress_firewall_policy): - attrs['ingress_firewall_policy_id'] = client.find_resource( - const.FWP, parsed_args.ingress_firewall_policy, - cmd_resource=const.CMD_FWP)['id'] + attrs['ingress_firewall_policy_id'] = client.find_firewall_policy( + parsed_args.ingress_firewall_policy)['id'] elif parsed_args.ingress_firewall_policy: - attrs['ingress_firewall_policy_id'] = client.find_resource( - const.FWP, parsed_args.ingress_firewall_policy, - cmd_resource=const.CMD_FWP)['id'] + attrs['ingress_firewall_policy_id'] = client.find_firewall_policy( + parsed_args.ingress_firewall_policy)['id'] elif parsed_args.no_ingress_firewall_policy: attrs['ingress_firewall_policy_id'] = None if (parsed_args.egress_firewall_policy and parsed_args.no_egress_firewall_policy): - attrs['egress_firewall_policy_id'] = client.find_resource( - const.FWP, parsed_args.egress_firewall_policy, - cmd_resource=const.CMD_FWP)['id'] + attrs['egress_firewall_policy_id'] = client.find_firewall_policy( + parsed_args.egress_firewall_policy)['id'] elif parsed_args.egress_firewall_policy: - attrs['egress_firewall_policy_id'] = client.find_resource( - const.FWP, parsed_args.egress_firewall_policy, - cmd_resource=const.CMD_FWP)['id'] + attrs['egress_firewall_policy_id'] = client.find_firewall_policy( + parsed_args.egress_firewall_policy)['id'] elif parsed_args.no_egress_firewall_policy: attrs['egress_firewall_policy_id'] = None if parsed_args.share: @@ -147,16 +157,15 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): if parsed_args.description: attrs['description'] = str(parsed_args.description) if parsed_args.port and parsed_args.no_port: - attrs['ports'] = sorted([client.find_resource( - 'port', p)['id'] for p in set(parsed_args.port)]) + attrs['ports'] = sorted([client.find_port( + p)['id'] for p in set(parsed_args.port)]) elif parsed_args.port: ports = [] for p in set(parsed_args.port): - ports.append(client.find_resource('port', p)['id']) + ports.append(client.find_port(p)['id']) if not is_create: - ports += client.find_resource( - const.FWG, parsed_args.firewall_group, - cmd_resource=const.CMD_FWG)['ports'] + ports += client.find_firewall_group( + parsed_args.firewall_group)['ports'] attrs['ports'] = sorted(set(ports)) elif parsed_args.no_port: attrs['ports'] = [] @@ -185,11 +194,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) - obj = client.create_fwaas_firewall_group( - {const.FWG: attrs})[const.FWG] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_firewall_group(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) @@ -207,13 +216,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network result = 0 for fwg in parsed_args.firewall_group: try: - fwg_id = client.find_resource( - const.FWG, fwg, cmd_resource=const.CMD_FWG)['id'] - client.delete_fwaas_firewall_group(fwg_id) + fwg_id = client.find_firewall_group(fwg)['id'] + client.delete_firewall_group(fwg_id) except Exception as e: result += 1 LOG.error(_("Failed to delete firewall group with " @@ -240,8 +248,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_fwaas_firewall_groups()[const.FWGS] + client = self.app.client_manager.network + obj = client.firewall_groups() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( @@ -272,13 +280,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fwg_id = client.find_resource(const.FWG, parsed_args.firewall_group, - cmd_resource=const.CMD_FWG)['id'] + client = self.app.client_manager.network + fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: - client.update_fwaas_firewall_group(fwg_id, {const.FWG: attrs}) + client.update_firewall_group(fwg_id, **attrs) except Exception as e: msg = (_("Failed to set firewall group '%(group)s': %(e)s") % {'group': parsed_args.firewall_group, 'e': e}) @@ -297,11 +304,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fwg_id = client.find_resource(const.FWG, parsed_args.firewall_group, - cmd_resource=const.CMD_FWG)['id'] - obj = client.show_fwaas_firewall_group(fwg_id)[const.FWG] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] + obj = client.get_firewall_group(fwg_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) @@ -347,9 +354,8 @@ def get_parser(self, prog_name): help=_('Disable firewall group')) return parser - def _get_attrs(self, client_manager, parsed_args): + def _get_attrs(self, client, parsed_args): attrs = {} - client = client_manager.neutronclient if parsed_args.ingress_firewall_policy: attrs['ingress_firewall_policy_id'] = None if parsed_args.egress_firewall_policy: @@ -359,23 +365,20 @@ def _get_attrs(self, client_manager, parsed_args): if parsed_args.enable: attrs['admin_state_up'] = False if parsed_args.port: - old = client.find_resource( - const.FWG, parsed_args.firewall_group, - cmd_resource=const.CMD_FWG)['ports'] - new = [client.find_resource( - 'port', r)['id'] for r in parsed_args.port] + old = client.find_firewall_group( + parsed_args.firewall_group)['ports'] + new = [client.find_port(r)['id'] for r in parsed_args.port] attrs['ports'] = sorted(list(set(old) - set(new))) if parsed_args.all_port: attrs['ports'] = [] return attrs def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fwg_id = client.find_resource(const.FWG, parsed_args.firewall_group, - cmd_resource=const.CMD_FWG)['id'] - attrs = self._get_attrs(self.app.client_manager, parsed_args) + client = self.app.client_manager.network + fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] + attrs = self._get_attrs(client, parsed_args) try: - client.update_fwaas_firewall_group(fwg_id, {const.FWG: attrs}) + client.update_firewall_group(fwg_id, **attrs) except Exception as e: msg = (_("Failed to unset firewall group '%(group)s': %(e)s") % {'group': parsed_args.firewall_group, 'e': e}) diff --git a/neutronclient/osc/v2/fwaas/firewallpolicy.py b/neutronclient/osc/v2/fwaas/firewallpolicy.py index cc6beb54d..e049698f7 100644 --- a/neutronclient/osc/v2/fwaas/firewallpolicy.py +++ b/neutronclient/osc/v2/fwaas/firewallpolicy.py @@ -30,6 +30,18 @@ _formatters = {} + +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'description': 'Description', + 'firewall_rules': 'Firewall Rules', + 'audited': 'Audited', + 'shared': 'Shared', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), @@ -43,7 +55,7 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} - client = client_manager.neutronclient + client = client_manager.network if is_create: if 'project' in parsed_args and parsed_args.project is not None: @@ -55,18 +67,16 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): if parsed_args.firewall_rule and parsed_args.no_firewall_rule: _firewall_rules = [] for f in parsed_args.firewall_rule: - _firewall_rules.append(client.find_resource( - const.FWR, f, cmd_resource=const.CMD_FWR)['id']) + _firewall_rules.append(client.find_firewall_rule(f)['id']) attrs[const.FWRS] = _firewall_rules elif parsed_args.firewall_rule: rules = [] if not is_create: - rules += client.find_resource( - const.FWP, parsed_args.firewall_policy, - cmd_resource=const.CMD_FWP)[const.FWRS] + foobar = client.find_firewall_policy( + parsed_args.firewall_policy) + rules += foobar[const.FWRS] for f in parsed_args.firewall_rule: - rules.append(client.find_resource( - const.FWR, f, cmd_resource=const.CMD_FWR)['id']) + rules.append(client.find_firewall_rule(f)['id']) attrs[const.FWRS] = rules elif parsed_args.no_firewall_rule: attrs[const.FWRS] = [] @@ -137,11 +147,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) - obj = client.create_fwaas_firewall_policy( - {const.FWP: attrs})[const.FWP] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_firewall_policy(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) @@ -159,13 +169,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network result = 0 for fwp in parsed_args.firewall_policy: try: - fwp_id = client.find_resource( - const.FWP, fwp, cmd_resource='fwaas_' + const.FWP)['id'] - client.delete_fwaas_firewall_policy(fwp_id) + fwp_id = client.find_firewall_policy(fwp)['id'] + client.delete_firewall_policy(fwp_id) except Exception as e: result += 1 LOG.error(_("Failed to delete Firewall policy with " @@ -205,31 +214,28 @@ def get_parser(self, prog_name): return parser def args2body(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network _rule_id = _get_required_firewall_rule(client, parsed_args) _insert_before = '' if 'insert_before' in parsed_args: if parsed_args.insert_before: - _insert_before = client.find_resource( - const.FWR, parsed_args.insert_before, - cmd_resource=const.CMD_FWR)['id'] + _insert_before = client.find_firewall_rule( + parsed_args.insert_before)['id'] _insert_after = '' if 'insert_after' in parsed_args: if parsed_args.insert_after: - _insert_after = client.find_resource( - const.FWR, parsed_args.insert_after, - cmd_resource=const.CMD_FWR)['id'] + _insert_after = client.find_firewall_rule( + parsed_args.insert_after)['id'] return {'firewall_rule_id': _rule_id, 'insert_before': _insert_before, 'insert_after': _insert_after} def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - policy_id = client.find_resource( - const.FWP, parsed_args.firewall_policy, - cmd_resource=const.CMD_FWP)['id'] + client = self.app.client_manager.network + policy_id = client.find_firewall_policy( + parsed_args.firewall_policy)['id'] body = self.args2body(parsed_args) - client.insert_rule_fwaas_firewall_policy(policy_id, body) + client.insert_rule_into_policy(policy_id, body) rule_id = body['firewall_rule_id'] policy = parsed_args.firewall_policy print((_('Inserted firewall rule %(rule)s in firewall policy ' @@ -253,13 +259,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - policy_id = client.find_resource( - const.FWP, parsed_args.firewall_policy, - cmd_resource=const.CMD_FWP)['id'] + client = self.app.client_manager.network + policy_id = client.find_firewall_policy( + parsed_args.firewall_policy)['id'] fwr_id = _get_required_firewall_rule(client, parsed_args) body = {'firewall_rule_id': fwr_id} - client.remove_rule_fwaas_firewall_policy(policy_id, body) + client.remove_rule_from_policy(policy_id, body) rule_id = body['firewall_rule_id'] policy = parsed_args.firewall_policy print((_('Removed firewall rule %(rule)s from firewall policy ' @@ -281,8 +286,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_fwaas_firewall_policies()[const.FWPS] + client = self.app.client_manager.network + obj = client.firewall_policies() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( @@ -315,14 +320,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fwp_id = client.find_resource( - const.FWP, parsed_args.firewall_policy, - cmd_resource=const.CMD_FWP)['id'] + client = self.app.client_manager.network + fwp_id = client.find_firewall_policy( + parsed_args.firewall_policy)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: - client.update_fwaas_firewall_policy(fwp_id, {const.FWP: attrs}) + client.update_firewall_policy(fwp_id, **attrs) except Exception as e: msg = (_("Failed to set firewall policy '%(policy)s': %(e)s") % {'policy': parsed_args.firewall_policy, 'e': e}) @@ -341,12 +345,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fwp_id = client.find_resource(const.FWP, - parsed_args.firewall_policy, - cmd_resource=const.CMD_FWP)['id'] - obj = client.show_fwaas_firewall_policy(fwp_id)[const.FWP] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + fwp_id = client.find_firewall_policy( + parsed_args.firewall_policy)['id'] + obj = client.get_firewall_policy(fwp_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) @@ -355,8 +359,7 @@ def _get_required_firewall_rule(client, parsed_args): if not parsed_args.firewall_rule: msg = (_("Firewall rule (name or ID) is required.")) raise exceptions.CommandError(msg) - return client.find_resource( - const.FWR, parsed_args.firewall_rule, cmd_resource=const.CMD_FWR)['id'] + return client.find_firewall_rule(parsed_args.firewall_rule)['id'] class UnsetFirewallPolicy(command.Command): @@ -392,16 +395,14 @@ def get_parser(self, prog_name): def _get_attrs(self, client_manager, parsed_args): attrs = {} - client = client_manager.neutronclient + client = client_manager.network if parsed_args.firewall_rule: - current = client.find_resource( - const.FWP, parsed_args.firewall_policy, - cmd_resource=const.CMD_FWP)[const.FWRS] + current = client.find_firewall_policy( + parsed_args.firewall_policy)[const.FWRS] removed = [] for f in set(parsed_args.firewall_rule): - removed.append(client.find_resource( - const.FWR, f, cmd_resource=const.CMD_FWR)['id']) + removed.append(client.find_firewall_rule(f)['id']) attrs[const.FWRS] = [r for r in current if r not in removed] if parsed_args.all_firewall_rule: attrs[const.FWRS] = [] @@ -412,13 +413,12 @@ def _get_attrs(self, client_manager, parsed_args): return attrs def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fwp_id = client.find_resource( - const.FWP, parsed_args.firewall_policy, - cmd_resource=const.CMD_FWP)['id'] + client = self.app.client_manager.network + fwp_id = client.find_firewall_policy( + parsed_args.firewall_policy)['id'] attrs = self._get_attrs(self.app.client_manager, parsed_args) try: - client.update_fwaas_firewall_policy(fwp_id, {const.FWP: attrs}) + client.update_firewall_policy(fwp_id, **attrs) except Exception as e: msg = (_("Failed to unset firewall policy '%(policy)s': %(e)s") % {'policy': parsed_args.firewall_policy, 'e': e}) diff --git a/neutronclient/osc/v2/fwaas/firewallrule.py b/neutronclient/osc/v2/fwaas/firewallrule.py index 720c4d29a..206a9b4e1 100644 --- a/neutronclient/osc/v2/fwaas/firewallrule.py +++ b/neutronclient/osc/v2/fwaas/firewallrule.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. # -import copy import logging from cliff import columns as cliff_columns @@ -31,12 +30,34 @@ LOG = logging.getLogger(__name__) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'enabled': 'Enabled', + 'summary': 'Summary', + 'description': 'Description', + 'firewall_policy_id': 'Firewall Policy', + 'ip_version': 'IP Version', + 'action': 'Action', + 'protocol': 'Protocol', + 'source_ip_address': 'Source IP Address', + 'source_port': 'Source Port', + 'destination_ip_address': 'Destination IP Address', + 'destination_port': 'Destination Port', + 'shared': 'Shared', + 'source_firewall_group_id': 'Source Firewall Group ID', + 'destination_firewall_group_id': 'Destination Firewall Group ID', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + _attr_map = ( ('id', 'ID', column_util.LIST_BOTH), ('name', 'Name', column_util.LIST_BOTH), ('enabled', 'Enabled', column_util.LIST_BOTH), ('summary', 'Summary', column_util.LIST_SHORT_ONLY), ('description', 'Description', column_util.LIST_LONG_ONLY), + ('firewall_policy_id', 'Firewall Policy', column_util.LIST_BOTH), ('ip_version', 'IP Version', column_util.LIST_LONG_ONLY), ('action', 'Action', column_util.LIST_LONG_ONLY), ('protocol', 'Protocol', column_util.LIST_LONG_ONLY), @@ -159,7 +180,7 @@ def _get_common_parser(parser): def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} - client = client_manager.neutronclient + client = client_manager.network if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['tenant_id'] = osc_utils.find_project( @@ -204,15 +225,13 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): if parsed_args.no_share: attrs['shared'] = False if parsed_args.source_firewall_group: - attrs['source_firewall_group_id'] = client.find_resource( - const.FWG, parsed_args.source_firewall_group, - cmd_resource=const.CMD_FWG)['id'] + attrs['source_firewall_group_id'] = client.find_firewall_group( + parsed_args.source_firewall_group)['id'] if parsed_args.no_source_firewall_group: attrs['source_firewall_group_id'] = None if parsed_args.destination_firewall_group: - attrs['destination_firewall_group_id'] = client.find_resource( - const.FWG, parsed_args.destination_firewall_group, - cmd_resource=const.CMD_FWG)['id'] + attrs['destination_firewall_group_id'] = client.find_firewall_group( + parsed_args.destination_firewall_group)['id'] if parsed_args.no_destination_firewall_group: attrs['destination_firewall_group_id'] = None return attrs @@ -236,11 +255,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) - obj = client.create_fwaas_firewall_rule( - {const.FWR: attrs})[const.FWR] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_firewall_rule(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return display_columns, data @@ -258,13 +277,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network result = 0 for fwr in parsed_args.firewall_rule: try: - fwr_id = client.find_resource( - const.FWR, fwr, cmd_resource=const.CMD_FWR)['id'] - client.delete_fwaas_firewall_rule(fwr_id) + fwr_id = client.find_firewall_rule(fwr)['id'] + client.delete_firewall_rule(fwr_id) except Exception as e: result += 1 LOG.error(_("Failed to delete Firewall rule with " @@ -292,8 +310,8 @@ def get_parser(self, prog_name): return parser def extend_list(self, data, parsed_args): - ext_data = copy.deepcopy(data) - for d in ext_data: + ext_data = [] + for d in data: protocol = d['protocol'].upper() if d['protocol'] else 'ANY' src_ip = 'none specified' dst_ip = 'none specified' @@ -311,11 +329,12 @@ def extend_list(self, data, parsed_args): src = 'source(port): ' + src_ip + src_port dst = 'dest(port): ' + dst_ip + dst_port d['summary'] = ',\n '.join([protocol, src, dst, action]) + ext_data.append(d) return ext_data def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_fwaas_firewall_rules()[const.FWRS] + client = self.app.client_manager.network + obj = client.firewall_rules() obj_extend = self.extend_list(obj, parsed_args) headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) @@ -336,14 +355,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) - fwr_id = client.find_resource( - const.FWR, parsed_args.firewall_rule, - cmd_resource=const.CMD_FWR)['id'] + fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] try: - client.update_fwaas_firewall_rule(fwr_id, {const.FWR: attrs}) + client.update_firewall_rule(fwr_id, **attrs) except Exception as e: msg = (_("Failed to set firewall rule '%(rule)s': %(e)s") % {'rule': parsed_args.firewall_rule, 'e': e}) @@ -362,12 +379,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fwr_id = client.find_resource( - const.FWR, parsed_args.firewall_rule, - cmd_resource=const.CMD_FWR)['id'] - obj = client.show_fwaas_firewall_rule(fwr_id)[const.FWR] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] + obj = client.get_firewall_rule(fwr_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) @@ -440,13 +456,11 @@ def _get_attrs(self, client_manager, parsed_args): return attrs def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = self._get_attrs(self.app.client_manager, parsed_args) - fwr_id = client.find_resource( - const.FWR, parsed_args.firewall_rule, - cmd_resource=const.CMD_FWR)['id'] + fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] try: - client.update_fwaas_firewall_rule(fwr_id, {const.FWR: attrs}) + client.update_firewall_rule(fwr_id, **attrs) except Exception as e: msg = (_("Failed to unset firewall rule '%(rule)s': %(e)s") % {'rule': parsed_args.firewall_rule, 'e': e}) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/common.py b/neutronclient/tests/unit/osc/v2/fwaas/common.py index 8b497a9ff..ae0d97fbb 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/common.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/common.py @@ -42,23 +42,20 @@ def test_list_with_long_option(self): self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) - self.assertListItemEqual([self.data], list(data)) class TestShowFWaaS(test_fakes.TestNeutronClientOSCV2): def test_show_filtered_by_id_or_name(self): target = self.resource['id'] + headers, data = None, None def _mock_fwaas(*args, **kwargs): - # Find specified ingress_firewall_policy - if self.neutronclient.find_resource.call_count == 1: - self.assertEqual(self.res, args[0]) - self.assertEqual(self.resource['id'], args[1]) - self.assertEqual({'cmd_resource': 'fwaas_' + self.res}, kwargs) - return {'id': args[1]} + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = _mock_fwaas + self.networkclient.find_firewall_policy.side_effect = _mock_fwaas + self.networkclient.find_firewall_group.side_effect = _mock_fwaas + self.networkclient.find_firewall_rule.side_effect = _mock_fwaas arglist = [target] verifylist = [(self.res, target)] @@ -67,7 +64,6 @@ def _mock_fwaas(*args, **kwargs): self.mocked.assert_called_once_with(target) self.assertEqual(self.ordered_headers, headers) - self.assertItemEqual(self.ordered_data, data) class TestCreateFWaaS(test_fakes.TestNeutronClientOSCV2): @@ -87,8 +83,7 @@ def test_set_name(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'name': update}}) + self.mocked.assert_called_once_with(target, **{'name': update}) self.assertIsNone(result) def test_set_description(self): @@ -102,8 +97,7 @@ def test_set_description(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'description': update}}) + self.mocked.assert_called_once_with(target, **{'description': update}) self.assertIsNone(result) def test_set_shared(self): @@ -116,8 +110,7 @@ def test_set_shared(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'shared': True}}) + self.mocked.assert_called_once_with(target, **{'shared': True}) self.assertIsNone(result) def test_set_duplicate_shared(self): @@ -130,8 +123,7 @@ def test_set_duplicate_shared(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'shared': True}}) + self.mocked.assert_called_once_with(target, **{'shared': True}) self.assertIsNone(result) def test_set_no_share(self): @@ -144,8 +136,7 @@ def test_set_no_share(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'shared': False}}) + self.mocked.assert_called_once_with(target, **{'shared': False}) self.assertIsNone(result) def test_set_duplicate_no_share(self): @@ -158,8 +149,7 @@ def test_set_duplicate_no_share(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'shared': False}}) + self.mocked.assert_called_once_with(target, **{'shared': False}) self.assertIsNone(result) def test_set_no_share_and_shared(self): @@ -215,6 +205,14 @@ class TestDeleteFWaaS(test_fakes.TestNeutronClientOSCV2): def test_delete_with_one_resource(self): target = self.resource['id'] + + def _mock_fwaas(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_firewall_group.side_effect = _mock_fwaas + self.networkclient.find_firewall_policy.side_effect = _mock_fwaas + self.networkclient.find_firewall_rule.side_effect = _mock_fwaas + arglist = [target] verifylist = [(self.res, [target])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -226,12 +224,11 @@ def test_delete_with_one_resource(self): def test_delete_with_multiple_resources(self): def _mock_fwaas(*args, **kwargs): - self.assertEqual(self.res, args[0]) - self.assertIsNotNone(args[1]) - self.assertEqual({'cmd_resource': 'fwaas_' + self.res}, kwargs) - return {'id': args[1]} + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = _mock_fwaas + self.networkclient.find_firewall_group.side_effect = _mock_fwaas + self.networkclient.find_firewall_policy.side_effect = _mock_fwaas + self.networkclient.find_firewall_rule.side_effect = _mock_fwaas target1 = 'target1' target2 = 'target2' @@ -244,7 +241,7 @@ def _mock_fwaas(*args, **kwargs): self.assertEqual(2, self.mocked.call_count) for idx, reference in enumerate([target1, target2]): - actual = ''.join(self.mocked.call_args_list[idx][0]) + actual = ''.join(self.mocked.call_args_list[idx][0][0]) self.assertEqual(reference, actual) def test_delete_multiple_with_exception(self): @@ -252,7 +249,7 @@ def test_delete_multiple_with_exception(self): arglist = [target1] verifylist = [(self.res, [target1])] - self.neutronclient.find_resource.side_effect = [ + self.networkclient.find_firewall_group.side_effect = [ target1, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -277,8 +274,7 @@ def test_unset_shared(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'shared': False}}) + self.mocked.assert_called_once_with(target, **{'shared': False}) self.assertIsNone(result) def test_set_shared_and_no_shared(self): @@ -304,6 +300,5 @@ def test_set_duplicate_shared(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'shared': False}}) + self.mocked.assert_called_once_with(target, **{'shared': False}) self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/fakes.py b/neutronclient/tests/unit/osc/v2/fwaas/fakes.py index d0110989b..56d09bffc 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/fakes.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/fakes.py @@ -15,9 +15,11 @@ # import collections -import copy from unittest import mock +from openstack.network.v2 import firewall_group as fw_group +from openstack.network.v2 import firewall_policy as fw_policy +from openstack.network.v2 import firewall_rule as fw_rule from oslo_utils import uuidutils @@ -32,7 +34,22 @@ def create(self, attrs={}): A OrderedDict faking the fwaas resource """ self.ordered.update(attrs) - return copy.deepcopy(self.ordered) + if 'FirewallGroup' == self.__class__.__name__: + return fw_group.FirewallGroup(**self.ordered) + if 'FirewallPolicy' == self.__class__.__name__: + return fw_policy.FirewallPolicy(**self.ordered) + if 'FirewallRule' == self.__class__.__name__: + fw_r = fw_rule.FirewallRule(**self.ordered) + protocol = fw_r['protocol'].upper() if fw_r['protocol'] else 'ANY' + src_ip = str(fw_r['source_ip_address']).lower() + src_port = '(' + str(fw_r['source_port']).lower() + ')' + dst_ip = str(fw_r['destination_ip_address']).lower() + dst_port = '(' + str(fw_r['destination_port']).lower() + ')' + src = 'source(port): ' + src_ip + src_port + dst = 'dest(port): ' + dst_ip + dst_port + action = fw_r['action'] if fw_r.get('action') else 'no-action' + fw_r['summary'] = ',\n '.join([protocol, src, dst, action]) + return fw_r def bulk_create(self, attrs=None, count=2): """Create multiple fake fwaas resources diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py index 41bfecb2d..45f42ee83 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py @@ -22,7 +22,6 @@ from osc_lib.tests import utils from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import constants as const from neutronclient.osc.v2.fwaas import firewallgroup from neutronclient.osc.v2 import utils as v2_utils from neutronclient.tests.unit.osc.v2 import fakes as test_fakes @@ -52,12 +51,12 @@ def _generate_response(ordered_dict=None, data=None): if data: up.append(data) source.update(up) - return tuple(source[key] for key in source) + return source def _generate_req_and_res(verifylist): request = dict(verifylist) - response = copy.deepcopy(_fwg) + response = _fwg for key, val in verifylist: del request[key] if re.match('^no_', key) and val is True: @@ -66,6 +65,10 @@ def _generate_req_and_res(verifylist): new_value = True elif key == 'disable' and val: new_value = False + elif val is True or val is False: + new_value = val + elif key in ('name', 'description'): + new_value = val else: new_value = val converted = CONVERT_MAP.get(key, key) @@ -78,20 +81,19 @@ class TestFirewallGroup(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: - req_body = {self.res_plural: [exp_req]} + req_body = {self.res_plural: list(exp_req)} else: - req_body = {self.res: exp_req} - self.mocked.assert_called_once_with(req_body) - self.assertEqual(self.ordered_headers, headers) - self.assertItemEqual(self.ordered_data, data) + req_body = exp_req + self.mocked.assert_called_once_with(**req_body) + self.assertEqual(self.ordered_headers, tuple(sorted(headers))) def setUp(self): super(TestFirewallGroup, self).setUp() def _find_resource(*args, **kwargs): - return {'id': args[1], 'ports': _fwg['ports']} + return {'id': args[0], 'ports': _fwg['ports']} - self.neutronclient.find_resource = mock.Mock( + self.networkclient.find_firewall_group = mock.Mock( side_effect=_find_resource) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _fwg['tenant_id'] @@ -120,7 +122,7 @@ def _find_resource(*args, **kwargs): )) self.data = _generate_response() self.ordered_headers = copy.deepcopy(tuple(sorted(self.headers))) - self.ordered_data = ( + self.expected_data = ( _fwg['description'], _fwg['egress_firewall_policy_id'], _fwg['id'], @@ -151,9 +153,9 @@ class TestCreateFirewallGroup(TestFirewallGroup, common.TestCreateFWaaS): def setUp(self): # Mock objects super(TestCreateFirewallGroup, self).setUp() - self.neutronclient.create_fwaas_firewall_group = mock.Mock( - return_value={self.res: _fwg}) - self.mocked = self.neutronclient.create_fwaas_firewall_group + self.networkclient.create_firewall_group = mock.Mock( + return_value=_fwg) + self.mocked = self.networkclient.create_firewall_group self.cmd = firewallgroup.CreateFirewallGroup(self.app, self.namespace) def _update_expect_response(self, request, response): @@ -165,14 +167,11 @@ def _update_expect_response(self, request, response): A OrderedDict of request body """ # Update response body - self.neutronclient.create_fwaas_firewall_group.return_value = \ - {self.res: dict(response)} + self.networkclient.create_firewall_group.return_value = response osc_utils.find_project.return_value.id = response['tenant_id'] # Update response(finally returns 'data') self.data = _generate_response(ordered_dict=response) - self.ordered_data = tuple( - response[column] for column in self.ordered_columns - ) + self.expected_data = response def test_create_with_no_option(self): # firewall_group-create with mandatory (none) params. @@ -180,12 +179,16 @@ def test_create_with_no_option(self): verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) - self.assertEqual(self.ordered_headers, headers) - self.assertItemEqual(self.ordered_data, data) + self.assertEqual(self.ordered_headers, tuple(sorted(headers))) def test_create_with_port(self): # firewall_group-create with 'port' port_id = 'id_for_port' + + def _mock_find(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_port.side_effect = _mock_find arglist = ['--port', port_id] verifylist = [('port', [port_id])] request, response = _generate_req_and_res(verifylist) @@ -200,9 +203,9 @@ def test_create_with_ingress_policy(self): ingress_policy = 'my-ingress-policy' def _mock_port_fwg(*args, **kwargs): - return {'id': args[1]} + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = _mock_port_fwg + self.networkclient.find_firewall_policy.side_effect = _mock_port_fwg arglist = ['--ingress-firewall-policy', ingress_policy] verifylist = [('ingress_firewall_policy', ingress_policy)] @@ -211,18 +214,19 @@ def _mock_port_fwg(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.find_resource.assert_called_once_with( - 'firewall_policy', ingress_policy, cmd_resource=const.CMD_FWP) + self.networkclient.find_firewall_policy.assert_called_once_with( + ingress_policy) self.check_results(headers, data, request) def test_create_with_egress_policy(self): egress_policy = 'my-egress-policy' - def _mock_port_fwg(*args, **kwargs): - return {'id': args[1]} + def _mock_find(*args, **kwargs): + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = _mock_port_fwg + self.networkclient.find_firewall_group.side_effect = _mock_find + self.networkclient.find_firewall_policy.side_effect = _mock_find arglist = ['--egress-firewall-policy', egress_policy] verifylist = [('egress_firewall_policy', egress_policy)] @@ -231,8 +235,8 @@ def _mock_port_fwg(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) - self.neutronclient.find_resource.assert_called_once_with( - 'firewall_policy', egress_policy, cmd_resource=const.CMD_FWP) + self.networkclient.find_firewall_policy.assert_called_once_with( + egress_policy) self.check_results(headers, data, request) def test_create_with_all_params(self): @@ -240,7 +244,13 @@ def test_create_with_all_params(self): description = 'my-desc' ingress_policy = 'my-ingress-policy' egress_policy = 'my-egress-policy' + + def _mock_find(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_firewall_policy.side_effect = _mock_find port = 'port' + self.networkclient.find_port.side_effect = _mock_find tenant_id = 'my-tenant' arglist = [ '--name', name, @@ -330,9 +340,9 @@ class TestListFirewallGroup(TestFirewallGroup, common.TestListFWaaS): def setUp(self): super(TestListFirewallGroup, self).setUp() # Mock objects - self.neutronclient.list_fwaas_firewall_groups = mock.Mock( - return_value={self.res_plural: [_fwg]}) - self.mocked = self.neutronclient.list_fwaas_firewall_groups + self.networkclient.firewall_groups = mock.Mock( + return_value=[_fwg]) + self.mocked = self.networkclient.firewall_groups self.cmd = firewallgroup.ListFirewallGroup(self.app, self.namespace) @@ -341,9 +351,9 @@ class TestShowFirewallGroup(TestFirewallGroup, common.TestShowFWaaS): def setUp(self): super(TestShowFirewallGroup, self).setUp() # Mock objects - self.neutronclient.show_fwaas_firewall_group = mock.Mock( - return_value={self.res: _fwg}) - self.mocked = self.neutronclient.show_fwaas_firewall_group + self.networkclient.get_firewall_group = mock.Mock( + return_value=_fwg) + self.mocked = self.networkclient.get_firewall_group self.cmd = firewallgroup.ShowFirewallGroup(self.app, self.namespace) @@ -353,9 +363,15 @@ def setUp(self): super(TestSetFirewallGroup, self).setUp() # Mock objects _fwg['ports'] = ['old_port'] - self.neutronclient.update_fwaas_firewall_group = mock.Mock( + self.networkclient.update_firewall_group = mock.Mock( return_value={self.res: _fwg}) - self.mocked = self.neutronclient.update_fwaas_firewall_group + self.mocked = self.networkclient.update_firewall_group + + def _mock_find_port(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_port.side_effect = _mock_find_port + self.cmd = firewallgroup.SetFirewallGroup(self.app, self.namespace) def _update_expect_response(self, request, response): @@ -380,22 +396,21 @@ def test_set_ingress_policy_and_egress_policy(self): def _mock_fwg_policy(*args, **kwargs): # 1. Find specified firewall_group - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWG) + if self.networkclient.find_firewall_group.call_count == 1: + self.networkclient.find_firewall_group.assert_called_with( + target) # 2. Find specified 'ingress_firewall_policy' - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'firewall_policy', ingress_policy, - cmd_resource=const.CMD_FWP) + if self.networkclient.find_firewall_policy.call_count == 1: + self.networkclient.find_firewall_policy.assert_called_with( + ingress_policy) # 3. Find specified 'ingress_firewall_policy' - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'firewall_policy', egress_policy, - cmd_resource=const.CMD_FWP) - return {'id': args[1]} + if self.networkclient.find_firewall_policy.call_count == 2: + self.networkclient.find_firewall_policy.assert_called_with( + egress_policy) + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = _mock_fwg_policy + self.networkclient.find_firewall_group.side_effect = _mock_fwg_policy + self.networkclient.find_firewall_policy.side_effect = _mock_fwg_policy arglist = [ target, @@ -411,8 +426,8 @@ def _mock_fwg_policy(*args, **kwargs): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'ingress_firewall_policy_id': ingress_policy, - 'egress_firewall_policy_id': egress_policy}}) + target, **{'ingress_firewall_policy_id': ingress_policy, + 'egress_firewall_policy_id': egress_policy}) self.assertIsNone(result) def test_set_port(self): @@ -422,27 +437,21 @@ def test_set_port(self): def _mock_port_fwg(*args, **kwargs): # 1. Find specified firewall_group - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWG) - return {'id': args[1]} + if self.networkclient.find_firewall_group.call_count in [1, 2]: + self.networkclient.find_firewall_group.assert_called_with( + target) + return {'id': args[0], 'ports': _fwg['ports']} # 2. Find specified 'port' #1 - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'port', args[1]) - return {'id': args[1]} + if self.networkclient.find_port.call_count == 1: + self.networkclient.find_port.assert_called_with(args) + return {'id': args[0]} # 3. Find specified 'port' #2 - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'port', args[1]) - return {'id': args[1]} - # 4. Find specified firewall_group and refer 'ports' attribute - if self.neutronclient.find_resource.call_count == 4: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWG) - return {'ports': _fwg['ports']} + if self.networkclient.find_port.call_count == 2: + self.networkclient.find_port.assert_called_with(args) + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = _mock_port_fwg + self.networkclient.find_fireall_group.side_effect = _mock_port_fwg + self.networkclient.find_port.side_effect = _mock_port_fwg arglist = [ target, @@ -457,8 +466,8 @@ def _mock_port_fwg(*args, **kwargs): result = self.cmd.take_action(parsed_args) expect = {'ports': sorted(_fwg['ports'] + [port1, port2])} - self.mocked.assert_called_once_with(target, {self.res: expect}) - self.assertEqual(4, self.neutronclient.find_resource.call_count) + self.mocked.assert_called_once_with(target, **expect) + self.assertEqual(2, self.networkclient.find_firewall_group.call_count) self.assertIsNone(result) def test_set_no_port(self): @@ -473,7 +482,7 @@ def test_set_no_port(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'ports': []}}) + target, **{'ports': []}) self.assertIsNone(result) def test_set_admin_state(self): @@ -487,12 +496,18 @@ def test_set_admin_state(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'admin_state_up': True}}) + target, **{'admin_state_up': True}) self.assertIsNone(result) def test_set_egress_policy(self): target = self.resource['id'] policy = 'egress_policy' + + def _mock_find_policy(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_firewall_policy.side_effect = _mock_find_policy + arglist = [target, '--egress-firewall-policy', policy] verifylist = [ (self.res, target), @@ -502,7 +517,7 @@ def test_set_egress_policy(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'egress_firewall_policy_id': policy}}) + target, **{'egress_firewall_policy_id': policy}) self.assertIsNone(result) def test_set_no_ingress_policies(self): @@ -516,7 +531,7 @@ def test_set_no_ingress_policies(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'ingress_firewall_policy_id': None}}) + target, **{'ingress_firewall_policy_id': None}) self.assertIsNone(result) def test_set_no_egress_policies(self): @@ -530,7 +545,7 @@ def test_set_no_egress_policies(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'egress_firewall_policy_id': None}}) + target, **{'egress_firewall_policy_id': None}) self.assertIsNone(result) def test_set_port_and_no_port(self): @@ -549,7 +564,7 @@ def test_set_port_and_no_port(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'ports': [port]}}) + target, **{'ports': [port]}) self.assertIsNone(result) def test_set_ingress_policy_and_no_ingress_policy(self): @@ -585,7 +600,7 @@ def test_set_egress_policy_and_no_egress_policy(self): self.check_parser, self.cmd, arglist, verifylist) def test_set_and_raises(self): - self.neutronclient.update_fwaas_firewall_group = mock.Mock( + self.networkclient.update_firewall_group = mock.Mock( side_effect=Exception) target = self.resource['id'] arglist = [target, '--name', 'my-name'] @@ -601,8 +616,8 @@ class TestDeleteFirewallGroup(TestFirewallGroup, common.TestDeleteFWaaS): def setUp(self): super(TestDeleteFirewallGroup, self).setUp() # Mock objects - self.neutronclient.delete_fwaas_firewall_group = mock.Mock() - self.mocked = self.neutronclient.delete_fwaas_firewall_group + self.networkclient.delete_firewall_group = mock.Mock() + self.mocked = self.networkclient.delete_firewall_group self.cmd = firewallgroup.DeleteFirewallGroup(self.app, self.namespace) @@ -612,8 +627,8 @@ def setUp(self): super(TestUnsetFirewallGroup, self).setUp() _fwg['ports'] = ['old_port'] # Mock objects - self.neutronclient.update_fwaas_firewall_group = mock.Mock() - self.mocked = self.neutronclient.update_fwaas_firewall_group + self.networkclient.update_firewall_group = mock.Mock() + self.mocked = self.networkclient.update_firewall_group self.cmd = firewallgroup.UnsetFirewallGroup(self.app, self.namespace) def test_unset_ingress_policy(self): @@ -629,7 +644,7 @@ def test_unset_ingress_policy(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'ingress_firewall_policy_id': None}}) + target, **{'ingress_firewall_policy_id': None}) self.assertIsNone(result) def test_unset_egress_policy(self): @@ -645,7 +660,7 @@ def test_unset_egress_policy(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'egress_firewall_policy_id': None}}) + target, **{'egress_firewall_policy_id': None}) self.assertIsNone(result) def test_unset_enable(self): @@ -661,7 +676,7 @@ def test_unset_enable(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'admin_state_up': False}}) + target, **{'admin_state_up': False}) self.assertIsNone(result) def test_unset_port(self): @@ -670,23 +685,21 @@ def test_unset_port(self): def _mock_port_fwg(*args, **kwargs): # 1. Find specified firewall_group - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWG) - return {'id': args[1]} + if self.networkclient.find_firewall_group.call_count in [1, 2]: + self.networkclient.find_firewall_group.assert_called_with( + target) + return {'id': args[0], 'ports': _fwg['ports']} # 2. Find specified firewall_group and refer 'ports' attribute - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWG) + if self.networkclient.find_port.call_count == 2: + self.networkclient.find_port.assert_called_with(target) return {'ports': _fwg['ports']} # 3. Find specified 'port' - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'port', port) - return {'id': args[1]} + if self.networkclient.find_port.call_count == 3: + self.networkclient.find_port.assert_called_with(port) + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = mock.Mock( - side_effect=_mock_port_fwg) + self.networkclient.find_firewall_group.side_effect = _mock_port_fwg + self.networkclient.find_port.side_effect = _mock_port_fwg arglist = [ target, @@ -698,7 +711,7 @@ def _mock_port_fwg(*args, **kwargs): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with(target, {self.res: {'ports': []}}) + self.mocked.assert_called_once_with(target, **{'ports': []}) self.assertIsNone(result) def test_unset_all_port(self): @@ -713,5 +726,5 @@ def test_unset_all_port(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with(target, {self.res: {'ports': []}}) + self.mocked.assert_called_once_with(target, **{'ports': []}) self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py index 7eba77483..7d49879dc 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py @@ -14,7 +14,6 @@ # under the License. # -import copy import re from unittest import mock @@ -22,7 +21,6 @@ from osc_lib.tests import utils from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import constants as const from neutronclient.osc.v2.fwaas import firewallpolicy from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.fwaas import common @@ -51,7 +49,7 @@ def _generate_data(ordered_dict=None, data=None): def _generate_req_and_res(verifylist): request = dict(verifylist) - response = copy.deepcopy(_fwp) + response = _fwp for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] @@ -61,6 +59,10 @@ def _generate_req_and_res(verifylist): new_value = True elif key == 'disable' and val: new_value = False + elif val is True or val is False: + new_value = val + elif key in ('name', 'description'): + new_value = val else: new_value = val request[converted] = new_value @@ -74,23 +76,13 @@ def check_results(self, headers, data, exp_req, is_list=False): if is_list: req_body = {self.res_plural: [exp_req]} else: - req_body = {self.res: exp_req} - self.mocked.assert_called_once_with(req_body) - self.assertEqual(self.ordered_headers, headers) - self.assertEqual(self.ordered_data, data) + req_body = exp_req + self.mocked.assert_called_once_with(**req_body) + self.assertEqual(self.ordered_headers, tuple(sorted(headers))) def setUp(self): super(TestFirewallPolicy, self).setUp() - def _find_resource(*args, **kwargs): - rule_id = args[1] - rules = [] - if self.res in args[0]: - rules = _fwp['firewall_rules'] - return {'id': rule_id, 'firewall_rules': rules} - - self.neutronclient.find_resource = mock.Mock( - side_effect=_find_resource) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _fwp['tenant_id'] self.res = 'firewall_policy' @@ -146,9 +138,9 @@ class TestCreateFirewallPolicy(TestFirewallPolicy, common.TestCreateFWaaS): def setUp(self): super(TestCreateFirewallPolicy, self).setUp() - self.neutronclient.create_fwaas_firewall_policy = mock.Mock( + self.networkclient.create_firewall_policy = mock.Mock( return_value={self.res: _fwp}) - self.mocked = self.neutronclient.create_fwaas_firewall_policy + self.mocked = self.networkclient.create_firewall_policy self.cmd = firewallpolicy.CreateFirewallPolicy(self.app, self.namespace) @@ -161,8 +153,7 @@ def _update_expect_response(self, request, response): A OrderedDict of request body """ # Update response body - self.neutronclient.create_fwaas_firewall_policy.return_value = \ - {self.res: dict(response)} + self.networkclient.create_firewall_policy.return_value = response osc_utils.find_project.return_value.id = response['tenant_id'] # Update response(finally returns 'data') self.data = _generate_data(data=response) @@ -199,11 +190,9 @@ def test_create_with_rules(self): rule2 = 'rule2' def _mock_policy(*args, **kwargs): - self.neutronclient.find_resource.assert_called_with( - 'firewall_rule', args[1], cmd_resource=const.CMD_FWR) - return {'id': args[1]} + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = _mock_policy + self.networkclient.find_firewall_rule.side_effect = _mock_policy arglist = [ name, @@ -218,7 +207,7 @@ def _mock_policy(*args, **kwargs): self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) - self.assertEqual(2, self.neutronclient.find_resource.call_count) + self.assertEqual(2, self.networkclient.find_firewall_rule.call_count) self.check_results(headers, data, request) @@ -228,6 +217,16 @@ def test_create_with_all_params(self): rule1 = 'rule1' rule2 = 'rule2' project = 'my-tenant' + + def _mock_find(*args, **kwargs): + if self.res in args[0]: + rules = _fwp['firewall_rules'] + return {'id': args[0], 'firewall_rules': rules} + return {'id': args[0]} + + self.networkclient.find_firewall_policy.side_effect = _mock_find + self.networkclient.find_firewall_rule.side_effect = _mock_find + arglist = [ name, '--description', desc, @@ -308,9 +307,9 @@ class TestListFirewallPolicy(TestFirewallPolicy, common.TestListFWaaS): def setUp(self): super(TestListFirewallPolicy, self).setUp() - self.neutronclient.list_fwaas_firewall_policies = mock.Mock( - return_value={'firewall_policies': [_fwp]}) - self.mocked = self.neutronclient.list_fwaas_firewall_policies + self.networkclient.firewall_policies = mock.Mock( + return_value=[_fwp]) + self.mocked = self.networkclient.firewall_policies self.cmd = firewallpolicy.ListFirewallPolicy(self.app, self.namespace) @@ -318,9 +317,9 @@ class TestShowFirewallPolicy(TestFirewallPolicy, common.TestShowFWaaS): def setUp(self): super(TestShowFirewallPolicy, self).setUp() - self.neutronclient.show_fwaas_firewall_policy = mock.Mock( - return_value={self.res: _fwp}) - self.mocked = self.neutronclient.show_fwaas_firewall_policy + self.networkclient.get_firewall_policy = mock.Mock( + return_value=_fwp) + self.mocked = self.networkclient.get_firewall_policy self.cmd = firewallpolicy.ShowFirewallPolicy(self.app, self.namespace) @@ -328,38 +327,26 @@ class TestSetFirewallPolicy(TestFirewallPolicy, common.TestSetFWaaS): def setUp(self): super(TestSetFirewallPolicy, self).setUp() - self.neutronclient.update_fwaas_firewall_policy = mock.Mock( - return_value={self.res: _fwp}) - self.mocked = self.neutronclient.update_fwaas_firewall_policy + self.networkclient.update_firewall_policy = mock.Mock( + return_value=_fwp) + self.mocked = self.networkclient.update_firewall_policy + + def _mock_find_rule(*args, **kwargs): + return {'id': args[0]} + + def _mock_find_policy(*args, **kwargs): + return {'id': args[0], + 'firewall_rules': _fwp['firewall_rules']} + + self.networkclient.find_firewall_policy.side_effect = _mock_find_policy + self.networkclient.find_firewall_rule.side_effect = _mock_find_rule + self.cmd = firewallpolicy.SetFirewallPolicy(self.app, self.namespace) def test_set_rules(self): target = self.resource['id'] rule1 = 'new_rule1' rule2 = 'new_rule2' - - def _mock_policy(*args, **kwargs): - # 1. Find specified firewall_policy - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWP) - # 2. Find specified firewall_policy's 'firewall_rules' attribute - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - self.res, args[1], cmd_resource=const.CMD_FWP) - return {'firewall_rules': _fwp['firewall_rules']} - # 3. Find specified firewall_rule - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'firewall_rule', args[1], cmd_resource=const.CMD_FWR) - # 4. Find specified firewall_rule - if self.neutronclient.find_resource.call_count == 4: - self.neutronclient.find_resource.assert_called_with( - 'firewall_rule', args[1], cmd_resource=const.CMD_FWR) - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = _mock_policy - arglist = [ target, '--firewall-rule', rule1, @@ -373,9 +360,10 @@ def _mock_policy(*args, **kwargs): result = self.cmd.take_action(parsed_args) expect = _fwp['firewall_rules'] + [rule1, rule2] - body = {self.res: {'firewall_rules': expect}} - self.mocked.assert_called_once_with(target, body) - self.assertEqual(4, self.neutronclient.find_resource.call_count) + body = {'firewall_rules': expect} + self.mocked.assert_called_once_with(target, **body) + self.assertEqual(2, self.networkclient.find_firewall_rule.call_count) + self.assertEqual(2, self.networkclient.find_firewall_policy.call_count) self.assertIsNone(result) def test_set_no_rules(self): @@ -388,8 +376,8 @@ def test_set_no_rules(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - body = {self.res: {'firewall_rules': []}} - self.mocked.assert_called_once_with(target, body) + body = {'firewall_rules': []} + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_set_rules_and_no_rules(self): @@ -408,9 +396,10 @@ def test_set_rules_and_no_rules(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - body = {self.res: {'firewall_rules': [rule1]}} - self.mocked.assert_called_once_with(target, body) - self.assertEqual(2, self.neutronclient.find_resource.call_count) + body = {'firewall_rules': [rule1]} + self.mocked.assert_called_once_with(target, **body) + self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) + self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) self.assertIsNone(result) def test_set_audited(self): @@ -424,7 +413,7 @@ def test_set_audited(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with(target, {self.res: body}) + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_set_no_audited(self): @@ -438,7 +427,7 @@ def test_set_no_audited(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with(target, {self.res: body}) + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_set_audited_and_no_audited(self): @@ -458,9 +447,10 @@ def test_set_audited_and_no_audited(self): self.check_parser, self.cmd, arglist, verifylist) def test_set_and_raises(self): - self.neutronclient.update_fwaas_firewall_policy = mock.Mock( + self.networkclient.update_firewall_policy = mock.Mock( side_effect=Exception) target = self.resource['id'] + arglist = [target, '--name', 'my-name'] verifylist = [(self.res, target), ('name', 'my-name')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -473,9 +463,9 @@ class TestDeleteFirewallPolicy(TestFirewallPolicy, common.TestDeleteFWaaS): def setUp(self): super(TestDeleteFirewallPolicy, self).setUp() - self.neutronclient.delete_fwaas_firewall_policy = mock.Mock( + self.networkclient.delete_firewall_policy = mock.Mock( return_value={self.res: _fwp}) - self.mocked = self.neutronclient.delete_fwaas_firewall_policy + self.mocked = self.networkclient.delete_firewall_policy self.cmd = firewallpolicy.DeleteFirewallPolicy( self.app, self.namespace) @@ -484,9 +474,16 @@ class TestFirewallPolicyInsertRule(TestFirewallPolicy): def setUp(self): super(TestFirewallPolicyInsertRule, self).setUp() - self.neutronclient.insert_rule_fwaas_firewall_policy = mock.Mock( + self.networkclient.insert_rule_firewall_policy = mock.Mock( return_value={self.res: _fwp}) - self.mocked = self.neutronclient.insert_rule_fwaas_firewall_policy + self.mocked = self.networkclient.insert_rule_into_policy + + def _mock_find_policy(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_firewall_policy.side_effect = _mock_find_policy + self.networkclient.find_firewall_rule.side_effect = _mock_find_policy + self.cmd = firewallpolicy.FirewallPolicyInsertRule(self.app, self.namespace) @@ -495,28 +492,6 @@ def test_insert_firewall_rule(self): rule = 'new-rule' before = 'before' after = 'after' - - def _mock_policy(*args, **kwargs): - # 1. Find specified firewall_policy - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWP) - # 2. Find specified firewall_rule - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'firewall_rule', args[1], cmd_resource=const.CMD_FWR) - # 3. Find specified firewall_rule as 'before' - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'firewall_rule', args[1], cmd_resource=const.CMD_FWR) - # 4. Find specified firewall_rule as 'after' - if self.neutronclient.find_resource.call_count == 4: - self.neutronclient.find_resource.assert_called_with( - 'firewall_rule', args[1], cmd_resource=const.CMD_FWR) - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = _mock_policy - arglist = [ target, rule, @@ -539,7 +514,8 @@ def _mock_policy(*args, **kwargs): 'insert_after': after }) self.assertIsNone(result) - self.assertEqual(4, self.neutronclient.find_resource.call_count) + self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) + self.assertEqual(3, self.networkclient.find_firewall_rule.call_count) def test_insert_with_no_firewall_rule(self): target = self.resource['id'] @@ -558,30 +534,22 @@ class TestFirewallPolicyRemoveRule(TestFirewallPolicy): def setUp(self): super(TestFirewallPolicyRemoveRule, self).setUp() - self.neutronclient.remove_rule_fwaas_firewall_policy = mock.Mock( + self.networkclient.remove_rule_firewall_policy = mock.Mock( return_value={self.res: _fwp}) - self.mocked = self.neutronclient.remove_rule_fwaas_firewall_policy + self.mocked = self.networkclient.remove_rule_from_policy + + def _mock_find_policy(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_firewall_policy.side_effect = _mock_find_policy + self.networkclient.find_firewall_rule.side_effect = _mock_find_policy + self.cmd = firewallpolicy.FirewallPolicyRemoveRule(self.app, self.namespace) def test_remove_firewall_rule(self): target = self.resource['id'] rule = 'remove-rule' - - def _mock_policy(*args, **kwargs): - # 1. Find specified firewall_policy - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWP) - # 2. Find specified firewall_rule - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'firewall_rule', rule, cmd_resource=const.CMD_FWR) - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = mock.Mock( - side_effect=_mock_policy) - arglist = [ target, rule, @@ -595,7 +563,8 @@ def _mock_policy(*args, **kwargs): self.mocked.assert_called_once_with( target, {'firewall_rule_id': rule}) self.assertIsNone(result) - self.assertEqual(2, self.neutronclient.find_resource.call_count) + self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) + self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) def test_remove_with_no_firewall_rule(self): target = self.resource['id'] @@ -614,9 +583,19 @@ class TestUnsetFirewallPolicy(TestFirewallPolicy, common.TestUnsetFWaaS): def setUp(self): super(TestUnsetFirewallPolicy, self).setUp() - self.neutronclient.update_fwaas_firewall_policy = mock.Mock( + self.networkclient.update_firewall_policy = mock.Mock( return_value={self.res: _fwp}) - self.mocked = self.neutronclient.update_fwaas_firewall_policy + self.mocked = self.networkclient.update_firewall_policy + + def _mock_find_rule(*args, **kwargs): + return {'id': args[0]} + + def _mock_find_policy(*args, **kwargs): + return {'id': args[0], 'firewall_rules': _fwp['firewall_rules']} + + self.networkclient.find_firewall_policy.side_effect = _mock_find_policy + self.networkclient.find_firewall_rule.side_effect = _mock_find_rule + self.cmd = firewallpolicy.UnsetFirewallPolicy(self.app, self.namespace) def test_unset_audited(self): @@ -632,8 +611,8 @@ def test_unset_audited(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - body = {self.res: {'audited': False}} - self.mocked.assert_called_once_with(target, body) + body = {'audited': False} + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_unset_firewall_rule_not_matched(self): @@ -651,33 +630,14 @@ def test_unset_firewall_rule_not_matched(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - body = {self.res: {'firewall_rules': _fwp['firewall_rules']}} - self.mocked.assert_called_once_with(target, body) + body = {'firewall_rules': _fwp['firewall_rules']} + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) def test_unset_firewall_rule_matched(self): _fwp['firewall_rules'] = ['rule1', 'rule2'] target = self.resource['id'] rule = 'rule1' - - def _mock_policy(*args, **kwargs): - # 1. Find specified firewall_policy - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWP) - # 2. Find 'firewall_rules' attribute from specified firewall_policy - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource=const.CMD_FWP) - return {'firewall_rules': _fwp['firewall_rules']} - # 3. Find specified 'firewall_rule' - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'firewall_rule', rule, cmd_resource=const.CMD_FWR) - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = _mock_policy - arglist = [ target, '--firewall-rule', rule, @@ -689,10 +649,11 @@ def _mock_policy(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - body = {self.res: {'firewall_rules': ['rule2']}} - self.mocked.assert_called_once_with(target, body) + body = {'firewall_rules': ['rule2']} + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) - self.assertEqual(3, self.neutronclient.find_resource.call_count) + self.assertEqual(2, self.networkclient.find_firewall_policy.call_count) + self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) def test_unset_all_firewall_rule(self): target = self.resource['id'] @@ -707,6 +668,6 @@ def test_unset_all_firewall_rule(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - body = {self.res: {'firewall_rules': []}} - self.mocked.assert_called_once_with(target, body) + body = {'firewall_rules': []} + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py index dac94cb74..2714fd055 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py @@ -14,7 +14,6 @@ # under the License. # -import copy import re from unittest import mock @@ -23,7 +22,6 @@ import testtools from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import constants as const from neutronclient.osc.v2.fwaas import firewallrule from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.fwaas import common @@ -48,7 +46,8 @@ def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _fwr if data: source.update(data) - return tuple(_replace_display_columns(key, source[key]) for key in source) + ret = tuple(_replace_display_columns(key, source[key]) for key in source) + return ret def _replace_display_columns(key, val): @@ -59,7 +58,7 @@ def _replace_display_columns(key, val): def _generate_req_and_res(verifylist): request = dict(verifylist) - response = copy.deepcopy(_fwr) + response = _fwr for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] @@ -71,6 +70,10 @@ def _generate_req_and_res(verifylist): new_value = False elif (key == 'protocol' and val and val.lower() == 'any'): new_value = None + elif val is True or val is False: + new_value = val + elif key in ('name', 'description'): + new_value = val else: new_value = val request[converted] = new_value @@ -80,25 +83,20 @@ def _generate_req_and_res(verifylist): class TestFirewallRule(test_fakes.TestNeutronClientOSCV2): - def check_results(self, headers, data, exp_req, is_list=False): + def check_results(self, headers, data, exp_req=None, is_list=False): if is_list: req_body = {self.res_plural: [exp_req]} else: - req_body = {self.res: exp_req} - self.mocked.assert_called_once_with(req_body) + req_body = exp_req + if not exp_req: + self.mocked.assert_called_once_with() + else: + self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, headers) - self.assertItemEqual(self.ordered_data, data) def setUp(self): super(TestFirewallRule, self).setUp() - def _mock_fwr(*args, **kwargs): - self.neutronclient.find_resource.assert_called_once_with( - self.res, self.resource['id'], cmd_resource=const.CMD_FWR) - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = mock.Mock( - side_effect=_mock_fwr) osc_utils.find_project = mock.Mock() osc_utils.find_project.id = _fwr['tenant_id'] self.res = 'firewall_rule' @@ -109,6 +107,7 @@ def _mock_fwr(*args, **kwargs): 'Name', 'Enabled', 'Description', + 'Firewall Policy', 'IP Version', 'Action', 'Protocol', @@ -129,6 +128,7 @@ def _mock_fwr(*args, **kwargs): 'Destination IP Address', 'Destination Port', 'Enabled', + 'Firewall Policy', 'ID', 'IP Version', 'Name', @@ -138,6 +138,7 @@ def _mock_fwr(*args, **kwargs): 'Source Firewall Group ID', 'Source IP Address', 'Source Port', + 'Summary', ) self.ordered_data = ( _fwr['action'], @@ -145,6 +146,7 @@ def _mock_fwr(*args, **kwargs): _fwr['destination_firewall_group_id'], _fwr['destination_ip_address'], _fwr['destination_port'], + _fwr['firewall_policy_id'], _fwr['enabled'], _fwr['id'], _fwr['ip_version'], @@ -179,9 +181,15 @@ class TestCreateFirewallRule(TestFirewallRule, common.TestCreateFWaaS): def setUp(self): super(TestCreateFirewallRule, self).setUp() - self.neutronclient.create_fwaas_firewall_rule = mock.Mock( - return_value={self.res: _fwr}) - self.mocked = self.neutronclient.create_fwaas_firewall_rule + self.networkclient.create_firewall_rule = mock.Mock( + return_value=_fwr) + self.mocked = self.networkclient.create_firewall_rule + + def _mock_find_group(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_firewall_group.side_effect = _mock_find_group + self.cmd = firewallrule.CreateFirewallRule(self.app, self.namespace) def _update_expect_response(self, request, response): @@ -193,8 +201,7 @@ def _update_expect_response(self, request, response): A OrderedDict of request body """ # Update response body - self.neutronclient.create_fwaas_firewall_rule.return_value = \ - {self.res: dict(response)} + self.networkclient.create_firewall_rule.return_value = response osc_utils.find_project.return_value.id = response['tenant_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) @@ -254,17 +261,6 @@ def _set_all_params(self, args={}): return arglist, verifylist def _test_create_with_all_params(self, args={}): - def _mock_fwr(*args, **kwargs): - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_once_with( - const.FWG, 'my-src-fwg', cmd_resource=const.CMD_FWG) - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - const.FWG, 'my-dst-fwg', cmd_resource=const.CMD_FWG) - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = mock.Mock( - side_effect=_mock_fwr) arglist, verifylist = self._set_all_params(args) request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) @@ -279,7 +275,7 @@ def test_create_with_no_options(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) - self.check_results(headers, data, {}) + self.check_results(headers, data, None) def test_create_with_all_params(self): self._test_create_with_all_params() @@ -349,19 +345,19 @@ def _setup_summary(self, expect=None): if expect: if expect.get('protocol'): protocol = expect['protocol'] - if expect.get('source'): - src = expect['source'] - if expect.get('dest'): - dst = expect['dest'] + if expect.get('source_ip_address'): + src_ip = expect['source_ip_address'] + if expect.get('source_port'): + src_port = expect['source_port'] + if expect.get('destination_ip_address'): + dst_ip = expect['destination_ip_address'] + if expect.get('destination_port'): + dst_port = expect['destination_port'] if expect.get('action'): action = expect['action'] - summary = ',\n '.join([protocol, src, dst, action]) - self.short_data = ( - _fwr['id'], - _fwr['name'], - _fwr['enabled'], - summary - ) + src = 'source(port): ' + src_ip + '(' + src_port + ')' + dst = 'dest(port): ' + dst_ip + '(' + dst_port + ')' + return ',\n '.join([protocol, src, dst, action]) def setUp(self): super(TestListFirewallRule, self).setUp() @@ -372,11 +368,21 @@ def setUp(self): 'Name', 'Enabled', 'Summary', + 'Firewall Policy', + ) + + summary = self._setup_summary(_fwr) + + self.short_data = ( + _fwr['id'], + _fwr['name'], + _fwr['enabled'], + summary, + _fwr['firewall_policy_id'] ) - self._setup_summary() - self.neutronclient.list_fwaas_firewall_rules = mock.Mock( - return_value={self.res_plural: [_fwr]}) - self.mocked = self.neutronclient.list_fwaas_firewall_rules + self.networkclient.firewall_rules = mock.Mock( + return_value=[_fwr]) + self.mocked = self.networkclient.firewall_rules def test_list_with_long_option(self): arglist = ['--long'] @@ -386,8 +392,6 @@ def test_list_with_long_option(self): self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) - m = list(data) - self.assertListItemEqual([self.data], m) def test_list_with_no_option(self): arglist = [] @@ -404,9 +408,9 @@ class TestShowFirewallRule(TestFirewallRule, common.TestShowFWaaS): def setUp(self): super(TestShowFirewallRule, self).setUp() - self.neutronclient.show_fwaas_firewall_rule = mock.Mock( - return_value={self.res: _fwr}) - self.mocked = self.neutronclient.show_fwaas_firewall_rule + self.networkclient.get_firewall_rule = mock.Mock( + return_value=_fwr) + self.mocked = self.networkclient.get_firewall_rule self.cmd = firewallrule.ShowFirewallRule(self.app, self.namespace) @@ -414,9 +418,15 @@ class TestSetFirewallRule(TestFirewallRule, common.TestSetFWaaS): def setUp(self): super(TestSetFirewallRule, self).setUp() - self.neutronclient.update_fwaas_firewall_rule = mock.Mock( - return_value={self.res: _fwr}) - self.mocked = self.neutronclient.update_fwaas_firewall_rule + self.networkclient.update_firewall_rule = mock.Mock( + return_value=_fwr) + self.mocked = self.networkclient.update_firewall_rule + + def _mock_find_rule(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_firewall_rule.side_effect = _mock_find_rule + self.cmd = firewallrule.SetFirewallRule(self.app, self.namespace) def test_set_protocol_with_any(self): @@ -430,8 +440,7 @@ def test_set_protocol_with_any(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'protocol': None}}) + self.mocked.assert_called_once_with(target, **{'protocol': None}) self.assertIsNone(result) def test_set_protocol_with_udp(self): @@ -445,8 +454,7 @@ def test_set_protocol_with_udp(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'protocol': protocol}}) + self.mocked.assert_called_once_with(target, **{'protocol': protocol}) self.assertIsNone(result) def test_set_source_ip_address(self): @@ -461,7 +469,7 @@ def test_set_source_ip_address(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'source_ip_address': src_ip}}) + target, **{'source_ip_address': src_ip}) self.assertIsNone(result) def test_set_source_port(self): @@ -476,7 +484,7 @@ def test_set_source_port(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'source_port': src_port}}) + target, **{'source_port': src_port}) self.assertIsNone(result) def test_set_destination_ip_address(self): @@ -491,7 +499,7 @@ def test_set_destination_ip_address(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'destination_ip_address': dst_ip}}) + target, **{'destination_ip_address': dst_ip}) self.assertIsNone(result) def test_set_destination_port(self): @@ -506,7 +514,7 @@ def test_set_destination_port(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'destination_port': dst_port}}) + target, **{'destination_port': dst_port}) self.assertIsNone(result) def test_set_enable_rule(self): @@ -519,8 +527,7 @@ def test_set_enable_rule(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'enabled': True}}) + self.mocked.assert_called_once_with(target, **{'enabled': True}) self.assertIsNone(result) def test_set_disable_rule(self): @@ -533,8 +540,7 @@ def test_set_disable_rule(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'enabled': False}}) + self.mocked.assert_called_once_with(target, **{'enabled': False}) self.assertIsNone(result) def test_set_action(self): @@ -548,8 +554,7 @@ def test_set_action(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'action': action}}) + self.mocked.assert_called_once_with(target, **{'action': action}) self.assertIsNone(result) def test_set_enable_rule_and_disable_rule(self): @@ -578,7 +583,7 @@ def test_set_no_source_ip_address(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'source_ip_address': None}}) + target, **{'source_ip_address': None}) self.assertIsNone(result) def test_set_no_source_port(self): @@ -594,8 +599,7 @@ def test_set_no_source_port(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'source_port': None}}) + self.mocked.assert_called_once_with(target, **{'source_port': None}) self.assertIsNone(result) def test_set_no_destination_ip_address(self): @@ -612,7 +616,7 @@ def test_set_no_destination_ip_address(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'destination_ip_address': None}}) + target, **{'destination_ip_address': None}) self.assertIsNone(result) def test_set_no_destination_port(self): @@ -629,7 +633,7 @@ def test_set_no_destination_port(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'destination_port': None}}) + target, **{'destination_port': None}) self.assertIsNone(result) def test_set_source_ip_address_and_no(self): @@ -697,7 +701,7 @@ def test_set_destination_port_and_no(self): self.check_parser, self.cmd, arglist, verifylist) def test_set_and_raises(self): - self.neutronclient.update_fwaas_firewall_rule = mock.Mock( + self.networkclient.update_firewall_rule = mock.Mock( side_effect=Exception) target = self.resource['id'] arglist = [target, '--name', 'my-name'] @@ -721,7 +725,7 @@ def test_set_no_destination_fwg(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'destination_firewall_group_id': None}}) + target, **{'destination_firewall_group_id': None}) self.assertIsNone(result) def test_set_no_source_fwg(self): @@ -738,7 +742,7 @@ def test_set_no_source_fwg(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'source_firewall_group_id': None}}) + target, **{'source_firewall_group_id': None}) self.assertIsNone(result) def test_create_with_src_fwg_and_no(self): @@ -780,13 +784,19 @@ class TestUnsetFirewallRule(TestFirewallRule, common.TestUnsetFWaaS): def setUp(self): super(TestUnsetFirewallRule, self).setUp() - self.neutronclient.update_fwaas_firewall_rule = mock.Mock( + self.networkclient.update_firewall_rule = mock.Mock( return_value={self.res: _fwr}) - self.mocked = self.neutronclient.update_fwaas_firewall_rule + self.mocked = self.networkclient.update_firewall_rule + + def _mock_find_rule(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_firewall_rule.side_effect = _mock_find_rule + self.cmd = firewallrule.UnsetFirewallRule(self.app, self.namespace) def test_unset_protocol_and_raise(self): - self.neutronclient.update_fwaas_firewall_rule.side_effect = Exception + self.networkclient.update_firewall_rule.side_effect = Exception target = self.resource['id'] arglist = [ target, @@ -813,7 +823,7 @@ def test_unset_source_port(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'source_port': None}}) + target, **{'source_port': None}) self.assertIsNone(result) def test_unset_destination_port(self): @@ -830,7 +840,7 @@ def test_unset_destination_port(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'destination_port': None}}) + target, **{'destination_port': None}) self.assertIsNone(result) def test_unset_source_ip_address(self): @@ -847,7 +857,7 @@ def test_unset_source_ip_address(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'source_ip_address': None}}) + target, **{'source_ip_address': None}) self.assertIsNone(result) def test_unset_destination_ip_address(self): @@ -864,7 +874,7 @@ def test_unset_destination_ip_address(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'destination_ip_address': None}}) + target, **{'destination_ip_address': None}) self.assertIsNone(result) def test_unset_enable_rule(self): @@ -881,7 +891,7 @@ def test_unset_enable_rule(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'enabled': False}}) + target, **{'enabled': False}) self.assertIsNone(result) @@ -889,7 +899,6 @@ class TestDeleteFirewallRule(TestFirewallRule, common.TestDeleteFWaaS): def setUp(self): super(TestDeleteFirewallRule, self).setUp() - self.neutronclient.delete_fwaas_firewall_rule = mock.Mock( - return_value={self.res: _fwr}) - self.mocked = self.neutronclient.delete_fwaas_firewall_rule + self.networkclient.delete_firewall_rule = mock.Mock(return_value=_fwr) + self.mocked = self.networkclient.delete_firewall_rule self.cmd = firewallrule.DeleteFirewallRule(self.app, self.namespace) diff --git a/requirements.txt b/requirements.txt index 3ed2768cc..ff8961688 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ cliff>=3.4.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 iso8601>=0.1.11 # MIT netaddr>=0.7.18 # BSD -openstacksdk>=1.0.2 # Apache-2.0 +openstacksdk>=1.5.0 # Apache-2.0 osc-lib>=1.12.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 From 6597c421ff90576f02403d93a9a38649eabf64dd Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 7 Sep 2023 09:42:55 +0000 Subject: [PATCH 112/149] Update master for stable/2023.2 Add file to the reno documentation build to show release notes for stable/2023.2. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/2023.2. Sem-Ver: feature Change-Id: I7d5138a0e6bbbd33dd2bb737f865e54e4541a279 --- releasenotes/source/2023.2.rst | 6 ++++++ releasenotes/source/index.rst | 1 + 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/2023.2.rst diff --git a/releasenotes/source/2023.2.rst b/releasenotes/source/2023.2.rst new file mode 100644 index 000000000..a4838d7d0 --- /dev/null +++ b/releasenotes/source/2023.2.rst @@ -0,0 +1,6 @@ +=========================== +2023.2 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2023.2 diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index 5dbb2f331..dffa77497 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + 2023.2 2023.1 zed yoga From 396432ab06aeace3d4199a8a42d60fd9b2ebf503 Mon Sep 17 00:00:00 2001 From: elajkat Date: Wed, 21 Jun 2023 15:56:28 +0200 Subject: [PATCH 113/149] OSC: Remove VPNAAS V2 calls to neutronclient Depends-On: https://review.opendev.org/c/openstack/openstacksdk/+/886822 Actually the new SDK release is the dependency, so bump minimum SDK version to 1.5.0. Change-Id: I1933dceb3dc28b464e6e9c4ce468abbd03a00ba4 Related-Bug: #1999774 --- neutronclient/osc/v2/vpnaas/endpoint_group.py | 63 +++++----- neutronclient/osc/v2/vpnaas/ikepolicy.py | 58 ++++++---- .../osc/v2/vpnaas/ipsec_site_connection.py | 109 ++++++++++-------- neutronclient/osc/v2/vpnaas/ipsecpolicy.py | 59 ++++++---- neutronclient/osc/v2/vpnaas/vpnservice.py | 64 ++++++---- .../tests/unit/osc/v2/vpnaas/common.py | 56 ++++++--- .../tests/unit/osc/v2/vpnaas/fakes.py | 30 +++-- .../unit/osc/v2/vpnaas/test_endpoint_group.py | 59 +++++----- .../unit/osc/v2/vpnaas/test_ikepolicy.py | 68 +++++------ .../v2/vpnaas/test_ipsec_site_connection.py | 105 ++++++++--------- .../unit/osc/v2/vpnaas/test_ipsecpolicy.py | 72 ++++++------ .../unit/osc/v2/vpnaas/test_vpnservice.py | 82 ++++++------- 12 files changed, 447 insertions(+), 378 deletions(-) diff --git a/neutronclient/osc/v2/vpnaas/endpoint_group.py b/neutronclient/osc/v2/vpnaas/endpoint_group.py index 668b3d80a..e37c2cef4 100644 --- a/neutronclient/osc/v2/vpnaas/endpoint_group.py +++ b/neutronclient/osc/v2/vpnaas/endpoint_group.py @@ -32,9 +32,19 @@ ('type', 'Type', column_util.LIST_BOTH), ('endpoints', 'Endpoints', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), + ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'type': 'Type', + 'endpoints': 'Endpoints', + 'description': 'Description', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + def _get_common_parser(parser): parser.add_argument( @@ -83,23 +93,22 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.name: attrs['name'] = str(parsed_args.name) attrs['type'] = parsed_args.type if parsed_args.type == 'subnet': - _subnet_ids = [client.find_resource( - 'subnet', + _subnet_ids = [client.find_subnet( endpoint, - cmd_resource='subnet')['id'] - for endpoint in parsed_args.endpoints] + ignore_missing=False)['id'] + for endpoint in parsed_args.endpoints] attrs['endpoints'] = _subnet_ids else: attrs['endpoints'] = parsed_args.endpoints - obj = client.create_endpoint_group( - {'endpoint_group': attrs})['endpoint_group'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_vpn_endpoint_group(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -117,15 +126,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network result = 0 for endpoint in parsed_args.endpoint_group: try: - endpoint_id = client.find_resource( - 'endpoint_group', - endpoint, - cmd_resource='endpoint_group')['id'] - client.delete_endpoint_group(endpoint_id) + endpoint_id = client.find_vpn_endpoint_group( + endpoint, ignore_missing=False)['id'] + client.delete_vpn_endpoint_group(endpoint_id) except Exception as e: result += 1 LOG.error(_("Failed to delete endpoint group with " @@ -153,8 +160,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_endpoint_groups()['endpoint_groups'] + client = self.app.client_manager.network + obj = client.vpn_endpoint_groups() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) @@ -177,17 +184,15 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.name: attrs['name'] = str(parsed_args.name) - endpoint_id = client.find_resource( - 'endpoint_group', parsed_args.endpoint_group, - cmd_resource='endpoint_group')['id'] + endpoint_id = client.find_vpn_endpoint_group( + parsed_args.endpoint_group, ignore_missing=False)['id'] try: - client.update_endpoint_group(endpoint_id, - {'endpoint_group': attrs}) + client.update_vpn_endpoint_group(endpoint_id, **attrs) except Exception as e: msg = (_("Failed to set endpoint group " "%(endpoint_group)s: %(e)s") @@ -207,11 +212,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - endpoint_id = client.find_resource( - 'endpoint_group', parsed_args.endpoint_group, - cmd_resource='endpoint_group')['id'] - obj = client.show_endpoint_group(endpoint_id)['endpoint_group'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + endpoint_id = client.find_vpn_endpoint_group( + parsed_args.endpoint_group, ignore_missing=False)['id'] + obj = client.get_vpn_endpoint_group(endpoint_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) diff --git a/neutronclient/osc/v2/vpnaas/ikepolicy.py b/neutronclient/osc/v2/vpnaas/ikepolicy.py index 73b6402d3..766a550f1 100644 --- a/neutronclient/osc/v2/vpnaas/ikepolicy.py +++ b/neutronclient/osc/v2/vpnaas/ikepolicy.py @@ -38,10 +38,24 @@ ('description', 'Description', column_util.LIST_LONG_ONLY), ('phase1_negotiation_mode', 'Phase1 Negotiation Mode', column_util.LIST_LONG_ONLY), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), + ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('lifetime', 'Lifetime', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'auth_algorithm': 'Authentication Algorithm', + 'encryption_algorithm': 'Encryption Algorithm', + 'ike_version': 'IKE Version', + 'pfs': 'Perfect Forward Secrecy (PFS)', + 'phase1_negotiation_mode': 'Phase1 Negotiation Mode', + 'lifetime': 'Lifetime', + 'description': 'Description', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + def _convert_to_lowercase(string): return string.lower() @@ -89,7 +103,7 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if 'project' in parsed_args and parsed_args.project is not None: - attrs['tenant_id'] = osc_utils.find_project( + attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, @@ -126,12 +140,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.name: attrs['name'] = str(parsed_args.name) - obj = client.create_ikepolicy({'ikepolicy': attrs})['ikepolicy'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_vpn_ike_policy(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', 'units', 'value']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -149,13 +164,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network result = 0 for ike in parsed_args.ikepolicy: try: - ike_id = client.find_resource( - 'ikepolicy', ike, cmd_resource='ikepolicy')['id'] - client.delete_ikepolicy(ike_id) + ike_id = client.find_vpn_ike_policy(ike, + ignore_missing=False)['id'] + client.delete_vpn_ike_policy(ike_id) except Exception as e: result += 1 LOG.error(_("Failed to delete IKE policy with " @@ -182,8 +197,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_ikepolicies()['ikepolicies'] + client = self.app.client_manager.network + obj = client.vpn_ike_policies() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) @@ -206,16 +221,15 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.name: attrs['name'] = parsed_args.name - ike_id = client.find_resource( - 'ikepolicy', parsed_args.ikepolicy, - cmd_resource='ikepolicy')['id'] + ike_id = client.find_vpn_ike_policy(parsed_args.ikepolicy, + ignore_missing=False)['id'] try: - client.update_ikepolicy(ike_id, {'ikepolicy': attrs}) + client.update_vpn_ike_policy(ike_id, **attrs) except Exception as e: msg = (_("Failed to set IKE policy '%(ike)s': %(e)s") % {'ike': parsed_args.ikepolicy, 'e': e}) @@ -234,11 +248,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - ike_id = client.find_resource( - 'ikepolicy', parsed_args.ikepolicy, - cmd_resource='ikepolicy')['id'] - obj = client.show_ikepolicy(ike_id)['ikepolicy'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + ike_id = client.find_vpn_ike_policy(parsed_args.ikepolicy, + ignore_missing=False)['id'] + obj = client.get_vpn_ike_policy(ike_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', 'units', 'value']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) diff --git a/neutronclient/osc/v2/vpnaas/ipsec_site_connection.py b/neutronclient/osc/v2/vpnaas/ipsec_site_connection.py index 4a861f081..1497793b0 100644 --- a/neutronclient/osc/v2/vpnaas/ipsec_site_connection.py +++ b/neutronclient/osc/v2/vpnaas/ipsec_site_connection.py @@ -41,14 +41,14 @@ ('peer_address', 'Peer Address', column_util.LIST_BOTH), ('auth_mode', 'Authentication Algorithm', column_util.LIST_BOTH), ('status', 'Status', column_util.LIST_BOTH), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), + ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('peer_cidrs', 'Peer CIDRs', column_util.LIST_LONG_ONLY), ('vpnservice_id', 'VPN Service', column_util.LIST_LONG_ONLY), ('ipsecpolicy_id', 'IPSec Policy', column_util.LIST_LONG_ONLY), ('ikepolicy_id', 'IKE Policy', column_util.LIST_LONG_ONLY), ('mtu', 'MTU', column_util.LIST_LONG_ONLY), ('initiator', 'Initiator', column_util.LIST_LONG_ONLY), - ('admin_state_up', 'State', column_util.LIST_LONG_ONLY), + ('is_admin_state_up', 'State', column_util.LIST_LONG_ONLY), ('description', 'Description', column_util.LIST_LONG_ONLY), ('psk', 'Pre-shared Key', column_util.LIST_LONG_ONLY), ('route_mode', 'Route Mode', column_util.LIST_LONG_ONLY), @@ -57,8 +57,33 @@ ('local_ep_group_id', 'Local Endpoint Group ID', column_util.LIST_LONG_ONLY), ('peer_ep_group_id', 'Peer Endpoint Group ID', column_util.LIST_LONG_ONLY), + ('dpd', 'DPD', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'peer_address': 'Peer Address', + 'auth_mode': 'Authentication Algorithm', + 'status': 'Status', + 'peer_cidrs': 'Peer CIDRs', + 'vpnservice_id': 'VPN Service', + 'ipsecpolicy_id': 'IPSec Policy', + 'ikepolicy_id': 'IKE Policy', + 'mtu': 'MTU', + 'initiator': 'Initiator', + 'is_admin_state_up': 'State', + 'psk': 'Pre-shared Key', + 'route_mode': 'Route Mode', + 'local_id': 'Local ID', + 'peer_id': 'Peer ID', + 'local_ep_group_id': 'Local Endpoint Group ID', + 'peer_ep_group_id': 'Peer Endpoint Group ID', + 'description': 'Description', + 'project_id': 'Project', + 'dpd': 'DPD', +} + def _convert_to_lowercase(string): return string.lower() @@ -122,7 +147,7 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if 'project' in parsed_args and parsed_args.project is not None: - attrs['tenant_id'] = osc_utils.find_project( + attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, @@ -141,16 +166,12 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): vpn_utils.validate_dpd_dict(parsed_args.dpd) attrs['dpd'] = parsed_args.dpd if parsed_args.local_endpoint_group: - _local_epg = client_manager.neutronclient.find_resource( - 'endpoint_group', - parsed_args.local_endpoint_group, - cmd_resource='endpoint_group')['id'] + _local_epg = client_manager.network.find_vpn_endpoint_group( + parsed_args.local_endpoint_group)['id'] attrs['local_ep_group_id'] = _local_epg if parsed_args.peer_endpoint_group: - _peer_epg = client_manager.neutronclient.find_resource( - 'endpoint_group', - parsed_args.peer_endpoint_group, - cmd_resource='endpoint_group')['id'] + _peer_epg = client_manager.network.find_vpn_endpoint_group( + parsed_args.peer_endpoint_group)['id'] attrs['peer_ep_group_id'] = _peer_epg if parsed_args.peer_cidrs: attrs['peer_cidrs'] = parsed_args.peer_cidrs @@ -203,25 +224,19 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.vpnservice: - _vpnservice_id = client.find_resource( - 'vpnservice', - parsed_args.vpnservice, - cmd_resource='vpnservice')['id'] + _vpnservice_id = client.find_vpn_service( + parsed_args.vpnservice, ignore_missing=False)['id'] attrs['vpnservice_id'] = _vpnservice_id if parsed_args.ikepolicy: - _ikepolicy_id = client.find_resource( - 'ikepolicy', - parsed_args.ikepolicy, - cmd_resource='ikepolicy')['id'] + _ikepolicy_id = client.find_vpn_ike_policy( + parsed_args.ikepolicy, ignore_missing=False)['id'] attrs['ikepolicy_id'] = _ikepolicy_id if parsed_args.ipsecpolicy: - _ipsecpolicy_id = client.find_resource( - 'ipsecpolicy', - parsed_args.ipsecpolicy, - cmd_resource='ipsecpolicy')['id'] + _ipsecpolicy_id = client.find_vpn_ipsec_policy( + parsed_args.ipsecpolicy, ignore_missing=False)['id'] attrs['ipsecpolicy_id'] = _ipsecpolicy_id if parsed_args.peer_id: attrs['peer_id'] = parsed_args.peer_id @@ -239,9 +254,10 @@ def take_action(self, parsed_args): if not parsed_args.peer_cidrs and not parsed_args.local_endpoint_group: message = _("You must specify endpoint groups or peer CIDR(s)") raise exceptions.CommandError(message) - obj = client.create_ipsec_site_connection( - {'ipsec_site_connection': attrs})['ipsec_site_connection'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_vpn_ipsec_site_connection(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', 'action', + 'timeout', 'interval']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return display_columns, data @@ -259,15 +275,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network result = 0 for ipsec_conn in parsed_args.ipsec_site_connection: try: - ipsec_con_id = client.find_resource( - 'ipsec_site_connection', - ipsec_conn, - cmd_resource='ipsec_site_connection')['id'] - client.delete_ipsec_site_connection(ipsec_con_id) + ipsec_con_id = client.find_vpn_ipsec_site_connection( + ipsec_conn, ignore_missing=False)['id'] + client.delete_vpn_ipsec_site_connection(ipsec_con_id) except Exception as e: result += 1 LOG.error(_("Failed to delete IPsec site connection with " @@ -296,8 +310,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_ipsec_site_connections()['ipsec_site_connections'] + client = self.app.client_manager.network + obj = client.vpn_ipsec_site_connections() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( @@ -328,7 +342,7 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.peer_id: @@ -337,13 +351,10 @@ def take_action(self, parsed_args): attrs['peer_address'] = parsed_args.peer_address if parsed_args.name: attrs['name'] = parsed_args.name - ipsec_conn_id = client.find_resource( - 'ipsec_site_connection', parsed_args.ipsec_site_connection, - cmd_resource='ipsec_site_connection')['id'] + ipsec_conn_id = client.find_vpn_ipsec_site_connection( + parsed_args.ipsec_site_connection, ignore_missing=False)['id'] try: - client.update_ipsec_site_connection( - ipsec_conn_id, - {'ipsec_site_connection': attrs}) + client.update_vpn_ipsec_site_connection(ipsec_conn_id, **attrs) except Exception as e: msg = (_("Failed to set IPsec site " "connection '%(ipsec_conn)s': %(e)s") @@ -363,12 +374,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - ipsec_site_id = client.find_resource( - 'ipsec_site_connection', parsed_args.ipsec_site_connection, - cmd_resource='ipsec_site_connection')['id'] - obj = client.show_ipsec_site_connection( - ipsec_site_id)['ipsec_site_connection'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + ipsec_site_id = client.find_vpn_ipsec_site_connection( + parsed_args.ipsec_site_connection, ignore_missing=False)['id'] + obj = client.get_vpn_ipsec_site_connection(ipsec_site_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', 'action', + 'timeout', 'interval']) data = utils.get_dict_properties(obj, columns, formatters=_formatters) return (display_columns, data) diff --git a/neutronclient/osc/v2/vpnaas/ipsecpolicy.py b/neutronclient/osc/v2/vpnaas/ipsecpolicy.py index 2c80543e7..877602ffc 100644 --- a/neutronclient/osc/v2/vpnaas/ipsecpolicy.py +++ b/neutronclient/osc/v2/vpnaas/ipsecpolicy.py @@ -37,10 +37,23 @@ ('encryption_algorithm', 'Encryption Algorithm', column_util.LIST_BOTH), ('pfs', 'Perfect Forward Secrecy (PFS)', column_util.LIST_LONG_ONLY), ('description', 'Description', column_util.LIST_LONG_ONLY), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), + ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('lifetime', 'Lifetime', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'auth_algorithm': 'Authentication Algorithm', + 'encapsulation_mode': 'Encapsulation Mode', + 'transform_protocol': 'Transform Protocol', + 'encryption_algorithm': 'Encryption Algorithm', + 'pfs': 'Perfect Forward Secrecy (PFS)', + 'lifetime': 'Lifetime', + 'description': 'Description', + 'project_id': 'Project', +} + def _convert_to_lowercase(string): return string.lower() @@ -87,7 +100,7 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if 'project' in parsed_args and parsed_args.project is not None: - attrs['tenant_id'] = osc_utils.find_project( + attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, @@ -124,12 +137,14 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.name: attrs['name'] = str(parsed_args.name) - obj = client.create_ipsecpolicy({'ipsecpolicy': attrs})['ipsecpolicy'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_vpn_ipsec_policy(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', + 'phase1_negotiation_mode', 'units', 'value']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -147,13 +162,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network result = 0 for ipsec in parsed_args.ipsecpolicy: try: - ipsec_id = client.find_resource( - 'ipsecpolicy', ipsec, cmd_resource='ipsecpolicy')['id'] - client.delete_ipsecpolicy(ipsec_id) + ipsec_id = client.find_vpn_ipsec_policy( + ipsec, ignore_missing=False)['id'] + client.delete_vpn_ipsec_policy(ipsec_id) except Exception as e: result += 1 LOG.error(_("Failed to delete IPsec policy with " @@ -181,8 +196,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_ipsecpolicies()['ipsecpolicies'] + client = self.app.client_manager.network + obj = client.vpn_ipsec_policies() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) @@ -205,16 +220,15 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.name: attrs['name'] = str(parsed_args.name) - ipsec_id = client.find_resource( - 'ipsecpolicy', parsed_args.ipsecpolicy, - cmd_resource='ipsecpolicy')['id'] + ipsec_id = client.find_vpn_ipsec_policy( + parsed_args.ipsecpolicy, ignore_missing=False)['id'] try: - client.update_ipsecpolicy(ipsec_id, {'ipsecpolicy': attrs}) + client.update_vpn_ipsec_policy(ipsec_id, **attrs) except Exception as e: msg = (_("Failed to set IPsec policy '%(ipsec)s': %(e)s") % {'ipsec': parsed_args.ipsecpolicy, 'e': e}) @@ -233,11 +247,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - ipsec_id = client.find_resource( - 'ipsecpolicy', parsed_args.ipsecpolicy, - cmd_resource='ipsecpolicy')['id'] - obj = client.show_ipsecpolicy(ipsec_id)['ipsecpolicy'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + ipsec_id = client.find_vpn_ipsec_policy( + parsed_args.ipsecpolicy, ignore_missing=False)['id'] + obj = client.get_vpn_ipsec_policy(ipsec_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', + 'phase1_negotiation_mode', 'units', 'value']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) diff --git a/neutronclient/osc/v2/vpnaas/vpnservice.py b/neutronclient/osc/v2/vpnaas/vpnservice.py index 3d5b10e7d..f845a57ff 100644 --- a/neutronclient/osc/v2/vpnaas/vpnservice.py +++ b/neutronclient/osc/v2/vpnaas/vpnservice.py @@ -32,12 +32,24 @@ ('router_id', 'Router', column_util.LIST_BOTH), ('subnet_id', 'Subnet', column_util.LIST_BOTH), ('flavor_id', 'Flavor', column_util.LIST_BOTH), - ('admin_state_up', 'State', column_util.LIST_BOTH), + ('is_admin_state_up', 'State', column_util.LIST_BOTH), ('status', 'Status', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), + ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'router_id': 'Router', + 'subnet_id': 'Subnet', + 'flavor_id': 'Flavor', + 'is_admin_state_up': 'State', + 'status': 'Status', + 'description': 'Description', + 'project_id': 'Project', +} + def _get_common_parser(parser): parser.add_argument( @@ -70,7 +82,7 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} if is_create: if 'project' in parsed_args and parsed_args.project is not None: - attrs['tenant_id'] = osc_utils.find_project( + attrs['project_id'] = osc_utils.find_project( client_manager.identity, parsed_args.project, parsed_args.project_domain, @@ -113,16 +125,18 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) if parsed_args.name: attrs['name'] = str(parsed_args.name) if parsed_args.router: - _router_id = self.app.client_manager.network.find_router( - parsed_args.router).id + _router_id = client.find_router(parsed_args.router, + ignore_missing=False).id attrs['router_id'] = _router_id - obj = client.create_vpnservice({'vpnservice': attrs})['vpnservice'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_vpn_service(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', 'external_v4_ip', + 'external_v6_ip']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -140,13 +154,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network result = 0 for vpn in parsed_args.vpnservice: try: - vpn_id = client.find_resource( - 'vpnservice', vpn, cmd_resource='vpnservice')['id'] - client.delete_vpnservice(vpn_id) + vpn_id = client.find_vpn_service(vpn, + ignore_missing=False)['id'] + client.delete_vpn_service(vpn_id) except Exception as e: result += 1 LOG.error(_("Failed to delete VPN service with " @@ -174,8 +188,8 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_vpnservices()['vpnservices'] + client = self.app.client_manager.network + obj = client.vpn_services() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) for s in obj)) @@ -198,16 +212,15 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.name: attrs['name'] = str(parsed_args.name) - vpn_id = client.find_resource( - 'vpnservice', parsed_args.vpnservice, - cmd_resource='vpnservice')['id'] + vpn_id = client.find_vpn_service(parsed_args.vpnservice, + ignore_missing=False)['id'] try: - client.update_vpnservice(vpn_id, {'vpnservice': attrs}) + client.update_vpn_service(vpn_id, **attrs) except Exception as e: msg = (_("Failed to set vpn service '%(vpn)s': %(e)s") % {'vpn': parsed_args.vpnservice, 'e': e}) @@ -226,11 +239,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - vpn_id = client.find_resource( - 'vpnservice', parsed_args.vpnservice, - cmd_resource='vpnservice')['id'] - obj = client.show_vpnservice(vpn_id)['vpnservice'] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + vpn_id = client.find_vpn_service(parsed_args.vpnservice, + ignore_missing=False)['id'] + obj = client.get_vpn_service(vpn_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', 'external_v4_ip', + 'external_v6_ip']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/common.py b/neutronclient/tests/unit/osc/v2/vpnaas/common.py index 4edee8b97..7aaebdbe3 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/common.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/common.py @@ -29,6 +29,17 @@ class TestDeleteVPNaaS(test_fakes.TestNeutronClientOSCV2): def test_delete_with_one_resource(self): target = self.resource['id'] + + def _mock_vpnaas(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_vpn_endpoint_group.side_effect = _mock_vpnaas + self.networkclient.find_vpn_ipsec_site_connection.side_effect = \ + _mock_vpnaas + self.networkclient.find_vpn_ike_policy.side_effect = _mock_vpnaas + self.networkclient.find_vpn_ipsec_policy.side_effect = _mock_vpnaas + self.networkclient.find_vpn_service.side_effect = _mock_vpnaas + arglist = [target] verifylist = [(self.res, [target])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -40,12 +51,14 @@ def test_delete_with_one_resource(self): def test_delete_with_multiple_resources(self): def _mock_vpnaas(*args, **kwargs): - self.assertEqual(self.res, args[0]) - self.assertIsNotNone(args[1]) - self.assertEqual({'cmd_resource': self.res}, kwargs) - return {'id': args[1]} + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = _mock_vpnaas + self.networkclient.find_vpn_endpoint_group.side_effect = _mock_vpnaas + self.networkclient.find_vpn_ipsec_site_connection.side_effect = \ + _mock_vpnaas + self.networkclient.find_vpn_ike_policy.side_effect = _mock_vpnaas + self.networkclient.find_vpn_ipsec_policy.side_effect = _mock_vpnaas + self.networkclient.find_vpn_service.side_effect = _mock_vpnaas target1 = 'target1' target2 = 'target2' @@ -66,7 +79,19 @@ def test_delete_multiple_with_exception(self): arglist = [target1] verifylist = [(self.res, [target1])] - self.neutronclient.find_resource.side_effect = [ + self.networkclient.find_vpn_ipsec_site_connection.side_effect = [ + target1, exceptions.CommandError + ] + self.networkclient.find_vpn_endpoint_group.side_effect = [ + target1, exceptions.CommandError + ] + self.networkclient.find_vpn_ike_policy.side_effect = [ + target1, exceptions.CommandError + ] + self.networkclient.find_vpn_service.side_effect = [ + target1, exceptions.CommandError + ] + self.networkclient.find_vpn_ipsec_policy.side_effect = [ target1, exceptions.CommandError ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -114,7 +139,7 @@ def test_set_name(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'name': update}}) + target, **{'name': update}) self.assertIsNone(result) def test_set_description(self): @@ -129,7 +154,7 @@ def test_set_description(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'description': update}}) + target, **{'description': update}) self.assertIsNone(result) @@ -139,13 +164,14 @@ def test_show_filtered_by_id_or_name(self): target = self.resource['id'] def _mock_vpnaas(*args, **kwargs): - if self.neutronclient.find_resource.call_count == 1: - self.assertEqual(self.res, args[0]) - self.assertEqual(self.resource['id'], args[1]) - self.assertEqual({'cmd_resource': self.res}, kwargs) - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = _mock_vpnaas + return {'id': args[0]} + + self.networkclient.find_vpn_endpoint_group.side_effect = _mock_vpnaas + self.networkclient.find_vpn_ipsec_site_connection.side_effect = \ + _mock_vpnaas + self.networkclient.find_vpn_ike_policy.side_effect = _mock_vpnaas + self.networkclient.find_vpn_ipsec_policy.side_effect = _mock_vpnaas + self.networkclient.find_vpn_service.side_effect = _mock_vpnaas arglist = [target] verifylist = [(self.res, target)] diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py b/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py index dfad250b3..2344c0a1f 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py @@ -15,10 +15,15 @@ # import collections -import copy from unittest import mock import uuid +from openstack.network.v2 import vpn_endpoint_group as vpn_epg +from openstack.network.v2 import vpn_ike_policy as vpn_ikep +from openstack.network.v2 import vpn_ipsec_policy as vpn_ipsecp +from openstack.network.v2 import vpn_ipsec_site_connection as vpn_sitec +from openstack.network.v2 import vpn_service + class FakeVPNaaS(object): @@ -31,7 +36,14 @@ def create(self, attrs={}): A OrderedDict faking the vpnaas resource """ self.ordered.update(attrs) - return copy.deepcopy(self.ordered) + if 'IKEPolicy' == self.__class__.__name__: + return vpn_ikep.VpnIkePolicy(**self.ordered) + if 'IPSecPolicy' == self.__class__.__name__: + return vpn_ipsecp.VpnIpsecPolicy(**self.ordered) + if 'VPNService' == self.__class__.__name__: + return vpn_service.VpnService(**self.ordered) + if 'EndpointGroup' == self.__class__.__name__: + return vpn_epg.VpnEndpointGroup(**self.ordered) def bulk_create(self, attrs=None, count=2): """Create multiple fake vpnaas resources @@ -74,7 +86,7 @@ def __init__(self): ('pfs', 'group5'), ('description', 'my-desc-' + uuid.uuid4().hex), ('phase1_negotiation_mode', 'main'), - ('tenant_id', 'tenant-id-' + uuid.uuid4().hex), + ('project_id', 'project-id-' + uuid.uuid4().hex), ('lifetime', {'units': 'seconds', 'value': 3600}), )) @@ -93,7 +105,7 @@ def __init__(self): ('encryption_algorithm', 'aes-128'), ('pfs', 'group5'), ('description', 'my-desc-' + uuid.uuid4().hex), - ('tenant_id', 'tenant-id-' + uuid.uuid4().hex), + ('project_id', 'project-id-' + uuid.uuid4().hex), ('lifetime', {'units': 'seconds', 'value': 3600}), )) @@ -112,7 +124,7 @@ def __init__(self): ('admin_state_up', True), ('status', 'ACTIVE'), ('description', 'my-desc-' + uuid.uuid4().hex), - ('tenant_id', 'tenant-id-' + uuid.uuid4().hex), + ('project_id', 'project-id-' + uuid.uuid4().hex), )) @@ -127,7 +139,7 @@ def __init__(self): ('type', 'cidr'), ('endpoints', ['10.0.0.0/24', '20.0.0.0/24']), ('description', 'my-desc-' + uuid.uuid4().hex), - ('tenant_id', 'tenant-id-' + uuid.uuid4().hex), + ('project_id', 'project-id-' + uuid.uuid4().hex), )) @@ -141,7 +153,7 @@ def create_conn(attrs=None): A dictionary with all attributes :return: A Dictionary with id, name, peer_address, auth_mode, status, - tenant_id, peer_cidrs, vpnservice_id, ipsecpolicy_id, + project_id, peer_cidrs, vpnservice_id, ipsecpolicy_id, ikepolicy_id, mtu, initiator, admin_state_up, description, psk, route_mode, local_id, peer_id, local_ep_group_id, peer_ep_group_id @@ -155,7 +167,7 @@ def create_conn(attrs=None): 'peer_address': '192.168.2.10', 'auth_mode': '', 'status': '', - 'tenant_id': 'tenant-id-' + uuid.uuid4().hex, + 'project_id': 'project-id-' + uuid.uuid4().hex, 'peer_cidrs': [], 'vpnservice_id': 'vpnservice-id-' + uuid.uuid4().hex, 'ipsecpolicy_id': 'ipsecpolicy-id-' + uuid.uuid4().hex, @@ -174,4 +186,4 @@ def create_conn(attrs=None): # Overwrite default attributes. conn_attrs.update(attrs) - return copy.deepcopy(conn_attrs) + return vpn_sitec.VpnIPSecSiteConnection(**conn_attrs) diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py index 9c5dbcce5..e9da939b1 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_endpoint_group.py @@ -14,7 +14,6 @@ # under the License. # -import copy from unittest import mock from osc_lib.tests import utils as tests_utils @@ -36,12 +35,12 @@ def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _endpoint_group if data: source.update(data) - return tuple(source[key] for key in source) + return source def _generate_req_and_res(verifylist): request = dict(verifylist) - response = copy.deepcopy(_endpoint_group) + response = _endpoint_group for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] @@ -55,25 +54,25 @@ class TestEndpointGroup(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: - req_body = {self.res_plural: [exp_req]} + req_body = {self.res_plural: list(exp_req)} else: - req_body = {self.res: exp_req} - self.mocked.assert_called_once_with(req_body) - self.assertEqual(self.ordered_headers, headers) + req_body = exp_req + self.mocked.assert_called_once_with(**req_body) + self.assertEqual(self.ordered_headers, tuple(sorted(headers))) self.assertEqual(self.ordered_data, data) def setUp(self): super(TestEndpointGroup, self).setUp() def _mock_endpoint_group(*args, **kwargs): - self.neutronclient.find_resource.assert_called_once_with( - self.res, self.resource['id'], cmd_resource='endpoint_group') - return {'id': args[1]} + self.networkclient.find_vpn_endpoint_group.assert_called_once_with( + self.resource['id'], ignore_missing=False) + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = mock.Mock( + self.networkclient.find_vpn_endpoint_group.side_effect = mock.Mock( side_effect=_mock_endpoint_group) osc_utils.find_project = mock.Mock() - osc_utils.find_project.id = _endpoint_group['tenant_id'] + osc_utils.find_project.id = _endpoint_group['project_id'] self.res = 'endpoint_group' self.res_plural = 'endpoint_groups' self.resource = _endpoint_group @@ -99,7 +98,7 @@ def _mock_endpoint_group(*args, **kwargs): _endpoint_group['endpoints'], _endpoint_group['id'], _endpoint_group['name'], - _endpoint_group['tenant_id'], + _endpoint_group['project_id'], _endpoint_group['type'], ) self.ordered_columns = ( @@ -107,7 +106,7 @@ def _mock_endpoint_group(*args, **kwargs): 'endpoints', 'id', 'name', - 'tenant_id', + 'project_id', 'type', ) @@ -116,9 +115,9 @@ class TestCreateEndpointGroup(TestEndpointGroup, common.TestCreateVPNaaS): def setUp(self): super(TestCreateEndpointGroup, self).setUp() - self.neutronclient.create_endpoint_group = mock.Mock( - return_value={self.res: _endpoint_group}) - self.mocked = self.neutronclient.create_endpoint_group + self.networkclient.create_vpn_endpoint_group = mock.Mock( + return_value=_endpoint_group) + self.mocked = self.networkclient.create_vpn_endpoint_group self.cmd = endpoint_group.CreateEndpointGroup(self.app, self.namespace) def _update_expect_response(self, request, response): @@ -144,7 +143,7 @@ def _set_all_params_cidr(self, args={}): description = args.get('description') or 'my-desc' endpoint_type = args.get('type') or 'cidr' endpoints = args.get('endpoints') or ['10.0.0.0/24', '20.0.0.0/24'] - tenant_id = args.get('tenant_id') or 'my-tenant' + tenant_id = args.get('project_id') or 'my-tenant' arglist = [ '--description', description, '--type', endpoint_type, @@ -186,9 +185,8 @@ class TestDeleteEndpointGroup(TestEndpointGroup, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteEndpointGroup, self).setUp() - self.neutronclient.delete_endpoint_group = mock.Mock( - return_value={self.res: _endpoint_group}) - self.mocked = self.neutronclient.delete_endpoint_group + self.networkclient.delete_vpn_endpoint_group = mock.Mock() + self.mocked = self.networkclient.delete_vpn_endpoint_group self.cmd = endpoint_group.DeleteEndpointGroup(self.app, self.namespace) @@ -212,9 +210,9 @@ def setUp(self): _endpoint_group['endpoints'], ) - self.neutronclient.list_endpoint_groups = mock.Mock( - return_value={self.res_plural: [_endpoint_group]}) - self.mocked = self.neutronclient.list_endpoint_groups + self.networkclient.vpn_endpoint_groups = mock.Mock( + return_value=[_endpoint_group]) + self.mocked = self.networkclient.vpn_endpoint_groups def test_list_with_long_option(self): arglist = ['--long'] @@ -224,7 +222,6 @@ def test_list_with_long_option(self): self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) - self.assertEqual([self.data], list(data)) def test_list_with_no_option(self): arglist = [] @@ -241,9 +238,9 @@ class TestSetEndpointGroup(TestEndpointGroup, common.TestSetVPNaaS): def setUp(self): super(TestSetEndpointGroup, self).setUp() - self.neutronclient.update_endpoint_group = mock.Mock( - return_value={self.res: _endpoint_group}) - self.mocked = self.neutronclient.update_endpoint_group + self.networkclient.update_vpn_endpoint_group = mock.Mock( + return_value=_endpoint_group) + self.mocked = self.networkclient.update_vpn_endpoint_group self.cmd = endpoint_group.SetEndpointGroup(self.app, self.namespace) @@ -251,7 +248,7 @@ class TestShowEndpointGroup(TestEndpointGroup, common.TestShowVPNaaS): def setUp(self): super(TestShowEndpointGroup, self).setUp() - self.neutronclient.show_endpoint_group = mock.Mock( - return_value={self.res: _endpoint_group}) - self.mocked = self.neutronclient.show_endpoint_group + self.networkclient.get_vpn_endpoint_group = mock.Mock( + return_value=_endpoint_group) + self.mocked = self.networkclient.get_vpn_endpoint_group self.cmd = endpoint_group.ShowEndpointGroup(self.app, self.namespace) diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py index cfe65a26b..bf68611f8 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_ikepolicy.py @@ -14,7 +14,6 @@ # under the License. # -import copy from unittest import mock from osc_lib.tests import utils as tests_utils @@ -28,7 +27,7 @@ _ikepolicy = fakes.IKEPolicy().create() CONVERT_MAP = { - 'project': 'tenant_id', + 'project': 'project_id', } @@ -36,12 +35,12 @@ def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _ikepolicy if data: source.update(data) - return tuple(source[key] for key in source) + return source def _generate_req_and_res(verifylist): request = dict(verifylist) - response = copy.deepcopy(_ikepolicy) + response = _ikepolicy for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] @@ -55,25 +54,25 @@ class TestIKEPolicy(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: - req_body = {self.res_plural: [exp_req]} + req_body = {self.res_plural: list(exp_req)} else: - req_body = {self.res: exp_req} - self.mocked.assert_called_once_with(req_body) - self.assertEqual(self.ordered_headers, headers) + req_body = exp_req + self.mocked.assert_called_once_with(**req_body) + self.assertEqual(self.ordered_headers, tuple(sorted(headers))) self.assertEqual(self.ordered_data, data) def setUp(self): super(TestIKEPolicy, self).setUp() def _mock_ikepolicy(*args, **kwargs): - self.neutronclient.find_resource.assert_called_once_with( - self.res, self.resource['id'], cmd_resource='ikepolicy') - return {'id': args[1]} + self.networkclient.find_vpn_ike_policy.assert_called_once_with( + self.resource['id'], ignore_missing=False) + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = mock.Mock( + self.networkclient.find_vpn_ike_policy.side_effect = mock.Mock( side_effect=_mock_ikepolicy) osc_utils.find_project = mock.Mock() - osc_utils.find_project.id = _ikepolicy['tenant_id'] + osc_utils.find_project.id = _ikepolicy['project_id'] self.res = 'ikepolicy' self.res_plural = 'ikepolicies' self.resource = _ikepolicy @@ -112,7 +111,7 @@ def _mock_ikepolicy(*args, **kwargs): _ikepolicy['name'], _ikepolicy['pfs'], _ikepolicy['phase1_negotiation_mode'], - _ikepolicy['tenant_id'], + _ikepolicy['project_id'], ) self.ordered_columns = ( 'auth_algorithm', @@ -124,7 +123,7 @@ def _mock_ikepolicy(*args, **kwargs): 'name', 'pfs', 'phase1_negotiation_mode', - 'tenant_id', + 'project_id', ) @@ -132,9 +131,9 @@ class TestCreateIKEPolicy(TestIKEPolicy, common.TestCreateVPNaaS): def setUp(self): super(TestCreateIKEPolicy, self).setUp() - self.neutronclient.create_ikepolicy = mock.Mock( - return_value={self.res: _ikepolicy}) - self.mocked = self.neutronclient.create_ikepolicy + self.networkclient.create_vpn_ike_policy = mock.Mock( + return_value=_ikepolicy) + self.mocked = self.networkclient.create_vpn_ike_policy self.cmd = ikepolicy.CreateIKEPolicy(self.app, self.namespace) def _update_expect_response(self, request, response): @@ -146,9 +145,8 @@ def _update_expect_response(self, request, response): A OrderedDict of request body """ # Update response body - self.neutronclient.create_ikepolicy.return_value = \ - {self.res: dict(response)} - osc_utils.find_project.return_value.id = response['tenant_id'] + self.networkclient.create_vpn_ikepolicy.return_value = response + osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( @@ -217,9 +215,8 @@ class TestDeleteIKEPolicy(TestIKEPolicy, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteIKEPolicy, self).setUp() - self.neutronclient.delete_ikepolicy = mock.Mock( - return_value={self.res: _ikepolicy}) - self.mocked = self.neutronclient.delete_ikepolicy + self.networkclient.delete_vpn_ike_policy = mock.Mock() + self.mocked = self.networkclient.delete_vpn_ike_policy self.cmd = ikepolicy.DeleteIKEPolicy(self.app, self.namespace) @@ -247,9 +244,9 @@ def setUp(self): _ikepolicy['pfs'], ) - self.neutronclient.list_ikepolicies = mock.Mock( - return_value={self.res_plural: [_ikepolicy]}) - self.mocked = self.neutronclient.list_ikepolicies + self.networkclient.vpn_ike_policies = mock.Mock( + return_value=[_ikepolicy]) + self.mocked = self.networkclient.vpn_ike_policies def test_list_with_long_option(self): arglist = ['--long'] @@ -259,7 +256,6 @@ def test_list_with_long_option(self): self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) - self.assertEqual([self.data], list(data)) def test_list_with_no_option(self): arglist = [] @@ -276,9 +272,9 @@ class TestSetIKEPolicy(TestIKEPolicy, common.TestSetVPNaaS): def setUp(self): super(TestSetIKEPolicy, self).setUp() - self.neutronclient.update_ikepolicy = mock.Mock( - return_value={self.res: _ikepolicy}) - self.mocked = self.neutronclient.update_ikepolicy + self.networkclient.update_vpn_ike_policy = mock.Mock( + return_value=_ikepolicy) + self.mocked = self.networkclient.update_vpn_ike_policy self.cmd = ikepolicy.SetIKEPolicy(self.app, self.namespace) def test_set_auth_algorithm_with_sha256(self): @@ -293,7 +289,7 @@ def test_set_auth_algorithm_with_sha256(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'auth_algorithm': 'sha256'}}) + target, **{'auth_algorithm': 'sha256'}) self.assertIsNone(result) def test_set_phase1_negotiation_mode_with_aggressive(self): @@ -309,7 +305,7 @@ def test_set_phase1_negotiation_mode_with_aggressive(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'phase1_negotiation_mode': 'aggressive'}}) + target, **{'phase1_negotiation_mode': 'aggressive'}) self.assertIsNone(result) @@ -317,7 +313,7 @@ class TestShowIKEPolicy(TestIKEPolicy, common.TestShowVPNaaS): def setUp(self): super(TestShowIKEPolicy, self).setUp() - self.neutronclient.show_ikepolicy = mock.Mock( - return_value={self.res: _ikepolicy}) - self.mocked = self.neutronclient.show_ikepolicy + self.networkclient.get_vpn_ike_policy = mock.Mock( + return_value=_ikepolicy) + self.mocked = self.networkclient.get_vpn_ike_policy self.cmd = ikepolicy.ShowIKEPolicy(self.app, self.namespace) diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py index 96313b459..4929ea843 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsec_site_connection.py @@ -14,7 +14,6 @@ # under the License. # -import copy from unittest import mock from osc_lib.cli import format_columns @@ -29,7 +28,7 @@ _ipsec_site_conn = fakes.IPsecSiteConnection().create_conn() CONVERT_MAP = { - 'project': 'tenant_id', + 'project': 'project_id', 'ikepolicy': 'ikepolicy_id', 'ipsecpolicy': 'ipsecpolicy_id', 'vpnservice': 'vpnservice_id', @@ -42,33 +41,12 @@ def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _ipsec_site_conn if data: source.update(data) - return ( - _ipsec_site_conn['id'], - _ipsec_site_conn['name'], - _ipsec_site_conn['peer_address'], - _ipsec_site_conn['auth_mode'], - _ipsec_site_conn['status'], - _ipsec_site_conn['tenant_id'], - format_columns.ListColumn(_ipsec_site_conn['peer_cidrs']), - _ipsec_site_conn['vpnservice_id'], - _ipsec_site_conn['ipsecpolicy_id'], - _ipsec_site_conn['ikepolicy_id'], - _ipsec_site_conn['mtu'], - _ipsec_site_conn['initiator'], - _ipsec_site_conn['admin_state_up'], - _ipsec_site_conn['description'], - _ipsec_site_conn['psk'], - _ipsec_site_conn['route_mode'], - _ipsec_site_conn['local_id'], - _ipsec_site_conn['peer_id'], - _ipsec_site_conn['local_ep_group_id'], - _ipsec_site_conn['peer_ep_group_id'], - ) + return source def _generate_req_and_res(verifylist): request = dict(verifylist) - response = copy.deepcopy(_ipsec_site_conn) + response = _ipsec_site_conn for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] @@ -82,23 +60,23 @@ class TestIPsecSiteConn(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: - req_body = {self.res_plural: [exp_req]} + req_body = {self.res_plural: list(exp_req)} else: - req_body = {self.res: exp_req} - self.mocked.assert_called_once_with(req_body) - self.assertEqual(self.ordered_headers, headers) + req_body = exp_req + self.mocked.assert_called_once_with(**req_body) + self.assertEqual(self.ordered_headers, tuple(sorted(headers))) self.assertItemEqual(self.ordered_data, data) def setUp(self): super(TestIPsecSiteConn, self).setUp() def _mock_ipsec_site_conn(*args, **kwargs): - return {'id': args[1]} + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = mock.Mock( - side_effect=_mock_ipsec_site_conn) + self.networkclient.find_vpn_ipsec_site_connection.side_effect = \ + mock.Mock(side_effect=_mock_ipsec_site_conn) osc_utils.find_project = mock.Mock() - osc_utils.find_project.id = _ipsec_site_conn['tenant_id'] + osc_utils.find_project.id = _ipsec_site_conn['project_id'] self.res = 'ipsec_site_connection' self.res_plural = 'ipsec_site_connections' self.resource = _ipsec_site_conn @@ -122,11 +100,13 @@ def _mock_ipsec_site_conn(*args, **kwargs): 'Local ID', 'Peer ID', 'Local Endpoint Group ID', - 'Peer Endpoint Group ID' + 'Peer Endpoint Group ID', + 'DPD', ) self.data = _generate_data() self.ordered_headers = ( 'Authentication Algorithm', + 'DPD', 'Description', 'ID', 'IKE Policy', @@ -149,6 +129,7 @@ def _mock_ipsec_site_conn(*args, **kwargs): ) self.ordered_data = ( _ipsec_site_conn['auth_mode'], + _ipsec_site_conn['dpd'], _ipsec_site_conn['description'], _ipsec_site_conn['id'], _ipsec_site_conn['ikepolicy_id'], @@ -163,7 +144,7 @@ def _mock_ipsec_site_conn(*args, **kwargs): _ipsec_site_conn['peer_ep_group_id'], _ipsec_site_conn['peer_id'], _ipsec_site_conn['psk'], - _ipsec_site_conn['tenant_id'], + _ipsec_site_conn['project_id'], _ipsec_site_conn['route_mode'], _ipsec_site_conn['admin_state_up'], _ipsec_site_conn['status'], @@ -175,9 +156,9 @@ class TestCreateIPsecSiteConn(TestIPsecSiteConn, common.TestCreateVPNaaS): def setUp(self): super(TestCreateIPsecSiteConn, self).setUp() - self.neutronclient.create_ipsec_site_connection = mock.Mock( - return_value={self.res: _ipsec_site_conn}) - self.mocked = self.neutronclient.create_ipsec_site_connection + self.networkclient.create_vpn_ipsec_site_connection = mock.Mock( + return_value=_ipsec_site_conn) + self.mocked = self.networkclient.create_vpn_ipsec_site_connection self.cmd = ipsec_site_connection.CreateIPsecSiteConnection( self.app, self.namespace) @@ -190,13 +171,14 @@ def _update_expect_response(self, request, response): A OrderedDict of request body """ # Update response body - self.neutronclient.create_ipsec_site_connection.return_value = \ - {self.res: dict(response)} - osc_utils.find_project.return_value.id = response['tenant_id'] + self.networkclient.create_vpn_ipsec_site_connection.return_value = \ + response + osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = ( response['auth_mode'], + response['dpd'], response['description'], response['id'], response['ikepolicy_id'], @@ -211,7 +193,7 @@ def _update_expect_response(self, request, response): response['peer_ep_group_id'], response['peer_id'], response['psk'], - response['tenant_id'], + response['project_id'], response['route_mode'], response['admin_state_up'], response['status'], @@ -268,6 +250,18 @@ def _set_all_params(self, args={}): def _test_create_with_all_params(self, args={}): arglist, verifylist = self._set_all_params(args) request, response = _generate_req_and_res(verifylist) + + def _mock_endpoint_group(*args, **kwargs): + return {'id': args[0]} + + self.networkclient.find_vpn_endpoint_group.side_effect = mock.Mock( + side_effect=_mock_endpoint_group) + self.networkclient.find_vpn_service.side_effect = mock.Mock( + side_effect=_mock_endpoint_group) + self.networkclient.find_vpn_ike_policy.side_effect = mock.Mock( + side_effect=_mock_endpoint_group) + self.networkclient.find_vpn_ipsec_policy.side_effect = mock.Mock( + side_effect=_mock_endpoint_group) self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) @@ -289,9 +283,8 @@ class TestDeleteIPsecSiteConn(TestIPsecSiteConn, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteIPsecSiteConn, self).setUp() - self.neutronclient.delete_ipsec_site_connection = mock.Mock( - return_value={self.res: _ipsec_site_conn}) - self.mocked = self.neutronclient.delete_ipsec_site_connection + self.networkclient.delete_vpn_ipsec_site_connection = mock.Mock() + self.mocked = self.networkclient.delete_vpn_ipsec_site_connection self.cmd = ipsec_site_connection.DeleteIPsecSiteConnection( self.app, self.namespace) @@ -319,9 +312,9 @@ def setUp(self): _ipsec_site_conn['status'], ) - self.neutronclient.list_ipsec_site_connections = mock.Mock( - return_value={self.res_plural: [_ipsec_site_conn]}) - self.mocked = self.neutronclient.list_ipsec_site_connections + self.networkclient.vpn_ipsec_site_connections = mock.Mock( + return_value=[_ipsec_site_conn]) + self.mocked = self.networkclient.vpn_ipsec_site_connections def test_list_with_long_option(self): arglist = ['--long'] @@ -331,7 +324,6 @@ def test_list_with_long_option(self): self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) - self.assertListItemEqual([self.data], list(data)) def test_list_with_no_option(self): arglist = [] @@ -348,9 +340,9 @@ class TestSetIPsecSiteConn(TestIPsecSiteConn, common.TestSetVPNaaS): def setUp(self): super(TestSetIPsecSiteConn, self).setUp() - self.neutronclient.update_ipsec_site_connection = mock.Mock( - return_value={self.res: _ipsec_site_conn}) - self.mocked = self.neutronclient.update_ipsec_site_connection + self.networkclient.update_vpn_ipsec_site_connection = mock.Mock( + return_value=_ipsec_site_conn) + self.mocked = self.networkclient.update_vpn_ipsec_site_connection self.cmd = ipsec_site_connection.SetIPsecSiteConnection( self.app, self.namespace) @@ -365,8 +357,7 @@ def test_set_ipsec_site_conn_with_peer_id(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {self.res: {'peer_id': peer_id}}) + self.mocked.assert_called_once_with(target, **{'peer_id': peer_id}) self.assertIsNone(result) @@ -374,8 +365,8 @@ class TestShowIPsecSiteConn(TestIPsecSiteConn, common.TestShowVPNaaS): def setUp(self): super(TestShowIPsecSiteConn, self).setUp() - self.neutronclient.show_ipsec_site_connection = mock.Mock( - return_value={self.res: _ipsec_site_conn}) - self.mocked = self.neutronclient.show_ipsec_site_connection + self.networkclient.get_vpn_ipsec_site_connection = mock.Mock( + return_value=_ipsec_site_conn) + self.mocked = self.networkclient.get_vpn_ipsec_site_connection self.cmd = ipsec_site_connection.ShowIPsecSiteConnection( self.app, self.namespace) diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py index 0df98e3f3..3729a11fe 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_ipsecpolicy.py @@ -14,7 +14,6 @@ # under the License. # -import copy from unittest import mock from osc_lib.tests import utils as tests_utils @@ -28,7 +27,7 @@ _ipsecpolicy = fakes.IPSecPolicy().create() CONVERT_MAP = { - 'project': 'tenant_id', + 'project': 'project_id', } @@ -36,12 +35,12 @@ def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _ipsecpolicy if data: source.update(data) - return tuple(source[key] for key in source) + return source def _generate_req_and_res(verifylist): request = dict(verifylist) - response = copy.deepcopy(_ipsecpolicy) + response = _ipsecpolicy for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] @@ -55,10 +54,10 @@ class TestIPSecPolicy(test_fakes.TestNeutronClientOSCV2): def check_results(self, headers, data, exp_req, is_list=False): if is_list: - req_body = {self.res_plural: [exp_req]} + req_body = {self.res_plural: list(exp_req)} else: - req_body = {self.res: exp_req} - self.mocked.assert_called_once_with(req_body) + req_body = exp_req + self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) @@ -66,14 +65,14 @@ def setUp(self): super(TestIPSecPolicy, self).setUp() def _mock_ipsecpolicy(*args, **kwargs): - self.neutronclient.find_resource.assert_called_once_with( - self.res, self.resource['id'], cmd_resource='ipsecpolicy') - return {'id': args[1]} + self.networkclient.find_vpn_ipsec_policy.assert_called_once_with( + self.resource['id'], ignore_missing=False) + return {'id': args[0]} - self.neutronclient.find_resource.side_effect = mock.Mock( + self.networkclient.find_vpn_ipsec_policy.side_effect = mock.Mock( side_effect=_mock_ipsecpolicy) osc_utils.find_project = mock.Mock() - osc_utils.find_project.id = _ipsecpolicy['tenant_id'] + osc_utils.find_project.id = _ipsecpolicy['project_id'] self.res = 'ipsecpolicy' self.res_plural = 'ipsecpolicies' self.resource = _ipsecpolicy @@ -111,7 +110,7 @@ def _mock_ipsecpolicy(*args, **kwargs): _ipsecpolicy['lifetime'], _ipsecpolicy['name'], _ipsecpolicy['pfs'], - _ipsecpolicy['tenant_id'], + _ipsecpolicy['project_id'], _ipsecpolicy['transform_protocol'], ) self.ordered_columns = ( @@ -123,7 +122,7 @@ def _mock_ipsecpolicy(*args, **kwargs): 'lifetime', 'name', 'pfs', - 'tenant_id', + 'project_id', 'transform_protocol', ) @@ -132,9 +131,9 @@ class TestCreateIPSecPolicy(TestIPSecPolicy, common.TestCreateVPNaaS): def setUp(self): super(TestCreateIPSecPolicy, self).setUp() - self.neutronclient.create_ipsecpolicy = mock.Mock( - return_value={self.res: _ipsecpolicy}) - self.mocked = self.neutronclient.create_ipsecpolicy + self.networkclient.create_vpn_ipsec_policy = mock.Mock( + return_value=_ipsecpolicy) + self.mocked = self.networkclient.create_vpn_ipsec_policy self.cmd = ipsecpolicy.CreateIPsecPolicy(self.app, self.namespace) def _update_expect_response(self, request, response): @@ -146,9 +145,9 @@ def _update_expect_response(self, request, response): A OrderedDict of request body """ # Update response body - self.neutronclient.create_ipsecpolicy.return_value = \ - {self.res: dict(response)} - osc_utils.find_project.return_value.id = response['tenant_id'] + self.networkclient.create_vpn_ipsec_policy.return_value = \ + response + osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( @@ -163,7 +162,7 @@ def _set_all_params(self, args={}): encryption_algorithm = args.get('encryption_algorithm') or 'aes-128' pfs = args.get('pfs') or 'group5' description = args.get('description') or 'my-desc' - tenant_id = args.get('tenant_id') or 'my-tenant' + project_id = args.get('project_id') or 'my-project' arglist = [ name, '--auth-algorithm', auth_algorithm, @@ -172,7 +171,7 @@ def _set_all_params(self, args={}): '--encryption-algorithm', encryption_algorithm, '--pfs', pfs, '--description', description, - '--project', tenant_id, + '--project', project_id, ] verifylist = [ ('name', name), @@ -182,7 +181,7 @@ def _set_all_params(self, args={}): ('encryption_algorithm', encryption_algorithm), ('pfs', pfs), ('description', description), - ('project', tenant_id), + ('project', project_id), ] return arglist, verifylist @@ -192,7 +191,6 @@ def _test_create_with_all_params(self, args={}): self._update_expect_response(request, response) parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) - self.check_results(headers, data, request) def test_create_with_no_options(self): @@ -213,9 +211,8 @@ class TestDeleteIPSecPolicy(TestIPSecPolicy, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteIPSecPolicy, self).setUp() - self.neutronclient.delete_ipsecpolicy = mock.Mock( - return_value={self.res: _ipsecpolicy}) - self.mocked = self.neutronclient.delete_ipsecpolicy + self.networkclient.delete_vpn_ipsec_policy = mock.Mock() + self.mocked = self.networkclient.delete_vpn_ipsec_policy self.cmd = ipsecpolicy.DeleteIPsecPolicy(self.app, self.namespace) @@ -243,9 +240,9 @@ def setUp(self): _ipsecpolicy['encryption_algorithm'], ) - self.neutronclient.list_ipsecpolicies = mock.Mock( - return_value={self.res_plural: [_ipsecpolicy]}) - self.mocked = self.neutronclient.list_ipsecpolicies + self.networkclient.vpn_ipsec_policies = mock.Mock( + return_value=[_ipsecpolicy]) + self.mocked = self.networkclient.vpn_ipsec_policies def test_list_with_long_option(self): arglist = ['--long'] @@ -255,7 +252,6 @@ def test_list_with_long_option(self): self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) - self.assertEqual([self.data], list(data)) def test_list_with_no_option(self): arglist = [] @@ -272,9 +268,9 @@ class TestSetIPSecPolicy(TestIPSecPolicy, common.TestSetVPNaaS): def setUp(self): super(TestSetIPSecPolicy, self).setUp() - self.neutronclient.update_ipsecpolicy = mock.Mock( - return_value={self.res: _ipsecpolicy}) - self.mocked = self.neutronclient.update_ipsecpolicy + self.networkclient.update_vpn_ipsec_policy = mock.Mock( + return_value=_ipsecpolicy) + self.mocked = self.networkclient.update_vpn_ipsec_policy self.cmd = ipsecpolicy.SetIPsecPolicy(self.app, self.namespace) def test_set_auth_algorithm_with_sha256(self): @@ -289,7 +285,7 @@ def test_set_auth_algorithm_with_sha256(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'auth_algorithm': 'sha256'}}) + target, **{'auth_algorithm': 'sha256'}) self.assertIsNone(result) @@ -297,7 +293,7 @@ class TestShowIPSecPolicy(TestIPSecPolicy, common.TestShowVPNaaS): def setUp(self): super(TestShowIPSecPolicy, self).setUp() - self.neutronclient.show_ipsecpolicy = mock.Mock( - return_value={self.res: _ipsecpolicy}) - self.mocked = self.neutronclient.show_ipsecpolicy + self.networkclient.get_vpn_ipsec_policy = mock.Mock( + return_value=_ipsecpolicy) + self.mocked = self.networkclient.get_vpn_ipsec_policy self.cmd = ipsecpolicy.ShowIPsecPolicy(self.app, self.namespace) diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py index 7630eb8e0..458c7f654 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py @@ -14,7 +14,6 @@ # under the License. # -import copy from unittest import mock import uuid @@ -28,7 +27,7 @@ _vpnservice = fakes.VPNService().create() CONVERT_MAP = { - 'project': 'tenant_id', + 'project': 'project_id', 'router': 'router_id', 'subnet': 'subnet_id' } @@ -38,12 +37,12 @@ def _generate_data(ordered_dict=None, data=None): source = ordered_dict if ordered_dict else _vpnservice if data: source.update(data) - return tuple(source[key] for key in source) + return source def _generate_req_and_res(verifylist): request = dict(verifylist) - response = copy.deepcopy(_vpnservice) + response = _vpnservice for key, val in verifylist: converted = CONVERT_MAP.get(key, key) del request[key] @@ -57,10 +56,10 @@ class TestVPNService(test_fakes.TestNeutronClientOSCV2): def _check_results(self, headers, data, exp_req, is_list=False): if is_list: - req_body = {self.res_plural: [exp_req]} + req_body = {self.res_plural: list(exp_req)} else: - req_body = {self.res: exp_req} - self.mocked.assert_called_once_with(req_body) + req_body = exp_req + self.mocked.assert_called_once_with(**req_body) self.assertEqual(self.ordered_headers, headers) self.assertEqual(self.ordered_data, data) @@ -68,23 +67,20 @@ def setUp(self): super(TestVPNService, self).setUp() def _mock_vpnservice(*args, **kwargs): - self.neutronclient.find_resource.assert_called_once_with( - self.res, self.resource['id'], cmd_resource='vpnservice') - return {'id': args[1]} + self.networkclient.find_vpn_service.assert_called_once_with( + self.resource['id'], ignore_missing=False) + return {'id': args[0]} - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_router = mock.Mock() - self.app.client_manager.network.find_subnet = mock.Mock() + self.networkclient.find_router = mock.Mock() + self.networkclient.find_subnet = mock.Mock() self.fake_router = mock.Mock() self.fake_subnet = mock.Mock() - self.app.client_manager.network.find_router.return_value = \ - self.fake_router - self.app.client_manager.network.find_subnet.return_value = \ - self.fake_subnet + self.networkclient.find_router.return_value = self.fake_router + self.networkclient.find_subnet.return_value = self.fake_subnet self.args = { 'name': 'my-name', 'description': 'my-desc', - 'tenant_id': 'tenant-id-' + uuid.uuid4().hex, + 'project_id': 'project-id-' + uuid.uuid4().hex, 'router_id': 'router-id-' + uuid.uuid4().hex, 'subnet_id': 'subnet-id-' + uuid.uuid4().hex, @@ -92,10 +88,10 @@ def _mock_vpnservice(*args, **kwargs): self.fake_subnet.id = self.args['subnet_id'] self.fake_router.id = self.args['router_id'] - self.neutronclient.find_resource.side_effect = mock.Mock( + self.networkclient.find_vpn_service.side_effect = mock.Mock( side_effect=_mock_vpnservice) osc_utils.find_project = mock.Mock() - osc_utils.find_project.id = _vpnservice['tenant_id'] + osc_utils.find_project.id = _vpnservice['project_id'] self.res = 'vpnservice' self.res_plural = 'vpnservices' @@ -128,7 +124,7 @@ def _mock_vpnservice(*args, **kwargs): _vpnservice['flavor_id'], _vpnservice['id'], _vpnservice['name'], - _vpnservice['tenant_id'], + _vpnservice['project_id'], _vpnservice['router_id'], _vpnservice['admin_state_up'], _vpnservice['status'], @@ -139,7 +135,7 @@ def _mock_vpnservice(*args, **kwargs): 'flavor_id', 'id', 'name', - 'tenant_id', + 'project_id', 'router_id', 'admin_state_up', 'status', @@ -151,9 +147,9 @@ class TestCreateVPNService(TestVPNService, common.TestCreateVPNaaS): def setUp(self): super(TestCreateVPNService, self).setUp() - self.neutronclient.create_vpnservice = mock.Mock( - return_value={self.res: _vpnservice}) - self.mocked = self.neutronclient.create_vpnservice + self.networkclient.create_vpn_service = mock.Mock( + return_value=_vpnservice) + self.mocked = self.networkclient.create_vpn_service self.cmd = vpnservice.CreateVPNService(self.app, self.namespace) def _update_expect_response(self, request, response): @@ -165,9 +161,8 @@ def _update_expect_response(self, request, response): A OrderedDict of request body """ # Update response body - self.neutronclient.create_vpnservice.return_value = \ - {self.res: dict(response)} - osc_utils.find_project.return_value.id = response['tenant_id'] + self.networkclient.create_vpn_service.return_value = response + osc_utils.find_project.return_value.id = response['project_id'] # Update response(finally returns 'data') self.data = _generate_data(ordered_dict=response) self.ordered_data = tuple( @@ -179,17 +174,17 @@ def _set_all_params(self): description = self.args.get('description') router_id = self.args.get('router_id') subnet_id = self.args.get('subnet_id') - tenant_id = self.args.get('tenant_id') + project_id = self.args.get('project_id') arglist = [ '--description', description, - '--project', tenant_id, + '--project', project_id, '--subnet', subnet_id, '--router', router_id, name, ] verifylist = [ ('description', description), - ('project', tenant_id), + ('project', project_id), ('subnet', subnet_id), ('router', router_id), ('name', name), @@ -213,9 +208,8 @@ class TestDeleteVPNService(TestVPNService, common.TestDeleteVPNaaS): def setUp(self): super(TestDeleteVPNService, self).setUp() - self.neutronclient.delete_vpnservice = mock.Mock( - return_value={self.res: _vpnservice}) - self.mocked = self.neutronclient.delete_vpnservice + self.networkclient.delete_vpn_service = mock.Mock() + self.mocked = self.networkclient.delete_vpn_service self.cmd = vpnservice.DeleteVPNService(self.app, self.namespace) @@ -245,9 +239,8 @@ def setUp(self): _vpnservice['status'], ) - self.neutronclient.list_vpnservices = mock.Mock( - return_value={self.res_plural: [_vpnservice]}) - self.mocked = self.neutronclient.list_vpnservices + self.networkclient.vpn_services = mock.Mock(return_value=[_vpnservice]) + self.mocked = self.networkclient.vpn_services def test_list_with_long_option(self): arglist = ['--long'] @@ -257,7 +250,6 @@ def test_list_with_long_option(self): self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) - self.assertEqual([self.data], list(data)) def test_list_with_no_option(self): arglist = [] @@ -274,9 +266,9 @@ class TestSetVPNService(TestVPNService, common.TestSetVPNaaS): def setUp(self): super(TestSetVPNService, self).setUp() - self.neutronclient.update_vpnservice = mock.Mock( - return_value={self.res: _vpnservice}) - self.mocked = self.neutronclient.update_vpnservice + self.networkclient.update_vpn_service = mock.Mock( + return_value=_vpnservice) + self.mocked = self.networkclient.update_vpn_service self.cmd = vpnservice.SetVPNSercice(self.app, self.namespace) def test_set_name(self): @@ -291,7 +283,7 @@ def test_set_name(self): result = self.cmd.take_action(parsed_args) self.mocked.assert_called_once_with( - target, {self.res: {'name': update}}) + target, **{'name': update}) self.assertIsNone(result) @@ -299,7 +291,7 @@ class TestShowVPNService(TestVPNService, common.TestShowVPNaaS): def setUp(self): super(TestShowVPNService, self).setUp() - self.neutronclient.show_vpnservice = mock.Mock( - return_value={self.res: _vpnservice}) - self.mocked = self.neutronclient.show_vpnservice + self.networkclient.get_vpn_service = mock.Mock( + return_value=_vpnservice) + self.mocked = self.networkclient.get_vpn_service self.cmd = vpnservice.ShowVPNService(self.app, self.namespace) From b9152a5042b107d7fcb9c84463e3760b3d02af40 Mon Sep 17 00:00:00 2001 From: elajkat Date: Thu, 29 Jun 2023 16:17:18 +0200 Subject: [PATCH 114/149] OSC: Remove SFC V2 calls to neutronclient Change SFC CLI to use SDK instead of deprecated neutronclient python bindings. Add possibility to delete multiple resources as it is common for other delete commands. Bump SDK minimum version to 1.5.0. Depends-On: https://review.opendev.org/c/openstack/openstacksdk/+/887387 Actually the new SDK release is the dependency. Related-Bug: #1999774 Change-Id: Ic22b8163155904113db8a4acf1fe7d75ae100a84 --- .../osc/v2/sfc/sfc_flow_classifier.py | 98 +++++--- neutronclient/osc/v2/sfc/sfc_port_chain.py | 147 +++++++----- neutronclient/osc/v2/sfc/sfc_port_pair.py | 89 ++++--- .../osc/v2/sfc/sfc_port_pair_group.py | 112 +++++---- neutronclient/osc/v2/sfc/sfc_service_graph.py | 81 ++++--- neutronclient/tests/unit/osc/v2/sfc/fakes.py | 62 +++-- .../unit/osc/v2/sfc/test_flow_classifier.py | 95 ++++---- .../tests/unit/osc/v2/sfc/test_port_chain.py | 224 +++++++----------- .../tests/unit/osc/v2/sfc/test_port_pair.py | 99 ++++---- .../unit/osc/v2/sfc/test_port_pair_group.py | 194 ++++++--------- .../unit/osc/v2/sfc/test_service_graph.py | 72 +++--- 11 files changed, 653 insertions(+), 620 deletions(-) diff --git a/neutronclient/osc/v2/sfc/sfc_flow_classifier.py b/neutronclient/osc/v2/sfc/sfc_flow_classifier.py index d223674c4..775730fc2 100755 --- a/neutronclient/osc/v2/sfc/sfc_flow_classifier.py +++ b/neutronclient/osc/v2/sfc/sfc_flow_classifier.py @@ -55,6 +55,26 @@ ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'description': 'Description', + 'summary': 'Summary', + 'protocol': 'Protocol', + 'ethertype': 'Ethertype', + 'source_ip_prefix': 'Source IP', + 'destination_ip_prefix': 'Destination IP', + 'logical_source_port': 'Logical Source Port', + 'logical_destination_port': 'Logical Destination Port', + 'source_port_range_min': 'Source Port Range Min', + 'source_port_range_max': 'Source Port Range Max', + 'destination_port_range_min': 'Destination Port Range Min', + 'destination_port_range_max': 'Destination Port Range Max', + 'l7_parameters': 'L7 Parameters', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + class CreateSfcFlowClassifier(command.ShowOne): _description = _("Create a flow classifier") @@ -114,11 +134,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) - body = {resource: attrs} - obj = client.create_sfc_flow_classifier(body)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_sfc_flow_classifier(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', 'summary']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -131,20 +151,27 @@ def get_parser(self, prog_name): parser.add_argument( 'flow_classifier', metavar='', - help=_("Flow classifier to delete (name or ID)") + nargs='+', + help=_("Flow classifier(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): - # TODO(mohan): Add support for deleting multiple resources. - client = self.app.client_manager.neutronclient - fc_id = _get_id(client, parsed_args.flow_classifier, resource) - try: - client.delete_sfc_flow_classifier(fc_id) - except Exception as e: - msg = (_("Failed to delete flow classifier with name " - "or ID '%(fc)s': %(e)s") - % {'fc': parsed_args.flow_classifier, 'e': e}) + client = self.app.client_manager.network + result = 0 + for fcl in parsed_args.flow_classifier: + try: + fc_id = client.find_sfc_flow_classifier( + fcl, ignore_missing=False)['id'] + client.delete_sfc_flow_classifier(fc_id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete flow classifier with name " + "or ID '%(fc)s': %(e)s"), {'fc': fcl, 'e': e}) + if result > 0: + total = len(parsed_args.flow_classifier) + msg = (_("%(result)s of %(total)s flow classifier(s) " + "failed to delete.") % {'result': result, 'total': total}) raise exceptions.CommandError(msg) @@ -161,8 +188,8 @@ def get_parser(self, prog_name): return parser def extend_list(self, data, parsed_args): - ext_data = data['flow_classifiers'] - for d in ext_data: + ext_data = [] + for d in data: val = [] protocol = d['protocol'].upper() if d['protocol'] else 'any' val.append('protocol: ' + protocol) @@ -180,6 +207,7 @@ def extend_list(self, data, parsed_args): l7_param = 'l7_parameters: {%s}' % ','.join(d['l7_parameters']) val.append(l7_param) d['summary'] = ',\n'.join(val) + ext_data.append(d) return ext_data def _get_protocol_port_details(self, data, val): @@ -197,8 +225,8 @@ def _get_protocol_port_details(self, data, val): val, ip_prefix, min_port, max_port) def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - obj = client.list_sfc_flow_classifiers() + client = self.app.client_manager.network + obj = client.sfc_flow_classifiers() obj_extend = self.extend_list(obj, parsed_args) headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) @@ -227,13 +255,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fc_id = _get_id(client, parsed_args.flow_classifier, resource) + client = self.app.client_manager.network + fc_id = client.find_sfc_flow_classifier(parsed_args.flow_classifier, + ignore_missing=False)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) - body = {resource: attrs} try: - client.update_sfc_flow_classifier(fc_id, body) + client.update_sfc_flow_classifier(fc_id, **attrs) except Exception as e: msg = (_("Failed to update flow classifier '%(fc)s': %(e)s") % {'fc': parsed_args.flow_classifier, 'e': e}) @@ -253,10 +281,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - fc_id = _get_id(client, parsed_args.flow_classifier, resource) - obj = client.show_sfc_flow_classifier(fc_id)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + fc_id = client.find_sfc_flow_classifier(parsed_args.flow_classifier, + ignore_missing=False)['id'] + obj = client.get_sfc_flow_classifier(fc_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id', 'summary']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -282,13 +312,13 @@ def _get_attrs(client_manager, attrs, parsed_args): if parsed_args.destination_ip_prefix is not None: attrs['destination_ip_prefix'] = parsed_args.destination_ip_prefix if parsed_args.logical_source_port is not None: - attrs['logical_source_port'] = _get_id( - client_manager.neutronclient, parsed_args.logical_source_port, - 'port') + attrs['logical_source_port'] = client_manager.network.find_port( + parsed_args.logical_source_port, ignore_missing=False + )['id'] if parsed_args.logical_destination_port is not None: - attrs['logical_destination_port'] = _get_id( - client_manager.neutronclient, parsed_args.logical_destination_port, - 'port') + attrs['logical_destination_port'] = client_manager.network.find_port( + parsed_args.logical_destination_port, ignore_missing=False + )['id'] if parsed_args.source_port is not None: _fill_protocol_port_info(attrs, 'source', parsed_args.source_port) @@ -314,7 +344,3 @@ def _fill_protocol_port_info(attrs, port_type, port_val): message = (_("Protocol port value %s must be an integer " "or integer:integer.") % port_val) raise nc_exc.CommandError(message=message) - - -def _get_id(client, id_or_name, resource): - return client.find_resource(resource, id_or_name)['id'] diff --git a/neutronclient/osc/v2/sfc/sfc_port_chain.py b/neutronclient/osc/v2/sfc/sfc_port_chain.py index 4ce790dc3..d96007b85 100755 --- a/neutronclient/osc/v2/sfc/sfc_port_chain.py +++ b/neutronclient/osc/v2/sfc/sfc_port_chain.py @@ -36,10 +36,20 @@ ('chain_parameters', 'Chain Parameters', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), - ('chain_id', 'Chain ID', column_util.LIST_BOTH), ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'port_pair_groups': 'Port Pair Groups', + 'flow_classifiers': 'Flow Classifiers', + 'chain_parameters': 'Chain Parameters', + 'description': 'Description', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + class CreateSfcPortChain(command.ShowOne): _description = _("Create a port chain") @@ -81,11 +91,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) - body = {resource: attrs} - obj = client.create_sfc_port_chain(body)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_sfc_port_chain(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -98,20 +108,28 @@ def get_parser(self, prog_name): parser.add_argument( 'port_chain', metavar="", - help=_("Port chain to delete (name or ID)") + nargs='+', + help=_("Port chain(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): - # TODO(mohan): Add support for deleting multiple resources. - client = self.app.client_manager.neutronclient - pc_id = _get_id(client, parsed_args.port_chain, resource) - try: - client.delete_sfc_port_chain(pc_id) - except Exception as e: - msg = (_("Failed to delete port chain with name " - "or ID '%(pc)s': %(e)s") - % {'pc': parsed_args.port_chain, 'e': e}) + client = self.app.client_manager.network + result = 0 + for pc in parsed_args.port_chain: + try: + pc_id = client.find_sfc_port_chain( + pc, ignore_missing=False)['id'] + client.delete_sfc_port_chain(pc_id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete port chain with name " + "or ID '%(pc)s': %(e)s"), {'pc': pc, 'e': e}) + if result > 0: + total = len(parsed_args.port_chain) + msg = (_("%(result)s of %(total)s port chain(s) " + "failed to delete.") % {'result': result, + 'total': total}) raise exceptions.CommandError(msg) @@ -129,13 +147,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - data = client.list_sfc_port_chains() + client = self.app.client_manager.network + data = client.sfc_port_chains() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) - for s in data['port_chains'])) + for s in data)) class SetSfcPortChain(command.Command): @@ -184,8 +202,9 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - pc_id = _get_id(client, parsed_args.port_chain, resource) + client = self.app.client_manager.network + pc_id = client.find_sfc_port_chain(parsed_args.port_chain, + ignore_missing=False)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.no_flow_classifier: @@ -194,13 +213,14 @@ def take_action(self, parsed_args): if parsed_args.no_flow_classifier: fc_list = [] else: - fc_list = client.find_resource( - resource, parsed_args.port_chain, - cmd_resource='sfc_port_chain')['flow_classifiers'] + fc_list = client.find_sfc_port_chain( + parsed_args.port_chain, + ignore_missing=False + )['flow_classifiers'] for fc in parsed_args.flow_classifiers: - fc_id = client.find_resource( - 'flow_classifier', fc, - cmd_resource='sfc_flow_classifier')['id'] + fc_id = client.find_sfc_flow_classifier( + fc, + ignore_missing=False)['id'] if fc_id not in fc_list: fc_list.append(fc_id) attrs['flow_classifiers'] = fc_list @@ -211,27 +231,25 @@ def take_action(self, parsed_args): if parsed_args.no_port_pair_group and parsed_args.port_pair_groups: ppg_list = [] for ppg in parsed_args.port_pair_groups: - ppg_id = client.find_resource( - 'port_pair_group', ppg, - cmd_resource='sfc_port_pair_group')['id'] + ppg_id = client.find_sfc_port_pair_group( + ppg, ignore_missing=False)['id'] if ppg_id not in ppg_list: ppg_list.append(ppg_id) attrs['port_pair_groups'] = ppg_list if (parsed_args.port_pair_groups and not parsed_args.no_port_pair_group): - ppg_list = client.find_resource( - resource, parsed_args.port_chain, - cmd_resource='sfc_port_chain')['port_pair_groups'] + ppg_list = client.find_sfc_port_chain( + parsed_args.port_chain, + ignore_missing=False + )['port_pair_groups'] for ppg in parsed_args.port_pair_groups: - ppg_id = client.find_resource( - 'port_pair_group', ppg, - cmd_resource='sfc_port_pair_group')['id'] + ppg_id = client.find_sfc_port_pair_group( + ppg, ignore_missing=False)['id'] if ppg_id not in ppg_list: ppg_list.append(ppg_id) attrs['port_pair_groups'] = ppg_list - body = {resource: attrs} try: - client.update_sfc_port_chain(pc_id, body) + client.update_sfc_port_chain(pc_id, **attrs) except Exception as e: msg = (_("Failed to update port chain '%(pc)s': %(e)s") % {'pc': parsed_args.port_chain, 'e': e}) @@ -251,10 +269,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - pc_id = _get_id(client, parsed_args.port_chain, resource) - obj = client.show_sfc_port_chain(pc_id)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + pc_id = client.find_sfc_port_chain(parsed_args.port_chain, + ignore_missing=False)['id'] + obj = client.get_sfc_port_chain(pc_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -290,30 +310,31 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - pc_id = _get_id(client, parsed_args.port_chain, resource) + client = self.app.client_manager.network + pc_id = client.find_sfc_port_chain(parsed_args.port_chain, + ignore_missing=False)['id'] attrs = {} if parsed_args.flow_classifiers: - fc_list = client.find_resource( - resource, parsed_args.port_chain, - cmd_resource='sfc_port_chain')['flow_classifiers'] + fc_list = client.find_sfc_port_chain( + parsed_args.port_chain, ignore_missing=False + )['flow_classifiers'] for fc in parsed_args.flow_classifiers: - fc_id = client.find_resource( - 'flow_classifier', fc, - cmd_resource='sfc_flow_classifier')['id'] + fc_id = client.find_sfc_flow_classifier( + fc, + ignore_missing=False)['id'] if fc_id in fc_list: fc_list.remove(fc_id) attrs['flow_classifiers'] = fc_list if parsed_args.all_flow_classifier: attrs['flow_classifiers'] = [] if parsed_args.port_pair_groups: - ppg_list = client.find_resource( - resource, parsed_args.port_chain, - cmd_resource='sfc_port_chain')['port_pair_groups'] + ppg_list = client.find_sfc_port_chain( + parsed_args.port_chain, + ignore_missing=False)['port_pair_groups'] for ppg in parsed_args.port_pair_groups: - ppg_id = client.find_resource( - 'port_pair_group', ppg, - cmd_resource='sfc_port_pair_group')['id'] + ppg_id = client.find_sfc_port_pair_group( + ppg, + ignore_missing=False)['id'] if ppg_id in ppg_list: ppg_list.remove(ppg_id) if ppg_list == []: @@ -321,9 +342,8 @@ def take_action(self, parsed_args): ' specified.') raise exceptions.CommandError(message) attrs['port_pair_groups'] = ppg_list - body = {resource: attrs} try: - client.update_sfc_port_chain(pc_id, body) + client.update_sfc_port_chain(pc_id, **attrs) except Exception as e: msg = (_("Failed to unset port chain '%(pc)s': %(e)s") % {'pc': parsed_args.port_chain, 'e': e}) @@ -332,17 +352,18 @@ def take_action(self, parsed_args): def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} + client = client_manager.network if parsed_args.name is not None: attrs['name'] = parsed_args.name if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.port_pair_groups: - attrs['port_pair_groups'] = [(_get_id(client_manager.neutronclient, - ppg, 'port_pair_group')) + attrs['port_pair_groups'] = [client.find_sfc_port_pair_group( + ppg, ignore_missing=False)['id'] for ppg in parsed_args.port_pair_groups] if parsed_args.flow_classifiers: - attrs['flow_classifiers'] = [(_get_id(client_manager.neutronclient, fc, - 'flow_classifier')) + attrs['flow_classifiers'] = [client.find_sfc_flow_classifier( + fc, ignore_missing=False)['id'] for fc in parsed_args.flow_classifiers] if is_create is True: _get_attrs(attrs, parsed_args) @@ -358,7 +379,3 @@ def _get_attrs(attrs, parsed_args): if 'symmetric' in chain_param: chain_params['symmetric'] = chain_param['symmetric'] attrs['chain_parameters'] = chain_params - - -def _get_id(client, id_or_name, resource): - return client.find_resource(resource, id_or_name)['id'] diff --git a/neutronclient/osc/v2/sfc/sfc_port_pair.py b/neutronclient/osc/v2/sfc/sfc_port_pair.py index 68d131cdd..11e8e7631 100755 --- a/neutronclient/osc/v2/sfc/sfc_port_pair.py +++ b/neutronclient/osc/v2/sfc/sfc_port_pair.py @@ -38,6 +38,17 @@ ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'description': 'Description', + 'ingress': 'Ingress Logical Port', + 'egress': 'Egress Logical Port', + 'service_function_parameters': 'Service Function Parameters', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + class CreateSfcPortPair(command.ShowOne): _description = _("Create a port pair") @@ -76,11 +87,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) - body = {resource: attrs} - obj = client.create_sfc_port_pair(body)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_sfc_port_pair(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -93,20 +104,29 @@ def get_parser(self, prog_name): parser.add_argument( 'port_pair', metavar="", - help=_("Port pair to delete (name or ID)") + nargs='+', + help=_("Port pair(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): - # TODO(mohan): Add support for deleting multiple resources. - client = self.app.client_manager.neutronclient - port_pair_id = _get_id(client, parsed_args.port_pair, resource) - try: - client.delete_sfc_port_pair(port_pair_id) - except Exception as e: - msg = (_("Failed to delete port pair with name " - "or ID '%(port_pair)s': %(e)s") - % {'port_pair': parsed_args.port_pair, 'e': e}) + client = self.app.client_manager.network + result = 0 + for pp in parsed_args.port_pair: + try: + port_pair_id = client.find_sfc_port_pair( + pp, ignore_missing=False)['id'] + client.delete_sfc_port_pair(port_pair_id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete port pair with name " + "or ID '%(port_pair)s': %(e)s"), + {'port_pair': pp, 'e': e}) + if result > 0: + total = len(parsed_args.port_pair) + msg = (_("%(result)s of %(total)s port pair(s) " + "failed to delete.") % {'result': result, + 'total': total}) raise exceptions.CommandError(msg) @@ -123,14 +143,14 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - data = client.list_sfc_port_pairs() + client = self.app.client_manager.network + data = client.sfc_port_pairs() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns, - ) for s in data['port_pairs'])) + ) for s in data)) class SetSfcPortPair(command.Command): @@ -154,13 +174,14 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - port_pair_id = _get_id(client, parsed_args.port_pair, resource) + client = self.app.client_manager.network + port_pair_id = client.find_sfc_port_pair( + parsed_args.port_pair, ignore_missing=False + )['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) - body = {resource: attrs} try: - client.update_sfc_port_pair(port_pair_id, body) + client.update_sfc_port_pair(port_pair_id, **attrs) except Exception as e: msg = (_("Failed to update port pair '%(port_pair)s': %(e)s") % {'port_pair': parsed_args.port_pair, 'e': e}) @@ -180,10 +201,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - port_pair_id = _get_id(client, parsed_args.port_pair, resource) - obj = client.show_sfc_port_pair(port_pair_id)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + port_pair_id = client.find_sfc_port_pair( + parsed_args.port_pair, ignore_missing=False + )['id'] + obj = client.get_sfc_port_pair(port_pair_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -200,12 +224,15 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): def _get_attrs(client_manager, attrs, parsed_args): + client = client_manager.network if parsed_args.ingress is not None: - attrs['ingress'] = _get_id(client_manager.neutronclient, - parsed_args.ingress, 'port') + attrs['ingress'] = client.find_port( + parsed_args.ingress, ignore_missing=False + )['id'] if parsed_args.egress is not None: - attrs['egress'] = _get_id(client_manager.neutronclient, - parsed_args.egress, 'port') + attrs['egress'] = client.find_port( + parsed_args.egress, ignore_missing=False + )['id'] if parsed_args.service_function_parameters is not None: attrs['service_function_parameters'] = _get_service_function_params( parsed_args.service_function_parameters) @@ -222,7 +249,3 @@ def _get_service_function_params(sf_params): if 'weight' in sf_param: attrs['weight'] = sf_param['weight'] return attrs - - -def _get_id(client, id_or_name, resource): - return client.find_resource(resource, id_or_name)['id'] diff --git a/neutronclient/osc/v2/sfc/sfc_port_pair_group.py b/neutronclient/osc/v2/sfc/sfc_port_pair_group.py index 8e7fadd26..5ad3ebea7 100755 --- a/neutronclient/osc/v2/sfc/sfc_port_pair_group.py +++ b/neutronclient/osc/v2/sfc/sfc_port_pair_group.py @@ -34,11 +34,21 @@ ('port_pair_group_parameters', 'Port Pair Group Parameters', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), - ('group_id', 'Loadbalance ID', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), - ('tap_enabled', 'Tap Enabled', column_util.LIST_BOTH) + ('is_tap_enabled', 'Tap Enabled', column_util.LIST_BOTH) ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'description': 'Description', + 'port_pairs': 'Port Pair', + 'port_pair_group_parameters': 'Port Pair Group Parameters', + 'is_tap_enabled': 'Tap Enabled', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + class CreateSfcPortPairGroup(command.ShowOne): _description = _("Create a port pair group") @@ -85,11 +95,11 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) - body = {resource: attrs} - obj = client.create_sfc_port_pair_group(body)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_sfc_port_pair_group(**attrs) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -102,20 +112,28 @@ def get_parser(self, prog_name): parser.add_argument( 'port_pair_group', metavar='', - help=_("Port pair group to delete (name or ID)") + nargs='+', + help=_("Port pair group(s) to delete (name or ID)") ) return parser def take_action(self, parsed_args): - # TODO(mohan): Add support for deleting multiple resources. - client = self.app.client_manager.neutronclient - ppg_id = _get_id(client, parsed_args.port_pair_group, resource) - try: - client.delete_sfc_port_pair_group(ppg_id) - except Exception as e: - msg = (_("Failed to delete port pair group with name " - "or ID '%(ppg)s': %(e)s") - % {'ppg': parsed_args.port_pair_group, 'e': e}) + client = self.app.client_manager.network + result = 0 + for ppg in parsed_args.port_pair_group: + try: + ppg_id = client.find_sfc_port_pair_group( + ppg, ignore_missing=False)['id'] + client.delete_sfc_port_pair_group(ppg_id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete port pair group with name " + "or ID '%(ppg)s': %(e)s"), {'ppg': ppg, 'e': e}) + if result > 0: + total = len(parsed_args.port_pair_group) + msg = (_("%(result)s of %(total)s port pair group(s) " + "failed to delete.") % {'result': result, + 'total': total}) raise exceptions.CommandError(msg) @@ -133,14 +151,14 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - data = client.list_sfc_port_pair_groups() + client = self.app.client_manager.network + data = client.sfc_port_pair_groups() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties( s, columns, - ) for s in data['port_pair_groups'])) + ) for s in data)) class SetSfcPortPairGroup(command.Command): @@ -175,26 +193,26 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - ppg_id = _get_id(client, parsed_args.port_pair_group, resource) + client = self.app.client_manager.network + ppg_id = client.find_sfc_port_pair_group( + parsed_args.port_pair_group)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) if parsed_args.no_port_pair: attrs['port_pairs'] = [] if parsed_args.port_pairs: - added = [client.find_resource('port_pair', pp, - cmd_resource='sfc_port_pair')['id'] + added = [client.find_sfc_port_pair(pp, + ignore_missing=False)['id'] for pp in parsed_args.port_pairs] if parsed_args.no_port_pair: existing = [] else: - existing = client.find_resource( - resource, parsed_args.port_pair_group, - cmd_resource='sfc_port_pair_group')['port_pairs'] + existing = client.find_sfc_port_pair_group( + parsed_args.port_pair_group, + ignore_missing=False)['port_pairs'] attrs['port_pairs'] = sorted(list(set(existing) | set(added))) - body = {resource: attrs} try: - client.update_sfc_port_pair_group(ppg_id, body) + client.update_sfc_port_pair_group(ppg_id, **attrs) except Exception as e: msg = (_("Failed to update port pair group '%(ppg)s': %(e)s") % {'ppg': parsed_args.port_pair_group, 'e': e}) @@ -214,10 +232,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - ppg_id = _get_id(client, parsed_args.port_pair_group, resource) - obj = client.show_sfc_port_pair_group(ppg_id)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + ppg_id = client.find_sfc_port_pair_group( + parsed_args.port_pair_group, ignore_missing=False)['id'] + obj = client.get_sfc_port_pair_group(ppg_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -246,22 +266,22 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - ppg_id = _get_id(client, parsed_args.port_pair_group, resource) + client = self.app.client_manager.network + ppg_id = client.find_sfc_port_pair_group( + parsed_args.port_pair_group, ignore_missing=False)['id'] attrs = {} if parsed_args.port_pairs: - existing = client.find_resource( - resource, parsed_args.port_pair_group, - cmd_resource='sfc_port_pair_group')['port_pairs'] - removed = [client.find_resource('port_pair', pp, - cmd_resource='sfc_port_pair')['id'] + existing = client.find_sfc_port_pair_group( + parsed_args.port_pair_group, + ignore_missing=False)['port_pairs'] + removed = [client.find_sfc_port_pair(pp, + ignore_missing=False)['id'] for pp in parsed_args.port_pairs] attrs['port_pairs'] = list(set(existing) - set(removed)) if parsed_args.all_port_pair: attrs['port_pairs'] = [] - body = {resource: attrs} try: - client.update_sfc_port_pair_group(ppg_id, body) + client.update_sfc_port_pair_group(ppg_id, **attrs) except Exception as e: msg = (_("Failed to unset port pair group '%(ppg)s': %(e)s") % {'ppg': parsed_args.port_pair_group, 'e': e}) @@ -280,15 +300,17 @@ def _get_ppg_param(attrs, ppg): def _get_common_attrs(client_manager, parsed_args, is_create=True): + client = client_manager.network attrs = {} if parsed_args.name is not None: attrs['name'] = parsed_args.name if parsed_args.description is not None: attrs['description'] = parsed_args.description if parsed_args.port_pairs: - attrs['port_pairs'] = [(_get_id(client_manager.neutronclient, pp, - 'port_pair')) + attrs['port_pairs'] = [client.find_sfc_port_pair( + pp, ignore_missing=False)['id'] for pp in parsed_args.port_pairs] + if is_create: _get_attrs(attrs, parsed_args) return attrs @@ -302,7 +324,3 @@ def _get_attrs(attrs, parsed_args): attrs['tap_enabled'] = True if parsed_args.disable_tap: attrs['tap_enabled'] = False - - -def _get_id(client, id_or_name, resource): - return client.find_resource(resource, id_or_name)['id'] diff --git a/neutronclient/osc/v2/sfc/sfc_service_graph.py b/neutronclient/osc/v2/sfc/sfc_service_graph.py index fc4772675..6c87d95fe 100644 --- a/neutronclient/osc/v2/sfc/sfc_service_graph.py +++ b/neutronclient/osc/v2/sfc/sfc_service_graph.py @@ -33,6 +33,15 @@ ('project_id', 'Project', column_util.LIST_LONG_ONLY), ) +_attr_map_dict = { + 'id': 'ID', + 'name': 'Name', + 'description': 'Description', + 'port_chains': 'Branching Points', + 'tenant_id': 'Project', + 'project_id': 'Project', +} + class CreateSfcServiceGraph(command.ShowOne): """Create a service graph.""" @@ -57,12 +66,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args) try: - body = {resource: attrs} - obj = client.create_sfc_service_graph(body)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + obj = client.create_sfc_service_graph(**attrs) + display_columns, columns = \ + utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data except Exception as e: @@ -92,13 +102,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - service_graph_id = _get_id(client, parsed_args.service_graph, resource) + client = self.app.client_manager.network + service_graph_id = client.find_sfc_service_graph( + parsed_args.service_graph, ignore_missing=False)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) - body = {resource: attrs} try: - client.update_sfc_service_graph(service_graph_id, body) + client.update_sfc_service_graph(service_graph_id, **attrs) except Exception as e: msg = (_("Failed to update service graph " "'%(service_graph)s': %(e)s") @@ -114,14 +124,30 @@ def get_parser(self, prog_name): parser.add_argument( 'service_graph', metavar="", - help=_("ID or name of the service graph to delete.") + nargs='+', + help=_("ID or name of the service graph(s) to delete.") ) return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - id = _get_id(client, parsed_args.service_graph, resource) - client.delete_sfc_service_graph(id) + client = self.app.client_manager.network + result = 0 + for sg in parsed_args.service_graph: + try: + sg_id = client.find_sfc_service_graph( + sg, ignore_missing=False)['id'] + client.delete_sfc_service_graph(sg_id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete service graph with name " + "or ID '%(sg)s': %(e)s"), + {'sg': sg, 'e': e}) + if result > 0: + total = len(parsed_args.service_graph) + msg = (_("%(result)s of %(total)s service graph(s) " + "failed to delete.") % {'result': result, + 'total': total}) + raise exceptions.CommandError(msg) class ListSfcServiceGraph(command.Lister): @@ -138,13 +164,13 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - data = client.list_sfc_service_graphs() + client = self.app.client_manager.network + data = client.sfc_service_graphs() headers, columns = column_util.get_column_definitions( _attr_map, long_listing=parsed_args.long) return (headers, (utils.get_dict_properties(s, columns) - for s in data['service_graphs'])) + for s in data)) class ShowSfcServiceGraph(command.ShowOne): @@ -160,10 +186,12 @@ def get_parser(self, prog_name): return parser def take_action(self, parsed_args): - client = self.app.client_manager.neutronclient - sg_id = _get_id(client, parsed_args.service_graph, resource) - obj = client.show_sfc_service_graph(sg_id)[resource] - columns, display_columns = column_util.get_columns(obj, _attr_map) + client = self.app.client_manager.network + sg_id = client.find_sfc_service_graph(parsed_args.service_graph, + ignore_missing=False)['id'] + obj = client.get_sfc_service_graph(sg_id) + display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -179,10 +207,10 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): return attrs -def _validate_destination_chains(comma_split, attrs, client_manager, sc_): +def _validate_destination_chains(comma_split, attrs, client, sc_): for e in comma_split: if e != "": - dc_ = _get_id(client_manager.neutronclient, e, 'port_chain') + dc_ = client.find_sfc_port_chain(e, ignore_missing=False)['id'] attrs['port_chains'][sc_].append(dc_) if _check_cycle(attrs['port_chains'], sc_, dc_): raise(exceptions.CommandError( @@ -214,6 +242,7 @@ def _visit(graph, src, new_dest, new_src): def _get_attrs_for_create(client_manager, attrs, parsed_args): + client = client_manager.network if parsed_args.branching_points: attrs['port_chains'] = {} src_chain = None @@ -224,8 +253,8 @@ def _get_attrs_for_create(client_manager, attrs, parsed_args): "destination chain for each source chain.") colon_split = c.split(':') src_chain = colon_split.pop(0) - sc_ = _get_id(client_manager.neutronclient, - src_chain, 'port_chain') + sc_ = client.find_sfc_port_chain(src_chain, + ignore_missing=False)['id'] for i in colon_split: comma_split = i.split(',') unique = set(comma_split) @@ -240,8 +269,4 @@ def _get_attrs_for_create(client_manager, attrs, parsed_args): "use already ".format(src_chain)) attrs['port_chains'][sc_] = [] _validate_destination_chains( - comma_split, attrs, client_manager, sc_) - - -def _get_id(client, id_or_name, resource): - return client.find_resource(resource, id_or_name)['id'] + comma_split, attrs, client, sc_) diff --git a/neutronclient/tests/unit/osc/v2/sfc/fakes.py b/neutronclient/tests/unit/osc/v2/sfc/fakes.py index ba07107fd..390c67e4e 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/fakes.py +++ b/neutronclient/tests/unit/osc/v2/sfc/fakes.py @@ -14,13 +14,18 @@ # under the License. import argparse -import copy from unittest import mock from osc_lib.tests import utils from oslo_utils import uuidutils +from openstack.network.v2 import sfc_flow_classifier as flow_classifier +from openstack.network.v2 import sfc_port_chain as port_chain +from openstack.network.v2 import sfc_port_pair as port_pair +from openstack.network.v2 import sfc_port_pair_group as port_pair_group +from openstack.network.v2 import sfc_service_graph as service_graph + class TestNeutronClientOSCV2(utils.TestCommand): @@ -28,12 +33,32 @@ def setUp(self): super(TestNeutronClientOSCV2, self).setUp() self.namespace = argparse.Namespace() self.app.client_manager.session = mock.Mock() - self.app.client_manager.neutronclient = mock.Mock() - self.neutronclient = self.app.client_manager.neutronclient - self.neutronclient.find_resource = mock.Mock( - side_effect=lambda resource, name_or_id, project_id=None, - cmd_resource=None, parent_id=None, fields=None: - {'id': name_or_id}) + self.app.client_manager.network = mock.Mock() + self.network = self.app.client_manager.network + self.network.find_sfc_flow_classifier = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id} + ) + self.network.find_sfc_port_chain = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id} + ) + self.network.find_sfc_port_pair = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id} + ) + self.network.find_sfc_port_pair_group = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id} + ) + self.network.find_sfc_service_graph = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id} + ) + self.network.find_port = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id} + ) class FakeSfcPortPair(object): @@ -58,13 +83,14 @@ def create_port_pair(attrs=None): 'id': uuidutils.generate_uuid(), 'ingress': uuidutils.generate_uuid(), 'name': 'port-pair-name', - 'service_function_parameters': 'correlation=None,weight=1', + 'service_function_parameters': [('correlation', None), + ('weight', 1)], 'project_id': uuidutils.generate_uuid(), } # Overwrite default attributes. port_pair_attrs.update(attrs) - return copy.deepcopy(port_pair_attrs) + return port_pair.SfcPortPair(**port_pair_attrs) @staticmethod def create_port_pairs(attrs=None, count=1): @@ -102,18 +128,16 @@ def create_port_pair_group(attrs=None): # Set default attributes. port_pair_group_attrs = { 'id': uuidutils.generate_uuid(), - 'group_id': uuidutils.generate_uuid(), 'name': 'port-pair-group-name', 'description': 'description', 'port_pairs': uuidutils.generate_uuid(), - 'port_pair_group_parameters': '{"lb_fields": []}', + 'port_pair_group_parameters': {"lb_fields": []}, 'project_id': uuidutils.generate_uuid(), 'tap_enabled': False } - # port_pair_group_attrs default attributes. port_pair_group_attrs.update(attrs) - return copy.deepcopy(port_pair_group_attrs) + return port_pair_group.SfcPortPairGroup(**port_pair_group_attrs) @staticmethod def create_port_pair_groups(attrs=None, count=1): @@ -164,10 +188,10 @@ def create_flow_classifier(attrs=None): 'source_port_range_max': '20', 'source_port_range_min': '10', 'project_id': uuidutils.generate_uuid(), - 'l7_parameters': '{}' + 'l7_parameters': {} } flow_classifier_attrs.update(attrs) - return copy.deepcopy(flow_classifier_attrs) + return flow_classifier.SfcFlowClassifier(**flow_classifier_attrs) @staticmethod def create_flow_classifiers(attrs=None, count=1): @@ -205,18 +229,16 @@ def create_port_chain(attrs=None): # Set default attributes. port_chain_attrs = { 'id': uuidutils.generate_uuid(), - 'chain_id': uuidutils.generate_uuid(), 'name': 'port-chain-name', 'description': 'description', 'port_pair_groups': uuidutils.generate_uuid(), 'flow_classifiers': uuidutils.generate_uuid(), - 'chain_parameters': '{"correlation": mpls}', + 'chain_parameters': {"correlation": "mpls", "symmetric": False}, 'project_id': uuidutils.generate_uuid(), } - # port_pair_group_attrs default attributes. port_chain_attrs.update(attrs) - return copy.deepcopy(port_chain_attrs) + return port_chain.SfcPortChain(**port_chain_attrs) @staticmethod def create_port_chains(attrs=None, count=1): @@ -260,7 +282,7 @@ def create_sfc_service_graph(attrs=None): } service_graph_attrs.update(attrs) - return copy.deepcopy(service_graph_attrs) + return service_graph.SfcServiceGraph(**service_graph_attrs) @staticmethod def create_sfc_service_graphs(attrs=None, count=1): diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py b/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py index 379f72767..6a9e691f9 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py @@ -15,15 +15,12 @@ from unittest import mock +from osc_lib import exceptions +import testtools + from neutronclient.osc.v2.sfc import sfc_flow_classifier from neutronclient.tests.unit.osc.v2.sfc import fakes -get_id = 'neutronclient.osc.v2.sfc.sfc_flow_classifier._get_id' - - -def _get_id(client, id_or_name, resource): - return id_or_name - class TestCreateSfcFlowClassifier(fakes.TestNeutronClientOSCV2): @@ -43,7 +40,8 @@ class TestCreateSfcFlowClassifier(fakes.TestNeutronClientOSCV2): 'Protocol', 'Source IP', 'Source Port Range Max', - 'Source Port Range Min') + 'Source Port Range Min', + 'Summary',) def get_data(self): return ( @@ -66,9 +64,8 @@ def get_data(self): def setUp(self): super(TestCreateSfcFlowClassifier, self).setUp() - mock.patch(get_id, new=_get_id).start() - self.neutronclient.create_sfc_flow_classifier = mock.Mock( - return_value={'flow_classifier': self._fc}) + self.network.create_sfc_flow_classifier = mock.Mock( + return_value=self._fc) self.data = self.get_data() # Get the command object to test @@ -90,14 +87,13 @@ def test_create_flow_classifier_default_options(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_flow_classifier.assert_called_once_with({ - 'flow_classifier': { - 'name': self._fc['name'], - 'logical_source_port': self._fc['logical_source_port'], - 'ethertype': self._fc['ethertype']} - }) + self.network.create_sfc_flow_classifier.assert_called_once_with( + **{'name': self._fc['name'], + 'logical_source_port': self._fc['logical_source_port'], + 'ethertype': self._fc['ethertype'] + } + ) self.assertEqual(self.columns, columns) - self.assertEqual(self.data, data) def test_create_flow_classifier(self): arglist = [ @@ -129,8 +125,8 @@ def test_create_flow_classifier(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_flow_classifier.assert_called_once_with({ - 'flow_classifier': { + self.network.create_sfc_flow_classifier.assert_called_once_with( + **{ 'name': self._fc['name'], 'description': self._fc['description'], 'ethertype': self._fc['ethertype'], @@ -142,9 +138,8 @@ def test_create_flow_classifier(self): self._fc['logical_destination_port'], 'l7_parameters': param } - }) + ) self.assertEqual(self.columns, columns) - self.assertEqual(self.data, data) class TestDeleteSfcFlowClassifier(fakes.TestNeutronClientOSCV2): @@ -154,20 +149,19 @@ class TestDeleteSfcFlowClassifier(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestDeleteSfcFlowClassifier, self).setUp() - mock.patch(get_id, new=_get_id).start() - self.neutronclient.delete_sfc_flow_classifier = mock.Mock( + self.network.delete_sfc_flow_classifier = mock.Mock( return_value=None) self.cmd = sfc_flow_classifier.DeleteSfcFlowClassifier(self.app, self.namespace) def test_delete_flow_classifier(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_flow_classifier_delete = client.delete_sfc_flow_classifier arglist = [ self._flow_classifier[0]['id'], ] verifylist = [ - ('flow_classifier', self._flow_classifier[0]['id']), + ('flow_classifier', [self._flow_classifier[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -175,6 +169,22 @@ def test_delete_flow_classifier(self): self._flow_classifier[0]['id']) self.assertIsNone(result) + def test_delete_multiple_flow_classifiers_with_exception(self): + client = self.app.client_manager.network + target1 = self._flow_classifier[0]['id'] + arglist = [target1] + verifylist = [('flow_classifier', [target1])] + + client.find_sfc_flow_classifier.side_effect = [ + target1, exceptions.CommandError + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + msg = "1 of 2 flow classifier(s) failed to delete." + with testtools.ExpectedException(exceptions.CommandError) as e: + self.cmd.take_action(parsed_args) + self.assertEqual(msg, str(e)) + class TestSetSfcFlowClassifier(fakes.TestNeutronClientOSCV2): _flow_classifier = fakes.FakeSfcFlowClassifier.create_flow_classifier() @@ -183,14 +193,13 @@ class TestSetSfcFlowClassifier(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestSetSfcFlowClassifier, self).setUp() - mock.patch(get_id, new=_get_id).start() - self.neutronclient.update_sfc_flow_classifier = mock.Mock( + self.network.update_sfc_flow_classifier = mock.Mock( return_value=None) self.cmd = sfc_flow_classifier.SetSfcFlowClassifier(self.app, self.namespace) def test_set_flow_classifier(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_flow_classifier_update = client.update_sfc_flow_classifier arglist = [ self._flow_classifier_name, @@ -206,11 +215,11 @@ def test_set_flow_classifier(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'flow_classifier': { + attrs = { 'name': 'name_updated', - 'description': 'desc_updated'}} + 'description': 'desc_updated'} mock_flow_classifier_update.assert_called_once_with( - self._flow_classifier_name, attrs) + self._flow_classifier_name, **attrs) self.assertIsNone(result) @@ -234,7 +243,7 @@ class TestShowSfcFlowClassifier(fakes.TestNeutronClientOSCV2): _fc['source_port_range_max'], _fc['source_port_range_min'] ) - _flow_classifier = {'flow_classifier': _fc} + _flow_classifier = _fc _flow_classifier_id = _fc['id'] columns = ('Description', 'Destination IP', @@ -250,12 +259,12 @@ class TestShowSfcFlowClassifier(fakes.TestNeutronClientOSCV2): 'Protocol', 'Source IP', 'Source Port Range Max', - 'Source Port Range Min') + 'Source Port Range Min', + 'Summary',) def setUp(self): super(TestShowSfcFlowClassifier, self).setUp() - mock.patch(get_id, new=_get_id).start() - self.neutronclient.show_sfc_flow_classifier = mock.Mock( + self.network.get_sfc_flow_classifier = mock.Mock( return_value=self._flow_classifier ) # Get the command object to test @@ -263,8 +272,8 @@ def setUp(self): self.namespace) def test_show_flow_classifier(self): - client = self.app.client_manager.neutronclient - mock_flow_classifier_show = client.show_sfc_flow_classifier + client = self.app.client_manager.network + mock_flow_classifier_show = client.get_sfc_flow_classifier arglist = [ self._flow_classifier_id, ] @@ -277,7 +286,6 @@ def test_show_flow_classifier(self): mock_flow_classifier_show.assert_called_once_with( self._flow_classifier_id) self.assertEqual(self.columns, columns) - self.assertEqual(self.data, data) class TestListSfcFlowClassifier(fakes.TestNeutronClientOSCV2): @@ -324,9 +332,8 @@ class TestListSfcFlowClassifier(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestListSfcFlowClassifier, self).setUp() - mock.patch(get_id, new=_get_id).start() - self.neutronclient.list_sfc_flow_classifiers = mock.Mock( - return_value={'flow_classifiers': self._fc} + self.network.sfc_flow_classifiers = mock.Mock( + return_value=self._fc ) # Get the command object to test self.cmd = sfc_flow_classifier.ListSfcFlowClassifier(self.app, @@ -337,8 +344,7 @@ def test_list_flow_classifiers(self): verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args) - fcs = self.neutronclient \ - .list_sfc_flow_classifiers()['flow_classifiers'] + fcs = self.network.sfc_flow_classifiers() fc = fcs[0] data = [ fc['id'], @@ -355,8 +361,7 @@ def test_list_flow_classifiers(self): def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] - fcs = self.neutronclient \ - .list_sfc_flow_classifiers()['flow_classifiers'] + fcs = self.network.sfc_flow_classifiers() fc = fcs[0] data = [ fc['id'], diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py b/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py index da6455230..9b414c22c 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py @@ -16,6 +16,7 @@ from unittest import mock from osc_lib import exceptions +import testtools from neutronclient.osc.v2.sfc import sfc_port_chain from neutronclient.tests.unit.osc.v2.sfc import fakes @@ -29,8 +30,7 @@ class TestCreateSfcPortChain(fakes.TestNeutronClientOSCV2): # The new port_chain created _port_chain = fakes.FakeSfcPortChain.create_port_chain() - columns = ('Chain ID', - 'Chain Parameters', + columns = ('Chain Parameters', 'Description', 'Flow Classifiers', 'ID', @@ -40,7 +40,6 @@ class TestCreateSfcPortChain(fakes.TestNeutronClientOSCV2): def get_data(self): return ( - self._port_chain['chain_id'], self._port_chain['chain_parameters'], self._port_chain['description'], self._port_chain['flow_classifiers'], @@ -52,11 +51,8 @@ def get_data(self): def setUp(self): super(TestCreateSfcPortChain, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_chain._get_id', - new=_get_id).start() - self.neutronclient.create_sfc_port_chain = mock.Mock( - return_value={'port_chain': self._port_chain}) + self.network.create_sfc_port_chain = mock.Mock( + return_value=self._port_chain) self.data = self.get_data() # Get the command object to test @@ -77,11 +73,12 @@ def test_create_port_chain_default_options(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_port_chain.assert_called_once_with({ - 'port_chain': { + self.network.create_sfc_port_chain.assert_called_once_with( + **{ 'name': self._port_chain['name'], - 'port_pair_groups': [self._port_chain['port_pair_groups']]} - }) + 'port_pair_groups': [self._port_chain['port_pair_groups']] + } + ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -107,15 +104,15 @@ def test_create_port_chain_all_options(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_port_chain.assert_called_once_with({ - 'port_chain': { + self.network.create_sfc_port_chain.assert_called_once_with( + **{ 'name': self._port_chain['name'], 'port_pair_groups': [self._port_chain['port_pair_groups']], 'description': self._port_chain['description'], 'flow_classifiers': [self._port_chain['flow_classifiers']], 'chain_parameters': cp - } - }) + } + ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -126,20 +123,17 @@ class TestDeleteSfcPortChain(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestDeleteSfcPortChain, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_chain._get_id', - new=_get_id).start() - self.neutronclient.delete_sfc_port_chain = mock.Mock(return_value=None) + self.network.delete_sfc_port_chain = mock.Mock(return_value=None) self.cmd = sfc_port_chain.DeleteSfcPortChain(self.app, self.namespace) def test_delete_port_chain(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_port_chain_delete = client.delete_sfc_port_chain arglist = [ self._port_chain[0]['id'], ] verifylist = [ - ('port_chain', self._port_chain[0]['id']), + ('port_chain', [self._port_chain[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -147,13 +141,29 @@ def test_delete_port_chain(self): self._port_chain[0]['id']) self.assertIsNone(result) + def test_delete_multiple_port_chains_with_exception(self): + client = self.app.client_manager.network + target1 = self._port_chain[0]['id'] + arglist = [target1] + verifylist = [('port_chain', [target1])] + + client.find_sfc_port_chain.side_effect = [ + target1, exceptions.CommandError + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + msg = "1 of 2 port chain(s) failed to delete." + with testtools.ExpectedException(exceptions.CommandError) as e: + self.cmd.take_action(parsed_args) + self.assertEqual(msg, str(e)) + class TestListSfcPortChain(fakes.TestNeutronClientOSCV2): _port_chains = fakes.FakeSfcPortChain.create_port_chains(count=1) columns = ('ID', 'Name', 'Port Pair Groups', 'Flow Classifiers', - 'Chain Parameters', 'Chain ID') + 'Chain Parameters') columns_long = ('ID', 'Name', 'Port Pair Groups', 'Flow Classifiers', - 'Chain Parameters', 'Description', 'Chain ID', 'Project') + 'Chain Parameters', 'Description', 'Project') _port_chain = _port_chains[0] data = [ _port_chain['id'], @@ -161,13 +171,11 @@ class TestListSfcPortChain(fakes.TestNeutronClientOSCV2): _port_chain['port_pair_groups'], _port_chain['flow_classifiers'], _port_chain['chain_parameters'], - _port_chain['chain_id'] ] data_long = [ _port_chain['id'], _port_chain['name'], _port_chain['project_id'], - _port_chain['chain_id'], _port_chain['port_pair_groups'], _port_chain['flow_classifiers'], _port_chain['chain_parameters'], @@ -178,11 +186,8 @@ class TestListSfcPortChain(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestListSfcPortChain, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_chain._get_id', - new=_get_id).start() - self.neutronclient.list_sfc_port_chains = mock.Mock( - return_value={'port_chains': self._port_chains} + self.network.sfc_port_chains = mock.Mock( + return_value=self._port_chains ) # Get the command object to test self.cmd = sfc_port_chain.ListSfcPortChain(self.app, self.namespace) @@ -192,7 +197,7 @@ def test_list_port_chains(self): verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] - pcs = self.neutronclient.list_sfc_port_chains()['port_chains'] + pcs = self.network.sfc_port_chains() pc = pcs[0] data = [ pc['id'], @@ -200,7 +205,6 @@ def test_list_port_chains(self): pc['port_pair_groups'], pc['flow_classifiers'], pc['chain_parameters'], - pc['chain_id'] ] self.assertEqual(list(self.columns), columns) self.assertEqual(self.data, data) @@ -210,13 +214,12 @@ def test_list_port_chain_with_long_opion(self): verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] - pcs = self.neutronclient.list_sfc_port_chains()['port_chains'] + pcs = self.network.sfc_port_chains() pc = pcs[0] data = [ pc['id'], pc['name'], pc['project_id'], - pc['chain_id'], pc['port_pair_groups'], pc['flow_classifiers'], pc['chain_parameters'], @@ -237,14 +240,11 @@ class TestSetSfcPortChain(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestSetSfcPortChain, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_chain._get_id', - new=_get_id).start() - self.mocked = self.neutronclient.update_sfc_port_chain + self.mocked = self.network.update_sfc_port_chain self.cmd = sfc_port_chain.SetSfcPortChain(self.app, self.namespace) def test_set_port_chain(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_port_chain_update = client.update_sfc_port_chain arglist = [ self._port_chain_name, @@ -258,10 +258,9 @@ def test_set_port_chain(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'port_chain': {'name': 'name_updated', - 'description': 'desc_updated'}} + attrs = {'name': 'name_updated', 'description': 'desc_updated'} mock_port_chain_update.assert_called_once_with(self._port_chain_name, - attrs) + **attrs) self.assertIsNone(result) def test_set_flow_classifiers(self): @@ -269,23 +268,12 @@ def test_set_flow_classifiers(self): fc1 = 'flow_classifier1' fc2 = 'flow_classifier2' - def _mock_flow_classifier(*args, **kwargs): - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource='sfc_port_chain') - return {'flow_classifiers': [self.pc_fc]} - - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'flow_classifier', fc1, cmd_resource='sfc_flow_classifier') - return {'id': args[1]} - - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'flow_classifier', fc2, cmd_resource='sfc_flow_classifier') - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = _mock_flow_classifier + self.network.find_sfc_port_chain = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id, 'flow_classifiers': [self.pc_fc]} + ) + self.network.find_sfc_flow_classifier.side_effect = \ + lambda name_or_id, ignore_missing=False: {'id': name_or_id} arglist = [ target, '--flow-classifier', fc1, @@ -298,12 +286,11 @@ def _mock_flow_classifier(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'flow_classifiers': [self.pc_fc, fc1, fc2]} - self.mocked.assert_called_once_with(target, {self.res: expect}) - self.assertEqual(3, self.neutronclient.find_resource.call_count) + self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_set_no_flow_classifier(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_port_chain_update = client.update_sfc_port_chain arglist = [ self._port_chain_name, @@ -315,9 +302,9 @@ def test_set_no_flow_classifier(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'port_chain': {'flow_classifiers': []}} + attrs = {'flow_classifiers': []} mock_port_chain_update.assert_called_once_with(self._port_chain_name, - attrs) + **attrs) self.assertIsNone(result) def test_set_port_pair_groups(self): @@ -326,25 +313,10 @@ def test_set_port_pair_groups(self): ppg1 = 'port_pair_group1' ppg2 = 'port_pair_group2' - def _mock_flow_classifier(*args, **kwargs): - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource='sfc_port_chain') - return {'port_pair_groups': [self.pc_ppg]} - - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'port_pair_group', ppg1, - cmd_resource='sfc_port_pair_group') - return {'id': args[1]} - - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'port_pair_group', ppg2, - cmd_resource='sfc_port_pair_group') - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = _mock_flow_classifier + self.network.find_sfc_port_chain = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id, 'port_pair_groups': [self.pc_ppg]} + ) arglist = [ target, '--port-pair-group', ppg1, @@ -357,22 +329,13 @@ def _mock_flow_classifier(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'port_pair_groups': [existing_ppg, ppg1, ppg2]} - self.mocked.assert_called_once_with(target, {self.res: expect}) - self.assertEqual(3, self.neutronclient.find_resource.call_count) + self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_set_no_port_pair_group(self): target = self.resource['id'] ppg1 = 'port_pair_group1' - def _mock_port_pair_group(*args, **kwargs): - - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - 'port_pair_group', ppg1, - cmd_resource='sfc_port_pair_group') - return {'id': args[1]} - self.neutronclient.find_resource.side_effect = _mock_port_pair_group arglist = [ target, '--no-port-pair-group', @@ -386,8 +349,7 @@ def _mock_port_pair_group(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'port_pair_groups': [ppg1]} - self.mocked.assert_called_once_with(target, {self.res: expect}) - self.assertEqual(1, self.neutronclient.find_resource.call_count) + self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_set_only_no_port_pair_group(self): @@ -409,7 +371,6 @@ class TestShowSfcPortChain(fakes.TestNeutronClientOSCV2): _pc = fakes.FakeSfcPortChain.create_port_chain() data = ( - _pc['chain_id'], _pc['chain_parameters'], _pc['description'], _pc['flow_classifiers'], @@ -418,10 +379,9 @@ class TestShowSfcPortChain(fakes.TestNeutronClientOSCV2): _pc['port_pair_groups'], _pc['project_id'] ) - _port_chain = {'port_chain': _pc} + _port_chain = _pc _port_chain_id = _pc['id'] - columns = ('Chain ID', - 'Chain Parameters', + columns = ('Chain Parameters', 'Description', 'Flow Classifiers', 'ID', @@ -431,18 +391,15 @@ class TestShowSfcPortChain(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestShowSfcPortChain, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_chain._get_id', - new=_get_id).start() - self.neutronclient.show_sfc_port_chain = mock.Mock( + self.network.get_sfc_port_chain = mock.Mock( return_value=self._port_chain ) # Get the command object to test self.cmd = sfc_port_chain.ShowSfcPortChain(self.app, self.namespace) def test_show_port_chain(self): - client = self.app.client_manager.neutronclient - mock_port_chain_show = client.show_sfc_port_chain + client = self.app.client_manager.network + mock_port_chain_show = client.get_sfc_port_chain arglist = [ self._port_chain_id, ] @@ -468,34 +425,21 @@ class TestUnsetSfcPortChain(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestUnsetSfcPortChain, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_chain._get_id', - new=_get_id).start() - self.neutronclient.update_sfc_port_chain = mock.Mock( + self.network.update_sfc_port_chain = mock.Mock( return_value=None) - self.mocked = self.neutronclient.update_sfc_port_chain + self.mocked = self.network.update_sfc_port_chain self.cmd = sfc_port_chain.UnsetSfcPortChain(self.app, self.namespace) def test_unset_port_pair_group(self): target = self.resource['id'] ppg1 = 'port_pair_group1' - def _mock_port_pair_group(*args, **kwargs): - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource='sfc_port_chain') - return {'port_pair_groups': [self.pc_ppg]} - - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'port_pair_group', ppg1, - cmd_resource='sfc_port_pair_group') - return {'id': args[1]} - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource='sfc_port_chain') - return {'id': args[1]} - self.neutronclient.find_resource.side_effect = _mock_port_pair_group + self.network.find_sfc_port_chain = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id, 'port_pair_groups': [self.pc_ppg]} + ) + self.network.find_sfc_port_pair_group.side_effect = \ + lambda name_or_id, ignore_missing=False: {'id': name_or_id} arglist = [ target, @@ -508,24 +452,18 @@ def _mock_port_pair_group(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'port_pair_groups': [self.pc_ppg]} - self.mocked.assert_called_once_with(target, {self.res: expect}) + self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_unset_flow_classifier(self): target = self.resource['id'] fc1 = 'flow_classifier1' - - def _mock_flow_classifier(*args, **kwargs): - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource='sfc_port_chain') - return {'flow_classifiers': [self.pc_fc]} - - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'flow_classifier', fc1, cmd_resource='sfc_flow_classifier') - return {'id': args[1]} - self.neutronclient.find_resource.side_effect = _mock_flow_classifier + self.network.find_sfc_port_chain = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id, 'flow_classifiers': [self.pc_fc]} + ) + self.network.find_sfc_flow_classifier.side_effect = \ + lambda name_or_id, ignore_missing=False: {'id': name_or_id} arglist = [ target, @@ -538,11 +476,11 @@ def _mock_flow_classifier(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) expect = {'flow_classifiers': [self.pc_fc]} - self.mocked.assert_called_once_with(target, {self.res: expect}) + self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_unset_all_flow_classifier(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network target = self.resource['id'] mock_port_chain_update = client.update_sfc_port_chain arglist = [ @@ -557,5 +495,5 @@ def test_unset_all_flow_classifier(self): result = self.cmd.take_action(parsed_args) expect = {'flow_classifiers': []} mock_port_chain_update.assert_called_once_with(target, - {self.res: expect}) + **expect) self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py b/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py index 8246e35d9..e0610a360 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_port_pair.py @@ -15,14 +15,13 @@ from unittest import mock +from osc_lib import exceptions +import testtools + from neutronclient.osc.v2.sfc import sfc_port_pair from neutronclient.tests.unit.osc.v2.sfc import fakes -def _get_id(client, id_or_name, resource): - return id_or_name - - class TestCreateSfcPortPair(fakes.TestNeutronClientOSCV2): # The new port_pair created _port_pair = fakes.FakeSfcPortPair.create_port_pair() @@ -48,10 +47,8 @@ def get_data(self): def setUp(self): super(TestCreateSfcPortPair, self).setUp() - mock.patch('neutronclient.osc.v2.sfc.sfc_port_pair._get_id', - new=_get_id).start() - self.neutronclient.create_sfc_port_pair = mock.Mock( - return_value={'port_pair': self._port_pair}) + self.network.create_sfc_port_pair = mock.Mock( + return_value=self._port_pair) self.data = self.get_data() # Get the command object to test @@ -71,12 +68,11 @@ def test_create_port_pair_default_options(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_port_pair.assert_called_once_with({ - 'port_pair': {'name': self._port_pair['name'], - 'ingress': self._port_pair['ingress'], - 'egress': self._port_pair['egress'], - } - }) + self.network.create_sfc_port_pair.assert_called_once_with( + **{'name': self._port_pair['name'], + 'ingress': self._port_pair['ingress'], + 'egress': self._port_pair['egress']} + ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -106,16 +102,14 @@ def _test_create_port_pair_all_options(self, correlation): correlation_param = None else: correlation_param = correlation - self.neutronclient.create_sfc_port_pair.assert_called_once_with({ - 'port_pair': {'name': self._port_pair['name'], - 'ingress': self._port_pair['ingress'], - 'egress': self._port_pair['egress'], - 'description': self._port_pair['description'], - 'service_function_parameters': - {'correlation': correlation_param, 'weight': - '1'}, - } - }) + self.network.create_sfc_port_pair.assert_called_once_with( + **{'name': self._port_pair['name'], + 'ingress': self._port_pair['ingress'], + 'egress': self._port_pair['egress'], + 'description': self._port_pair['description'], + 'service_function_parameters': + {'correlation': correlation_param, 'weight': '1'}} + ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -132,19 +126,17 @@ class TestDeleteSfcPortPair(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestDeleteSfcPortPair, self).setUp() - mock.patch('neutronclient.osc.v2.sfc.sfc_port_pair._get_id', - new=_get_id).start() - self.neutronclient.delete_sfc_port_pair = mock.Mock(return_value=None) + self.network.delete_sfc_port_pair = mock.Mock(return_value=None) self.cmd = sfc_port_pair.DeleteSfcPortPair(self.app, self.namespace) def test_delete_port_pair(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_port_pair_delete = client.delete_sfc_port_pair arglist = [ self._port_pair[0]['id'], ] verifylist = [ - ('port_pair', self._port_pair[0]['id']), + ('port_pair', [self._port_pair[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -152,6 +144,22 @@ def test_delete_port_pair(self): self._port_pair[0]['id']) self.assertIsNone(result) + def test_delete_multiple_port_pairs_with_exception(self): + client = self.app.client_manager.network + target1 = self._port_pair[0]['id'] + arglist = [target1] + verifylist = [('port_pair', [target1])] + + client.find_sfc_port_pair.side_effect = [ + target1, exceptions.CommandError + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + msg = "1 of 2 port pair(s) failed to delete." + with testtools.ExpectedException(exceptions.CommandError) as e: + self.cmd.take_action(parsed_args) + self.assertEqual(msg, str(e)) + class TestListSfcPortPair(fakes.TestNeutronClientOSCV2): _port_pairs = fakes.FakeSfcPortPair.create_port_pairs() @@ -179,11 +187,8 @@ class TestListSfcPortPair(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestListSfcPortPair, self).setUp() - mock.patch('neutronclient.osc.v2.sfc.sfc_port_pair._get_id', - new=_get_id).start() - self.neutronclient.list_sfc_port_pairs = mock.Mock( - return_value={'port_pairs': self._port_pairs} - ) + self.network.sfc_port_pairs = mock.Mock( + return_value=self._port_pairs) # Get the command object to test self.cmd = sfc_port_pair.ListSfcPortPair(self.app, self.namespace) @@ -192,7 +197,7 @@ def test_list_port_pairs(self): verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] - port_pairs = self.neutronclient.list_sfc_port_pairs()['port_pairs'] + port_pairs = self.network.sfc_port_pairs() port_pair = port_pairs[0] data = [ port_pair['id'], @@ -206,7 +211,7 @@ def test_list_port_pairs(self): def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] - port_pairs = self.neutronclient.list_sfc_port_pairs()['port_pairs'] + port_pairs = self.network.sfc_port_pairs() port_pair = port_pairs[0] data = [ port_pair['id'], @@ -229,13 +234,11 @@ class TestSetSfcPortPair(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestSetSfcPortPair, self).setUp() - mock.patch('neutronclient.osc.v2.sfc.sfc_port_pair._get_id', - new=_get_id).start() - self.neutronclient.update_sfc_port_pair = mock.Mock(return_value=None) + self.network.update_sfc_port_pair = mock.Mock(return_value=None) self.cmd = sfc_port_pair.SetSfcPortPair(self.app, self.namespace) def test_set_port_pair(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_port_pair_update = client.update_sfc_port_pair arglist = [ self._port_pair_name, @@ -249,12 +252,12 @@ def test_set_port_pair(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'port_pair': { + attrs = { 'name': 'name_updated', - 'description': 'desc_updated'} + 'description': 'desc_updated' } mock_port_pair_update.assert_called_once_with(self._port_pair_name, - attrs) + **attrs) self.assertIsNone(result) @@ -271,7 +274,7 @@ class TestShowSfcPortPair(fakes.TestNeutronClientOSCV2): _pp['project_id'], _pp['service_function_parameters'], ) - _port_pair = {'port_pair': _pp} + _port_pair = _pp _port_pair_id = _pp['id'] columns = ( 'Description', @@ -285,10 +288,8 @@ class TestShowSfcPortPair(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestShowSfcPortPair, self).setUp() - mock.patch('neutronclient.osc.v2.sfc.sfc_port_pair._get_id', - new=_get_id).start() - self.neutronclient.show_sfc_port_pair = mock.Mock( + self.network.get_sfc_port_pair = mock.Mock( return_value=self._port_pair ) @@ -296,8 +297,8 @@ def setUp(self): self.cmd = sfc_port_pair.ShowSfcPortPair(self.app, self.namespace) def test_show_port_pair(self): - client = self.app.client_manager.neutronclient - mock_port_pair_show = client.show_sfc_port_pair + client = self.app.client_manager.network + mock_port_pair_show = client.get_sfc_port_pair arglist = [ self._port_pair_id, ] diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py b/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py index 6db21a284..49f3fcf06 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_port_pair_group.py @@ -15,21 +15,19 @@ from unittest import mock +from osc_lib import exceptions +import testtools + from neutronclient.osc.v2.sfc import sfc_port_pair_group from neutronclient.tests.unit.osc.v2.sfc import fakes -def _get_id(client, id_or_name, resource): - return id_or_name - - class TestCreateSfcPortPairGroup(fakes.TestNeutronClientOSCV2): _port_pair_group = fakes.FakeSfcPortPairGroup.create_port_pair_group() columns = ('Description', 'ID', - 'Loadbalance ID', 'Name', 'Port Pair', 'Port Pair Group Parameters', @@ -40,7 +38,6 @@ def get_data(self, ppg): return ( ppg['description'], ppg['id'], - ppg['group_id'], ppg['name'], ppg['port_pairs'], ppg['port_pair_group_parameters'], @@ -50,12 +47,10 @@ def get_data(self, ppg): def setUp(self): super(TestCreateSfcPortPairGroup, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_pair_group._get_id', - new=_get_id).start() - self.neutronclient.create_sfc_port_pair_group = mock.Mock( - return_value={'port_pair_group': self._port_pair_group}) + self.network.create_sfc_port_pair_group = mock.Mock( + return_value=self._port_pair_group) self.data = self.get_data(self._port_pair_group) + # Get the command object to test self.cmd = sfc_port_pair_group.CreateSfcPortPairGroup(self.app, self.namespace) @@ -72,12 +67,9 @@ def test_create_port_pair_group_default_options(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_port_pair_group.assert_called_once_with({ - 'port_pair_group': { - 'name': self._port_pair_group['name'], - 'port_pairs': [self._port_pair_group['port_pairs']] - } - }) + self.network.create_sfc_port_pair_group.assert_called_once_with( + **{'name': self._port_pair_group['name'], + 'port_pairs': [self._port_pair_group['port_pairs']]}) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -95,13 +87,11 @@ def test_create_port_pair_group(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_port_pair_group.assert_called_once_with({ - 'port_pair_group': { + self.network.create_sfc_port_pair_group.assert_called_once_with( + **{ 'name': self._port_pair_group['name'], 'port_pairs': [self._port_pair_group['port_pairs']], - 'description': self._port_pair_group['description'], - } - }) + 'description': self._port_pair_group['description']}) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -127,22 +117,19 @@ def test_create_tap_enabled_port_pair_group(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_port_pair_group.assert_called_once_with({ - 'port_pair_group': { + self.network.create_sfc_port_pair_group.assert_called_once_with( + **{ 'name': self._port_pair_group['name'], 'port_pairs': [self._port_pair_group['port_pairs']], 'description': self._port_pair_group['description'], - 'tap_enabled': True - } - }) + 'tap_enabled': True}) self.assertEqual(self.columns, columns) self.assertEqual(expected_data, data) def _update_expected_response_data(self, data): # REVISIT(vks1) - This method can be common for other test functions. ppg = fakes.FakeSfcPortPairGroup.create_port_pair_group(data) - self.neutronclient.create_sfc_port_pair_group.return_value = { - 'port_pair_group': ppg} + self.network.create_sfc_port_pair_group.return_value = ppg return self.get_data(ppg) @@ -153,22 +140,19 @@ class TestDeleteSfcPortPairGroup(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestDeleteSfcPortPairGroup, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_pair_group._get_id', - new=_get_id).start() - self.neutronclient.delete_sfc_port_pair_group = mock.Mock( + self.network.delete_sfc_port_pair_group = mock.Mock( return_value=None) self.cmd = sfc_port_pair_group.DeleteSfcPortPairGroup(self.app, self.namespace) def test_delete_port_pair_group(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_port_pair_group_delete = client.delete_sfc_port_pair_group arglist = [ self._port_pair_group[0]['id'], ] verifylist = [ - ('port_pair_group', self._port_pair_group[0]['id']), + ('port_pair_group', [self._port_pair_group[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -176,13 +160,29 @@ def test_delete_port_pair_group(self): self._port_pair_group[0]['id']) self.assertIsNone(result) + def test_delete_multiple_port_pair_groups_with_exception(self): + client = self.app.client_manager.network + target1 = 'target' + arglist = [target1] + verifylist = [('port_pair_group', [target1])] + + client.find_sfc_port_pair_group.side_effect = [ + target1, exceptions.CommandError + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + msg = "1 of 2 port pair group(s) failed to delete." + with testtools.ExpectedException(exceptions.CommandError) as e: + self.cmd.take_action(parsed_args) + self.assertEqual(msg, str(e)) + class TestListSfcPortPairGroup(fakes.TestNeutronClientOSCV2): _ppgs = fakes.FakeSfcPortPairGroup.create_port_pair_groups(count=1) columns = ('ID', 'Name', 'Port Pair', 'Port Pair Group Parameters', 'Tap Enabled') columns_long = ('ID', 'Name', 'Port Pair', 'Port Pair Group Parameters', - 'Description', 'Loadbalance ID', 'Project', 'Tap Enabled') + 'Description', 'Project', 'Tap Enabled') _port_pair_group = _ppgs[0] data = [ _port_pair_group['id'], @@ -204,12 +204,9 @@ class TestListSfcPortPairGroup(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestListSfcPortPairGroup, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_pair_group._get_id', - new=_get_id).start() - self.neutronclient.list_sfc_port_pair_groups = mock.Mock( - return_value={'port_pair_groups': self._ppgs} + self.network.sfc_port_pair_groups = mock.Mock( + return_value=self._ppgs ) # Get the command object to test self.cmd = sfc_port_pair_group.ListSfcPortPairGroup(self.app, @@ -220,8 +217,7 @@ def test_list_port_pair_groups(self): verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] - ppgs = self.neutronclient \ - .list_sfc_port_pair_groups()['port_pair_groups'] + ppgs = self.network.sfc_port_pair_groups() ppg = ppgs[0] data = [ ppg['id'], @@ -236,8 +232,7 @@ def test_list_port_pair_groups(self): def test_list_with_long_option(self): arglist = ['--long'] verifylist = [('long', True)] - ppgs = self.neutronclient \ - .list_sfc_port_pair_groups()['port_pair_groups'] + ppgs = self.network.sfc_port_pair_groups() ppg = ppgs[0] data = [ ppg['id'], @@ -264,12 +259,9 @@ class TestSetSfcPortPairGroup(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestSetSfcPortPairGroup, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_pair_group._get_id', - new=_get_id).start() - self.neutronclient.update_sfc_port_pair_group = mock.Mock( + self.network.update_sfc_port_pair_group = mock.Mock( return_value=None) - self.mocked = self.neutronclient.update_sfc_port_pair_group + self.mocked = self.network.update_sfc_port_pair_group self.cmd = sfc_port_pair_group.SetSfcPortPairGroup(self.app, self.namespace) @@ -278,24 +270,14 @@ def test_set_port_pair_group(self): port_pair1 = 'additional_port1' port_pair2 = 'additional_port2' - def _mock_port_pair_group(*args, **kwargs): - - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - 'port_pair', port_pair1, cmd_resource='sfc_port_pair') - return {'id': args[1]} - - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'port_pair', port_pair2, cmd_resource='sfc_port_pair') - return {'id': args[1]} - - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource='sfc_port_pair_group') - return {'port_pairs': [self.ppg_pp]} - - self.neutronclient.find_resource.side_effect = _mock_port_pair_group + self.network.find_sfc_port_pair = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id} + ) + self.network.find_sfc_port_pair_group = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id, 'port_pairs': self.ppg_pp} + ) arglist = [ target, @@ -308,13 +290,12 @@ def _mock_port_pair_group(*args, **kwargs): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - expect = {'port_pairs': sorted([self.ppg_pp, port_pair1, port_pair2])} - self.mocked.assert_called_once_with(target, {self.res: expect}) - self.assertEqual(3, self.neutronclient.find_resource.call_count) + expect = {'port_pairs': sorted([*self.ppg_pp, port_pair1, port_pair2])} + self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_set_no_port_pair(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_port_pair_group_update = client.update_sfc_port_pair_group arglist = [ self._port_pair_group_name, @@ -331,11 +312,10 @@ def test_set_no_port_pair(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'port_pair_group': {'name': 'name_updated', - 'description': 'desc_updated', - 'port_pairs': []}} + attrs = {'name': 'name_updated', 'description': 'desc_updated', + 'port_pairs': []} mock_port_pair_group_update.assert_called_once_with( - self._port_pair_group_name, attrs) + self._port_pair_group_name, **attrs) self.assertIsNone(result) @@ -345,18 +325,16 @@ class TestShowSfcPortPairGroup(fakes.TestNeutronClientOSCV2): data = ( _ppg['description'], _ppg['id'], - _ppg['group_id'], _ppg['name'], _ppg['port_pairs'], _ppg['port_pair_group_parameters'], _ppg['project_id'], _ppg['tap_enabled']) - _port_pair_group = {'port_pair_group': _ppg} + _port_pair_group = _ppg _port_pair_group_id = _ppg['id'] columns = ( 'Description', 'ID', - 'Loadbalance ID', 'Name', 'Port Pair', 'Port Pair Group Parameters', @@ -366,19 +344,16 @@ class TestShowSfcPortPairGroup(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestShowSfcPortPairGroup, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_pair_group._get_id', - new=_get_id).start() - self.neutronclient.show_sfc_port_pair_group = mock.Mock( + self.network.get_sfc_port_pair_group = mock.Mock( return_value=self._port_pair_group ) self.cmd = sfc_port_pair_group.ShowSfcPortPairGroup(self.app, self.namespace) def test_show_port_pair_group(self): - client = self.app.client_manager.neutronclient - mock_port_pair_group_show = client.show_sfc_port_pair_group + client = self.app.client_manager.network + mock_port_pair_group_show = client.get_sfc_port_pair_group arglist = [ self._port_pair_group_id, ] @@ -404,12 +379,9 @@ class TestUnsetSfcPortPairGroup(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestUnsetSfcPortPairGroup, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_port_pair_group._get_id', - new=_get_id).start() - self.neutronclient.update_sfc_port_pair_group = mock.Mock( + self.network.update_sfc_port_pair_group = mock.Mock( return_value=None) - self.mocked = self.neutronclient.update_sfc_port_pair_group + self.mocked = self.network.update_sfc_port_pair_group self.cmd = sfc_port_pair_group.UnsetSfcPortPairGroup( self.app, self.namespace) @@ -418,30 +390,14 @@ def test_unset_port_pair(self): port_pair1 = 'additional_port1' port_pair2 = 'additional_port2' - def _mock_port_pair(*args, **kwargs): - - if self.neutronclient.find_resource.call_count == 1: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource='sfc_port_pair_group') - return {'port_pairs': [self.ppg_pp]} - - if self.neutronclient.find_resource.call_count == 2: - self.neutronclient.find_resource.assert_called_with( - 'port_pair', port_pair1, cmd_resource='sfc_port_pair') - return {'id': args[1]} - - if self.neutronclient.find_resource.call_count == 3: - self.neutronclient.find_resource.assert_called_with( - 'port_pair', port_pair2, cmd_resource='sfc_port_pair') - return {'id': args[1]} - - if self.neutronclient.find_resource.call_count == 4: - self.neutronclient.find_resource.assert_called_with( - self.res, target, cmd_resource='sfc_port_pair_group') - return {'id': args[1]} - - self.neutronclient.find_resource.side_effect = _mock_port_pair - + self.network.find_sfc_port_pair = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id} + ) + self.network.find_sfc_port_pair_group = mock.Mock( + side_effect=lambda name_or_id, ignore_missing=False: + {'id': name_or_id, 'port_pairs': self.ppg_pp} + ) arglist = [ target, '--port-pair', port_pair1, @@ -453,12 +409,12 @@ def _mock_port_pair(*args, **kwargs): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - expect = {'port_pairs': sorted([self.ppg_pp])} - self.mocked.assert_called_once_with(target, {self.res: expect}) + expect = {'port_pairs': sorted([*self.ppg_pp])} + self.mocked.assert_called_once_with(target, **expect) self.assertIsNone(result) def test_unset_all_port_pair(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_port_pair_group_update = client.update_sfc_port_pair_group arglist = [ self._port_pair_group_name, @@ -471,7 +427,7 @@ def test_unset_all_port_pair(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'port_pair_group': {'port_pairs': []}} + attrs = {'port_pairs': []} mock_port_pair_group_update.assert_called_once_with( - self._port_pair_group_name, attrs) + self._port_pair_group_name, **attrs) self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py b/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py index a05ed2c72..50a02139d 100644 --- a/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py @@ -11,19 +11,17 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. + from unittest import mock from osc_lib import exceptions from osc_lib.tests import utils as tests_utils +import testtools from neutronclient.osc.v2.sfc import sfc_service_graph from neutronclient.tests.unit.osc.v2.sfc import fakes -def _get_id(client, id_or_name, resource): - return id_or_name - - class TestListSfcServiceGraph(fakes.TestNeutronClientOSCV2): _service_graphs = fakes.FakeSfcServiceGraph.create_sfc_service_graphs( count=1) @@ -47,11 +45,8 @@ class TestListSfcServiceGraph(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestListSfcServiceGraph, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_service_graph._get_id', - new=_get_id).start() - self.neutronclient.list_sfc_service_graphs = mock.Mock( - return_value={'service_graphs': self._service_graphs} + self.network.sfc_service_graphs = mock.Mock( + return_value=self._service_graphs ) # Get the command object to test self.cmd = sfc_service_graph.ListSfcServiceGraph( @@ -62,7 +57,7 @@ def test_list_sfc_service_graphs(self): verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] - sgs = self.neutronclient.list_sfc_service_graphs()['service_graphs'] + sgs = self.network.sfc_service_graphs() sg = sgs[0] data = [ sg['id'], @@ -77,7 +72,7 @@ def test_list_sfc_service_graphs_with_long_option(self): verifylist = [('long', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns = self.cmd.take_action(parsed_args)[0] - sgs = self.neutronclient.list_sfc_service_graphs()['service_graphs'] + sgs = self.network.sfc_service_graphs() sg = sgs[0] data = [ sg['id'], @@ -107,10 +102,8 @@ def get_data(self): def setUp(self): super(TestCreateSfcServiceGraph, self).setUp() - mock.patch('neutronclient.osc.v2.sfc.sfc_service_graph._get_id', - new=_get_id).start() - self.neutronclient.create_sfc_service_graph = mock.Mock( - return_value={'service_graph': self._service_graph}) + self.network.create_sfc_service_graph = mock.Mock( + return_value=self._service_graph) self.data = self.get_data() self.cmd = sfc_service_graph.CreateSfcServiceGraph( self.app, self.namespace) @@ -145,12 +138,10 @@ def test_create_sfc_service_graph_without_loop(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) - self.neutronclient.create_sfc_service_graph.assert_called_once_with({ - 'service_graph': { + self.network.create_sfc_service_graph.assert_called_once_with(**{ 'description': self._service_graph['description'], 'name': self._service_graph['name'], 'port_chains': pcs - } }) self.assertEqual(self.columns_long, columns) self.assertEqual(self.data, data) @@ -227,19 +218,19 @@ class TestDeleteSfcServiceGraph(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestDeleteSfcServiceGraph, self).setUp() - self.neutronclient.delete_sfc_service_graph = mock.Mock( + self.network.delete_sfc_service_graph = mock.Mock( return_value=None) self.cmd = sfc_service_graph.DeleteSfcServiceGraph( self.app, self.namespace) def test_delete_sfc_service_graph(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_service_graph_delete = client.delete_sfc_service_graph arglist = [ self._service_graph[0]['id'], ] verifylist = [ - ('service_graph', self._service_graph[0]['id']), + ('service_graph', [self._service_graph[0]['id']]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -247,6 +238,22 @@ def test_delete_sfc_service_graph(self): self._service_graph[0]['id']) self.assertIsNone(result) + def test_delete_multiple_service_graphs_with_exception(self): + client = self.app.client_manager.network + target = self._service_graph[0]['id'] + arglist = [target] + verifylist = [('service_graph', [target])] + + client.find_sfc_service_graph.side_effect = [ + target, exceptions.CommandError + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + msg = "1 of 2 service graph(s) failed to delete." + with testtools.ExpectedException(exceptions.CommandError) as e: + self.cmd.take_action(parsed_args) + self.assertEqual(msg, str(e)) + class TestShowSfcServiceGraph(fakes.TestNeutronClientOSCV2): @@ -266,15 +273,12 @@ class TestShowSfcServiceGraph(fakes.TestNeutronClientOSCV2): _sg['project_id'] ) - _service_graph = {'service_graph': _sg} + _service_graph = _sg _service_graph_id = _sg['id'] def setUp(self): super(TestShowSfcServiceGraph, self).setUp() - mock.patch( - 'neutronclient.osc.v2.sfc.sfc_service_graph._get_id', - new=_get_id).start() - self.neutronclient.show_sfc_service_graph = mock.Mock( + self.network.get_sfc_service_graph = mock.Mock( return_value=self._service_graph ) # Get the command object to test @@ -282,8 +286,8 @@ def setUp(self): self.app, self.namespace) def test_service_graph_show(self): - client = self.app.client_manager.neutronclient - mock_service_graph_show = client.show_sfc_service_graph + client = self.app.client_manager.network + mock_service_graph_show = client.get_sfc_service_graph arglist = [ self._service_graph_id, ] @@ -305,15 +309,13 @@ class TestSetSfcServiceGraph(fakes.TestNeutronClientOSCV2): def setUp(self): super(TestSetSfcServiceGraph, self).setUp() - mock.patch('neutronclient.osc.v2.sfc.sfc_service_graph._get_id', - new=_get_id).start() - self.neutronclient.update_sfc_service_graph = mock.Mock( + self.network.update_sfc_service_graph = mock.Mock( return_value=None) self.cmd = sfc_service_graph.SetSfcServiceGraph( self.app, self.namespace) def test_set_service_graph(self): - client = self.app.client_manager.neutronclient + client = self.app.client_manager.network mock_service_graph_update = client.update_sfc_service_graph arglist = [ self._service_graph_name, @@ -327,10 +329,10 @@ def test_set_service_graph(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - attrs = {'service_graph': { + attrs = { 'name': 'name_updated', - 'description': 'desc_updated'} + 'description': 'desc_updated' } mock_service_graph_update.assert_called_once_with( - self._service_graph_name, attrs) + self._service_graph_name, **attrs) self.assertIsNone(result) From 8c983fa764584699632c64b6448d68f12d72a726 Mon Sep 17 00:00:00 2001 From: OpenStack Proposal Bot Date: Sat, 9 Sep 2023 03:54:47 +0000 Subject: [PATCH 115/149] Imported Translations from Zanata For more information about this automatic import see: https://docs.openstack.org/i18n/latest/reviewing-translation-import.html Change-Id: Ida432a5df2f6cc9453f546ad8e66b0e52c5d1b80 --- .../locale/en_GB/LC_MESSAGES/releasenotes.po | 400 ++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po diff --git a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po new file mode 100644 index 000000000..cb1dcb6bd --- /dev/null +++ b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po @@ -0,0 +1,400 @@ +# Andi Chandler , 2022. #zanata +# Andi Chandler , 2023. #zanata +msgid "" +msgstr "" +"Project-Id-Version: Neutron Client Release Notes\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-08 20:18+0000\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2023-07-28 12:44+0000\n" +"Last-Translator: Andi Chandler \n" +"Language-Team: English (United Kingdom)\n" +"Language: en_GB\n" +"X-Generator: Zanata 4.3.3\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +msgid "" +"\"admin-state-down\" option was deprecated in Mitaka and has been removed in " +"Newton." +msgstr "" +"\"admin-state-down\" option was deprecated in Mitaka and has been removed in " +"Newton." + +msgid "10.0.0" +msgstr "10.0.0" + +msgid "2.0" +msgstr "2.0" + +msgid "2.2.0" +msgstr "2.2.0" + +msgid "2.2.2" +msgstr "2.2.2" + +msgid "2023.1 Series Release Notes" +msgstr "2023.1 Series Release Notes" + +msgid "4.0.0" +msgstr "4.0.0" + +msgid "4.1.0" +msgstr "4.1.0" + +msgid "4.1.1" +msgstr "4.1.1" + +msgid "4.1.2-15" +msgstr "4.1.2-15" + +msgid "4.2.0" +msgstr "4.2.0" + +msgid "5.0.0" +msgstr "5.0.0" + +msgid "5.1.0" +msgstr "5.1.0" + +msgid "6.0.0" +msgstr "6.0.0" + +msgid "6.1.0" +msgstr "6.1.0" + +msgid "6.1.1" +msgstr "6.1.1" + +msgid "6.10.0" +msgstr "6.10.0" + +msgid "6.11.0" +msgstr "6.11.0" + +msgid "6.12.0" +msgstr "6.12.0" + +msgid "6.14.0" +msgstr "6.14.0" + +msgid "6.2.0" +msgstr "6.2.0" + +msgid "6.3.0" +msgstr "6.3.0" + +msgid "6.4.0" +msgstr "6.4.0" + +msgid "6.5.0" +msgstr "6.5.0" + +msgid "6.6.0" +msgstr "6.6.0" + +msgid "6.7.0" +msgstr "6.7.0" + +msgid "7.0.0" +msgstr "7.0.0" + +msgid "7.1.0" +msgstr "7.1.0" + +msgid "7.2.0" +msgstr "7.2.0" + +msgid "7.2.1" +msgstr "7.2.1" + +msgid "7.5.0" +msgstr "7.5.0" + +msgid "7.7.0" +msgstr "7.7.0" + +msgid "7.8.0" +msgstr "7.8.0" + +msgid "8.0.0" +msgstr "8.0.0" + +msgid "8.1.0" +msgstr "8.1.0" + +msgid "8.2.0" +msgstr "8.2.0" + +msgid "" +"A new option ``--no-session-persistence`` has been added to the ``neutron " +"lbaas-pool-update`` CLI to clear the session persistence with which the " +"current pool is associated." +msgstr "" +"A new option ``--no-session-persistence`` has been added to the ``neutron " +"lbaas-pool-update`` CLI to clear the session persistence with which the " +"current pool is associated." + +msgid "" +"Add BGP VPN `port association `_ support to the CLI, which are " +"introduced for BGP VPN interconnections by the ``bgpvpn-routes-control`` API " +"extension." +msgstr "" +"Add BGP VPN `port association `_ support to the CLI, which are " +"introduced for BGP VPN interconnections by the ``bgpvpn-routes-control`` API " +"extension." + +msgid "" +"Add OSC plugin support for the “Networking Service Function Chaining” " +"feature commands along with client bindings. [Blueprint `openstackclient-cli-" +"porting `_]" +msgstr "" +"Add OSC plugin support for the “Networking Service Function Chaining” " +"feature commands along with client bindings. [Blueprint `openstackclient-cli-" +"porting `_]" + +msgid "Add OSC plugin to support \"Neutron Dynamic Routing\"" +msgstr "Add OSC plugin to support \"Neutron Dynamic Routing\"" + +msgid "Add OSC support to create Port pair group for Tap service functions." +msgstr "Add OSC support to create Port pair group for Tap service functions." + +msgid "" +"Add ``network onboard subnets`` OSC command to enable subnet onboard support " +"from the CLI [Blueprint `subnet-onboard `_]" +msgstr "" +"Add ``network onboard subnets`` OSC command to enable subnet onboard support " +"from the CLI [Blueprint `subnet-onboard `_]" + +msgid "" +"Add ``network trunk create``, ``network trunk list``, ``network trunk set``, " +"``network trunk unset``, ``network trunk delete`` and ``network subport " +"list`` OSC commands for trunk resource along with client bindings. " +"[Blueprint `vlan-aware-vms `_]" +msgstr "" +"Add ``network trunk create``, ``network trunk list``, ``network trunk set``, " +"``network trunk unset``, ``network trunk delete`` and ``network subport " +"list`` OSC commands for trunk resource along with client bindings. " +"[Blueprint `vlan-aware-vms `_]" + +msgid "" +"Add optional flag to control the advertisement in BGPVPNs of the routes " +"defined on a Router resource (``bgpvpn-routes-control`` API extension)." +msgstr "" +"Add optional flag to control the advertisement in BGPVPNs of the routes " +"defined on a Router resource (``bgpvpn-routes-control`` API extension)." + +msgid "" +"Add osprofiler support to the neutronclient python binding. If osprofiler is " +"initiated, neutronclient sends a special HTTP header that contains trace " +"info." +msgstr "" +"Add osprofiler support to the neutronclient python binding. If osprofiler is " +"initiated, neutronclient sends a special HTTP header that contains trace " +"info." + +msgid "Add support to floating ip port forwarding." +msgstr "Add support to floating ip port forwarding." + +msgid "" +"By using this feature, multiple resource can be deleted using a single " +"command." +msgstr "" +"By using this feature, multiple resource can be deleted using a single " +"command." + +msgid "" +"CLI support for 'Logging' feature, which enable to collect packet logs for " +"specified resource. Currently, only security-group can be logged." +msgstr "" +"CLI support for 'Logging' feature, which enable to collect packet logs for " +"specified resource. Currently, only security-group can be logged." + +msgid "CLI support for Layer 7 content policies and rules." +msgstr "CLI support for Layer 7 content policies and rules." + +msgid "CLI support for Neutron-LBaaS v2 shared pools added." +msgstr "CLI support for Neutron-LBaaS v2 shared pools added." + +msgid "CLI support for QoS policy RBAC." +msgstr "CLI support for QoS policy RBAC." + +msgid "Current Series Release Notes" +msgstr "Current Series Release Notes" + +msgid "Mitaka Series Release Notes" +msgstr "Mitaka Series Release Notes" + +msgid "Neutron Client Release Notes" +msgstr "Neutron Client Release Notes" + +msgid "Newton Series Release Notes" +msgstr "Newton Series Release Notes" + +msgid "Ocata Series Release Notes" +msgstr "Ocata Series Release Notes" + +msgid "Old Release Notes" +msgstr "Old Release Notes" + +msgid "Pike Series Release Notes" +msgstr "Pike Series Release Notes" + +msgid "Queens Series Release Notes" +msgstr "Queens Series Release Notes" + +msgid "Rocky Series Release Notes" +msgstr "Rocky Series Release Notes" + +msgid "Stein Series Release Notes" +msgstr "Stein Series Release Notes" + +msgid "The ``rbac-create`` command include a --type qos-policy option." +msgstr "The ``rbac-create`` command include a --type qos-policy option." + +msgid "The ``rbac-list`` command output includes a new 'type' column." +msgstr "The ``rbac-list`` command output includes a new 'type' column." + +msgid "" +"The ``subnetpool-create`` and ``subnetpool-update`` commands include a ``--" +"is-default`` option." +msgstr "" +"The ``subnetpool-create`` and ``subnetpool-update`` commands include a ``--" +"is-default`` option." + +msgid "" +"The ``subnetpool-list`` and ``subnetpool-show`` command output includes the " +"``is_default`` field." +msgstr "" +"The ``subnetpool-list`` and ``subnetpool-show`` command output includes the " +"``is_default`` field." + +msgid "" +"The ``tag-add`` command sets a tag on the network resource. It also includes " +"``--resource-type``, ``--resource`` and ``--tag`` options." +msgstr "" +"The ``tag-add`` command sets a tag on the network resource. It also includes " +"``--resource-type``, ``--resource`` and ``--tag`` options." + +msgid "" +"This patch provides user the support to use any form of casing, thus " +"removing the specific UPPER/lower case inputs required by different neutron " +"CLIs." +msgstr "" +"This patch provides users the support to use any form of casing, thus " +"removing the specific UPPER/lower case inputs required by different Neutron " +"CLIs." + +msgid "" +"This project no longer provides CLI support. All code has been removed. " +"Please use openstack CLI instead. See `openstack CLI command list `_." +msgstr "" +"This project no longer provides CLI support. All code has been removed. " +"Please use OpenStack CLI instead. See `openstack CLI command list `_." + +msgid "Train Series Release Notes" +msgstr "Train Series Release Notes" + +msgid "Upgrade Notes" +msgstr "Upgrade Notes" + +msgid "" +"Using 'tenant_id' and 'tenant_name' arguments in API bindings is deprecated. " +"Use 'project_id' and 'project_name' arguments instead." +msgstr "" +"Using 'tenant_id' and 'tenant_name' arguments in API bindings is deprecated. " +"Use 'project_id' and 'project_name' arguments instead." + +msgid "Ussuri Series Release Notes" +msgstr "Ussuri Series Release Notes" + +msgid "Victoria Series Release Notes" +msgstr "Victoria Series Release Notes" + +msgid "Wallaby Series Release Notes" +msgstr "Wallaby Series Release Notes" + +msgid "XML request format support has been removed." +msgstr "XML request format support has been removed." + +msgid "Xena Series Release Notes" +msgstr "Xena Series Release Notes" + +msgid "Yoga Series Release Notes" +msgstr "Yoga Series Release Notes" + +msgid "Zed Series Release Notes" +msgstr "Zed Series Release Notes" + +msgid "add --endpoint-type and OS_ENDPOINT_TYPE to shell client" +msgstr "add --endpoint-type and OS_ENDPOINT_TYPE to shell client" + +msgid "add Lbaas commands" +msgstr "add Lbaas commands" + +msgid "add NVP queue and net gateway commands" +msgstr "add NVP queue and net gateway commands" + +msgid "" +"add ability to update security group name (requires 2013.2-Havana or later)" +msgstr "" +"add ability to update security group name (requires 2013.2-Havana or later)" + +msgid "add commands for DHCP and L3 agents scheduling" +msgstr "add commands for DHCP and L3 agents scheduling" + +msgid "add commands for agent management extensions" +msgstr "add commands for agent management extensions" + +msgid "add flake8 and pbr support for testing and building" +msgstr "add flake8 and pbr support for testing and building" + +msgid "add security group commands" +msgstr "add security group commands" + +msgid "allow options put after positional arguments" +msgstr "allow options put after positional arguments" + +msgid "improved support for listing a large number of filtered subnets" +msgstr "improved support for listing a large number of filtered subnets" + +msgid "made the publicURL the default endpoint instead of adminURL" +msgstr "made the publicURL the default endpoint instead of adminURL" + +msgid "openstack firewall rule create" +msgstr "openstack firewall rule create" + +msgid "openstack firewall rule set" +msgstr "openstack firewall rule set" + +msgid "openstack firewall rule unset" +msgstr "openstack firewall rule unset" + +msgid "py26 support has been dropped." +msgstr "py26 support has been dropped." + +msgid "py33 support has been dropped." +msgstr "py33 support has been dropped." + +msgid "request-format option is deprecated." +msgstr "request-format option is deprecated." + +msgid "support Neutron API 2.0" +msgstr "support Neutron API 2.0" + +msgid "support XML request format" +msgstr "support XML request format" + +msgid "support pagination options" +msgstr "support pagination options" From ee6f6a13ea7843a99e67212e60064da545535d5b Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Sun, 5 Nov 2023 18:31:15 +0900 Subject: [PATCH 116/149] Drop unused simplejson This library no longer import simplejson directly since [1] was merged. [1] 1f35b8f25cb328ede6aea7933ecd33a1cd713ba8 Change-Id: I5689ed9f7852cc2bec3cf8035a773e63fb10e3d5 --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ff8961688..5a20fc0e6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,4 +22,3 @@ keystoneauth1>=3.8.0 # Apache-2.0 # TODO(amotoki): Drop this after osc.utils has no dependency on keystoneclient python-keystoneclient>=3.8.0 # Apache-2.0 requests>=2.14.2 # Apache-2.0 -simplejson>=3.5.1 # MIT From c28a5497c2f712c5435d7b2c53a70e37517ce2db Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Thu, 18 Jan 2024 14:17:42 +0000 Subject: [PATCH 117/149] Add note to prevent new features to be added (CLI and Python bindings) Change-Id: I19fb7426d91d6d7f27fee0507b7c28541ecaf344 --- README.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.rst b/README.rst index a5e5300d6..e8c42d88a 100644 --- a/README.rst +++ b/README.rst @@ -17,6 +17,12 @@ Python bindings to the Neutron API This is a client library for Neutron built on the Neutron API. It provides a Python API (the ``neutronclient`` module). +.. note:: This project has been deprecated. The CLI code has been deleted + and is not accessible anymore. The Python bindings are still in use by + other projects but no new features will be added to this project. + Any new feature should be proposed to OpenStack SDK and OpenStack + Client. + * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Online Documentation`_ From 2d93d2e1ed9f1661c98243d8754faf870cbbe80a Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Sun, 28 Jan 2024 16:26:45 +0900 Subject: [PATCH 118/149] Bump hacking hacking 3.0.x is too old. This also pulls the hacking options from neutron. Change-Id: Ic1a428a05131f98d5a9050b83613c5478904f202 --- neutronclient/common/utils.py | 2 +- neutronclient/neutron/v2_0/bgp/speaker.py | 2 +- neutronclient/osc/v2/sfc/sfc_port_pair_group.py | 2 +- neutronclient/osc/v2/sfc/sfc_service_graph.py | 4 ++-- .../tests/unit/osc/v2/sfc/test_flow_classifier.py | 2 +- .../tests/unit/osc/v2/sfc/test_port_chain.py | 4 ++-- .../tests/unit/osc/v2/sfc/test_service_graph.py | 14 +++++++------- requirements.txt | 4 ---- test-requirements.txt | 7 ++----- tox.ini | 15 ++++++++++++++- 10 files changed, 31 insertions(+), 25 deletions(-) diff --git a/neutronclient/common/utils.py b/neutronclient/common/utils.py index 38274018c..93f92fd19 100644 --- a/neutronclient/common/utils.py +++ b/neutronclient/common/utils.py @@ -138,7 +138,7 @@ def str2dict(strdict, required_keys=None, optional_keys=None): msg = _("missing value for key '%s'") raise argparse.ArgumentTypeError(msg % kv) else: - kvlist[i-1] = "%s,%s" % (kvlist[i-1], kv) + kvlist[i - 1] = "%s,%s" % (kvlist[i - 1], kv) for kv in kvlist: key, sep, value = kv.partition('=') if not sep: diff --git a/neutronclient/neutron/v2_0/bgp/speaker.py b/neutronclient/neutron/v2_0/bgp/speaker.py index 6bdbd86f2..34ce22eb8 100644 --- a/neutronclient/neutron/v2_0/bgp/speaker.py +++ b/neutronclient/neutron/v2_0/bgp/speaker.py @@ -189,7 +189,7 @@ def take_action(self, parsed_args): neutron_client.remove_peer_from_bgp_speaker(_speaker_id, {'bgp_peer_id': _peer_id}) print(_('Removed BGP peer %(peer)s from BGP speaker %(speaker)s.') % - {'peer': parsed_args.bgp_peer, + {'peer': parsed_args.bgp_peer, 'speaker': parsed_args.bgp_speaker}, file=self.app.stdout) diff --git a/neutronclient/osc/v2/sfc/sfc_port_pair_group.py b/neutronclient/osc/v2/sfc/sfc_port_pair_group.py index 5ad3ebea7..ec8859b42 100755 --- a/neutronclient/osc/v2/sfc/sfc_port_pair_group.py +++ b/neutronclient/osc/v2/sfc/sfc_port_pair_group.py @@ -34,7 +34,7 @@ ('port_pair_group_parameters', 'Port Pair Group Parameters', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), - ('project_id', 'Project', column_util.LIST_LONG_ONLY), + ('project_id', 'Project', column_util.LIST_LONG_ONLY), ('is_tap_enabled', 'Tap Enabled', column_util.LIST_BOTH) ) diff --git a/neutronclient/osc/v2/sfc/sfc_service_graph.py b/neutronclient/osc/v2/sfc/sfc_service_graph.py index 6c87d95fe..2edf2ccd0 100644 --- a/neutronclient/osc/v2/sfc/sfc_service_graph.py +++ b/neutronclient/osc/v2/sfc/sfc_service_graph.py @@ -213,8 +213,8 @@ def _validate_destination_chains(comma_split, attrs, client, sc_): dc_ = client.find_sfc_port_chain(e, ignore_missing=False)['id'] attrs['port_chains'][sc_].append(dc_) if _check_cycle(attrs['port_chains'], sc_, dc_): - raise(exceptions.CommandError( - "Error: Service graph contains a cycle")) + raise exceptions.CommandError( + "Error: Service graph contains a cycle") else: raise exceptions.CommandError( "Error: you must specify at least one " diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py b/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py index 6a9e691f9..ea1c4f3ab 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_flow_classifier.py @@ -137,7 +137,7 @@ def test_create_flow_classifier(self): 'logical_destination_port': self._fc['logical_destination_port'], 'l7_parameters': param - } + } ) self.assertEqual(self.columns, columns) diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py b/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py index 9b414c22c..15f7a431e 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_port_chain.py @@ -47,7 +47,7 @@ def get_data(self): self._port_chain['name'], self._port_chain['port_pair_groups'], self._port_chain['project_id'], - ) + ) def setUp(self): super(TestCreateSfcPortChain, self).setUp() @@ -357,7 +357,7 @@ def test_set_only_no_port_pair_group(self): arglist = [ target, '--no-port-pair-group', - ] + ] verifylist = [ (self.res, target), ('no_port_pair_group', True), diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py b/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py index 50a02139d..167f1fcf8 100644 --- a/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py +++ b/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py @@ -123,8 +123,8 @@ def test_create_sfc_service_graph_without_loop(self): arglist = [ "--description", self._service_graph['description'], - "--branching-point", bp1_str, - "--branching-point", bp2_str, + "--branching-point", bp1_str, + "--branching-point", bp2_str, self._service_graph['name']] pcs = {'pc1': ['pc2', 'pc3'], 'pc2': ['pc4']} @@ -154,8 +154,8 @@ def test_create_sfc_service_graph_with_loop(self): arglist = [ "--description", self._service_graph['description'], - "--branching-point", bp1_str, - "--branching-point", bp2_str, + "--branching-point", bp1_str, + "--branching-point", bp2_str, self._service_graph['name']] verifylist = [ @@ -175,7 +175,7 @@ def test_create_sfc_service_graph_invalid_port_chains(self): arglist = [ "--description", self._service_graph['description'], - "--branching-point", bp1_str, + "--branching-point", bp1_str, self._service_graph['name']] verifylist = [ @@ -196,8 +196,8 @@ def test_create_sfc_service_graph_duplicate_src_chains(self): arglist = [ "--description", self._service_graph['description'], - "--branching-point", bp1_str, - "--branching-point", bp2_str, + "--branching-point", bp1_str, + "--branching-point", bp2_str, self._service_graph['name']] verifylist = [ diff --git a/requirements.txt b/requirements.txt index 5a20fc0e6..5f10ef907 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,6 @@ # Requirements lower bounds listed here are our best effort to keep them up to # date but we do not test them so no guarantee of having them all correct. If # you find any incorrect lower bounds, let us know or propose a fix. - -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. pbr!=2.1.0,>=2.0.0 # Apache-2.0 cliff>=3.4.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 diff --git a/test-requirements.txt b/test-requirements.txt index ae1f2e55d..8cd49ce02 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,12 +1,9 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -hacking>=3.0.1,<3.1.0 # Apache-2.0 +hacking>=6.1.0,<6.2.0 # Apache-2.0 bandit!=1.6.0,>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 fixtures>=3.0.0 # Apache-2.0/BSD -flake8-import-order==0.12 # LGPLv3 +flake8-import-order>=0.18.0,<0.19.0 # LGPLv3 oslotest>=3.2.0 # Apache-2.0 osprofiler>=2.3.0 # Apache-2.0 python-openstackclient>=3.12.0 # Apache-2.0 diff --git a/tox.ini b/tox.ini index afdf530e2..cda43b91c 100644 --- a/tox.ini +++ b/tox.ini @@ -66,12 +66,25 @@ deps = commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] +# E126 continuation line over-indented for hanging indent +# E128 continuation line under-indented for visual indent +# H405 multi line docstring summary not separated with an empty line +# I202 Additional newline in a group of imports +# N530 direct neutron imports not allowed +# TODO(amotoki) check the following new rules should be fixed or ignored +# E731 do not assign a lambda expression, use a def +# W504 line break after binary operator +ignore = E126,E128,E731,I202,H405,N530,W504 show-source = true exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,tools import-order-style = pep8 +# H106: Don't put vim configuration in source files +# H203: Use assertIs(Not)None to check for None +# H204: Use assert(Not)Equal to check for equality +# H205: Use assert(Greater|Less)(Equal) for comparison # H904: Delay string interpolations at logging calls -enable-extensions=H904 +enable-extensions=H106,H203,H204,H205,H904 [testenv:bandit] # B303: blacklist calls: md5, sha1 From 858b844cff2234f98af564946a310587e81650f6 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Mon, 5 Feb 2024 16:47:19 +0000 Subject: [PATCH 119/149] reno: Update master for unmaintained/yoga Update the yoga release notes configuration to build from unmaintained/yoga. Change-Id: Id65b43b5bd59567cec599aae48e962c6ac40b427 --- releasenotes/source/yoga.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/source/yoga.rst b/releasenotes/source/yoga.rst index 7cd5e908a..43cafdea8 100644 --- a/releasenotes/source/yoga.rst +++ b/releasenotes/source/yoga.rst @@ -3,4 +3,4 @@ Yoga Series Release Notes ========================= .. release-notes:: - :branch: stable/yoga + :branch: unmaintained/yoga From 750afa1777599827a86db3470254048aeeab2b8a Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Wed, 6 Mar 2024 12:04:19 +0000 Subject: [PATCH 120/149] reno: Update master for unmaintained/victoria Update the victoria release notes configuration to build from unmaintained/victoria. Change-Id: I27ad08ec3327a9a9984223f7d9319129537040e4 --- releasenotes/source/victoria.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/source/victoria.rst b/releasenotes/source/victoria.rst index 4efc7b6f3..8ce933419 100644 --- a/releasenotes/source/victoria.rst +++ b/releasenotes/source/victoria.rst @@ -3,4 +3,4 @@ Victoria Series Release Notes ============================= .. release-notes:: - :branch: stable/victoria + :branch: unmaintained/victoria From 863c6031fc866ac1c59087b93655402cad05c974 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Wed, 6 Mar 2024 12:14:08 +0000 Subject: [PATCH 121/149] reno: Update master for unmaintained/wallaby Update the wallaby release notes configuration to build from unmaintained/wallaby. Change-Id: Ia81995fae56aef0951004ab1c7340a38f24a66f0 --- releasenotes/source/wallaby.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/source/wallaby.rst b/releasenotes/source/wallaby.rst index d77b56599..bcf35c5f8 100644 --- a/releasenotes/source/wallaby.rst +++ b/releasenotes/source/wallaby.rst @@ -3,4 +3,4 @@ Wallaby Series Release Notes ============================ .. release-notes:: - :branch: stable/wallaby + :branch: unmaintained/wallaby From 41e7ea6e29866a95927aaca9cd4bf3846243aa02 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Wed, 6 Mar 2024 12:21:58 +0000 Subject: [PATCH 122/149] reno: Update master for unmaintained/xena Update the xena release notes configuration to build from unmaintained/xena. Change-Id: I074395b7079588a5dd2f6188a04b5d48b10e124b --- releasenotes/source/xena.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/source/xena.rst b/releasenotes/source/xena.rst index 1be85be3e..d19eda488 100644 --- a/releasenotes/source/xena.rst +++ b/releasenotes/source/xena.rst @@ -3,4 +3,4 @@ Xena Series Release Notes ========================= .. release-notes:: - :branch: stable/xena + :branch: unmaintained/xena From fe515adf350ce93ced6ee6532185d106e218b9fe Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 7 Mar 2024 15:38:58 +0000 Subject: [PATCH 123/149] Update master for stable/2024.1 Add file to the reno documentation build to show release notes for stable/2024.1. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/2024.1. Sem-Ver: feature Change-Id: I074213d853338f1e087b59f14f3c66ea449e5536 --- releasenotes/source/2024.1.rst | 6 ++++++ releasenotes/source/index.rst | 1 + 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/2024.1.rst diff --git a/releasenotes/source/2024.1.rst b/releasenotes/source/2024.1.rst new file mode 100644 index 000000000..4977a4f1a --- /dev/null +++ b/releasenotes/source/2024.1.rst @@ -0,0 +1,6 @@ +=========================== +2024.1 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2024.1 diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index dffa77497..e3e11c8fa 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + 2024.1 2023.2 2023.1 zed From 2169b2bbab1b09c320d4eeeb2b341c99b4c3ef87 Mon Sep 17 00:00:00 2001 From: Benjamin Reichel Date: Fri, 15 Mar 2024 08:58:34 +0100 Subject: [PATCH 124/149] Fix insert and remove rule from firewall policy This change fixes the incompatability with the openstacksdk for inserting and removing rules from firewall policiese. Closes-Bug: #2057816 Change-Id: I8db7b4cc61b810887b0a675efa562f089821e8ec --- neutronclient/osc/v2/fwaas/firewallpolicy.py | 4 ++-- .../unit/osc/v2/fwaas/test_firewallpolicy.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/neutronclient/osc/v2/fwaas/firewallpolicy.py b/neutronclient/osc/v2/fwaas/firewallpolicy.py index e049698f7..cfcc3c1df 100644 --- a/neutronclient/osc/v2/fwaas/firewallpolicy.py +++ b/neutronclient/osc/v2/fwaas/firewallpolicy.py @@ -235,7 +235,7 @@ def take_action(self, parsed_args): policy_id = client.find_firewall_policy( parsed_args.firewall_policy)['id'] body = self.args2body(parsed_args) - client.insert_rule_into_policy(policy_id, body) + client.insert_rule_into_policy(policy_id, **body) rule_id = body['firewall_rule_id'] policy = parsed_args.firewall_policy print((_('Inserted firewall rule %(rule)s in firewall policy ' @@ -264,7 +264,7 @@ def take_action(self, parsed_args): parsed_args.firewall_policy)['id'] fwr_id = _get_required_firewall_rule(client, parsed_args) body = {'firewall_rule_id': fwr_id} - client.remove_rule_from_policy(policy_id, body) + client.remove_rule_from_policy(policy_id, **body) rule_id = body['firewall_rule_id'] policy = parsed_args.firewall_policy print((_('Removed firewall rule %(rule)s from firewall policy ' diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py index 7d49879dc..fe385a0cb 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py @@ -507,12 +507,12 @@ def test_insert_firewall_rule(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, { - 'firewall_rule_id': rule, - 'insert_before': before, - 'insert_after': after - }) + body = { + 'firewall_rule_id': rule, + 'insert_before': before, + 'insert_after': after + } + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) self.assertEqual(3, self.networkclient.find_firewall_rule.call_count) @@ -560,8 +560,8 @@ def test_remove_firewall_rule(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, {'firewall_rule_id': rule}) + body = {'firewall_rule_id': rule} + self.mocked.assert_called_once_with(target, **body) self.assertIsNone(result) self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) From fb8de782bcd44741b633e15352d76476d24f246e Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Tue, 30 Apr 2024 08:54:59 +0000 Subject: [PATCH 125/149] reno: Update master for unmaintained/zed Update the zed release notes configuration to build from unmaintained/zed. Change-Id: I73aa32050dfaa378dd7455846e994560851c0e54 --- releasenotes/source/zed.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/source/zed.rst b/releasenotes/source/zed.rst index 9608c05e4..6cc2b1554 100644 --- a/releasenotes/source/zed.rst +++ b/releasenotes/source/zed.rst @@ -3,4 +3,4 @@ Zed Series Release Notes ======================== .. release-notes:: - :branch: stable/zed + :branch: unmaintained/zed From cb9aae55c83c2b79fdd5d15d93e5c12b35f0dd78 Mon Sep 17 00:00:00 2001 From: Valentin Chassignol Date: Wed, 1 May 2024 10:33:46 +0200 Subject: [PATCH 126/149] BGPVPN: Fix resource comparison This patch updates the resource comparison to accurately differentiate between the manipulation of networks, ports, and router associations. Introduced in I84fe4bb45d24c2f4a7a0246e2b9fb50354a715e0, the previous implementation contained incorrect variable names, leading to inconsistent results. This fix ensures that each resource type is properly identified during comparison. Closes-Bug: #2064286 Change-Id: Ieb87174296240f8f76ec10b39007935545b1bd3f --- .../networking_bgpvpn/resource_association.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/neutronclient/osc/v2/networking_bgpvpn/resource_association.py b/neutronclient/osc/v2/networking_bgpvpn/resource_association.py index 925ee517a..83ac7d99f 100644 --- a/neutronclient/osc/v2/networking_bgpvpn/resource_association.py +++ b/neutronclient/osc/v2/networking_bgpvpn/resource_association.py @@ -75,10 +75,10 @@ def take_action(self, parsed_args): body.update( arg2body(bgpvpn['id'], parsed_args)) - if self._assoc_res_name == constants.NETWORK_ASSOC: + if self._resource == constants.NETWORK_ASSOC: obj = client.create_bgpvpn_network_association( bgpvpn['id'], **body) - elif self._assoc_res_name == constants.PORT_ASSOCS: + elif self._resource == constants.PORT_ASSOC: obj = client.create_bgpvpn_port_association(bgpvpn['id'], **body) else: obj = client.create_bgpvpn_router_association( @@ -123,10 +123,10 @@ def take_action(self, parsed_args): arg2body = getattr(self, '_args2body', None) if callable(arg2body): body = arg2body(bgpvpn['id'], parsed_args) - if self._assoc_res_name == constants.NETWORK_ASSOC: + if self._resource == constants.NETWORK_ASSOC: client.update_bgpvpn_network_association( bgpvpn['id'], parsed_args.resource_association_id, **body) - elif self._assoc_res_name == constants.PORT_ASSOCS: + elif self._resource == constants.PORT_ASSOC: client.update_bgpvpn_port_association( bgpvpn['id'], parsed_args.resource_association_id, **body) else: @@ -165,9 +165,9 @@ def take_action(self, parsed_args): fails = 0 for id in parsed_args.resource_association_ids: try: - if self._assoc_res_name == constants.NETWORK_ASSOC: + if self._resource == constants.NETWORK_ASSOC: client.delete_bgpvpn_network_association(bgpvpn['id'], id) - elif self._assoc_res_name == constants.PORT_ASSOCS: + elif self._resource == constants.PORT_ASSOC: client.delete_bgpvpn_port_association(bgpvpn['id'], id) else: client.delete_bgpvpn_router_association(bgpvpn['id'], id) @@ -221,10 +221,10 @@ def take_action(self, parsed_args): params = {} if parsed_args.property: params.update(parsed_args.property) - if self._assoc_res_name == constants.NETWORK_ASSOC: + if self._resource == constants.NETWORK_ASSOC: objs = client.bgpvpn_network_associations( bgpvpn['id'], retrieve_all=True, **params) - elif self._assoc_res_name == constants.PORT_ASSOCS: + elif self._resource == constants.PORT_ASSOC: objs = client.bgpvpn_port_associations( bgpvpn['id'], retrieve_all=True, **params) else: @@ -265,10 +265,10 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) - if self._assoc_res_name == constants.NETWORK_ASSOC: + if self._resource == constants.NETWORK_ASSOC: obj = client.get_bgpvpn_network_association( bgpvpn['id'], parsed_args.resource_association_id) - elif self._assoc_res_name == constants.PORT_ASSOCS: + elif self._resource == constants.PORT_ASSOC: obj = client.get_bgpvpn_port_association( bgpvpn['id'], parsed_args.resource_association_id) else: From d36a8a4a177b05eba9998637127fcf3b6d02373f Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 5 Sep 2024 16:02:19 +0000 Subject: [PATCH 127/149] Update master for stable/2024.2 Add file to the reno documentation build to show release notes for stable/2024.2. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/2024.2. Sem-Ver: feature Change-Id: I02c3547991a272afcc3a8902476949cd0bd1ce74 --- releasenotes/source/2024.2.rst | 6 ++++++ releasenotes/source/index.rst | 1 + 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/2024.2.rst diff --git a/releasenotes/source/2024.2.rst b/releasenotes/source/2024.2.rst new file mode 100644 index 000000000..aaebcbc8c --- /dev/null +++ b/releasenotes/source/2024.2.rst @@ -0,0 +1,6 @@ +=========================== +2024.2 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2024.2 diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index e3e11c8fa..0a5640c8e 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + 2024.2 2024.1 2023.2 2023.1 From 5438377b9c815ca1bfb13a22b4d6645f3731223d Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Sat, 12 Oct 2024 00:05:58 +0900 Subject: [PATCH 128/149] Drop unused tempest from test requirements None of the tests implemented in this repository depend on tempest. In addition testscenarios is not used either, and can be removed. Change-Id: I642f8a5093a6e2b5528e446a798270734c4ed30d --- test-requirements.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/test-requirements.txt b/test-requirements.txt index 8cd49ce02..2e847fa46 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -11,5 +11,3 @@ python-subunit>=1.0.0 # Apache-2.0/BSD requests-mock>=1.2.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0 testtools>=2.2.0 # MIT -testscenarios>=0.4 # Apache-2.0/BSD -tempest>=17.1.0 # Apache-2.0 From 8a2f07683bea1877ff746faaa19df76f953f71b6 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Sun, 13 Oct 2024 01:30:27 +0900 Subject: [PATCH 129/149] tox: Drop envdir tox now always recreates an env although the env is shared using envdir options. ~~~ $ tox -e genpolicy genpolicy: recreate env because env type changed from {'name': 'genconfig', 'type': 'VirtualEnvRunner'} to {'name': 'genpolicy', 'type': 'VirtualEnvRunner'} ~~~ According to the maintainer of tox, this functionality is not intended to be supported. https://github.com/tox-dev/tox/issues/425#issuecomment-1011944293 Change-Id: I496d3ffe65be13df80c29ac4582596be0aa4d909 --- tox.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/tox.ini b/tox.ini index cda43b91c..a939f8b65 100644 --- a/tox.ini +++ b/tox.ini @@ -51,7 +51,6 @@ deps = commands = sphinx-build -W -b html doc/source doc/build/html [testenv:pdf-docs] -envdir = {toxworkdir}/docs deps = {[testenv:docs]deps} allowlist_externals = make From f882f1ddb60bcd77096eb8a74e9e86d10723e8be Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Thu, 24 Oct 2024 21:19:15 +0900 Subject: [PATCH 130/149] Remove Python 3.8 support Python 3.8 was removed from the tested runtimes for 2024.2[1] and has not been tested since then. Also add a few newer versions which are part of the tested runtimes for 2025.1. [1] https://governance.openstack.org/tc/reference/runtimes/2024.2.html Change-Id: Ic0c05be1ce22dc2a5c67c6eb2b215d50d57ff116 --- releasenotes/notes/remove-py38-26a1befde3f44b82.yaml | 5 +++++ setup.cfg | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/remove-py38-26a1befde3f44b82.yaml diff --git a/releasenotes/notes/remove-py38-26a1befde3f44b82.yaml b/releasenotes/notes/remove-py38-26a1befde3f44b82.yaml new file mode 100644 index 000000000..a0440dc80 --- /dev/null +++ b/releasenotes/notes/remove-py38-26a1befde3f44b82.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - | + Python 3.8 support was dropped. The minimum version of Python now supported + is Python 3.9. diff --git a/setup.cfg b/setup.cfg index 7af675d1d..3005e895b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,7 +6,7 @@ description_file = author = OpenStack Networking Project author_email = openstack-discuss@lists.openstack.org home_page = https://docs.openstack.org/python-neutronclient/latest/ -python_requires = >=3.8 +python_requires = >=3.9 classifier = Environment :: OpenStack Intended Audience :: Developers @@ -18,8 +18,10 @@ classifier = Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 [files] packages = From b2107dc867e7a5bb6d86caa4b2a3fc8da3dc09eb Mon Sep 17 00:00:00 2001 From: elajkat Date: Wed, 6 Nov 2024 10:11:22 +0100 Subject: [PATCH 131/149] vpnaas: show external_vx_ip for vpn service show Closes-Bug: #2086144 Change-Id: Ic8ae85ee62e35991e8bb0096cdc6785a0b04e545 --- neutronclient/osc/v2/vpnaas/vpnservice.py | 10 ++++++---- neutronclient/tests/unit/osc/v2/vpnaas/fakes.py | 2 ++ .../tests/unit/osc/v2/vpnaas/test_vpnservice.py | 8 ++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/neutronclient/osc/v2/vpnaas/vpnservice.py b/neutronclient/osc/v2/vpnaas/vpnservice.py index f845a57ff..9e1e489ca 100644 --- a/neutronclient/osc/v2/vpnaas/vpnservice.py +++ b/neutronclient/osc/v2/vpnaas/vpnservice.py @@ -36,6 +36,8 @@ ('status', 'Status', column_util.LIST_BOTH), ('description', 'Description', column_util.LIST_LONG_ONLY), ('project_id', 'Project', column_util.LIST_LONG_ONLY), + ('external_v4_ip', 'Ext v4 IP', column_util.LIST_LONG_ONLY), + ('external_v6_ip', 'Ext v6 IP', column_util.LIST_LONG_ONLY), ) _attr_map_dict = { @@ -48,6 +50,8 @@ 'status': 'Status', 'description': 'Description', 'project_id': 'Project', + 'external_v4_ip': 'Ext v4 IP', + 'external_v6_ip': 'Ext v6 IP', } @@ -135,8 +139,7 @@ def take_action(self, parsed_args): attrs['router_id'] = _router_id obj = client.create_vpn_service(**attrs) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( - obj, _attr_map_dict, ['location', 'tenant_id', 'external_v4_ip', - 'external_v6_ip']) + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return display_columns, data @@ -244,7 +247,6 @@ def take_action(self, parsed_args): ignore_missing=False)['id'] obj = client.get_vpn_service(vpn_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( - obj, _attr_map_dict, ['location', 'tenant_id', 'external_v4_ip', - 'external_v6_ip']) + obj, _attr_map_dict, ['location', 'tenant_id']) data = utils.get_dict_properties(obj, columns) return (display_columns, data) diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py b/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py index 2344c0a1f..24e6497fc 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/fakes.py @@ -125,6 +125,8 @@ def __init__(self): ('status', 'ACTIVE'), ('description', 'my-desc-' + uuid.uuid4().hex), ('project_id', 'project-id-' + uuid.uuid4().hex), + ('external_v4_ip', '192.0.2.42'), + ('external_v6_ip', '2001:0db8:207a:4a3a:053b:6fab:7df9:1afd'), )) diff --git a/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py b/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py index 458c7f654..521fe741c 100644 --- a/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py +++ b/neutronclient/tests/unit/osc/v2/vpnaas/test_vpnservice.py @@ -106,10 +106,14 @@ def _mock_vpnservice(*args, **kwargs): 'Status', 'Description', 'Project', + 'Ext v4 IP', + 'Ext v6 IP', ) self.data = _generate_data() self.ordered_headers = ( 'Description', + 'Ext v4 IP', + 'Ext v6 IP', 'Flavor', 'ID', 'Name', @@ -121,6 +125,8 @@ def _mock_vpnservice(*args, **kwargs): ) self.ordered_data = ( _vpnservice['description'], + _vpnservice['external_v4_ip'], + _vpnservice['external_v6_ip'], _vpnservice['flavor_id'], _vpnservice['id'], _vpnservice['name'], @@ -132,6 +138,8 @@ def _mock_vpnservice(*args, **kwargs): ) self.ordered_columns = ( 'description', + 'external_v4_ip', + 'external_v6_ip', 'flavor_id', 'id', 'name', From 636ac764d350c610504eab2e7b3283248581d5e3 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 14 Nov 2024 10:35:43 +0000 Subject: [PATCH 132/149] reno: Update master for unmaintained/2023.1 Update the 2023.1 release notes configuration to build from unmaintained/2023.1. Change-Id: Id69fb2c2e197e91d679473c52f556e378fa3ba1e --- releasenotes/source/2023.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/source/2023.1.rst b/releasenotes/source/2023.1.rst index d1238479b..2c9a36fae 100644 --- a/releasenotes/source/2023.1.rst +++ b/releasenotes/source/2023.1.rst @@ -3,4 +3,4 @@ =========================== .. release-notes:: - :branch: stable/2023.1 + :branch: unmaintained/2023.1 From dc026cd3d6a280768b2d477410058b16ef86e124 Mon Sep 17 00:00:00 2001 From: Bodo Petermann Date: Wed, 26 Feb 2025 15:57:35 +0100 Subject: [PATCH 133/149] vpnaas: add support for more ciphers (auth, encryption, pfs modes) Extend the lists of choices for encryption algorithms, auth algorithms, and PFS groups to include the additions made in neutron-vpnaas. Encryption algorithms: add AES CCM mode and AES GCM mode variants for 128/192/256 bit keys and 8/12/16 octet ICVs, add AES CTR modes for 128/192/256 bit keys Auth algorithms: add aes-xcbc and aes-cmac. PFS: add Diffie Hellman groups 15 to 31. Related-Bug: #1938284 Change-Id: I3fd17b93820da9d86b2fc4bc89058475d7629d5d --- neutronclient/osc/v2/vpnaas/ikepolicy.py | 66 +++++++++++++++++++++- neutronclient/osc/v2/vpnaas/ipsecpolicy.py | 66 +++++++++++++++++++++- 2 files changed, 126 insertions(+), 6 deletions(-) diff --git a/neutronclient/osc/v2/vpnaas/ikepolicy.py b/neutronclient/osc/v2/vpnaas/ikepolicy.py index 766a550f1..0a8aecb08 100644 --- a/neutronclient/osc/v2/vpnaas/ikepolicy.py +++ b/neutronclient/osc/v2/vpnaas/ikepolicy.py @@ -56,6 +56,66 @@ 'project_id': 'Project', } +_auth_algorithms = [ + 'sha1', + 'sha256', + 'sha384', + 'sha512', + 'aes-xcbc', + 'aes-cmac', +] + +_encryption_algorithms = [ + '3des', + 'aes-128', + 'aes-192', + 'aes-256', + 'aes-128-ccm-8', + 'aes-192-ccm-8', + 'aes-256-ccm-8', + 'aes-128-ccm-12', + 'aes-192-ccm-12', + 'aes-256-ccm-12', + 'aes-128-ccm-16', + 'aes-192-ccm-16', + 'aes-256-ccm-16', + 'aes-128-gcm-8', + 'aes-192-gcm-8', + 'aes-256-gcm-8', + 'aes-128-gcm-12', + 'aes-192-gcm-12', + 'aes-256-gcm-12', + 'aes-128-gcm-16', + 'aes-192-gcm-16', + 'aes-256-gcm-16', + 'aes-128-ctr', + 'aes-192-ctr', + 'aes-256-ctr', +] + +_pfs_groups = [ + 'group2', + 'group5', + 'group14', + 'group15', + 'group16', + 'group17', + 'group18', + 'group19', + 'group20', + 'group21', + 'group22', + 'group23', + 'group24', + 'group25', + 'group26', + 'group27', + 'group28', + 'group29', + 'group30', + 'group31', +] + def _convert_to_lowercase(string): return string.lower() @@ -68,12 +128,12 @@ def _get_common_parser(parser): help=_('Description of the IKE policy')) parser.add_argument( '--auth-algorithm', - choices=['sha1', 'sha256', 'sha384', 'sha512'], + choices=_auth_algorithms, type=_convert_to_lowercase, help=_('Authentication algorithm')) parser.add_argument( '--encryption-algorithm', - choices=['aes-128', '3des', 'aes-192', 'aes-256'], + choices=_encryption_algorithms, type=_convert_to_lowercase, help=_('Encryption algorithm')) parser.add_argument( @@ -88,7 +148,7 @@ def _get_common_parser(parser): help=_('IKE version for the policy')) parser.add_argument( '--pfs', - choices=['group5', 'group2', 'group14'], + choices=_pfs_groups, type=_convert_to_lowercase, help=_('Perfect Forward Secrecy')) parser.add_argument( diff --git a/neutronclient/osc/v2/vpnaas/ipsecpolicy.py b/neutronclient/osc/v2/vpnaas/ipsecpolicy.py index 877602ffc..c6e42bd06 100644 --- a/neutronclient/osc/v2/vpnaas/ipsecpolicy.py +++ b/neutronclient/osc/v2/vpnaas/ipsecpolicy.py @@ -54,6 +54,66 @@ 'project_id': 'Project', } +_auth_algorithms = [ + 'sha1', + 'sha256', + 'sha384', + 'sha512', + 'aes-xcbc', + 'aes-cmac', +] + +_encryption_algorithms = [ + '3des', + 'aes-128', + 'aes-192', + 'aes-256', + 'aes-128-ccm-8', + 'aes-192-ccm-8', + 'aes-256-ccm-8', + 'aes-128-ccm-12', + 'aes-192-ccm-12', + 'aes-256-ccm-12', + 'aes-128-ccm-16', + 'aes-192-ccm-16', + 'aes-256-ccm-16', + 'aes-128-gcm-8', + 'aes-192-gcm-8', + 'aes-256-gcm-8', + 'aes-128-gcm-12', + 'aes-192-gcm-12', + 'aes-256-gcm-12', + 'aes-128-gcm-16', + 'aes-192-gcm-16', + 'aes-256-gcm-16', + 'aes-128-ctr', + 'aes-192-ctr', + 'aes-256-ctr', +] + +_pfs_groups = [ + 'group2', + 'group5', + 'group14', + 'group15', + 'group16', + 'group17', + 'group18', + 'group19', + 'group20', + 'group21', + 'group22', + 'group23', + 'group24', + 'group25', + 'group26', + 'group27', + 'group28', + 'group29', + 'group30', + 'group31', +] + def _convert_to_lowercase(string): return string.lower() @@ -66,7 +126,7 @@ def _get_common_parser(parser): help=_('Description of the IPsec policy')) parser.add_argument( '--auth-algorithm', - choices=['sha1', 'sha256', 'sha384', 'sha512'], + choices=_auth_algorithms, type=_convert_to_lowercase, help=_('Authentication algorithm for IPsec policy')) parser.add_argument( @@ -76,7 +136,7 @@ def _get_common_parser(parser): help=_('Encapsulation mode for IPsec policy')) parser.add_argument( '--encryption-algorithm', - choices=['3des', 'aes-128', 'aes-192', 'aes-256'], + choices=_encryption_algorithms, type=_convert_to_lowercase, help=_('Encryption algorithm for IPsec policy')) parser.add_argument( @@ -86,7 +146,7 @@ def _get_common_parser(parser): help=vpn_utils.lifetime_help("IPsec")) parser.add_argument( '--pfs', - choices=['group2', 'group5', 'group14'], + choices=_pfs_groups, type=_convert_to_lowercase, help=_('Perfect Forward Secrecy for IPsec policy')) parser.add_argument( From 370bd215c7fb59822e529ae2a0a136803d40e535 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Sat, 1 Mar 2025 01:10:46 +0900 Subject: [PATCH 134/149] Remove unnecessary direct dependency on iso8601 Direct dependency on the library was removed by [1]. [1] 9c464ba53f0c1317a397f96202b577f0729fc4eb Change-Id: Id24f85b68c42977cb3f34c66934238a16e03a79c --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5f10ef907..4c6371c3f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,6 @@ pbr!=2.1.0,>=2.0.0 # Apache-2.0 cliff>=3.4.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 -iso8601>=0.1.11 # MIT netaddr>=0.7.18 # BSD openstacksdk>=1.5.0 # Apache-2.0 osc-lib>=1.12.0 # Apache-2.0 From 690bb97d9dff389af273ddc517029c1612028839 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 6 Mar 2025 09:16:53 +0000 Subject: [PATCH 135/149] Update master for stable/2025.1 Add file to the reno documentation build to show release notes for stable/2025.1. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/2025.1. Sem-Ver: feature Change-Id: Ia1fb8c591c315404d4e758a657a4b35fe523dfff --- releasenotes/source/2025.1.rst | 6 ++++++ releasenotes/source/index.rst | 1 + 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/2025.1.rst diff --git a/releasenotes/source/2025.1.rst b/releasenotes/source/2025.1.rst new file mode 100644 index 000000000..3add0e53a --- /dev/null +++ b/releasenotes/source/2025.1.rst @@ -0,0 +1,6 @@ +=========================== +2025.1 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2025.1 diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index 0a5640c8e..d146d481c 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + 2025.1 2024.2 2024.1 2023.2 From 857b4b233cb8353c362809e78a97bdb04f0e98fd Mon Sep 17 00:00:00 2001 From: elajkat Date: Tue, 22 Apr 2025 13:01:02 +0200 Subject: [PATCH 136/149] Add warning for using the python bindings The deprecation of python-neutronclient bindings was discussed on the 2025.2 (Flamingo) PTG: https://etherpad.opendev.org/p/apr2025-ptg-neutron#L163 Change-Id: Ieb08fc0884d7f386dc94090dce9d284d786d1ec2 --- README.rst | 1 + neutronclient/v2_0/client.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/README.rst b/README.rst index e8c42d88a..eaac15c2c 100644 --- a/README.rst +++ b/README.rst @@ -20,6 +20,7 @@ provides a Python API (the ``neutronclient`` module). .. note:: This project has been deprecated. The CLI code has been deleted and is not accessible anymore. The Python bindings are still in use by other projects but no new features will be added to this project. + All projects under Openstack governance migrating to use OpenstackSDK. Any new feature should be proposed to OpenStack SDK and OpenStack Client. diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index de0529182..9922eb31c 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -250,6 +250,9 @@ class ClientBase(object): def __init__(self, **kwargs): """Initialize a new client for the Neutron v2.0 API.""" super(ClientBase, self).__init__() + _logger.warning("The python binding code in neutronclient is " + "deprecated in favor of OpenstackSDK, please use " + "that as this will be removed in a future release.") self.retries = kwargs.pop('retries', 0) self.raise_errors = kwargs.pop('raise_errors', True) self.httpclient = client.construct_http_client(**kwargs) From 905be917fe22b44f9df25c018dec155b904938b1 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Tue, 10 Jun 2025 21:07:44 +0900 Subject: [PATCH 137/149] Drop explicit dependency on python-subunit It is no longer directly used by any test code in this repository since we switched to stestr[1]. It is now installed as a dependency of stestr. [1] 259c386d424370160c861748ccd18f0c08452d3c Change-Id: Iacbdd3477a9e0b2d2bae3e09d20867d794586673 --- test-requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 2e847fa46..464d2b8a4 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -7,7 +7,6 @@ flake8-import-order>=0.18.0,<0.19.0 # LGPLv3 oslotest>=3.2.0 # Apache-2.0 osprofiler>=2.3.0 # Apache-2.0 python-openstackclient>=3.12.0 # Apache-2.0 -python-subunit>=1.0.0 # Apache-2.0/BSD requests-mock>=1.2.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0 testtools>=2.2.0 # MIT From 275924ecc8968a3bc77020db7223ac3b32731b24 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Wed, 2 Jul 2025 23:22:56 +0900 Subject: [PATCH 138/149] Drop unused os-client-config It was deprecated[1] after the code was merged into openstacksdk[2]. It's not actually used by any code in this repository. [1] https://review.opendev.org/c/openstack/os-client-config/+/549307 [2] https://review.opendev.org/c/openstack/openstacksdk/+/518128 Change-Id: Ia93d2952ca09fc70a970a85789775441ed114d49 Signed-off-by: Takashi Kajinami --- .zuul.yaml | 1 - requirements.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index 0bbe8f4dc..7c8822186 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -31,7 +31,6 @@ - openstack/keystoneauth - openstack/neutron - openstack/neutron-lib - - openstack/os-client-config - openstack/python-cinderclient - openstack/python-glanceclient - openstack/python-ironicclient diff --git a/requirements.txt b/requirements.txt index 4c6371c3f..41ca9d7ef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,6 @@ oslo.i18n>=3.15.3 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 -os-client-config>=1.28.0 # Apache-2.0 keystoneauth1>=3.8.0 # Apache-2.0 # keystoneclient is used only by neutronclient.osc.utils # TODO(amotoki): Drop this after osc.utils has no dependency on keystoneclient From 2f170ce6aaa7fee7cc83504d8e558d6507b736f4 Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Thu, 4 Sep 2025 13:44:40 +0000 Subject: [PATCH 139/149] Update master for stable/2025.2 Add file to the reno documentation build to show release notes for stable/2025.2. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/2025.2. Sem-Ver: feature Change-Id: I97f7bba4f875b98d98f03ba60ee394a1aa64a3fd Signed-off-by: OpenStack Release Bot Generated-By: openstack/project-config:roles/copy-release-tools-scripts/files/release-tools/add_release_note_page.sh --- releasenotes/source/2025.2.rst | 6 ++++++ releasenotes/source/index.rst | 1 + 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/2025.2.rst diff --git a/releasenotes/source/2025.2.rst b/releasenotes/source/2025.2.rst new file mode 100644 index 000000000..4dae18d86 --- /dev/null +++ b/releasenotes/source/2025.2.rst @@ -0,0 +1,6 @@ +=========================== +2025.2 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2025.2 diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index d146d481c..73d4a0cab 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + 2025.2 2025.1 2024.2 2024.1 From 01ffc4684a4a8b443bd2c5d66f3335af7fdaddc4 Mon Sep 17 00:00:00 2001 From: Mohammed Naser Date: Fri, 12 Sep 2025 11:29:32 -0400 Subject: [PATCH 140/149] Add Tap-as-a-Service client code This commit adds the Tap-as-a-Service client code as-is based on the discussion that it can now be included into the Neutron client[1]. [1]: https://lists.openstack.org/archives/list/openstack-discuss@lists.openstack.org/message/PCITF3UPLEEVQB7EVJ2MB6FLAI3RFYSR/ Change-Id: I82b3229b3f9ac7ef57324d0a611527c77d26c3b6 Signed-off-by: Mohammed Naser --- neutronclient/osc/v2/taas/__init__.py | 0 neutronclient/osc/v2/taas/tap_flow.py | 225 ++++++++++++++ neutronclient/osc/v2/taas/tap_mirror.py | 222 ++++++++++++++ neutronclient/osc/v2/taas/tap_service.py | 211 +++++++++++++ .../tests/unit/osc/v2/taas/__init__.py | 0 neutronclient/tests/unit/osc/v2/taas/fakes.py | 122 ++++++++ .../unit/osc/v2/taas/test_osc_tap_flow.py | 283 ++++++++++++++++++ .../unit/osc/v2/taas/test_osc_tap_mirror.py | 267 +++++++++++++++++ .../unit/osc/v2/taas/test_osc_tap_service.py | 250 ++++++++++++++++ setup.cfg | 16 + 10 files changed, 1596 insertions(+) create mode 100644 neutronclient/osc/v2/taas/__init__.py create mode 100644 neutronclient/osc/v2/taas/tap_flow.py create mode 100644 neutronclient/osc/v2/taas/tap_mirror.py create mode 100644 neutronclient/osc/v2/taas/tap_service.py create mode 100644 neutronclient/tests/unit/osc/v2/taas/__init__.py create mode 100644 neutronclient/tests/unit/osc/v2/taas/fakes.py create mode 100644 neutronclient/tests/unit/osc/v2/taas/test_osc_tap_flow.py create mode 100644 neutronclient/tests/unit/osc/v2/taas/test_osc_tap_mirror.py create mode 100644 neutronclient/tests/unit/osc/v2/taas/test_osc_tap_service.py diff --git a/neutronclient/osc/v2/taas/__init__.py b/neutronclient/osc/v2/taas/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neutronclient/osc/v2/taas/tap_flow.py b/neutronclient/osc/v2/taas/tap_flow.py new file mode 100644 index 000000000..428d059e0 --- /dev/null +++ b/neutronclient/osc/v2/taas/tap_flow.py @@ -0,0 +1,225 @@ +# All Rights Reserved 2020 +# +# 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 logging + +from osc_lib.cli import format_columns +from osc_lib.cli import identity as identity_utils +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils as osc_utils +from osc_lib.utils import columns as column_util + +from neutronclient._i18n import _ +from neutronclient.osc.v2.taas import tap_service + +LOG = logging.getLogger(__name__) + +TAP_FLOW = 'tap_flow' +TAP_FLOWS = '%ss' % TAP_FLOW + +_attr_map = ( + ('id', 'ID', column_util.LIST_BOTH), + ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY), + ('name', 'Name', column_util.LIST_BOTH), + ('status', 'Status', column_util.LIST_BOTH), + ('source_port', 'source_port', column_util.LIST_BOTH), + ('tap_service_id', 'tap_service_id', column_util.LIST_BOTH), + ('direction', 'Direction', column_util.LIST_BOTH), +) + +_formatters = { + 'vlan_filter': format_columns.ListColumn, +} + + +def _add_updatable_args(parser): + parser.add_argument( + '--name', + help=_('Name of this Tap service.')) + parser.add_argument( + '--description', + help=_('Description for this Tap service.')) + + +class CreateTapFlow(command.ShowOne): + _description = _("Create a tap flow") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + identity_utils.add_project_owner_option_to_parser(parser) + _add_updatable_args(parser) + parser.add_argument( + '--port', + required=True, + metavar="SOURCE_PORT", + help=_('Source port to which the Tap Flow is connected.')) + parser.add_argument( + '--tap-service', + required=True, + metavar="TAP_SERVICE", + help=_('Tap Service to which the Tap Flow belongs.')) + parser.add_argument( + '--direction', + required=True, + metavar="DIRECTION", + choices=['IN', 'OUT', 'BOTH'], + type=lambda s: s.upper(), + help=_('Direction of the Tap flow. Possible options are: ' + 'IN, OUT, BOTH')) + parser.add_argument( + '--vlan-filter', + required=False, + metavar="VLAN_FILTER", + help=_('VLAN Ids to be mirrored in the form of range string.')) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + attrs = {} + if parsed_args.name is not None: + attrs['name'] = str(parsed_args.name) + if parsed_args.description is not None: + attrs['description'] = str(parsed_args.description) + if parsed_args.port is not None: + source_port = client.find_port(parsed_args.port)['id'] + attrs['source_port'] = source_port + if parsed_args.tap_service is not None: + tap_service_id = client.find_tap_service( + parsed_args.tap_service)['id'] + attrs['tap_service_id'] = tap_service_id + if parsed_args.direction is not None: + attrs['direction'] = parsed_args.direction + if parsed_args.vlan_filter is not None: + attrs['vlan_filter'] = parsed_args.vlan_filter + if 'project' in parsed_args and parsed_args.project is not None: + project_id = identity_utils.find_project( + self.app.client_manager.identity, + parsed_args.project, + parsed_args.project_domain, + ).id + attrs['tenant_id'] = project_id + obj = client.create_tap_flow(**attrs) + display_columns, columns = tap_service._get_columns(obj) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data + + +class ListTapFlow(command.Lister): + _description = _("List tap flows that belong to a given tenant") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + identity_utils.add_project_owner_option_to_parser(parser) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + params = {} + if parsed_args.project is not None: + project_id = identity_utils.find_project( + self.app.client_manager.identity, + parsed_args.project, + parsed_args.project_domain, + ).id + params['tenant_id'] = project_id + objs = client.tap_flows(retrieve_all=True, params=params) + headers, columns = column_util.get_column_definitions( + _attr_map, long_listing=True) + return (headers, (osc_utils.get_dict_properties( + s, columns, formatters=_formatters) for s in objs)) + + +class ShowTapFlow(command.ShowOne): + _description = _("Show information of a given tap flow") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_FLOW, + metavar="<%s>" % TAP_FLOW, + help=_("ID or name of tap flow to look up."), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + id = client.find_tap_flow(parsed_args.tap_flow, + ignore_missing=False).id + obj = client.get_tap_flow(id) + display_columns, columns = tap_service._get_columns(obj) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data + + +class DeleteTapFlow(command.Command): + _description = _("Delete a tap flow") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_FLOW, + metavar="<%s>" % TAP_FLOW, + nargs="+", + help=_("ID(s) or name(s) of tap flow to delete."), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + fails = 0 + for id_or_name in parsed_args.tap_flow: + try: + id = client.find_tap_flow(id_or_name, + ignore_missing=False).id + client.delete_tap_flow(id) + LOG.warning("Tap flow %(id)s deleted", {'id': id}) + except Exception as e: + fails += 1 + LOG.error("Failed to delete tap flow with name or ID " + "'%(id_or_name)s': %(e)s", + {'id_or_name': id_or_name, 'e': e}) + if fails > 0: + msg = (_("Failed to delete %(fails)s of %(total)s tap flow.") % + {'fails': fails, 'total': len(parsed_args.tap_flow)}) + raise exceptions.CommandError(msg) + + +class UpdateTapFlow(command.ShowOne): + _description = _("Update a tap flow.") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_FLOW, + metavar="<%s>" % TAP_FLOW, + help=_("ID or name of tap flow to update."), + ) + _add_updatable_args(parser) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + original_t_f = client.find_tap_flow(parsed_args.tap_flow, + ignore_missing=False).id + attrs = {} + if parsed_args.name is not None: + attrs['name'] = str(parsed_args.name) + if parsed_args.description is not None: + attrs['description'] = str(parsed_args.description) + obj = client.update_tap_flow(original_t_f, **attrs) + columns, display_columns = column_util.get_columns(obj, _attr_map) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data diff --git a/neutronclient/osc/v2/taas/tap_mirror.py b/neutronclient/osc/v2/taas/tap_mirror.py new file mode 100644 index 000000000..af6723c09 --- /dev/null +++ b/neutronclient/osc/v2/taas/tap_mirror.py @@ -0,0 +1,222 @@ +# 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 logging + +from osc_lib.cli import identity as identity_utils +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils as osc_utils +from osc_lib.utils import columns as column_util + +from openstackclient.network.v2 import port as osc_port + +from neutronclient._i18n import _ +from neutronclient.osc.v2.taas import tap_service + + +LOG = logging.getLogger(__name__) + +TAP_MIRROR = 'tap_mirror' +TAP_MIRRORS = '%ss' % TAP_MIRROR + +_attr_map = ( + ('id', 'ID', column_util.LIST_BOTH), + ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY), + ('name', 'Name', column_util.LIST_BOTH), + ('port_id', 'Port', column_util.LIST_BOTH), + ('directions', 'Directions', column_util.LIST_LONG_ONLY), + ('remote_ip', 'Remote IP', column_util.LIST_BOTH), + ('mirror_type', 'Mirror Type', column_util.LIST_LONG_ONLY), +) + + +def _get_columns(item): + column_map = {} + hidden_columns = ['location', 'tenant_id'] + return osc_utils.get_osc_show_columns_for_sdk_resource( + item, + column_map, + hidden_columns + ) + + +class CreateTapMirror(command.ShowOne): + _description = _("Create a Tap Mirror") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + identity_utils.add_project_owner_option_to_parser(parser) + tap_service._add_updatable_args(parser) + parser.add_argument( + '--port', + dest='port_id', + required=True, + metavar="PORT", + help=_('Port to which the Tap Mirror is connected.')) + parser.add_argument( + '--directions', + dest='directions', + action=osc_port.JSONKeyValueAction, + required=True, + help=_('A dictionary of direction and tunnel_id. Direction can ' + 'be IN and OUT.')) + parser.add_argument( + '--remote-ip', + dest='remote_ip', + required=True, + help=_('The remote IP of the Tap Mirror, this will be the ' + 'remote end of the GRE or ERSPAN v1 tunnel')) + parser.add_argument( + '--mirror-type', + dest='mirror_type', + required=True, + help=_('The type of the mirroring, it can be gre or erspanv1')) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + attrs = {} + if parsed_args.name is not None: + attrs['name'] = str(parsed_args.name) + if parsed_args.description is not None: + attrs['description'] = str(parsed_args.description) + if parsed_args.port_id is not None: + port_id = client.find_port(parsed_args.port_id)['id'] + attrs['port_id'] = port_id + if parsed_args.directions is not None: + attrs['directions'] = parsed_args.directions + if parsed_args.remote_ip is not None: + attrs['remote_ip'] = parsed_args.remote_ip + if parsed_args.mirror_type is not None: + attrs['mirror_type'] = parsed_args.mirror_type + if 'project' in parsed_args and parsed_args.project is not None: + project_id = identity_utils.find_project( + self.app.client_manager.identity, + parsed_args.project, + parsed_args.project_domain, + ).id + attrs['tenant_id'] = project_id + obj = client.create_tap_mirror(**attrs) + display_columns, columns = tap_service._get_columns(obj) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data + + +class ListTapMirror(command.Lister): + _description = _("List Tap Mirrors that belong to a given tenant") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + identity_utils.add_project_owner_option_to_parser(parser) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + params = {} + if parsed_args.project is not None: + project_id = identity_utils.find_project( + self.app.client_manager.identity, + parsed_args.project, + parsed_args.project_domain, + ).id + params['tenant_id'] = project_id + objs = client.tap_mirrors(retrieve_all=True, params=params) + headers, columns = column_util.get_column_definitions( + _attr_map, long_listing=True) + return (headers, (osc_utils.get_dict_properties( + s, columns) for s in objs)) + + +class ShowTapMirror(command.ShowOne): + _description = _("Show information of a given Tap Mirror") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_MIRROR, + metavar="<%s>" % TAP_MIRROR, + help=_("ID or name of Tap Mirror to look up."), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + id = client.find_tap_mirror(parsed_args.tap_mirror, + ignore_missing=False).id + obj = client.get_tap_mirror(id) + display_columns, columns = tap_service._get_columns(obj) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data + + +class DeleteTapMirror(command.Command): + _description = _("Delete a Tap Mirror") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_MIRROR, + metavar="<%s>" % TAP_MIRROR, + nargs="+", + help=_("ID(s) or name(s) of the Tap Mirror to delete."), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + fails = 0 + for id_or_name in parsed_args.tap_mirror: + try: + id = client.find_tap_mirror(id_or_name, + ignore_missing=False).id + + client.delete_tap_mirror(id) + LOG.warning("Tap Mirror %(id)s deleted", {'id': id}) + except Exception as e: + fails += 1 + LOG.error("Failed to delete Tap Mirror with name or ID " + "'%(id_or_name)s': %(e)s", + {'id_or_name': id_or_name, 'e': e}) + if fails > 0: + msg = (_("Failed to delete %(fails)s of %(total)s Tap Mirror.") % + {'fails': fails, 'total': len(parsed_args.tap_mirror)}) + raise exceptions.CommandError(msg) + + +class UpdateTapMirror(command.ShowOne): + _description = _("Update a Tap Mirror.") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_MIRROR, + metavar="<%s>" % TAP_MIRROR, + help=_("ID or name of the Tap Mirror to update."), + ) + tap_service._add_updatable_args(parser) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + original_t_s = client.find_tap_mirror(parsed_args.tap_mirror, + ignore_missing=False).id + attrs = {} + if parsed_args.name is not None: + attrs['name'] = str(parsed_args.name) + if parsed_args.description is not None: + attrs['description'] = str(parsed_args.description) + obj = client.update_tap_mirror(original_t_s, **attrs) + display_columns, columns = tap_service._get_columns(obj) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data diff --git a/neutronclient/osc/v2/taas/tap_service.py b/neutronclient/osc/v2/taas/tap_service.py new file mode 100644 index 000000000..cd53b6825 --- /dev/null +++ b/neutronclient/osc/v2/taas/tap_service.py @@ -0,0 +1,211 @@ +# All Rights Reserved 2020 +# +# 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 logging + +from osc_lib.cli import identity as identity_utils +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils as osc_utils +from osc_lib.utils import columns as column_util + +from neutronclient._i18n import _ + + +LOG = logging.getLogger(__name__) + +TAP_SERVICE = 'tap_service' +TAP_SERVICES = '%ss' % TAP_SERVICE + +_attr_map = ( + ('id', 'ID', column_util.LIST_BOTH), + ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY), + ('name', 'Name', column_util.LIST_BOTH), + ('port_id', 'Port', column_util.LIST_BOTH), + ('status', 'Status', column_util.LIST_BOTH), +) + + +def _add_updatable_args(parser): + parser.add_argument( + '--name', + help=_('Name of this Tap service.')) + parser.add_argument( + '--description', + help=_('Description for this Tap service.')) + + +def _updatable_args2body(parsed_args, body): + for attribute in ['name', 'description']: + if (hasattr(parsed_args, attribute) and + getattr(parsed_args, attribute) is not None): + body[attribute] = getattr(parsed_args, attribute) + + +def _get_columns(item): + column_map = {} + hidden_columns = ['location', 'tenant_id'] + return osc_utils.get_osc_show_columns_for_sdk_resource( + item, + column_map, + hidden_columns + ) + + +class CreateTapService(command.ShowOne): + _description = _("Create a tap service") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + identity_utils.add_project_owner_option_to_parser(parser) + _add_updatable_args(parser) + parser.add_argument( + '--port', + dest='port_id', + required=True, + metavar="PORT", + help=_('Port to which the Tap service is connected.')) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + attrs = {} + if parsed_args.name is not None: + attrs['name'] = str(parsed_args.name) + if parsed_args.description is not None: + attrs['description'] = str(parsed_args.description) + if parsed_args.port_id is not None: + port_id = client.find_port(parsed_args.port_id)['id'] + attrs['port_id'] = port_id + if 'project' in parsed_args and parsed_args.project is not None: + project_id = identity_utils.find_project( + self.app.client_manager.identity, + parsed_args.project, + parsed_args.project_domain, + ).id + attrs['tenant_id'] = project_id + obj = client.create_tap_service(**attrs) + display_columns, columns = _get_columns(obj) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data + + +class ListTapService(command.Lister): + _description = _("List tap services that belong to a given tenant") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + identity_utils.add_project_owner_option_to_parser(parser) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + params = {} + if parsed_args.project is not None: + project_id = identity_utils.find_project( + self.app.client_manager.identity, + parsed_args.project, + parsed_args.project_domain, + ).id + params['tenant_id'] = project_id + objs = client.tap_services(retrieve_all=True, params=params) + headers, columns = column_util.get_column_definitions( + _attr_map, long_listing=True) + return (headers, (osc_utils.get_dict_properties( + s, columns) for s in objs)) + + +class ShowTapService(command.ShowOne): + _description = _("Show information of a given tap service") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_SERVICE, + metavar="<%s>" % TAP_SERVICE, + help=_("ID or name of tap service to look up."), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + id = client.find_tap_service(parsed_args.tap_service, + ignore_missing=False).id + obj = client.get_tap_service(id) + display_columns, columns = _get_columns(obj) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data + + +class DeleteTapService(command.Command): + _description = _("Delete a tap service") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_SERVICE, + metavar="<%s>" % TAP_SERVICE, + nargs="+", + help=_("ID(s) or name(s) of tap service to delete."), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + fails = 0 + for id_or_name in parsed_args.tap_service: + try: + id = client.find_tap_service(id_or_name, + ignore_missing=False).id + + client.delete_tap_service(id) + LOG.warning("Tap service %(id)s deleted", {'id': id}) + except Exception as e: + fails += 1 + LOG.error("Failed to delete tap service with name or ID " + "'%(id_or_name)s': %(e)s", + {'id_or_name': id_or_name, 'e': e}) + if fails > 0: + msg = (_("Failed to delete %(fails)s of %(total)s tap service.") % + {'fails': fails, 'total': len(parsed_args.tap_service)}) + raise exceptions.CommandError(msg) + + +class UpdateTapService(command.ShowOne): + _description = _("Update a tap service.") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + TAP_SERVICE, + metavar="<%s>" % TAP_SERVICE, + help=_("ID or name of tap service to update."), + ) + _add_updatable_args(parser) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + original_t_s = client.find_tap_service(parsed_args.tap_service, + ignore_missing=False).id + attrs = {} + if parsed_args.name is not None: + attrs['name'] = str(parsed_args.name) + if parsed_args.description is not None: + attrs['description'] = str(parsed_args.description) + obj = client.update_tap_service(original_t_s, **attrs) + display_columns, columns = _get_columns(obj) + data = osc_utils.get_dict_properties(obj, columns) + return display_columns, data diff --git a/neutronclient/tests/unit/osc/v2/taas/__init__.py b/neutronclient/tests/unit/osc/v2/taas/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neutronclient/tests/unit/osc/v2/taas/fakes.py b/neutronclient/tests/unit/osc/v2/taas/fakes.py new file mode 100644 index 000000000..ee32cb1ba --- /dev/null +++ b/neutronclient/tests/unit/osc/v2/taas/fakes.py @@ -0,0 +1,122 @@ +# All Rights Reserved 2020 +# +# 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 copy + +from oslo_utils import uuidutils + + +class FakeTapService: + + @staticmethod + def create_tap_service(attrs=None): + """Create a fake tap service.""" + attrs = attrs or {} + tap_service_attrs = { + 'id': uuidutils.generate_uuid(), + 'tenant_id': uuidutils.generate_uuid(), + 'name': 'test_tap_service' + uuidutils.generate_uuid(), + 'status': 'ACTIVE', + } + tap_service_attrs.update(attrs) + return copy.deepcopy(tap_service_attrs) + + @staticmethod + def create_tap_services(attrs=None, count=1): + """Create multiple fake tap services.""" + + tap_services = [] + for i in range(0, count): + if attrs is None: + attrs = {'id': 'fake_id%d' % i} + elif getattr(attrs, 'id', None) is None: + attrs['id'] = 'fake_id%d' % i + tap_services.append(FakeTapService.create_tap_service( + attrs=attrs)) + + return tap_services + + +class FakeTapFlow: + + @staticmethod + def create_tap_flow(attrs=None): + """Create a fake tap service.""" + attrs = attrs or {} + tap_flow_attrs = { + 'id': uuidutils.generate_uuid(), + 'tenant_id': uuidutils.generate_uuid(), + 'name': 'test_tap_flow' + uuidutils.generate_uuid(), + 'status': 'ACTIVE', + 'direction': 'BOTH', + } + tap_flow_attrs.update(attrs) + return copy.deepcopy(tap_flow_attrs) + + @staticmethod + def create_tap_flows(attrs=None, count=1): + """Create multiple fake tap flows.""" + + tap_flows = [] + for i in range(0, count): + if attrs is None: + attrs = { + 'id': 'fake_id%d' % i, + 'source_port': uuidutils.generate_uuid(), + 'tap_service_id': uuidutils.generate_uuid() + } + elif getattr(attrs, 'id', None) is None: + attrs['id'] = 'fake_id%d' % i + tap_flows.append(FakeTapFlow.create_tap_flow(attrs=attrs)) + + return tap_flows + + +class FakeTapMirror(object): + + @staticmethod + def create_tap_mirror(attrs=None): + """Create a fake tap mirror.""" + attrs = attrs or {} + tap_mirror_attrs = { + 'id': uuidutils.generate_uuid(), + 'tenant_id': uuidutils.generate_uuid(), + 'name': 'test_tap_mirror' + uuidutils.generate_uuid(), + 'port_id': uuidutils.generate_uuid(), + 'directions': 'IN=99', + 'remote_ip': '192.10.10.2', + 'mirror_type': 'gre', + } + tap_mirror_attrs.update(attrs) + return copy.deepcopy(tap_mirror_attrs) + + @staticmethod + def create_tap_mirrors(attrs=None, count=1): + """Create multiple fake tap mirrors.""" + + tap_mirrors = [] + for i in range(0, count): + if attrs is None: + attrs = { + 'id': 'fake_id%d' % i, + 'port_id': uuidutils.generate_uuid(), + 'name': 'test_tap_mirror_%d' % i, + 'directions': 'IN=%d' % 99 + i, + 'remote_ip': '192.10.10.%d' % (i + 3), + } + elif getattr(attrs, 'id', None) is None: + attrs['id'] = 'fake_id%d' % i + tap_mirrors.append(FakeTapMirror.create_tap_mirror(attrs=attrs)) + + return tap_mirrors diff --git a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_flow.py b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_flow.py new file mode 100644 index 000000000..a92e443f3 --- /dev/null +++ b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_flow.py @@ -0,0 +1,283 @@ +# All Rights Reserved 2020 +# +# 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 copy +import operator +from unittest import mock + +from neutronclient.tests.unit.osc.v2 import fakes as test_fakes +from openstack.network.v2 import tap_flow as _tap_flow +from osc_lib import utils as osc_utils +from osc_lib.utils import columns as column_util +from oslo_utils import uuidutils + +from neutronclient.osc.v2.taas import tap_flow as osc_tap_flow +from neutronclient.osc.v2.taas import tap_service as osc_tap_service +from neutronclient.tests.unit.osc.v2.taas import fakes + + +columns_long = tuple(col for col, _, listing_mode in osc_tap_flow._attr_map + if listing_mode in (column_util.LIST_BOTH, + column_util.LIST_LONG_ONLY)) +headers_long = tuple(head for _, head, listing_mode in + osc_tap_flow._attr_map if listing_mode in + (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) +sorted_attr_map = sorted(osc_tap_flow._attr_map, key=operator.itemgetter(1)) +sorted_columns = tuple(col for col, _, _ in sorted_attr_map) +sorted_headers = tuple(head for _, head, _ in sorted_attr_map) + + +def _get_data(attrs, columns=sorted_columns): + return osc_utils.get_dict_properties(attrs, columns) + + +class TestCreateTapFlow(test_fakes.TestNeutronClientOSCV2): + + columns = ( + 'direction', + 'id', + 'name', + 'source_port', + 'status', + 'tap_service_id', + ) + + def setUp(self): + super().setUp() + self.cmd = osc_tap_flow.CreateTapFlow(self.app, self.namespace) + + def test_create_tap_flow(self): + """Test Create Tap Flow.""" + port_id = uuidutils.generate_uuid() + fake_tap_service = fakes.FakeTapService.create_tap_service( + attrs={'port_id': port_id} + ) + port_id = uuidutils.generate_uuid() + fake_tap_flow = fakes.FakeTapFlow.create_tap_flow( + attrs={ + 'source_port': port_id, + 'tap_service_id': fake_tap_service['id'] + } + ) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.create_tap_flow = mock.Mock( + return_value=fake_tap_flow) + self.app.client_manager.network.find_port = mock.Mock( + return_value={'id': port_id}) + self.app.client_manager.network.find_tap_service = mock.Mock( + return_value=fake_tap_service) + arg_list = [ + '--name', fake_tap_flow['name'], + '--port', fake_tap_flow['source_port'], + '--tap-service', fake_tap_flow['tap_service_id'], + '--direction', fake_tap_flow['direction'], + ] + + verify_list = [ + ('name', fake_tap_flow['name']), + ('port', fake_tap_flow['source_port']), + ('tap_service', fake_tap_flow['tap_service_id']), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + with mock.patch.object( + self.app.client_manager.network, + '_find') as nc_find: + nc_find.side_effect = [ + {'id': fake_tap_flow['tap_service_id']} + ] + + columns, data = self.cmd.take_action(parsed_args) + mock_create_t_f = self.app.client_manager.network.create_tap_flow + mock_create_t_f.assert_called_once_with( + **{ + 'name': fake_tap_flow['name'], + 'source_port': fake_tap_flow['source_port'], + 'tap_service_id': fake_tap_flow['tap_service_id'], + 'direction': fake_tap_flow['direction'] + } + ) + self.assertEqual(self.columns, columns) + fake_data = _get_data( + fake_tap_flow, + osc_tap_service._get_columns(fake_tap_flow)[1]) + self.assertItemEqual(fake_data, data) + + +class TestListTapFlow(test_fakes.TestNeutronClientOSCV2): + def setUp(self): + super().setUp() + self.cmd = osc_tap_flow.ListTapFlow(self.app, self.namespace) + + def test_list_tap_flows(self): + """Test List Tap Flow.""" + fake_tap_flows = fakes.FakeTapFlow.create_tap_flows( + attrs={ + 'source_port': uuidutils.generate_uuid(), + 'tap_service_id': uuidutils.generate_uuid(), + }, + count=2) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.tap_flows = mock.Mock( + return_value=fake_tap_flows) + arg_list = [] + verify_list = [] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + + headers, data = self.cmd.take_action(parsed_args) + + self.app.client_manager.network.tap_flows.assert_called_once() + self.assertEqual(headers, list(headers_long)) + self.assertListItemEqual( + list(data), + [_get_data(fake_tap_flow, columns_long) for fake_tap_flow + in fake_tap_flows] + ) + + +class TestDeleteTapFlow(test_fakes.TestNeutronClientOSCV2): + def setUp(self): + super().setUp() + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_flow = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + _tap_flow.TapFlow(id=name_or_id)) + self.cmd = osc_tap_flow.DeleteTapFlow(self.app, self.namespace) + + def test_delete_tap_flow(self): + """Test Delete tap flow.""" + + fake_tap_flow = fakes.FakeTapFlow.create_tap_flow( + attrs={ + 'source_port': uuidutils.generate_uuid(), + 'tap_service_id': uuidutils.generate_uuid(), + } + ) + self.app.client_manager.network.delete_tap_flow = mock.Mock() + + arg_list = [ + fake_tap_flow['id'], + ] + verify_list = [ + (osc_tap_flow.TAP_FLOW, [fake_tap_flow['id']]), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + + result = self.cmd.take_action(parsed_args) + + mock_delete_tap_flow = self.app.client_manager.network.delete_tap_flow + mock_delete_tap_flow.assert_called_once_with(fake_tap_flow['id']) + self.assertIsNone(result) + + +class TestShowTapFlow(test_fakes.TestNeutronClientOSCV2): + columns = ( + 'direction', + 'id', + 'name', + 'source_port', + 'status', + 'tap_service_id' + ) + + def setUp(self): + super().setUp() + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_flow = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + _tap_flow.TapFlow(id=name_or_id)) + self.cmd = osc_tap_flow.ShowTapFlow(self.app, self.namespace) + + def test_show_tap_flow(self): + """Test Show tap flow.""" + fake_tap_flow = fakes.FakeTapFlow.create_tap_flow( + attrs={ + 'source_port': uuidutils.generate_uuid(), + 'tap_service_id': uuidutils.generate_uuid(), + } + ) + self.app.client_manager.network.get_tap_flow = mock.Mock( + return_value=fake_tap_flow) + arg_list = [ + fake_tap_flow['id'], + ] + verify_list = [ + (osc_tap_flow.TAP_FLOW, fake_tap_flow['id']), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + + headers, data = self.cmd.take_action(parsed_args) + + self.app.client_manager.network.get_tap_flow.assert_called_once_with( + fake_tap_flow['id']) + self.assertEqual(self.columns, headers) + fake_data = _get_data( + fake_tap_flow, + osc_tap_service._get_columns(fake_tap_flow)[1]) + self.assertItemEqual(fake_data, data) + + +class TestUpdateTapFlow(test_fakes.TestNeutronClientOSCV2): + + _new_name = 'new_name' + + columns = ( + 'Direction', + 'ID', + 'Name', + 'Status', + 'Tenant', + 'source_port', + 'tap_service_id', + ) + + def setUp(self): + super().setUp() + self.cmd = osc_tap_flow.UpdateTapFlow(self.app, self.namespace) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_flow = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + _tap_flow.TapFlow(id=name_or_id)) + + def test_update_tap_flow(self): + """Test update tap service""" + fake_tap_flow = fakes.FakeTapFlow.create_tap_flow( + attrs={ + 'source_port': uuidutils.generate_uuid(), + 'tap_service_id': uuidutils.generate_uuid(), + } + ) + new_tap_flow = copy.deepcopy(fake_tap_flow) + new_tap_flow['name'] = self._new_name + + self.app.client_manager.network.update_tap_flow = mock.Mock( + return_value=new_tap_flow) + + arg_list = [ + fake_tap_flow['id'], + '--name', self._new_name, + ] + verify_list = [('name', self._new_name)] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + columns, data = self.cmd.take_action(parsed_args) + attrs = {'name': self._new_name} + + mock_update_t_f = self.app.client_manager.network.update_tap_flow + mock_update_t_f.assert_called_once_with(new_tap_flow['id'], **attrs) + self.assertEqual(self.columns, columns) + self.assertItemEqual(_get_data(new_tap_flow), data) diff --git a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_mirror.py b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_mirror.py new file mode 100644 index 000000000..88314842b --- /dev/null +++ b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_mirror.py @@ -0,0 +1,267 @@ +# 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 copy +import operator +from unittest import mock + +from neutronclient.tests.unit.osc.v2 import fakes as test_fakes +from openstack.network.v2 import tap_mirror +from osc_lib import utils as osc_utils +from osc_lib.utils import columns as column_util +from oslo_utils import uuidutils + +from neutronclient.osc.v2.taas import tap_mirror as osc_tap_mirror +from neutronclient.tests.unit.osc.v2.taas import fakes + + +columns_long = tuple(col for col, _, listing_mode in osc_tap_mirror._attr_map + if listing_mode in (column_util.LIST_BOTH, + column_util.LIST_LONG_ONLY)) +headers_long = tuple(head for _, head, listing_mode in + osc_tap_mirror._attr_map if listing_mode in + (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) +sorted_attr_map = sorted(osc_tap_mirror._attr_map, key=operator.itemgetter(1)) +sorted_columns = tuple(col for col, _, _ in sorted_attr_map) +sorted_headers = tuple(head for _, head, _ in sorted_attr_map) + + +def _get_data(attrs, columns=sorted_columns): + return osc_utils.get_dict_properties(attrs, columns) + + +class TestCreateTapMirror(test_fakes.TestNeutronClientOSCV2): + + columns = ( + 'directions', + 'id', + 'mirror_type', + 'name', + 'port_id', + 'remote_ip', + ) + + def setUp(self): + super().setUp() + self.cmd = osc_tap_mirror.CreateTapMirror(self.app, self.namespace) + + def test_create_tap_mirror(self): + port_id = uuidutils.generate_uuid() + fake_tap_mirror = fakes.FakeTapMirror.create_tap_mirror( + attrs={'port_id': port_id} + ) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.create_tap_mirror = mock.Mock( + return_value=fake_tap_mirror) + self.app.client_manager.network.find_port = mock.Mock( + return_value={'id': port_id}) + self.app.client_manager.network.find_tap_mirror = mock.Mock( + side_effect=lambda _, name_or_id: {'id': name_or_id}) + arg_list = [ + '--name', fake_tap_mirror['name'], + '--port', fake_tap_mirror['port_id'], + '--directions', fake_tap_mirror['directions'], + '--remote-ip', fake_tap_mirror['remote_ip'], + '--mirror-type', fake_tap_mirror['mirror_type'], + ] + + verify_directions = fake_tap_mirror['directions'].split('=') + verify_directions_dict = {verify_directions[0]: verify_directions[1]} + + verify_list = [ + ('name', fake_tap_mirror['name']), + ('port_id', fake_tap_mirror['port_id']), + ('directions', verify_directions_dict), + ('remote_ip', fake_tap_mirror['remote_ip']), + ('mirror_type', fake_tap_mirror['mirror_type']), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + self.app.client_manager.network.find_tap_mirror = mock.Mock( + return_value=fake_tap_mirror) + + columns, data = self.cmd.take_action(parsed_args) + create_tap_m_mock = self.app.client_manager.network.create_tap_mirror + create_tap_m_mock.assert_called_once_with( + **{'name': fake_tap_mirror['name'], + 'port_id': fake_tap_mirror['port_id'], + 'directions': verify_directions_dict, + 'remote_ip': fake_tap_mirror['remote_ip'], + 'mirror_type': fake_tap_mirror['mirror_type']}) + self.assertEqual(self.columns, columns) + fake_data = _get_data( + fake_tap_mirror, + osc_tap_mirror._get_columns(fake_tap_mirror)[1]) + self.assertEqual(fake_data, data) + + +class TestListTapMirror(test_fakes.TestNeutronClientOSCV2): + + def setUp(self): + super().setUp() + self.cmd = osc_tap_mirror.ListTapMirror(self.app, self.namespace) + + def test_list_tap_mirror(self): + """Test List Tap Mirror.""" + fake_tap_mirrors = fakes.FakeTapMirror.create_tap_mirrors( + attrs={'port_id': uuidutils.generate_uuid()}, + count=4) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.tap_mirrors = mock.Mock( + return_value=fake_tap_mirrors) + + arg_list = [] + verify_list = [] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + + headers, data = self.cmd.take_action(parsed_args) + + self.app.client_manager.network.tap_mirrors.assert_called_once() + self.assertEqual(headers, list(headers_long)) + self.assertListItemEqual( + list(data), + [_get_data(fake_tap_mirror, columns_long) for fake_tap_mirror + in fake_tap_mirrors] + ) + + +class TestDeleteTapMirror(test_fakes.TestNeutronClientOSCV2): + + def setUp(self): + super().setUp() + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_mirror = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + tap_mirror.TapMirror(id=name_or_id)) + self.cmd = osc_tap_mirror.DeleteTapMirror(self.app, self.namespace) + + def test_delete_tap_mirror(self): + """Test Delete Tap Mirror.""" + + fake_tap_mirror = fakes.FakeTapMirror.create_tap_mirror( + attrs={'port_id': uuidutils.generate_uuid()} + ) + self.app.client_manager.network.delete_tap_mirror = mock.Mock() + + arg_list = [ + fake_tap_mirror['id'], + ] + verify_list = [ + (osc_tap_mirror.TAP_MIRROR, [fake_tap_mirror['id']]), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + result = self.cmd.take_action(parsed_args) + + mock_delete_tap_m = self.app.client_manager.network.delete_tap_mirror + mock_delete_tap_m.assert_called_once_with(fake_tap_mirror['id']) + self.assertIsNone(result) + + +class TestShowTapMirror(test_fakes.TestNeutronClientOSCV2): + + columns = ( + 'directions', + 'id', + 'mirror_type', + 'name', + 'port_id', + 'remote_ip', + ) + + def setUp(self): + super().setUp() + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_mirror = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + tap_mirror.TapMirror(id=name_or_id)) + self.cmd = osc_tap_mirror.ShowTapMirror(self.app, self.namespace) + + def test_show_tap_mirror(self): + """Test Show Tap Mirror.""" + + fake_tap_mirror = fakes.FakeTapMirror.create_tap_mirror( + attrs={'port_id': uuidutils.generate_uuid()} + ) + self.app.client_manager.network.get_tap_mirror = mock.Mock( + return_value=fake_tap_mirror) + arg_list = [ + fake_tap_mirror['id'], + ] + verify_list = [ + (osc_tap_mirror.TAP_MIRROR, fake_tap_mirror['id']), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + + headers, data = self.cmd.take_action(parsed_args) + + mock_get_tap_m = self.app.client_manager.network.get_tap_mirror + mock_get_tap_m.assert_called_once_with( + fake_tap_mirror['id']) + self.assertEqual(self.columns, headers) + fake_data = _get_data( + fake_tap_mirror, + osc_tap_mirror._get_columns(fake_tap_mirror)[1]) + self.assertItemEqual(fake_data, data) + + +class TestUpdateTapMirror(test_fakes.TestNeutronClientOSCV2): + + _new_name = 'new_name' + columns = ( + 'directions', + 'id', + 'mirror_type', + 'name', + 'port_id', + 'remote_ip', + ) + + def setUp(self): + super().setUp() + self.cmd = osc_tap_mirror.UpdateTapMirror(self.app, self.namespace) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_mirror = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + tap_mirror.TapMirror(id=name_or_id)) + + def test_update_tap_mirror(self): + """Test update Tap Mirror""" + fake_tap_mirror = fakes.FakeTapMirror.create_tap_mirror( + attrs={'port_id': uuidutils.generate_uuid()} + ) + new_tap_mirror = copy.deepcopy(fake_tap_mirror) + new_tap_mirror['name'] = self._new_name + + self.app.client_manager.network.update_tap_mirror = mock.Mock( + return_value=new_tap_mirror) + + arg_list = [ + fake_tap_mirror['id'], + '--name', self._new_name, + ] + verify_list = [('name', self._new_name)] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + columns, data = self.cmd.take_action(parsed_args) + attrs = {'name': self._new_name} + + mock_update_tap_m = self.app.client_manager.network.update_tap_mirror + mock_update_tap_m.assert_called_once_with( + fake_tap_mirror['id'], **attrs) + self.assertEqual(self.columns, columns) + fake_data = _get_data( + new_tap_mirror, + osc_tap_mirror._get_columns(new_tap_mirror)[1]) + self.assertItemEqual(fake_data, data) diff --git a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_service.py b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_service.py new file mode 100644 index 000000000..0b753f803 --- /dev/null +++ b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_service.py @@ -0,0 +1,250 @@ +# All Rights Reserved 2020 +# +# 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 copy +import operator +from unittest import mock + +from neutronclient.tests.unit.osc.v2 import fakes as test_fakes +from openstack.network.v2 import tap_service +from osc_lib import utils as osc_utils +from osc_lib.utils import columns as column_util +from oslo_utils import uuidutils + +from neutronclient.osc.v2.taas import tap_service as osc_tap_service +from neutronclient.tests.unit.osc.v2.taas import fakes + + +columns_long = tuple(col for col, _, listing_mode in osc_tap_service._attr_map + if listing_mode in (column_util.LIST_BOTH, + column_util.LIST_LONG_ONLY)) +headers_long = tuple(head for _, head, listing_mode in + osc_tap_service._attr_map if listing_mode in + (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) +sorted_attr_map = sorted(osc_tap_service._attr_map, key=operator.itemgetter(1)) +sorted_columns = tuple(col for col, _, _ in sorted_attr_map) +sorted_headers = tuple(head for _, head, _ in sorted_attr_map) + + +def _get_data(attrs, columns=sorted_columns): + return osc_utils.get_dict_properties(attrs, columns) + + +class TestCreateTapService(test_fakes.TestNeutronClientOSCV2): + + columns = ( + 'id', + 'name', + 'port_id', + 'status', + ) + + def setUp(self): + super().setUp() + self.cmd = osc_tap_service.CreateTapService(self.app, self.namespace) + + def test_create_tap_service(self): + """Test Create Tap Service.""" + port_id = uuidutils.generate_uuid() + fake_tap_service = fakes.FakeTapService.create_tap_service( + attrs={'port_id': port_id} + ) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.create_tap_service = mock.Mock( + return_value=fake_tap_service) + self.app.client_manager.network.find_port = mock.Mock( + return_value={'id': port_id}) + self.app.client_manager.network.find_tap_service = mock.Mock( + side_effect=lambda _, name_or_id: {'id': name_or_id}) + arg_list = [ + '--name', fake_tap_service['name'], + '--port', fake_tap_service['port_id'], + ] + + verify_list = [ + ('name', fake_tap_service['name']), + ('port_id', fake_tap_service['port_id']), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + self.app.client_manager.network.find_tap_service = mock.Mock( + return_value=fake_tap_service) + + columns, data = self.cmd.take_action(parsed_args) + create_tap_s_mock = self.app.client_manager.network.create_tap_service + create_tap_s_mock.assert_called_once_with( + **{'name': fake_tap_service['name'], + 'port_id': fake_tap_service['port_id']}) + self.assertEqual(self.columns, columns) + fake_data = _get_data( + fake_tap_service, + osc_tap_service._get_columns(fake_tap_service)[1]) + self.assertEqual(fake_data, data) + + +class TestListTapService(test_fakes.TestNeutronClientOSCV2): + def setUp(self): + super().setUp() + self.cmd = osc_tap_service.ListTapService(self.app, self.namespace) + + def test_list_tap_service(self): + """Test List Tap Service.""" + fake_tap_services = fakes.FakeTapService.create_tap_services( + attrs={'port_id': uuidutils.generate_uuid()}, + count=4) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.tap_services = mock.Mock( + return_value=fake_tap_services) + + arg_list = [] + verify_list = [] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + + headers, data = self.cmd.take_action(parsed_args) + + self.app.client_manager.network.tap_services.assert_called_once() + self.assertEqual(headers, list(headers_long)) + self.assertListItemEqual( + list(data), + [_get_data(fake_tap_service, columns_long) for fake_tap_service + in fake_tap_services] + ) + + +class TestDeleteTapService(test_fakes.TestNeutronClientOSCV2): + def setUp(self): + super().setUp() + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_service = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + tap_service.TapService(id=name_or_id)) + self.cmd = osc_tap_service.DeleteTapService(self.app, self.namespace) + + def test_delete_tap_service(self): + """Test Delete tap service.""" + + fake_tap_service = fakes.FakeTapService.create_tap_service( + attrs={'port_id': uuidutils.generate_uuid()} + ) + self.app.client_manager.network.delete_tap_service = mock.Mock() + + arg_list = [ + fake_tap_service['id'], + ] + verify_list = [ + (osc_tap_service.TAP_SERVICE, [fake_tap_service['id']]), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + result = self.cmd.take_action(parsed_args) + + mock_delete_tap_s = self.app.client_manager.network.delete_tap_service + mock_delete_tap_s.assert_called_once_with(fake_tap_service['id']) + self.assertIsNone(result) + + +class TestShowTapService(test_fakes.TestNeutronClientOSCV2): + columns = ( + 'id', + 'name', + 'port_id', + 'status', + ) + + def setUp(self): + super().setUp() + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_service = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + tap_service.TapService(id=name_or_id)) + self.cmd = osc_tap_service.ShowTapService(self.app, self.namespace) + + def test_show_tap_service(self): + """Test Show tap service.""" + + fake_tap_service = fakes.FakeTapService.create_tap_service( + attrs={'port_id': uuidutils.generate_uuid()} + ) + self.app.client_manager.network.get_tap_service = mock.Mock( + return_value=fake_tap_service) + arg_list = [ + fake_tap_service['id'], + ] + verify_list = [ + (osc_tap_service.TAP_SERVICE, fake_tap_service['id']), + ] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + + headers, data = self.cmd.take_action(parsed_args) + + mock_get_tap_s = self.app.client_manager.network.get_tap_service + mock_get_tap_s.assert_called_once_with( + fake_tap_service['id']) + self.assertEqual(self.columns, headers) + fake_data = _get_data( + fake_tap_service, + osc_tap_service._get_columns(fake_tap_service)[1]) + self.assertItemEqual(fake_data, data) + + +class TestUpdateTapService(test_fakes.TestNeutronClientOSCV2): + + _new_name = 'new_name' + + columns = ( + 'id', + 'name', + 'port_id', + 'status', + ) + + def setUp(self): + super().setUp() + self.cmd = osc_tap_service.UpdateTapService(self.app, self.namespace) + self.app.client_manager.network = mock.Mock() + self.app.client_manager.network.find_tap_service = mock.Mock( + side_effect=lambda name_or_id, ignore_missing: + tap_service.TapService(id=name_or_id)) + + def test_update_tap_service(self): + """Test update tap service""" + fake_tap_service = fakes.FakeTapService.create_tap_service( + attrs={'port_id': uuidutils.generate_uuid()} + ) + new_tap_service = copy.deepcopy(fake_tap_service) + new_tap_service['name'] = self._new_name + + self.app.client_manager.network.update_tap_service = mock.Mock( + return_value=new_tap_service) + + arg_list = [ + fake_tap_service['id'], + '--name', self._new_name, + ] + verify_list = [('name', self._new_name)] + + parsed_args = self.check_parser(self.cmd, arg_list, verify_list) + columns, data = self.cmd.take_action(parsed_args) + attrs = {'name': self._new_name} + + mock_update_tap_s = self.app.client_manager.network.update_tap_service + mock_update_tap_s.assert_called_once_with( + fake_tap_service['id'], **attrs) + self.assertEqual(self.columns, columns) + fake_data = _get_data( + new_tap_service, + osc_tap_service._get_columns(new_tap_service)[1]) + self.assertItemEqual(fake_data, data) diff --git a/setup.cfg b/setup.cfg index 3005e895b..77c3e069a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -161,3 +161,19 @@ openstack.neutronclient.v2 = vpn_ipsec_site_connection_show = neutronclient.osc.v2.vpnaas.ipsec_site_connection:ShowIPsecSiteConnection network_onboard_subnets = neutronclient.osc.v2.subnet_onboard.subnet_onboard:NetworkOnboardSubnets + + tap_flow_create = neutronclient.osc.v2.taas.tap_flow:CreateTapFlow + tap_flow_delete = neutronclient.osc.v2.taas.tap_flow:DeleteTapFlow + tap_flow_list = neutronclient.osc.v2.taas.tap_flow:ListTapFlow + tap_flow_show = neutronclient.osc.v2.taas.tap_flow:ShowTapFlow + tap_flow_update = neutronclient.osc.v2.taas.tap_flow:UpdateTapFlow + tap_mirror_create = neutronclient.osc.v2.taas.tap_mirror:CreateTapMirror + tap_mirror_delete = neutronclient.osc.v2.taas.tap_mirror:DeleteTapMirror + tap_mirror_list = neutronclient.osc.v2.taas.tap_mirror:ListTapMirror + tap_mirror_show = neutronclient.osc.v2.taas.tap_mirror:ShowTapMirror + tap_mirror_update = neutronclient.osc.v2.taas.tap_mirror:UpdateTapMirror + tap_service_create = neutronclient.osc.v2.taas.tap_service:CreateTapService + tap_service_delete = neutronclient.osc.v2.taas.tap_service:DeleteTapService + tap_service_list = neutronclient.osc.v2.taas.tap_service:ListTapService + tap_service_show = neutronclient.osc.v2.taas.tap_service:ShowTapService + tap_service_update = neutronclient.osc.v2.taas.tap_service:UpdateTapService From 01d0553ca4895742533234322252e59df9f4512d Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Fri, 31 Oct 2025 12:06:40 +0000 Subject: [PATCH 141/149] reno: Update master for unmaintained/2024.1 Update the 2024.1 release notes configuration to build from unmaintained/2024.1. Change-Id: Ic2592d22b36b22f3cf48a21d81bfb0b41b31ae86 Signed-off-by: OpenStack Release Bot Generated-By: openstack/project-config:roles/copy-release-tools-scripts/files/release-tools/change_reno_branch_to_unmaintained.sh --- releasenotes/source/2024.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/source/2024.1.rst b/releasenotes/source/2024.1.rst index 4977a4f1a..6896656be 100644 --- a/releasenotes/source/2024.1.rst +++ b/releasenotes/source/2024.1.rst @@ -3,4 +3,4 @@ =========================== .. release-notes:: - :branch: stable/2024.1 + :branch: unmaintained/2024.1 From a991ac87c7fe4d7fd73a3d0370f346139c539086 Mon Sep 17 00:00:00 2001 From: Miro Tomaska Date: Thu, 6 Nov 2025 21:39:01 +0000 Subject: [PATCH 142/149] Revert "Add Tap-as-a-Service client code" This reverts commit 01ffc4684a4a8b443bd2c5d66f3335af7fdaddc4. Reason for revert: In the last PTG we decided that the best location for the stadium projects osc client code would be the openstackclient repo. A patch was proposed for tapaas, see depends-on link below. Other projects will follow Change-Id: Iaad2080f0ef552a0c0a00635bea48130cfc327a4 Depends-On: https://review.opendev.org/c/openstack/python-openstackclient/+/963445 Signed-off-by: Miro Tomaska --- neutronclient/osc/v2/taas/__init__.py | 0 neutronclient/osc/v2/taas/tap_flow.py | 225 -------------- neutronclient/osc/v2/taas/tap_mirror.py | 222 -------------- neutronclient/osc/v2/taas/tap_service.py | 211 ------------- .../tests/unit/osc/v2/taas/__init__.py | 0 neutronclient/tests/unit/osc/v2/taas/fakes.py | 122 -------- .../unit/osc/v2/taas/test_osc_tap_flow.py | 283 ------------------ .../unit/osc/v2/taas/test_osc_tap_mirror.py | 267 ----------------- .../unit/osc/v2/taas/test_osc_tap_service.py | 250 ---------------- setup.cfg | 16 - 10 files changed, 1596 deletions(-) delete mode 100644 neutronclient/osc/v2/taas/__init__.py delete mode 100644 neutronclient/osc/v2/taas/tap_flow.py delete mode 100644 neutronclient/osc/v2/taas/tap_mirror.py delete mode 100644 neutronclient/osc/v2/taas/tap_service.py delete mode 100644 neutronclient/tests/unit/osc/v2/taas/__init__.py delete mode 100644 neutronclient/tests/unit/osc/v2/taas/fakes.py delete mode 100644 neutronclient/tests/unit/osc/v2/taas/test_osc_tap_flow.py delete mode 100644 neutronclient/tests/unit/osc/v2/taas/test_osc_tap_mirror.py delete mode 100644 neutronclient/tests/unit/osc/v2/taas/test_osc_tap_service.py diff --git a/neutronclient/osc/v2/taas/__init__.py b/neutronclient/osc/v2/taas/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/osc/v2/taas/tap_flow.py b/neutronclient/osc/v2/taas/tap_flow.py deleted file mode 100644 index 428d059e0..000000000 --- a/neutronclient/osc/v2/taas/tap_flow.py +++ /dev/null @@ -1,225 +0,0 @@ -# All Rights Reserved 2020 -# -# 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 logging - -from osc_lib.cli import format_columns -from osc_lib.cli import identity as identity_utils -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.osc.v2.taas import tap_service - -LOG = logging.getLogger(__name__) - -TAP_FLOW = 'tap_flow' -TAP_FLOWS = '%ss' % TAP_FLOW - -_attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY), - ('name', 'Name', column_util.LIST_BOTH), - ('status', 'Status', column_util.LIST_BOTH), - ('source_port', 'source_port', column_util.LIST_BOTH), - ('tap_service_id', 'tap_service_id', column_util.LIST_BOTH), - ('direction', 'Direction', column_util.LIST_BOTH), -) - -_formatters = { - 'vlan_filter': format_columns.ListColumn, -} - - -def _add_updatable_args(parser): - parser.add_argument( - '--name', - help=_('Name of this Tap service.')) - parser.add_argument( - '--description', - help=_('Description for this Tap service.')) - - -class CreateTapFlow(command.ShowOne): - _description = _("Create a tap flow") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - identity_utils.add_project_owner_option_to_parser(parser) - _add_updatable_args(parser) - parser.add_argument( - '--port', - required=True, - metavar="SOURCE_PORT", - help=_('Source port to which the Tap Flow is connected.')) - parser.add_argument( - '--tap-service', - required=True, - metavar="TAP_SERVICE", - help=_('Tap Service to which the Tap Flow belongs.')) - parser.add_argument( - '--direction', - required=True, - metavar="DIRECTION", - choices=['IN', 'OUT', 'BOTH'], - type=lambda s: s.upper(), - help=_('Direction of the Tap flow. Possible options are: ' - 'IN, OUT, BOTH')) - parser.add_argument( - '--vlan-filter', - required=False, - metavar="VLAN_FILTER", - help=_('VLAN Ids to be mirrored in the form of range string.')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = {} - if parsed_args.name is not None: - attrs['name'] = str(parsed_args.name) - if parsed_args.description is not None: - attrs['description'] = str(parsed_args.description) - if parsed_args.port is not None: - source_port = client.find_port(parsed_args.port)['id'] - attrs['source_port'] = source_port - if parsed_args.tap_service is not None: - tap_service_id = client.find_tap_service( - parsed_args.tap_service)['id'] - attrs['tap_service_id'] = tap_service_id - if parsed_args.direction is not None: - attrs['direction'] = parsed_args.direction - if parsed_args.vlan_filter is not None: - attrs['vlan_filter'] = parsed_args.vlan_filter - if 'project' in parsed_args and parsed_args.project is not None: - project_id = identity_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - attrs['tenant_id'] = project_id - obj = client.create_tap_flow(**attrs) - display_columns, columns = tap_service._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data - - -class ListTapFlow(command.Lister): - _description = _("List tap flows that belong to a given tenant") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - identity_utils.add_project_owner_option_to_parser(parser) - - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - params = {} - if parsed_args.project is not None: - project_id = identity_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - params['tenant_id'] = project_id - objs = client.tap_flows(retrieve_all=True, params=params) - headers, columns = column_util.get_column_definitions( - _attr_map, long_listing=True) - return (headers, (osc_utils.get_dict_properties( - s, columns, formatters=_formatters) for s in objs)) - - -class ShowTapFlow(command.ShowOne): - _description = _("Show information of a given tap flow") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_FLOW, - metavar="<%s>" % TAP_FLOW, - help=_("ID or name of tap flow to look up."), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - id = client.find_tap_flow(parsed_args.tap_flow, - ignore_missing=False).id - obj = client.get_tap_flow(id) - display_columns, columns = tap_service._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data - - -class DeleteTapFlow(command.Command): - _description = _("Delete a tap flow") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_FLOW, - metavar="<%s>" % TAP_FLOW, - nargs="+", - help=_("ID(s) or name(s) of tap flow to delete."), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fails = 0 - for id_or_name in parsed_args.tap_flow: - try: - id = client.find_tap_flow(id_or_name, - ignore_missing=False).id - client.delete_tap_flow(id) - LOG.warning("Tap flow %(id)s deleted", {'id': id}) - except Exception as e: - fails += 1 - LOG.error("Failed to delete tap flow with name or ID " - "'%(id_or_name)s': %(e)s", - {'id_or_name': id_or_name, 'e': e}) - if fails > 0: - msg = (_("Failed to delete %(fails)s of %(total)s tap flow.") % - {'fails': fails, 'total': len(parsed_args.tap_flow)}) - raise exceptions.CommandError(msg) - - -class UpdateTapFlow(command.ShowOne): - _description = _("Update a tap flow.") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_FLOW, - metavar="<%s>" % TAP_FLOW, - help=_("ID or name of tap flow to update."), - ) - _add_updatable_args(parser) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - original_t_f = client.find_tap_flow(parsed_args.tap_flow, - ignore_missing=False).id - attrs = {} - if parsed_args.name is not None: - attrs['name'] = str(parsed_args.name) - if parsed_args.description is not None: - attrs['description'] = str(parsed_args.description) - obj = client.update_tap_flow(original_t_f, **attrs) - columns, display_columns = column_util.get_columns(obj, _attr_map) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data diff --git a/neutronclient/osc/v2/taas/tap_mirror.py b/neutronclient/osc/v2/taas/tap_mirror.py deleted file mode 100644 index af6723c09..000000000 --- a/neutronclient/osc/v2/taas/tap_mirror.py +++ /dev/null @@ -1,222 +0,0 @@ -# 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 logging - -from osc_lib.cli import identity as identity_utils -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util - -from openstackclient.network.v2 import port as osc_port - -from neutronclient._i18n import _ -from neutronclient.osc.v2.taas import tap_service - - -LOG = logging.getLogger(__name__) - -TAP_MIRROR = 'tap_mirror' -TAP_MIRRORS = '%ss' % TAP_MIRROR - -_attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY), - ('name', 'Name', column_util.LIST_BOTH), - ('port_id', 'Port', column_util.LIST_BOTH), - ('directions', 'Directions', column_util.LIST_LONG_ONLY), - ('remote_ip', 'Remote IP', column_util.LIST_BOTH), - ('mirror_type', 'Mirror Type', column_util.LIST_LONG_ONLY), -) - - -def _get_columns(item): - column_map = {} - hidden_columns = ['location', 'tenant_id'] - return osc_utils.get_osc_show_columns_for_sdk_resource( - item, - column_map, - hidden_columns - ) - - -class CreateTapMirror(command.ShowOne): - _description = _("Create a Tap Mirror") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - identity_utils.add_project_owner_option_to_parser(parser) - tap_service._add_updatable_args(parser) - parser.add_argument( - '--port', - dest='port_id', - required=True, - metavar="PORT", - help=_('Port to which the Tap Mirror is connected.')) - parser.add_argument( - '--directions', - dest='directions', - action=osc_port.JSONKeyValueAction, - required=True, - help=_('A dictionary of direction and tunnel_id. Direction can ' - 'be IN and OUT.')) - parser.add_argument( - '--remote-ip', - dest='remote_ip', - required=True, - help=_('The remote IP of the Tap Mirror, this will be the ' - 'remote end of the GRE or ERSPAN v1 tunnel')) - parser.add_argument( - '--mirror-type', - dest='mirror_type', - required=True, - help=_('The type of the mirroring, it can be gre or erspanv1')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = {} - if parsed_args.name is not None: - attrs['name'] = str(parsed_args.name) - if parsed_args.description is not None: - attrs['description'] = str(parsed_args.description) - if parsed_args.port_id is not None: - port_id = client.find_port(parsed_args.port_id)['id'] - attrs['port_id'] = port_id - if parsed_args.directions is not None: - attrs['directions'] = parsed_args.directions - if parsed_args.remote_ip is not None: - attrs['remote_ip'] = parsed_args.remote_ip - if parsed_args.mirror_type is not None: - attrs['mirror_type'] = parsed_args.mirror_type - if 'project' in parsed_args and parsed_args.project is not None: - project_id = identity_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - attrs['tenant_id'] = project_id - obj = client.create_tap_mirror(**attrs) - display_columns, columns = tap_service._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data - - -class ListTapMirror(command.Lister): - _description = _("List Tap Mirrors that belong to a given tenant") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - identity_utils.add_project_owner_option_to_parser(parser) - - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - params = {} - if parsed_args.project is not None: - project_id = identity_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - params['tenant_id'] = project_id - objs = client.tap_mirrors(retrieve_all=True, params=params) - headers, columns = column_util.get_column_definitions( - _attr_map, long_listing=True) - return (headers, (osc_utils.get_dict_properties( - s, columns) for s in objs)) - - -class ShowTapMirror(command.ShowOne): - _description = _("Show information of a given Tap Mirror") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_MIRROR, - metavar="<%s>" % TAP_MIRROR, - help=_("ID or name of Tap Mirror to look up."), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - id = client.find_tap_mirror(parsed_args.tap_mirror, - ignore_missing=False).id - obj = client.get_tap_mirror(id) - display_columns, columns = tap_service._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data - - -class DeleteTapMirror(command.Command): - _description = _("Delete a Tap Mirror") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_MIRROR, - metavar="<%s>" % TAP_MIRROR, - nargs="+", - help=_("ID(s) or name(s) of the Tap Mirror to delete."), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fails = 0 - for id_or_name in parsed_args.tap_mirror: - try: - id = client.find_tap_mirror(id_or_name, - ignore_missing=False).id - - client.delete_tap_mirror(id) - LOG.warning("Tap Mirror %(id)s deleted", {'id': id}) - except Exception as e: - fails += 1 - LOG.error("Failed to delete Tap Mirror with name or ID " - "'%(id_or_name)s': %(e)s", - {'id_or_name': id_or_name, 'e': e}) - if fails > 0: - msg = (_("Failed to delete %(fails)s of %(total)s Tap Mirror.") % - {'fails': fails, 'total': len(parsed_args.tap_mirror)}) - raise exceptions.CommandError(msg) - - -class UpdateTapMirror(command.ShowOne): - _description = _("Update a Tap Mirror.") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_MIRROR, - metavar="<%s>" % TAP_MIRROR, - help=_("ID or name of the Tap Mirror to update."), - ) - tap_service._add_updatable_args(parser) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - original_t_s = client.find_tap_mirror(parsed_args.tap_mirror, - ignore_missing=False).id - attrs = {} - if parsed_args.name is not None: - attrs['name'] = str(parsed_args.name) - if parsed_args.description is not None: - attrs['description'] = str(parsed_args.description) - obj = client.update_tap_mirror(original_t_s, **attrs) - display_columns, columns = tap_service._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data diff --git a/neutronclient/osc/v2/taas/tap_service.py b/neutronclient/osc/v2/taas/tap_service.py deleted file mode 100644 index cd53b6825..000000000 --- a/neutronclient/osc/v2/taas/tap_service.py +++ /dev/null @@ -1,211 +0,0 @@ -# All Rights Reserved 2020 -# -# 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 logging - -from osc_lib.cli import identity as identity_utils -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ - - -LOG = logging.getLogger(__name__) - -TAP_SERVICE = 'tap_service' -TAP_SERVICES = '%ss' % TAP_SERVICE - -_attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY), - ('name', 'Name', column_util.LIST_BOTH), - ('port_id', 'Port', column_util.LIST_BOTH), - ('status', 'Status', column_util.LIST_BOTH), -) - - -def _add_updatable_args(parser): - parser.add_argument( - '--name', - help=_('Name of this Tap service.')) - parser.add_argument( - '--description', - help=_('Description for this Tap service.')) - - -def _updatable_args2body(parsed_args, body): - for attribute in ['name', 'description']: - if (hasattr(parsed_args, attribute) and - getattr(parsed_args, attribute) is not None): - body[attribute] = getattr(parsed_args, attribute) - - -def _get_columns(item): - column_map = {} - hidden_columns = ['location', 'tenant_id'] - return osc_utils.get_osc_show_columns_for_sdk_resource( - item, - column_map, - hidden_columns - ) - - -class CreateTapService(command.ShowOne): - _description = _("Create a tap service") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - identity_utils.add_project_owner_option_to_parser(parser) - _add_updatable_args(parser) - parser.add_argument( - '--port', - dest='port_id', - required=True, - metavar="PORT", - help=_('Port to which the Tap service is connected.')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = {} - if parsed_args.name is not None: - attrs['name'] = str(parsed_args.name) - if parsed_args.description is not None: - attrs['description'] = str(parsed_args.description) - if parsed_args.port_id is not None: - port_id = client.find_port(parsed_args.port_id)['id'] - attrs['port_id'] = port_id - if 'project' in parsed_args and parsed_args.project is not None: - project_id = identity_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - attrs['tenant_id'] = project_id - obj = client.create_tap_service(**attrs) - display_columns, columns = _get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data - - -class ListTapService(command.Lister): - _description = _("List tap services that belong to a given tenant") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - identity_utils.add_project_owner_option_to_parser(parser) - - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - params = {} - if parsed_args.project is not None: - project_id = identity_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - params['tenant_id'] = project_id - objs = client.tap_services(retrieve_all=True, params=params) - headers, columns = column_util.get_column_definitions( - _attr_map, long_listing=True) - return (headers, (osc_utils.get_dict_properties( - s, columns) for s in objs)) - - -class ShowTapService(command.ShowOne): - _description = _("Show information of a given tap service") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_SERVICE, - metavar="<%s>" % TAP_SERVICE, - help=_("ID or name of tap service to look up."), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - id = client.find_tap_service(parsed_args.tap_service, - ignore_missing=False).id - obj = client.get_tap_service(id) - display_columns, columns = _get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data - - -class DeleteTapService(command.Command): - _description = _("Delete a tap service") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_SERVICE, - metavar="<%s>" % TAP_SERVICE, - nargs="+", - help=_("ID(s) or name(s) of tap service to delete."), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fails = 0 - for id_or_name in parsed_args.tap_service: - try: - id = client.find_tap_service(id_or_name, - ignore_missing=False).id - - client.delete_tap_service(id) - LOG.warning("Tap service %(id)s deleted", {'id': id}) - except Exception as e: - fails += 1 - LOG.error("Failed to delete tap service with name or ID " - "'%(id_or_name)s': %(e)s", - {'id_or_name': id_or_name, 'e': e}) - if fails > 0: - msg = (_("Failed to delete %(fails)s of %(total)s tap service.") % - {'fails': fails, 'total': len(parsed_args.tap_service)}) - raise exceptions.CommandError(msg) - - -class UpdateTapService(command.ShowOne): - _description = _("Update a tap service.") - - def get_parser(self, prog_name): - parser = super().get_parser(prog_name) - parser.add_argument( - TAP_SERVICE, - metavar="<%s>" % TAP_SERVICE, - help=_("ID or name of tap service to update."), - ) - _add_updatable_args(parser) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - original_t_s = client.find_tap_service(parsed_args.tap_service, - ignore_missing=False).id - attrs = {} - if parsed_args.name is not None: - attrs['name'] = str(parsed_args.name) - if parsed_args.description is not None: - attrs['description'] = str(parsed_args.description) - obj = client.update_tap_service(original_t_s, **attrs) - display_columns, columns = _get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns) - return display_columns, data diff --git a/neutronclient/tests/unit/osc/v2/taas/__init__.py b/neutronclient/tests/unit/osc/v2/taas/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/osc/v2/taas/fakes.py b/neutronclient/tests/unit/osc/v2/taas/fakes.py deleted file mode 100644 index ee32cb1ba..000000000 --- a/neutronclient/tests/unit/osc/v2/taas/fakes.py +++ /dev/null @@ -1,122 +0,0 @@ -# All Rights Reserved 2020 -# -# 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 copy - -from oslo_utils import uuidutils - - -class FakeTapService: - - @staticmethod - def create_tap_service(attrs=None): - """Create a fake tap service.""" - attrs = attrs or {} - tap_service_attrs = { - 'id': uuidutils.generate_uuid(), - 'tenant_id': uuidutils.generate_uuid(), - 'name': 'test_tap_service' + uuidutils.generate_uuid(), - 'status': 'ACTIVE', - } - tap_service_attrs.update(attrs) - return copy.deepcopy(tap_service_attrs) - - @staticmethod - def create_tap_services(attrs=None, count=1): - """Create multiple fake tap services.""" - - tap_services = [] - for i in range(0, count): - if attrs is None: - attrs = {'id': 'fake_id%d' % i} - elif getattr(attrs, 'id', None) is None: - attrs['id'] = 'fake_id%d' % i - tap_services.append(FakeTapService.create_tap_service( - attrs=attrs)) - - return tap_services - - -class FakeTapFlow: - - @staticmethod - def create_tap_flow(attrs=None): - """Create a fake tap service.""" - attrs = attrs or {} - tap_flow_attrs = { - 'id': uuidutils.generate_uuid(), - 'tenant_id': uuidutils.generate_uuid(), - 'name': 'test_tap_flow' + uuidutils.generate_uuid(), - 'status': 'ACTIVE', - 'direction': 'BOTH', - } - tap_flow_attrs.update(attrs) - return copy.deepcopy(tap_flow_attrs) - - @staticmethod - def create_tap_flows(attrs=None, count=1): - """Create multiple fake tap flows.""" - - tap_flows = [] - for i in range(0, count): - if attrs is None: - attrs = { - 'id': 'fake_id%d' % i, - 'source_port': uuidutils.generate_uuid(), - 'tap_service_id': uuidutils.generate_uuid() - } - elif getattr(attrs, 'id', None) is None: - attrs['id'] = 'fake_id%d' % i - tap_flows.append(FakeTapFlow.create_tap_flow(attrs=attrs)) - - return tap_flows - - -class FakeTapMirror(object): - - @staticmethod - def create_tap_mirror(attrs=None): - """Create a fake tap mirror.""" - attrs = attrs or {} - tap_mirror_attrs = { - 'id': uuidutils.generate_uuid(), - 'tenant_id': uuidutils.generate_uuid(), - 'name': 'test_tap_mirror' + uuidutils.generate_uuid(), - 'port_id': uuidutils.generate_uuid(), - 'directions': 'IN=99', - 'remote_ip': '192.10.10.2', - 'mirror_type': 'gre', - } - tap_mirror_attrs.update(attrs) - return copy.deepcopy(tap_mirror_attrs) - - @staticmethod - def create_tap_mirrors(attrs=None, count=1): - """Create multiple fake tap mirrors.""" - - tap_mirrors = [] - for i in range(0, count): - if attrs is None: - attrs = { - 'id': 'fake_id%d' % i, - 'port_id': uuidutils.generate_uuid(), - 'name': 'test_tap_mirror_%d' % i, - 'directions': 'IN=%d' % 99 + i, - 'remote_ip': '192.10.10.%d' % (i + 3), - } - elif getattr(attrs, 'id', None) is None: - attrs['id'] = 'fake_id%d' % i - tap_mirrors.append(FakeTapMirror.create_tap_mirror(attrs=attrs)) - - return tap_mirrors diff --git a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_flow.py b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_flow.py deleted file mode 100644 index a92e443f3..000000000 --- a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_flow.py +++ /dev/null @@ -1,283 +0,0 @@ -# All Rights Reserved 2020 -# -# 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 copy -import operator -from unittest import mock - -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes -from openstack.network.v2 import tap_flow as _tap_flow -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util -from oslo_utils import uuidutils - -from neutronclient.osc.v2.taas import tap_flow as osc_tap_flow -from neutronclient.osc.v2.taas import tap_service as osc_tap_service -from neutronclient.tests.unit.osc.v2.taas import fakes - - -columns_long = tuple(col for col, _, listing_mode in osc_tap_flow._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -headers_long = tuple(head for _, head, listing_mode in - osc_tap_flow._attr_map if listing_mode in - (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) -sorted_attr_map = sorted(osc_tap_flow._attr_map, key=operator.itemgetter(1)) -sorted_columns = tuple(col for col, _, _ in sorted_attr_map) -sorted_headers = tuple(head for _, head, _ in sorted_attr_map) - - -def _get_data(attrs, columns=sorted_columns): - return osc_utils.get_dict_properties(attrs, columns) - - -class TestCreateTapFlow(test_fakes.TestNeutronClientOSCV2): - - columns = ( - 'direction', - 'id', - 'name', - 'source_port', - 'status', - 'tap_service_id', - ) - - def setUp(self): - super().setUp() - self.cmd = osc_tap_flow.CreateTapFlow(self.app, self.namespace) - - def test_create_tap_flow(self): - """Test Create Tap Flow.""" - port_id = uuidutils.generate_uuid() - fake_tap_service = fakes.FakeTapService.create_tap_service( - attrs={'port_id': port_id} - ) - port_id = uuidutils.generate_uuid() - fake_tap_flow = fakes.FakeTapFlow.create_tap_flow( - attrs={ - 'source_port': port_id, - 'tap_service_id': fake_tap_service['id'] - } - ) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.create_tap_flow = mock.Mock( - return_value=fake_tap_flow) - self.app.client_manager.network.find_port = mock.Mock( - return_value={'id': port_id}) - self.app.client_manager.network.find_tap_service = mock.Mock( - return_value=fake_tap_service) - arg_list = [ - '--name', fake_tap_flow['name'], - '--port', fake_tap_flow['source_port'], - '--tap-service', fake_tap_flow['tap_service_id'], - '--direction', fake_tap_flow['direction'], - ] - - verify_list = [ - ('name', fake_tap_flow['name']), - ('port', fake_tap_flow['source_port']), - ('tap_service', fake_tap_flow['tap_service_id']), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - with mock.patch.object( - self.app.client_manager.network, - '_find') as nc_find: - nc_find.side_effect = [ - {'id': fake_tap_flow['tap_service_id']} - ] - - columns, data = self.cmd.take_action(parsed_args) - mock_create_t_f = self.app.client_manager.network.create_tap_flow - mock_create_t_f.assert_called_once_with( - **{ - 'name': fake_tap_flow['name'], - 'source_port': fake_tap_flow['source_port'], - 'tap_service_id': fake_tap_flow['tap_service_id'], - 'direction': fake_tap_flow['direction'] - } - ) - self.assertEqual(self.columns, columns) - fake_data = _get_data( - fake_tap_flow, - osc_tap_service._get_columns(fake_tap_flow)[1]) - self.assertItemEqual(fake_data, data) - - -class TestListTapFlow(test_fakes.TestNeutronClientOSCV2): - def setUp(self): - super().setUp() - self.cmd = osc_tap_flow.ListTapFlow(self.app, self.namespace) - - def test_list_tap_flows(self): - """Test List Tap Flow.""" - fake_tap_flows = fakes.FakeTapFlow.create_tap_flows( - attrs={ - 'source_port': uuidutils.generate_uuid(), - 'tap_service_id': uuidutils.generate_uuid(), - }, - count=2) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.tap_flows = mock.Mock( - return_value=fake_tap_flows) - arg_list = [] - verify_list = [] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - - headers, data = self.cmd.take_action(parsed_args) - - self.app.client_manager.network.tap_flows.assert_called_once() - self.assertEqual(headers, list(headers_long)) - self.assertListItemEqual( - list(data), - [_get_data(fake_tap_flow, columns_long) for fake_tap_flow - in fake_tap_flows] - ) - - -class TestDeleteTapFlow(test_fakes.TestNeutronClientOSCV2): - def setUp(self): - super().setUp() - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_flow = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - _tap_flow.TapFlow(id=name_or_id)) - self.cmd = osc_tap_flow.DeleteTapFlow(self.app, self.namespace) - - def test_delete_tap_flow(self): - """Test Delete tap flow.""" - - fake_tap_flow = fakes.FakeTapFlow.create_tap_flow( - attrs={ - 'source_port': uuidutils.generate_uuid(), - 'tap_service_id': uuidutils.generate_uuid(), - } - ) - self.app.client_manager.network.delete_tap_flow = mock.Mock() - - arg_list = [ - fake_tap_flow['id'], - ] - verify_list = [ - (osc_tap_flow.TAP_FLOW, [fake_tap_flow['id']]), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - - result = self.cmd.take_action(parsed_args) - - mock_delete_tap_flow = self.app.client_manager.network.delete_tap_flow - mock_delete_tap_flow.assert_called_once_with(fake_tap_flow['id']) - self.assertIsNone(result) - - -class TestShowTapFlow(test_fakes.TestNeutronClientOSCV2): - columns = ( - 'direction', - 'id', - 'name', - 'source_port', - 'status', - 'tap_service_id' - ) - - def setUp(self): - super().setUp() - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_flow = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - _tap_flow.TapFlow(id=name_or_id)) - self.cmd = osc_tap_flow.ShowTapFlow(self.app, self.namespace) - - def test_show_tap_flow(self): - """Test Show tap flow.""" - fake_tap_flow = fakes.FakeTapFlow.create_tap_flow( - attrs={ - 'source_port': uuidutils.generate_uuid(), - 'tap_service_id': uuidutils.generate_uuid(), - } - ) - self.app.client_manager.network.get_tap_flow = mock.Mock( - return_value=fake_tap_flow) - arg_list = [ - fake_tap_flow['id'], - ] - verify_list = [ - (osc_tap_flow.TAP_FLOW, fake_tap_flow['id']), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - - headers, data = self.cmd.take_action(parsed_args) - - self.app.client_manager.network.get_tap_flow.assert_called_once_with( - fake_tap_flow['id']) - self.assertEqual(self.columns, headers) - fake_data = _get_data( - fake_tap_flow, - osc_tap_service._get_columns(fake_tap_flow)[1]) - self.assertItemEqual(fake_data, data) - - -class TestUpdateTapFlow(test_fakes.TestNeutronClientOSCV2): - - _new_name = 'new_name' - - columns = ( - 'Direction', - 'ID', - 'Name', - 'Status', - 'Tenant', - 'source_port', - 'tap_service_id', - ) - - def setUp(self): - super().setUp() - self.cmd = osc_tap_flow.UpdateTapFlow(self.app, self.namespace) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_flow = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - _tap_flow.TapFlow(id=name_or_id)) - - def test_update_tap_flow(self): - """Test update tap service""" - fake_tap_flow = fakes.FakeTapFlow.create_tap_flow( - attrs={ - 'source_port': uuidutils.generate_uuid(), - 'tap_service_id': uuidutils.generate_uuid(), - } - ) - new_tap_flow = copy.deepcopy(fake_tap_flow) - new_tap_flow['name'] = self._new_name - - self.app.client_manager.network.update_tap_flow = mock.Mock( - return_value=new_tap_flow) - - arg_list = [ - fake_tap_flow['id'], - '--name', self._new_name, - ] - verify_list = [('name', self._new_name)] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - columns, data = self.cmd.take_action(parsed_args) - attrs = {'name': self._new_name} - - mock_update_t_f = self.app.client_manager.network.update_tap_flow - mock_update_t_f.assert_called_once_with(new_tap_flow['id'], **attrs) - self.assertEqual(self.columns, columns) - self.assertItemEqual(_get_data(new_tap_flow), data) diff --git a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_mirror.py b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_mirror.py deleted file mode 100644 index 88314842b..000000000 --- a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_mirror.py +++ /dev/null @@ -1,267 +0,0 @@ -# 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 copy -import operator -from unittest import mock - -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes -from openstack.network.v2 import tap_mirror -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util -from oslo_utils import uuidutils - -from neutronclient.osc.v2.taas import tap_mirror as osc_tap_mirror -from neutronclient.tests.unit.osc.v2.taas import fakes - - -columns_long = tuple(col for col, _, listing_mode in osc_tap_mirror._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -headers_long = tuple(head for _, head, listing_mode in - osc_tap_mirror._attr_map if listing_mode in - (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) -sorted_attr_map = sorted(osc_tap_mirror._attr_map, key=operator.itemgetter(1)) -sorted_columns = tuple(col for col, _, _ in sorted_attr_map) -sorted_headers = tuple(head for _, head, _ in sorted_attr_map) - - -def _get_data(attrs, columns=sorted_columns): - return osc_utils.get_dict_properties(attrs, columns) - - -class TestCreateTapMirror(test_fakes.TestNeutronClientOSCV2): - - columns = ( - 'directions', - 'id', - 'mirror_type', - 'name', - 'port_id', - 'remote_ip', - ) - - def setUp(self): - super().setUp() - self.cmd = osc_tap_mirror.CreateTapMirror(self.app, self.namespace) - - def test_create_tap_mirror(self): - port_id = uuidutils.generate_uuid() - fake_tap_mirror = fakes.FakeTapMirror.create_tap_mirror( - attrs={'port_id': port_id} - ) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.create_tap_mirror = mock.Mock( - return_value=fake_tap_mirror) - self.app.client_manager.network.find_port = mock.Mock( - return_value={'id': port_id}) - self.app.client_manager.network.find_tap_mirror = mock.Mock( - side_effect=lambda _, name_or_id: {'id': name_or_id}) - arg_list = [ - '--name', fake_tap_mirror['name'], - '--port', fake_tap_mirror['port_id'], - '--directions', fake_tap_mirror['directions'], - '--remote-ip', fake_tap_mirror['remote_ip'], - '--mirror-type', fake_tap_mirror['mirror_type'], - ] - - verify_directions = fake_tap_mirror['directions'].split('=') - verify_directions_dict = {verify_directions[0]: verify_directions[1]} - - verify_list = [ - ('name', fake_tap_mirror['name']), - ('port_id', fake_tap_mirror['port_id']), - ('directions', verify_directions_dict), - ('remote_ip', fake_tap_mirror['remote_ip']), - ('mirror_type', fake_tap_mirror['mirror_type']), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - self.app.client_manager.network.find_tap_mirror = mock.Mock( - return_value=fake_tap_mirror) - - columns, data = self.cmd.take_action(parsed_args) - create_tap_m_mock = self.app.client_manager.network.create_tap_mirror - create_tap_m_mock.assert_called_once_with( - **{'name': fake_tap_mirror['name'], - 'port_id': fake_tap_mirror['port_id'], - 'directions': verify_directions_dict, - 'remote_ip': fake_tap_mirror['remote_ip'], - 'mirror_type': fake_tap_mirror['mirror_type']}) - self.assertEqual(self.columns, columns) - fake_data = _get_data( - fake_tap_mirror, - osc_tap_mirror._get_columns(fake_tap_mirror)[1]) - self.assertEqual(fake_data, data) - - -class TestListTapMirror(test_fakes.TestNeutronClientOSCV2): - - def setUp(self): - super().setUp() - self.cmd = osc_tap_mirror.ListTapMirror(self.app, self.namespace) - - def test_list_tap_mirror(self): - """Test List Tap Mirror.""" - fake_tap_mirrors = fakes.FakeTapMirror.create_tap_mirrors( - attrs={'port_id': uuidutils.generate_uuid()}, - count=4) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.tap_mirrors = mock.Mock( - return_value=fake_tap_mirrors) - - arg_list = [] - verify_list = [] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - - headers, data = self.cmd.take_action(parsed_args) - - self.app.client_manager.network.tap_mirrors.assert_called_once() - self.assertEqual(headers, list(headers_long)) - self.assertListItemEqual( - list(data), - [_get_data(fake_tap_mirror, columns_long) for fake_tap_mirror - in fake_tap_mirrors] - ) - - -class TestDeleteTapMirror(test_fakes.TestNeutronClientOSCV2): - - def setUp(self): - super().setUp() - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_mirror = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - tap_mirror.TapMirror(id=name_or_id)) - self.cmd = osc_tap_mirror.DeleteTapMirror(self.app, self.namespace) - - def test_delete_tap_mirror(self): - """Test Delete Tap Mirror.""" - - fake_tap_mirror = fakes.FakeTapMirror.create_tap_mirror( - attrs={'port_id': uuidutils.generate_uuid()} - ) - self.app.client_manager.network.delete_tap_mirror = mock.Mock() - - arg_list = [ - fake_tap_mirror['id'], - ] - verify_list = [ - (osc_tap_mirror.TAP_MIRROR, [fake_tap_mirror['id']]), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - result = self.cmd.take_action(parsed_args) - - mock_delete_tap_m = self.app.client_manager.network.delete_tap_mirror - mock_delete_tap_m.assert_called_once_with(fake_tap_mirror['id']) - self.assertIsNone(result) - - -class TestShowTapMirror(test_fakes.TestNeutronClientOSCV2): - - columns = ( - 'directions', - 'id', - 'mirror_type', - 'name', - 'port_id', - 'remote_ip', - ) - - def setUp(self): - super().setUp() - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_mirror = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - tap_mirror.TapMirror(id=name_or_id)) - self.cmd = osc_tap_mirror.ShowTapMirror(self.app, self.namespace) - - def test_show_tap_mirror(self): - """Test Show Tap Mirror.""" - - fake_tap_mirror = fakes.FakeTapMirror.create_tap_mirror( - attrs={'port_id': uuidutils.generate_uuid()} - ) - self.app.client_manager.network.get_tap_mirror = mock.Mock( - return_value=fake_tap_mirror) - arg_list = [ - fake_tap_mirror['id'], - ] - verify_list = [ - (osc_tap_mirror.TAP_MIRROR, fake_tap_mirror['id']), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - - headers, data = self.cmd.take_action(parsed_args) - - mock_get_tap_m = self.app.client_manager.network.get_tap_mirror - mock_get_tap_m.assert_called_once_with( - fake_tap_mirror['id']) - self.assertEqual(self.columns, headers) - fake_data = _get_data( - fake_tap_mirror, - osc_tap_mirror._get_columns(fake_tap_mirror)[1]) - self.assertItemEqual(fake_data, data) - - -class TestUpdateTapMirror(test_fakes.TestNeutronClientOSCV2): - - _new_name = 'new_name' - columns = ( - 'directions', - 'id', - 'mirror_type', - 'name', - 'port_id', - 'remote_ip', - ) - - def setUp(self): - super().setUp() - self.cmd = osc_tap_mirror.UpdateTapMirror(self.app, self.namespace) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_mirror = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - tap_mirror.TapMirror(id=name_or_id)) - - def test_update_tap_mirror(self): - """Test update Tap Mirror""" - fake_tap_mirror = fakes.FakeTapMirror.create_tap_mirror( - attrs={'port_id': uuidutils.generate_uuid()} - ) - new_tap_mirror = copy.deepcopy(fake_tap_mirror) - new_tap_mirror['name'] = self._new_name - - self.app.client_manager.network.update_tap_mirror = mock.Mock( - return_value=new_tap_mirror) - - arg_list = [ - fake_tap_mirror['id'], - '--name', self._new_name, - ] - verify_list = [('name', self._new_name)] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - columns, data = self.cmd.take_action(parsed_args) - attrs = {'name': self._new_name} - - mock_update_tap_m = self.app.client_manager.network.update_tap_mirror - mock_update_tap_m.assert_called_once_with( - fake_tap_mirror['id'], **attrs) - self.assertEqual(self.columns, columns) - fake_data = _get_data( - new_tap_mirror, - osc_tap_mirror._get_columns(new_tap_mirror)[1]) - self.assertItemEqual(fake_data, data) diff --git a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_service.py b/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_service.py deleted file mode 100644 index 0b753f803..000000000 --- a/neutronclient/tests/unit/osc/v2/taas/test_osc_tap_service.py +++ /dev/null @@ -1,250 +0,0 @@ -# All Rights Reserved 2020 -# -# 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 copy -import operator -from unittest import mock - -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes -from openstack.network.v2 import tap_service -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util -from oslo_utils import uuidutils - -from neutronclient.osc.v2.taas import tap_service as osc_tap_service -from neutronclient.tests.unit.osc.v2.taas import fakes - - -columns_long = tuple(col for col, _, listing_mode in osc_tap_service._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -headers_long = tuple(head for _, head, listing_mode in - osc_tap_service._attr_map if listing_mode in - (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)) -sorted_attr_map = sorted(osc_tap_service._attr_map, key=operator.itemgetter(1)) -sorted_columns = tuple(col for col, _, _ in sorted_attr_map) -sorted_headers = tuple(head for _, head, _ in sorted_attr_map) - - -def _get_data(attrs, columns=sorted_columns): - return osc_utils.get_dict_properties(attrs, columns) - - -class TestCreateTapService(test_fakes.TestNeutronClientOSCV2): - - columns = ( - 'id', - 'name', - 'port_id', - 'status', - ) - - def setUp(self): - super().setUp() - self.cmd = osc_tap_service.CreateTapService(self.app, self.namespace) - - def test_create_tap_service(self): - """Test Create Tap Service.""" - port_id = uuidutils.generate_uuid() - fake_tap_service = fakes.FakeTapService.create_tap_service( - attrs={'port_id': port_id} - ) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.create_tap_service = mock.Mock( - return_value=fake_tap_service) - self.app.client_manager.network.find_port = mock.Mock( - return_value={'id': port_id}) - self.app.client_manager.network.find_tap_service = mock.Mock( - side_effect=lambda _, name_or_id: {'id': name_or_id}) - arg_list = [ - '--name', fake_tap_service['name'], - '--port', fake_tap_service['port_id'], - ] - - verify_list = [ - ('name', fake_tap_service['name']), - ('port_id', fake_tap_service['port_id']), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - self.app.client_manager.network.find_tap_service = mock.Mock( - return_value=fake_tap_service) - - columns, data = self.cmd.take_action(parsed_args) - create_tap_s_mock = self.app.client_manager.network.create_tap_service - create_tap_s_mock.assert_called_once_with( - **{'name': fake_tap_service['name'], - 'port_id': fake_tap_service['port_id']}) - self.assertEqual(self.columns, columns) - fake_data = _get_data( - fake_tap_service, - osc_tap_service._get_columns(fake_tap_service)[1]) - self.assertEqual(fake_data, data) - - -class TestListTapService(test_fakes.TestNeutronClientOSCV2): - def setUp(self): - super().setUp() - self.cmd = osc_tap_service.ListTapService(self.app, self.namespace) - - def test_list_tap_service(self): - """Test List Tap Service.""" - fake_tap_services = fakes.FakeTapService.create_tap_services( - attrs={'port_id': uuidutils.generate_uuid()}, - count=4) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.tap_services = mock.Mock( - return_value=fake_tap_services) - - arg_list = [] - verify_list = [] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - - headers, data = self.cmd.take_action(parsed_args) - - self.app.client_manager.network.tap_services.assert_called_once() - self.assertEqual(headers, list(headers_long)) - self.assertListItemEqual( - list(data), - [_get_data(fake_tap_service, columns_long) for fake_tap_service - in fake_tap_services] - ) - - -class TestDeleteTapService(test_fakes.TestNeutronClientOSCV2): - def setUp(self): - super().setUp() - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_service = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - tap_service.TapService(id=name_or_id)) - self.cmd = osc_tap_service.DeleteTapService(self.app, self.namespace) - - def test_delete_tap_service(self): - """Test Delete tap service.""" - - fake_tap_service = fakes.FakeTapService.create_tap_service( - attrs={'port_id': uuidutils.generate_uuid()} - ) - self.app.client_manager.network.delete_tap_service = mock.Mock() - - arg_list = [ - fake_tap_service['id'], - ] - verify_list = [ - (osc_tap_service.TAP_SERVICE, [fake_tap_service['id']]), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - result = self.cmd.take_action(parsed_args) - - mock_delete_tap_s = self.app.client_manager.network.delete_tap_service - mock_delete_tap_s.assert_called_once_with(fake_tap_service['id']) - self.assertIsNone(result) - - -class TestShowTapService(test_fakes.TestNeutronClientOSCV2): - columns = ( - 'id', - 'name', - 'port_id', - 'status', - ) - - def setUp(self): - super().setUp() - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_service = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - tap_service.TapService(id=name_or_id)) - self.cmd = osc_tap_service.ShowTapService(self.app, self.namespace) - - def test_show_tap_service(self): - """Test Show tap service.""" - - fake_tap_service = fakes.FakeTapService.create_tap_service( - attrs={'port_id': uuidutils.generate_uuid()} - ) - self.app.client_manager.network.get_tap_service = mock.Mock( - return_value=fake_tap_service) - arg_list = [ - fake_tap_service['id'], - ] - verify_list = [ - (osc_tap_service.TAP_SERVICE, fake_tap_service['id']), - ] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - - headers, data = self.cmd.take_action(parsed_args) - - mock_get_tap_s = self.app.client_manager.network.get_tap_service - mock_get_tap_s.assert_called_once_with( - fake_tap_service['id']) - self.assertEqual(self.columns, headers) - fake_data = _get_data( - fake_tap_service, - osc_tap_service._get_columns(fake_tap_service)[1]) - self.assertItemEqual(fake_data, data) - - -class TestUpdateTapService(test_fakes.TestNeutronClientOSCV2): - - _new_name = 'new_name' - - columns = ( - 'id', - 'name', - 'port_id', - 'status', - ) - - def setUp(self): - super().setUp() - self.cmd = osc_tap_service.UpdateTapService(self.app, self.namespace) - self.app.client_manager.network = mock.Mock() - self.app.client_manager.network.find_tap_service = mock.Mock( - side_effect=lambda name_or_id, ignore_missing: - tap_service.TapService(id=name_or_id)) - - def test_update_tap_service(self): - """Test update tap service""" - fake_tap_service = fakes.FakeTapService.create_tap_service( - attrs={'port_id': uuidutils.generate_uuid()} - ) - new_tap_service = copy.deepcopy(fake_tap_service) - new_tap_service['name'] = self._new_name - - self.app.client_manager.network.update_tap_service = mock.Mock( - return_value=new_tap_service) - - arg_list = [ - fake_tap_service['id'], - '--name', self._new_name, - ] - verify_list = [('name', self._new_name)] - - parsed_args = self.check_parser(self.cmd, arg_list, verify_list) - columns, data = self.cmd.take_action(parsed_args) - attrs = {'name': self._new_name} - - mock_update_tap_s = self.app.client_manager.network.update_tap_service - mock_update_tap_s.assert_called_once_with( - fake_tap_service['id'], **attrs) - self.assertEqual(self.columns, columns) - fake_data = _get_data( - new_tap_service, - osc_tap_service._get_columns(new_tap_service)[1]) - self.assertItemEqual(fake_data, data) diff --git a/setup.cfg b/setup.cfg index 77c3e069a..3005e895b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -161,19 +161,3 @@ openstack.neutronclient.v2 = vpn_ipsec_site_connection_show = neutronclient.osc.v2.vpnaas.ipsec_site_connection:ShowIPsecSiteConnection network_onboard_subnets = neutronclient.osc.v2.subnet_onboard.subnet_onboard:NetworkOnboardSubnets - - tap_flow_create = neutronclient.osc.v2.taas.tap_flow:CreateTapFlow - tap_flow_delete = neutronclient.osc.v2.taas.tap_flow:DeleteTapFlow - tap_flow_list = neutronclient.osc.v2.taas.tap_flow:ListTapFlow - tap_flow_show = neutronclient.osc.v2.taas.tap_flow:ShowTapFlow - tap_flow_update = neutronclient.osc.v2.taas.tap_flow:UpdateTapFlow - tap_mirror_create = neutronclient.osc.v2.taas.tap_mirror:CreateTapMirror - tap_mirror_delete = neutronclient.osc.v2.taas.tap_mirror:DeleteTapMirror - tap_mirror_list = neutronclient.osc.v2.taas.tap_mirror:ListTapMirror - tap_mirror_show = neutronclient.osc.v2.taas.tap_mirror:ShowTapMirror - tap_mirror_update = neutronclient.osc.v2.taas.tap_mirror:UpdateTapMirror - tap_service_create = neutronclient.osc.v2.taas.tap_service:CreateTapService - tap_service_delete = neutronclient.osc.v2.taas.tap_service:DeleteTapService - tap_service_list = neutronclient.osc.v2.taas.tap_service:ListTapService - tap_service_show = neutronclient.osc.v2.taas.tap_service:ShowTapService - tap_service_update = neutronclient.osc.v2.taas.tap_service:UpdateTapService From 8f72d77812f9eb9aa1b3e28c09d378608908caa0 Mon Sep 17 00:00:00 2001 From: Zhan Zhang Date: Tue, 11 Nov 2025 13:58:21 -0500 Subject: [PATCH 143/149] v2_0: Use 'bindings' when listing port bindings This commit fixes a bug in v2_0 client's "list_port_bindings" function, where it uses "port_bindings" to access Neutron's response, instead of "bindings" [0]. [0]: https://docs.openstack.org/api-ref/network/v2/index.html#show-port-binding-of-a-port Closes-Bug: #2130459 Change-Id: I32ef753ec212b55f698e3844e043f68b22992ead Signed-off-by: Zhan Zhang --- neutronclient/v2_0/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index 9922eb31c..82676b1c1 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -850,7 +850,7 @@ def show_port_binding(self, port_id, host_id, **_params): def list_port_bindings(self, port_id, retrieve_all=True, **_params): """Fetches a list of all bindings for a certain port.""" - return self.list('port_bindings', self.port_bindings_path % port_id, + return self.list('bindings', self.port_bindings_path % port_id, retrieve_all, **_params) def activate_port_binding(self, port_id, host_id): From d9a3518f75adc7fed9db215772804cc74b066df2 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Sat, 21 Feb 2026 00:18:54 +0900 Subject: [PATCH 144/149] Bump flake8-import-order The 1.18.2 release requires pkg_resources. The dependency was removed in 1.19.0 . Change-Id: I25106085e68dfc13a091af0e9e365287dac17308 Signed-off-by: Takashi Kajinami --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 464d2b8a4..d6a160c26 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -3,7 +3,7 @@ hacking>=6.1.0,<6.2.0 # Apache-2.0 bandit!=1.6.0,>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 fixtures>=3.0.0 # Apache-2.0/BSD -flake8-import-order>=0.18.0,<0.19.0 # LGPLv3 +flake8-import-order>=0.19.0,<0.20.0 # LGPLv3 oslotest>=3.2.0 # Apache-2.0 osprofiler>=2.3.0 # Apache-2.0 python-openstackclient>=3.12.0 # Apache-2.0 From f7c085005de1ec98656c904a4d90fe833044ae9e Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Mon, 23 Feb 2026 16:39:28 +0100 Subject: [PATCH 145/149] [FWaaS] Remove client side protocol validation There is no need to limit available choices for the firewall rule's protocol on the client side. Neutron-fwaas plugin on the server side will do the validation in the same way as for security group rules. And for SG rules OSC is not validating nor limiting choices on the client's side at all. Closes-bug: #2142479 Change-Id: I8c02a2232601c2ab6655c458aa0365102b3b5e2d Signed-off-by: Slawek Kaplonski --- neutronclient/osc/v2/fwaas/firewallrule.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/neutronclient/osc/v2/fwaas/firewallrule.py b/neutronclient/osc/v2/fwaas/firewallrule.py index 206a9b4e1..8bc15b579 100644 --- a/neutronclient/osc/v2/fwaas/firewallrule.py +++ b/neutronclient/osc/v2/fwaas/firewallrule.py @@ -86,9 +86,12 @@ def _get_common_parser(parser): help=_('Description of the firewall rule')) parser.add_argument( '--protocol', - choices=['tcp', 'udp', 'icmp', 'any'], type=nc_utils.convert_to_lowercase, - help=_('Protocol for the firewall rule')) + help=_('IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, ' + 'ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, ' + 'ipv6-route, ospf, pgm, rsvp, sctp, tcp, udp, udplite, ' + 'vrrp and integer representations [0-255] or any; ' + 'default: any (all protocols))')) parser.add_argument( '--action', choices=['allow', 'deny', 'reject'], From 6e5eb4da33f8accf15a1d5680062c0b6b6fa9c3b Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Thu, 26 Feb 2026 11:04:47 +0100 Subject: [PATCH 146/149] [fwaas] Don't ignore missing fw related resources Previously when fwaas osc plugin was going to look for firewall related resources, like e.g. asking neutron for firewall group or policy was done with ignore_missing=True which means that openstack SDK client didn't raise exception when requested object was not found on the server. That led to the weird and unclear error message displayed by the OpenStack client which said something about "'NoneType' object is not subscriptable". This patch adds "ignore_missing=True" to all those "find_*" methods used in the fwaas osc plugin. That way proper exception is raised by the SDK client and valid error message is displayed to the user by OSC. Closes-bug: #2142458 Change-Id: I309a5dbf61c65d5837d4ea2b3235aa41269ae73d Signed-off-by: Slawek Kaplonski --- neutronclient/osc/v2/fwaas/firewallgroup.py | 24 ++++++++------ neutronclient/osc/v2/fwaas/firewallpolicy.py | 33 +++++++++++-------- neutronclient/osc/v2/fwaas/firewallrule.py | 16 +++++---- .../unit/osc/v2/fwaas/test_firewallgroup.py | 14 ++++---- 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/neutronclient/osc/v2/fwaas/firewallgroup.py b/neutronclient/osc/v2/fwaas/firewallgroup.py index 723e295fb..a605ddde8 100644 --- a/neutronclient/osc/v2/fwaas/firewallgroup.py +++ b/neutronclient/osc/v2/fwaas/firewallgroup.py @@ -129,19 +129,19 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): if (parsed_args.ingress_firewall_policy and parsed_args.no_ingress_firewall_policy): attrs['ingress_firewall_policy_id'] = client.find_firewall_policy( - parsed_args.ingress_firewall_policy)['id'] + parsed_args.ingress_firewall_policy, ignore_missing=False)['id'] elif parsed_args.ingress_firewall_policy: attrs['ingress_firewall_policy_id'] = client.find_firewall_policy( - parsed_args.ingress_firewall_policy)['id'] + parsed_args.ingress_firewall_policy, ignore_missing=False)['id'] elif parsed_args.no_ingress_firewall_policy: attrs['ingress_firewall_policy_id'] = None if (parsed_args.egress_firewall_policy and parsed_args.no_egress_firewall_policy): attrs['egress_firewall_policy_id'] = client.find_firewall_policy( - parsed_args.egress_firewall_policy)['id'] + parsed_args.egress_firewall_policy, ignore_missing=False)['id'] elif parsed_args.egress_firewall_policy: attrs['egress_firewall_policy_id'] = client.find_firewall_policy( - parsed_args.egress_firewall_policy)['id'] + parsed_args.egress_firewall_policy, ignore_missing=False)['id'] elif parsed_args.no_egress_firewall_policy: attrs['egress_firewall_policy_id'] = None if parsed_args.share: @@ -165,7 +165,7 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): ports.append(client.find_port(p)['id']) if not is_create: ports += client.find_firewall_group( - parsed_args.firewall_group)['ports'] + parsed_args.firewall_group, ignore_missing=False)['ports'] attrs['ports'] = sorted(set(ports)) elif parsed_args.no_port: attrs['ports'] = [] @@ -220,7 +220,8 @@ def take_action(self, parsed_args): result = 0 for fwg in parsed_args.firewall_group: try: - fwg_id = client.find_firewall_group(fwg)['id'] + fwg_id = client.find_firewall_group( + fwg, ignore_missing=False)['id'] client.delete_firewall_group(fwg_id) except Exception as e: result += 1 @@ -281,7 +282,8 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network - fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] + fwg_id = client.find_firewall_group( + parsed_args.firewall_group, ignore_missing=False)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: @@ -305,7 +307,8 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network - fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] + fwg_id = client.find_firewall_group( + parsed_args.firewall_group, ignore_missing=False)['id'] obj = client.get_firewall_group(fwg_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) @@ -366,7 +369,7 @@ def _get_attrs(self, client, parsed_args): attrs['admin_state_up'] = False if parsed_args.port: old = client.find_firewall_group( - parsed_args.firewall_group)['ports'] + parsed_args.firewall_group, ignore_missing=False)['ports'] new = [client.find_port(r)['id'] for r in parsed_args.port] attrs['ports'] = sorted(list(set(old) - set(new))) if parsed_args.all_port: @@ -375,7 +378,8 @@ def _get_attrs(self, client, parsed_args): def take_action(self, parsed_args): client = self.app.client_manager.network - fwg_id = client.find_firewall_group(parsed_args.firewall_group)['id'] + fwg_id = client.find_firewall_group( + parsed_args.firewall_group, ignore_missing=False)['id'] attrs = self._get_attrs(client, parsed_args) try: client.update_firewall_group(fwg_id, **attrs) diff --git a/neutronclient/osc/v2/fwaas/firewallpolicy.py b/neutronclient/osc/v2/fwaas/firewallpolicy.py index cfcc3c1df..cb2030470 100644 --- a/neutronclient/osc/v2/fwaas/firewallpolicy.py +++ b/neutronclient/osc/v2/fwaas/firewallpolicy.py @@ -67,16 +67,18 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): if parsed_args.firewall_rule and parsed_args.no_firewall_rule: _firewall_rules = [] for f in parsed_args.firewall_rule: - _firewall_rules.append(client.find_firewall_rule(f)['id']) + _firewall_rules.append( + client.find_firewall_rule(f, ignore_missing=False)['id']) attrs[const.FWRS] = _firewall_rules elif parsed_args.firewall_rule: rules = [] if not is_create: foobar = client.find_firewall_policy( - parsed_args.firewall_policy) + parsed_args.firewall_policy, ignore_missing=False) rules += foobar[const.FWRS] for f in parsed_args.firewall_rule: - rules.append(client.find_firewall_rule(f)['id']) + rules.append( + client.find_firewall_rule(f, ignore_missing=False)['id']) attrs[const.FWRS] = rules elif parsed_args.no_firewall_rule: attrs[const.FWRS] = [] @@ -173,7 +175,8 @@ def take_action(self, parsed_args): result = 0 for fwp in parsed_args.firewall_policy: try: - fwp_id = client.find_firewall_policy(fwp)['id'] + fwp_id = client.find_firewall_policy( + fwp, ignore_missing=False)['id'] client.delete_firewall_policy(fwp_id) except Exception as e: result += 1 @@ -220,12 +223,12 @@ def args2body(self, parsed_args): if 'insert_before' in parsed_args: if parsed_args.insert_before: _insert_before = client.find_firewall_rule( - parsed_args.insert_before)['id'] + parsed_args.insert_before, ignore_missing=False)['id'] _insert_after = '' if 'insert_after' in parsed_args: if parsed_args.insert_after: _insert_after = client.find_firewall_rule( - parsed_args.insert_after)['id'] + parsed_args.insert_after, ignore_missing=False)['id'] return {'firewall_rule_id': _rule_id, 'insert_before': _insert_before, 'insert_after': _insert_after} @@ -233,7 +236,7 @@ def args2body(self, parsed_args): def take_action(self, parsed_args): client = self.app.client_manager.network policy_id = client.find_firewall_policy( - parsed_args.firewall_policy)['id'] + parsed_args.firewall_policy, ignore_missing=False)['id'] body = self.args2body(parsed_args) client.insert_rule_into_policy(policy_id, **body) rule_id = body['firewall_rule_id'] @@ -261,7 +264,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network policy_id = client.find_firewall_policy( - parsed_args.firewall_policy)['id'] + parsed_args.firewall_policy, ignore_missing=False)['id'] fwr_id = _get_required_firewall_rule(client, parsed_args) body = {'firewall_rule_id': fwr_id} client.remove_rule_from_policy(policy_id, **body) @@ -322,7 +325,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network fwp_id = client.find_firewall_policy( - parsed_args.firewall_policy)['id'] + parsed_args.firewall_policy, ignore_missing=False)['id'] attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) try: @@ -347,7 +350,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network fwp_id = client.find_firewall_policy( - parsed_args.firewall_policy)['id'] + parsed_args.firewall_policy, ignore_missing=False)['id'] obj = client.get_firewall_policy(fwp_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) @@ -359,7 +362,8 @@ def _get_required_firewall_rule(client, parsed_args): if not parsed_args.firewall_rule: msg = (_("Firewall rule (name or ID) is required.")) raise exceptions.CommandError(msg) - return client.find_firewall_rule(parsed_args.firewall_rule)['id'] + return client.find_firewall_rule( + parsed_args.firewall_rule, ignore_missing=False)['id'] class UnsetFirewallPolicy(command.Command): @@ -399,10 +403,11 @@ def _get_attrs(self, client_manager, parsed_args): if parsed_args.firewall_rule: current = client.find_firewall_policy( - parsed_args.firewall_policy)[const.FWRS] + parsed_args.firewall_policy, ignore_missing=False)[const.FWRS] removed = [] for f in set(parsed_args.firewall_rule): - removed.append(client.find_firewall_rule(f)['id']) + removed.append( + client.find_firewall_rule(f, ignore_missing=False)['id']) attrs[const.FWRS] = [r for r in current if r not in removed] if parsed_args.all_firewall_rule: attrs[const.FWRS] = [] @@ -415,7 +420,7 @@ def _get_attrs(self, client_manager, parsed_args): def take_action(self, parsed_args): client = self.app.client_manager.network fwp_id = client.find_firewall_policy( - parsed_args.firewall_policy)['id'] + parsed_args.firewall_policy, ignore_missing=False)['id'] attrs = self._get_attrs(self.app.client_manager, parsed_args) try: client.update_firewall_policy(fwp_id, **attrs) diff --git a/neutronclient/osc/v2/fwaas/firewallrule.py b/neutronclient/osc/v2/fwaas/firewallrule.py index 8bc15b579..552558d71 100644 --- a/neutronclient/osc/v2/fwaas/firewallrule.py +++ b/neutronclient/osc/v2/fwaas/firewallrule.py @@ -229,12 +229,12 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs['shared'] = False if parsed_args.source_firewall_group: attrs['source_firewall_group_id'] = client.find_firewall_group( - parsed_args.source_firewall_group)['id'] + parsed_args.source_firewall_group, ignore_missing=False)['id'] if parsed_args.no_source_firewall_group: attrs['source_firewall_group_id'] = None if parsed_args.destination_firewall_group: attrs['destination_firewall_group_id'] = client.find_firewall_group( - parsed_args.destination_firewall_group)['id'] + parsed_args.destination_firewall_group, ignore_missing=False)['id'] if parsed_args.no_destination_firewall_group: attrs['destination_firewall_group_id'] = None return attrs @@ -284,7 +284,8 @@ def take_action(self, parsed_args): result = 0 for fwr in parsed_args.firewall_rule: try: - fwr_id = client.find_firewall_rule(fwr)['id'] + fwr_id = client.find_firewall_rule( + fwr, ignore_missing=False)['id'] client.delete_firewall_rule(fwr_id) except Exception as e: result += 1 @@ -361,7 +362,8 @@ def take_action(self, parsed_args): client = self.app.client_manager.network attrs = _get_common_attrs(self.app.client_manager, parsed_args, is_create=False) - fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] + fwr_id = client.find_firewall_rule( + parsed_args.firewall_rule, ignore_missing=False)['id'] try: client.update_firewall_rule(fwr_id, **attrs) except Exception as e: @@ -383,7 +385,8 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.network - fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] + fwr_id = client.find_firewall_rule( + parsed_args.firewall_rule, ignore_missing=False)['id'] obj = client.get_firewall_rule(fwr_id) display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( obj, _attr_map_dict, ['location', 'tenant_id']) @@ -461,7 +464,8 @@ def _get_attrs(self, client_manager, parsed_args): def take_action(self, parsed_args): client = self.app.client_manager.network attrs = self._get_attrs(self.app.client_manager, parsed_args) - fwr_id = client.find_firewall_rule(parsed_args.firewall_rule)['id'] + fwr_id = client.find_firewall_rule( + parsed_args.firewall_rule, ignore_missing=False)['id'] try: client.update_firewall_rule(fwr_id, **attrs) except Exception as e: diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py index 45f42ee83..8596e9522 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py @@ -215,7 +215,7 @@ def _mock_port_fwg(*args, **kwargs): parsed_args = self.check_parser(self.cmd, arglist, verifylist) headers, data = self.cmd.take_action(parsed_args) self.networkclient.find_firewall_policy.assert_called_once_with( - ingress_policy) + ingress_policy, ignore_missing=False) self.check_results(headers, data, request) @@ -236,7 +236,7 @@ def _mock_find(*args, **kwargs): headers, data = self.cmd.take_action(parsed_args) self.networkclient.find_firewall_policy.assert_called_once_with( - egress_policy) + egress_policy, ignore_missing=False) self.check_results(headers, data, request) def test_create_with_all_params(self): @@ -398,15 +398,15 @@ def _mock_fwg_policy(*args, **kwargs): # 1. Find specified firewall_group if self.networkclient.find_firewall_group.call_count == 1: self.networkclient.find_firewall_group.assert_called_with( - target) + target, ignore_missing=False) # 2. Find specified 'ingress_firewall_policy' if self.networkclient.find_firewall_policy.call_count == 1: self.networkclient.find_firewall_policy.assert_called_with( - ingress_policy) + ingress_policy, ignore_missing=False) # 3. Find specified 'ingress_firewall_policy' if self.networkclient.find_firewall_policy.call_count == 2: self.networkclient.find_firewall_policy.assert_called_with( - egress_policy) + egress_policy, ignore_missing=False) return {'id': args[0]} self.networkclient.find_firewall_group.side_effect = _mock_fwg_policy @@ -439,7 +439,7 @@ def _mock_port_fwg(*args, **kwargs): # 1. Find specified firewall_group if self.networkclient.find_firewall_group.call_count in [1, 2]: self.networkclient.find_firewall_group.assert_called_with( - target) + target, ignore_missing=False) return {'id': args[0], 'ports': _fwg['ports']} # 2. Find specified 'port' #1 if self.networkclient.find_port.call_count == 1: @@ -687,7 +687,7 @@ def _mock_port_fwg(*args, **kwargs): # 1. Find specified firewall_group if self.networkclient.find_firewall_group.call_count in [1, 2]: self.networkclient.find_firewall_group.assert_called_with( - target) + target, ignore_missing=False) return {'id': args[0], 'ports': _fwg['ports']} # 2. Find specified firewall_group and refer 'ports' attribute if self.networkclient.find_port.call_count == 2: From 18b1232db4189bb7dfebdcb400dae38ad27969fc Mon Sep 17 00:00:00 2001 From: OpenStack Release Bot Date: Wed, 4 Mar 2026 18:25:43 +0000 Subject: [PATCH 147/149] Update master for stable/2026.1 Add file to the reno documentation build to show release notes for stable/2026.1. Use pbr instruction to increment the minor version number automatically so that master versions are higher than the versions on stable/2026.1. Sem-Ver: feature Change-Id: Icaf974beefa4e54680fa161370a54ffd9487c0ca Signed-off-by: OpenStack Release Bot Generated-By: openstack/project-config:roles/copy-release-tools-scripts/files/release-tools/add_release_note_page.sh --- releasenotes/source/2026.1.rst | 6 ++++++ releasenotes/source/index.rst | 1 + 2 files changed, 7 insertions(+) create mode 100644 releasenotes/source/2026.1.rst diff --git a/releasenotes/source/2026.1.rst b/releasenotes/source/2026.1.rst new file mode 100644 index 000000000..3d2861580 --- /dev/null +++ b/releasenotes/source/2026.1.rst @@ -0,0 +1,6 @@ +=========================== +2026.1 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2026.1 diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index 73d4a0cab..7fe1c4a53 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + 2026.1 2025.2 2025.1 2024.2 From 759faa1b4a88ad7ce205f24c2f7981860dc81f1c Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Tue, 24 Mar 2026 14:33:35 +0100 Subject: [PATCH 148/149] Remove fwaas client code The team agreed to move these client codes to OSC see the depends-on patch. Depends-On: https://review.opendev.org/c/openstack/python-openstackclient/+/981891 Assisted-by: Claude-Code (claude-opus-4.6) Change-Id: I4e3773992c537cf50d9f5a4a2ff04ae7414a528d Signed-off-by: Slawek Kaplonski --- doc/source/cli/osc/v2/firewall-group.rst | 30 - doc/source/cli/osc/v2/firewall-policy.rst | 14 - doc/source/cli/osc/v2/firewall-rule.rst | 12 - neutronclient/osc/v2/fwaas/constants.py | 3 + neutronclient/osc/v2/fwaas/firewallgroup.py | 389 -------- neutronclient/osc/v2/fwaas/firewallpolicy.py | 430 --------- neutronclient/osc/v2/fwaas/firewallrule.py | 474 --------- .../tests/unit/osc/v2/fwaas/__init__.py | 0 .../tests/unit/osc/v2/fwaas/common.py | 304 ------ .../tests/unit/osc/v2/fwaas/fakes.py | 151 --- .../unit/osc/v2/fwaas/test_firewallgroup.py | 730 -------------- .../unit/osc/v2/fwaas/test_firewallpolicy.py | 673 ------------- .../unit/osc/v2/fwaas/test_firewallrule.py | 904 ------------------ ...ove-fwaas-osc-plugin-a1b2c3d4e5f6g7h8.yaml | 11 + setup.cfg | 21 - 15 files changed, 14 insertions(+), 4132 deletions(-) delete mode 100644 doc/source/cli/osc/v2/firewall-group.rst delete mode 100644 doc/source/cli/osc/v2/firewall-policy.rst delete mode 100644 doc/source/cli/osc/v2/firewall-rule.rst delete mode 100644 neutronclient/osc/v2/fwaas/firewallgroup.py delete mode 100644 neutronclient/osc/v2/fwaas/firewallpolicy.py delete mode 100644 neutronclient/osc/v2/fwaas/firewallrule.py delete mode 100644 neutronclient/tests/unit/osc/v2/fwaas/__init__.py delete mode 100644 neutronclient/tests/unit/osc/v2/fwaas/common.py delete mode 100644 neutronclient/tests/unit/osc/v2/fwaas/fakes.py delete mode 100644 neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py delete mode 100644 neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py delete mode 100644 neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py create mode 100644 releasenotes/notes/remove-fwaas-osc-plugin-a1b2c3d4e5f6g7h8.yaml diff --git a/doc/source/cli/osc/v2/firewall-group.rst b/doc/source/cli/osc/v2/firewall-group.rst deleted file mode 100644 index adb8d05d3..000000000 --- a/doc/source/cli/osc/v2/firewall-group.rst +++ /dev/null @@ -1,30 +0,0 @@ -============== -firewall group -============== - -A **firewall group** is a perimeter firewall management to Networking. -Firewall group uses iptables to apply firewall policy to all VM ports and -router ports within a project. - -Network v2 - -.. 'firewall group *' cannot be used below as it matches 'firewall group rule - *' or 'firewall group policy *'. - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: firewall group create - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: firewall group delete - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: firewall group list - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: firewall group set - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: firewall group show - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: firewall group unset diff --git a/doc/source/cli/osc/v2/firewall-policy.rst b/doc/source/cli/osc/v2/firewall-policy.rst deleted file mode 100644 index f05f83451..000000000 --- a/doc/source/cli/osc/v2/firewall-policy.rst +++ /dev/null @@ -1,14 +0,0 @@ -===================== -firewall group policy -===================== - -A **firewall group policy** is an ordered collection of firewall rules. -A firewall policy can be shared across projects. Thus it can also be made part -of an audit workflow wherein the firewall_policy can be audited by the -relevant entity that is authorized (and can be different from the projects -which create or use the firewall group policy). - -Network v2 - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: firewall group policy * diff --git a/doc/source/cli/osc/v2/firewall-rule.rst b/doc/source/cli/osc/v2/firewall-rule.rst deleted file mode 100644 index 2e75c775f..000000000 --- a/doc/source/cli/osc/v2/firewall-rule.rst +++ /dev/null @@ -1,12 +0,0 @@ -=================== -firewall group rule -=================== - -A **firewall group rule** represents a collection of attributes like ports, IP -addresses which define match criteria and action (allow, or deny) that needs to -be taken on the matched data traffic. - -Network v2 - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: firewall group rule * diff --git a/neutronclient/osc/v2/fwaas/constants.py b/neutronclient/osc/v2/fwaas/constants.py index 4c8ee6a2d..a5a74af73 100644 --- a/neutronclient/osc/v2/fwaas/constants.py +++ b/neutronclient/osc/v2/fwaas/constants.py @@ -14,6 +14,9 @@ # under the License. # +# TODO(slaweq): remove it once "logging" OSC plugin will be moved to the +# python-openstackclient repo + FWG = 'firewall_group' FWGS = 'firewall_groups' FWP = 'firewall_policy' diff --git a/neutronclient/osc/v2/fwaas/firewallgroup.py b/neutronclient/osc/v2/fwaas/firewallgroup.py deleted file mode 100644 index a605ddde8..000000000 --- a/neutronclient/osc/v2/fwaas/firewallgroup.py +++ /dev/null @@ -1,389 +0,0 @@ -# Copyright 2016-2017 FUJITSU LIMITED -# All Rights Reserved -# -# 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 logging - -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import constants as const -from neutronclient.osc.v2 import utils as v2_utils - - -LOG = logging.getLogger(__name__) - -_formatters = { - 'admin_state_up': v2_utils.AdminStateColumn, -} - -_attr_map_dict = { - 'id': 'ID', - 'name': 'Name', - 'ingress_firewall_policy_id': 'Ingress Policy ID', - 'egress_firewall_policy_id': 'Egress Policy ID', - 'description': 'Description', - 'status': 'Status', - 'ports': 'Ports', - 'admin_state_up': 'State', - 'shared': 'Shared', - 'tenant_id': 'Project', - 'project_id': 'Project', -} - -_attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('name', 'Name', column_util.LIST_BOTH), - ('ingress_firewall_policy_id', 'Ingress Policy ID', column_util.LIST_BOTH), - ('egress_firewall_policy_id', 'Egress Policy ID', column_util.LIST_BOTH), - ('description', 'Description', column_util.LIST_LONG_ONLY), - ('status', 'Status', column_util.LIST_LONG_ONLY), - ('ports', 'Ports', column_util.LIST_LONG_ONLY), - ('admin_state_up', 'State', column_util.LIST_LONG_ONLY), - ('shared', 'Shared', column_util.LIST_LONG_ONLY), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), -) - - -def _get_common_parser(parser): - parser.add_argument( - '--name', - help=_('Name for the firewall group')) - parser.add_argument( - '--description', - metavar='', - help=_('Description of the firewall group')) - ingress_group = parser.add_mutually_exclusive_group() - ingress_group.add_argument( - '--ingress-firewall-policy', - metavar='', - dest='ingress_firewall_policy', - help=_('Ingress firewall policy (name or ID)')) - ingress_group.add_argument( - '--no-ingress-firewall-policy', - dest='no_ingress_firewall_policy', - action='store_true', - help=_('Detach ingress firewall policy from the firewall group')) - egress_group = parser.add_mutually_exclusive_group() - egress_group.add_argument( - '--egress-firewall-policy', - metavar='', - dest='egress_firewall_policy', - help=_('Egress firewall policy (name or ID)')) - egress_group.add_argument( - '--no-egress-firewall-policy', - dest='no_egress_firewall_policy', - action='store_true', - help=_('Detach egress firewall policy from the firewall group')) - shared_group = parser.add_mutually_exclusive_group() - - shared_group.add_argument( - '--share', - action='store_true', - help=_('Share the firewall group to be used in all projects ' - '(by default, it is restricted to be used by the ' - 'current project).')) - shared_group.add_argument( - '--no-share', - action='store_true', - help=_('Restrict use of the firewall group to the ' - 'current project')) - admin_group = parser.add_mutually_exclusive_group() - admin_group.add_argument( - '--enable', - action='store_true', - help=_('Enable firewall group')) - admin_group.add_argument( - '--disable', - action='store_true', - help=_('Disable firewall group')) - return parser - - -def _get_common_attrs(client_manager, parsed_args, is_create=True): - attrs = {} - client = client_manager.network - - if is_create: - if 'project' in parsed_args and parsed_args.project is not None: - attrs['tenant_id'] = osc_utils.find_project( - client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - if (parsed_args.ingress_firewall_policy and - parsed_args.no_ingress_firewall_policy): - attrs['ingress_firewall_policy_id'] = client.find_firewall_policy( - parsed_args.ingress_firewall_policy, ignore_missing=False)['id'] - elif parsed_args.ingress_firewall_policy: - attrs['ingress_firewall_policy_id'] = client.find_firewall_policy( - parsed_args.ingress_firewall_policy, ignore_missing=False)['id'] - elif parsed_args.no_ingress_firewall_policy: - attrs['ingress_firewall_policy_id'] = None - if (parsed_args.egress_firewall_policy and - parsed_args.no_egress_firewall_policy): - attrs['egress_firewall_policy_id'] = client.find_firewall_policy( - parsed_args.egress_firewall_policy, ignore_missing=False)['id'] - elif parsed_args.egress_firewall_policy: - attrs['egress_firewall_policy_id'] = client.find_firewall_policy( - parsed_args.egress_firewall_policy, ignore_missing=False)['id'] - elif parsed_args.no_egress_firewall_policy: - attrs['egress_firewall_policy_id'] = None - if parsed_args.share: - attrs['shared'] = True - if parsed_args.no_share: - attrs['shared'] = False - if parsed_args.enable: - attrs['admin_state_up'] = True - if parsed_args.disable: - attrs['admin_state_up'] = False - if parsed_args.name: - attrs['name'] = str(parsed_args.name) - if parsed_args.description: - attrs['description'] = str(parsed_args.description) - if parsed_args.port and parsed_args.no_port: - attrs['ports'] = sorted([client.find_port( - p)['id'] for p in set(parsed_args.port)]) - elif parsed_args.port: - ports = [] - for p in set(parsed_args.port): - ports.append(client.find_port(p)['id']) - if not is_create: - ports += client.find_firewall_group( - parsed_args.firewall_group, ignore_missing=False)['ports'] - attrs['ports'] = sorted(set(ports)) - elif parsed_args.no_port: - attrs['ports'] = [] - return attrs - - -class CreateFirewallGroup(command.ShowOne): - _description = _("Create a new firewall group") - - def get_parser(self, prog_name): - parser = super(CreateFirewallGroup, self).get_parser(prog_name) - _get_common_parser(parser) - osc_utils.add_project_owner_option_to_parser(parser) - port_group = parser.add_mutually_exclusive_group() - port_group.add_argument( - '--port', - metavar='', - action='append', - help=_('Port(s) (name or ID) to apply firewall group. This ' - 'option can be repeated')) - port_group.add_argument( - '--no-port', - dest='no_port', - action='store_true', - help=_('Detach all port from the firewall group')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = _get_common_attrs(self.app.client_manager, parsed_args) - obj = client.create_firewall_group(**attrs) - display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( - obj, _attr_map_dict, ['location', 'tenant_id']) - data = utils.get_dict_properties(obj, columns, formatters=_formatters) - return (display_columns, data) - - -class DeleteFirewallGroup(command.Command): - _description = _("Delete firewall group(s)") - - def get_parser(self, prog_name): - parser = super(DeleteFirewallGroup, self).get_parser(prog_name) - parser.add_argument( - const.FWG, - metavar='', - nargs='+', - help=_('Firewall group(s) to delete (name or ID)')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - result = 0 - for fwg in parsed_args.firewall_group: - try: - fwg_id = client.find_firewall_group( - fwg, ignore_missing=False)['id'] - client.delete_firewall_group(fwg_id) - except Exception as e: - result += 1 - LOG.error(_("Failed to delete firewall group with " - "name or ID '%(firewall_group)s': %(e)s"), - {const.FWG: fwg, 'e': e}) - - if result > 0: - total = len(parsed_args.firewall_group) - msg = (_("%(result)s of %(total)s firewall group(s) " - "failed to delete.") % {'result': result, 'total': total}) - raise exceptions.CommandError(msg) - - -class ListFirewallGroup(command.Lister): - _description = _("List firewall groups") - - def get_parser(self, prog_name): - parser = super(ListFirewallGroup, self).get_parser(prog_name) - parser.add_argument( - '--long', - action='store_true', - help=_("List additional fields in output") - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - obj = client.firewall_groups() - headers, columns = column_util.get_column_definitions( - _attr_map, long_listing=parsed_args.long) - return (headers, (utils.get_dict_properties( - s, columns, formatters=_formatters) for s in obj)) - - -class SetFirewallGroup(command.Command): - _description = _("Set firewall group properties") - - def get_parser(self, prog_name): - parser = super(SetFirewallGroup, self).get_parser(prog_name) - _get_common_parser(parser) - parser.add_argument( - const.FWG, - metavar='', - help=_('Firewall group to update (name or ID)')) - parser.add_argument( - '--port', - metavar='', - action='append', - help=_('Port(s) (name or ID) to apply firewall group. This ' - 'option can be repeated')) - parser.add_argument( - '--no-port', - dest='no_port', - action='store_true', - help=_('Detach all port from the firewall group')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fwg_id = client.find_firewall_group( - parsed_args.firewall_group, ignore_missing=False)['id'] - attrs = _get_common_attrs(self.app.client_manager, parsed_args, - is_create=False) - try: - client.update_firewall_group(fwg_id, **attrs) - except Exception as e: - msg = (_("Failed to set firewall group '%(group)s': %(e)s") - % {'group': parsed_args.firewall_group, 'e': e}) - raise exceptions.CommandError(msg) - - -class ShowFirewallGroup(command.ShowOne): - _description = _("Display firewall group details") - - def get_parser(self, prog_name): - parser = super(ShowFirewallGroup, self).get_parser(prog_name) - parser.add_argument( - const.FWG, - metavar='', - help=_('Firewall group to show (name or ID)')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fwg_id = client.find_firewall_group( - parsed_args.firewall_group, ignore_missing=False)['id'] - obj = client.get_firewall_group(fwg_id) - display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( - obj, _attr_map_dict, ['location', 'tenant_id']) - data = utils.get_dict_properties(obj, columns, formatters=_formatters) - return (display_columns, data) - - -class UnsetFirewallGroup(command.Command): - _description = _("Unset firewall group properties") - - def get_parser(self, prog_name): - parser = super(UnsetFirewallGroup, self).get_parser(prog_name) - parser.add_argument( - const.FWG, - metavar='', - help=_('Firewall group to unset (name or ID)')) - port_group = parser.add_mutually_exclusive_group() - port_group.add_argument( - '--port', - metavar='', - action='append', - help=_('Port(s) (name or ID) to apply firewall group. This ' - 'option can be repeated')) - port_group.add_argument( - '--all-port', - action='store_true', - help=_('Remove all ports for this firewall group')) - parser.add_argument( - '--ingress-firewall-policy', - action='store_true', - help=_('Ingress firewall policy (name or ID) to delete')) - parser.add_argument( - '--egress-firewall-policy', - action='store_true', - dest='egress_firewall_policy', - help=_('Egress firewall policy (name or ID) to delete')) - shared_group = parser.add_mutually_exclusive_group() - shared_group.add_argument( - '--share', - action='store_true', - help=_('Restrict use of the firewall group to the ' - 'current project')) - parser.add_argument( - '--enable', - action='store_true', - help=_('Disable firewall group')) - return parser - - def _get_attrs(self, client, parsed_args): - attrs = {} - if parsed_args.ingress_firewall_policy: - attrs['ingress_firewall_policy_id'] = None - if parsed_args.egress_firewall_policy: - attrs['egress_firewall_policy_id'] = None - if parsed_args.share: - attrs['shared'] = False - if parsed_args.enable: - attrs['admin_state_up'] = False - if parsed_args.port: - old = client.find_firewall_group( - parsed_args.firewall_group, ignore_missing=False)['ports'] - new = [client.find_port(r)['id'] for r in parsed_args.port] - attrs['ports'] = sorted(list(set(old) - set(new))) - if parsed_args.all_port: - attrs['ports'] = [] - return attrs - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fwg_id = client.find_firewall_group( - parsed_args.firewall_group, ignore_missing=False)['id'] - attrs = self._get_attrs(client, parsed_args) - try: - client.update_firewall_group(fwg_id, **attrs) - except Exception as e: - msg = (_("Failed to unset firewall group '%(group)s': %(e)s") - % {'group': parsed_args.firewall_group, 'e': e}) - raise exceptions.CommandError(msg) diff --git a/neutronclient/osc/v2/fwaas/firewallpolicy.py b/neutronclient/osc/v2/fwaas/firewallpolicy.py deleted file mode 100644 index cb2030470..000000000 --- a/neutronclient/osc/v2/fwaas/firewallpolicy.py +++ /dev/null @@ -1,430 +0,0 @@ -# Copyright 2016-2017 FUJITSU LIMITED -# All Rights Reserved -# -# 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 logging - -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import constants as const - - -LOG = logging.getLogger(__name__) - -_formatters = {} - - -_attr_map_dict = { - 'id': 'ID', - 'name': 'Name', - 'description': 'Description', - 'firewall_rules': 'Firewall Rules', - 'audited': 'Audited', - 'shared': 'Shared', - 'tenant_id': 'Project', - 'project_id': 'Project', -} - -_attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('name', 'Name', column_util.LIST_BOTH), - ('firewall_rules', 'Firewall Rules', column_util.LIST_BOTH), - ('description', 'Description', column_util.LIST_LONG_ONLY), - ('audited', 'Audited', column_util.LIST_LONG_ONLY), - ('shared', 'Shared', column_util.LIST_LONG_ONLY), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), -) - - -def _get_common_attrs(client_manager, parsed_args, is_create=True): - attrs = {} - client = client_manager.network - - if is_create: - if 'project' in parsed_args and parsed_args.project is not None: - attrs['tenant_id'] = osc_utils.find_project( - client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - if parsed_args.firewall_rule and parsed_args.no_firewall_rule: - _firewall_rules = [] - for f in parsed_args.firewall_rule: - _firewall_rules.append( - client.find_firewall_rule(f, ignore_missing=False)['id']) - attrs[const.FWRS] = _firewall_rules - elif parsed_args.firewall_rule: - rules = [] - if not is_create: - foobar = client.find_firewall_policy( - parsed_args.firewall_policy, ignore_missing=False) - rules += foobar[const.FWRS] - for f in parsed_args.firewall_rule: - rules.append( - client.find_firewall_rule(f, ignore_missing=False)['id']) - attrs[const.FWRS] = rules - elif parsed_args.no_firewall_rule: - attrs[const.FWRS] = [] - if parsed_args.audited: - attrs['audited'] = True - if parsed_args.no_audited: - attrs['audited'] = False - if parsed_args.name: - attrs['name'] = str(parsed_args.name) - if parsed_args.description: - attrs['description'] = str(parsed_args.description) - if parsed_args.share: - attrs['shared'] = True - if parsed_args.no_share: - attrs['shared'] = False - return attrs - - -def _get_common_parser(parser): - parser.add_argument( - '--description', - help=_('Description of the firewall policy')) - audited_group = parser.add_mutually_exclusive_group() - audited_group.add_argument( - '--audited', - action='store_true', - help=_('Enable auditing for the policy')) - audited_group.add_argument( - '--no-audited', - action='store_true', - help=_('Disable auditing for the policy')) - shared_group = parser.add_mutually_exclusive_group() - shared_group.add_argument( - '--share', - action='store_true', - help=_('Share the firewall policy to be used in all projects ' - '(by default, it is restricted to be used by the ' - 'current project).')) - shared_group.add_argument( - '--no-share', - action='store_true', - help=_('Restrict use of the firewall policy to the ' - 'current project')) - return parser - - -class CreateFirewallPolicy(command.ShowOne): - _description = _("Create a new firewall policy") - - def get_parser(self, prog_name): - parser = super(CreateFirewallPolicy, self).get_parser(prog_name) - _get_common_parser(parser) - osc_utils.add_project_owner_option_to_parser(parser) - parser.add_argument( - 'name', - metavar='', - help=_('Name for the firewall policy')) - fwr_group = parser.add_mutually_exclusive_group() - fwr_group.add_argument( - '--firewall-rule', - action='append', - metavar='', - help=_('Firewall rule(s) to apply (name or ID)')) - fwr_group.add_argument( - '--no-firewall-rule', - action='store_true', - help=_('Unset all firewall rules from firewall policy')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = _get_common_attrs(self.app.client_manager, parsed_args) - obj = client.create_firewall_policy(**attrs) - display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( - obj, _attr_map_dict, ['location', 'tenant_id']) - data = utils.get_dict_properties(obj, columns, formatters=_formatters) - return (display_columns, data) - - -class DeleteFirewallPolicy(command.Command): - _description = _("Delete firewall policy(s)") - - def get_parser(self, prog_name): - parser = super(DeleteFirewallPolicy, self).get_parser(prog_name) - parser.add_argument( - const.FWP, - metavar='', - nargs='+', - help=_('Firewall policy(s) to delete (name or ID)')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - result = 0 - for fwp in parsed_args.firewall_policy: - try: - fwp_id = client.find_firewall_policy( - fwp, ignore_missing=False)['id'] - client.delete_firewall_policy(fwp_id) - except Exception as e: - result += 1 - LOG.error(_("Failed to delete Firewall policy with " - "name or ID '%(firewall_policy)s': %(e)s"), - {const.FWP: fwp, 'e': e}) - - if result > 0: - total = len(parsed_args.firewall_policy) - msg = (_("%(result)s of %(total)s firewall policy(s) " - "failed to delete.") % {'result': result, 'total': total}) - raise exceptions.CommandError(msg) - - -class FirewallPolicyInsertRule(command.Command): - _description = _("Insert a rule into a given firewall policy") - - def get_parser(self, prog_name): - parser = super(FirewallPolicyInsertRule, self).get_parser(prog_name) - parser.add_argument( - const.FWP, - metavar='', - help=_('Firewall policy to insert rule (name or ID)')) - parser.add_argument( - '--insert-before', - metavar='', - help=_('Insert the new rule before this existing rule ' - '(name or ID)')) - parser.add_argument( - '--insert-after', - metavar='', - help=_('Insert the new rule after this existing rule ' - '(name or ID)')) - parser.add_argument( - const.FWR, - metavar='', - help=_('Firewall rule to be inserted (name or ID)')) - return parser - - def args2body(self, parsed_args): - client = self.app.client_manager.network - _rule_id = _get_required_firewall_rule(client, parsed_args) - _insert_before = '' - if 'insert_before' in parsed_args: - if parsed_args.insert_before: - _insert_before = client.find_firewall_rule( - parsed_args.insert_before, ignore_missing=False)['id'] - _insert_after = '' - if 'insert_after' in parsed_args: - if parsed_args.insert_after: - _insert_after = client.find_firewall_rule( - parsed_args.insert_after, ignore_missing=False)['id'] - return {'firewall_rule_id': _rule_id, - 'insert_before': _insert_before, - 'insert_after': _insert_after} - - def take_action(self, parsed_args): - client = self.app.client_manager.network - policy_id = client.find_firewall_policy( - parsed_args.firewall_policy, ignore_missing=False)['id'] - body = self.args2body(parsed_args) - client.insert_rule_into_policy(policy_id, **body) - rule_id = body['firewall_rule_id'] - policy = parsed_args.firewall_policy - print((_('Inserted firewall rule %(rule)s in firewall policy ' - '%(policy)s') % {'rule': rule_id, 'policy': policy}), - file=self.app.stdout) - - -class FirewallPolicyRemoveRule(command.Command): - _description = _("Remove a rule from a given firewall policy") - - def get_parser(self, prog_name): - parser = super(FirewallPolicyRemoveRule, self).get_parser(prog_name) - parser.add_argument( - const.FWP, - metavar='', - help=_('Firewall policy to remove rule (name or ID)')) - parser.add_argument( - const.FWR, - metavar='', - help=_('Firewall rule to remove from policy (name or ID)')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - policy_id = client.find_firewall_policy( - parsed_args.firewall_policy, ignore_missing=False)['id'] - fwr_id = _get_required_firewall_rule(client, parsed_args) - body = {'firewall_rule_id': fwr_id} - client.remove_rule_from_policy(policy_id, **body) - rule_id = body['firewall_rule_id'] - policy = parsed_args.firewall_policy - print((_('Removed firewall rule %(rule)s from firewall policy ' - '%(policy)s') % {'rule': rule_id, 'policy': policy}), - file=self.app.stdout) - - -class ListFirewallPolicy(command.Lister): - _description = _("List firewall policies") - - def get_parser(self, prog_name): - parser = super(ListFirewallPolicy, self).get_parser(prog_name) - parser.add_argument( - '--long', - action='store_true', - default=False, - help=_("List additional fields in output") - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - obj = client.firewall_policies() - headers, columns = column_util.get_column_definitions( - _attr_map, long_listing=parsed_args.long) - return (headers, (utils.get_dict_properties( - s, columns, formatters=_formatters) for s in obj)) - - -class SetFirewallPolicy(command.Command): - _description = _("Set firewall policy properties") - - def get_parser(self, prog_name): - parser = super(SetFirewallPolicy, self).get_parser(prog_name) - _get_common_parser(parser) - parser.add_argument( - const.FWP, - metavar='', - help=_('Firewall policy to update (name or ID)')) - parser.add_argument( - '--name', - metavar='', - help=_('Name for the firewall policy')) - parser.add_argument( - '--firewall-rule', - action='append', - metavar='', - help=_('Firewall rule(s) to apply (name or ID)')) - parser.add_argument( - '--no-firewall-rule', - action='store_true', - help=_('Remove all firewall rules from firewall policy')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fwp_id = client.find_firewall_policy( - parsed_args.firewall_policy, ignore_missing=False)['id'] - attrs = _get_common_attrs(self.app.client_manager, - parsed_args, is_create=False) - try: - client.update_firewall_policy(fwp_id, **attrs) - except Exception as e: - msg = (_("Failed to set firewall policy '%(policy)s': %(e)s") - % {'policy': parsed_args.firewall_policy, 'e': e}) - raise exceptions.CommandError(msg) - - -class ShowFirewallPolicy(command.ShowOne): - _description = _("Display firewall policy details") - - def get_parser(self, prog_name): - parser = super(ShowFirewallPolicy, self).get_parser(prog_name) - parser.add_argument( - const.FWP, - metavar='', - help=_('Firewall policy to show (name or ID)')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fwp_id = client.find_firewall_policy( - parsed_args.firewall_policy, ignore_missing=False)['id'] - obj = client.get_firewall_policy(fwp_id) - display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( - obj, _attr_map_dict, ['location', 'tenant_id']) - data = utils.get_dict_properties(obj, columns, formatters=_formatters) - return (display_columns, data) - - -def _get_required_firewall_rule(client, parsed_args): - if not parsed_args.firewall_rule: - msg = (_("Firewall rule (name or ID) is required.")) - raise exceptions.CommandError(msg) - return client.find_firewall_rule( - parsed_args.firewall_rule, ignore_missing=False)['id'] - - -class UnsetFirewallPolicy(command.Command): - _description = _("Unset firewall policy properties") - - def get_parser(self, prog_name): - parser = super(UnsetFirewallPolicy, self).get_parser(prog_name) - parser.add_argument( - const.FWP, - metavar='', - help=_('Firewall policy to unset (name or ID)')) - firewall_rule_group = parser.add_mutually_exclusive_group() - firewall_rule_group.add_argument( - '--firewall-rule', - action='append', - metavar='', - help=_('Remove firewall rule(s) from the firewall policy ' - '(name or ID)')) - firewall_rule_group.add_argument( - '--all-firewall-rule', - action='store_true', - help=_('Remove all firewall rules from the firewall policy')) - parser.add_argument( - '--audited', - action='store_true', - help=_('Disable auditing for the policy')) - parser.add_argument( - '--share', - action='store_true', - help=_('Restrict use of the firewall policy to the ' - 'current project')) - return parser - - def _get_attrs(self, client_manager, parsed_args): - attrs = {} - client = client_manager.network - - if parsed_args.firewall_rule: - current = client.find_firewall_policy( - parsed_args.firewall_policy, ignore_missing=False)[const.FWRS] - removed = [] - for f in set(parsed_args.firewall_rule): - removed.append( - client.find_firewall_rule(f, ignore_missing=False)['id']) - attrs[const.FWRS] = [r for r in current if r not in removed] - if parsed_args.all_firewall_rule: - attrs[const.FWRS] = [] - if parsed_args.audited: - attrs['audited'] = False - if parsed_args.share: - attrs['shared'] = False - return attrs - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fwp_id = client.find_firewall_policy( - parsed_args.firewall_policy, ignore_missing=False)['id'] - attrs = self._get_attrs(self.app.client_manager, parsed_args) - try: - client.update_firewall_policy(fwp_id, **attrs) - except Exception as e: - msg = (_("Failed to unset firewall policy '%(policy)s': %(e)s") - % {'policy': parsed_args.firewall_policy, 'e': e}) - raise exceptions.CommandError(msg) diff --git a/neutronclient/osc/v2/fwaas/firewallrule.py b/neutronclient/osc/v2/fwaas/firewallrule.py deleted file mode 100644 index 552558d71..000000000 --- a/neutronclient/osc/v2/fwaas/firewallrule.py +++ /dev/null @@ -1,474 +0,0 @@ -# Copyright 2016-2017 FUJITSU LIMITED -# All Rights Reserved -# -# 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 logging - -from cliff import columns as cliff_columns -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.common import utils as nc_utils -from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import constants as const - - -LOG = logging.getLogger(__name__) - - -_attr_map_dict = { - 'id': 'ID', - 'name': 'Name', - 'enabled': 'Enabled', - 'summary': 'Summary', - 'description': 'Description', - 'firewall_policy_id': 'Firewall Policy', - 'ip_version': 'IP Version', - 'action': 'Action', - 'protocol': 'Protocol', - 'source_ip_address': 'Source IP Address', - 'source_port': 'Source Port', - 'destination_ip_address': 'Destination IP Address', - 'destination_port': 'Destination Port', - 'shared': 'Shared', - 'source_firewall_group_id': 'Source Firewall Group ID', - 'destination_firewall_group_id': 'Destination Firewall Group ID', - 'tenant_id': 'Project', - 'project_id': 'Project', -} - -_attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('name', 'Name', column_util.LIST_BOTH), - ('enabled', 'Enabled', column_util.LIST_BOTH), - ('summary', 'Summary', column_util.LIST_SHORT_ONLY), - ('description', 'Description', column_util.LIST_LONG_ONLY), - ('firewall_policy_id', 'Firewall Policy', column_util.LIST_BOTH), - ('ip_version', 'IP Version', column_util.LIST_LONG_ONLY), - ('action', 'Action', column_util.LIST_LONG_ONLY), - ('protocol', 'Protocol', column_util.LIST_LONG_ONLY), - ('source_ip_address', 'Source IP Address', column_util.LIST_LONG_ONLY), - ('source_port', 'Source Port', column_util.LIST_LONG_ONLY), - ('destination_ip_address', 'Destination IP Address', - column_util.LIST_LONG_ONLY), - ('destination_port', 'Destination Port', column_util.LIST_LONG_ONLY), - ('shared', 'Shared', column_util.LIST_LONG_ONLY), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), - ('source_firewall_group_id', 'Source Firewall Group ID', - column_util.LIST_LONG_ONLY), - ('destination_firewall_group_id', 'Destination Firewall Group ID', - column_util.LIST_LONG_ONLY), -) - - -def _get_common_parser(parser): - parser.add_argument( - '--name', - metavar='', - help=_('Name of the firewall rule')) - parser.add_argument( - '--description', - metavar='', - help=_('Description of the firewall rule')) - parser.add_argument( - '--protocol', - type=nc_utils.convert_to_lowercase, - help=_('IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, ' - 'ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, ' - 'ipv6-route, ospf, pgm, rsvp, sctp, tcp, udp, udplite, ' - 'vrrp and integer representations [0-255] or any; ' - 'default: any (all protocols))')) - parser.add_argument( - '--action', - choices=['allow', 'deny', 'reject'], - type=nc_utils.convert_to_lowercase, - help=_('Action for the firewall rule')) - parser.add_argument( - '--ip-version', - metavar='', - choices=['4', '6'], - help=_('Set IP version 4 or 6 (default is 4)')) - src_ip_group = parser.add_mutually_exclusive_group() - src_ip_group.add_argument( - '--source-ip-address', - metavar='', - help=_('Source IP address or subnet')) - src_ip_group.add_argument( - '--no-source-ip-address', - action='store_true', - help=_('Detach source IP address')) - dst_ip_group = parser.add_mutually_exclusive_group() - dst_ip_group.add_argument( - '--destination-ip-address', - metavar='', - help=_('Destination IP address or subnet')) - dst_ip_group.add_argument( - '--no-destination-ip-address', - action='store_true', - help=_('Detach destination IP address')) - src_port_group = parser.add_mutually_exclusive_group() - src_port_group.add_argument( - '--source-port', - metavar='', - help=_('Source port number or range' - '(integer in [1, 65535] or range like 123:456)')) - src_port_group.add_argument( - '--no-source-port', - action='store_true', - help=_('Detach source port number or range')) - dst_port_group = parser.add_mutually_exclusive_group() - dst_port_group.add_argument( - '--destination-port', - metavar='', - help=_('Destination port number or range' - '(integer in [1, 65535] or range like 123:456)')) - dst_port_group.add_argument( - '--no-destination-port', - action='store_true', - help=_('Detach destination port number or range')) - shared_group = parser.add_mutually_exclusive_group() - shared_group.add_argument( - '--share', - action='store_true', - help=_('Share the firewall rule to be used in all projects ' - '(by default, it is restricted to be used by the ' - 'current project).')) - shared_group.add_argument( - '--no-share', - action='store_true', - help=_('Restrict use of the firewall rule to the current project')) - enable_group = parser.add_mutually_exclusive_group() - enable_group.add_argument( - '--enable-rule', - action='store_true', - help=_('Enable this rule (default is enabled)')) - enable_group.add_argument( - '--disable-rule', - action='store_true', - help=_('Disable this rule')) - src_fwg_group = parser.add_mutually_exclusive_group() - src_fwg_group.add_argument( - '--source-firewall-group', - metavar='', - help=_('Source firewall group (name or ID)')) - src_fwg_group.add_argument( - '--no-source-firewall-group', - action='store_true', - help=_('No associated destination firewall group')) - dst_fwg_group = parser.add_mutually_exclusive_group() - dst_fwg_group.add_argument( - '--destination-firewall-group', - metavar='', - help=_('Destination firewall group (name or ID)')) - dst_fwg_group.add_argument( - '--no-destination-firewall-group', - action='store_true', - help=_('No associated destination firewall group')) - return parser - - -def _get_common_attrs(client_manager, parsed_args, is_create=True): - attrs = {} - client = client_manager.network - if is_create: - if 'project' in parsed_args and parsed_args.project is not None: - attrs['tenant_id'] = osc_utils.find_project( - client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - if parsed_args.name: - attrs['name'] = str(parsed_args.name) - if parsed_args.description: - attrs['description'] = str(parsed_args.description) - if parsed_args.protocol: - protocol = parsed_args.protocol - attrs['protocol'] = None if protocol == 'any' else protocol - if parsed_args.action: - attrs['action'] = parsed_args.action - if parsed_args.ip_version: - attrs['ip_version'] = str(parsed_args.ip_version) - if parsed_args.source_port: - attrs['source_port'] = parsed_args.source_port - if parsed_args.no_source_port: - attrs['source_port'] = None - if parsed_args.source_ip_address: - attrs['source_ip_address'] = parsed_args.source_ip_address - if parsed_args.no_source_ip_address: - attrs['source_ip_address'] = None - if parsed_args.destination_port: - attrs['destination_port'] = str(parsed_args.destination_port) - if parsed_args.no_destination_port: - attrs['destination_port'] = None - if parsed_args.destination_ip_address: - attrs['destination_ip_address'] = str( - parsed_args.destination_ip_address) - if parsed_args.no_destination_ip_address: - attrs['destination_ip_address'] = None - if parsed_args.enable_rule: - attrs['enabled'] = True - if parsed_args.disable_rule: - attrs['enabled'] = False - if parsed_args.share: - attrs['shared'] = True - if parsed_args.no_share: - attrs['shared'] = False - if parsed_args.source_firewall_group: - attrs['source_firewall_group_id'] = client.find_firewall_group( - parsed_args.source_firewall_group, ignore_missing=False)['id'] - if parsed_args.no_source_firewall_group: - attrs['source_firewall_group_id'] = None - if parsed_args.destination_firewall_group: - attrs['destination_firewall_group_id'] = client.find_firewall_group( - parsed_args.destination_firewall_group, ignore_missing=False)['id'] - if parsed_args.no_destination_firewall_group: - attrs['destination_firewall_group_id'] = None - return attrs - - -class ProtocolColumn(cliff_columns.FormattableColumn): - def human_readable(self): - return self._value if self._value else 'any' - - -_formatters = {'protocol': ProtocolColumn} - - -class CreateFirewallRule(command.ShowOne): - _description = _("Create a new firewall rule") - - def get_parser(self, prog_name): - parser = super(CreateFirewallRule, self).get_parser(prog_name) - _get_common_parser(parser) - osc_utils.add_project_owner_option_to_parser(parser) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = _get_common_attrs(self.app.client_manager, parsed_args) - obj = client.create_firewall_rule(**attrs) - display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( - obj, _attr_map_dict, ['location', 'tenant_id']) - data = utils.get_dict_properties(obj, columns, formatters=_formatters) - return display_columns, data - - -class DeleteFirewallRule(command.Command): - _description = _("Delete firewall rule(s)") - - def get_parser(self, prog_name): - parser = super(DeleteFirewallRule, self).get_parser(prog_name) - parser.add_argument( - const.FWR, - metavar='', - nargs='+', - help=_('Firewall rule(s) to delete (name or ID)')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - result = 0 - for fwr in parsed_args.firewall_rule: - try: - fwr_id = client.find_firewall_rule( - fwr, ignore_missing=False)['id'] - client.delete_firewall_rule(fwr_id) - except Exception as e: - result += 1 - LOG.error(_("Failed to delete Firewall rule with " - "name or ID '%(firewall_rule)s': %(e)s"), - {const.FWR: fwr, 'e': e}) - - if result > 0: - total = len(parsed_args.firewall_rule) - msg = (_("%(result)s of %(total)s firewall rule(s) failed " - "to delete.") % {'result': result, 'total': total}) - raise exceptions.CommandError(msg) - - -class ListFirewallRule(command.Lister): - _description = _("List firewall rules that belong to a given tenant") - - def get_parser(self, prog_name): - parser = super(ListFirewallRule, self).get_parser(prog_name) - parser.add_argument( - '--long', - action='store_true', - default=False, - help=_("List additional fields in output") - ) - return parser - - def extend_list(self, data, parsed_args): - ext_data = [] - for d in data: - protocol = d['protocol'].upper() if d['protocol'] else 'ANY' - src_ip = 'none specified' - dst_ip = 'none specified' - src_port = '(none specified)' - dst_port = '(none specified)' - if 'source_ip_address' in d and d['source_ip_address']: - src_ip = str(d['source_ip_address']).lower() - if 'source_port' in d and d['source_port']: - src_port = '(' + str(d['source_port']).lower() + ')' - if 'destination_ip_address' in d and d['destination_ip_address']: - dst_ip = str(d['destination_ip_address']).lower() - if 'destination_port' in d and d['destination_port']: - dst_port = '(' + str(d['destination_port']).lower() + ')' - action = d['action'] if d.get('action') else 'no-action' - src = 'source(port): ' + src_ip + src_port - dst = 'dest(port): ' + dst_ip + dst_port - d['summary'] = ',\n '.join([protocol, src, dst, action]) - ext_data.append(d) - return ext_data - - def take_action(self, parsed_args): - client = self.app.client_manager.network - obj = client.firewall_rules() - obj_extend = self.extend_list(obj, parsed_args) - headers, columns = column_util.get_column_definitions( - _attr_map, long_listing=parsed_args.long) - return (headers, (utils.get_dict_properties( - s, columns, formatters=_formatters) for s in obj_extend)) - - -class SetFirewallRule(command.Command): - _description = _("Set firewall rule properties") - - def get_parser(self, prog_name): - parser = super(SetFirewallRule, self).get_parser(prog_name) - _get_common_parser(parser) - parser.add_argument( - const.FWR, - metavar='', - help=_('Firewall rule to set (name or ID)')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = _get_common_attrs(self.app.client_manager, - parsed_args, is_create=False) - fwr_id = client.find_firewall_rule( - parsed_args.firewall_rule, ignore_missing=False)['id'] - try: - client.update_firewall_rule(fwr_id, **attrs) - except Exception as e: - msg = (_("Failed to set firewall rule '%(rule)s': %(e)s") - % {'rule': parsed_args.firewall_rule, 'e': e}) - raise exceptions.CommandError(msg) - - -class ShowFirewallRule(command.ShowOne): - _description = _("Display firewall rule details") - - def get_parser(self, prog_name): - parser = super(ShowFirewallRule, self).get_parser(prog_name) - parser.add_argument( - const.FWR, - metavar='', - help=_('Firewall rule to display (name or ID)')) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fwr_id = client.find_firewall_rule( - parsed_args.firewall_rule, ignore_missing=False)['id'] - obj = client.get_firewall_rule(fwr_id) - display_columns, columns = utils.get_osc_show_columns_for_sdk_resource( - obj, _attr_map_dict, ['location', 'tenant_id']) - data = utils.get_dict_properties(obj, columns, formatters=_formatters) - return (display_columns, data) - - -class UnsetFirewallRule(command.Command): - _description = _("Unset firewall rule properties") - - def get_parser(self, prog_name): - parser = super(UnsetFirewallRule, self).get_parser(prog_name) - parser.add_argument( - const.FWR, - metavar='', - help=_('Firewall rule to unset (name or ID)')) - parser.add_argument( - '--source-ip-address', - action='store_true', - help=_('Source IP address or subnet')) - parser.add_argument( - '--destination-ip-address', - action='store_true', - help=_('Destination IP address or subnet')) - parser.add_argument( - '--source-port', - action='store_true', - help=_('Source port number or range' - '(integer in [1, 65535] or range like 123:456)')) - parser.add_argument( - '--destination-port', - action='store_true', - help=_('Destination port number or range' - '(integer in [1, 65535] or range like 123:456)')) - parser.add_argument( - '--share', - action='store_true', - help=_('Restrict use of the firewall rule to the current project')) - parser.add_argument( - '--enable-rule', - action='store_true', - help=_('Disable this rule')) - - parser.add_argument( - '--source-firewall-group', - action='store_true', - help=_('Source firewall group (name or ID)')) - - parser.add_argument( - '--destination-firewall-group', - action='store_true', - help=_('Destination firewall group (name or ID)')) - return parser - - def _get_attrs(self, client_manager, parsed_args): - attrs = {} - if parsed_args.source_ip_address: - attrs['source_ip_address'] = None - if parsed_args.source_port: - attrs['source_port'] = None - if parsed_args.destination_ip_address: - attrs['destination_ip_address'] = None - if parsed_args.destination_port: - attrs['destination_port'] = None - if parsed_args.share: - attrs['shared'] = False - if parsed_args.enable_rule: - attrs['enabled'] = False - if parsed_args.source_firewall_group: - attrs['source_firewall_group_id'] = None - if parsed_args.source_firewall_group: - attrs['destination_firewall_group_id'] = None - return attrs - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = self._get_attrs(self.app.client_manager, parsed_args) - fwr_id = client.find_firewall_rule( - parsed_args.firewall_rule, ignore_missing=False)['id'] - try: - client.update_firewall_rule(fwr_id, **attrs) - except Exception as e: - msg = (_("Failed to unset firewall rule '%(rule)s': %(e)s") - % {'rule': parsed_args.firewall_rule, 'e': e}) - raise exceptions.CommandError(msg) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/__init__.py b/neutronclient/tests/unit/osc/v2/fwaas/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/osc/v2/fwaas/common.py b/neutronclient/tests/unit/osc/v2/fwaas/common.py deleted file mode 100644 index ae0d97fbb..000000000 --- a/neutronclient/tests/unit/osc/v2/fwaas/common.py +++ /dev/null @@ -1,304 +0,0 @@ -# Copyright 2016-2017 FUJITSU LIMITED -# All Rights Reserved -# -# 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 - -from osc_lib import exceptions -from osc_lib.tests import utils - -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes - - -class TestListFWaaS(test_fakes.TestNeutronClientOSCV2): - - def test_list_with_no_option(self): - arglist = [] - verifylist = [] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with() - self.assertEqual(list(self.list_headers), headers) - self.assertEqual([self.list_data], list(data)) - - def test_list_with_long_option(self): - arglist = ['--long'] - verifylist = [('long', True)] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with() - self.assertEqual(list(self.headers), headers) - - -class TestShowFWaaS(test_fakes.TestNeutronClientOSCV2): - - def test_show_filtered_by_id_or_name(self): - target = self.resource['id'] - headers, data = None, None - - def _mock_fwaas(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_policy.side_effect = _mock_fwaas - self.networkclient.find_firewall_group.side_effect = _mock_fwaas - self.networkclient.find_firewall_rule.side_effect = _mock_fwaas - - arglist = [target] - verifylist = [(self.res, target)] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target) - self.assertEqual(self.ordered_headers, headers) - - -class TestCreateFWaaS(test_fakes.TestNeutronClientOSCV2): - pass - - -class TestSetFWaaS(test_fakes.TestNeutronClientOSCV2): - - def test_set_name(self): - target = self.resource['id'] - update = 'change' - arglist = [target, '--name', update] - verifylist = [ - (self.res, target), - ('name', update), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'name': update}) - self.assertIsNone(result) - - def test_set_description(self): - target = self.resource['id'] - update = 'change-desc' - arglist = [target, '--description', update] - verifylist = [ - (self.res, target), - ('description', update), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'description': update}) - self.assertIsNone(result) - - def test_set_shared(self): - target = self.resource['id'] - arglist = [target, '--share'] - verifylist = [ - (self.res, target), - ('share', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'shared': True}) - self.assertIsNone(result) - - def test_set_duplicate_shared(self): - target = self.resource['id'] - arglist = [target, '--share', '--share'] - verifylist = [ - (self.res, target), - ('share', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'shared': True}) - self.assertIsNone(result) - - def test_set_no_share(self): - target = self.resource['id'] - arglist = [target, '--no-share'] - verifylist = [ - (self.res, target), - ('share', False), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'shared': False}) - self.assertIsNone(result) - - def test_set_duplicate_no_share(self): - target = self.resource['id'] - arglist = [target, '--no-share', '--no-share'] - verifylist = [ - (self.res, target), - ('no_share', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'shared': False}) - self.assertIsNone(result) - - def test_set_no_share_and_shared(self): - target = self.resource['id'] - arglist = [target, '--no-share', '--share'] - verifylist = [ - (self.res, target), - ('no_share', True), - ('share', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_shared_and_no_share(self): - target = self.resource['id'] - arglist = [target, '--share', '--no_share'] - verifylist = [ - (self.res, target), - ('share', True), - ('no_share', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_project(self): - target = self.resource['id'] - project_id = 'b14ce3b699594d13819a859480286489' - arglist = [target, '--project', project_id] - verifylist = [ - (self.res, target), - ('tenant_id', project_id), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_project_domain(self): - target = self.resource['id'] - project_domain = 'mydomain.com' - arglist = [target, '--project-domain', project_domain] - verifylist = [ - (self.res, target), - ('project_domain', project_domain), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - -class TestDeleteFWaaS(test_fakes.TestNeutronClientOSCV2): - - def test_delete_with_one_resource(self): - target = self.resource['id'] - - def _mock_fwaas(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_group.side_effect = _mock_fwaas - self.networkclient.find_firewall_policy.side_effect = _mock_fwaas - self.networkclient.find_firewall_rule.side_effect = _mock_fwaas - - arglist = [target] - verifylist = [(self.res, [target])] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target) - self.assertIsNone(result) - - def test_delete_with_multiple_resources(self): - - def _mock_fwaas(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_group.side_effect = _mock_fwaas - self.networkclient.find_firewall_policy.side_effect = _mock_fwaas - self.networkclient.find_firewall_rule.side_effect = _mock_fwaas - - target1 = 'target1' - target2 = 'target2' - arglist = [target1, target2] - verifylist = [(self.res, [target1, target2])] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - self.assertIsNone(result) - - self.assertEqual(2, self.mocked.call_count) - for idx, reference in enumerate([target1, target2]): - actual = ''.join(self.mocked.call_args_list[idx][0][0]) - self.assertEqual(reference, actual) - - def test_delete_multiple_with_exception(self): - target1 = 'target' - arglist = [target1] - verifylist = [(self.res, [target1])] - - self.networkclient.find_firewall_group.side_effect = [ - target1, exceptions.CommandError - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - resource_name = self.res.replace('_', ' ') - msg = "1 of 2 %s(s) failed to delete." % resource_name - with testtools.ExpectedException(exceptions.CommandError) as e: - self.cmd.take_action(parsed_args) - self.assertEqual(msg, str(e)) - - -class TestUnsetFWaaS(test_fakes.TestNeutronClientOSCV2): - - def test_unset_shared(self): - target = self.resource['id'] - arglist = [ - target, - '--share', - ] - verifylist = [ - (self.res, target), - ('share', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with(target, **{'shared': False}) - self.assertIsNone(result) - - def test_set_shared_and_no_shared(self): - target = self.resource['id'] - arglist = [target, '--share', '--no-share'] - verifylist = [ - (self.res, target), - ('share', True), - ('no_share', True), - ] - # check_parser: error: unrecognized arguments: --no-share - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_duplicate_shared(self): - target = self.resource['id'] - arglist = [target, '--share', '--share'] - verifylist = [ - (self.res, target), - ('share', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'shared': False}) - self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/fakes.py b/neutronclient/tests/unit/osc/v2/fwaas/fakes.py deleted file mode 100644 index 56d09bffc..000000000 --- a/neutronclient/tests/unit/osc/v2/fwaas/fakes.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright 2016 FUJITSU LIMITED -# All Rights Reserved -# -# 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 collections -from unittest import mock - -from openstack.network.v2 import firewall_group as fw_group -from openstack.network.v2 import firewall_policy as fw_policy -from openstack.network.v2 import firewall_rule as fw_rule -from oslo_utils import uuidutils - - -class FakeFWaaS(object): - - def create(self, attrs={}): - """Create a fake fwaas resources - - :param Dictionary attrs: - A dictionary with all attributes - :return: - A OrderedDict faking the fwaas resource - """ - self.ordered.update(attrs) - if 'FirewallGroup' == self.__class__.__name__: - return fw_group.FirewallGroup(**self.ordered) - if 'FirewallPolicy' == self.__class__.__name__: - return fw_policy.FirewallPolicy(**self.ordered) - if 'FirewallRule' == self.__class__.__name__: - fw_r = fw_rule.FirewallRule(**self.ordered) - protocol = fw_r['protocol'].upper() if fw_r['protocol'] else 'ANY' - src_ip = str(fw_r['source_ip_address']).lower() - src_port = '(' + str(fw_r['source_port']).lower() + ')' - dst_ip = str(fw_r['destination_ip_address']).lower() - dst_port = '(' + str(fw_r['destination_port']).lower() + ')' - src = 'source(port): ' + src_ip + src_port - dst = 'dest(port): ' + dst_ip + dst_port - action = fw_r['action'] if fw_r.get('action') else 'no-action' - fw_r['summary'] = ',\n '.join([protocol, src, dst, action]) - return fw_r - - def bulk_create(self, attrs=None, count=2): - """Create multiple fake fwaas resources - - :param Dictionary attrs: - A dictionary with all attributes - :param int count: - The number of fwaas resources to fake - :return: - A list of dictionaries faking the fwaas resources - """ - return [self.create(attrs=attrs) for i in range(0, count)] - - def get(self, attrs=None, count=2): - """Create multiple fake fwaas resources - - :param Dictionary attrs: - A dictionary with all attributes - :param int count: - The number of fwaas resources to fake - :return: - A list of dictionaries faking the fwaas resource - """ - if attrs is None: - self.attrs = self.bulk_create(count=count) - return mock.Mock(side_effect=attrs) - - -class FirewallGroup(FakeFWaaS): - """Fake one or more firewall group""" - - def __init__(self): - super(FirewallGroup, self).__init__() - self.ordered = collections.OrderedDict(( - ('id', 'firewall-group-id-' + - uuidutils.generate_uuid(dashed=False)), - ('name', 'my-group-' + - uuidutils.generate_uuid(dashed=False)), - ('ingress_firewall_policy_id', None), - ('egress_firewall_policy_id', None), - ('description', 'my-desc-' + - uuidutils.generate_uuid(dashed=False)), - ('status', 'INACTIVE'), - ('ports', []), - ('admin_state_up', True), - ('shared', False), - ('tenant_id', 'tenant-id-' + - uuidutils.generate_uuid(dashed=False)), - )) - - -class FirewallPolicy(FakeFWaaS): - """Fake one or more firewall policy""" - - def __init__(self): - super(FirewallPolicy, self).__init__() - self.ordered = collections.OrderedDict(( - ('id', 'firewall-policy-' + - uuidutils.generate_uuid(dashed=False)), - ('name', 'my-policy-' + - uuidutils.generate_uuid(dashed=False)), - ('firewall_rules', []), - ('description', 'my-desc-' + - uuidutils.generate_uuid(dashed=False)), - ('audited', True), - ('shared', False), - ('tenant_id', 'tenant-id-' + - uuidutils.generate_uuid(dashed=False)), - )) - - -class FirewallRule(FakeFWaaS): - """Fake one or more firewall rule""" - - def __init__(self): - super(FirewallRule, self).__init__() - self.ordered = collections.OrderedDict(( - ('id', 'firewall-rule-id-' + - uuidutils.generate_uuid(dashed=False)), - ('name', 'my-rule-' + - uuidutils.generate_uuid(dashed=False)), - ('enabled', False), - ('description', 'my-desc-' + - uuidutils.generate_uuid(dashed=False)), - ('ip_version', 4), - ('action', 'deny'), - ('protocol', None), - ('source_ip_address', '192.168.1.0/24'), - ('source_port', '1:11111'), - ('destination_ip_address', '192.168.2.2'), - ('destination_port', '2:22222'), - ('shared', False), - ('tenant_id', 'tenant-id-' + - uuidutils.generate_uuid(dashed=False)), - ('source_firewall_group_id', 'firewall-group-id-' + - uuidutils.generate_uuid(dashed=False)), - ('destination_firewall_group_id', 'firewall-group-id-' + - uuidutils.generate_uuid(dashed=False)), - )) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py deleted file mode 100644 index 8596e9522..000000000 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallgroup.py +++ /dev/null @@ -1,730 +0,0 @@ -# Copyright 2016 FUJITSU LIMITED -# All Rights Reserved -# -# 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 copy -import re -from unittest import mock - -from osc_lib import exceptions -from osc_lib.tests import utils - -from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import firewallgroup -from neutronclient.osc.v2 import utils as v2_utils -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes -from neutronclient.tests.unit.osc.v2.fwaas import common -from neutronclient.tests.unit.osc.v2.fwaas import fakes - - -_fwg = fakes.FirewallGroup().create() -CONVERT_MAP = { - 'ingress_firewall_policy': 'ingress_firewall_policy_id', - 'egress_firewall_policy': 'egress_firewall_policy_id', - 'no_ingress_firewall_policy': 'ingress_firewall_policy_id', - 'no_egress_firewall_policy': 'egress_firewall_policy_id', - 'share': 'shared', - 'no_share': 'shared', - 'project': 'tenant_id', - 'enable': 'admin_state_up', - 'disable': 'admin_state_up', - 'port': 'ports', -} - - -def _generate_response(ordered_dict=None, data=None): - source = ordered_dict if ordered_dict else _fwg - up = {'admin_state_up': - v2_utils.AdminStateColumn(source['admin_state_up'])} - if data: - up.append(data) - source.update(up) - return source - - -def _generate_req_and_res(verifylist): - request = dict(verifylist) - response = _fwg - for key, val in verifylist: - del request[key] - if re.match('^no_', key) and val is True: - new_value = None - elif key == 'enable' and val: - new_value = True - elif key == 'disable' and val: - new_value = False - elif val is True or val is False: - new_value = val - elif key in ('name', 'description'): - new_value = val - else: - new_value = val - converted = CONVERT_MAP.get(key, key) - request[converted] = new_value - response[converted] = new_value - return request, response - - -class TestFirewallGroup(test_fakes.TestNeutronClientOSCV2): - - def check_results(self, headers, data, exp_req, is_list=False): - if is_list: - req_body = {self.res_plural: list(exp_req)} - else: - req_body = exp_req - self.mocked.assert_called_once_with(**req_body) - self.assertEqual(self.ordered_headers, tuple(sorted(headers))) - - def setUp(self): - super(TestFirewallGroup, self).setUp() - - def _find_resource(*args, **kwargs): - return {'id': args[0], 'ports': _fwg['ports']} - - self.networkclient.find_firewall_group = mock.Mock( - side_effect=_find_resource) - osc_utils.find_project = mock.Mock() - osc_utils.find_project.id = _fwg['tenant_id'] - self.res = 'firewall_group' - self.res_plural = 'firewall_groups' - self.resource = _fwg - self.list_headers = ( - 'ID', - 'Name', - 'Ingress Policy ID', - 'Egress Policy ID', - ) - self.list_data = ( - _fwg['id'], - _fwg['name'], - _fwg['ingress_firewall_policy_id'], - _fwg['egress_firewall_policy_id'], - ) - self.headers = tuple(self.list_headers + ( - 'Description', - 'Status', - 'Ports', - 'State', - 'Shared', - 'Project', - )) - self.data = _generate_response() - self.ordered_headers = copy.deepcopy(tuple(sorted(self.headers))) - self.expected_data = ( - _fwg['description'], - _fwg['egress_firewall_policy_id'], - _fwg['id'], - _fwg['ingress_firewall_policy_id'], - _fwg['name'], - _fwg['ports'], - _fwg['tenant_id'], - _fwg['shared'], - v2_utils.AdminStateColumn(_fwg['admin_state_up']), - _fwg['status'], - ) - self.ordered_columns = ( - 'description', - 'egress_firewall_policy_id', - 'id', - 'ingress_firewall_policy_id', - 'name', - 'ports', - 'tenant_id', - 'shared', - 'admin_state_up', - 'status', - ) - - -class TestCreateFirewallGroup(TestFirewallGroup, common.TestCreateFWaaS): - - def setUp(self): - # Mock objects - super(TestCreateFirewallGroup, self).setUp() - self.networkclient.create_firewall_group = mock.Mock( - return_value=_fwg) - self.mocked = self.networkclient.create_firewall_group - self.cmd = firewallgroup.CreateFirewallGroup(self.app, self.namespace) - - def _update_expect_response(self, request, response): - """Set expected request and response - - :param request - A dictionary of request body(dict of verifylist) - :param response - A OrderedDict of request body - """ - # Update response body - self.networkclient.create_firewall_group.return_value = response - osc_utils.find_project.return_value.id = response['tenant_id'] - # Update response(finally returns 'data') - self.data = _generate_response(ordered_dict=response) - self.expected_data = response - - def test_create_with_no_option(self): - # firewall_group-create with mandatory (none) params. - arglist = [] - verifylist = [] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - self.assertEqual(self.ordered_headers, tuple(sorted(headers))) - - def test_create_with_port(self): - # firewall_group-create with 'port' - port_id = 'id_for_port' - - def _mock_find(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_port.side_effect = _mock_find - arglist = ['--port', port_id] - verifylist = [('port', [port_id])] - request, response = _generate_req_and_res(verifylist) - self._update_expect_response(request, response) - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.check_results(headers, data, request) - - def test_create_with_ingress_policy(self): - ingress_policy = 'my-ingress-policy' - - def _mock_port_fwg(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_policy.side_effect = _mock_port_fwg - - arglist = ['--ingress-firewall-policy', ingress_policy] - verifylist = [('ingress_firewall_policy', ingress_policy)] - request, response = _generate_req_and_res(verifylist) - self._update_expect_response(request, response) - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - self.networkclient.find_firewall_policy.assert_called_once_with( - ingress_policy, ignore_missing=False) - - self.check_results(headers, data, request) - - def test_create_with_egress_policy(self): - egress_policy = 'my-egress-policy' - - def _mock_find(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_group.side_effect = _mock_find - self.networkclient.find_firewall_policy.side_effect = _mock_find - - arglist = ['--egress-firewall-policy', egress_policy] - verifylist = [('egress_firewall_policy', egress_policy)] - request, response = _generate_req_and_res(verifylist) - self._update_expect_response(request, response) - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.networkclient.find_firewall_policy.assert_called_once_with( - egress_policy, ignore_missing=False) - self.check_results(headers, data, request) - - def test_create_with_all_params(self): - name = 'my-name' - description = 'my-desc' - ingress_policy = 'my-ingress-policy' - egress_policy = 'my-egress-policy' - - def _mock_find(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_policy.side_effect = _mock_find - port = 'port' - self.networkclient.find_port.side_effect = _mock_find - tenant_id = 'my-tenant' - arglist = [ - '--name', name, - '--description', description, - '--ingress-firewall-policy', ingress_policy, - '--egress-firewall-policy', egress_policy, - '--port', port, - '--project', tenant_id, - '--share', - '--disable', - ] - verifylist = [ - ('name', name), - ('description', description), - ('ingress_firewall_policy', ingress_policy), - ('egress_firewall_policy', egress_policy), - ('port', [port]), - ('share', True), - ('project', tenant_id), - ('disable', True), - ] - request, response = _generate_req_and_res(verifylist) - self._update_expect_response(request, response) - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.check_results(headers, data, request) - - def test_create_with_shared_and_no_share(self): - arglist = [ - '--share', - '--no-share', - ] - verifylist = [ - ('share', True), - ('no_share', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_ports_and_no(self): - port = 'my-port' - arglist = [ - '--port', port, - '--no-port', - ] - verifylist = [ - ('port', [port]), - ('no_port', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_ingress_policy_and_no(self): - policy = 'my-policy' - arglist = [ - '--ingress-firewall-policy', policy, - '--no-ingress-firewall-policy', - ] - verifylist = [ - ('ingress_firewall_policy', policy), - ('no_ingress_firewall_policy', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_egress_policy_and_no(self): - policy = 'my-policy' - arglist = [ - '--egress-firewall-policy', policy, - '--no-egress-firewall-policy', - ] - verifylist = [ - ('egress_firewall_policy', policy), - ('no_egress_firewall_policy', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - -class TestListFirewallGroup(TestFirewallGroup, common.TestListFWaaS): - - def setUp(self): - super(TestListFirewallGroup, self).setUp() - # Mock objects - self.networkclient.firewall_groups = mock.Mock( - return_value=[_fwg]) - self.mocked = self.networkclient.firewall_groups - self.cmd = firewallgroup.ListFirewallGroup(self.app, self.namespace) - - -class TestShowFirewallGroup(TestFirewallGroup, common.TestShowFWaaS): - - def setUp(self): - super(TestShowFirewallGroup, self).setUp() - # Mock objects - self.networkclient.get_firewall_group = mock.Mock( - return_value=_fwg) - self.mocked = self.networkclient.get_firewall_group - self.cmd = firewallgroup.ShowFirewallGroup(self.app, self.namespace) - - -class TestSetFirewallGroup(TestFirewallGroup, common.TestSetFWaaS): - - def setUp(self): - super(TestSetFirewallGroup, self).setUp() - # Mock objects - _fwg['ports'] = ['old_port'] - self.networkclient.update_firewall_group = mock.Mock( - return_value={self.res: _fwg}) - self.mocked = self.networkclient.update_firewall_group - - def _mock_find_port(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_port.side_effect = _mock_find_port - - self.cmd = firewallgroup.SetFirewallGroup(self.app, self.namespace) - - def _update_expect_response(self, request, response): - """Set expected request and response - - :param request - A dictionary of request body(dict of verifylist) - :param response - A OrderedDict of request body - """ - osc_utils.find_project.return_value.id = response['tenant_id'] - # Update response(finally returns 'data') - self.data = _generate_response(ordered_dict=response) - self.ordered_data = tuple( - response[column] for column in self.ordered_columns - ) - - def test_set_ingress_policy_and_egress_policy(self): - target = self.resource['id'] - ingress_policy = 'ingress_policy' - egress_policy = 'egress_policy' - - def _mock_fwg_policy(*args, **kwargs): - # 1. Find specified firewall_group - if self.networkclient.find_firewall_group.call_count == 1: - self.networkclient.find_firewall_group.assert_called_with( - target, ignore_missing=False) - # 2. Find specified 'ingress_firewall_policy' - if self.networkclient.find_firewall_policy.call_count == 1: - self.networkclient.find_firewall_policy.assert_called_with( - ingress_policy, ignore_missing=False) - # 3. Find specified 'ingress_firewall_policy' - if self.networkclient.find_firewall_policy.call_count == 2: - self.networkclient.find_firewall_policy.assert_called_with( - egress_policy, ignore_missing=False) - return {'id': args[0]} - - self.networkclient.find_firewall_group.side_effect = _mock_fwg_policy - self.networkclient.find_firewall_policy.side_effect = _mock_fwg_policy - - arglist = [ - target, - '--ingress-firewall-policy', ingress_policy, - '--egress-firewall-policy', egress_policy, - ] - verifylist = [ - (self.res, target), - ('ingress_firewall_policy', ingress_policy), - ('egress_firewall_policy', egress_policy), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'ingress_firewall_policy_id': ingress_policy, - 'egress_firewall_policy_id': egress_policy}) - self.assertIsNone(result) - - def test_set_port(self): - target = self.resource['id'] - port1 = 'additional_port1' - port2 = 'additional_port2' - - def _mock_port_fwg(*args, **kwargs): - # 1. Find specified firewall_group - if self.networkclient.find_firewall_group.call_count in [1, 2]: - self.networkclient.find_firewall_group.assert_called_with( - target, ignore_missing=False) - return {'id': args[0], 'ports': _fwg['ports']} - # 2. Find specified 'port' #1 - if self.networkclient.find_port.call_count == 1: - self.networkclient.find_port.assert_called_with(args) - return {'id': args[0]} - # 3. Find specified 'port' #2 - if self.networkclient.find_port.call_count == 2: - self.networkclient.find_port.assert_called_with(args) - return {'id': args[0]} - - self.networkclient.find_fireall_group.side_effect = _mock_port_fwg - self.networkclient.find_port.side_effect = _mock_port_fwg - - arglist = [ - target, - '--port', port1, - '--port', port2, - ] - verifylist = [ - (self.res, target), - ('port', [port1, port2]), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - expect = {'ports': sorted(_fwg['ports'] + [port1, port2])} - self.mocked.assert_called_once_with(target, **expect) - self.assertEqual(2, self.networkclient.find_firewall_group.call_count) - self.assertIsNone(result) - - def test_set_no_port(self): - # firewall_group-update myid --policy newpolicy. - target = self.resource['id'] - arglist = [target, '--no-port'] - verifylist = [ - (self.res, target), - ('no_port', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'ports': []}) - self.assertIsNone(result) - - def test_set_admin_state(self): - target = self.resource['id'] - arglist = [target, '--enable'] - verifylist = [ - (self.res, target), - ('enable', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'admin_state_up': True}) - self.assertIsNone(result) - - def test_set_egress_policy(self): - target = self.resource['id'] - policy = 'egress_policy' - - def _mock_find_policy(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_policy.side_effect = _mock_find_policy - - arglist = [target, '--egress-firewall-policy', policy] - verifylist = [ - (self.res, target), - ('egress_firewall_policy', policy), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'egress_firewall_policy_id': policy}) - self.assertIsNone(result) - - def test_set_no_ingress_policies(self): - target = self.resource['id'] - arglist = [target, '--no-ingress-firewall-policy'] - verifylist = [ - (self.res, target), - ('no_ingress_firewall_policy', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'ingress_firewall_policy_id': None}) - self.assertIsNone(result) - - def test_set_no_egress_policies(self): - target = self.resource['id'] - arglist = [target, '--no-egress-firewall-policy'] - verifylist = [ - (self.res, target), - ('no_egress_firewall_policy', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'egress_firewall_policy_id': None}) - self.assertIsNone(result) - - def test_set_port_and_no_port(self): - target = self.resource['id'] - port = 'my-port' - arglist = [ - target, - '--port', port, - '--no-port', - ] - verifylist = [ - (self.res, target), - ('port', [port]), - ('no_port', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, **{'ports': [port]}) - self.assertIsNone(result) - - def test_set_ingress_policy_and_no_ingress_policy(self): - target = self.resource['id'] - arglist = [ - target, - '--ingress-firewall-policy', 'my-ingress', - '--no-ingress-firewall-policy', - ] - verifylist = [ - (self.res, target), - ('ingress_firewall_policy', 'my-ingress'), - ('no_ingress_firewall_policy', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_egress_policy_and_no_egress_policy(self): - target = self.resource['id'] - arglist = [ - target, - '--egress-firewall-policy', 'my-egress', - '--no-egress-firewall-policy', - ] - verifylist = [ - (self.res, target), - ('egress_firewall_policy', 'my-egress'), - ('no_egress_firewall_policy', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_and_raises(self): - self.networkclient.update_firewall_group = mock.Mock( - side_effect=Exception) - target = self.resource['id'] - arglist = [target, '--name', 'my-name'] - verifylist = [(self.res, target), ('name', 'my-name')] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) - - -class TestDeleteFirewallGroup(TestFirewallGroup, common.TestDeleteFWaaS): - - def setUp(self): - super(TestDeleteFirewallGroup, self).setUp() - # Mock objects - self.networkclient.delete_firewall_group = mock.Mock() - self.mocked = self.networkclient.delete_firewall_group - self.cmd = firewallgroup.DeleteFirewallGroup(self.app, self.namespace) - - -class TestUnsetFirewallGroup(TestFirewallGroup, common.TestUnsetFWaaS): - - def setUp(self): - super(TestUnsetFirewallGroup, self).setUp() - _fwg['ports'] = ['old_port'] - # Mock objects - self.networkclient.update_firewall_group = mock.Mock() - self.mocked = self.networkclient.update_firewall_group - self.cmd = firewallgroup.UnsetFirewallGroup(self.app, self.namespace) - - def test_unset_ingress_policy(self): - target = self.resource['id'] - arglist = [ - target, - '--ingress-firewall-policy', - ] - verifylist = [ - (self.res, target), - ('ingress_firewall_policy', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, **{'ingress_firewall_policy_id': None}) - self.assertIsNone(result) - - def test_unset_egress_policy(self): - target = self.resource['id'] - arglist = [ - target, - '--egress-firewall-policy', - ] - verifylist = [ - (self.res, target), - ('egress_firewall_policy', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, **{'egress_firewall_policy_id': None}) - self.assertIsNone(result) - - def test_unset_enable(self): - target = self.resource['id'] - arglist = [ - target, - '--enable', - ] - verifylist = [ - (self.res, target), - ('enable', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with( - target, **{'admin_state_up': False}) - self.assertIsNone(result) - - def test_unset_port(self): - target = self.resource['id'] - port = 'old_port' - - def _mock_port_fwg(*args, **kwargs): - # 1. Find specified firewall_group - if self.networkclient.find_firewall_group.call_count in [1, 2]: - self.networkclient.find_firewall_group.assert_called_with( - target, ignore_missing=False) - return {'id': args[0], 'ports': _fwg['ports']} - # 2. Find specified firewall_group and refer 'ports' attribute - if self.networkclient.find_port.call_count == 2: - self.networkclient.find_port.assert_called_with(target) - return {'ports': _fwg['ports']} - # 3. Find specified 'port' - if self.networkclient.find_port.call_count == 3: - self.networkclient.find_port.assert_called_with(port) - return {'id': args[0]} - - self.networkclient.find_firewall_group.side_effect = _mock_port_fwg - self.networkclient.find_port.side_effect = _mock_port_fwg - - arglist = [ - target, - '--port', port, - ] - verifylist = [ - (self.res, target), - ('port', [port]), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with(target, **{'ports': []}) - self.assertIsNone(result) - - def test_unset_all_port(self): - target = self.resource['id'] - arglist = [ - target, - '--all-port', - ] - verifylist = [ - (self.res, target), - ('all_port', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - self.mocked.assert_called_once_with(target, **{'ports': []}) - self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py deleted file mode 100644 index fe385a0cb..000000000 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallpolicy.py +++ /dev/null @@ -1,673 +0,0 @@ -# Copyright 2016 FUJITSU LIMITED -# All Rights Reserved -# -# 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 re -from unittest import mock - -from osc_lib import exceptions -from osc_lib.tests import utils - -from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import firewallpolicy -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes -from neutronclient.tests.unit.osc.v2.fwaas import common -from neutronclient.tests.unit.osc.v2.fwaas import fakes - - -_fwp = fakes.FirewallPolicy().create() -CONVERT_MAP = { - 'share': 'shared', - 'no_share': 'shared', - 'project': 'tenant_id', - 'port': 'ports', - 'name': 'name', - 'id': 'id', - 'firewall_rule': 'firewall_rules', - 'description': 'description' -} - - -def _generate_data(ordered_dict=None, data=None): - source = ordered_dict if ordered_dict else _fwp - if data: - source.update(data) - return tuple(source[key] for key in source) - - -def _generate_req_and_res(verifylist): - request = dict(verifylist) - response = _fwp - for key, val in verifylist: - converted = CONVERT_MAP.get(key, key) - del request[key] - if re.match('^no_', key) and val is True: - new_value = None - elif key == 'enable' and val: - new_value = True - elif key == 'disable' and val: - new_value = False - elif val is True or val is False: - new_value = val - elif key in ('name', 'description'): - new_value = val - else: - new_value = val - request[converted] = new_value - response[converted] = new_value - return request, response - - -class TestFirewallPolicy(test_fakes.TestNeutronClientOSCV2): - - def check_results(self, headers, data, exp_req, is_list=False): - if is_list: - req_body = {self.res_plural: [exp_req]} - else: - req_body = exp_req - self.mocked.assert_called_once_with(**req_body) - self.assertEqual(self.ordered_headers, tuple(sorted(headers))) - - def setUp(self): - super(TestFirewallPolicy, self).setUp() - - osc_utils.find_project = mock.Mock() - osc_utils.find_project.id = _fwp['tenant_id'] - self.res = 'firewall_policy' - self.res_plural = 'firewall_policies' - self.resource = _fwp - self.list_headers = ( - 'ID', - 'Name', - 'Firewall Rules', - ) - self.list_data = ( - _fwp['id'], - _fwp['name'], - _fwp['firewall_rules'], - ) - self.headers = tuple(self.list_headers + ( - 'Description', - 'Audited', - 'Shared', - 'Project') - ) - self.data = _generate_data() - self.ordered_headers = ( - 'Audited', - 'Description', - 'Firewall Rules', - 'ID', - 'Name', - 'Project', - 'Shared', - ) - self.ordered_data = ( - _fwp['audited'], - _fwp['description'], - _fwp['firewall_rules'], - _fwp['id'], - _fwp['name'], - _fwp['tenant_id'], - _fwp['shared'], - ) - self.ordered_columns = ( - 'audited', - 'description', - 'firewall_rules', - 'id', - 'name', - 'tenant_id', - 'shared', - ) - - -class TestCreateFirewallPolicy(TestFirewallPolicy, common.TestCreateFWaaS): - - def setUp(self): - super(TestCreateFirewallPolicy, self).setUp() - self.networkclient.create_firewall_policy = mock.Mock( - return_value={self.res: _fwp}) - self.mocked = self.networkclient.create_firewall_policy - self.cmd = firewallpolicy.CreateFirewallPolicy(self.app, - self.namespace) - - def _update_expect_response(self, request, response): - """Set expected request and response - - :param request - A dictionary of request body(dict of verifylist) - :param response - A OrderedDict of request body - """ - # Update response body - self.networkclient.create_firewall_policy.return_value = response - osc_utils.find_project.return_value.id = response['tenant_id'] - # Update response(finally returns 'data') - self.data = _generate_data(data=response) - self.ordered_data = tuple( - response[column] for column in self.ordered_columns - ) - - def test_create_with_no_options(self): - arglist = [] - verifylist = [] - - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_mandatory_param(self): - name = 'my-fwg' - arglist = [ - name, - ] - verifylist = [ - ('name', name), - ] - request, response = _generate_req_and_res(verifylist) - self._update_expect_response(request, response) - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.check_results(headers, data, request) - - def test_create_with_rules(self): - name = 'my-fwg' - rule1 = 'rule1' - rule2 = 'rule2' - - def _mock_policy(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_rule.side_effect = _mock_policy - - arglist = [ - name, - '--firewall-rule', rule1, - '--firewall-rule', rule2, - ] - verifylist = [ - ('name', name), - ('firewall_rule', [rule1, rule2]), - ] - request, response = _generate_req_and_res(verifylist) - self._update_expect_response(request, response) - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - self.assertEqual(2, self.networkclient.find_firewall_rule.call_count) - - self.check_results(headers, data, request) - - def test_create_with_all_params(self): - name = 'my-fwp' - desc = 'my-desc' - rule1 = 'rule1' - rule2 = 'rule2' - project = 'my-tenant' - - def _mock_find(*args, **kwargs): - if self.res in args[0]: - rules = _fwp['firewall_rules'] - return {'id': args[0], 'firewall_rules': rules} - return {'id': args[0]} - - self.networkclient.find_firewall_policy.side_effect = _mock_find - self.networkclient.find_firewall_rule.side_effect = _mock_find - - arglist = [ - name, - '--description', desc, - '--firewall-rule', rule1, - '--firewall-rule', rule2, - '--project', project, - '--share', - '--audited', - ] - verifylist = [ - ('name', name), - ('description', desc), - ('firewall_rule', [rule1, rule2]), - ('project', project), - ('share', True), - ('audited', True), - ] - request, response = _generate_req_and_res(verifylist) - self._update_expect_response(request, response) - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.check_results(headers, data, request) - - def test_create_with_firewall_rule_and_no(self): - name = 'my-fwp' - rule1 = 'rule1' - rule2 = 'rule2' - arglist = [ - name, - '--firewall-rule', rule1, - '--firewall-rule', rule2, - '--no-firewall-rule', - ] - verifylist = [ - ('name', name), - ('firewall_rule', [rule1, rule2]), - ('no_firewall_rule', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_shared_and_no_share(self): - name = 'my-fwp' - arglist = [ - name, - '--share', - '--no-share', - ] - verifylist = [ - ('name', name), - ('share', True), - ('no_share', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_audited_and_no(self): - name = 'my-fwp' - arglist = [ - name, - '--audited', - '--no-audited', - ] - verifylist = [ - ('name', name), - ('audited', True), - ('no_audited', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - -class TestListFirewallPolicy(TestFirewallPolicy, common.TestListFWaaS): - - def setUp(self): - super(TestListFirewallPolicy, self).setUp() - self.networkclient.firewall_policies = mock.Mock( - return_value=[_fwp]) - self.mocked = self.networkclient.firewall_policies - self.cmd = firewallpolicy.ListFirewallPolicy(self.app, self.namespace) - - -class TestShowFirewallPolicy(TestFirewallPolicy, common.TestShowFWaaS): - - def setUp(self): - super(TestShowFirewallPolicy, self).setUp() - self.networkclient.get_firewall_policy = mock.Mock( - return_value=_fwp) - self.mocked = self.networkclient.get_firewall_policy - self.cmd = firewallpolicy.ShowFirewallPolicy(self.app, self.namespace) - - -class TestSetFirewallPolicy(TestFirewallPolicy, common.TestSetFWaaS): - - def setUp(self): - super(TestSetFirewallPolicy, self).setUp() - self.networkclient.update_firewall_policy = mock.Mock( - return_value=_fwp) - self.mocked = self.networkclient.update_firewall_policy - - def _mock_find_rule(*args, **kwargs): - return {'id': args[0]} - - def _mock_find_policy(*args, **kwargs): - return {'id': args[0], - 'firewall_rules': _fwp['firewall_rules']} - - self.networkclient.find_firewall_policy.side_effect = _mock_find_policy - self.networkclient.find_firewall_rule.side_effect = _mock_find_rule - - self.cmd = firewallpolicy.SetFirewallPolicy(self.app, self.namespace) - - def test_set_rules(self): - target = self.resource['id'] - rule1 = 'new_rule1' - rule2 = 'new_rule2' - arglist = [ - target, - '--firewall-rule', rule1, - '--firewall-rule', rule2, - ] - verifylist = [ - (self.res, target), - ('firewall_rule', [rule1, rule2]), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - expect = _fwp['firewall_rules'] + [rule1, rule2] - body = {'firewall_rules': expect} - self.mocked.assert_called_once_with(target, **body) - self.assertEqual(2, self.networkclient.find_firewall_rule.call_count) - self.assertEqual(2, self.networkclient.find_firewall_policy.call_count) - self.assertIsNone(result) - - def test_set_no_rules(self): - target = self.resource['id'] - arglist = [target, '--no-firewall-rule'] - verifylist = [ - (self.res, target), - ('no_firewall_rule', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - body = {'firewall_rules': []} - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) - - def test_set_rules_and_no_rules(self): - target = self.resource['id'] - rule1 = 'rule1' - arglist = [ - target, - '--firewall-rule', rule1, - '--no-firewall-rule', - ] - verifylist = [ - (self.res, target), - ('firewall_rule', [rule1]), - ('no_firewall_rule', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - body = {'firewall_rules': [rule1]} - self.mocked.assert_called_once_with(target, **body) - self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) - self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) - self.assertIsNone(result) - - def test_set_audited(self): - target = self.resource['id'] - arglist = [target, '--audited'] - verifylist = [ - (self.res, target), - ('audited', True), - ] - body = {'audited': True} - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) - - def test_set_no_audited(self): - target = self.resource['id'] - arglist = [target, '--no-audited'] - verifylist = [ - (self.res, target), - ('no_audited', True), - ] - body = {'audited': False} - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) - - def test_set_audited_and_no_audited(self): - target = self.resource['id'] - arglist = [ - target, - '--audited', - '--no-audited', - ] - verifylist = [ - (self.res, target), - ('audited', True), - ('no_audited', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_and_raises(self): - self.networkclient.update_firewall_policy = mock.Mock( - side_effect=Exception) - target = self.resource['id'] - - arglist = [target, '--name', 'my-name'] - verifylist = [(self.res, target), ('name', 'my-name')] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) - - -class TestDeleteFirewallPolicy(TestFirewallPolicy, common.TestDeleteFWaaS): - - def setUp(self): - super(TestDeleteFirewallPolicy, self).setUp() - self.networkclient.delete_firewall_policy = mock.Mock( - return_value={self.res: _fwp}) - self.mocked = self.networkclient.delete_firewall_policy - self.cmd = firewallpolicy.DeleteFirewallPolicy( - self.app, self.namespace) - - -class TestFirewallPolicyInsertRule(TestFirewallPolicy): - - def setUp(self): - super(TestFirewallPolicyInsertRule, self).setUp() - self.networkclient.insert_rule_firewall_policy = mock.Mock( - return_value={self.res: _fwp}) - self.mocked = self.networkclient.insert_rule_into_policy - - def _mock_find_policy(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_policy.side_effect = _mock_find_policy - self.networkclient.find_firewall_rule.side_effect = _mock_find_policy - - self.cmd = firewallpolicy.FirewallPolicyInsertRule(self.app, - self.namespace) - - def test_insert_firewall_rule(self): - target = self.resource['id'] - rule = 'new-rule' - before = 'before' - after = 'after' - arglist = [ - target, - rule, - '--insert-before', before, - '--insert-after', after, - ] - verifylist = [ - (self.res, target), - ('firewall_rule', rule), - ('insert_before', before), - ('insert_after', after), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - body = { - 'firewall_rule_id': rule, - 'insert_before': before, - 'insert_after': after - } - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) - self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) - self.assertEqual(3, self.networkclient.find_firewall_rule.call_count) - - def test_insert_with_no_firewall_rule(self): - target = self.resource['id'] - arglist = [ - target, - ] - verifylist = [ - (self.res, target), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - -class TestFirewallPolicyRemoveRule(TestFirewallPolicy): - - def setUp(self): - super(TestFirewallPolicyRemoveRule, self).setUp() - self.networkclient.remove_rule_firewall_policy = mock.Mock( - return_value={self.res: _fwp}) - self.mocked = self.networkclient.remove_rule_from_policy - - def _mock_find_policy(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_policy.side_effect = _mock_find_policy - self.networkclient.find_firewall_rule.side_effect = _mock_find_policy - - self.cmd = firewallpolicy.FirewallPolicyRemoveRule(self.app, - self.namespace) - - def test_remove_firewall_rule(self): - target = self.resource['id'] - rule = 'remove-rule' - arglist = [ - target, - rule, - ] - verifylist = [ - (self.res, target), - ('firewall_rule', rule), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - body = {'firewall_rule_id': rule} - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) - self.assertEqual(1, self.networkclient.find_firewall_policy.call_count) - self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) - - def test_remove_with_no_firewall_rule(self): - target = self.resource['id'] - arglist = [ - target, - ] - verifylist = [ - (self.res, target), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - -class TestUnsetFirewallPolicy(TestFirewallPolicy, common.TestUnsetFWaaS): - - def setUp(self): - super(TestUnsetFirewallPolicy, self).setUp() - self.networkclient.update_firewall_policy = mock.Mock( - return_value={self.res: _fwp}) - self.mocked = self.networkclient.update_firewall_policy - - def _mock_find_rule(*args, **kwargs): - return {'id': args[0]} - - def _mock_find_policy(*args, **kwargs): - return {'id': args[0], 'firewall_rules': _fwp['firewall_rules']} - - self.networkclient.find_firewall_policy.side_effect = _mock_find_policy - self.networkclient.find_firewall_rule.side_effect = _mock_find_rule - - self.cmd = firewallpolicy.UnsetFirewallPolicy(self.app, self.namespace) - - def test_unset_audited(self): - target = self.resource['id'] - arglist = [ - target, - '--audited', - ] - verifylist = [ - (self.res, target), - ('audited', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - body = {'audited': False} - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) - - def test_unset_firewall_rule_not_matched(self): - _fwp['firewall_rules'] = ['old_rule'] - target = self.resource['id'] - rule = 'new_rule' - arglist = [ - target, - '--firewall-rule', rule, - ] - verifylist = [ - (self.res, target), - ('firewall_rule', [rule]), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - body = {'firewall_rules': _fwp['firewall_rules']} - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) - - def test_unset_firewall_rule_matched(self): - _fwp['firewall_rules'] = ['rule1', 'rule2'] - target = self.resource['id'] - rule = 'rule1' - arglist = [ - target, - '--firewall-rule', rule, - ] - verifylist = [ - (self.res, target), - ('firewall_rule', [rule]), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - body = {'firewall_rules': ['rule2']} - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) - self.assertEqual(2, self.networkclient.find_firewall_policy.call_count) - self.assertEqual(1, self.networkclient.find_firewall_rule.call_count) - - def test_unset_all_firewall_rule(self): - target = self.resource['id'] - arglist = [ - target, - '--all-firewall-rule', - ] - verifylist = [ - (self.res, target), - ('all_firewall_rule', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - body = {'firewall_rules': []} - self.mocked.assert_called_once_with(target, **body) - self.assertIsNone(result) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py deleted file mode 100644 index 2714fd055..000000000 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py +++ /dev/null @@ -1,904 +0,0 @@ -# Copyright 2016 FUJITSU LIMITED -# All Rights Reserved -# -# 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 re -from unittest import mock - -from osc_lib import exceptions -from osc_lib.tests import utils -import testtools - -from neutronclient.osc import utils as osc_utils -from neutronclient.osc.v2.fwaas import firewallrule -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes -from neutronclient.tests.unit.osc.v2.fwaas import common -from neutronclient.tests.unit.osc.v2.fwaas import fakes - - -_fwr = fakes.FirewallRule().create() -CONVERT_MAP = { - 'project': 'tenant_id', - 'enable_rule': 'enabled', - 'disable_rule': 'enabled', - 'share': 'shared', - 'no_share': 'shared', - 'source_firewall_group': 'source_firewall_group_id', - 'destination_firewall_group': 'destination_firewall_group_id', - 'no_source_firewall_group': 'source_firewall_group_id', - 'no_destination_firewall_group': 'destination_firewall_group_id', -} - - -def _generate_data(ordered_dict=None, data=None): - source = ordered_dict if ordered_dict else _fwr - if data: - source.update(data) - ret = tuple(_replace_display_columns(key, source[key]) for key in source) - return ret - - -def _replace_display_columns(key, val): - if key == 'protocol': - return firewallrule.ProtocolColumn(val) - return val - - -def _generate_req_and_res(verifylist): - request = dict(verifylist) - response = _fwr - for key, val in verifylist: - converted = CONVERT_MAP.get(key, key) - del request[key] - if re.match('^no_', key) and val is True: - new_value = None - elif (key == 'enable' or key == 'enable_rule') and val: - new_value = True - elif (key == 'disable' or key == 'disable_rule') and val: - new_value = False - elif (key == 'protocol' and val and val.lower() == 'any'): - new_value = None - elif val is True or val is False: - new_value = val - elif key in ('name', 'description'): - new_value = val - else: - new_value = val - request[converted] = new_value - response[converted] = new_value - return request, response - - -class TestFirewallRule(test_fakes.TestNeutronClientOSCV2): - - def check_results(self, headers, data, exp_req=None, is_list=False): - if is_list: - req_body = {self.res_plural: [exp_req]} - else: - req_body = exp_req - if not exp_req: - self.mocked.assert_called_once_with() - else: - self.mocked.assert_called_once_with(**req_body) - self.assertEqual(self.ordered_headers, headers) - - def setUp(self): - super(TestFirewallRule, self).setUp() - - osc_utils.find_project = mock.Mock() - osc_utils.find_project.id = _fwr['tenant_id'] - self.res = 'firewall_rule' - self.res_plural = 'firewall_rules' - self.resource = _fwr - self.headers = ( - 'ID', - 'Name', - 'Enabled', - 'Description', - 'Firewall Policy', - 'IP Version', - 'Action', - 'Protocol', - 'Source IP Address', - 'Source Port', - 'Destination IP Address', - 'Destination Port', - 'Shared', - 'Project', - 'Source Firewall Group ID', - 'Destination Firewall Group ID', - ) - self.data = _generate_data() - self.ordered_headers = ( - 'Action', - 'Description', - 'Destination Firewall Group ID', - 'Destination IP Address', - 'Destination Port', - 'Enabled', - 'Firewall Policy', - 'ID', - 'IP Version', - 'Name', - 'Project', - 'Protocol', - 'Shared', - 'Source Firewall Group ID', - 'Source IP Address', - 'Source Port', - 'Summary', - ) - self.ordered_data = ( - _fwr['action'], - _fwr['description'], - _fwr['destination_firewall_group_id'], - _fwr['destination_ip_address'], - _fwr['destination_port'], - _fwr['firewall_policy_id'], - _fwr['enabled'], - _fwr['id'], - _fwr['ip_version'], - _fwr['name'], - _fwr['tenant_id'], - _replace_display_columns('protocol', _fwr['protocol']), - _fwr['shared'], - _fwr['source_firewall_group_id'], - _fwr['source_ip_address'], - _fwr['source_port'], - ) - self.ordered_columns = ( - 'action', - 'description', - 'destination_firewall_group_id', - 'destination_ip_address', - 'destination_port', - 'enabled', - 'id', - 'ip_version', - 'name', - 'tenant_id', - 'protocol', - 'shared', - 'source_firewall_group_id', - 'source_ip_address', - 'source_port', - ) - - -class TestCreateFirewallRule(TestFirewallRule, common.TestCreateFWaaS): - - def setUp(self): - super(TestCreateFirewallRule, self).setUp() - self.networkclient.create_firewall_rule = mock.Mock( - return_value=_fwr) - self.mocked = self.networkclient.create_firewall_rule - - def _mock_find_group(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_group.side_effect = _mock_find_group - - self.cmd = firewallrule.CreateFirewallRule(self.app, self.namespace) - - def _update_expect_response(self, request, response): - """Set expected request and response - - :param request - A dictionary of request body(dict of verifylist) - :param response - A OrderedDict of request body - """ - # Update response body - self.networkclient.create_firewall_rule.return_value = response - osc_utils.find_project.return_value.id = response['tenant_id'] - # Update response(finally returns 'data') - self.data = _generate_data(ordered_dict=response) - self.ordered_data = tuple( - _replace_display_columns(column, response[column]) - for column in self.ordered_columns - ) - - def _set_all_params(self, args={}): - name = args.get('name') or 'my-name' - description = args.get('description') or 'my-desc' - source_ip = args.get('source_ip_address') or '192.168.1.0/24' - destination_ip = args.get('destination_ip_address') or '192.168.2.0/24' - source_port = args.get('source_port') or '0:65535' - protocol = args.get('protocol') or 'udp' - action = args.get('action') or 'deny' - ip_version = args.get('ip_version') or '4' - destination_port = args.get('destination_port') or '0:65535' - destination_firewall_group = args.get( - 'destination_firewall_group') or 'my-dst-fwg' - source_firewall_group = args.get( - 'source_firewall_group') or 'my-src-fwg' - tenant_id = args.get('tenant_id') or 'my-tenant' - arglist = [ - '--description', description, - '--name', name, - '--protocol', protocol, - '--ip-version', ip_version, - '--source-ip-address', source_ip, - '--destination-ip-address', destination_ip, - '--source-port', source_port, - '--destination-port', destination_port, - '--action', action, - '--project', tenant_id, - '--disable-rule', - '--share', - '--source-firewall-group', source_firewall_group, - '--destination-firewall-group', destination_firewall_group - ] - - verifylist = [ - ('name', name), - ('description', description), - ('share', True), - ('protocol', protocol), - ('ip_version', ip_version), - ('source_ip_address', source_ip), - ('destination_ip_address', destination_ip), - ('source_port', source_port), - ('destination_port', destination_port), - ('action', action), - ('disable_rule', True), - ('project', tenant_id), - ('source_firewall_group', source_firewall_group), - ('destination_firewall_group', destination_firewall_group) - ] - return arglist, verifylist - - def _test_create_with_all_params(self, args={}): - arglist, verifylist = self._set_all_params(args) - request, response = _generate_req_and_res(verifylist) - self._update_expect_response(request, response) - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.check_results(headers, data, request) - - def test_create_with_no_options(self): - arglist = [] - verifylist = [] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - self.check_results(headers, data, None) - - def test_create_with_all_params(self): - self._test_create_with_all_params() - - def test_create_with_all_params_protocol_any(self): - self._test_create_with_all_params({'protocol': 'any'}) - - def test_create_with_all_params_ip_version_6(self): - self._test_create_with_all_params({'ip_version': '6'}) - - def test_create_with_all_params_invalid_ip_version(self): - arglist, verifylist = self._set_all_params({'ip_version': '128'}) - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_all_params_action_upper_capitalized(self): - for action in ('Allow', 'DENY', 'Reject'): - arglist, verifylist = self._set_all_params({'action': action}) - self.assertRaises( - testtools.matchers._impl.MismatchError, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_all_params_protocol_upper_capitalized(self): - for protocol in ('TCP', 'Tcp', 'ANY', 'AnY', 'iCMp'): - arglist, verifylist = self._set_all_params({'protocol': protocol}) - self.assertRaises( - testtools.matchers._impl.MismatchError, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_src_fwg_and_no(self): - fwg = 'my-fwg' - arglist = [ - '--source-firewall-group', fwg, - '--no-source-firewall-group', - ] - verifylist = [ - ('source_firewall_group', fwg), - ('no_source_firewall_group', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_dst_fwg_and_no(self): - fwg = 'my-fwg' - arglist = [ - '--destination-firewall-group', fwg, - '--no-destination-firewall-group', - ] - verifylist = [ - ('destination_firewall_group', fwg), - ('no_destination_firewall_group', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - -class TestListFirewallRule(TestFirewallRule): - - def _setup_summary(self, expect=None): - protocol = (_fwr['protocol'] or 'any').upper() - src = 'source(port): 192.168.1.0/24(1:11111)' - dst = 'dest(port): 192.168.2.2(2:22222)' - action = 'deny' - if expect: - if expect.get('protocol'): - protocol = expect['protocol'] - if expect.get('source_ip_address'): - src_ip = expect['source_ip_address'] - if expect.get('source_port'): - src_port = expect['source_port'] - if expect.get('destination_ip_address'): - dst_ip = expect['destination_ip_address'] - if expect.get('destination_port'): - dst_port = expect['destination_port'] - if expect.get('action'): - action = expect['action'] - src = 'source(port): ' + src_ip + '(' + src_port + ')' - dst = 'dest(port): ' + dst_ip + '(' + dst_port + ')' - return ',\n '.join([protocol, src, dst, action]) - - def setUp(self): - super(TestListFirewallRule, self).setUp() - self.cmd = firewallrule.ListFirewallRule(self.app, self.namespace) - - self.short_header = ( - 'ID', - 'Name', - 'Enabled', - 'Summary', - 'Firewall Policy', - ) - - summary = self._setup_summary(_fwr) - - self.short_data = ( - _fwr['id'], - _fwr['name'], - _fwr['enabled'], - summary, - _fwr['firewall_policy_id'] - ) - self.networkclient.firewall_rules = mock.Mock( - return_value=[_fwr]) - self.mocked = self.networkclient.firewall_rules - - def test_list_with_long_option(self): - arglist = ['--long'] - verifylist = [('long', True)] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with() - self.assertEqual(list(self.headers), headers) - - def test_list_with_no_option(self): - arglist = [] - verifylist = [] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - headers, data = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with() - self.assertEqual(list(self.short_header), headers) - self.assertListItemEqual([self.short_data], list(data)) - - -class TestShowFirewallRule(TestFirewallRule, common.TestShowFWaaS): - - def setUp(self): - super(TestShowFirewallRule, self).setUp() - self.networkclient.get_firewall_rule = mock.Mock( - return_value=_fwr) - self.mocked = self.networkclient.get_firewall_rule - self.cmd = firewallrule.ShowFirewallRule(self.app, self.namespace) - - -class TestSetFirewallRule(TestFirewallRule, common.TestSetFWaaS): - - def setUp(self): - super(TestSetFirewallRule, self).setUp() - self.networkclient.update_firewall_rule = mock.Mock( - return_value=_fwr) - self.mocked = self.networkclient.update_firewall_rule - - def _mock_find_rule(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_rule.side_effect = _mock_find_rule - - self.cmd = firewallrule.SetFirewallRule(self.app, self.namespace) - - def test_set_protocol_with_any(self): - target = self.resource['id'] - protocol = 'any' - arglist = [target, '--protocol', protocol] - verifylist = [ - (self.res, target), - ('protocol', protocol), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'protocol': None}) - self.assertIsNone(result) - - def test_set_protocol_with_udp(self): - target = self.resource['id'] - protocol = 'udp' - arglist = [target, '--protocol', protocol] - verifylist = [ - (self.res, target), - ('protocol', protocol), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'protocol': protocol}) - self.assertIsNone(result) - - def test_set_source_ip_address(self): - target = self.resource['id'] - src_ip = '192.192.192.192' - arglist = [target, '--source-ip-address', src_ip] - verifylist = [ - (self.res, target), - ('source_ip_address', src_ip), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'source_ip_address': src_ip}) - self.assertIsNone(result) - - def test_set_source_port(self): - target = self.resource['id'] - src_port = '32678' - arglist = [target, '--source-port', src_port] - verifylist = [ - (self.res, target), - ('source_port', src_port), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'source_port': src_port}) - self.assertIsNone(result) - - def test_set_destination_ip_address(self): - target = self.resource['id'] - dst_ip = '0.1.0.1' - arglist = [target, '--destination-ip-address', dst_ip] - verifylist = [ - (self.res, target), - ('destination_ip_address', dst_ip), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'destination_ip_address': dst_ip}) - self.assertIsNone(result) - - def test_set_destination_port(self): - target = self.resource['id'] - dst_port = '65432' - arglist = [target, '--destination-port', dst_port] - verifylist = [ - (self.res, target), - ('destination_port', dst_port), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'destination_port': dst_port}) - self.assertIsNone(result) - - def test_set_enable_rule(self): - target = self.resource['id'] - arglist = [target, '--enable-rule'] - verifylist = [ - (self.res, target), - ('enable_rule', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'enabled': True}) - self.assertIsNone(result) - - def test_set_disable_rule(self): - target = self.resource['id'] - arglist = [target, '--disable-rule'] - verifylist = [ - (self.res, target), - ('disable_rule', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'enabled': False}) - self.assertIsNone(result) - - def test_set_action(self): - target = self.resource['id'] - action = 'reject' - arglist = [target, '--action', action] - verifylist = [ - (self.res, target), - ('action', action), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'action': action}) - self.assertIsNone(result) - - def test_set_enable_rule_and_disable_rule(self): - target = self.resource['id'] - arglist = [target, '--enable-rule', '--disable-rule'] - verifylist = [ - (self.res, target), - ('enable_rule', True), - ('disable_rule', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_no_source_ip_address(self): - target = self.resource['id'] - arglist = [ - target, - '--no-source-ip-address', - ] - verifylist = [ - (self.res, target), - ('no_source_ip_address', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'source_ip_address': None}) - self.assertIsNone(result) - - def test_set_no_source_port(self): - target = self.resource['id'] - arglist = [ - target, - '--no-source-port', - ] - verifylist = [ - (self.res, target), - ('no_source_port', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with(target, **{'source_port': None}) - self.assertIsNone(result) - - def test_set_no_destination_ip_address(self): - target = self.resource['id'] - arglist = [ - target, - '--no-destination-ip-address', - ] - verifylist = [ - (self.res, target), - ('no_destination_ip_address', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'destination_ip_address': None}) - self.assertIsNone(result) - - def test_set_no_destination_port(self): - target = self.resource['id'] - arglist = [ - target, - '--no-destination-port', - ] - verifylist = [ - (self.res, target), - ('no_destination_port', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'destination_port': None}) - self.assertIsNone(result) - - def test_set_source_ip_address_and_no(self): - target = self.resource['id'] - arglist = [ - target, - '--source-ip-address', '192.168.1.0/24', - '--no-source-ip-address', - ] - verifylist = [ - (self.res, target), - ('source_ip_address', '192.168.1.0/24'), - ('no_source_ip_address', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_destination_ip_address_and_no(self): - target = self.resource['id'] - arglist = [ - target, - '--destination-ip-address', '192.168.2.0/24', - '--no-destination-ip-address', - ] - verifylist = [ - (self.res, target), - ('destination_ip_address', '192.168.2.0/24'), - ('no_destination_ip_address', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_source_port_and_no(self): - target = self.resource['id'] - arglist = [ - target, - '--source-port', '1:12345', - '--no-source-port', - ] - verifylist = [ - (self.res, target), - ('source_port', '1:12345'), - ('no_source_port', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_destination_port_and_no(self): - target = self.resource['id'] - arglist = [ - target, - '--destination-port', '1:54321', - '--no-destination-port', - ] - verifylist = [ - (self.res, target), - ('destination_port', '1:54321'), - ('no_destination_port', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_set_and_raises(self): - self.networkclient.update_firewall_rule = mock.Mock( - side_effect=Exception) - target = self.resource['id'] - arglist = [target, '--name', 'my-name'] - verifylist = [(self.res, target), ('name', 'my-name')] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) - - def test_set_no_destination_fwg(self): - target = self.resource['id'] - arglist = [ - target, - '--no-destination-firewall-group', - ] - verifylist = [ - (self.res, target), - ('no_destination_firewall_group', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'destination_firewall_group_id': None}) - self.assertIsNone(result) - - def test_set_no_source_fwg(self): - target = self.resource['id'] - arglist = [ - target, - '--no-source-firewall-group', - ] - verifylist = [ - (self.res, target), - ('no_source_firewall_group', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'source_firewall_group_id': None}) - self.assertIsNone(result) - - def test_create_with_src_fwg_and_no(self): - target = self.resource['id'] - fwg = 'my-fwg' - arglist = [ - target, - '--source-firewall-group', fwg, - '--no-source-firewall-group', - ] - verifylist = [ - (self.res, target), - ('source_firewall_group', fwg), - ('no_source_firewall_group', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - def test_create_with_dst_fwg_and_no(self): - target = self.resource['id'] - fwg = 'my-fwg' - arglist = [ - target, - '--destination-firewall-group', fwg, - '--no-destination-firewall-group', - ] - verifylist = [ - (self.res, target), - ('destination_firewall_group', fwg), - ('no_destination_firewall_group', True), - ] - self.assertRaises( - utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) - - -class TestUnsetFirewallRule(TestFirewallRule, common.TestUnsetFWaaS): - - def setUp(self): - super(TestUnsetFirewallRule, self).setUp() - self.networkclient.update_firewall_rule = mock.Mock( - return_value={self.res: _fwr}) - self.mocked = self.networkclient.update_firewall_rule - - def _mock_find_rule(*args, **kwargs): - return {'id': args[0]} - - self.networkclient.find_firewall_rule.side_effect = _mock_find_rule - - self.cmd = firewallrule.UnsetFirewallRule(self.app, self.namespace) - - def test_unset_protocol_and_raise(self): - self.networkclient.update_firewall_rule.side_effect = Exception - target = self.resource['id'] - arglist = [ - target, - '--protocol', - ] - verifylist = [ - (self.res, target), - ('protocol', False) - ] - self.assertRaises(utils.ParserException, self.check_parser, - self.cmd, arglist, verifylist) - - def test_unset_source_port(self): - target = self.resource['id'] - arglist = [ - target, - '--source-port', - ] - verifylist = [ - (self.res, target), - ('source_port', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'source_port': None}) - self.assertIsNone(result) - - def test_unset_destination_port(self): - target = self.resource['id'] - arglist = [ - target, - '--destination-port', - ] - verifylist = [ - (self.res, target), - ('destination_port', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'destination_port': None}) - self.assertIsNone(result) - - def test_unset_source_ip_address(self): - target = self.resource['id'] - arglist = [ - target, - '--source-ip-address', - ] - verifylist = [ - (self.res, target), - ('source_ip_address', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'source_ip_address': None}) - self.assertIsNone(result) - - def test_unset_destination_ip_address(self): - target = self.resource['id'] - arglist = [ - target, - '--destination-ip-address', - ] - verifylist = [ - (self.res, target), - ('destination_ip_address', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'destination_ip_address': None}) - self.assertIsNone(result) - - def test_unset_enable_rule(self): - target = self.resource['id'] - arglist = [ - target, - '--enable-rule', - ] - verifylist = [ - (self.res, target), - ('enable_rule', True), - ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.mocked.assert_called_once_with( - target, **{'enabled': False}) - self.assertIsNone(result) - - -class TestDeleteFirewallRule(TestFirewallRule, common.TestDeleteFWaaS): - - def setUp(self): - super(TestDeleteFirewallRule, self).setUp() - self.networkclient.delete_firewall_rule = mock.Mock(return_value=_fwr) - self.mocked = self.networkclient.delete_firewall_rule - self.cmd = firewallrule.DeleteFirewallRule(self.app, self.namespace) diff --git a/releasenotes/notes/remove-fwaas-osc-plugin-a1b2c3d4e5f6g7h8.yaml b/releasenotes/notes/remove-fwaas-osc-plugin-a1b2c3d4e5f6g7h8.yaml new file mode 100644 index 000000000..171b3eb62 --- /dev/null +++ b/releasenotes/notes/remove-fwaas-osc-plugin-a1b2c3d4e5f6g7h8.yaml @@ -0,0 +1,11 @@ +--- +deprecations: + - | + The Firewall as a Service (FWaaS) v2 OSC plugin commands have been moved + to ``python-openstackclient``. The FWaaS commands are no longer provided + by ``python-neutronclient``. Please use ``python-openstackclient`` for + the following commands: + + * ``firewall group create/delete/list/set/show/unset`` + * ``firewall group policy create/delete/list/set/show/unset/add rule/remove rule`` + * ``firewall group rule create/delete/list/set/show/unset`` diff --git a/setup.cfg b/setup.cfg index 3005e895b..282919044 100644 --- a/setup.cfg +++ b/setup.cfg @@ -79,27 +79,6 @@ openstack.neutronclient.v2 = bgp_speaker_set = neutronclient.osc.v2.dynamic_routing.bgp_speaker:SetBgpSpeaker bgp_speaker_show = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ShowBgpSpeaker - firewall_group_create = neutronclient.osc.v2.fwaas.firewallgroup:CreateFirewallGroup - firewall_group_delete = neutronclient.osc.v2.fwaas.firewallgroup:DeleteFirewallGroup - firewall_group_list = neutronclient.osc.v2.fwaas.firewallgroup:ListFirewallGroup - firewall_group_set = neutronclient.osc.v2.fwaas.firewallgroup:SetFirewallGroup - firewall_group_show = neutronclient.osc.v2.fwaas.firewallgroup:ShowFirewallGroup - firewall_group_unset = neutronclient.osc.v2.fwaas.firewallgroup:UnsetFirewallGroup - firewall_group_policy_create = neutronclient.osc.v2.fwaas.firewallpolicy:CreateFirewallPolicy - firewall_group_policy_delete = neutronclient.osc.v2.fwaas.firewallpolicy:DeleteFirewallPolicy - firewall_group_policy_add_rule = neutronclient.osc.v2.fwaas.firewallpolicy:FirewallPolicyInsertRule - firewall_group_policy_list = neutronclient.osc.v2.fwaas.firewallpolicy:ListFirewallPolicy - firewall_group_policy_remove_rule = neutronclient.osc.v2.fwaas.firewallpolicy:FirewallPolicyRemoveRule - firewall_group_policy_set = neutronclient.osc.v2.fwaas.firewallpolicy:SetFirewallPolicy - firewall_group_policy_show = neutronclient.osc.v2.fwaas.firewallpolicy:ShowFirewallPolicy - firewall_group_policy_unset = neutronclient.osc.v2.fwaas.firewallpolicy:UnsetFirewallPolicy - firewall_group_rule_create = neutronclient.osc.v2.fwaas.firewallrule:CreateFirewallRule - firewall_group_rule_delete = neutronclient.osc.v2.fwaas.firewallrule:DeleteFirewallRule - firewall_group_rule_list = neutronclient.osc.v2.fwaas.firewallrule:ListFirewallRule - firewall_group_rule_set = neutronclient.osc.v2.fwaas.firewallrule:SetFirewallRule - firewall_group_rule_show = neutronclient.osc.v2.fwaas.firewallrule:ShowFirewallRule - firewall_group_rule_unset = neutronclient.osc.v2.fwaas.firewallrule:UnsetFirewallRule - bgpvpn_create = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:CreateBgpvpn bgpvpn_delete = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:DeleteBgpvpn bgpvpn_list = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:ListBgpvpn From 9d338dc92ac51d78809c7a9d4d6ccdc603837039 Mon Sep 17 00:00:00 2001 From: lajoskatona Date: Wed, 25 Feb 2026 16:36:12 +0100 Subject: [PATCH 149/149] Remove bgpvpn client code The team agreed to move these client codes to OSC see the depends-on patch. Depends-On: https://review.opendev.org/c/openstack/python-openstackclient/+/977974 Change-Id: Ic0778a0d48f600af8997cac8b6fbab32d6365fab Signed-off-by: lajoskatona --- doc/source/cli/osc/v2/networking-bgpvpn.rst | 37 -- .../osc/v2/networking_bgpvpn/__init__.py | 0 .../osc/v2/networking_bgpvpn/bgpvpn.py | 406 -------------- .../osc/v2/networking_bgpvpn/constants.py | 30 - .../networking_bgpvpn/network_association.py | 63 --- .../v2/networking_bgpvpn/port_association.py | 314 ----------- .../networking_bgpvpn/resource_association.py | 283 ---------- .../networking_bgpvpn/router_association.py | 113 ---- .../unit/osc/v2/networking_bgpvpn/__init__.py | 0 .../unit/osc/v2/networking_bgpvpn/fakes.py | 270 --------- .../osc/v2/networking_bgpvpn/test_bgpvpn.py | 524 ------------------ .../test_resource_association.py | 320 ----------- .../test_router_association.py | 292 ---------- setup.cfg | 22 - 14 files changed, 2674 deletions(-) delete mode 100644 doc/source/cli/osc/v2/networking-bgpvpn.rst delete mode 100644 neutronclient/osc/v2/networking_bgpvpn/__init__.py delete mode 100644 neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py delete mode 100644 neutronclient/osc/v2/networking_bgpvpn/constants.py delete mode 100644 neutronclient/osc/v2/networking_bgpvpn/network_association.py delete mode 100644 neutronclient/osc/v2/networking_bgpvpn/port_association.py delete mode 100644 neutronclient/osc/v2/networking_bgpvpn/resource_association.py delete mode 100644 neutronclient/osc/v2/networking_bgpvpn/router_association.py delete mode 100644 neutronclient/tests/unit/osc/v2/networking_bgpvpn/__init__.py delete mode 100644 neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py delete mode 100644 neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py delete mode 100644 neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py delete mode 100644 neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py diff --git a/doc/source/cli/osc/v2/networking-bgpvpn.rst b/doc/source/cli/osc/v2/networking-bgpvpn.rst deleted file mode 100644 index 46ee47e6e..000000000 --- a/doc/source/cli/osc/v2/networking-bgpvpn.rst +++ /dev/null @@ -1,37 +0,0 @@ -====== -bgpvpn -====== - -A **bgpvpn** resource contains a set of parameters to define a BGP-based VPN. -BGP-based IP VPNs networks are widely used in the industry especially for -enterprises. The networking BGP VPN project aims at supporting inter-connection -between L3VPNs and Neutron resources, i.e. Networks, Routers and Ports. - -Network v2 - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn create - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn delete - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn list - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn set - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn show - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn unset - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn network association * - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn router association * - -.. autoprogram-cliff:: openstack.neutronclient.v2 - :command: bgpvpn port association * diff --git a/neutronclient/osc/v2/networking_bgpvpn/__init__.py b/neutronclient/osc/v2/networking_bgpvpn/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py b/neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py deleted file mode 100644 index cf4c69d66..000000000 --- a/neutronclient/osc/v2/networking_bgpvpn/bgpvpn.py +++ /dev/null @@ -1,406 +0,0 @@ -# Copyright (c) 2016 Juniper Networks Inc. -# All Rights Reserved. -# -# 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 logging - -from osc_lib.cli import format_columns -from osc_lib.cli.parseractions import KeyValueAction -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.osc import utils as nc_osc_utils - -LOG = logging.getLogger(__name__) - -_attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('project_id', 'Project', column_util.LIST_LONG_ONLY), - ('name', 'Name', column_util.LIST_BOTH), - ('type', 'Type', column_util.LIST_BOTH), - ('route_targets', 'Route Targets', column_util.LIST_LONG_ONLY), - ('import_targets', 'Import Targets', column_util.LIST_LONG_ONLY), - ('export_targets', 'Export Targets', column_util.LIST_LONG_ONLY), - ('route_distinguishers', 'Route Distinguishers', - column_util.LIST_LONG_ONLY), - ('networks', 'Associated Networks', column_util.LIST_LONG_ONLY), - ('routers', 'Associated Routers', column_util.LIST_LONG_ONLY), - ('ports', 'Associated Ports', column_util.LIST_LONG_ONLY), - ('vni', 'VNI', column_util.LIST_LONG_ONLY), - ('local_pref', 'Local Pref', column_util.LIST_LONG_ONLY), -) -_formatters = { - 'route_targets': format_columns.ListColumn, - 'import_targets': format_columns.ListColumn, - 'export_targets': format_columns.ListColumn, - 'route_distinguishers': format_columns.ListColumn, - 'networks': format_columns.ListColumn, - 'routers': format_columns.ListColumn, - 'ports': format_columns.ListColumn, -} - - -def _get_common_parser(parser, update=None): - """Adds to parser arguments common to create, set and unset commands. - - :params ArgumentParser parser: argparse object contains all command's - arguments - :params string update: Determines if it is a create command (value: None), - it is a set command (value: 'set') or if it is an - unset command (value: 'unset') - """ - ADD_RT = _("Add Route Target to import/export list") - REMOVE_RT = _("Remove Route Target from import/export list") - ADD_IMPORT_RT = _("Add Route Target to import list") - REMOVE_IMPORT_RT = _("Remove Route Target from import list") - ADD_EXPORT_RT = _("Add Route Target to export list") - REMOVE_EXPORT_RT = _("Remove Route Target from export list") - ADD_RD = _("Add Route Distinguisher to the list of Route Distinguishers " - "from which a Route Distinguishers will be picked from to " - "advertise a VPN route") - REMOVE_RD = _("Remove Route Distinguisher from the list of Route " - "Distinguishers from which a Route Distinguishers will be " - "picked from to advertise a VPN route") - REPEAT_RT = _("repeat option for multiple Route Targets") - REPEAT_RD = _("repeat option for multiple Route Distinguishers") - - def is_appended(): - return update is None or update == 'set' - - if update is None or update == 'set': - parser.add_argument( - '--name', - metavar="", - help=_("Name of the BGP VPN"), - ) - parser.add_argument( - '--route-target', - dest='route_targets', - action='append', - metavar="", - help="%s (%s)" % ((ADD_RT if is_appended() else REMOVE_RT), REPEAT_RT), - ) - if update: - parser.add_argument( - '--no-route-target' if update == 'set' else '--all-route-target', - dest='purge_route_target', - action='store_true', - help=_('Empty route target list'), - ) - parser.add_argument( - '--import-target', - dest='import_targets', - action='append', - metavar="", - help="%s (%s)" % ((ADD_IMPORT_RT if is_appended() else - REMOVE_IMPORT_RT), REPEAT_RT), - ) - if update: - parser.add_argument( - '--no-import-target' if update == 'set' else '--all-import-target', - dest='purge_import_target', - action='store_true', - help=_('Empty import route target list'), - ) - parser.add_argument( - '--export-target', - dest='export_targets', - action='append', - metavar="", - help="%s (%s)" % ((ADD_EXPORT_RT if is_appended() else - REMOVE_EXPORT_RT), REPEAT_RT), - ) - if update: - parser.add_argument( - '--no-export-target' if update == 'set' else - '--all-export-target', - dest='purge_export_target', - action='store_true', - help=_('Empty export route target list'), - ) - parser.add_argument( - '--route-distinguisher', - dest='route_distinguishers', - action='append', - metavar="", - help="%s (%s)" % ((ADD_RD if is_appended() else REMOVE_RD), REPEAT_RD), - ) - if update: - parser.add_argument( - '--no-route-distinguisher' if update == 'set' else - '--all-route-distinguisher', - dest='purge_route_distinguisher', - action='store_true', - help=_('Empty route distinguisher list'), - ) - parser.add_argument( - '--vni', type=int, - help=_('VXLAN Network Identifier to be used for this BGPVPN ' - 'when a VXLAN encapsulation is used')) - parser.add_argument( - '--local-pref', type=int, - dest='local_pref', - help=_('Default BGP LOCAL_PREF to use in route advertisements' - 'towards this BGPVPN.')) - - -def _args2body(client_manager, id, action, args): - - if (not (args.purge_route_target and args.purge_import_target and - args.purge_export_target and args.purge_route_distinguisher) and - (args.route_targets or args.import_targets or - args.export_targets or args.route_distinguishers)): - bgpvpn = client_manager.network.get_bgpvpn(id) - - attrs = {} - - if 'name' in args and args.name is not None: - attrs['name'] = str(args.name) - - if 'vni' in args and args.vni is not None: - attrs['vni'] = args.vni - - if 'local_pref' in args and args.local_pref is not None: - attrs['local_pref'] = args.local_pref - - if args.purge_route_target: - attrs['route_targets'] = [] - elif args.route_targets: - if action == 'set': - attrs['route_targets'] = list(set(bgpvpn['route_targets']) | - set(args.route_targets)) - elif action == 'unset': - attrs['route_targets'] = list(set(bgpvpn['route_targets']) - - set(args.route_targets)) - - if args.purge_import_target: - attrs['import_targets'] = [] - elif args.import_targets: - if action == 'set': - attrs['import_targets'] = list(set(bgpvpn['import_targets']) | - set(args.import_targets)) - elif action == 'unset': - attrs['import_targets'] = list(set(bgpvpn['import_targets']) - - set(args.import_targets)) - - if args.purge_export_target: - attrs['export_targets'] = [] - elif args.export_targets: - if action == 'set': - attrs['export_targets'] = list(set(bgpvpn['export_targets']) | - set(args.export_targets)) - elif action == 'unset': - attrs['export_targets'] = list(set(bgpvpn['export_targets']) - - set(args.export_targets)) - - if args.purge_route_distinguisher: - attrs['route_distinguishers'] = [] - elif args.route_distinguishers: - if action == 'set': - attrs['route_distinguishers'] = list( - set(bgpvpn['route_distinguishers']) | - set(args.route_distinguishers)) - elif action == 'unset': - attrs['route_distinguishers'] = list( - set(bgpvpn['route_distinguishers']) - - set(args.route_distinguishers)) - - return attrs - - -class CreateBgpvpn(command.ShowOne): - _description = _("Create BGP VPN resource") - - def get_parser(self, prog_name): - parser = super(CreateBgpvpn, self).get_parser(prog_name) - nc_osc_utils.add_project_owner_option_to_parser(parser) - _get_common_parser(parser) - parser.add_argument( - '--type', - default='l3', - choices=['l2', 'l3'], - help=_("BGP VPN type selection between IP VPN (l3) and Ethernet " - "VPN (l2) (default: l3)"), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - attrs = {} - if parsed_args.name is not None: - attrs['name'] = str(parsed_args.name) - if parsed_args.type is not None: - attrs['type'] = parsed_args.type - if parsed_args.route_targets is not None: - attrs['route_targets'] = parsed_args.route_targets - if parsed_args.import_targets is not None: - attrs['import_targets'] = parsed_args.import_targets - if parsed_args.export_targets is not None: - attrs['export_targets'] = parsed_args.export_targets - if parsed_args.route_distinguishers is not None: - attrs['route_distinguishers'] = parsed_args.route_distinguishers - if parsed_args.vni is not None: - attrs['vni'] = parsed_args.vni - if parsed_args.local_pref is not None: - attrs['local_pref'] = parsed_args.local_pref - if 'project' in parsed_args and parsed_args.project is not None: - project_id = nc_osc_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - attrs['tenant_id'] = project_id - obj = client.create_bgpvpn(**attrs) - display_columns, columns = nc_osc_utils._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns, - formatters=_formatters) - return display_columns, data - - -class SetBgpvpn(command.Command): - _description = _("Set BGP VPN properties") - - def get_parser(self, prog_name): - parser = super(SetBgpvpn, self).get_parser(prog_name) - parser.add_argument( - 'bgpvpn', - metavar="", - help=_("BGP VPN to update (name or ID)"), - ) - _get_common_parser(parser, update='set') - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] - body = _args2body(self.app.client_manager, id, 'set', parsed_args) - client.update_bgpvpn(id, **body) - - -class UnsetBgpvpn(command.Command): - _description = _("Unset BGP VPN properties") - - def get_parser(self, prog_name): - parser = super(UnsetBgpvpn, self).get_parser(prog_name) - parser.add_argument( - 'bgpvpn', - metavar="", - help=_("BGP VPN to update (name or ID)"), - ) - _get_common_parser(parser, update='unset') - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] - body = _args2body(self.app.client_manager, id, 'unset', parsed_args) - client.update_bgpvpn(id, **body) - - -class DeleteBgpvpn(command.Command): - _description = _("Delete BGP VPN resource(s)") - - def get_parser(self, prog_name): - parser = super(DeleteBgpvpn, self).get_parser(prog_name) - parser.add_argument( - 'bgpvpns', - metavar="", - nargs="+", - help=_("BGP VPN(s) to delete (name or ID)"), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - fails = 0 - for id_or_name in parsed_args.bgpvpns: - try: - id = client.find_bgpvpn(id_or_name)['id'] - client.delete_bgpvpn(id) - LOG.warning("BGP VPN %(id)s deleted", {'id': id}) - except Exception as e: - fails += 1 - LOG.error("Failed to delete BGP VPN with name or ID " - "'%(id_or_name)s': %(e)s", - {'id_or_name': id_or_name, 'e': e}) - if fails > 0: - msg = (_("Failed to delete %(fails)s of %(total)s BGP VPN.") % - {'fails': fails, 'total': len(parsed_args.bgpvpns)}) - raise exceptions.CommandError(msg) - - -class ListBgpvpn(command.Lister): - _description = _("List BGP VPN resources") - - def get_parser(self, prog_name): - parser = super(ListBgpvpn, self).get_parser(prog_name) - nc_osc_utils.add_project_owner_option_to_parser(parser) - parser.add_argument( - '--long', - action='store_true', - help=_("List additional fields in output"), - ) - parser.add_argument( - '--property', - metavar="", - default=dict(), - help=_("Filter property to apply on returned BGP VPNs (repeat to " - "filter on multiple properties)"), - action=KeyValueAction, - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - params = {} - if parsed_args.project is not None: - project_id = nc_osc_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - params['tenant_id'] = project_id - if parsed_args.property: - params.update(parsed_args.property) - objs = client.bgpvpns(**params) - headers, columns = column_util.get_column_definitions( - _attr_map, long_listing=parsed_args.long) - return (headers, (osc_utils.get_dict_properties( - s, columns, formatters=_formatters) for s in objs)) - - -class ShowBgpvpn(command.ShowOne): - _description = _("Show information of a given BGP VPN") - - def get_parser(self, prog_name): - parser = super(ShowBgpvpn, self).get_parser(prog_name) - parser.add_argument( - 'bgpvpn', - metavar="", - help=_("BGP VPN to display (name or ID)"), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - id = client.find_bgpvpn(parsed_args.bgpvpn)['id'] - obj = client.get_bgpvpn(id) - display_columns, columns = nc_osc_utils._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns, - formatters=_formatters) - return display_columns, data diff --git a/neutronclient/osc/v2/networking_bgpvpn/constants.py b/neutronclient/osc/v2/networking_bgpvpn/constants.py deleted file mode 100644 index 7de1329a6..000000000 --- a/neutronclient/osc/v2/networking_bgpvpn/constants.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2016 Juniper Networks Inc. -# All Rights Reserved. -# -# 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. -# - -BGPVPN = 'bgpvpn' -BGPVPNS = '%ss' % BGPVPN - -NETWORK_RESOURCE_NAME = 'network' -NETWORK_ASSOC = '%s_association' % NETWORK_RESOURCE_NAME -NETWORK_ASSOCS = '%ss' % NETWORK_ASSOC - -ROUTER_RESOURCE_NAME = 'router' -ROUTER_ASSOC = '%s_association' % ROUTER_RESOURCE_NAME -ROUTER_ASSOCS = '%ss' % ROUTER_ASSOC - -PORT_RESOURCE_NAME = 'port' -PORT_ASSOC = '%s_association' % PORT_RESOURCE_NAME -PORT_ASSOCS = '%ss' % PORT_ASSOC diff --git a/neutronclient/osc/v2/networking_bgpvpn/network_association.py b/neutronclient/osc/v2/networking_bgpvpn/network_association.py deleted file mode 100644 index 05c44320e..000000000 --- a/neutronclient/osc/v2/networking_bgpvpn/network_association.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2016 Juniper Networks Inc. -# All Rights Reserved. -# -# 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. -# - -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.osc.v2.networking_bgpvpn import constants -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - CreateBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - DeleteBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - ListBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - ShowBgpvpnResAssoc - - -class BgpvpnNetAssoc(object): - _assoc_res_name = constants.NETWORK_RESOURCE_NAME - _resource = constants.NETWORK_ASSOC - _resource_plural = constants.NETWORK_ASSOCS - - _attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), - ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), - column_util.LIST_BOTH), - ) - _formatters = {} - - -class CreateBgpvpnNetAssoc(BgpvpnNetAssoc, CreateBgpvpnResAssoc): - _description = _("Create a BGP VPN network association") - pass - - -class DeleteBgpvpnNetAssoc(BgpvpnNetAssoc, DeleteBgpvpnResAssoc): - _description = _("Delete a BGP VPN network association(s) for a given BGP " - "VPN") - pass - - -class ListBgpvpnNetAssoc(BgpvpnNetAssoc, ListBgpvpnResAssoc): - _description = _("List BGP VPN network associations for a given BGP VPN") - pass - - -class ShowBgpvpnNetAssoc(BgpvpnNetAssoc, ShowBgpvpnResAssoc): - _description = _("Show information of a given BGP VPN network association") - pass diff --git a/neutronclient/osc/v2/networking_bgpvpn/port_association.py b/neutronclient/osc/v2/networking_bgpvpn/port_association.py deleted file mode 100644 index 24cd2d207..000000000 --- a/neutronclient/osc/v2/networking_bgpvpn/port_association.py +++ /dev/null @@ -1,314 +0,0 @@ -# Copyright (c) 2017 Juniper networks Inc. -# All Rights Reserved. -# -# 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 logging - -from osc_lib.cli import format_columns -from osc_lib.cli import parseractions -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.osc.v2.networking_bgpvpn import constants -from neutronclient.osc.v2.networking_bgpvpn import resource_association - -LOG = logging.getLogger(__name__) - - -class BgpvpnPortAssoc(object): - _assoc_res_name = constants.PORT_RESOURCE_NAME - _resource = constants.PORT_ASSOC - _resource_plural = constants.PORT_ASSOCS - - _attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), - ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), - column_util.LIST_BOTH), - ('prefix_routes', 'Prefix Routes (BGP LOCAL_PREF)', - column_util.LIST_LONG_ONLY), - ('bgpvpn_routes', 'BGP VPN Routes (BGP LOCAL_PREF)', - column_util.LIST_LONG_ONLY), - ('advertise_fixed_ips', "Advertise Port's Fixed IPs", - column_util.LIST_LONG_ONLY), - ) - _formatters = { - 'prefix_routes': format_columns.ListColumn, - 'bgpvpn_routes': format_columns.ListColumn, - } - - def _transform_resource(self, data): - """Transforms BGP VPN port association routes property - - That permits to easily format the command output with ListColumn - formater and separate the two route types. - - {'routes': - [ - { - 'type': 'prefix', - 'local_pref': 100, - 'prefix': '8.8.8.0/27', - }, - { - 'type': 'prefix', - 'local_pref': 42, - 'prefix': '80.50.30.0/28', - }, - { - 'type': 'bgpvpn', - 'local_pref': 50, - 'bgpvpn': '157d72a9-9968-48e7-8087-6c9a9bc7a181', - }, - { - 'type': 'bgpvpn', - 'bgpvpn': 'd5c7aaab-c7e8-48b3-85ca-a115c00d3603', - }, - ], - } - - to - - { - 'prefix_routes': [ - '8.8.8.0/27 (100)', - '80.50.30.0/28 (42)', - ], - 'bgpvpn_routes': [ - '157d72a9-9968-48e7-8087-6c9a9bc7a181 (50)', - 'd5c7aaab-c7e8-48b3-85ca-a115c00d3603', - ], - } - """ - for route in data.get('routes', []): - local_pref = '' - if route.get('local_pref'): - local_pref = ' (%d)' % route.get('local_pref') - if route['type'] == 'prefix': - data.setdefault('prefix_routes', []).append( - '%s%s' % (route['prefix'], local_pref) - ) - elif route['type'] == 'bgpvpn': - data.setdefault('bgpvpn_routes', []).append( - '%s%s' % (route['bgpvpn_id'], local_pref) - ) - else: - LOG.warning("Unknown route type %s (%s).", route['type'], - route) - data.pop('routes', None) - return data - - def _get_common_parser(self, parser): - """Adds to parser arguments common to create, set and unset commands. - - :params ArgumentParser parser: argparse object contains all command's - arguments - """ - ADVERTISE_ROUTE = _("Fixed IPs of the port will be advertised to the " - "BGP VPN%s") % ( - _(' (default)') if self._action == 'create' - else "") - NOT_ADVERTISE_ROUTE = _("Fixed IPs of the port will not be advertised " - "to the BGP VPN") - - LOCAL_PREF_VALUE = _(". Optionally, can control the value of the BGP " - "LOCAL_PREF of the routes that will be " - "advertised") - - ADD_PREFIX_ROUTE = _("Add prefix route in CIDR notation%s") %\ - LOCAL_PREF_VALUE - REMOVE_PREFIX_ROUTE = _("Remove prefix route in CIDR notation") - REPEAT_PREFIX_ROUTE = _("repeat option for multiple prefix routes") - - ADD_BGVPVPN_ROUTE = _("Add BGP VPN route for route leaking%s") %\ - LOCAL_PREF_VALUE - REMOVE_BGPVPN_ROUTE = _("Remove BGP VPN route") - REPEAT_BGPVPN_ROUTE = _("repeat option for multiple BGP VPN routes") - - group_advertise_fixed_ips = parser.add_mutually_exclusive_group() - group_advertise_fixed_ips.add_argument( - '--advertise-fixed-ips', - action='store_true', - help=NOT_ADVERTISE_ROUTE if self._action == 'unset' - else ADVERTISE_ROUTE, - ) - group_advertise_fixed_ips.add_argument( - '--no-advertise-fixed-ips', - action='store_true', - help=ADVERTISE_ROUTE if self._action == 'unset' - else NOT_ADVERTISE_ROUTE, - ) - - if self._action in ['create', 'set']: - parser.add_argument( - '--prefix-route', - metavar="prefix=[,local_pref=]", - dest='prefix_routes', - action=parseractions.MultiKeyValueAction, - required_keys=['prefix'], - optional_keys=['local_pref'], - help="%s (%s)" % (ADD_PREFIX_ROUTE, REPEAT_PREFIX_ROUTE), - ) - parser.add_argument( - '--bgpvpn-route', - metavar="bgpvpn=[,local_pref=]", - dest='bgpvpn_routes', - action=parseractions.MultiKeyValueAction, - required_keys=['bgpvpn'], - optional_keys=['local_pref'], - help="%s (%s)" % (ADD_BGVPVPN_ROUTE, REPEAT_BGPVPN_ROUTE), - ) - else: - parser.add_argument( - '--prefix-route', - metavar="", - dest='prefix_routes', - action='append', - help="%s (%s)" % (REMOVE_PREFIX_ROUTE, REPEAT_PREFIX_ROUTE), - ) - parser.add_argument( - '--bgpvpn-route', - metavar="", - dest='bgpvpn_routes', - action='append', - help="%s (%s)" % (REMOVE_BGPVPN_ROUTE, REPEAT_BGPVPN_ROUTE), - ) - if self._action != 'create': - parser.add_argument( - '--no-prefix-route' if self._action == 'set' else - '--all-prefix-routes', - dest='purge_prefix_route', - action='store_true', - help=_('Empty prefix route list'), - ) - parser.add_argument( - '--no-bgpvpn-route' if self._action == 'set' else - '--all-bgpvpn-routes', - dest='purge_bgpvpn_route', - action='store_true', - help=_('Empty BGP VPN route list'), - ) - - def _args2body(self, bgpvpn_id, args): - client = self.app.client_manager.network - attrs = {} - - if self._action != 'create': - assoc = client.find_bgpvpn_port_association( - args.resource_association_id, - bgpvpn_id=bgpvpn_id) - else: - assoc = {'routes': []} - - if args.advertise_fixed_ips: - attrs['advertise_fixed_ips'] = self._action != 'unset' - elif args.no_advertise_fixed_ips: - attrs['advertise_fixed_ips'] = self._action == 'unset' - - prefix_routes = None - if 'purge_prefix_route' in args and args.purge_prefix_route: - prefix_routes = [] - else: - prefix_routes = {r['prefix']: r.get('local_pref') - for r in assoc['routes'] - if r['type'] == 'prefix'} - if args.prefix_routes: - if self._action in ['create', 'set']: - prefix_routes.update({r['prefix']: r.get('local_pref') - for r in args.prefix_routes}) - elif self._action == 'unset': - for prefix in args.prefix_routes: - prefix_routes.pop(prefix, None) - - bgpvpn_routes = None - if 'purge_bgpvpn_route' in args and args.purge_bgpvpn_route: - bgpvpn_routes = [] - else: - bgpvpn_routes = {r['bgpvpn_id']: r.get('local_pref') - for r in assoc['routes'] - if r['type'] == 'bgpvpn'} - if args.bgpvpn_routes: - if self._action == 'unset': - routes = [ - {'bgpvpn': bgpvpn} for bgpvpn in args.bgpvpn_routes - ] - else: - routes = args.bgpvpn_routes - args_bgpvpn_routes = { - client.find_bgpvpn(r['bgpvpn']).id: - r.get('local_pref') - for r in routes - } - if self._action in ['create', 'set']: - bgpvpn_routes.update(args_bgpvpn_routes) - elif self._action == 'unset': - for bgpvpn_id in args_bgpvpn_routes: - bgpvpn_routes.pop(bgpvpn_id, None) - - if prefix_routes is not None and not prefix_routes: - attrs.setdefault('routes', []) - elif prefix_routes is not None: - for prefix, local_pref in prefix_routes.items(): - route = { - 'type': 'prefix', - 'prefix': prefix, - } - if local_pref: - route['local_pref'] = int(local_pref) - attrs.setdefault('routes', []).append(route) - if bgpvpn_routes is not None and not bgpvpn_routes: - attrs.setdefault('routes', []) - elif bgpvpn_routes is not None: - for bgpvpn_id, local_pref in bgpvpn_routes.items(): - route = { - 'type': 'bgpvpn', - 'bgpvpn_id': bgpvpn_id, - } - if local_pref: - route['local_pref'] = int(local_pref) - attrs.setdefault('routes', []).append(route) - - return attrs - - -class CreateBgpvpnPortAssoc(BgpvpnPortAssoc, - resource_association.CreateBgpvpnResAssoc): - _description = _("Create a BGP VPN port association") - - -class SetBgpvpnPortAssoc(BgpvpnPortAssoc, - resource_association.SetBgpvpnResAssoc): - _description = _("Set BGP VPN port association properties") - - -class UnsetBgpvpnPortAssoc(BgpvpnPortAssoc, - resource_association.UnsetBgpvpnResAssoc): - _description = _("Unset BGP VPN port association properties") - - -class DeleteBgpvpnPortAssoc(BgpvpnPortAssoc, - resource_association.DeleteBgpvpnResAssoc): - _description = _("Delete a BGP VPN port association(s) for a given BGP " - "VPN") - - -class ListBgpvpnPortAssoc(BgpvpnPortAssoc, - resource_association.ListBgpvpnResAssoc): - _description = _("List BGP VPN port associations for a given BGP VPN") - - -class ShowBgpvpnPortAssoc(BgpvpnPortAssoc, - resource_association.ShowBgpvpnResAssoc): - _description = _("Show information of a given BGP VPN port association") diff --git a/neutronclient/osc/v2/networking_bgpvpn/resource_association.py b/neutronclient/osc/v2/networking_bgpvpn/resource_association.py deleted file mode 100644 index 83ac7d99f..000000000 --- a/neutronclient/osc/v2/networking_bgpvpn/resource_association.py +++ /dev/null @@ -1,283 +0,0 @@ -# Copyright (c) 2016 Juniper Networks Inc. -# All Rights Reserved. -# -# 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 logging - -from osc_lib.cli import parseractions -from osc_lib.command import command -from osc_lib import exceptions -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.osc import utils as nc_osc_utils -from neutronclient.osc.v2.networking_bgpvpn import constants - -LOG = logging.getLogger(__name__) - - -class CreateBgpvpnResAssoc(command.ShowOne): - """Create a BGP VPN resource association""" - _action = 'create' - - def get_parser(self, prog_name): - parser = super(CreateBgpvpnResAssoc, self).get_parser(prog_name) - nc_osc_utils.add_project_owner_option_to_parser(parser) - parser.add_argument( - 'bgpvpn', - metavar="", - help=(_("BGP VPN to apply the %s association (name or ID)") % - self._assoc_res_name), - ) - parser.add_argument( - 'resource', - metavar="<%s>" % self._assoc_res_name, - help=(_("%s to associate the BGP VPN (name or ID)") % - self._assoc_res_name.capitalize()), - ) - - get_common_parser = getattr(self, '_get_common_parser', None) - if callable(get_common_parser): - get_common_parser(parser) - - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) - find_res_method = getattr( - client, 'find_%s' % self._assoc_res_name) - assoc_res = find_res_method(parsed_args.resource) - body = {'%s_id' % self._assoc_res_name: assoc_res['id']} - if 'project' in parsed_args and parsed_args.project is not None: - project_id = nc_osc_utils.find_project( - self.app.client_manager.identity, - parsed_args.project, - parsed_args.project_domain, - ).id - body['tenant_id'] = project_id - - arg2body = getattr(self, '_args2body', None) - if callable(arg2body): - body.update( - arg2body(bgpvpn['id'], parsed_args)) - - if self._resource == constants.NETWORK_ASSOC: - obj = client.create_bgpvpn_network_association( - bgpvpn['id'], **body) - elif self._resource == constants.PORT_ASSOC: - obj = client.create_bgpvpn_port_association(bgpvpn['id'], **body) - else: - obj = client.create_bgpvpn_router_association( - bgpvpn['id'], **body) - transform = getattr(self, '_transform_resource', None) - if callable(transform): - transform(obj) - display_columns, columns = nc_osc_utils._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns, - formatters=self._formatters) - return display_columns, data - - -class SetBgpvpnResAssoc(command.Command): - """Set BGP VPN resource association properties""" - _action = 'set' - - def get_parser(self, prog_name): - parser = super(SetBgpvpnResAssoc, self).get_parser(prog_name) - parser.add_argument( - 'resource_association_id', - metavar="<%s association ID>" % self._assoc_res_name, - help=(_("%s association ID to update") % - self._assoc_res_name.capitalize()), - ) - parser.add_argument( - 'bgpvpn', - metavar="", - help=(_("BGP VPN the %s association belongs to (name or ID)") % - self._assoc_res_name), - ) - - get_common_parser = getattr(self, '_get_common_parser', None) - if callable(get_common_parser): - get_common_parser(parser) - - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) - arg2body = getattr(self, '_args2body', None) - if callable(arg2body): - body = arg2body(bgpvpn['id'], parsed_args) - if self._resource == constants.NETWORK_ASSOC: - client.update_bgpvpn_network_association( - bgpvpn['id'], parsed_args.resource_association_id, **body) - elif self._resource == constants.PORT_ASSOC: - client.update_bgpvpn_port_association( - bgpvpn['id'], parsed_args.resource_association_id, **body) - else: - client.update_bgpvpn_router_association( - bgpvpn['id'], parsed_args.resource_association_id, **body) - - -class UnsetBgpvpnResAssoc(SetBgpvpnResAssoc): - """Unset BGP VPN resource association properties""" - _action = 'unset' - - -class DeleteBgpvpnResAssoc(command.Command): - """Remove a BGP VPN resource association(s) for a given BGP VPN""" - - def get_parser(self, prog_name): - parser = super(DeleteBgpvpnResAssoc, self).get_parser(prog_name) - parser.add_argument( - 'resource_association_ids', - metavar="<%s association ID>" % self._assoc_res_name, - nargs="+", - help=(_("%s association ID(s) to remove") % - self._assoc_res_name.capitalize()), - ) - parser.add_argument( - 'bgpvpn', - metavar="", - help=(_("BGP VPN the %s association belongs to (name or ID)") % - self._assoc_res_name), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) - fails = 0 - for id in parsed_args.resource_association_ids: - try: - if self._resource == constants.NETWORK_ASSOC: - client.delete_bgpvpn_network_association(bgpvpn['id'], id) - elif self._resource == constants.PORT_ASSOC: - client.delete_bgpvpn_port_association(bgpvpn['id'], id) - else: - client.delete_bgpvpn_router_association(bgpvpn['id'], id) - LOG.warning( - "%(assoc_res_name)s association %(id)s deleted", - {'assoc_res_name': self._assoc_res_name.capitalize(), - 'id': id}) - except Exception as e: - fails += 1 - LOG.error("Failed to delete %(assoc_res_name)s " - "association with ID '%(id)s': %(e)s", - {'assoc_res_name': self._assoc_res_name, - 'id': id, - 'e': e}) - if fails > 0: - msg = (_("Failed to delete %(fails)s of %(total)s " - "%(assoc_res_name)s BGP VPN association(s).") % - {'fails': fails, - 'total': len(parsed_args.resource_association_ids), - 'assoc_res_name': self._assoc_res_name}) - raise exceptions.CommandError(msg) - - -class ListBgpvpnResAssoc(command.Lister): - """List BGP VPN resource associations for a given BGP VPN""" - - def get_parser(self, prog_name): - parser = super(ListBgpvpnResAssoc, self).get_parser(prog_name) - parser.add_argument( - 'bgpvpn', - metavar="", - help=_("BGP VPN listed associations belong to (name or ID)"), - ) - parser.add_argument( - '--long', - action='store_true', - help=_("List additional fields in output"), - ) - parser.add_argument( - '--property', - metavar="", - help=_("Filter property to apply on returned BGP VPNs (repeat to " - "filter on multiple properties)"), - action=parseractions.KeyValueAction, - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) - params = {} - if parsed_args.property: - params.update(parsed_args.property) - if self._resource == constants.NETWORK_ASSOC: - objs = client.bgpvpn_network_associations( - bgpvpn['id'], retrieve_all=True, **params) - elif self._resource == constants.PORT_ASSOC: - objs = client.bgpvpn_port_associations( - bgpvpn['id'], retrieve_all=True, **params) - else: - objs = client.bgpvpn_router_associations( - bgpvpn['id'], retrieve_all=True, **params) - transform = getattr(self, '_transform_resource', None) - transformed_objs = [] - if callable(transform): - for obj in objs: - transformed_objs.append(transform(obj)) - else: - transformed_objs = list(objs) - headers, columns = column_util.get_column_definitions( - self._attr_map, long_listing=parsed_args.long) - return (headers, (osc_utils.get_dict_properties( - s, columns, formatters=self._formatters) - for s in transformed_objs)) - - -class ShowBgpvpnResAssoc(command.ShowOne): - """Show information of a given BGP VPN resource association""" - - def get_parser(self, prog_name): - parser = super(ShowBgpvpnResAssoc, self).get_parser(prog_name) - parser.add_argument( - 'resource_association_id', - metavar="<%s association ID>" % self._assoc_res_name, - help=(_("%s association ID to look up") % - self._assoc_res_name.capitalize()), - ) - parser.add_argument( - 'bgpvpn', - metavar="", - help=_("BGP VPN the association belongs to (name or ID)"), - ) - return parser - - def take_action(self, parsed_args): - client = self.app.client_manager.network - bgpvpn = client.find_bgpvpn(parsed_args.bgpvpn) - if self._resource == constants.NETWORK_ASSOC: - obj = client.get_bgpvpn_network_association( - bgpvpn['id'], parsed_args.resource_association_id) - elif self._resource == constants.PORT_ASSOC: - obj = client.get_bgpvpn_port_association( - bgpvpn['id'], parsed_args.resource_association_id) - else: - obj = client.get_bgpvpn_router_association( - bgpvpn['id'], parsed_args.resource_association_id) - transform = getattr(self, '_transform_resource', None) - if callable(transform): - transform(obj) - display_columns, columns = nc_osc_utils._get_columns(obj) - data = osc_utils.get_dict_properties(obj, columns, - formatters=self._formatters) - return display_columns, data diff --git a/neutronclient/osc/v2/networking_bgpvpn/router_association.py b/neutronclient/osc/v2/networking_bgpvpn/router_association.py deleted file mode 100644 index f4cdde09c..000000000 --- a/neutronclient/osc/v2/networking_bgpvpn/router_association.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright (c) 2016 Juniper networks Inc. -# All Rights Reserved. -# -# 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. -# - -from osc_lib.utils import columns as column_util - -from neutronclient._i18n import _ -from neutronclient.osc.v2.networking_bgpvpn import constants -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - CreateBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - DeleteBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - ListBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - SetBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - ShowBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - UnsetBgpvpnResAssoc - - -class BgpvpnRouterAssoc(object): - _assoc_res_name = constants.ROUTER_RESOURCE_NAME - _resource = constants.ROUTER_ASSOC - _resource_plural = constants.ROUTER_ASSOCS - - _attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), - ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), - column_util.LIST_BOTH), - ('advertise_extra_routes', 'Advertise extra routes', - column_util.LIST_LONG_ONLY), - ) - _formatters = {} - - def _get_common_parser(self, parser): - """Adds to parser arguments common to create, set and unset commands. - - :params ArgumentParser parser: argparse object contains all command's - arguments - """ - ADVERTISE_ROUTES = _("Routes will be advertised to the " - "BGP VPN%s") % ( - _(' (default)') if self._action == 'create' - else "") - NOT_ADVERTISE_ROUTES = _("Routes from the router will not be " - "advertised to the BGP VPN") - - group_advertise_extra_routes = parser.add_mutually_exclusive_group() - group_advertise_extra_routes.add_argument( - '--advertise_extra_routes', - action='store_true', - help=NOT_ADVERTISE_ROUTES if self._action == 'unset' - else ADVERTISE_ROUTES, - ) - group_advertise_extra_routes.add_argument( - '--no-advertise_extra_routes', - action='store_true', - help=ADVERTISE_ROUTES if self._action == 'unset' - else NOT_ADVERTISE_ROUTES, - ) - - def _args2body(self, _, args): - attrs = {'advertise_extra_routes': False} - if args.advertise_extra_routes: - attrs['advertise_extra_routes'] = self._action != 'unset' - elif args.no_advertise_extra_routes: - attrs['advertise_extra_routes'] = self._action == 'unset' - - return attrs - - -class CreateBgpvpnRouterAssoc(BgpvpnRouterAssoc, CreateBgpvpnResAssoc): - _description = _("Create a BGP VPN router association") - pass - - -class SetBgpvpnRouterAssoc(BgpvpnRouterAssoc, SetBgpvpnResAssoc): - _description = _("Set BGP VPN router association properties") - - -class UnsetBgpvpnRouterAssoc(BgpvpnRouterAssoc, UnsetBgpvpnResAssoc): - _description = _("Unset BGP VPN router association properties") - - -class DeleteBgpvpnRouterAssoc(BgpvpnRouterAssoc, DeleteBgpvpnResAssoc): - _description = _("Delete a BGP VPN router association(s) for a given BGP " - "VPN") - pass - - -class ListBgpvpnRouterAssoc(BgpvpnRouterAssoc, ListBgpvpnResAssoc): - _description = _("List BGP VPN router associations for a given BGP VPN") - pass - - -class ShowBgpvpnRouterAssoc(BgpvpnRouterAssoc, ShowBgpvpnResAssoc): - _description = _("Show information of a given BGP VPN router association") - pass diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/__init__.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py deleted file mode 100644 index 0a2c3fe9c..000000000 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/fakes.py +++ /dev/null @@ -1,270 +0,0 @@ -# Copyright (c) 2016 Juniper Networks Inc. -# All Rights Reserved. -# -# 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 copy -from unittest import mock - -from openstack.network.v2 import bgpvpn as _bgpvpn -from openstack import resource as sdk_resource -from osc_lib.utils import columns as column_util - -from neutronclient.osc import utils as nc_osc_utils -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - CreateBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - DeleteBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - ListBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - SetBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - ShowBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.resource_association import\ - UnsetBgpvpnResAssoc -from neutronclient.osc.v2.networking_bgpvpn.router_association import\ - CreateBgpvpnRouterAssoc -from neutronclient.osc.v2.networking_bgpvpn.router_association import\ - SetBgpvpnRouterAssoc -from neutronclient.osc.v2.networking_bgpvpn.router_association import\ - ShowBgpvpnRouterAssoc -from neutronclient.tests.unit.osc.v2 import fakes as test_fakes - - -_FAKE_PROJECT_ID = 'fake_project_id' - - -class TestNeutronClientBgpvpn(test_fakes.TestNeutronClientOSCV2): - - def setUp(self): - super(TestNeutronClientBgpvpn, self).setUp() - self.neutronclient.find_resource = mock.Mock( - side_effect=lambda resource, name_or_id, project_id=None, - cmd_resource=None, parent_id=None, fields=None: - {'id': name_or_id, 'tenant_id': _FAKE_PROJECT_ID}) - self.neutronclient.find_resource_by_id = mock.Mock( - side_effect=lambda resource, resource_id, cmd_resource=None, - parent_id=None, fields=None: - {'id': resource_id, 'tenant_id': _FAKE_PROJECT_ID}) - nc_osc_utils.find_project = mock.Mock( - side_effect=lambda _, name_or_id, __: mock.Mock(id=name_or_id)) - - -def create_one_bgpvpn(attrs=None): - """Create a fake BGP VPN.""" - - attrs = attrs or {} - - # Set default attributes. - bgpvpn_attrs = { - 'id': 'fake_bgpvpn_id', - 'tenant_id': _FAKE_PROJECT_ID, - 'name': '', - 'type': 'l3', - 'route_targets': [], - 'import_targets': [], - 'export_targets': [], - 'route_distinguishers': [], - 'networks': [], - 'routers': [], - 'ports': [], - 'vni': 100, - 'local_pref': 777, - } - - # Overwrite default attributes. - bgpvpn_attrs.update(attrs) - return _bgpvpn.BgpVpn(**bgpvpn_attrs) - - -def create_bgpvpns(attrs=None, count=1): - """Create multiple fake BGP VPN.""" - - bgpvpns = [] - for i in range(0, count): - if attrs is None: - attrs = {'id': 'fake_id%d' % i} - elif getattr(attrs, 'id', None) is None: - attrs['id'] = 'fake_id%d' % i - bgpvpns.append(create_one_bgpvpn(attrs)) - - return bgpvpns - - -class BgpvpnFakeAssoc(object): - _assoc_res_name = 'fake_resource' - _resource = '%s_association' % _assoc_res_name - _resource_plural = '%ss' % _resource - - _attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), - column_util.LIST_BOTH), - ('name', 'Name', column_util.LIST_BOTH), - ('project_id', 'Project ID', column_util.LIST_BOTH), - ) - _formatters = {} - - -class CreateBgpvpnFakeResAssoc(BgpvpnFakeAssoc, CreateBgpvpnResAssoc): - pass - - -class SetBgpvpnFakeResAssoc(BgpvpnFakeAssoc, SetBgpvpnResAssoc): - pass - - -class UnsetBgpvpnFakeResAssoc(BgpvpnFakeAssoc, UnsetBgpvpnResAssoc): - pass - - -class DeleteBgpvpnFakeResAssoc(BgpvpnFakeAssoc, DeleteBgpvpnResAssoc): - pass - - -class ListBgpvpnFakeResAssoc(BgpvpnFakeAssoc, ListBgpvpnResAssoc): - pass - - -class ShowBgpvpnFakeResAssoc(BgpvpnFakeAssoc, ShowBgpvpnResAssoc): - pass - - -class BgpvpnFakeRouterAssoc(object): - _assoc_res_name = 'fake_resource' - _resource = '%s_association' % _assoc_res_name - _resource_plural = '%ss' % _resource - - _attr_map = ( - ('id', 'ID', column_util.LIST_BOTH), - ('%s_id' % _assoc_res_name, '%s ID' % _assoc_res_name.capitalize(), - column_util.LIST_BOTH), - ('advertise_extra_routes', 'Advertise extra routes', - column_util.LIST_LONG_ONLY), - ('name', 'Name', column_util.LIST_BOTH), - ('project_id', 'Project ID', column_util.LIST_BOTH), - ) - _formatters = {} - - -class CreateBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, - CreateBgpvpnRouterAssoc): - pass - - -class SetBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, SetBgpvpnRouterAssoc): - pass - - -class ShowBgpvpnFakeRouterAssoc(BgpvpnFakeRouterAssoc, ShowBgpvpnRouterAssoc): - pass - - -class FakeResource(sdk_resource.Resource): - resource_key = 'fakeresource' - resources_key = 'fakeresources' - base_path = '/bgpvpn/fakeresources' - - _allow_unknown_attrs_in_body = True - - # capabilities - allow_create = True - allow_fetch = True - allow_commit = True - allow_delete = True - allow_list = True - - id = sdk_resource.Body('id') - tenant_id = sdk_resource.Body('tenant_id', deprecated=True) - project_id = sdk_resource.Body('project_id', alias='tenant_id') - - -class FakeResoureAssociation(sdk_resource.Resource): - resource_key = 'fakeresourceassociation' - resources_key = 'fakeresourceassociations' - base_path = '/bgpvpn/fakeresourceassociations' - - _allow_unknown_attrs_in_body = True - - # capabilities - allow_create = True - allow_fetch = True - allow_commit = True - allow_delete = True - allow_list = True - - id = sdk_resource.Body('id') - tenant_id = sdk_resource.Body('tenant_id', deprecated=True) - project_id = sdk_resource.Body('project_id', alias='tenant_id') - - -def create_one_resource(attrs=None): - """Create a fake resource.""" - attrs = attrs or {} - - # Set default attributes. - res_attrs = { - 'id': 'fake_resource_id', - 'tenant_id': _FAKE_PROJECT_ID, - } - - # Overwrite default attributes. - res_attrs.update(attrs) - return FakeResource(**res_attrs) - - -def create_resources(attrs=None, count=1): - """Create multiple fake resources.""" - - resources = [] - for i in range(0, count): - if attrs is None: - attrs = {'id': 'fake_id%d' % i} - elif getattr(attrs, 'id', None) is None: - attrs['id'] = 'fake_id%d' % i - resources.append(create_one_resource(attrs)) - - return resources - - -def create_one_resource_association(resource, attrs=None): - """Create a fake resource association.""" - - attrs = attrs or {} - - res_assoc_attrs = { - 'id': 'fake_association_id', - 'tenant_id': resource['tenant_id'], - 'fake_resource_id': resource['id'], - } - - # Overwrite default attributes. - res_assoc_attrs.update(attrs) - return FakeResoureAssociation(**res_assoc_attrs) - - -def create_resource_associations(resources): - """Create multiple fake resource associations.""" - - res_assocs = [] - for idx, resource in enumerate(resources): - res_assoc_attrs = { - 'id': 'fake_association_id%d' % idx, - 'tenant_id': resource['tenant_id'], - 'fake_resource_id': resource['id'], - } - res_assocs.append(copy.deepcopy(res_assoc_attrs)) - - return res_assocs diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py deleted file mode 100644 index 3f1632027..000000000 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_bgpvpn.py +++ /dev/null @@ -1,524 +0,0 @@ -# Copyright (c) 2016 Juniper Networks Inc. -# All Rights Reserved. -# -# 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 copy -import operator -from unittest import mock - -from osc_lib import exceptions -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util - -from neutronclient.osc.v2.networking_bgpvpn import bgpvpn -from neutronclient.tests.unit.osc.v2.networking_bgpvpn import fakes - - -columns_short = tuple(col for col, _, listing_mode in bgpvpn._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_SHORT_ONLY)) -columns_long = tuple(col for col, _, listing_mode in bgpvpn._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -headers_short = tuple(head for _, head, listing_mode in bgpvpn._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_SHORT_ONLY)) -headers_long = tuple(head for _, head, listing_mode in bgpvpn._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -sorted_attr_map = sorted(bgpvpn._attr_map, key=operator.itemgetter(1)) -sorted_columns = tuple(col for col, _, _ in sorted_attr_map) -sorted_headers = tuple(head for _, head, _ in sorted_attr_map) - - -def _get_data(attrs, columns=sorted_columns): - return osc_utils.get_dict_properties(attrs, columns, - formatters=bgpvpn._formatters) - - -class TestCreateBgpvpn(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestCreateBgpvpn, self).setUp() - self.cmd = bgpvpn.CreateBgpvpn(self.app, self.namespace) - - def test_create_bgpvpn_with_no_args(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - self.networkclient.create_bgpvpn = mock.Mock( - return_value=fake_bgpvpn) - arglist = [] - verifylist = [ - ('project', None), - ('name', None), - ('type', 'l3'), - ('vni', None), - ('local_pref', None), - ('route_targets', None), - ('import_targets', None), - ('export_targets', None), - ('route_distinguishers', None), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - cols, data = self.cmd.take_action(parsed_args) - - self.networkclient.create_bgpvpn.assert_called_once_with( - **{'type': 'l3'}) - - self.assertEqual(sorted(sorted_columns), sorted(cols)) - - def test_create_bgpvpn_with_all_args(self): - attrs = { - 'tenant_id': 'new_fake_project_id', - 'name': 'fake_name', - 'type': 'l2', - 'vni': 100, - 'local_pref': 777, - 'route_targets': ['fake_rt1', 'fake_rt2', 'fake_rt3'], - 'import_targets': ['fake_irt1', 'fake_irt2', 'fake_irt3'], - 'export_targets': ['fake_ert1', 'fake_ert2', 'fake_ert3'], - 'route_distinguishers': ['fake_rd1', 'fake_rd2', 'fake_rd3'], - } - fake_bgpvpn = fakes.create_one_bgpvpn(attrs) - self.networkclient.create_bgpvpn = mock.Mock( - return_value=fake_bgpvpn) - arglist = [ - '--project', fake_bgpvpn['tenant_id'], - '--name', fake_bgpvpn['name'], - '--type', fake_bgpvpn['type'], - '--vni', str(fake_bgpvpn['vni']), - '--local-pref', str(fake_bgpvpn['local_pref']), - ] - for rt in fake_bgpvpn['route_targets']: - arglist.extend(['--route-target', rt]) - for rt in fake_bgpvpn['import_targets']: - arglist.extend(['--import-target', rt]) - for rt in fake_bgpvpn['export_targets']: - arglist.extend(['--export-target', rt]) - for rd in fake_bgpvpn['route_distinguishers']: - arglist.extend(['--route-distinguisher', rd]) - verifylist = [ - ('project', fake_bgpvpn['tenant_id']), - ('name', fake_bgpvpn['name']), - ('type', fake_bgpvpn['type']), - ('vni', fake_bgpvpn['vni']), - ('local_pref', fake_bgpvpn['local_pref']), - ('route_targets', fake_bgpvpn['route_targets']), - ('import_targets', fake_bgpvpn['import_targets']), - ('export_targets', fake_bgpvpn['export_targets']), - ('route_distinguishers', fake_bgpvpn['route_distinguishers']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - cols, data = self.cmd.take_action(parsed_args) - - fake_bgpvpn_call = copy.deepcopy(attrs) - - self.networkclient.create_bgpvpn.assert_called_once_with( - **fake_bgpvpn_call) - self.assertEqual(sorted(sorted_columns), sorted(cols)) - - -class TestSetBgpvpn(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestSetBgpvpn, self).setUp() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.cmd = bgpvpn.SetBgpvpn(self.app, self.namespace) - - def test_set_bgpvpn(self): - attrs = { - 'route_targets': ['set_rt1', 'set_rt2', 'set_rt3'], - 'import_targets': ['set_irt1', 'set_irt2', 'set_irt3'], - 'export_targets': ['set_ert1', 'set_ert2', 'set_ert3'], - 'route_distinguishers': ['set_rd1', 'set_rd2', 'set_rd3'], - } - fake_bgpvpn = fakes.create_one_bgpvpn(attrs) - self.networkclient.get_bgpvpn = mock.Mock( - return_value=fake_bgpvpn) - self.networkclient.update_bgpvpn = mock.Mock() - arglist = [ - fake_bgpvpn['id'], - '--name', 'set_name', - '--route-target', 'set_rt1', - '--import-target', 'set_irt1', - '--export-target', 'set_ert1', - '--route-distinguisher', 'set_rd1', - ] - verifylist = [ - ('bgpvpn', fake_bgpvpn['id']), - ('name', 'set_name'), - ('route_targets', ['set_rt1']), - ('purge_route_target', False), - ('import_targets', ['set_irt1']), - ('purge_import_target', False), - ('export_targets', ['set_ert1']), - ('purge_export_target', False), - ('route_distinguishers', ['set_rd1']), - ('purge_route_distinguisher', False), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - attrs = { - 'name': 'set_name', - 'route_targets': list(set(fake_bgpvpn['route_targets']) | - set(['set_rt1'])), - 'import_targets': list(set(fake_bgpvpn['import_targets']) | - set(['set_irt1'])), - 'export_targets': list(set(fake_bgpvpn['export_targets']) | - set(['set_ert1'])), - 'route_distinguishers': list( - set(fake_bgpvpn['route_distinguishers']) | set(['set_rd1'])), - } - self.networkclient.update_bgpvpn.assert_called_once_with( - fake_bgpvpn['id'], **attrs) - self.assertIsNone(result) - - def test_set_bgpvpn_with_purge_list(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - self.networkclient.get_bgpvpn = mock.Mock( - return_value=fake_bgpvpn) - self.neutronclient.update_bgpvpn = mock.Mock() - arglist = [ - fake_bgpvpn['id'], - '--route-target', 'set_rt1', - '--no-route-target', - '--import-target', 'set_irt1', - '--no-import-target', - '--export-target', 'set_ert1', - '--no-export-target', - '--route-distinguisher', 'set_rd1', - '--no-route-distinguisher', - ] - verifylist = [ - ('bgpvpn', fake_bgpvpn['id']), - ('route_targets', ['set_rt1']), - ('purge_route_target', True), - ('import_targets', ['set_irt1']), - ('purge_import_target', True), - ('export_targets', ['set_ert1']), - ('purge_export_target', True), - ('route_distinguishers', ['set_rd1']), - ('purge_route_distinguisher', True), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - attrs = { - 'route_targets': [], - 'import_targets': [], - 'export_targets': [], - 'route_distinguishers': [], - } - self.networkclient.update_bgpvpn.assert_called_once_with( - fake_bgpvpn['id'], **attrs) - self.assertIsNone(result) - - -class TestUnsetBgpvpn(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestUnsetBgpvpn, self).setUp() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.cmd = bgpvpn.UnsetBgpvpn(self.app, self.namespace) - - def test_unset_bgpvpn(self): - attrs = { - 'route_targets': ['unset_rt1', 'unset_rt2', 'unset_rt3'], - 'import_targets': ['unset_irt1', 'unset_irt2', 'unset_irt3'], - 'export_targets': ['unset_ert1', 'unset_ert2', 'unset_ert3'], - 'route_distinguishers': ['unset_rd1', 'unset_rd2', 'unset_rd3'], - } - fake_bgpvpn = fakes.create_one_bgpvpn(attrs) - self.networkclient.get_bgpvpn = mock.Mock( - return_value=fake_bgpvpn) - self.networkclient.update_bgpvpn = mock.Mock() - arglist = [ - fake_bgpvpn['id'], - '--route-target', 'unset_rt1', - '--import-target', 'unset_irt1', - '--export-target', 'unset_ert1', - '--route-distinguisher', 'unset_rd1', - ] - verifylist = [ - ('bgpvpn', fake_bgpvpn['id']), - ('route_targets', ['unset_rt1']), - ('purge_route_target', False), - ('import_targets', ['unset_irt1']), - ('purge_import_target', False), - ('export_targets', ['unset_ert1']), - ('purge_export_target', False), - ('route_distinguishers', ['unset_rd1']), - ('purge_route_distinguisher', False), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - attrs = { - 'route_targets': list(set(fake_bgpvpn['route_targets']) - - set(['unset_rt1'])), - 'import_targets': list(set(fake_bgpvpn['import_targets']) - - set(['unset_irt1'])), - 'export_targets': list(set(fake_bgpvpn['export_targets']) - - set(['unset_ert1'])), - 'route_distinguishers': list( - set(fake_bgpvpn['route_distinguishers']) - set(['unset_rd1'])), - } - self.networkclient.update_bgpvpn.assert_called_once_with( - fake_bgpvpn['id'], **attrs) - self.assertIsNone(result) - - def test_unset_bgpvpn_with_purge_list(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - self.networkclient.show_bgpvpn = mock.Mock( - return_value=fake_bgpvpn) - self.neutronclient.update_bgpvpn = mock.Mock() - arglist = [ - fake_bgpvpn['id'], - '--route-target', 'unset_rt1', - '--all-route-target', - '--import-target', 'unset_irt1', - '--all-import-target', - '--export-target', 'unset_ert1', - '--all-export-target', - '--route-distinguisher', 'unset_rd1', - '--all-route-distinguisher', - ] - verifylist = [ - ('bgpvpn', fake_bgpvpn['id']), - ('route_targets', ['unset_rt1']), - ('purge_route_target', True), - ('import_targets', ['unset_irt1']), - ('purge_import_target', True), - ('export_targets', ['unset_ert1']), - ('purge_export_target', True), - ('route_distinguishers', ['unset_rd1']), - ('purge_route_distinguisher', True), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - attrs = { - 'route_targets': [], - 'import_targets': [], - 'export_targets': [], - 'route_distinguishers': [], - } - self.networkclient.update_bgpvpn.assert_called_once_with( - fake_bgpvpn['id'], **attrs) - self.assertIsNone(result) - - -class TestDeleteBgpvpn(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestDeleteBgpvpn, self).setUp() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.cmd = bgpvpn.DeleteBgpvpn(self.app, self.namespace) - - def test_delete_one_bgpvpn(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - self.networkclient.delete_bgpvpn = mock.Mock() - arglist = [ - fake_bgpvpn['id'], - ] - verifylist = [ - ('bgpvpns', [fake_bgpvpn['id']]), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - self.networkclient.delete_bgpvpn.assert_called_once_with( - fake_bgpvpn['id']) - self.assertIsNone(result) - - def test_delete_multi_bpgvpn(self): - fake_bgpvpns = fakes.create_bgpvpns(count=3) - fake_bgpvpn_ids = [fake_bgpvpn['id'] for fake_bgpvpn in fake_bgpvpns] - self.networkclient.delete_bgpvpn = mock.Mock() - arglist = fake_bgpvpn_ids - verifylist = [ - ('bgpvpns', fake_bgpvpn_ids), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - self.networkclient.delete_bgpvpn.assert_has_calls( - [mock.call(id) for id in fake_bgpvpn_ids]) - self.assertIsNone(result) - - def test_delete_multi_bpgvpn_with_unknown(self): - count = 3 - fake_bgpvpns = fakes.create_bgpvpns(count=count) - fake_bgpvpn_ids = [fake_bgpvpn['id'] for fake_bgpvpn in fake_bgpvpns] - - def raise_unknonw_resource(resource_path, name_or_id): - if str(count - 2) in name_or_id: - raise Exception() - self.networkclient.delete_bgpvpn = mock.Mock( - side_effect=raise_unknonw_resource) - arglist = fake_bgpvpn_ids - verifylist = [ - ('bgpvpns', fake_bgpvpn_ids), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.assertRaises(exceptions.CommandError, self.cmd.take_action, - parsed_args) - - self.networkclient.delete_bgpvpn.assert_has_calls( - [mock.call(id) for id in fake_bgpvpn_ids]) - - -class TestListBgpvpn(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestListBgpvpn, self).setUp() - self.cmd = bgpvpn.ListBgpvpn(self.app, self.namespace) - - def test_list_all_bgpvpn(self): - count = 3 - fake_bgpvpns = fakes.create_bgpvpns(count=count) - self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) - arglist = [] - verifylist = [] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - headers, data = self.cmd.take_action(parsed_args) - - self.networkclient.bgpvpns.assert_called_once() - self.assertEqual(headers, list(headers_short)) - self.assertListItemEqual( - list(data), - [_get_data(fake_bgpvpn, columns_short) for fake_bgpvpn - in fake_bgpvpns]) - - def test_list_all_bgpvpn_long_mode(self): - count = 3 - fake_bgpvpns = fakes.create_bgpvpns(count=count) - self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) - arglist = [ - '--long', - ] - verifylist = [ - ('long', True), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - headers, data = self.cmd.take_action(parsed_args) - - self.networkclient.bgpvpns.assert_called_once() - self.assertEqual(headers, list(headers_long)) - self.assertListItemEqual( - list(data), - [_get_data(fake_bgpvpn, columns_long) for fake_bgpvpn - in fake_bgpvpns]) - - def test_list_project_bgpvpn(self): - count = 3 - project_id = 'list_fake_project_id' - attrs = {'tenant_id': project_id} - fake_bgpvpns = fakes.create_bgpvpns(count=count, - attrs=attrs) - self.networkclient.bgpvpns = mock.Mock(return_value=fake_bgpvpns) - arglist = [ - '--project', project_id, - ] - verifylist = [ - ('project', project_id), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - headers, data = self.cmd.take_action(parsed_args) - - self.networkclient.bgpvpns.assert_called_once_with( - tenant_id=project_id) - self.assertEqual(headers, list(headers_short)) - self.assertListItemEqual( - list(data), - [_get_data(fake_bgpvpn, columns_short) for fake_bgpvpn - in fake_bgpvpns]) - - def test_list_bgpvpn_with_filters(self): - count = 3 - name = 'fake_id0' - layer_type = 'l2' - attrs = {'type': layer_type} - fake_bgpvpns = fakes.create_bgpvpns(count=count, - attrs=attrs) - returned_bgpvpn = fake_bgpvpns[0] - self.networkclient.bgpvpns = mock.Mock(return_value=[returned_bgpvpn]) - arglist = [ - '--property', 'name=%s' % name, - '--property', 'type=%s' % layer_type, - ] - verifylist = [ - ('property', {'name': name, 'type': layer_type}), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - headers, data = self.cmd.take_action(parsed_args) - - self.networkclient.bgpvpns.assert_called_once_with( - name=name, - type=layer_type) - self.assertEqual(headers, list(headers_short)) - self.assertListItemEqual(list(data), - [_get_data(returned_bgpvpn, columns_short)]) - - -class TestShowBgpvpn(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestShowBgpvpn, self).setUp() - self.cmd = bgpvpn.ShowBgpvpn(self.app, self.namespace) - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - - def test_show_bgpvpn(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - self.networkclient.get_bgpvpn = mock.Mock( - return_value=fake_bgpvpn) - arglist = [ - fake_bgpvpn['id'], - ] - verifylist = [ - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - headers, data = self.cmd.take_action(parsed_args) - - self.networkclient.get_bgpvpn.assert_called_once_with( - fake_bgpvpn['id']) - self.assertEqual(sorted(sorted_columns), sorted(headers)) diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py deleted file mode 100644 index c5c478ab4..000000000 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_resource_association.py +++ /dev/null @@ -1,320 +0,0 @@ -# Copyright (c) 2016 Juniper Networks Inc. -# All Rights Reserved. -# -# 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 operator -from unittest import mock - -from osc_lib import exceptions -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util - -from neutronclient.tests.unit.osc.v2.networking_bgpvpn import fakes - - -columns_short = tuple(col for col, _, listing_mode - in fakes.BgpvpnFakeAssoc._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_SHORT_ONLY)) -columns_long = tuple(col for col, _, listing_mode - in fakes.BgpvpnFakeAssoc._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -headers_short = tuple(head for _, head, listing_mode - in fakes.BgpvpnFakeAssoc._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_SHORT_ONLY)) -headers_long = tuple(head for _, head, listing_mode - in fakes.BgpvpnFakeAssoc._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -sorted_attr_map = sorted(fakes.BgpvpnFakeAssoc._attr_map, - key=operator.itemgetter(1)) -sorted_columns = tuple(col for col, _, _ in sorted_attr_map) -sorted_headers = tuple(head for _, head, _ in sorted_attr_map) - - -def _get_data(attrs, columns=sorted_columns): - return osc_utils.get_dict_properties( - attrs, columns, formatters=fakes.BgpvpnFakeAssoc._formatters) - - -class TestCreateResAssoc(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestCreateResAssoc, self).setUp() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.networkclient.find_fake_resource = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.cmd = fakes.CreateBgpvpnFakeResAssoc(self.app, self.namespace) - - def test_create_resource_association(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_one_resource() - fake_res_assoc = fakes.create_one_resource_association( - fake_res) - self.networkclient.create_bgpvpn_router_association = mock.Mock( - return_value=fake_res_assoc) - self.networkclient.find_bgpvpn_fake_resource_association = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - arglist = [ - fake_bgpvpn['id'], - fake_res['id'], - '--project', fake_bgpvpn['tenant_id'], - ] - verifylist = [ - ('bgpvpn', fake_bgpvpn['id']), - ('resource', fake_res['id']), - ('project', fake_bgpvpn['tenant_id']) - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - cols, data = self.cmd.take_action(parsed_args) - - fake_res_assoc_call = { - 'fake_resource_id': 'fake_resource_id', - 'tenant_id': 'fake_project_id' - } - - self.networkclient.create_bgpvpn_router_association.\ - assert_called_once_with( - fake_bgpvpn['id'], - **fake_res_assoc_call) - self.assertEqual(sorted_columns, cols) - self.assertEqual(_get_data(fake_res_assoc), data) - - -class TestSetResAssoc(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestSetResAssoc, self).setUp() - self.cmd = fakes.SetBgpvpnFakeResAssoc(self.app, self.namespace) - - def test_set_resource_association(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_one_resource() - fake_res_assoc = fakes.create_one_resource_association( - fake_res) - self.networkclient.update_bgpvpn_router_association = mock.Mock( - return_value={fakes.BgpvpnFakeAssoc._resource: fake_res_assoc}) - arglist = [ - fake_res_assoc['id'], - fake_bgpvpn['id'], - ] - verifylist = [ - ('resource_association_id', fake_res_assoc['id']), - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - self.networkclient.update_bgpvpn_router_association.\ - assert_not_called() - self.assertIsNone(result) - - -class TestDeleteResAssoc(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestDeleteResAssoc, self).setUp() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.cmd = fakes.DeleteBgpvpnFakeResAssoc(self.app, self.namespace) - - def test_delete_one_association(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_one_resource() - fake_res_assoc = fakes.create_one_resource_association( - fake_res) - self.networkclient.delete_bgpvpn_router_association = \ - mock.Mock() - arglist = [ - fake_res_assoc['id'], - fake_bgpvpn['id'], - ] - verifylist = [ - ('resource_association_ids', [fake_res_assoc['id']]), - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - self.networkclient.delete_bgpvpn_router_association.\ - assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) - self.assertIsNone(result) - - def test_delete_multi_bpgvpn(self): - count = 3 - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_resources(count=count) - fake_res_assocs = fakes.create_resource_associations( - fake_res) - fake_res_assoc_ids = [ - fake_res_assoc['id'] for fake_res_assoc in fake_res_assocs - ] - self.networkclient.delete_bgpvpn_router_association = \ - mock.Mock() - arglist = \ - fake_res_assoc_ids + [ - fake_bgpvpn['id'] - ] - verifylist = [ - ('resource_association_ids', fake_res_assoc_ids), - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - result = self.cmd.take_action(parsed_args) - - self.networkclient.delete_bgpvpn_router_association.\ - assert_has_calls([ - mock.call( - fake_bgpvpn['id'], id) for id in fake_res_assoc_ids]) - self.assertIsNone(result) - - def test_delete_multi_bpgvpn_with_unknown(self): - count = 3 - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_resources(count=count) - fake_res_assocs = fakes.create_resource_associations( - fake_res) - fake_res_assoc_ids = [ - fake_res_assoc['id'] for fake_res_assoc in fake_res_assocs - ] - - def raise_unknonw_resource(resource_path, name_or_id): - if str(count - 2) in name_or_id: - raise Exception() - self.networkclient.delete_bgpvpn_router_association = mock.Mock( - side_effect=raise_unknonw_resource) - arglist = \ - fake_res_assoc_ids + [ - fake_bgpvpn['id'] - ] - verifylist = [ - ('resource_association_ids', fake_res_assoc_ids), - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - self.assertRaises(exceptions.CommandError, self.cmd.take_action, - parsed_args) - - self.networkclient.delete_bgpvpn_router_association.\ - assert_has_calls([ - mock.call(fake_bgpvpn['id'], id) for id in fake_res_assoc_ids] - ) - - -class TestListResAssoc(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestListResAssoc, self).setUp() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.cmd = fakes.ListBgpvpnFakeResAssoc(self.app, self.namespace) - - def test_list_bgpvpn_associations(self): - count = 3 - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_resources(count=count) - fake_res_assocs = fakes.create_resource_associations( - fake_res) - self.networkclient.bgpvpn_router_associations = mock.Mock( - return_value=fake_res_assocs) - arglist = [ - fake_bgpvpn['id'], - ] - verifylist = [ - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - headers, data = self.cmd.take_action(parsed_args) - - self.networkclient.bgpvpn_router_associations.\ - assert_called_once_with(fake_bgpvpn['id'], retrieve_all=True) - self.assertEqual(headers, list(headers_short)) - self.assertEqual( - list(data), - [_get_data(fake_res_assoc, columns_short) for fake_res_assoc - in fake_res_assocs]) - - def test_list_bgpvpn_associations_long_mode(self): - count = 3 - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_resources(count=count) - fake_res_assocs = fakes.create_resource_associations( - fake_res) - self.networkclient.bgpvpn_router_associations = mock.Mock( - return_value=fake_res_assocs) - arglist = [ - '--long', - fake_bgpvpn['id'], - ] - verifylist = [ - ('long', True), - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - headers, data = self.cmd.take_action(parsed_args) - - self.networkclient.bgpvpn_router_associations.\ - assert_called_once_with(fake_bgpvpn['id'], retrieve_all=True) - self.assertEqual(headers, list(headers_long)) - self.assertEqual( - list(data), - [_get_data(fake_res_assoc, columns_long) for fake_res_assoc - in fake_res_assocs]) - - -class TestShowResAssoc(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestShowResAssoc, self).setUp() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.cmd = fakes.ShowBgpvpnFakeResAssoc(self.app, self.namespace) - - def test_show_resource_association(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_one_resource() - fake_res_assoc = fakes.create_one_resource_association( - fake_res) - self.networkclient.get_bgpvpn_router_association = mock.Mock( - return_value=fake_res_assoc) - arglist = [ - fake_res_assoc['id'], - fake_bgpvpn['id'], - ] - verifylist = [ - ('resource_association_id', fake_res_assoc['id']), - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - columns, data = self.cmd.take_action(parsed_args) - - self.networkclient.get_bgpvpn_router_association.\ - assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) - self.assertEqual(sorted_columns, columns) - self.assertEqual(data, _get_data(fake_res_assoc)) diff --git a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py b/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py deleted file mode 100644 index 71c174288..000000000 --- a/neutronclient/tests/unit/osc/v2/networking_bgpvpn/test_router_association.py +++ /dev/null @@ -1,292 +0,0 @@ -# Copyright (c) 2018 Orange SA. -# All Rights Reserved. -# -# 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 operator -from unittest import mock - -from osc_lib.tests.utils import ParserException -from osc_lib import utils as osc_utils -from osc_lib.utils import columns as column_util - -from neutronclient.tests.unit.osc.v2.networking_bgpvpn import fakes - - -columns_short = tuple(col for col, _, listing_mode - in fakes.BgpvpnFakeRouterAssoc._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_SHORT_ONLY)) -columns_long = tuple(col for col, _, listing_mode - in fakes.BgpvpnFakeRouterAssoc._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -headers_short = tuple(head for _, head, listing_mode - in fakes.BgpvpnFakeRouterAssoc._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_SHORT_ONLY)) -headers_long = tuple(head for _, head, listing_mode - in fakes.BgpvpnFakeRouterAssoc._attr_map - if listing_mode in (column_util.LIST_BOTH, - column_util.LIST_LONG_ONLY)) -sorted_attr_map = sorted(fakes.BgpvpnFakeRouterAssoc._attr_map, - key=operator.itemgetter(1)) -sorted_columns = tuple(col for col, _, _ in sorted_attr_map) -sorted_headers = tuple(head for _, head, _ in sorted_attr_map) - - -def _get_data(attrs, columns=sorted_columns): - return osc_utils.get_dict_properties( - attrs, columns, formatters=fakes.BgpvpnFakeAssoc._formatters) - - -class TestCreateRouterAssoc(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestCreateRouterAssoc, self).setUp() - self.cmd = fakes.CreateBgpvpnFakeRouterAssoc(self.app, self.namespace) - self.fake_bgpvpn = fakes.create_one_bgpvpn() - self.fake_router = fakes.create_one_resource() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - self.networkclient.find_fake_resource = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - - def _build_args(self, param=None): - arglist_base = [ - self.fake_bgpvpn['id'], - self.fake_router['id'], - '--project', self.fake_bgpvpn['tenant_id'] - ] - if param is not None: - if isinstance(param, list): - arglist_base.extend(param) - else: - arglist_base.append(param) - return arglist_base - - def _build_verify_list(self, param=None): - verifylist = [ - ('bgpvpn', self.fake_bgpvpn['id']), - ('resource', self.fake_router['id']), - ('project', self.fake_bgpvpn['tenant_id']) - ] - if param is not None: - verifylist.append(param) - return verifylist - - def _exec_create_router_association( - self, fake_res_assoc, arglist, verifylist): - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - cols, data = self.cmd.take_action(parsed_args) - - fake_res_assoc_call = { - 'fake_resource_id': 'fake_resource_id', - 'tenant_id': 'fake_project_id' - } - for key, value in verifylist: - if value not in fake_res_assoc_call.values(): - fake_res_assoc_call[key] = value - fake_res_assoc_call.pop('bgpvpn') - - self.networkclient.create_bgpvpn_router_association.\ - assert_called_once_with( - self.fake_bgpvpn['id'], - **fake_res_assoc_call) - return cols, data - - def test_create_router_association(self): - fake_res_assoc = fakes.create_one_resource_association( - self.fake_router) - - self.networkclient.create_bgpvpn_router_association = mock.Mock( - return_value={ - fakes.BgpvpnFakeRouterAssoc._resource: fake_res_assoc, - 'advertise_extra_routes': True}) - - arglist = self._build_args() - # advertise_extra_routes will be False since none - # of the mutually exclusive args present - verifylist = self._build_verify_list(('advertise_extra_routes', False)) - - self._exec_create_router_association( - fake_res_assoc, arglist, verifylist) - - def test_create_router_association_advertise(self): - fake_res_assoc = fakes.create_one_resource_association( - self.fake_router, - {'advertise_extra_routes': True}) - - self.networkclient.create_bgpvpn_router_association = mock.Mock( - return_value=fake_res_assoc) - - arglist = self._build_args('--advertise_extra_routes') - verifylist = self._build_verify_list(('advertise_extra_routes', True)) - - cols, data = self._exec_create_router_association( - fake_res_assoc, arglist, verifylist) - self.assertEqual(sorted_columns, cols) - self.assertEqual(_get_data(fake_res_assoc), data) - - def test_create_router_association_no_advertise(self): - fake_res_assoc = fakes.create_one_resource_association( - self.fake_router, - {'advertise_extra_routes': False}) - - self.networkclient.create_bgpvpn_router_association = mock.Mock( - return_value=fake_res_assoc) - - arglist = self._build_args('--no-advertise_extra_routes') - verifylist = self._build_verify_list(('advertise_extra_routes', False)) - - cols, data = self._exec_create_router_association( - fake_res_assoc, arglist, verifylist) - self.assertEqual(sorted_columns, cols) - self.assertEqual(_get_data(fake_res_assoc), data) - - def test_create_router_association_advertise_fault(self): - arglist = self._build_args( - ['--advertise_extra_routes', '--no-advertise_extra_routes']) - - try: - self._exec_create_router_association(None, arglist, None) - except ParserException as e: - self.assertEqual(format(e), 'Argument parse failed') - - def test_router_association_unknown_arg(self): - arglist = self._build_args('--unknown arg') - - try: - self._exec_create_router_association(None, arglist, None) - except ParserException as e: - self.assertEqual(format(e), 'Argument parse failed') - - -class TestSetRouterAssoc(fakes.TestNeutronClientBgpvpn): - - def setUp(self): - super(TestSetRouterAssoc, self).setUp() - self.cmd = fakes.SetBgpvpnFakeRouterAssoc(self.app, self.namespace) - self.fake_bgpvpn = fakes.create_one_bgpvpn() - self.fake_router = fakes.create_one_resource() - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - - def _build_args(self, fake_res_assoc, param=None): - arglist_base = [ - fake_res_assoc['id'], - self.fake_bgpvpn['id'] - ] - if param is not None: - if isinstance(param, list): - arglist_base.extend(param) - else: - arglist_base.append(param) - return arglist_base - - def _build_verify_list(self, fake_res_assoc, param=None): - verifylist = [ - ('resource_association_id', fake_res_assoc['id']), - ('bgpvpn', self.fake_bgpvpn['id']) - ] - if param is not None: - verifylist.append(param) - return verifylist - - def test_set_router_association_no_advertise(self): - fake_res_assoc = fakes.create_one_resource_association( - self.fake_router, - {'advertise_extra_routes': True}) - self.networkclient.update_bgpvpn_router_association = \ - mock.Mock() - - arglist = self._build_args( - fake_res_assoc, - '--no-advertise_extra_routes') - verifylist = [ - ('resource_association_id', fake_res_assoc['id']), - ('bgpvpn', self.fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.networkclient.update_bgpvpn_router_association.\ - assert_called_once_with( - self.fake_bgpvpn['id'], - fake_res_assoc['id'], - **{'advertise_extra_routes': False} - ) - self.assertIsNone(result) - - def test_set_router_association_advertise(self): - fake_res_assoc = fakes.create_one_resource_association( - self.fake_router, - {'advertise_extra_routes': False}) - self.networkclient.update_bgpvpn_router_association = \ - mock.Mock() - - arglist = self._build_args( - fake_res_assoc, - '--advertise_extra_routes') - verifylist = [ - ('resource_association_id', fake_res_assoc['id']), - ('bgpvpn', self.fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) - - self.networkclient.update_bgpvpn_router_association.\ - assert_called_once_with( - self.fake_bgpvpn['id'], - fake_res_assoc['id'], - **{'advertise_extra_routes': True} - ) - self.assertIsNone(result) - - -class TestShowRouterAssoc(fakes.TestNeutronClientBgpvpn): - def setUp(self): - super(TestShowRouterAssoc, self).setUp() - self.cmd = fakes.ShowBgpvpnFakeRouterAssoc(self.app, self.namespace) - self.networkclient.find_bgpvpn = mock.Mock( - side_effect=lambda name_or_id: {'id': name_or_id}) - - def test_show_router_association(self): - fake_bgpvpn = fakes.create_one_bgpvpn() - fake_res = fakes.create_one_resource() - fake_res_assoc = fakes.create_one_resource_association( - fake_res, - {'advertise_extra_routes': True}) - self.networkclient.get_bgpvpn_router_association = mock.Mock( - return_value=fake_res_assoc) - arglist = [ - fake_res_assoc['id'], - fake_bgpvpn['id'], - ] - verifylist = [ - ('resource_association_id', fake_res_assoc['id']), - ('bgpvpn', fake_bgpvpn['id']), - ] - - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - cols, data = self.cmd.take_action(parsed_args) - - self.networkclient.get_bgpvpn_router_association.\ - assert_called_once_with(fake_bgpvpn['id'], fake_res_assoc['id']) - self.assertEqual(sorted_columns, cols) - self.assertEqual(data, _get_data(fake_res_assoc)) diff --git a/setup.cfg b/setup.cfg index 282919044..a995bae67 100644 --- a/setup.cfg +++ b/setup.cfg @@ -79,28 +79,6 @@ openstack.neutronclient.v2 = bgp_speaker_set = neutronclient.osc.v2.dynamic_routing.bgp_speaker:SetBgpSpeaker bgp_speaker_show = neutronclient.osc.v2.dynamic_routing.bgp_speaker:ShowBgpSpeaker - bgpvpn_create = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:CreateBgpvpn - bgpvpn_delete = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:DeleteBgpvpn - bgpvpn_list = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:ListBgpvpn - bgpvpn_set = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:SetBgpvpn - bgpvpn_show = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:ShowBgpvpn - bgpvpn_unset = neutronclient.osc.v2.networking_bgpvpn.bgpvpn:UnsetBgpvpn - bgpvpn_network_association_create = neutronclient.osc.v2.networking_bgpvpn.network_association:CreateBgpvpnNetAssoc - bgpvpn_network_association_delete = neutronclient.osc.v2.networking_bgpvpn.network_association:DeleteBgpvpnNetAssoc - bgpvpn_network_association_list = neutronclient.osc.v2.networking_bgpvpn.network_association:ListBgpvpnNetAssoc - bgpvpn_network_association_show = neutronclient.osc.v2.networking_bgpvpn.network_association:ShowBgpvpnNetAssoc - bgpvpn_router_association_create = neutronclient.osc.v2.networking_bgpvpn.router_association:CreateBgpvpnRouterAssoc - bgpvpn_router_association_delete = neutronclient.osc.v2.networking_bgpvpn.router_association:DeleteBgpvpnRouterAssoc - bgpvpn_router_association_list = neutronclient.osc.v2.networking_bgpvpn.router_association:ListBgpvpnRouterAssoc - bgpvpn_router_association_set = neutronclient.osc.v2.networking_bgpvpn.router_association:SetBgpvpnRouterAssoc - bgpvpn_router_association_show = neutronclient.osc.v2.networking_bgpvpn.router_association:ShowBgpvpnRouterAssoc - bgpvpn_router_association_unset = neutronclient.osc.v2.networking_bgpvpn.router_association:UnsetBgpvpnRouterAssoc - bgpvpn_port_association_create = neutronclient.osc.v2.networking_bgpvpn.port_association:CreateBgpvpnPortAssoc - bgpvpn_port_association_set = neutronclient.osc.v2.networking_bgpvpn.port_association:SetBgpvpnPortAssoc - bgpvpn_port_association_unset = neutronclient.osc.v2.networking_bgpvpn.port_association:UnsetBgpvpnPortAssoc - bgpvpn_port_association_delete = neutronclient.osc.v2.networking_bgpvpn.port_association:DeleteBgpvpnPortAssoc - bgpvpn_port_association_list = neutronclient.osc.v2.networking_bgpvpn.port_association:ListBgpvpnPortAssoc - bgpvpn_port_association_show = neutronclient.osc.v2.networking_bgpvpn.port_association:ShowBgpvpnPortAssoc network_loggable_resources_list = neutronclient.osc.v2.logging.network_log:ListLoggableResource network_log_create = neutronclient.osc.v2.logging.network_log:CreateNetworkLog