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():
: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
"""
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")
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(":")
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)
"""\r
\r
import logging\r
+import sys\r
from mininet.node import OVSSwitch\r
import ast\r
import time\r
data = {}\r
\r
data['cookie'] = flow_dict['cookie']\r
+ data['cookie_mask'] = flow_dict['cookie']\r
\r
if 'tx' in flow_dict['metric_key']:\r
data['match'] = {'in_port':flow_dict['mon_port']}\r
\r
# query Ryu\r
ret = self.net.ryu_REST('stats/flow', dpid=flow_dict['switch_dpid'], data=data)\r
- flow_stat_dict = ast.literal_eval(ret)\r
+ if isinstance(ret, dict):\r
+ flow_stat_dict = ret\r
+ elif isinstance(ret, basestring):\r
+ flow_stat_dict = ast.literal_eval(ret.rstrip())\r
+ else:\r
+ flow_stat_dict = None\r
\r
logging.debug('received flow stat:{0} '.format(flow_stat_dict))\r
+\r
self.set_flow_metric(flow_dict, flow_stat_dict)\r
\r
self.monitor_flow_lock.release()\r
previous_monitor_time = metric_dict['previous_monitor_time']\r
cookie = metric_dict['cookie']\r
\r
- # TODO aggregate all found flow stats\r
- #flow_stat = flow_stat_dict[str(switch_dpid)][0]\r
- #if 'bytes' in metric_key:\r
- # counter = flow_stat['byte_count']\r
- #elif 'packet' in metric_key:\r
- # counter = flow_stat['packet_count']\r
-\r
counter = 0\r
for flow_stat in flow_stat_dict[str(switch_dpid)]:\r
if 'bytes' in metric_key:\r
self.prom_metrics[metric_dict['metric_key']]. \\r
labels({'vnf_name': vnf_name, 'vnf_interface': vnf_interface, 'flow_id': cookie}). \\r
set(counter)\r
- pushadd_to_gateway(self.pushgateway, job='sonemu-SDNcontroller', registry=self.registry)\r
+ try:\r
+ pushadd_to_gateway(self.pushgateway, job='sonemu-SDNcontroller', registry=self.registry)\r
+ except Exception, e:\r
+ logging.warning("Pushgateway not reachable: {0} {1}".format(Exception, e))\r
\r
\r
def start_Prometheus(self, port=9090):\r
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
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:
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)
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