cpu resource control via rest api + unittest including ELAN test
authorstevenvanrossem <steven.vanrossem@intec.ugent.be>
Wed, 16 Nov 2016 22:30:57 +0000 (23:30 +0100)
committerstevenvanrossem <steven.vanrossem@intec.ugent.be>
Wed, 16 Nov 2016 22:30:57 +0000 (23:30 +0100)
Vagrantfile [changed mode: 0644->0755]
setup-cli.py [changed mode: 0644->0755]
src/emuvim/api/rest/compute.py
src/emuvim/api/rest/rest_api_endpoint.py
src/emuvim/dcemulator/net.py
src/emuvim/dcemulator/node.py
src/emuvim/test/unittests/test_sonata_dummy_gatekeeper.py

old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index c3680a0..f0c8954 100755 (executable)
@@ -48,8 +48,13 @@ class Compute(Resource):
     """
     global dcs
 
-    def put(self, dc_label, compute_name):
+    def put(self, dc_label, compute_name, resource=None, value=None):
+        # check if resource update
+        if resource and value:
+           c = self._update_resource(dc_label, compute_name, resource, value)
+           return c.getStatus(), 200
 
+        # deploy new container
         # check if json data is a dict
         data = request.json
         if data is None:
@@ -72,6 +77,20 @@ class Compute(Resource):
             logging.exception("API error.")
             return ex.message, 500
 
+    def _update_resource(self, dc_label, compute_name, resource, value):
+        #check if container exists
+        d = dcs.get(dc_label).net.getNodeByName(compute_name)
+        if resource == 'cpu':
+            cpu_period = int(dcs.get(dc_label).net.cpu_period)
+            cpu_quota = int(cpu_period * float(value))
+            #put default values back
+            if float(value) <= 0:
+                cpu_period = 100000
+                cpu_quota = -1
+            d.updateCpuLimit(cpu_period=cpu_period, cpu_quota=cpu_quota)
+        return d
+
+
     def get(self, dc_label, compute_name):
 
         logging.debug("API CALL: compute status")
index e382f5a..a065e16 100755 (executable)
@@ -61,7 +61,9 @@ class RestApiEndpoint(object):
 
         # setup endpoints
 
-        self.api.add_resource(Compute, "/restapi/compute/<dc_label>/<compute_name>")
+        self.api.add_resource(Compute,
+                              "/restapi/compute/<dc_label>/<compute_name>",
+                              "/restapi/compute/<dc_label>/<compute_name>/<resource>/<value>")
         self.api.add_resource(ComputeList,
                       "/restapi/compute",
                       "/restapi/compute/<dc_label>")
index 731331b..3b4dd54 100755 (executable)
@@ -47,6 +47,9 @@ from emuvim.dcemulator.resourcemodel import ResourceModelRegistrar
 LOG = logging.getLogger("dcemulator.net")
 LOG.setLevel(logging.DEBUG)
 
+# default CPU period used for cpu percentage-based cfs values (microseconds)
+CPU_PERIOD = 1000000
+
 class DCNetwork(Containernet):
     """
     Wraps the original Mininet/Containernet class and provides
@@ -56,7 +59,7 @@ class DCNetwork(Containernet):
     """
 
     def __init__(self, controller=RemoteController, monitor=False,
-                 enable_learning=False, # learning switch behavior of the default ovs switches icw Ryu controller can be turned off/on, neede for E-LAN functionality
+                 enable_learning=False, # learning switch behavior of the default ovs switches icw Ryu controller can be turned off/on, needed for E-LAN functionality
                  dc_emulation_max_cpu=1.0,  # fraction of overall CPU time for emulation
                  dc_emulation_max_mem=512,  # emulation max mem in MB
                  **kwargs):
@@ -121,6 +124,7 @@ class DCNetwork(Containernet):
         # initialize resource model registrar
         self.rm_registrar = ResourceModelRegistrar(
             dc_emulation_max_cpu, dc_emulation_max_mem)
+        self.cpu_period = CPU_PERIOD
 
     def addDatacenter(self, label, metadata={}, resource_log_path=None):
         """
index 8219761..8e7a63a 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.
@@ -148,7 +147,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", **kwargs):
         """
         Create a new container as compute resource and connect it to this
         data center.
@@ -174,15 +173,28 @@ 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
         )
 
+
+
         # apply resource limits to container if a resource model is defined
         if self._resource_model is not None:
             try:
index 2e01d92..053fdb6 100755 (executable)
@@ -44,7 +44,7 @@ class testSonataDummyGatekeeper(SimpleTestTopology):
 #    @unittest.skip("disabled")
     def test_GK_Api_start_service(self):
         # create network
-        self.createNet(nswitches=0, ndatacenter=2, nhosts=2, ndockers=0)
+        self.createNet(nswitches=0, ndatacenter=2, nhosts=2, ndockers=0, enable_learning=True)
         # setup links
         self.net.addLink(self.dc[0], self.h[0])
         self.net.addLink(self.dc[0], self.dc[1])
@@ -87,10 +87,37 @@ class testSonataDummyGatekeeper(SimpleTestTopology):
         # check compute list result
         self.assertEqual(len(self.dc[0].listCompute()), 2)
         # check connectivity by using ping
+        ELAN_list=[]
+        for i in [0]:
+            for vnf in self.dc[i].listCompute():
+                # check connection
+                p = self.net.ping([self.h[i], vnf])
+                print p
+                self.assertTrue(p <= 0.0)
+
+                # check E LAN connection
+                network_list = vnf.getNetworkStatus()
+                mgmt_ip = [intf['ip'] for intf in network_list if intf['intf_name'] == 'mgmt']
+                self.assertTrue(len(mgmt_ip) > 0)
+                ip_address = mgmt_ip[0]
+                ELAN_list.append(ip_address)
+                print ip_address
+
+        # check ELAN connection by ping over the mgmt network (needs to be configured as ELAN in the test service)
         for vnf in self.dc[0].listCompute():
-            p = self.net.ping([self.h[0], vnf])
-            print p
-#            self.assertTrue(p <= 50.0)
+            network_list = vnf.getNetworkStatus()
+            mgmt_ip = [intf['ip'] for intf in network_list if intf['intf_name'] == 'mgmt']
+            self.assertTrue(len(mgmt_ip) > 0)
+            ip_address = mgmt_ip[0]
+            print ELAN_list
+            print ip_address
+            test_ip_list = list(ELAN_list)
+            test_ip_list.remove(ip_address)
+            for ip in test_ip_list:
+                p = self.net.ping([vnf],manualdestip=ip)
+                print p
+                self.assertTrue(p <= 0.0)
+
         # stop Mininet network
         self.stopNet()
         initialize_GK()