diff --git a/.zuul.yaml b/.zuul.yaml index e7b01da409..e1c1f970af 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -106,6 +106,7 @@ q-metering: true q-qos: true neutron-tag-ports-during-bulk-creation: true + neutron-conntrack-helper: true devstack_localrc: Q_AGENT: openvswitch Q_ML2_TENANT_NETWORK_TYPE: vxlan diff --git a/doc/source/cli/command-objects/network-l3-conntrack-helper.rst b/doc/source/cli/command-objects/network-l3-conntrack-helper.rst new file mode 100644 index 0000000000..badbab6337 --- /dev/null +++ b/doc/source/cli/command-objects/network-l3-conntrack-helper.rst @@ -0,0 +1,8 @@ +=========================== +network l3 conntrack helper +=========================== + +Network v2 + +.. autoprogram-cliff:: openstack.network.v2 + :command: network l3 conntrack helper * diff --git a/openstackclient/network/v2/l3_conntrack_helper.py b/openstackclient/network/v2/l3_conntrack_helper.py new file mode 100644 index 0000000000..dae259273f --- /dev/null +++ b/openstackclient/network/v2/l3_conntrack_helper.py @@ -0,0 +1,255 @@ +# 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. +# + +"""L3 Conntrack Helper action implementations""" + +import logging + +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils + +from openstackclient.i18n import _ +from openstackclient.network import sdk_utils + + +LOG = logging.getLogger(__name__) + + +def _get_columns(item): + column_map = {} + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + +def _get_attrs(client, parsed_args): + router = client.find_router(parsed_args.router, ignore_missing=False) + attrs = {'router_id': router.id} + if parsed_args.helper: + attrs['helper'] = parsed_args.helper + if parsed_args.protocol: + attrs['protocol'] = parsed_args.protocol + if parsed_args.port: + attrs['port'] = parsed_args.port + + return attrs + + +class CreateConntrackHelper(command.ShowOne): + _description = _("Create a new L3 conntrack helper") + + def get_parser(self, prog_name): + parser = super(CreateConntrackHelper, self).get_parser(prog_name) + parser.add_argument( + 'router', + metavar='', + help=_('Router for which conntrack helper will be created') + ) + parser.add_argument( + '--helper', + required=True, + metavar='', + help=_('The netfilter conntrack helper module') + ) + parser.add_argument( + '--protocol', + required=True, + metavar='', + help=_('The network protocol for the netfilter conntrack target ' + 'rule') + ) + parser.add_argument( + '--port', + required=True, + metavar='', + type=int, + help=_('The network port for the netfilter conntrack target rule') + ) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + + attrs = _get_attrs(client, parsed_args) + obj = client.create_conntrack_helper(attrs.pop('router_id'), **attrs) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters={}) + + return (display_columns, data) + + +class DeleteConntrackHelper(command.Command): + _description = _("Delete L3 conntrack helper") + + def get_parser(self, prog_name): + parser = super(DeleteConntrackHelper, self).get_parser(prog_name) + parser.add_argument( + 'router', + metavar='', + help=_('Router that the conntrack helper belong to') + ) + parser.add_argument( + 'conntrack_helper_ids', + metavar='', + nargs='+', + help=_('The ID of the conntrack helper(s) to delete') + ) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + result = 0 + + router = client.find_router(parsed_args.router, ignore_missing=False) + for ct_helper in parsed_args.conntrack_helper_ids: + try: + client.delete_conntrack_helper( + ct_helper, router.id, ignore_missing=False) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete L3 conntrack helper with " + "ID '%(ct_helper)s': %(e)s"), + {'ct_helper': ct_helper, 'e': e}) + + if result > 0: + total = len(parsed_args.conntrack_helper_ids) + msg = (_("%(result)s of %(total)s L3 conntrack helpers failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) + + +class ListConntrackHelper(command.Lister): + _description = _("List L3 conntrack helpers") + + def get_parser(self, prog_name): + parser = super(ListConntrackHelper, self).get_parser(prog_name) + parser.add_argument( + 'router', + metavar='', + help=_('Router that the conntrack helper belong to') + ) + parser.add_argument( + '--helper', + metavar='', + help=_('The netfilter conntrack helper module') + ) + parser.add_argument( + '--protocol', + metavar='', + help=_('The network protocol for the netfilter conntrack target ' + 'rule') + ) + parser.add_argument( + '--port', + metavar='', + help=_('The network port for the netfilter conntrack target rule') + ) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + columns = ( + 'id', + 'router_id', + 'helper', + 'protocol', + 'port', + ) + column_headers = ( + 'ID', + 'Router ID', + 'Helper', + 'Protocol', + 'Port', + ) + attrs = _get_attrs(client, parsed_args) + data = client.conntrack_helpers(attrs.pop('router_id'), **attrs) + + return (column_headers, + (utils.get_item_properties( + s, columns, formatters={}, + ) for s in data)) + + +class SetConntrackHelper(command.Command): + _description = _("Set L3 conntrack helper properties") + + def get_parser(self, prog_name): + parser = super(SetConntrackHelper, self).get_parser(prog_name) + parser.add_argument( + 'router', + metavar='', + help=_('Router that the conntrack helper belong to') + ) + parser.add_argument( + 'conntrack_helper_id', + metavar='', + help=_('The ID of the conntrack helper(s)') + ) + parser.add_argument( + '--helper', + metavar='', + help=_('The netfilter conntrack helper module') + ) + parser.add_argument( + '--protocol', + metavar='', + help=_('The network protocol for the netfilter conntrack target ' + 'rule') + ) + parser.add_argument( + '--port', + metavar='', + type=int, + help=_('The network port for the netfilter conntrack target rule') + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + attrs = _get_attrs(client, parsed_args) + if attrs: + client.update_conntrack_helper( + parsed_args.conntrack_helper_id, attrs.pop('router_id'), + **attrs) + + +class ShowConntrackHelper(command.ShowOne): + _description = _("Display L3 conntrack helper details") + + def get_parser(self, prog_name): + parser = super(ShowConntrackHelper, self).get_parser(prog_name) + parser.add_argument( + 'router', + metavar='', + help=_('Router that the conntrack helper belong to') + ) + parser.add_argument( + 'conntrack_helper_id', + metavar='', + help=_('The ID of the conntrack helper') + ) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + router = client.find_router(parsed_args.router, ignore_missing=False) + obj = client.get_conntrack_helper( + parsed_args.conntrack_helper_id, router.id) + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns, formatters={}) + + return (display_columns, data) diff --git a/openstackclient/tests/functional/network/v2/test_l3_conntrack_helper.py b/openstackclient/tests/functional/network/v2/test_l3_conntrack_helper.py new file mode 100644 index 0000000000..bbb9a7cd97 --- /dev/null +++ b/openstackclient/tests/functional/network/v2/test_l3_conntrack_helper.py @@ -0,0 +1,145 @@ +# 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 json +import uuid + +from openstackclient.tests.functional.network.v2 import common + + +class L3ConntrackHelperTests(common.NetworkTests): + + def setUp(self): + super(L3ConntrackHelperTests, self).setUp() + # Nothing in this class works with Nova Network + if not self.haz_network: + self.skipTest("No Network service present") + if not self.is_extension_enabled('l3-conntrack-helper'): + self.skipTest("No l3-conntrack-helper extension present") + if not self.is_extension_enabled('expose-l3-conntrack-helper'): + self.skipTest("No expose-l3-conntrack-helper extension present") + + def _create_router(self): + router_name = uuid.uuid4().hex + json_output = json.loads(self.openstack( + 'router create -f json ' + router_name + )) + self.assertIsNotNone(json_output['id']) + router_id = json_output['id'] + self.addCleanup(self.openstack, 'router delete ' + router_id) + return router_id + + def _create_helpers(self, router_id, helpers): + created_helpers = [] + for helper in helpers: + output = json.loads(self.openstack( + 'network l3 conntrack helper create %(router)s ' + '--helper %(helper)s --protocol %(protocol)s --port %(port)s ' + '-f json' % {'router': router_id, + 'helper': helper['helper'], + 'protocol': helper['protocol'], + 'port': helper['port']})) + self.assertEqual(helper['helper'], output['helper']) + self.assertEqual(helper['protocol'], output['protocol']) + self.assertEqual(helper['port'], output['port']) + created_helpers.append(output) + return created_helpers + + def test_l3_conntrack_helper_create_and_delete(self): + """Test create, delete multiple""" + + helpers = [ + { + 'helper': 'tftp', + 'protocol': 'udp', + 'port': 69 + }, { + 'helper': 'ftp', + 'protocol': 'tcp', + 'port': 21 + } + ] + router_id = self._create_router() + created_helpers = self._create_helpers(router_id, helpers) + ct_ids = " ".join([ct['id'] for ct in created_helpers]) + + raw_output = self.openstack( + '--debug network l3 conntrack helper delete %(router)s ' + '%(ct_ids)s' % { + 'router': router_id, 'ct_ids': ct_ids}) + self.assertOutput('', raw_output) + + def test_l3_conntrack_helper_list(self): + helpers = [ + { + 'helper': 'tftp', + 'protocol': 'udp', + 'port': 69 + }, { + 'helper': 'ftp', + 'protocol': 'tcp', + 'port': 21 + } + ] + expected_helpers = [ + { + 'Helper': 'tftp', + 'Protocol': 'udp', + 'Port': 69 + }, { + 'Helper': 'ftp', + 'Protocol': 'tcp', + 'Port': 21 + } + ] + router_id = self._create_router() + self._create_helpers(router_id, helpers) + output = json.loads(self.openstack( + 'network l3 conntrack helper list %s -f json ' % router_id + )) + for ct in output: + self.assertEqual(router_id, ct.pop('Router ID')) + ct.pop("ID") + self.assertIn(ct, expected_helpers) + + def test_l3_conntrack_helper_set_and_show(self): + helper = { + 'helper': 'tftp', + 'protocol': 'udp', + 'port': 69} + router_id = self._create_router() + created_helper = self._create_helpers(router_id, [helper])[0] + output = json.loads(self.openstack( + 'network l3 conntrack helper show %(router_id)s %(ct_id)s ' + '-f json' % { + 'router_id': router_id, 'ct_id': created_helper['id']})) + self.assertEqual(helper['helper'], output['helper']) + self.assertEqual(helper['protocol'], output['protocol']) + self.assertEqual(helper['port'], output['port']) + + raw_output = self.openstack( + 'network l3 conntrack helper set %(router_id)s %(ct_id)s ' + '--port %(port)s ' % { + 'router_id': router_id, + 'ct_id': created_helper['id'], + 'port': helper['port'] + 1}) + self.assertOutput('', raw_output) + + output = json.loads(self.openstack( + 'network l3 conntrack helper show %(router_id)s %(ct_id)s ' + '-f json' % { + 'router_id': router_id, 'ct_id': created_helper['id']})) + self.assertEqual(helper['port'] + 1, output['port']) + self.assertEqual(helper['helper'], output['helper']) + self.assertEqual(helper['protocol'], output['protocol']) diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py index e5023d43c5..ab77d719c0 100644 --- a/openstackclient/tests/unit/network/v2/fakes.py +++ b/openstackclient/tests/unit/network/v2/fakes.py @@ -1973,3 +1973,78 @@ class FakeFloatingIPPortForwarding(object): ) return mock.Mock(side_effect=port_forwardings) + + +class FakeL3ConntrackHelper(object): + """"Fake one or more L3 conntrack helper""" + + @staticmethod + def create_one_l3_conntrack_helper(attrs=None): + """Create a fake L3 conntrack helper. + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeResource object with protocol, port, etc. + """ + attrs = attrs or {} + router_id = ( + attrs.get('router_id') or 'router-id-' + uuid.uuid4().hex + ) + # Set default attributes. + ct_attrs = { + 'id': uuid.uuid4().hex, + 'router_id': router_id, + 'helper': 'tftp', + 'protocol': 'tcp', + 'port': randint(1, 65535), + } + + # Overwrite default attributes. + ct_attrs.update(attrs) + + ct = fakes.FakeResource( + info=copy.deepcopy(ct_attrs), + loaded=True + ) + return ct + + @staticmethod + def create_l3_conntrack_helpers(attrs=None, count=2): + """Create multiple fake L3 Conntrack helpers. + + :param Dictionary attrs: + A dictionary with all attributes + :param int count: + The number of L3 Conntrack helper rule to fake + :return: + A list of FakeResource objects faking the Conntrack helpers + """ + ct_helpers = [] + for i in range(0, count): + ct_helpers.append( + FakeL3ConntrackHelper.create_one_l3_conntrack_helper(attrs) + ) + return ct_helpers + + @staticmethod + def get_l3_conntrack_helpers(ct_helpers=None, count=2): + """Get a list of faked L3 Conntrack helpers. + + If ct_helpers list is provided, then initialize the Mock object + with the list. Otherwise create one. + + :param List ct_helpers: + A list of FakeResource objects faking conntrack helpers + :param int count: + The number of L3 conntrack helpers to fake + :return: + An iterable Mock object with side_effect set to a list of faked + L3 conntrack helpers + """ + if ct_helpers is None: + ct_helpers = ( + FakeL3ConntrackHelper.create_l3_conntrack_helpers(count) + ) + + return mock.Mock(side_effect=ct_helpers) diff --git a/openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py b/openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py new file mode 100644 index 0000000000..1676c9ffad --- /dev/null +++ b/openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py @@ -0,0 +1,316 @@ +# 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 osc_lib import exceptions + +from openstackclient.network.v2 import l3_conntrack_helper +from openstackclient.tests.unit.network.v2 import fakes as network_fakes +from openstackclient.tests.unit import utils as tests_utils + + +class TestConntrackHelper(network_fakes.TestNetworkV2): + + def setUp(self): + super(TestConntrackHelper, self).setUp() + # Get a shortcut to the network client + self.network = self.app.client_manager.network + self.router = network_fakes.FakeRouter.create_one_router() + self.network.find_router = mock.Mock(return_value=self.router) + + +class TestCreateL3ConntrackHelper(TestConntrackHelper): + + def setUp(self): + super(TestCreateL3ConntrackHelper, self).setUp() + attrs = {'router_id': self.router.id} + self.ct_helper = ( + network_fakes.FakeL3ConntrackHelper.create_one_l3_conntrack_helper( + attrs)) + self.columns = ( + 'helper', + 'id', + 'port', + 'protocol', + 'router_id' + ) + + self.data = ( + self.ct_helper.helper, + self.ct_helper.id, + self.ct_helper.port, + self.ct_helper.protocol, + self.ct_helper.router_id + ) + self.network.create_conntrack_helper = mock.Mock( + return_value=self.ct_helper) + + # Get the command object to test + self.cmd = l3_conntrack_helper.CreateConntrackHelper(self.app, + self.namespace) + + def test_create_no_options(self): + arglist = [] + verifylist = [] + + # Missing required args should bail here + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, verifylist) + + def test_create_default_options(self): + arglist = [ + '--helper', 'tftp', + '--protocol', 'udp', + '--port', '69', + self.router.id, + ] + + verifylist = [ + ('helper', 'tftp'), + ('protocol', 'udp'), + ('port', 69), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = (self.cmd.take_action(parsed_args)) + + self.network.create_conntrack_helper.assert_called_once_with( + self.router.id, + **{'helper': 'tftp', 'protocol': 'udp', + 'port': 69} + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_create_wrong_options(self): + arglist = [ + '--protocol', 'udp', + '--port', '69', + self.router.id, + ] + + self.assertRaises( + tests_utils.ParserException, + self.check_parser, + self.cmd, arglist, None) + + +class TestDeleteL3ConntrackHelper(TestConntrackHelper): + + def setUp(self): + super(TestDeleteL3ConntrackHelper, self).setUp() + attrs = {'router_id': self.router.id} + self.ct_helper = ( + network_fakes.FakeL3ConntrackHelper.create_one_l3_conntrack_helper( + attrs)) + self.network.delete_conntrack_helper = mock.Mock( + return_value=None) + + # Get the command object to test + self.cmd = l3_conntrack_helper.DeleteConntrackHelper(self.app, + self.namespace) + + def test_delete(self): + arglist = [ + self.ct_helper.router_id, + self.ct_helper.id + ] + verifylist = [ + ('conntrack_helper_ids', [self.ct_helper.id]), + ('router', self.ct_helper.router_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + self.network.delete_conntrack_helper.assert_called_once_with( + self.ct_helper.id, self.router.id, + ignore_missing=False) + self.assertIsNone(result) + + def test_delete_error(self): + arglist = [ + self.router.id, + self.ct_helper.id + ] + verifylist = [ + ('conntrack_helper_ids', [self.ct_helper.id]), + ('router', self.router.id), + ] + self.network.delete_conntrack_helper.side_effect = Exception( + 'Error message') + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, parsed_args) + + +class TestListL3ConntrackHelper(TestConntrackHelper): + + def setUp(self): + super(TestListL3ConntrackHelper, self).setUp() + attrs = {'router_id': self.router.id} + ct_helpers = ( + network_fakes.FakeL3ConntrackHelper.create_l3_conntrack_helpers( + attrs, count=3)) + self.columns = ( + 'ID', + 'Router ID', + 'Helper', + 'Protocol', + 'Port', + ) + self.data = [] + for ct_helper in ct_helpers: + self.data.append(( + ct_helper.id, + ct_helper.router_id, + ct_helper.helper, + ct_helper.protocol, + ct_helper.port, + )) + self.network.conntrack_helpers = mock.Mock( + return_value=ct_helpers) + + # Get the command object to test + self.cmd = l3_conntrack_helper.ListConntrackHelper(self.app, + self.namespace) + + def test_conntrack_helpers_list(self): + arglist = [ + self.router.id + ] + verifylist = [ + ('router', self.router.id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.conntrack_helpers.assert_called_once_with( + self.router.id) + self.assertEqual(self.columns, columns) + list_data = list(data) + self.assertEqual(len(self.data), len(list_data)) + for index in range(len(list_data)): + self.assertEqual(self.data[index], list_data[index]) + + +class TestSetL3ConntrackHelper(TestConntrackHelper): + + def setUp(self): + super(TestSetL3ConntrackHelper, self).setUp() + attrs = {'router_id': self.router.id} + self.ct_helper = ( + network_fakes.FakeL3ConntrackHelper.create_one_l3_conntrack_helper( + attrs)) + self.network.update_conntrack_helper = mock.Mock(return_value=None) + + # Get the command object to test + self.cmd = l3_conntrack_helper.SetConntrackHelper(self.app, + self.namespace) + + def test_set_nothing(self): + arglist = [ + self.router.id, + self.ct_helper.id, + ] + verifylist = [ + ('router', self.router.id), + ('conntrack_helper_id', self.ct_helper.id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = (self.cmd.take_action(parsed_args)) + + self.network.update_conntrack_helper.assert_called_once_with( + self.ct_helper.id, self.router.id + ) + self.assertIsNone(result) + + def test_set_port(self): + arglist = [ + self.router.id, + self.ct_helper.id, + '--port', '124', + ] + verifylist = [ + ('router', self.router.id), + ('conntrack_helper_id', self.ct_helper.id), + ('port', 124), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = (self.cmd.take_action(parsed_args)) + + self.network.update_conntrack_helper.assert_called_once_with( + self.ct_helper.id, self.router.id, port=124 + ) + self.assertIsNone(result) + + +class TestShowL3ConntrackHelper(TestConntrackHelper): + + def setUp(self): + super(TestShowL3ConntrackHelper, self).setUp() + attrs = {'router_id': self.router.id} + self.ct_helper = ( + network_fakes.FakeL3ConntrackHelper.create_one_l3_conntrack_helper( + attrs)) + self.columns = ( + 'helper', + 'id', + 'port', + 'protocol', + 'router_id' + ) + + self.data = ( + self.ct_helper.helper, + self.ct_helper.id, + self.ct_helper.port, + self.ct_helper.protocol, + self.ct_helper.router_id + ) + self.network.get_conntrack_helper = mock.Mock( + return_value=self.ct_helper) + + # Get the command object to test + self.cmd = l3_conntrack_helper.ShowConntrackHelper(self.app, + self.namespace) + + def test_show_no_options(self): + arglist = [] + verifylist = [] + + # Missing required args should bail here + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, verifylist) + + def test_show_default_options(self): + arglist = [ + self.router.id, + self.ct_helper.id, + ] + verifylist = [ + ('router', self.router.id), + ('conntrack_helper_id', self.ct_helper.id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = (self.cmd.take_action(parsed_args)) + + self.network.get_conntrack_helper.assert_called_once_with( + self.ct_helper.id, self.router.id + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) diff --git a/releasenotes/notes/L3-conntrack-helper-bd0d9da041747e84.yaml b/releasenotes/notes/L3-conntrack-helper-bd0d9da041747e84.yaml new file mode 100644 index 0000000000..de5348dc16 --- /dev/null +++ b/releasenotes/notes/L3-conntrack-helper-bd0d9da041747e84.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Add new commands ``network l3 conntrack helper create``, + ``network l3 conntrack helper set``, ``network l3 conntrack helper show``, + ``network l3 conntrack helper set`` and + ``network l3 conntrack helper delete`` to support Neutron L3 conntrack + helper CRUD operations. diff --git a/setup.cfg b/setup.cfg index d6d7a3d2b0..7084c70bf3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -448,6 +448,12 @@ openstack.network.v2 = network_show = openstackclient.network.v2.network:ShowNetwork network_unset = openstackclient.network.v2.network:UnsetNetwork + network_l3_conntrack_helper_create = openstackclient.network.v2.l3_conntrack_helper:CreateConntrackHelper + network_l3_conntrack_helper_delete = openstackclient.network.v2.l3_conntrack_helper:DeleteConntrackHelper + network_l3_conntrack_helper_list = openstackclient.network.v2.l3_conntrack_helper:ListConntrackHelper + network_l3_conntrack_helper_set = openstackclient.network.v2.l3_conntrack_helper:SetConntrackHelper + network_l3_conntrack_helper_show = openstackclient.network.v2.l3_conntrack_helper:ShowConntrackHelper + network_meter_create = openstackclient.network.v2.network_meter:CreateMeter network_meter_delete = openstackclient.network.v2.network_meter:DeleteMeter network_meter_list = openstackclient.network.v2.network_meter:ListMeter