merge rest api updates
diff --git a/src/emuvim/api/rest/compute.py b/src/emuvim/api/rest/compute.py
index 78b49e3..c3680a0 100755
--- a/src/emuvim/api/rest/compute.py
+++ b/src/emuvim/api/rest/compute.py
@@ -113,10 +113,10 @@
 class ComputeList(Resource):
     global dcs
 
-    def get(self, dc_label):
+    def get(self, dc_label=None):
         logging.debug("API CALL: compute list")
         try:
-            if dc_label == 'None':
+            if dc_label is None or dc_label == 'None':
                 # return list with all compute nodes in all DCs
                 all_containers = []
                 for dc in dcs.itervalues():
diff --git a/src/emuvim/api/rest/network.py b/src/emuvim/api/rest/network.py
index e3945b0..83fbde7 100755
--- a/src/emuvim/api/rest/network.py
+++ b/src/emuvim/api/rest/network.py
@@ -53,6 +53,7 @@
     :param match: OpenFlow match format of the flow entry
     :param bidirectional: boolean value if the link needs to be implemented from src to dst and back
     :param cookie: cookie value, identifier of the flow entry to be installed.
+    :param priority: integer indicating the priority of the flow entry
     :return: message string indicating if the chain action is succesful or not
     """
 
diff --git a/src/emuvim/api/rest/rest_api_endpoint.py b/src/emuvim/api/rest/rest_api_endpoint.py
index b586915..e382f5a 100755
--- a/src/emuvim/api/rest/rest_api_endpoint.py
+++ b/src/emuvim/api/rest/rest_api_endpoint.py
@@ -60,8 +60,11 @@
         self.api = Api(self.app)
 
         # setup endpoints
+
         self.api.add_resource(Compute, "/restapi/compute/<dc_label>/<compute_name>")
-        self.api.add_resource(ComputeList, "/restapi/compute/<dc_label>")
+        self.api.add_resource(ComputeList,
+                      "/restapi/compute",
+                      "/restapi/compute/<dc_label>")
 
         self.api.add_resource(DatacenterStatus, "/restapi/datacenter/<dc_label>")
         self.api.add_resource(DatacenterList, "/restapi/datacenter")
diff --git a/src/emuvim/api/sonata/dummygatekeeper.py b/src/emuvim/api/sonata/dummygatekeeper.py
index 0fb3aa0..916e168 100755
--- a/src/emuvim/api/sonata/dummygatekeeper.py
+++ b/src/emuvim/api/sonata/dummygatekeeper.py
@@ -166,7 +166,9 @@
         fwd_links = self.nsd["forwarding_graphs"][0]["constituent_virtual_links"]
         eline_fwd_links = [l for l in vlinks if (l["id"] in fwd_links) and (l["connectivity_type"] == "E-Line")]
 
-        cookie = 1  # not clear why this is needed - to check with Steven
+        # cookie is used as identifier for the flowrules installed by the dummygatekeeper
+        # eg. different services get a unique cookie for their flowrules
+        cookie = 1
         for link in eline_fwd_links:
             src_id, src_if_name = link["connection_points_reference"][0].split(":")
             dst_id, dst_if_name = link["connection_points_reference"][1].split(":")
@@ -187,7 +189,6 @@
                     src_docker_name, dst_docker_name,
                     vnf_src_interface=src_if_name, vnf_dst_interface=dst_if_name,
                     bidirectional=True, cmd="add-flow", cookie=cookie)
-                cookie += 1
 
                 # re-configure the VNFs IP assignment and ensure that a new subnet is used for each E-Link
                 src_vnfi = self._get_vnf_instance(instance_uuid, src_name)
diff --git a/src/emuvim/dcemulator/monitoring.py b/src/emuvim/dcemulator/monitoring.py
index 80b139c..ba04771 100755
--- a/src/emuvim/dcemulator/monitoring.py
+++ b/src/emuvim/dcemulator/monitoring.py
@@ -27,6 +27,7 @@
 """

 

 import logging

+import sys

 from mininet.node import  OVSSwitch

 import ast

 import time

@@ -348,6 +349,7 @@
                 data = {}

 

                 data['cookie'] = flow_dict['cookie']

+                data['cookie_mask'] = flow_dict['cookie']

 

                 if 'tx' in flow_dict['metric_key']:

                     data['match'] = {'in_port':flow_dict['mon_port']}

@@ -357,9 +359,15 @@
 

                 # query Ryu

                 ret = self.net.ryu_REST('stats/flow', dpid=flow_dict['switch_dpid'], data=data)

-                flow_stat_dict = ast.literal_eval(ret)

+                if isinstance(ret, dict):

+                    flow_stat_dict = ret

+                elif isinstance(ret, basestring):

+                    flow_stat_dict = ast.literal_eval(ret.rstrip())

+                else:

+                    flow_stat_dict = None

 

                 logging.debug('received flow stat:{0} '.format(flow_stat_dict))

+

                 self.set_flow_metric(flow_dict, flow_stat_dict)

 

             self.monitor_flow_lock.release()

@@ -446,13 +454,6 @@
         previous_monitor_time = metric_dict['previous_monitor_time']

         cookie = metric_dict['cookie']

 

-        # TODO aggregate all found flow stats

-        #flow_stat = flow_stat_dict[str(switch_dpid)][0]

-        #if 'bytes' in metric_key:

-        #    counter = flow_stat['byte_count']

-        #elif 'packet' in metric_key:

-        #    counter = flow_stat['packet_count']

-

         counter = 0

         for flow_stat in flow_stat_dict[str(switch_dpid)]:

             if 'bytes' in metric_key:

@@ -466,7 +467,10 @@
         self.prom_metrics[metric_dict['metric_key']]. \

             labels({'vnf_name': vnf_name, 'vnf_interface': vnf_interface, 'flow_id': cookie}). \

             set(counter)

-        pushadd_to_gateway(self.pushgateway, job='sonemu-SDNcontroller', registry=self.registry)

+        try:

+            pushadd_to_gateway(self.pushgateway, job='sonemu-SDNcontroller', registry=self.registry)

+        except Exception, e:

+            logging.warning("Pushgateway not reachable: {0} {1}".format(Exception, e))

 

 

     def start_Prometheus(self, port=9090):

diff --git a/src/emuvim/dcemulator/net.py b/src/emuvim/dcemulator/net.py
index bca20b2..15bb6f1 100755
--- a/src/emuvim/dcemulator/net.py
+++ b/src/emuvim/dcemulator/net.py
@@ -30,10 +30,8 @@
 import site
 import time
 from subprocess import Popen
-import os
 import re
-import urllib2
-from functools import partial
+import requests
 
 from mininet.net import Containernet
 from mininet.node import Controller, DefaultController, OVSSwitch, OVSKernelSwitch, Docker, RemoteController
@@ -94,9 +92,10 @@
         self.vlans = range(4096)[::-1]
 
         # link to Ryu REST_API
-        ryu_ip = '0.0.0.0'
+        ryu_ip = 'localhost'
         ryu_port = '8080'
         self.ryu_REST_api = 'http://{0}:{1}'.format(ryu_ip, ryu_port)
+        self.RyuSession = requests.Session()
 
         # monitoring agent
         if monitor:
@@ -261,8 +260,22 @@
     def CLI(self):
         CLI(self)
 
-    # to remove chain do setChain( src, dst, cmd='del-flows')
     def setChain(self, vnf_src_name, vnf_dst_name, vnf_src_interface=None, vnf_dst_interface=None, **kwargs):
+        """
+        Chain 2 vnf interfaces together by installing the flowrules in the switches along their path.
+        Currently the path is found using the default networkx shortest path function.
+        Each chain gets a unique vlan id , so different chains wil not interfere.
+
+        :param vnf_src_name: vnf name (string)
+        :param vnf_dst_name: vnf name (string)
+        :param vnf_src_interface: source interface name  (string)
+        :param vnf_dst_interface: destination interface name  (string)
+        :param cmd: 'add-flow' (default) to add a chain, 'del-flows' to remove a chain
+        :param cookie: cookie for the installed flowrules (can be used later as identifier for a set of installed chains)
+        :param match: custom match entry to be added to the flowrules (default: only in_port and vlan tag)
+        :param priority: custom flowrule priority
+        :return: output log string
+        """
         cmd = kwargs.get('cmd')
         if cmd == 'add-flow':
             ret = self._chainAddFlow(vnf_src_name, vnf_dst_name, vnf_src_interface, vnf_dst_interface, **kwargs)
@@ -533,22 +546,35 @@
         Popen(['pkill', '-f', 'ryu-manager'])
 
     def ryu_REST(self, prefix, dpid=None, data=None):
-        try:
-            if dpid:
-                url = self.ryu_REST_api + '/' + str(prefix) + '/' + str(dpid)
-            else:
-                url = self.ryu_REST_api + '/' + str(prefix)
-            if data:
-                #LOG.info('POST: {0}'.format(str(data)))
-                req = urllib2.Request(url, str(data))
-            else:
-                req = urllib2.Request(url)
 
-            ret = urllib2.urlopen(req).read()
+        if dpid:
+            url = self.ryu_REST_api + '/' + str(prefix) + '/' + str(dpid)
+        else:
+            url = self.ryu_REST_api + '/' + str(prefix)
+        if data:
+            req = self.RyuSession.post(url, json=data)
+        else:
+            req = self.RyuSession.get(url)
+
+
+        # do extra logging if status code is not 200 (OK)
+        if req.status_code is not requests.codes.ok:
+            logging.info(
+                'type {0}  encoding: {1} text: {2} headers: {3} history: {4}'.format(req.headers['content-type'],
+                                                                                     req.encoding, req.text,
+                                                                                     req.headers, req.history))
+            LOG.info('url: {0}'.format(str(url)))
+            if data: LOG.info('POST: {0}'.format(str(data)))
+            LOG.info('status: {0} reason: {1}'.format(req.status_code, req.reason))
+
+
+        if 'json' in req.headers['content-type']:
+            ret = req.json()
             return ret
-        except:
-            LOG.info('error url: {0}'.format(str(url)))
-            if data: LOG.info('error POST: {0}'.format(str(data)))
+
+        ret = req.text.rstrip()
+        return ret
+
 
     # 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