# acknowledge the contributions of their colleagues of the SONATA
# partner consortium (www.sonata-nfv.eu).
import logging
-
-import site
import time
-from subprocess import Popen
import re
import requests
import os
import json
-
+import networkx as nx
+from subprocess import Popen
+from gevent import monkey
from mininet.net import Containernet
from mininet.node import OVSSwitch, OVSKernelSwitch, Docker, RemoteController
from mininet.cli import CLI
from mininet.link import TCLink
from mininet.clean import cleanup
-import networkx as nx
from emuvim.dcemulator.monitoring import DCNetworkMonitor
from emuvim.dcemulator.node import Datacenter, EmulatorCompute
from emuvim.dcemulator.resourcemodel import ResourceModelRegistrar
+# ensure correct functionality of all gevent based REST servers
+monkey.patch_all()
+
+# setup logging
LOG = logging.getLogger("dcemulator.net")
LOG.setLevel(logging.DEBUG)
return "No path could be found between {0} and {1}".format(
vnf_src_name, vnf_dst_name)
- LOG.info("Path between {0} and {1}: {2}".format(
+ LOG.debug("Creating path between {0} and {1}: {2}".format(
vnf_src_name, vnf_dst_name, path))
current_hop = src_sw
if next_hop == vnf_dst_name:
switch_outport_nr = dst_sw_outport_nr
- LOG.info("end node reached: {0}".format(vnf_dst_name))
+ LOG.debug("end node reached: {0}".format(vnf_dst_name))
elif not isinstance(next_node, OVSSwitch):
LOG.info("Next node: {0} is not a switch".format(next_hop))
return "Next node: {0} is not a switch".format(next_hop)
return "No path could be found between {0} and {1}".format(
vnf_src_name, vnf_dst_name)
- LOG.info("Path between {0} and {1}: {2}".format(
+ LOG.debug("Creating path between {0} and {1}: {2}".format(
vnf_src_name, vnf_dst_name, path))
current_hop = src_sw
if next_hop == vnf_dst_name:
switch_outport_nr = dst_sw_outport_nr
- LOG.info("end node reached: {0}".format(vnf_dst_name))
+ LOG.debug("end node reached: {0}".format(vnf_dst_name))
elif not isinstance(next_node, OVSSwitch):
LOG.info("Next node: {0} is not a switch".format(next_hop))
return "Next node: {0} is not a switch".format(next_hop)
'match_input': kwargs.get('match')
}
flow_options_str = json.dumps(flow_options, indent=1)
+ LOG.info("Installed flow rule: ({}:{}) -> ({}:{}) with options: {}"
+ .format(vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface, flow_options))
return "success: {2} between {0} and {1} with options: {3}".format(
vnf_src_name, vnf_dst_name, cmd, flow_options_str)
cmd = kwargs.get('cmd')
path = kwargs.get('path')
index = kwargs.get('pathindex')
+ mod_dl_dst = kwargs.get('mod_dl_dst')
vlan = kwargs.get('vlan')
priority = kwargs.get('priority', DEFAULT_PRIORITY)
else: # middle nodes
match += ',dl_vlan=%s' % vlan
+ if mod_dl_dst:
+ action = {}
+ action['type'] = 'SET_FIELD'
+ action['field'] = 'eth_dst'
+ action['value'] = mod_dl_dst
+ flow['actions'].append(action)
# output action must come last
action = {}
# start Ryu Openflow controller as Remote Controller for the DCNetwork
def startRyu(self, learning_switch=True):
# start Ryu controller with rest-API
- python_install_path = site.getsitepackages()[0]
+
# ryu default learning switch
- # ryu_path = python_install_path + '/ryu/app/simple_switch_13.py'
+ # ryu_learning_app = python_install_path + '/ryu/app/simple_switch_13.py'
# custom learning switch that installs a default NORMAL action in the
# ovs switches
dir_path = os.path.dirname(os.path.realpath(__file__))
- ryu_path = dir_path + '/son_emu_simple_switch_13.py'
- ryu_path2 = python_install_path + '/ryu/app/ofctl_rest.py'
+ ryu_learning_app = dir_path + '/son_emu_simple_switch_13.py'
+ ryu_rest_app = 'ryu.app.ofctl_rest'
# change the default Openflow controller port to 6653 (official IANA-assigned port number), as used by Mininet
# Ryu still uses 6633 as default
ryu_option = '--ofp-tcp-listen-port'
ryu_cmd = 'ryu-manager'
FNULL = open("/tmp/ryu.log", 'w')
if learning_switch:
- self.ryu_process = Popen(
- [ryu_cmd, ryu_path, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL)
- LOG.debug('starting ryu-controller with {0}'.format(ryu_path))
- LOG.debug('starting ryu-controller with {0}'.format(ryu_path2))
+ # learning and rest api
+ args = [ryu_cmd, ryu_learning_app, ryu_rest_app, ryu_option, ryu_of_port]
else:
# no learning switch, but with rest api
- self.ryu_process = Popen(
- [ryu_cmd, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL)
- LOG.debug('starting ryu-controller with {0}'.format(ryu_path2))
+ args = [ryu_cmd, ryu_rest_app, ryu_option, ryu_of_port]
+ self.ryu_process = Popen(args, stdout=FNULL, stderr=FNULL)
+ LOG.debug('starting ryu-controller with %s' % args)
time.sleep(1)
def killRyu(self):
url = self.ryu_REST_api + '/' + str(prefix) + '/' + str(dpid)
else:
url = self.ryu_REST_api + '/' + str(prefix)
+
+ LOG.debug('sending RYU command: %s, payload: %s', url, data)
if data:
req = self.RyuSession.post(url, json=data)
else:
# do extra logging if status code is not 200 (OK)
if req.status_code is not requests.codes.ok:
- logging.info(
+ LOG.info(
'type {0} encoding: {1} text: {2} headers: {3} history: {4}'.format(req.headers['content-type'],
req.encoding, req.text,
req.headers, req.history))