Added memory model to UPB simple resource model
[osm/vim-emu.git] / src / emuvim / dcemulator / resourcemodel / upb / simple.py
index 503e35c..84aa7a9 100644 (file)
@@ -8,15 +8,105 @@ LOG = logging.getLogger("rm.upb.simple")
 LOG.setLevel(logging.DEBUG)
 
 
 LOG.setLevel(logging.DEBUG)
 
 
-class UpbSimpleCloudDcApproxRM(BaseResourceModel):
+class UpbSimpleCloudDcRM(BaseResourceModel):
     """
     This will be an example resource model that limits the overall
     resources that can be deployed per data center.
     """
     This will be an example resource model that limits the overall
     resources that can be deployed per data center.
+    No over provisioning. Resources are fixed throughout entire container
+    lifetime.
     """
     """
-    # TODO Implement resource model issue #12
 
     def __init__(self, max_cu=32, max_mu=1024):
 
     def __init__(self, max_cu=32, max_mu=1024):
-        self._max_cu = max_cu
-        self._max_mu = max_mu
+        """
+        Initialize model.
+        :param max_cu: Maximum number of compute units available in this DC.
+        :param max_mu: Maximum memory of entire dc.
+        :return:
+        """
+        self.dc_max_cu = max_cu
+        self.dc_max_mu = max_mu
+        self.dc_alloc_cu = 0
+        self.dc_alloc_mu = 0
         super(self.__class__, self).__init__()
 
         super(self.__class__, self).__init__()
 
+    def allocate(self, name, flavor_name):
+        """
+        Calculate resources for container with given flavor.
+        :param name: Container name.
+        :param flavor_name: Flavor name.
+        :return:
+        """
+        # bookkeeping and flavor handling
+        if flavor_name not in self._flavors:
+            raise Exception("Flavor %r does not exist" % flavor_name)
+        fl = self._flavors.get(flavor_name)
+        self.allocated_compute_instances[name] = flavor_name
+        # calc and return
+        return self._allocate_cpu(fl), self._allocate_mem(fl), -1.0  # return 3tuple (cpu, memory, disk)
+
+    def free(self, name):
+        """
+        Free resources of given container.
+        :param name: Container name.
+        :return:
+        """
+        if name not in self.allocated_compute_instances:
+            return False
+        # bookkeeping
+        self._free_cpu(self._flavors.get(self.allocated_compute_instances[name]))
+        self._free_mem(self._flavors.get(self.allocated_compute_instances[name]))
+        del self.allocated_compute_instances[name]
+        # we don't have to calculate anything special here in this simple model
+        return True
+
+    def _allocate_cpu(self, flavor):
+        """
+        Allocate CPU time.
+        :param flavor: flavor dict
+        :return: cpu time fraction
+        """
+        fl_cu = flavor.get("compute")
+        # check for over provisioning
+        if self.dc_alloc_cu + fl_cu > self.dc_max_cu:
+            raise Exception("Not enough compute resources left.")
+        self.dc_alloc_cu += fl_cu
+        # get cpu time fraction for entire emulation
+        e_cpu = self.registrar.e_cpu
+        # calculate cpu time fraction of a single compute unit
+        cu = float(e_cpu) / sum([rm.dc_max_cu for rm in list(self.registrar.resource_models)])
+        # calculate cpu time fraction for container with given flavor
+        return cu * fl_cu
+
+    def _free_cpu(self, flavor):
+        """
+        Free CPU allocation.
+        :param flavor: flavor dict
+        :return:
+        """
+        self.dc_alloc_cu -= flavor.get("compute")
+
+    def _allocate_mem(self, flavor):
+        """
+        Allocate mem.
+        :param flavor: flavor dict
+        :return: mem limit in MB
+        """
+        fl_mu = flavor.get("memory")
+        # check for over provisioning
+        if self.dc_alloc_mu + fl_mu > self.dc_max_mu:
+            raise Exception("Not enough memory resources left.")
+        self.dc_alloc_mu += fl_mu
+        # get cpu time fraction for entire emulation
+        e_mem = self.registrar.e_mem
+        # calculate cpu time fraction of a single compute unit
+        mu = float(e_mem) / sum([rm.dc_max_mu for rm in list(self.registrar.resource_models)])
+        # calculate cpu time fraction for container with given flavor
+        return mu * fl_mu
+
+    def _free_mem(self, flavor):
+        """
+        Free memory allocation
+        :param flavor: flavor dict
+        :return:
+        """
+        self.dc_alloc_mu -= flavor.get("memory")