X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2Fvim-emu.git;a=blobdiff_plain;f=src%2Femuvim%2Fapi%2Fopenstack%2Fresources%2Fport_chain.py;h=1f2a367bd7241eda31881e3a621022de9eeed3e4;hp=2e91159964111bee7a1136c6d027ad13c05c2804;hb=c6d9e9e619bb543da62009b30b3de8f7e5676817;hpb=7b38ee1ed94ec3e9124e8e5b9c21cf224d39edc3 diff --git a/src/emuvim/api/openstack/resources/port_chain.py b/src/emuvim/api/openstack/resources/port_chain.py index 2e91159..1f2a367 100644 --- a/src/emuvim/api/openstack/resources/port_chain.py +++ b/src/emuvim/api/openstack/resources/port_chain.py @@ -1,3 +1,28 @@ +# Copyright (c) 2015 SONATA-NFV and Paderborn University +# 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. +# +# Neither the name of the SONATA-NFV, Paderborn University +# nor the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# This work has been performed in the framework of the SONATA project, +# funded by the European Commission under Grant number 671517 through +# the Horizon 2020 and 5G-PPP programmes. The authors would like to +# acknowledge the contributions of their colleagues of the SONATA +# partner consortium (www.sonata-nfv.eu). import random import uuid import logging @@ -13,7 +38,8 @@ class PortChain(object): self.flow_classifiers = list() self.chain_parameters = dict() - # Cookie for internal identification of installed flows (e.g. to delete them) + # Cookie for internal identification of installed flows (e.g. to delete + # them) self.cookie = random.randint(1, 0xffffffff) def create_dict(self, compute): @@ -27,40 +53,52 @@ class PortChain(object): } return representation + def _get_port_pair(self, port_pair_group_id, compute): + port_pair_group = compute.find_port_pair_group_by_name_or_id(port_pair_group_id) + if len(port_pair_group.port_pairs) != 1: + raise RuntimeError("Only port pair groups with a single port pair are supported!") + return compute.find_port_pair_by_name_or_id(port_pair_group.port_pairs[0]) + def install(self, compute): + + port_pair_chain = map(lambda port_pair_group_id: self._get_port_pair(port_pair_group_id, compute), + self.port_pair_groups) + ingress_ports = map(lambda port_pair: port_pair.ingress, port_pair_chain) + egress_ports = map(lambda port_pair: port_pair.ingress, port_pair_chain) + chain_start = ingress_ports[0] + chain_rest = ingress_ports[1:] + + source_port_to_chain_start = [] for flow_classifier_id in self.flow_classifiers: flow_classifier = compute.find_flow_classifier_by_name_or_id(flow_classifier_id) if flow_classifier: - pass - # TODO: for every flow classifier create match and pass it to setChain + port = compute.find_port_by_name_or_id(flow_classifier.logical_source_port) + source_port_to_chain_start.append((port, chain_start)) - for group_id in self.port_pair_groups: - port_pair_group = compute.find_port_pair_group_by_name_or_id(group_id) - for port_pair_id in port_pair_group.port_pairs: - port_pair = compute.find_port_pair_by_name_or_id(port_pair_id) + chain = source_port_to_chain_start + zip(egress_ports, chain_rest) - server_ingress = None - server_egress = None - for server in compute.computeUnits.values(): - if port_pair.ingress.name in server.port_names: - server_ingress = server - elif port_pair.egress.name in server.port_names: - server_egress = server + for (egress_port, ingress_port) in chain: + server_egress = None + server_ingress = None + for server in compute.computeUnits.values(): + if egress_port.name in server.port_names or egress_port.id in server.port_names: + server_egress = server + if ingress_port.name in server.port_names or ingress_port.id in server.port_names: + server_ingress = server - # TODO: Not sure, if this should throw an error - if not server_ingress: - logging.warn("Neutron SFC: ingress port %s not connected." % str(port_pair.ingress.name)) - continue - if not server_egress: - logging.warn("Neutron SFC: egress port %s not connected." % str(port_pair.egress.name)) - continue + if not server_egress: + raise RuntimeError("Neutron SFC: egress port %s not connected to any server." % + egress_port.name) + if not server_ingress: + raise RuntimeError("Neutron SFC: ingress port %s not connected to any server." % + ingress_port.name) - compute.dc.net.setChain( - server_ingress.name, server_egress.name, - port_pair.ingress.intf_name, port_pair.egress.intf_name, - cmd="add-flow", cookie=self.cookie, priority=10, bidirectional=False, - monitor=False - ) + compute.dc.net.setChain( + server_egress.name, server_ingress.name, + egress_port.intf_name, ingress_port.intf_name, + cmd="add-flow", cookie=self.cookie, priority=10, bidirectional=False, + monitor=False, skip_vlan_tag=True + ) def uninstall(self, compute): # TODO: implement