X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=src%2Femuvim%2Fdcemulator%2Fnet.py;h=ade984fbb54fa5183eaef295ba3e765830e363bf;hb=53d3c141d3fcd2e56e1dbc1cffd862b4f32010ff;hp=1adc8bcb518e4ad7abccad982b4abe702c82b13f;hpb=73efd195b7d0876b76af6caa7ba27fa5bb43fcb2;p=osm%2Fvim-emu.git diff --git a/src/emuvim/dcemulator/net.py b/src/emuvim/dcemulator/net.py index 1adc8bc..ade984f 100755 --- a/src/emuvim/dcemulator/net.py +++ b/src/emuvim/dcemulator/net.py @@ -1,6 +1,29 @@ """ -Distributed Cloud Emulator (dcemulator) -(c) 2015 by Manuel Peuster +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 [, ANY ADDITIONAL AFFILIATION] +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 logging @@ -21,6 +44,9 @@ from emuvim.dcemulator.monitoring import DCNetworkMonitor from emuvim.dcemulator.node import Datacenter, EmulatorCompute from emuvim.dcemulator.resourcemodel import ResourceModelRegistrar +LOG = logging.getLogger("dcemulator.net") +LOG.setLevel(logging.DEBUG) + class DCNetwork(Containernet): """ Wraps the original Mininet/Containernet class and provides @@ -87,7 +113,7 @@ class DCNetwork(Containernet): dc.net = self # set reference to network self.dcs[label] = dc dc.create() # finally create the data center in our Mininet instance - logging.info("added data center: %s" % label) + LOG.info("added data center: %s" % label) return dc def addLink(self, node1, node2, **params): @@ -97,7 +123,7 @@ class DCNetwork(Containernet): """ assert node1 is not None assert node2 is not None - logging.debug("addLink: n1=%s n2=%s" % (str(node1), str(node2))) + LOG.debug("addLink: n1=%s n2=%s" % (str(node1), str(node2))) # ensure type of node1 if isinstance( node1, basestring ): if node1 in self.dcs: @@ -238,7 +264,7 @@ class DCNetwork(Containernet): if kwargs.get('bidirectional'): ret = ret +'\n' + self._chainAddFlow(vnf_dst_name, vnf_src_name, vnf_dst_interface, vnf_src_interface, **kwargs) - elif cmd == 'del-flows': # TODO: del-flow to be implemented + elif cmd == 'del-flows': ret = self._chainAddFlow(vnf_src_name, vnf_dst_name, vnf_src_interface, vnf_dst_interface, **kwargs) if kwargs.get('bidirectional'): ret = ret + '\n' + self._chainAddFlow(vnf_dst_name, vnf_src_name, vnf_dst_interface, vnf_src_interface, **kwargs) @@ -251,7 +277,14 @@ class DCNetwork(Containernet): def _chainAddFlow(self, vnf_src_name, vnf_dst_name, vnf_src_interface=None, vnf_dst_interface=None, **kwargs): - # TODO: this needs to be cleaned up + src_sw = None + dst_sw = None + src_sw_inport_nr = 0 + dst_sw_outport_nr = 0 + + LOG.debug("call chainAddFlow vnf_src_name=%r, vnf_src_interface=%r, vnf_dst_name=%r, vnf_dst_interface=%r", + vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface) + #check if port is specified (vnf:port) if vnf_src_interface is None: # take first interface by default @@ -262,10 +295,10 @@ class DCNetwork(Containernet): for connected_sw in self.DCNetwork_graph.neighbors(vnf_src_name): link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw] for link in link_dict: - if link_dict[link]['src_port_id'] == vnf_src_interface: + if (link_dict[link]['src_port_id'] == vnf_src_interface or + link_dict[link]['src_port_name'] == vnf_src_interface): # Fix: we might also get interface names, e.g, from a son-emu-cli call # found the right link and connected switch src_sw = connected_sw - src_sw_inport_nr = link_dict[link]['dst_port_nr'] break @@ -279,7 +312,8 @@ class DCNetwork(Containernet): for connected_sw in self.DCNetwork_graph.neighbors(vnf_dst_name): link_dict = self.DCNetwork_graph[connected_sw][vnf_dst_name] for link in link_dict: - if link_dict[link]['dst_port_id'] == vnf_dst_interface: + if link_dict[link]['dst_port_id'] == vnf_dst_interface or \ + link_dict[link]['dst_port_name'] == vnf_dst_interface: # Fix: we might also get interface names, e.g, from a son-emu-cli call # found the right link and connected switch dst_sw = connected_sw dst_sw_outport_nr = link_dict[link]['src_port_nr'] @@ -292,10 +326,15 @@ class DCNetwork(Containernet): # if all shortest paths are wanted, use: all_shortest_paths path = nx.shortest_path(self.DCNetwork_graph, src_sw, dst_sw, weight=kwargs.get('weight')) except: - logging.info("No path could be found between {0} and {1}".format(vnf_src_name, vnf_dst_name)) + LOG.exception("No path could be found between {0} and {1} using src_sw={2} and dst_sw={3}".format( + vnf_src_name, vnf_dst_name, src_sw, dst_sw)) + LOG.debug("Graph nodes: %r" % self.DCNetwork_graph.nodes()) + LOG.debug("Graph edges: %r" % self.DCNetwork_graph.edges()) + for e, v in self.DCNetwork_graph.edges(): + LOG.debug("%r" % self.DCNetwork_graph[e][v]) return "No path could be found between {0} and {1}".format(vnf_src_name, vnf_dst_name) - logging.info("Path between {0} and {1}: {2}".format(vnf_src_name, vnf_dst_name, path)) + LOG.info("Path between {0} and {1}: {2}".format(vnf_src_name, vnf_dst_name, path)) current_hop = src_sw switch_inport_nr = src_sw_inport_nr @@ -320,9 +359,9 @@ class DCNetwork(Containernet): if next_hop == vnf_dst_name: switch_outport_nr = dst_sw_outport_nr - logging.info("end node reached: {0}".format(vnf_dst_name)) + LOG.info("end node reached: {0}".format(vnf_dst_name)) elif not isinstance( next_node, OVSSwitch ): - logging.info("Next node: {0} is not a switch".format(next_hop)) + LOG.info("Next node: {0} is not a switch".format(next_hop)) return "Next node: {0} is not a switch".format(next_hop) else: # take first link between switches by default @@ -452,7 +491,7 @@ class DCNetwork(Containernet): ofcmd = '' node.dpctl(cmd, ofcmd) - logging.info("{3} in switch: {0} in_port: {1} out_port: {2}".format(node.name, switch_inport_nr, + LOG.info("{3} in switch: {0} in_port: {1} out_port: {2}".format(node.name, switch_inport_nr, switch_outport_nr, cmd)) # start Ryu Openflow controller as Remote Controller for the DCNetwork @@ -486,7 +525,7 @@ class DCNetwork(Containernet): else: url = self.ryu_REST_api + '/' + str(prefix) if data: - #logging.info('POST: {0}'.format(str(data))) + #LOG.info('POST: {0}'.format(str(data))) req = urllib2.Request(url, str(data)) else: req = urllib2.Request(url) @@ -494,8 +533,8 @@ class DCNetwork(Containernet): ret = urllib2.urlopen(req).read() return ret except: - logging.info('error url: {0}'.format(str(url))) - if data: logging.info('error POST: {0}'.format(str(data))) + LOG.info('error url: {0}'.format(str(url))) + if data: LOG.info('error POST: {0}'.format(str(data))) # need to respect that some match fields must be integers # http://ryu.readthedocs.io/en/latest/app/ofctl_rest.html#description-of-match-and-actions