Implemented Openstack Neutron SFC API
Signed-off-by: Malte Splietker <malte.splietker@gmail.com>
diff --git a/src/emuvim/api/openstack/resources/__init__.py b/src/emuvim/api/openstack/resources/__init__.py
index ffddf54..fca6c6c 100755
--- a/src/emuvim/api/openstack/resources/__init__.py
+++ b/src/emuvim/api/openstack/resources/__init__.py
@@ -2,6 +2,10 @@
from model import Model
from net import Net
from port import Port
+from port_pair import PortPair
+from port_pair_group import PortPairGroup
+from flow_classifier import FlowClassifier
+from port_chain import PortChain
from resource import Resource
from router import Router
from server import Server
diff --git a/src/emuvim/api/openstack/resources/flow_classifier.py b/src/emuvim/api/openstack/resources/flow_classifier.py
new file mode 100644
index 0000000..dff6638
--- /dev/null
+++ b/src/emuvim/api/openstack/resources/flow_classifier.py
@@ -0,0 +1,52 @@
+import uuid
+
+
+class FlowClassifier(object):
+ def __init__(self, name):
+ self.id = str(uuid.uuid4())
+ self.tenant_id = "abcdefghijklmnopqrstuvwxyz123456"
+ self.name = name
+ self.description = ""
+ self.ethertype = "IPv4"
+ self.protocol = None
+ self.source_port_range_min = 0
+ self.source_port_range_max = 0
+ self.destination_port_range_min = 0
+ self.destination_port_range_max = 0
+ self.source_ip_prefix = None
+ self.destination_ip_prefix = None
+ self.logical_source_port = ""
+ self.logical_destination_port = ""
+ self.l7_parameters = dict()
+
+ def create_dict(self, compute):
+ representation = {
+ "name": self.name,
+ "tenant_id": self.tenant_id,
+ "description": self.description,
+ "id": self.id,
+ }
+ if self.ethertype:
+ representation["ethertype"] = self.ethertype
+ if self.protocol:
+ representation["protocol"] = self.protocol
+ if self.source_port_range_min:
+ representation["source_port_range_min"] = self.source_port_range_min
+ if self.source_port_range_max:
+ representation["source_port_range_max"] = self.source_port_range_max
+ if self.destination_port_range_min:
+ representation["destination_port_range_min"] = self.destination_port_range_min
+ if self.destination_port_range_max:
+ representation["destination_port_range_max"] = self.destination_port_range_max
+ if self.source_ip_prefix:
+ representation["source_ip_prefix"] = self.source_ip_prefix
+ if self.destination_ip_prefix:
+ representation["destination_ip_prefix"] = self.destination_ip_prefix
+ if len(self.logical_source_port):
+ representation["logical_source_port"] = self.logical_source_port
+ if len(self.logical_destination_port):
+ representation["logical_destination_port"] = self.logical_destination_port
+ if len(self.l7_parameters.items()):
+ representation["l7_parameters"] = self.l7_parameters
+
+ return representation
diff --git a/src/emuvim/api/openstack/resources/port_chain.py b/src/emuvim/api/openstack/resources/port_chain.py
new file mode 100644
index 0000000..2e91159
--- /dev/null
+++ b/src/emuvim/api/openstack/resources/port_chain.py
@@ -0,0 +1,71 @@
+import random
+import uuid
+import logging
+
+
+class PortChain(object):
+ def __init__(self, name):
+ self.id = str(uuid.uuid4())
+ self.tenant_id = "abcdefghijklmnopqrstuvwxyz123456"
+ self.name = name
+ self.description = ""
+ self.port_pair_groups = list()
+ self.flow_classifiers = list()
+ self.chain_parameters = dict()
+
+ # Cookie for internal identification of installed flows (e.g. to delete them)
+ self.cookie = random.randint(1, 0xffffffff)
+
+ def create_dict(self, compute):
+ representation = {
+ "name": self.name,
+ "tenant_id": self.tenant_id,
+ "description": self.description,
+ "flow_classifiers": self.flow_classifiers,
+ "port_pair_groups": self.port_pair_groups,
+ "id": self.id
+ }
+ return representation
+
+ def install(self, compute):
+ for flow_classifier_id in self.flow_classifiers:
+ flow_classifier = compute.find_flow_classifier_by_name_or_id(flow_classifier_id)
+ if flow_classifier:
+ pass
+ # TODO: for every flow classifier create match and pass it to setChain
+
+ for group_id in self.port_pair_groups:
+ port_pair_group = compute.find_port_pair_group_by_name_or_id(group_id)
+ for port_pair_id in port_pair_group.port_pairs:
+ port_pair = compute.find_port_pair_by_name_or_id(port_pair_id)
+
+ server_ingress = None
+ server_egress = None
+ for server in compute.computeUnits.values():
+ if port_pair.ingress.name in server.port_names:
+ server_ingress = server
+ elif port_pair.egress.name in server.port_names:
+ server_egress = server
+
+ # TODO: Not sure, if this should throw an error
+ if not server_ingress:
+ logging.warn("Neutron SFC: ingress port %s not connected." % str(port_pair.ingress.name))
+ continue
+ if not server_egress:
+ logging.warn("Neutron SFC: egress port %s not connected." % str(port_pair.egress.name))
+ continue
+
+ compute.dc.net.setChain(
+ server_ingress.name, server_egress.name,
+ port_pair.ingress.intf_name, port_pair.egress.intf_name,
+ cmd="add-flow", cookie=self.cookie, priority=10, bidirectional=False,
+ monitor=False
+ )
+
+ def uninstall(self, compute):
+ # TODO: implement
+ logging.warn("Removing flows is currently not implemented.")
+
+ def update(self):
+ # TODO: implement
+ logging.warn("Updating flows is currently not implemented.")
diff --git a/src/emuvim/api/openstack/resources/port_pair.py b/src/emuvim/api/openstack/resources/port_pair.py
new file mode 100644
index 0000000..38b983e
--- /dev/null
+++ b/src/emuvim/api/openstack/resources/port_pair.py
@@ -0,0 +1,23 @@
+import uuid
+
+
+class PortPair(object):
+ def __init__(self, name):
+ self.id = str(uuid.uuid4())
+ self.tenant_id = "abcdefghijklmnopqrstuvwxyz123456"
+ self.name = name
+ self.description = ""
+ self.ingress = None
+ self.egress = None
+ self.service_function_parameters = dict()
+
+ def create_dict(self, compute):
+ representation = {
+ "name": self.name,
+ "tenant_id": self.tenant_id,
+ "description": self.description,
+ "ingress": self.ingress.id,
+ "egress": self.egress.id,
+ "id": self.id
+ }
+ return representation
diff --git a/src/emuvim/api/openstack/resources/port_pair_group.py b/src/emuvim/api/openstack/resources/port_pair_group.py
new file mode 100644
index 0000000..9514689
--- /dev/null
+++ b/src/emuvim/api/openstack/resources/port_pair_group.py
@@ -0,0 +1,22 @@
+import uuid
+
+
+class PortPairGroup(object):
+ def __init__(self, name):
+ self.id = str(uuid.uuid4())
+ self.tenant_id = "abcdefghijklmnopqrstuvwxyz123456"
+ self.name = name
+ self.description = ""
+ self.port_pairs = list()
+ self.port_pair_group_parameters = dict()
+
+ def create_dict(self, compute):
+ representation = {
+ "name": self.name,
+ "tenant_id": self.tenant_id,
+ "description": self.description,
+ "port_pairs": self.port_pairs,
+ "port_pair_group_parameters": self.port_pair_group_parameters,
+ "id": self.id
+ }
+ return representation
diff --git a/src/emuvim/api/openstack/resources/server.py b/src/emuvim/api/openstack/resources/server.py
index d20a2d4..654521a 100755
--- a/src/emuvim/api/openstack/resources/server.py
+++ b/src/emuvim/api/openstack/resources/server.py
@@ -7,6 +7,7 @@
self.image = image
self.command = command
self.port_names = list()
+ self.properties = dict()
self.flavor = flavor
self.son_emu_command = None
self.emulator_compute = None