Fix: Added gevent monkey patch to fix issue that blocks
[osm/vim-emu.git] / src / emuvim / dcemulator / net.py
index 1f30ba7..58c2bff 100755 (executable)
 # 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(sys=True)
+
+# setup logging
 LOG = logging.getLogger("dcemulator.net")
 LOG.setLevel(logging.DEBUG)
 
@@ -760,6 +762,7 @@ class DCNetwork(Containernet):
         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)
@@ -827,6 +830,12 @@ class DCNetwork(Containernet):
 
                 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 = {}
@@ -898,14 +907,14 @@ class DCNetwork(Containernet):
     # 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'
@@ -913,15 +922,13 @@ class DCNetwork(Containernet):
         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):
@@ -942,6 +949,8 @@ class DCNetwork(Containernet):
             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:
@@ -949,7 +958,7 @@ class DCNetwork(Containernet):
 
         # 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))