status["name"] = self.name
status["network"] = self.getNetworkStatus()
status["image"] = self.dimage
+ status["flavor_name"] = self.flavor_name
status["cpu_quota"] = self.cpu_quota
status["cpu_period"] = self.cpu_period
status["cpu_shares"] = self.cpu_shares
if len(network) < 1:
network.append({})
- # allocate in resource resource model and compute resource limits for new container
- cpu_limit = mem_limit = disk_limit = -1
- cpu_period = cpu_quota = None
- if self._resource_model is not None:
- # call allocate in resource model to calculate resource limit for this container
- (cpu_limit, mem_limit, disk_limit) = alloc = self._resource_model.allocate(name, flavor_name)
- LOG.debug("Allocation result: %r" % str(alloc))
- # check if we have a cpu_limit given by the used resource model
- if cpu_limit > 0:
- # calculate cpu period and quota for CFS
- # (see: https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt)
- # TODO consider multi core machines etc! non trivial!
- # Attention minimum cpu_quota is 1ms (micro)
- cpu_period = 100000 # lets consider a fixed period of 100000 microseconds for now
- cpu_quota = cpu_period * cpu_limit # calculate the fraction of cpu time for this container
- LOG.debug(
- "CPU limit: cpu_quota = cpu_period * cpu_limit = %f * %f = %f" % (cpu_period, cpu_limit, cpu_quota))
- # ATTENTION >= 1000 to avoid a invalid argument system error ... no idea why
- if cpu_quota < 1000:
- cpu_quota = 1000
- LOG.warning("Increased CPU quota for %r to avoid system error." % name)
- # check if we have a mem_limit given by the used resource model
- if mem_limit > 0:
- LOG.debug(
- "MEM limit: mem_limit = %f MB" % mem_limit)
- # ATTENTION minimum mem_limit per container is 4MB
- if mem_limit < 4:
- mem_limit = 4
- LOG.warning("Increased MEM limit for %r because it was less than 4.0 MB." % name)
# create the container
d = self.net.addDocker(
"%s" % (name),
dimage=image,
dcmd=command,
datacenter=self,
- flavor_name=flavor_name,
- cpu_period=int(cpu_period) if cpu_limit > 0 else None, # set cpu limits if needed
- cpu_quota=int(cpu_quota) if cpu_limit > 0 else None,
- mem_limit="%dm" % int(mem_limit) if mem_limit > 0 else None, # set mem limits if needed
- memswap_limit="%dm" % int(mem_limit) if mem_limit > 0 else None # lets set swap to mem limit for now
+ flavor_name=flavor_name
)
+
+ # apply resource limits to container if a resource model is defined
+ if self._resource_model is not None:
+ self._resource_model.allocate(d)
+ self._resource_model.write_allocation_log(d, self.resource_log_path)
+
# connect all given networks
# 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
self.net.addLink(d, self.switch, params1=nw, cls=Link)
# do bookkeeping
self.containers[name] = d
-
- # write resource log if a path is given
- if self.resource_log_path is not None:
- l = dict()
- l["t"] = time.time()
- l["name"] = name
- l["compute"] = d.getStatus()
- l["flavor_name"] = flavor_name
- l["action"] = "allocate"
- l["cpu_limit"] = cpu_limit
- l["mem_limit"] = mem_limit
- l["disk_limit"] = disk_limit
- l["rm_state"] = None if self._resource_model is None else self._resource_model.get_state_dict()
- # append to logfile
- with open(self.resource_log_path, "a") as f:
- f.write("%s\n" % json.dumps(l))
return d # we might use UUIDs for naming later on
def stopCompute(self, name):
if name not in self.containers:
raise Exception("Container with name %s not found." % name)
LOG.debug("Stopping compute instance %r in data center %r" % (name, str(self)))
+
+ # call resource model and free resources
+ if self._resource_model is not None:
+ self._resource_model.free(self.containers[name])
+ self._resource_model.write_free_log(self.containers[name], self.resource_log_path)
+
+ # remove links
self.net.removeLink(
link=None, node1=self.containers[name], node2=self.switch)
+
+ # remove container
self.net.removeDocker("%s" % (name))
del self.containers[name]
- # call resource model and free resources
- if self._resource_model is not None:
- self._resource_model.free(name)
- # write resource log if a path is given
- if self.resource_log_path is not None:
- l = dict()
- l["t"] = time.time()
- l["name"] = name
- l["flavor_name"] = None
- l["action"] = "free"
- l["cpu_limit"] = -1
- l["mem_limit"] = -1
- l["disk_limit"] = -1
- l["rm_state"] = None if self._resource_model is None else self._resource_model.get_state_dict()
- # append to logfile
- with open(self.resource_log_path, "a") as f:
- f.write("%s\n" % json.dumps(l))
return True
def listCompute(self):