merge with latest upstream status
[osm/vim-emu.git] / src / emuvim / dcemulator / node.py
index aa9fb4a..fd4b8fb 100755 (executable)
@@ -38,7 +38,6 @@ LOG.setLevel(logging.DEBUG)
 
 DCDPID_BASE = 1000  # start of switch dpid's used for data center switches
 
-
 class EmulatorCompute(Docker):
     """
     Emulator specific compute node class.
@@ -61,9 +60,17 @@ class EmulatorCompute(Docker):
         Helper method to receive information about the virtual networks
         this compute instance is connected to.
         """
-        # format list of tuples (name, Ip, MAC, isUp, status)
-        return [{'intf_name':str(i), 'ip':i.IP(), 'mac':i.MAC(), 'up':i.isUp(), 'status':i.status()}
-                for i in self.intfList()]
+        # get all links and find dc switch interface
+        networkStatusList = []
+        for i in self.intfList():
+            vnf_name = self.name
+            vnf_interface = str(i)
+            dc_port_name = self.datacenter.net.find_connected_dc_interface(vnf_name, vnf_interface)
+            # format list of tuples (name, Ip, MAC, isUp, status, dc_portname)
+            intf_dict = {'intf_name': str(i), 'ip': i.IP(), 'mac': i.MAC(), 'up': i.isUp(), 'status': i.status(), 'dc_portname': dc_port_name}
+            networkStatusList.append(intf_dict)
+
+        return networkStatusList
 
     def getStatus(self):
         """
@@ -83,6 +90,7 @@ class EmulatorCompute(Docker):
         status["memswap_limit"] = self.memswap_limit
         status["state"] = self.dcli.inspect_container(self.dc)["State"]
         status["id"] = self.dcli.inspect_container(self.dc)["Id"]
+        status["short_id"] = self.dcli.inspect_container(self.dc)["Id"][:12]
         status["datacenter"] = (None if self.datacenter is None
                                 else self.datacenter.label)
         return status
@@ -105,7 +113,7 @@ class Datacenter(object):
         self.name = "dc%d" % Datacenter.DC_COUNTER
         Datacenter.DC_COUNTER += 1
         # use this for user defined names that can be longer than self.name
-        self.label = label  
+        self.label = label
         # dict to store arbitrary metadata (e.g. latitude and longitude)
         self.metadata = metadata
         # path to which resource information should be logged (e.g. for experiments). None = no logging
@@ -140,7 +148,7 @@ class Datacenter(object):
     def start(self):
         pass
 
-    def startCompute(self, name, image=None, command=None, network=None, flavor_name="tiny"):
+    def startCompute(self, name, image=None, command=None, network=None, flavor_name="tiny", **params):
         """
         Create a new container as compute resource and connect it to this
         data center.
@@ -166,15 +174,30 @@ class Datacenter(object):
             if len(network) < 1:
                 network.append({})
 
+        # apply hard-set resource limits=0
+        cpu_percentage = kwargs.get('cpu_percent')
+        if cpu_percentage:
+            cpu_period = self.net.cpu_period
+            cpu_quota = self.net.cpu_period * float(cpu_percentage)
+        else:
+            cpu_quota = None
+            cpu_period = None
+
         # create the container
         d = self.net.addDocker(
             "%s" % (name),
             dimage=image,
             dcmd=command,
             datacenter=self,
-            flavor_name=flavor_name
+            flavor_name=flavor_name,
+            cpu_period = cpu_period,
+            cpu_quota = cpu_quota,
+            environment = {'VNF_NAME':name}
+            **params
         )
 
+
+
         # apply resource limits to container if a resource model is defined
         if self._resource_model is not None:
             try:
@@ -191,6 +214,9 @@ class Datacenter(object):
         # if no --net option is given, network = [{}], so 1 empty dict in the list
         # this results in 1 default interface with a default ip address
         for nw in network:
+            # clean up network configuration (e.g. RTNETLINK does not allow ':' in intf names
+            if nw.get("id") is not None:
+                nw["id"] = self._clean_ifname(nw["id"])
             # TODO we cannot use TCLink here (see: https://github.com/mpeuster/containernet/issues/3)
             self.net.addLink(d, self.switch, params1=nw, cls=Link, intfName1=nw.get('id'))
         # do bookkeeping
@@ -256,3 +282,19 @@ class Datacenter(object):
         self.net.rm_registrar.register(self, rm)
         LOG.info("Assigned RM: %r to DC: %r" % (rm, self))
 
+    @staticmethod
+    def _clean_ifname(name):
+        """
+        Cleans up given string to be a
+        RTNETLINK compatible interface name.
+        :param name: string
+        :return: string
+        """
+        if name is None:
+            return "if0"
+        name = name.replace(":", "-")
+        name = name.replace(" ", "-")
+        name = name.replace(".", "-")
+        name = name.replace("_", "-")
+        return name
+