Improved IP/E-Line management of 5GTANGO LLCM.
authorpeusterm <manuel.peuster@uni-paderborn.de>
Thu, 18 Oct 2018 13:03:55 +0000 (15:03 +0200)
committerpeusterm <manuel.peuster@uni-paderborn.de>
Thu, 18 Oct 2018 13:24:29 +0000 (15:24 +0200)
Change-Id: I8e0c9d00e7470ef73b83d7e7d5bfde898116f632
Signed-off-by: peusterm <manuel.peuster@uni-paderborn.de>
pipeline_local.sh [new file with mode: 0755]
src/emuvim/api/tango/llcm.py
src/emuvim/dcemulator/net.py

diff --git a/pipeline_local.sh b/pipeline_local.sh
new file mode 100755 (executable)
index 0000000..e6e4018
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+# helper script to be executed before committing
+set -e
+# trigger pep8 style check
+echo "Doing flake8 style check ..."
+flake8 --exclude=.eggs,devops --ignore=E501 .
+echo "done."
+# trigger the tests
+echo "Running unit tests ..."
+sudo pytest -v
+echo "done."
index 3beacce..31abe74 100755 (executable)
@@ -74,7 +74,7 @@ DEPLOY_SAP = False
 
 # flag to indicate if we use bidirectional forwarding rules in the
 # automatic chaining process
-BIDIRECTIONAL_CHAIN = False
+BIDIRECTIONAL_CHAIN = True
 
 # override the management interfaces in the descriptors with default
 # docker0 interfaces in the containers
@@ -403,6 +403,9 @@ class Service(object):
                 volumes=volumes,
                 type=kwargs.get('type', 'docker'))
 
+            # add vnfd reference to vnfi
+            vnfi.vnfd = vnfd
+
             # rename the docker0 interfaces (eth0) to the management port name
             # defined in the VNFD
             if USE_DOCKER_MGMT:
@@ -655,6 +658,7 @@ class Service(object):
         # eg. different services get a unique cookie for their flowrules
         cookie = 1
         for link in eline_fwd_links:
+            LOG.info("Found E-Line: {}".format(link))
             # check if we need to deploy this link when its a management link:
             if USE_DOCKER_MGMT:
                 if self.check_mgmt_interface(
@@ -704,24 +708,34 @@ class Service(object):
 
             # Link between 2 VNFs
             else:
+                LOG.info("Creating E-Line: src={}, dst={}"
+                         .format(src_id, dst_id))
                 # make sure we use the correct sap vnf name
                 if src_sap_id in self.saps_int:
                     src_id = src_sap_id
                 if dst_sap_id in self.saps_int:
                     dst_id = dst_sap_id
-                # re-configure the VNFs IP assignment and ensure that a new
-                # subnet is used for each E-Link
+                # get involved vnfis
                 src_vnfi = self._get_vnf_instance(instance_uuid, src_id)
                 dst_vnfi = self._get_vnf_instance(instance_uuid, dst_id)
+
                 if src_vnfi is not None and dst_vnfi is not None:
+                    setChaining = True
+                    # re-configure the VNFs IP assignment and ensure that a new
+                    # subnet is used for each E-Link
                     eline_net = ELINE_SUBNETS.pop(0)
                     ip1 = "{0}/{1}".format(str(eline_net[1]),
                                            eline_net.prefixlen)
                     ip2 = "{0}/{1}".format(str(eline_net[2]),
                                            eline_net.prefixlen)
-                    self._vnf_reconfigure_network(src_vnfi, src_if_name, ip1)
-                    self._vnf_reconfigure_network(dst_vnfi, dst_if_name, ip2)
-                    setChaining = True
+                    # check if VNFs have fixed IPs (address field in VNFDs)
+                    if (self._get_vnfd_cp_from_vnfi(src_vnfi, src_if_name)
+                            .get("address") is None):
+                        self._vnf_reconfigure_network(src_vnfi, src_if_name, ip1)
+                    # check if VNFs have fixed IPs (address field in VNFDs)
+                    if (self._get_vnfd_cp_from_vnfi(dst_vnfi, dst_if_name)
+                            .get("address") is None):
+                        self._vnf_reconfigure_network(dst_vnfi, dst_if_name, ip2)
 
             # Set the chaining
             if setChaining:
@@ -729,9 +743,18 @@ class Service(object):
                     src_id, dst_id,
                     vnf_src_interface=src_if_name, vnf_dst_interface=dst_if_name,
                     bidirectional=BIDIRECTIONAL_CHAIN, cmd="add-flow", cookie=cookie, priority=10)
-                LOG.debug(
-                    "Setting up E-Line link. (%s:%s) -> (%s:%s)" % (
-                        src_id, src_if_name, dst_id, dst_if_name))
+
+    def _get_vnfd_cp_from_vnfi(self, vnfi, ifname):
+        """
+        Gets the connection point data structure from the VNFD
+        of the given VNFI using ifname.
+        """
+        if vnfi.vnfd is None:
+            return {}
+        cps = vnfi.vnfd.get("connection_points")
+        for cp in cps:
+            if cp.get("id") == ifname:
+                return cp
 
     def _connect_elans(self, elan_fwd_links, instance_uuid):
         """
index 005e272..1f30ba7 100755 (executable)
@@ -462,7 +462,7 @@ class DCNetwork(Containernet):
             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
@@ -484,7 +484,7 @@ class DCNetwork(Containernet):
 
             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)
@@ -666,7 +666,7 @@ class DCNetwork(Containernet):
                 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
@@ -706,7 +706,7 @@ class DCNetwork(Containernet):
 
             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)
@@ -746,6 +746,8 @@ class DCNetwork(Containernet):
             '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)