diff options
| author | Daire Ní Chatháin <daire.ni.chathain@intel.com> | 2017-06-20 15:34:28 +0000 |
|---|---|---|
| committer | Akihiro Motoki <amotoki@gmail.com> | 2017-10-30 10:40:59 +0000 |
| commit | e4b65ef29c1602a5a897a8e0cc05dff147defde3 (patch) | |
| tree | 7697966b37590564e3e3985766768405b1712c65 | |
| parent | 0907ccc4df68c71f1af71976819bff741829e434 (diff) | |
| download | python-neutronclient-e4b65ef29c1602a5a897a8e0cc05dff147defde3.tar.gz | |
Add Service Graphs networking-sfc resource
Co-Authored-By: Igor Duarte Cardoso <igor.duarte.cardoso@intel.com>
Partial-Bug: #1587486
Depends-On: I372da15f99f3cbfb7ffd1d8bf87a79bc56180afe
Change-Id: Ie54da56d2388cb375bccd883c111c5f87e293047
| -rw-r--r-- | doc/source/cli/osc/v2/networking-sfc.rst | 3 | ||||
| -rw-r--r-- | neutronclient/osc/v2/sfc/sfc_service_graph.py | 247 | ||||
| -rwxr-xr-x | neutronclient/tests/unit/osc/v2/sfc/fakes.py | 45 | ||||
| -rw-r--r-- | neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py | 336 | ||||
| -rw-r--r-- | neutronclient/v2_0/client.py | 26 | ||||
| -rw-r--r-- | releasenotes/notes/add-service-graph-ce4a25b3e32d70a6.yaml | 5 | ||||
| -rw-r--r-- | setup.cfg | 5 |
7 files changed, 667 insertions, 0 deletions
diff --git a/doc/source/cli/osc/v2/networking-sfc.rst b/doc/source/cli/osc/v2/networking-sfc.rst index 09d13d6..4f4242d 100644 --- a/doc/source/cli/osc/v2/networking-sfc.rst +++ b/doc/source/cli/osc/v2/networking-sfc.rst @@ -34,3 +34,6 @@ Network v2 .. autoprogram-cliff:: openstack.neutronclient.v2 :command: sfc port pair group * + +.. autoprogram-cliff:: openstack.neutronclient.v2 + :command: sfc service graph * diff --git a/neutronclient/osc/v2/sfc/sfc_service_graph.py b/neutronclient/osc/v2/sfc/sfc_service_graph.py new file mode 100644 index 0000000..53edff8 --- /dev/null +++ b/neutronclient/osc/v2/sfc/sfc_service_graph.py @@ -0,0 +1,247 @@ +# Copyright 2017 Intel 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. + +import logging + +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils + +from neutronclient._i18n import _ +from neutronclient.osc import utils as nc_osc_utils + +LOG = logging.getLogger(__name__) + +resource = 'service_graph' + +_attr_map = ( + ('id', 'ID', nc_osc_utils.LIST_BOTH), + ('name', 'Name', nc_osc_utils.LIST_BOTH), + ('port_chains', 'Branching Points', nc_osc_utils.LIST_BOTH), + ('description', 'Description', nc_osc_utils.LIST_LONG_ONLY), + ('project_id', 'Project', nc_osc_utils.LIST_LONG_ONLY), +) + + +class CreateSfcServiceGraph(command.ShowOne): + """Create a service graph.""" + def get_parser(self, prog_name): + parser = super(CreateSfcServiceGraph, self).get_parser(prog_name) + parser.add_argument( + 'name', + metavar='<name>', + help=_('Name of the service graph.')) + parser.add_argument( + '--description', + help=_('Description for the service graph.')) + parser.add_argument( + '--branching-point', + metavar='SRC_CHAIN:DST_CHAIN_1,DST_CHAIN_2,DST_CHAIN_N', + dest='branching_points', + action='append', + default=[], required=True, + help=_('Service graph branching point: the key is the source ' + 'Port Chain while the value is a list of destination ' + 'Port Chains. This option can be repeated.')) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.neutronclient + 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 = nc_osc_utils.get_columns(obj, _attr_map) + data = utils.get_dict_properties(obj, columns) + return display_columns, data + except Exception as e: + msg = (_("Failed to create service graph using '%(pcs)s': %(e)s") + % {'pcs': parsed_args.branching_points, 'e': e}) + raise exceptions.CommandError(msg) + + +class SetSfcServiceGraph(command.Command): + _description = _("Set service graph properties") + + def get_parser(self, prog_name): + parser = super(SetSfcServiceGraph, self).get_parser(prog_name) + parser.add_argument( + '--name', + metavar='<name>', + help=_('Name of the service graph')) + parser.add_argument( + '--description', + metavar='<description>', + help=_('Description for the service graph')) + parser.add_argument( + 'service_graph', + metavar='<service-graph>', + help=_("Service graph to modify (name or ID)") + ) + 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) + 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) + except Exception as e: + msg = (_("Failed to update service graph " + "'%(service_graph)s': %(e)s") + % {'service_graph': parsed_args.service_graph, 'e': e}) + raise exceptions.CommandError(msg) + + +class DeleteSfcServiceGraph(command.Command): + """Delete a given service graph.""" + + def get_parser(self, prog_name): + parser = super(DeleteSfcServiceGraph, self).get_parser(prog_name) + parser.add_argument( + 'service_graph', + metavar="<service-graph>", + help=_("ID or name of the service graph 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) + + +class ListSfcServiceGraph(command.Lister): + _description = _("List service graphs") + + def get_parser(self, prog_name): + parser = super(ListSfcServiceGraph, 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_sfc_service_graphs() + headers, columns = nc_osc_utils.get_column_definitions( + _attr_map, long_listing=parsed_args.long) + return (headers, + (utils.get_dict_properties(s, columns) + for s in data['service_graphs'])) + + +class ShowSfcServiceGraph(command.ShowOne): + """Show information of a given service graph.""" + + def get_parser(self, prog_name): + parser = super(ShowSfcServiceGraph, self).get_parser(prog_name) + parser.add_argument( + 'service_graph', + metavar="<service-graph>", + help=_("ID or name of the service graph to display.") + ) + 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 = nc_osc_utils.get_columns(obj, _attr_map) + data = utils.get_dict_properties(obj, columns) + return display_columns, data + + +def _get_common_attrs(client_manager, parsed_args, is_create=True): + 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 is_create: + _get_attrs_for_create(client_manager, attrs, parsed_args) + return attrs + + +def _validate_destination_chains(comma_split, attrs, client_manager, sc_): + for e in comma_split: + if e != "": + dc_ = _get_id(client_manager.neutronclient, e, 'port_chain') + attrs['port_chains'][sc_].append(dc_) + if _check_cycle(attrs['port_chains'], sc_, dc_): + raise(exceptions.CommandError( + "Error: Service graph contains a cycle")) + else: + raise exceptions.CommandError( + "Error: you must specify at least one " + "destination chain for each source chain") + return attrs + + +def _check_cycle(graph, new_src, new_dest): + for src in graph: + if src == new_dest: + if _visit(graph, src, new_dest, new_src): + return True + return False + + +def _visit(graph, src, new_dest, new_src): + if src in graph: + found_cycle = False + for dest in graph[src]: + if new_src == dest or found_cycle: + return True + else: + found_cycle = _visit(graph, dest, new_dest, new_src) + return False + + +def _get_attrs_for_create(client_manager, attrs, parsed_args): + if parsed_args.branching_points: + attrs['port_chains'] = {} + src_chain = None + for c in parsed_args.branching_points: + if ':' not in c: + raise exceptions.CommandError( + "Error: You must specify at least one " + "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') + for i in colon_split: + comma_split = i.split(',') + unique = set(comma_split) + if len(unique) != len(comma_split): + raise exceptions.CommandError( + "Error: Duplicate " + "destination chains from " + "source chain {}".format(src_chain)) + if sc_ in attrs['port_chains']: + raise exceptions.CommandError( + "Error: Source chain {} is in " + "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'] diff --git a/neutronclient/tests/unit/osc/v2/sfc/fakes.py b/neutronclient/tests/unit/osc/v2/sfc/fakes.py index 54bd5a8..5ae1144 100755 --- a/neutronclient/tests/unit/osc/v2/sfc/fakes.py +++ b/neutronclient/tests/unit/osc/v2/sfc/fakes.py @@ -232,3 +232,48 @@ class FakeSfcPortChain(object): for _ in range(count): port_chains.append(FakeSfcPortChain.create_port_chain(attrs)) return port_chains + + +class FakeSfcServiceGraph(object): + """Fake service graph attributes.""" + + @staticmethod + def create_sfc_service_graph(attrs=None): + """Create a fake service graph. + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A Dictionary with faking service graph attributes + """ + attrs = attrs or {} + + # Set default attributes. + service_graph_attrs = { + 'id': uuidutils.generate_uuid(), + 'name': 'port-pair-group-name', + 'description': 'description', + 'port_chains': {uuidutils.generate_uuid(): [ + uuidutils.generate_uuid()]}, + 'project_id': uuidutils.generate_uuid(), + } + + service_graph_attrs.update(attrs) + return copy.deepcopy(service_graph_attrs) + + @staticmethod + def create_sfc_service_graphs(attrs=None, count=1): + """Create multiple service graphs. + + :param Dictionary attrs: + A dictionary with all attributes + :param int count: + The number of service graphs to fake + :return: + A list of dictionaries faking the service graphs. + """ + service_graphs = [] + for _ in range(count): + service_graphs.append( + FakeSfcServiceGraph.create_sfc_service_graph(attrs)) + return service_graphs diff --git a/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py b/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py new file mode 100644 index 0000000..da12aa5 --- /dev/null +++ b/neutronclient/tests/unit/osc/v2/sfc/test_service_graph.py @@ -0,0 +1,336 @@ +# Copyright 2017 Intel 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. + +import mock +from osc_lib import exceptions +from osc_lib.tests import utils as tests_utils + +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) + columns = ('ID', 'Name', 'Branching Points') + columns_long = ('ID', 'Name', 'Branching Points', 'Description', 'Project') + _service_graph = _service_graphs[0] + data = [ + _service_graph['id'], + _service_graph['name'], + _service_graph['port_chains'] + ] + data_long = [ + _service_graph['id'], + _service_graph['name'], + _service_graph['port_chains'], + _service_graph['description'], + _service_graph['project_id'] + ] + _service_graph1 = {'service_graphs': _service_graph} + _service_graph_id = _service_graph['id'] + + 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} + ) + # Get the command object to test + self.cmd = sfc_service_graph.ListSfcServiceGraph( + self.app, self.namespace) + + def test_list_sfc_service_graphs(self): + arglist = [] + 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'] + sg = sgs[0] + data = [ + sg['id'], + sg['name'], + sg['port_chains'] + ] + self.assertEqual(list(self.columns), columns) + self.assertEqual(self.data, data) + + def test_list_sfc_service_graphs_with_long_option(self): + arglist = ['--long'] + 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'] + sg = sgs[0] + data = [ + sg['id'], + sg['name'], + sg['port_chains'], + sg['description'], + sg['project_id'] + ] + self.assertEqual(list(self.columns_long), columns) + self.assertEqual(self.data_long, data) + + +class TestCreateSfcServiceGraph(fakes.TestNeutronClientOSCV2): + _service_graph = fakes.FakeSfcServiceGraph.create_sfc_service_graph() + + columns = ('ID', 'Name', 'Branching Points') + columns_long = ('Branching Points', 'Description', 'ID', 'Name', 'Project') + + def get_data(self): + return ( + self._service_graph['port_chains'], + self._service_graph['description'], + self._service_graph['id'], + self._service_graph['name'], + self._service_graph['project_id'], + ) + + 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.data = self.get_data() + self.cmd = sfc_service_graph.CreateSfcServiceGraph( + self.app, self.namespace) + + def test_create_sfc_service_graph(self): + arglist = [] + verifylist = [] + + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, verifylist) + + def test_create_sfc_service_graph_without_loop(self): + bp1_str = 'pc1:pc2,pc3' + bp2_str = 'pc2:pc4' + self.cmd = sfc_service_graph.CreateSfcServiceGraph( + self.app, self.namespace) + + arglist = [ + "--description", self._service_graph['description'], + "--branching-point", bp1_str, + "--branching-point", bp2_str, + self._service_graph['name']] + + pcs = {'pc1': ['pc2', 'pc3'], 'pc2': ['pc4']} + + verifylist = [ + ("description", self._service_graph['description']), + ("branching_points", [bp1_str, bp2_str]), + ("name", self._service_graph['name']) + ] + + 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': { + 'description': self._service_graph['description'], + 'name': self._service_graph['name'], + 'port_chains': pcs + } + }) + self.assertEqual(self.columns_long, columns) + self.assertEqual(self.data, data) + + def test_create_sfc_service_graph_with_loop(self): + bp1_str = 'pc1:pc2,pc3;' + bp2_str = 'pc2:pc1' + self.cmd = sfc_service_graph.CreateSfcServiceGraph( + self.app, self.namespace) + + arglist = [ + "--description", self._service_graph['description'], + "--branching-point", bp1_str, + "--branching-point", bp2_str, + self._service_graph['name']] + + verifylist = [ + ("description", self._service_graph['description']), + ("branching_points", [bp1_str, bp2_str]), + ("name", self._service_graph['name']) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args) + + def test_create_sfc_service_graph_invalid_port_chains(self): + bp1_str = 'pc1:pc2,pc3:' + self.cmd = sfc_service_graph.CreateSfcServiceGraph( + self.app, self.namespace) + + arglist = [ + "--description", self._service_graph['description'], + "--branching-point", bp1_str, + self._service_graph['name']] + + verifylist = [ + ("description", self._service_graph['description']), + ("branching_points", [bp1_str]), + ("name", self._service_graph['name']) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args) + + def test_create_sfc_service_graph_duplicate_src_chains(self): + bp1_str = 'pc1:pc2,pc3;' + bp2_str = 'pc1:pc4' + self.cmd = sfc_service_graph.CreateSfcServiceGraph( + self.app, self.namespace) + + arglist = [ + "--description", self._service_graph['description'], + "--branching-point", bp1_str, + "--branching-point", bp2_str, + self._service_graph['name']] + + verifylist = [ + ("description", self._service_graph['description']), + ("branching_points", [bp1_str, bp2_str]), + ("name", self._service_graph['name']) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args) + + +class TestDeleteSfcServiceGraph(fakes.TestNeutronClientOSCV2): + + _service_graph = fakes.FakeSfcServiceGraph.create_sfc_service_graphs( + count=1) + + def setUp(self): + super(TestDeleteSfcServiceGraph, self).setUp() + self.neutronclient.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 + mock_service_graph_delete = client.delete_sfc_service_graph + arglist = [ + self._service_graph[0]['id'], + ] + verifylist = [ + ('service_graph', self._service_graph[0]['id']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + mock_service_graph_delete.assert_called_once_with( + self._service_graph[0]['id']) + self.assertIsNone(result) + + +class TestShowSfcServiceGraph(fakes.TestNeutronClientOSCV2): + + _sg = fakes.FakeSfcServiceGraph.create_sfc_service_graph() + columns = ('ID', 'Name', 'Branching Points') + columns_long = ('Branching Points', 'Description', 'ID', 'Name', 'Project') + data = ( + _sg['id'], + _sg['name'], + _sg['port_chains'] + ) + data_long = ( + _sg['port_chains'], + _sg['description'], + _sg['id'], + _sg['name'], + _sg['project_id'] + ) + + _service_graph = {'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( + return_value=self._service_graph + ) + # Get the command object to test + self.cmd = sfc_service_graph.ShowSfcServiceGraph( + 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 + arglist = [ + self._service_graph_id, + ] + verifylist = [ + ('service_graph', self._service_graph_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + mock_service_graph_show.assert_called_once_with(self._service_graph_id) + self.assertEqual(self.columns_long, columns) + self.assertEqual(self.data_long, data) + + +class TestSetSfcServiceGraph(fakes.TestNeutronClientOSCV2): + _service_graph = fakes.FakeSfcServiceGraph.create_sfc_service_graph() + _service_graph_name = _service_graph['name'] + _service_graph_id = _service_graph['id'] + + 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( + 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 + mock_service_graph_update = client.update_sfc_service_graph + arglist = [ + self._service_graph_name, + '--name', 'name_updated', + '--description', 'desc_updated' + ] + verifylist = [ + ('service_graph', self._service_graph_name), + ('name', 'name_updated'), + ('description', 'desc_updated'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + attrs = {'service_graph': { + 'name': 'name_updated', + 'description': 'desc_updated'} + } + mock_service_graph_update.assert_called_once_with( + self._service_graph_name, attrs) + self.assertIsNone(result) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index f4e49f8..2384705 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -518,6 +518,8 @@ class Client(ClientBase): sfc_port_pair_group_path = "/sfc/port_pair_groups/%s" sfc_port_chains_path = "/sfc/port_chains" sfc_port_chain_path = "/sfc/port_chains/%s" + sfc_service_graphs_path = "/sfc/service_graphs" + sfc_service_graph_path = "/sfc/service_graphs/%s" endpoint_groups_path = "/vpn/endpoint-groups" endpoint_group_path = "/vpn/endpoint-groups/%s" @@ -704,6 +706,7 @@ class Client(ClientBase): 'port_pairs': 'port_pair', 'port_pair_groups': 'port_pair_group', 'port_chains': 'port_chain', + 'service_graphs': 'service_graph', } def list_ext(self, collection, path, retrieve_all, **_params): @@ -2260,6 +2263,29 @@ class Client(ClientBase): return self.get(self.sfc_flow_classifier_path % (flow_classifier), params=_params) + def create_sfc_service_graph(self, body=None): + """Create the specified Service Graph.""" + return self.post(self.sfc_service_graphs_path, body=body) + + def update_sfc_service_graph(self, service_graph, body=None): + """Update a Service Graph.""" + return self.put(self.sfc_service_graph_path % service_graph, + body=body) + + def delete_sfc_service_graph(self, service_graph): + """Deletes the specified Service Graph.""" + return self.delete(self.sfc_service_graph_path % service_graph) + + def list_sfc_service_graphs(self, retrieve_all=True, **_params): + """Fetches a list of all Service Graphs.""" + return self.list('service_graphs', self.sfc_service_graphs_path, + retrieve_all, **_params) + + def show_sfc_service_graph(self, service_graph, **_params): + """Fetches information of a certain Service Graph.""" + return self.get(self.sfc_service_graph_path % service_graph, + params=_params) + 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-service-graph-ce4a25b3e32d70a6.yaml b/releasenotes/notes/add-service-graph-ce4a25b3e32d70a6.yaml new file mode 100644 index 0000000..f0b52ab --- /dev/null +++ b/releasenotes/notes/add-service-graph-ce4a25b3e32d70a6.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Added support for SFC Service Graph resource. + Related RFE: https://bugs.launchpad.net/networking-sfc/+bug/1587486. @@ -64,6 +64,11 @@ openstack.neutronclient.v2 = sfc_port_pair_group_set = neutronclient.osc.v2.sfc.sfc_port_pair_group:SetSfcPortPairGroup sfc_port_pair_group_show = neutronclient.osc.v2.sfc.sfc_port_pair_group:ShowSfcPortPairGroup sfc_port_pair_group_unset = neutronclient.osc.v2.sfc.sfc_port_pair_group:UnsetSfcPortPairGroup + sfc_service_graph_create = neutronclient.osc.v2.sfc.sfc_service_graph:CreateSfcServiceGraph + sfc_service_graph_delete = neutronclient.osc.v2.sfc.sfc_service_graph:DeleteSfcServiceGraph + sfc_service_graph_set = neutronclient.osc.v2.sfc.sfc_service_graph:SetSfcServiceGraph + sfc_service_graph_list = neutronclient.osc.v2.sfc.sfc_service_graph:ListSfcServiceGraph + sfc_service_graph_show = neutronclient.osc.v2.sfc.sfc_service_graph:ShowSfcServiceGraph firewall_group_create = neutronclient.osc.v2.fwaas.firewallgroup:CreateFirewallGroup firewall_group_delete = neutronclient.osc.v2.fwaas.firewallgroup:DeleteFirewallGroup |
