Added UPB simple resource model and corresponding tests. Closes #12
diff --git a/src/emuvim/dcemulator/node.py b/src/emuvim/dcemulator/node.py
index 9ccdb7f..8de3ae7 100755
--- a/src/emuvim/dcemulator/node.py
+++ b/src/emuvim/dcemulator/node.py
@@ -192,6 +192,11 @@
         }
 
     def assignResourceModel(self, rm):
+        """
+        Assign a resource model to this DC.
+        :param rm: a BaseResourceModel object
+        :return:
+        """
         if self._resource_model is not None:
             raise Exception("There is already an resource model assigned to this DC.")
         self._resource_model = rm
diff --git a/src/emuvim/dcemulator/resourcemodel/__init__.py b/src/emuvim/dcemulator/resourcemodel/__init__.py
index 52a35e5..3d05b96 100644
--- a/src/emuvim/dcemulator/resourcemodel/__init__.py
+++ b/src/emuvim/dcemulator/resourcemodel/__init__.py
@@ -29,12 +29,25 @@
             raise Exception("There is already an resource model assigned to this DC.")
         self._resource_models[dc] = rm
         rm.registrar = self
+        rm.dcs.append(dc)
         LOG.info("Registrar: Added resource model: %r" % rm)
 
     @property
     def resource_models(self):
+        """
+        List of registered resource models
+        :return:
+        """
         return list(self._resource_models.itervalues())
 
+    @property
+    def num_dcs_with_rms(self):
+        """
+        Total number of data centers that are connected to a resource model
+        :return:
+        """
+        return sum([len(rm.dcs) for rm in list(self._resource_models.itervalues())])
+
 
 class ResourceFlavor(object):
     """
@@ -60,6 +73,7 @@
         self._flavors = dict()
         self._initDefaultFlavors()
         self.registrar = None  # pointer to registrar
+        self.dcs = list()
         self.allocated_compute_instances = dict()
         LOG.info("Resource model %r initialized" % self)
 
diff --git a/src/emuvim/dcemulator/resourcemodel/upb/simple.py b/src/emuvim/dcemulator/resourcemodel/upb/simple.py
index 503e35c..f8b8b94 100644
--- a/src/emuvim/dcemulator/resourcemodel/upb/simple.py
+++ b/src/emuvim/dcemulator/resourcemodel/upb/simple.py
@@ -8,15 +8,65 @@
 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.
+    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):
-        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
         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:
+        """
+        # TODO Add memory model calculation (split in private methods for each tuple component)
+        # 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)
+        fl_cu = fl.get("compute")
+        self.allocated_compute_instances[name] = flavor_name
+        # 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
+        #
+        # calculate cpu limitation:
+        #
+        # get cpu time fraction for entire emulation
+        e_cpu = self.registrar.e_cpu
+        # calculate cpu time fraction of a single compute unit
+        cu = e_cpu / sum([rm.dc_max_cu for rm in list(self.registrar.resource_models)])
+        # calculate cpu time fraction for container with given flavor
+        c_ct = cu * fl_cu
+        return c_ct, -1.0, -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.dc_alloc_cu -= self._flavors.get(self.allocated_compute_instances[name]).get("compute")
+        del self.allocated_compute_instances[name]
+        # we don't have to calculate anything special here in this simple model
+        return True