[haizea-commit] r603 - in branches/TP2.0: src/haizea/core src/haizea/core/enact src/haizea/core/scheduler tests
haizea-commit at mailman.cs.uchicago.edu
haizea-commit at mailman.cs.uchicago.edu
Mon Jul 13 11:35:50 CDT 2009
Author: borja
Date: 2009-07-13 11:35:44 -0500 (Mon, 13 Jul 2009)
New Revision: 603
Modified:
branches/TP2.0/src/haizea/core/enact/__init__.py
branches/TP2.0/src/haizea/core/enact/opennebula.py
branches/TP2.0/src/haizea/core/enact/simulated.py
branches/TP2.0/src/haizea/core/leases.py
branches/TP2.0/src/haizea/core/manager.py
branches/TP2.0/src/haizea/core/scheduler/mapper.py
branches/TP2.0/src/haizea/core/scheduler/resourcepool.py
branches/TP2.0/src/haizea/core/scheduler/slottable.py
branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py
branches/TP2.0/tests/common.py
branches/TP2.0/tests/sample_slottables.py
branches/TP2.0/tests/test_mapper.py
branches/TP2.0/tests/test_slottable.py
Log:
- Forked ResourceTuple into two classes: ResourceTuple (only used by the scheduler) and Capacity (used by higher-level modules).
- Implemented multi-instance resource types (e.g., multiple CPUs per node).
Modified: branches/TP2.0/src/haizea/core/enact/__init__.py
===================================================================
--- branches/TP2.0/src/haizea/core/enact/__init__.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/enact/__init__.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -17,7 +17,6 @@
# -------------------------------------------------------------------------- #
from haizea.common.utils import abstract
-from haizea.core.scheduler.slottable import ResourceTuple
class ResourcePoolInfo(object):
def __init__(self):
Modified: branches/TP2.0/src/haizea/core/enact/opennebula.py
===================================================================
--- branches/TP2.0/src/haizea/core/enact/opennebula.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/enact/opennebula.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -17,7 +17,7 @@
# -------------------------------------------------------------------------- #
from haizea.core.scheduler import EnactmentError
-from haizea.core.scheduler.resourcepool import Node
+from haizea.core.scheduler.resourcepool import ResourcePoolNode
from haizea.core.scheduler.slottable import ResourceTuple
from haizea.core.enact import ResourcePoolInfo, VMEnactment, DeploymentEnactment
from haizea.common.utils import get_config
Modified: branches/TP2.0/src/haizea/core/enact/simulated.py
===================================================================
--- branches/TP2.0/src/haizea/core/enact/simulated.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/enact/simulated.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -16,8 +16,7 @@
# limitations under the License. #
# -------------------------------------------------------------------------- #
-from haizea.core.scheduler.resourcepool import Node
-from haizea.core.scheduler.slottable import ResourceTuple
+from haizea.core.scheduler.resourcepool import ResourcePoolNode
from haizea.core.enact import ResourcePoolInfo, VMEnactment, DeploymentEnactment
import haizea.common.constants as constants
from haizea.common.utils import get_config
@@ -51,7 +50,7 @@
nodes = site.nodes.get_all_nodes()
- self.nodes = [Node(id, "simul-%i" % id, capacity) for (id, capacity) in nodes.items()]
+ self.nodes = [ResourcePoolNode(id, "simul-%i" % id, capacity) for (id, capacity) in nodes.items()]
for n in self.nodes:
n.enactment_info = n.nod_id
@@ -74,8 +73,8 @@
# Unpack action
pnode = action.vnodes[vnode].pnode
image = action.vnodes[vnode].diskimage
- cpu = action.vnodes[vnode].resources.get_by_type(constants.RES_CPU)
- memory = action.vnodes[vnode].resources.get_by_type(constants.RES_MEM)
+ cpu = 100 #action.vnodes[vnode].resources.get_by_type(constants.RES_CPU)
+ memory = 1024 #action.vnodes[vnode].resources.get_by_type(constants.RES_MEM)
self.logger.debug("Received request to start VM for L%iV%i on host %i, image=%s, cpu=%i, mem=%i"
% (action.lease_haizea_id, vnode, pnode, image, cpu, memory))
@@ -108,12 +107,15 @@
self.bandwidth = config.get("imagetransfer-bandwidth")
- imgcapacity = ResourceTuple.create_empty()
- imgcapacity.set_by_type(constants.RES_NETOUT, self.bandwidth)
+ # Commenting for now
+ #imgcapacity = ResourceTuple.create_empty()
+ #imgcapacity.set_by_type(constants.RES_NETOUT, self.bandwidth)
+ imgcapacity = None
+
# TODO: Determine node number based on site
- self.fifo_node = Node(1000, "FIFOnode", imgcapacity)
- self.edf_node = Node(1001, "EDFnode", imgcapacity)
+ self.fifo_node = ResourcePoolNode(1000, "FIFOnode", imgcapacity)
+ self.edf_node = ResourcePoolNode(1001, "EDFnode", imgcapacity)
def get_edf_node(self):
return self.edf_node
@@ -121,8 +123,9 @@
def get_fifo_node(self):
return self.fifo_node
+ # Commenting for now
def get_aux_nodes(self):
- return [self.edf_node, self.fifo_node]
+ return [] #[self.edf_node, self.fifo_node]
def get_bandwidth(self):
return self.bandwidth
Modified: branches/TP2.0/src/haizea/core/leases.py
===================================================================
--- branches/TP2.0/src/haizea/core/leases.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/leases.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -349,6 +349,30 @@
def __init__(self):
StateMachine.__init__(self, LeaseStateMachine.initial_state, LeaseStateMachine.transitions, Lease.state_str)
+class Capacity(object):
+ def __init__(self, types):
+ self.ninstances = dict([(type, 1) for type in types])
+ self.quantity = dict([(type, [0]) for type in types])
+
+ def get_quantity(self, type):
+ return self.get_quantity_instance(type, 1)
+
+ def get_quantity_instance(self, type, instance):
+ return self.quantity[type][instance-1]
+
+ def set_quantity(self, type, amount):
+ self.set_quantity_instance(type, 1, amount)
+
+ def set_quantity_instance(self, type, instance, amount):
+ self.quantity[type][instance-1] = amount
+
+ def set_ninstances(self, type, ninstances):
+ self.ninstances[type] = ninstances
+ self.quantity[type] = [0 for i in range(ninstances)]
+
+ def get_resource_types(self):
+ return self.quantity.keys()
+
class Timestamp(object):
def __init__(self, requested):
self.requested = requested
@@ -449,12 +473,25 @@
self.resource_types = resource_types
self.attr_types = attr_types
- def add_resource(self, name, amount):
- from haizea.core.scheduler.slottable import ResourceTuple
- ResourceTuple.add_resource_type(name)
- self.resource_types.add(name)
- self.nodes.add_resource(name, amount)
+ def add_resource(self, name, amounts):
+ self.resource_types.append(name)
+ self.nodes.add_resource(name, amounts)
+ def create_empty_resource_quantity(self):
+ return Capacity(self.resource_types)
+
+ def get_resource_types_with_max_instances(self):
+ max_ninstances = dict((rt, 1) for rt in self.resource_types)
+ for node_set in self.nodes.node_sets:
+ capacity = node_set[1]
+ for resource_type in capacity.get_resource_types():
+ if capacity.ninstances[resource_type] > max_ninstances[resource_type]:
+ max_ninstances[resource_type] = capacity.ninstances[resource_type]
+
+ max_ninstances = [(rt,max_ninstances[rt]) for rt in self.resource_types]
+
+ return max_ninstances
+
@classmethod
def from_xml_file(cls, xml_file):
return cls.__from_xml_element(ET.parse(xml_file).getroot())
@@ -464,19 +501,25 @@
return cls.__from_xml_element(ET.parse(xml_file).getroot().find("site"))
@classmethod
- def __from_xml_element(cls, site_element):
- from haizea.core.scheduler.slottable import ResourceTuple
-
+ def __from_xml_element(cls, site_element):
resource_types = site_element.find("resource-types")
- resource_types = set(resource_types.get("names").split())
- for resource_type in resource_types:
- ResourceTuple.add_resource_type(resource_type)
+ resource_types = resource_types.get("names").split()
# TODO: Attributes
+ attrs = []
nodes = Nodes.from_xml_element(site_element.find("nodes"))
- return cls(nodes, resource_types, None)
+ # Validate nodes
+ for node_set in nodes.node_sets:
+ capacity = node_set[1]
+ for resource_type in capacity.get_resource_types():
+ print resource_type, resource_types
+ if resource_type not in resource_types:
+ # TODO: Raise something more meaningful
+ raise Exception
+
+ return cls(nodes, resource_types, attrs)
@classmethod
def from_resources_string(cls, resource_str):
@@ -516,24 +559,33 @@
nodenum += 1
return nodes
- def add_resource(self, type, amount):
+ def add_resource(self, type, amounts):
for node_set in self.node_sets:
r = node_set[1]
- r.set_by_type(type, amount)
+ r.set_ninstances(type, len(amounts))
+ for ninstance, amount in enumerate(amounts):
+ r.set_quantity_instance(type, ninstance+1, amount)
@classmethod
def from_xml_element(cls, nodes_element):
- from haizea.core.scheduler.slottable import ResourceTuple
-
nodesets = []
nodesets_elems = nodes_element.findall("node-set")
for nodeset_elem in nodesets_elems:
- r = ResourceTuple.create_empty()
+ r = Capacity([])
resources = nodeset_elem.findall("res")
for i, res in enumerate(resources):
type = res.get("type")
- amount = int(res.get("amount"))
- r.set_by_type(type, amount)
+ if len(res.getchildren()) == 0:
+ amount = int(res.get("amount"))
+ r.set_ninstances(type, 1)
+ r.set_quantity(type, amount)
+ else:
+ instances = res.findall("instance")
+ r.set_ninstances(type, len(instances))
+ for i, instance in enumerate(instances):
+ amount = int(instance.get("amount"))
+ r.set_quantity_instance(type, i+1, amount)
+
numnodes = int(nodeset_elem.get("numnodes"))
nodesets.append((numnodes,r))
Modified: branches/TP2.0/src/haizea/core/manager.py
===================================================================
--- branches/TP2.0/src/haizea/core/manager.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/manager.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -149,9 +149,10 @@
resourcepool = ResourcePool(info_enact, vm_enact, deploy_enact)
# Slot table
- slottable = SlotTable()
+ slottable = SlotTable(site.get_resource_types_with_max_instances())
for n in resourcepool.get_nodes() + resourcepool.get_aux_nodes():
- slottable.add_node(n)
+ rt = slottable.create_resource_tuple_from_capacity(n.capacity)
+ slottable.add_node(rt)
# Policy engine
self.policy = SimplePolicy(slottable)
Modified: branches/TP2.0/src/haizea/core/scheduler/mapper.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/mapper.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/scheduler/mapper.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -56,7 +56,7 @@
capacity = requested_resources[vnode]
maxend = end
for pnode in pnodes:
- need_to_map = ResourceTuple.create_empty()
+ need_to_map = self.slottable.create_empty_resource_tuple()
need_to_map.incr(capacity)
avail=aw.get_availability_at_node(start, pnode, preempted_leases = preempting)
pnode_done = False
@@ -146,19 +146,18 @@
return nodes
def __sort_vnodes(self, requested_resources):
- max_res = ResourceTuple.create_empty()
+ max_res = self.slottable.create_empty_resource_tuple()
for res in requested_resources.values():
- for t in ResourceTuple.get_resource_types():
- v = res.get_by_type(t)
- if v > max_res.get_by_type(t):
- max_res.set_by_type(t,v)
+ for i in range(len(res._res)):
+ if res._res[i] > max_res._res[i]:
+ max_res._res[i] = res._res[i]
norm_res = {}
for k,v in requested_resources.items():
norm_capacity = 0
- for t in ResourceTuple.get_resource_types():
- if max_res.get_by_type(t) > 0:
- norm_capacity += v.get_by_type(t) / float(max_res.get_by_type(t))
+ for i in range(len(max_res._res)):
+ if max_res._res[i] > 0:
+ norm_capacity += v._res[i] / float(max_res._res[i])
norm_res[k] = norm_capacity
vnodes = norm_res.items()
Modified: branches/TP2.0/src/haizea/core/scheduler/resourcepool.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/resourcepool.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/scheduler/resourcepool.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -166,7 +166,7 @@
def get_max_disk_usage(self):
return max([n.get_disk_usage() for n in self.nodes])
-class Node(object):
+class ResourcePoolNode(object):
def __init__(self, nod_id, hostname, capacity):
self.logger = logging.getLogger("RESOURCEPOOL")
self.nod_id = nod_id
@@ -308,7 +308,7 @@
return self.get_node(pnode_id).exists_reusable_image(diskimage_id, after = after)
-class NodeWithReusableImages(Node):
+class ResourcePoolNodeWithReusableImages(ResourcePoolNode):
def __init__(self, nod_id, hostname, capacity):
Node.__init__(self, nod_id, hostname, capacity)
self.reusable_images = []
Modified: branches/TP2.0/src/haizea/core/scheduler/slottable.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/slottable.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/scheduler/slottable.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -40,70 +40,67 @@
This class ...
- """
- type2pos = {}
- pos2type = {}
- nres = 0
+ """
+ SINGLE_INSTANCE = 1
+ MULTI_INSTANCE = 2
- def __init__(self, res):
+ def __init__(self, slottable, res):
+ self.slottable = slottable
self._res = res
-
- @classmethod
- def from_list(cls, l):
- return cls(l[:])
+ if self.slottable.has_multiinst:
+ self.multiinst = dict([(i,[]) for i in range(self.slottable.rtuple_len, self.slottable.rtuple_nres)])
@classmethod
def copy(cls, rt):
- return cls(rt._res[:])
-
- @classmethod
- def add_resource_type(cls, name):
- if name in cls.type2pos:
- # Can't add a resourcetype more than once
- # TODO: Raise something more meaningful
- raise
- cls.type2pos[name] = cls.nres
- cls.pos2type[cls.nres] = name
- cls.nres += 1
-
- @classmethod
- def get_resource_types(cls):
- return cls.type2pos.keys()
-
- @classmethod
- def create_empty(cls):
- return cls([0 for x in range(cls.nres)])
+ rt2 = cls(rt.slottable, rt._res[:])
+ if rt.slottable.has_multiinst:
+ rt2.multiinst = dict([(i, l[:]) for (i,l) in rt.multiinst.items()])
+ return rt2
def fits_in(self, res2):
- fits = True
- for i in xrange(len(self._res)):
+ for i in xrange(self.slottable.rtuple_len):
if self._res[i] > res2._res[i]:
- fits = False
- break
- return fits
+ return False
+ if self.slottable.has_multiinst:
+ multiinst2 = dict([(i, l[:]) for (i,l) in res2.multiinst.items()])
+ for (pos, l) in self.multiinst.items():
+ insts = multiinst2[pos]
+ for quantity in l:
+ fits = False
+ for i in range(len(insts)):
+ if quantity <= insts[i]:
+ fits = True
+ insts[i] -= quantity
+ break
+ if fits == False:
+ return False
+ return True
- def get_num_fits_in(self, res2):
- canfit = 10000 # Arbitrarily large
- for i in xrange(len(self._res)):
- if self._res[i] != 0:
- f = res2._res[i] / self._res[i]
- if f < canfit:
- canfit = f
- return int(floor(canfit))
-
def decr(self, res2):
- for slottype in xrange(len(self._res)):
+ for slottype in xrange(self.slottable.rtuple_len):
self._res[slottype] -= res2._res[slottype]
-
+ if self.slottable.has_multiinst:
+ for (pos, l) in res2.multiinst.items():
+ insts = self.multiinst[pos]
+ for quantity in l:
+ fits = False
+ for i in range(len(insts)):
+ if quantity <= insts[i]:
+ fits = True
+ insts[i] -= quantity
+ break
+ if fits == False:
+ raise Exception, "Can't decrease"
+
def incr(self, res2):
- for slottype in xrange(len(self._res)):
+ for slottype in xrange(self.slottable.rtuple_len):
self._res[slottype] += res2._res[slottype]
+ if self.slottable.has_multiinst:
+ for (pos, l) in res2.multiinst.items():
+ self.multiinst[pos] += l[:]
- def get_by_type(self, resourcetype):
- return self._res[self.type2pos[resourcetype]]
-
- def set_by_type(self, resourcetype, value):
- self._res[self.type2pos[resourcetype]] = value
+ def get_by_type(self, restype):
+ return self._res[self.slottable.rtuple_restype2pos[restype]]
def is_zero_or_less(self):
return sum([v for v in self._res]) <= 0
@@ -111,7 +108,8 @@
def __repr__(self):
r=""
for i, x in enumerate(self._res):
- r += "%s:%.2f " % (self.pos2type[i], x)
+ r += "%s:%i " % (i, x)
+ r+= `self.multiinst`
return r
def __eq__(self, res2):
@@ -167,14 +165,8 @@
return rr
class Node(object):
- def __init__(self, capacity, resourcepoolnode):
+ def __init__(self, capacity):
self.capacity = ResourceTuple.copy(capacity)
- self.resourcepoolnode = resourcepoolnode
-
- @classmethod
- def from_resourcepool_node(cls, node):
- capacity = node.get_capacity()
- return cls(capacity, node)
class NodeList(object):
def __init__(self):
@@ -192,7 +184,7 @@
def copy(self):
nodelist = NodeList()
for n in self.nodelist:
- nodelist.add(Node(n.capacity, n.resourcepoolnode))
+ nodelist.add(Node(n.capacity))
return nodelist
def to_dict(self):
@@ -229,16 +221,45 @@
"""
- def __init__(self):
+ def __init__(self, resource_types):
self.logger = logging.getLogger("SLOT")
self.nodes = NodeList()
+ self.resource_types = resource_types
self.reservations_by_start = []
self.reservations_by_end = []
self.__dirty()
- def add_node(self, resourcepoolnode):
- self.nodes.add(Node.from_resourcepool_node(resourcepoolnode))
+ # Resource tuple fields
+ res_singleinstance = [rt for rt,ninst in resource_types if ninst == ResourceTuple.SINGLE_INSTANCE]
+ self.rtuple_len = len(res_singleinstance)
+ self.rtuple_nres = len(resource_types)
+ res_multiinstance = [(rt,ninst) for rt,ninst in resource_types if ninst == ResourceTuple.MULTI_INSTANCE]
+ self.has_multiinst = len(res_multiinstance) > 0
+ self.rtuple_restype2pos = dict([(rt,i) for (i,rt) in enumerate(res_singleinstance)])
+ pos = self.rtuple_len
+ for rt, ninst in res_multiinstance:
+ self.rtuple_restype2pos[rt] = pos
+ pos = pos + 1
+ def add_node(self, resourcetuple):
+ self.nodes.add(Node(resourcetuple))
+
+ def create_empty_resource_tuple(self):
+ return ResourceTuple(self, [0] * self.rtuple_len)
+
+ def create_resource_tuple_from_capacity(self, capacity):
+ rt = ResourceTuple(self, [0] * self.rtuple_len)
+ for restype in capacity.get_resource_types():
+ pos = self.rtuple_restype2pos[restype]
+ if pos < self.rtuple_len:
+ rt._res[pos] = capacity.get_quantity(restype)
+ else:
+ ninst = capacity.ninstances[restype]
+ for i in range(ninst):
+ rt.multiinst[pos].append(capacity.get_quantity_instance(restype, i))
+
+ return rt
+
def is_empty(self):
return (len(self.reservations_by_start) == 0)
@@ -247,7 +268,7 @@
avail = sum([node.capacity.get_by_type(restype) for node in nodes.values()])
return (avail == 0)
- def get_total_capacity(self, restype = constants.RES_CPU):
+ def get_total_capacity(self, restype):
return sum([n.capacity.get_by_type(restype) for n in self.nodes.nodelist])
def get_reservations_at(self, time):
@@ -526,7 +547,7 @@
for node in r.resources_in_pnode:
if not nodes.has_key(node):
n = self.nodes[node]
- nodes[node] = Node(n.capacity, n.resourcepoolnode)
+ nodes[node] = Node(n.capacity)
nodes[node].capacity.decr(r.resources_in_pnode[node])
# For the remaining nodes, use a reference to the original node, not a copy
@@ -575,8 +596,9 @@
def add_lease(self, lease, capacity):
if not lease in self.leases:
self.leases.add(lease)
- self.available_if_preempting[lease] = ResourceTuple.create_empty()
- self.available_if_preempting[lease].incr(capacity)
+ self.available_if_preempting[lease] = ResourceTuple.copy(capacity)
+ else:
+ self.available_if_preempting[lease].incr(capacity)
def get_avail_withpreemption(self, leases):
avail = ResourceTuple.copy(available)
@@ -594,6 +616,10 @@
def fits(self, capacity, until):
for avail in self.avail_list:
+ print capacity
+ print avail.until, avail.available
+ print capacity.fits_in(avail.available)
+ print "----------"
if avail.until == None or avail.until >= until:
return capacity.fits_in(avail.available)
Modified: branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -90,8 +90,11 @@
def __schedule_exact(self, lease, nexttime, earliest):
start = lease.start.requested
end = start + lease.duration.requested
+
+ requested_resources = dict([(k,self.slottable.create_resource_tuple_from_capacity(v)) for k,v in lease.requested_resources.items()])
+ print requested_resources
mapping, actualend, preemptions = self.mapper.map(lease,
- lease.requested_resources,
+ requested_resources,
start,
end,
strictend = True)
@@ -102,7 +105,7 @@
res = {}
for (vnode,pnode) in mapping.items():
- vnode_res = lease.requested_resources[vnode]
+ vnode_res = requested_resources[vnode]
if res.has_key(pnode):
res[pnode].incr(vnode_res)
else:
@@ -204,8 +207,11 @@
reservation = False
+ requested_resources = dict([(k,self.slottable.create_resource_tuple_from_capacity(v)) for k,v in lease.requested_resources.items()])
+
# First, assuming we can't make reservations in the future
start, end, mapping, preemptions = self.__find_fit_at_points(lease,
+ requested_resources,
changepoints,
duration,
min_duration)
@@ -219,6 +225,7 @@
# reserve it in the future
if start == None and allow_reservation_in_future:
start, end, mapping, preemptions = self.__find_fit_at_points(lease,
+ requested_resources,
futurecp,
duration,
min_duration
@@ -237,7 +244,7 @@
res = {}
for (vnode,pnode) in mapping.items():
- vnode_res = lease.requested_resources[vnode]
+ vnode_res = requested_resources[vnode]
if res.has_key(pnode):
res[pnode].incr(vnode_res)
else:
@@ -354,20 +361,20 @@
def get_utilization(self, time):
- total = self.slottable.get_total_capacity()
+# total = self.slottable.get_total_capacity()
util = {}
- reservations = self.slottable.get_reservations_at(time)
- for r in reservations:
- for node in r.resources_in_pnode:
- if isinstance(r, VMResourceReservation):
- use = r.resources_in_pnode[node].get_by_type(constants.RES_CPU)
- util[type(r)] = use + util.setdefault(type(r),0.0)
- elif isinstance(r, SuspensionResourceReservation) or isinstance(r, ResumptionResourceReservation) or isinstance(r, ShutdownResourceReservation):
- use = r.vmrr.resources_in_pnode[node].get_by_type(constants.RES_CPU)
- util[type(r)] = use + util.setdefault(type(r),0.0)
- util[None] = total - sum(util.values())
- for k in util:
- util[k] /= total
+# reservations = self.slottable.get_reservations_at(time)
+# for r in reservations:
+# for node in r.resources_in_pnode:
+# if isinstance(r, VMResourceReservation):
+# use = r.resources_in_pnode[node].get_by_type(constants.RES_CPU)
+# util[type(r)] = use + util.setdefault(type(r),0.0)
+# elif isinstance(r, SuspensionResourceReservation) or isinstance(r, ResumptionResourceReservation) or isinstance(r, ShutdownResourceReservation):
+# use = r.vmrr.resources_in_pnode[node].get_by_type(constants.RES_CPU)
+# util[type(r)] = use + util.setdefault(type(r),0.0)
+# util[None] = total - sum(util.values())
+# for k in util:
+# util[k] /= total
return util
@@ -387,14 +394,15 @@
return self.maxres > 0
- def __find_fit_at_points(self, lease, changepoints, duration, min_duration):
+ def __find_fit_at_points(self, lease, requested_resources, changepoints, duration, min_duration):
found = False
+
for time, onlynodes in changepoints:
start = time
end = start + duration
self.logger.debug("Attempting to map from %s to %s" % (start, end))
mapping, actualend, preemptions = self.mapper.map(lease,
- lease.requested_resources,
+ requested_resources,
start,
end,
strictend = False,
@@ -634,7 +642,7 @@
enactment_overhead = get_config().get("enactment-overhead")
mem = 0
for vnode in lease.requested_resources:
- mem += lease.requested_resources[vnode].get_by_type(constants.RES_MEM)
+ mem += lease.requested_resources[vnode].get_quantity(constants.RES_MEM)
if susp_exclusion == constants.SUSPRES_EXCLUSION_GLOBAL:
return lease.numnodes * (self.__compute_suspend_resume_time(mem, rate) + enactment_overhead)
elif susp_exclusion == constants.SUSPRES_EXCLUSION_LOCAL:
Modified: branches/TP2.0/tests/common.py
===================================================================
--- branches/TP2.0/tests/common.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/tests/common.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -120,7 +120,7 @@
slottable.add_reservation(rr)
def create_tmp_slottable(slottable):
- tmp_slottable = SlotTable()
+ tmp_slottable = SlotTable(slottable.resource_types)
tmp_slottable.nodes = slottable.nodes
tmp_slottable.reservations_by_start = slottable.reservations_by_start[:]
tmp_slottable.reservations_by_end = slottable.reservations_by_end[:]
Modified: branches/TP2.0/tests/sample_slottables.py
===================================================================
--- branches/TP2.0/tests/sample_slottables.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/tests/sample_slottables.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -1,5 +1,5 @@
-from haizea.core.leases import Lease
-from haizea.core.scheduler.resourcepool import Node
+from haizea.core.leases import Lease, Capacity
+from haizea.core.scheduler.resourcepool import ResourcePoolNode
from haizea.core.scheduler.slottable import ResourceTuple, SlotTable, ResourceReservation, AvailabilityWindow
from mx import DateTime
import haizea.common.constants as constants
@@ -20,30 +20,36 @@
T1415 = DateTime.DateTime(2006,11,25,14,15)
T1420 = DateTime.DateTime(2006,11,25,14,20)
-resource_types = [(constants.RES_CPU, constants.RESTYPE_FLOAT, "CPU"),
- (constants.RES_MEM, constants.RESTYPE_INT, "Mem")]
-ResourceTuple.set_resource_types(resource_types)
+resource_types_with_max_instances = [(constants.RES_CPU,1),(constants.RES_MEM,1)]
-FULL_NODE = ResourceTuple.create_empty()
-FULL_NODE.set_by_type(constants.RES_CPU, 1.0)
-FULL_NODE.set_by_type(constants.RES_MEM, 1024)
+def create_capacities(slottable):
+ FULL_NODE = Capacity([constants.RES_CPU,constants.RES_MEM])
+ FULL_NODE.set_quantity(constants.RES_CPU, 100)
+ FULL_NODE.set_quantity(constants.RES_MEM, 1024)
+ FULL_NODE = slottable.create_resource_tuple_from_capacity(FULL_NODE)
+
+ HALF_NODE = Capacity([constants.RES_CPU,constants.RES_MEM])
+ HALF_NODE.set_quantity(constants.RES_CPU, 50)
+ HALF_NODE.set_quantity(constants.RES_MEM, 512)
+ HALF_NODE = slottable.create_resource_tuple_from_capacity(HALF_NODE)
-HALF_NODE = ResourceTuple.create_empty()
-HALF_NODE.set_by_type(constants.RES_CPU, 0.5)
-HALF_NODE.set_by_type(constants.RES_MEM, 512)
+ QRTR_NODE = Capacity([constants.RES_CPU,constants.RES_MEM])
+ QRTR_NODE.set_quantity(constants.RES_CPU, 25)
+ QRTR_NODE.set_quantity(constants.RES_MEM, 256)
+ QRTR_NODE = slottable.create_resource_tuple_from_capacity(QRTR_NODE)
-QRTR_NODE = ResourceTuple.create_empty()
-QRTR_NODE.set_by_type(constants.RES_CPU, 0.25)
-QRTR_NODE.set_by_type(constants.RES_MEM, 256)
-
-EMPT_NODE = ResourceTuple.create_empty()
+ EMPT_NODE = slottable.create_empty_resource_tuple()
+
+ return FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE
def sample_slottable_1():
- slottable = SlotTable()
- slottable.add_node(Node(1, "test-1", FULL_NODE))
- slottable.add_node(Node(2, "test-2", FULL_NODE))
- slottable.add_node(Node(3, "test-3", FULL_NODE))
- slottable.add_node(Node(4, "test-4", FULL_NODE))
+ slottable = SlotTable([(constants.RES_CPU,ResourceTuple.SINGLE_INSTANCE),(constants.RES_MEM,ResourceTuple.SINGLE_INSTANCE)])
+ FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE = create_capacities(slottable)
+
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
lease1 = Lease(None,[],None,None,None,1,None)
lease1.id = 1
@@ -88,13 +94,14 @@
return slottable, [lease1,lease2,lease3,lease4,lease5,lease6]
def sample_slottable_2():
- slottable = SlotTable()
+ slottable = SlotTable([(constants.RES_CPU,ResourceTuple.SINGLE_INSTANCE),(constants.RES_MEM,ResourceTuple.SINGLE_INSTANCE)])
+ FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE = create_capacities(slottable)
+
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
- slottable.add_node(Node(1, "test-1", FULL_NODE))
- slottable.add_node(Node(2, "test-2", FULL_NODE))
- slottable.add_node(Node(3, "test-3", FULL_NODE))
- slottable.add_node(Node(4, "test-4", FULL_NODE))
-
lease1 = create_ar_lease(lease_id = 1,
submit_time = T1200,
start = T1330,
@@ -114,13 +121,14 @@
return slottable, [lease1,lease2]
def sample_slottable_3():
- slottable = SlotTable()
+ slottable = SlotTable([(constants.RES_CPU,ResourceTuple.SINGLE_INSTANCE),(constants.RES_MEM,ResourceTuple.SINGLE_INSTANCE)])
+ FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE = create_capacities(slottable)
+
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
+ slottable.add_node(FULL_NODE)
- slottable.add_node(Node(1, "test-1", FULL_NODE))
- slottable.add_node(Node(2, "test-2", FULL_NODE))
- slottable.add_node(Node(3, "test-3", FULL_NODE))
- slottable.add_node(Node(4, "test-4", FULL_NODE))
-
lease1 = create_ar_lease(lease_id = 1,
submit_time = T1200,
start = T1345,
Modified: branches/TP2.0/tests/test_mapper.py
===================================================================
--- branches/TP2.0/tests/test_mapper.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/tests/test_mapper.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -1,5 +1,5 @@
from haizea.core.leases import Lease
-from haizea.core.scheduler.resourcepool import Node
+from haizea.core.scheduler.resourcepool import ResourcePoolNode
from haizea.core.scheduler.policy import Policy
from haizea.core.scheduler.slottable import ResourceTuple, SlotTable, ResourceReservation, AvailabilityWindow
from haizea.core.scheduler.mapper import GreedyMapper
@@ -79,6 +79,7 @@
def test_mapping_nopreemption_strictend(self):
self.slottable, leases = sample_slottable_2()
+ FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE = create_capacities(self.slottable)
policy = SimplePolicy(self.slottable, preemption = False)
self.mapper = GreedyMapper(self.slottable, policy)
@@ -138,6 +139,7 @@
def test_mapping_nopreemption_nostrictend(self):
self.slottable, leases = sample_slottable_3()
+ FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE = create_capacities(self.slottable)
policy = SimplePolicy(self.slottable, preemption = False)
self.mapper = GreedyMapper(self.slottable, policy)
@@ -197,6 +199,7 @@
def test_mapping_preemption_strictend(self):
self.slottable, leases = sample_slottable_3()
+ FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE = create_capacities(self.slottable)
policy = SimplePolicy(self.slottable, preemption = True)
self.mapper = GreedyMapper(self.slottable, policy)
Modified: branches/TP2.0/tests/test_slottable.py
===================================================================
--- branches/TP2.0/tests/test_slottable.py 2009-07-07 10:43:04 UTC (rev 602)
+++ branches/TP2.0/tests/test_slottable.py 2009-07-13 16:35:44 UTC (rev 603)
@@ -1,5 +1,5 @@
-from haizea.core.leases import Lease
-from haizea.core.scheduler.resourcepool import Node
+from haizea.core.leases import Lease, Capacity
+from haizea.core.scheduler.resourcepool import ResourcePoolNode
from haizea.core.scheduler.slottable import ResourceTuple, SlotTable, ResourceReservation, AvailabilityWindow
from mx import DateTime
from sample_slottables import *
@@ -9,9 +9,99 @@
def __init__(self):
self.slottable = None
+ def test_resource_tuple(self):
+
+ multiinst = [(constants.RES_CPU,ResourceTuple.MULTI_INSTANCE),(constants.RES_MEM,ResourceTuple.SINGLE_INSTANCE)]
+
+ self.slottable = SlotTable(multiinst)
+
+ c1_100 = Capacity([constants.RES_CPU,constants.RES_MEM])
+ c1_100.set_quantity(constants.RES_CPU, 100)
+ c1_100.set_quantity(constants.RES_MEM, 1024)
+ c1_100 = self.slottable.create_resource_tuple_from_capacity(c1_100)
+
+ c2_100 = Capacity([constants.RES_CPU,constants.RES_MEM])
+ c2_100.set_ninstances(constants.RES_CPU, 2)
+ c2_100.set_quantity_instance(constants.RES_CPU, 1, 100)
+ c2_100.set_quantity_instance(constants.RES_CPU, 2, 100)
+ c2_100.set_quantity(constants.RES_MEM, 1024)
+ c2_100 = self.slottable.create_resource_tuple_from_capacity(c2_100)
+
+ c1_50 = Capacity([constants.RES_CPU,constants.RES_MEM])
+ c1_50.set_quantity(constants.RES_CPU, 50)
+ c1_50.set_quantity(constants.RES_MEM, 1024)
+ c1_50 = self.slottable.create_resource_tuple_from_capacity(c1_50)
+
+ c2_50 = Capacity([constants.RES_CPU,constants.RES_MEM])
+ c2_50.set_ninstances(constants.RES_CPU, 2)
+ c2_50.set_quantity_instance(constants.RES_CPU, 1, 50)
+ c2_50.set_quantity_instance(constants.RES_CPU, 2, 50)
+ c2_50.set_quantity(constants.RES_MEM, 1024)
+ c2_50 = self.slottable.create_resource_tuple_from_capacity(c2_50)
+
+ assert c1_100.fits_in(c2_100)
+ assert not c1_100.fits_in(c1_50)
+ assert not c1_100.fits_in(c2_50)
+
+ assert not c2_100.fits_in(c1_100)
+ assert not c2_100.fits_in(c1_50)
+ assert not c2_100.fits_in(c2_50)
+
+ assert c1_50.fits_in(c1_100)
+ assert c1_50.fits_in(c2_100)
+ assert c1_50.fits_in(c2_50)
+
+ assert c2_50.fits_in(c1_100)
+ assert c2_50.fits_in(c2_100)
+ assert not c2_50.fits_in(c1_50)
+
+ empty = self.slottable.create_empty_resource_tuple()
+ empty.incr(c2_100)
+ assert empty._res[0] == 1024
+ assert empty.multiinst[1] == [100,100]
+
+ empty = self.slottable.create_empty_resource_tuple()
+ empty.incr(c1_100)
+ assert empty._res[0] == 1024
+ assert empty.multiinst[1] == [100]
+ empty.incr(c1_100)
+ assert empty._res[0] == 2048
+ assert empty.multiinst[1] == [100,100]
+
+ empty = self.slottable.create_empty_resource_tuple()
+ empty.incr(c1_100)
+ assert empty._res[0] == 1024
+ assert empty.multiinst[1] == [100]
+ empty.incr(c1_50)
+ assert empty._res[0] == 2048
+ assert empty.multiinst[1] == [100,50]
+
+ c1_100a = ResourceTuple.copy(c1_100)
+ c1_100a.decr(c1_50)
+ assert c1_100a._res[0] == 0
+ assert c1_100a.multiinst[1] == [50]
+
+ c2_100a = ResourceTuple.copy(c2_100)
+ c2_100a._res[0] = 2048
+ c2_100a.decr(c1_50)
+ assert c2_100a._res[0] == 1024
+ assert c2_100a.multiinst[1] == [50,100]
+ c2_100a.decr(c1_50)
+ assert c2_100a._res[0] == 0
+ assert c2_100a.multiinst[1] == [0,100]
+
+ c2_100a = ResourceTuple.copy(c2_100)
+ c2_100a._res[0] = 2048
+ c2_100a.decr(c2_50)
+ assert c2_100a._res[0] == 1024
+ assert c2_100a.multiinst[1] == [0,100]
+ c2_100a.decr(c2_50)
+ assert c2_100a._res[0] == 0
+ assert c2_100a.multiinst[1] == [0,0]
+
def test_slottable(self):
def assert_capacity(node, percent):
- assert node.capacity.get_by_type(constants.RES_CPU) == percent * 1.0
+ assert node.capacity.get_by_type(constants.RES_CPU) == percent * 100
assert node.capacity.get_by_type(constants.RES_MEM) == percent * 1024
def reservations_1_assertions():
@@ -237,38 +327,38 @@
rrs = self.slottable.get_reservations_ending_between(T1400, T1415)
assert set(rrs) == set([rr2,rr4,rr5])
- rrs = self.slottable.get_reservations_starting_after(T1300)
+ rrs = self.slottable.get_reservations_starting_on_or_after(T1300)
assert set(rrs) == set([rr1,rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_starting_after(T1305)
+ rrs = self.slottable.get_reservations_starting_on_or_after(T1305)
assert set(rrs) == set([rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_starting_after(T1315)
+ rrs = self.slottable.get_reservations_starting_on_or_after(T1315)
assert set(rrs) == set([rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_starting_after(T1330)
+ rrs = self.slottable.get_reservations_starting_on_or_after(T1330)
assert set(rrs) == set([rr2,rr4,rr5])
- rrs = self.slottable.get_reservations_starting_after(T1335)
+ rrs = self.slottable.get_reservations_starting_on_or_after(T1335)
assert set(rrs) == set([rr5])
- rrs = self.slottable.get_reservations_starting_after(T1345)
+ rrs = self.slottable.get_reservations_starting_on_or_after(T1345)
assert set(rrs) == set([rr5])
- rrs = self.slottable.get_reservations_starting_after(T1400)
+ rrs = self.slottable.get_reservations_starting_on_or_after(T1400)
assert len(rrs) == 0
- rrs = self.slottable.get_reservations_starting_after(T1415)
+ rrs = self.slottable.get_reservations_starting_on_or_after(T1415)
assert len(rrs) == 0
- rrs = self.slottable.get_reservations_ending_after(T1300)
+ rrs = self.slottable.get_reservations_ending_on_or_after(T1300)
assert set(rrs) == set([rr1,rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_ending_after(T1305)
+ rrs = self.slottable.get_reservations_ending_on_or_after(T1305)
assert set(rrs) == set([rr1,rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_ending_after(T1315)
+ rrs = self.slottable.get_reservations_ending_on_or_after(T1315)
assert set(rrs) == set([rr1,rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_ending_after(T1330)
+ rrs = self.slottable.get_reservations_ending_on_or_after(T1330)
assert set(rrs) == set([rr1,rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_ending_after(T1335)
+ rrs = self.slottable.get_reservations_ending_on_or_after(T1335)
assert set(rrs) == set([rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_ending_after(T1345)
+ rrs = self.slottable.get_reservations_ending_on_or_after(T1345)
assert set(rrs) == set([rr2,rr3,rr4,rr5])
- rrs = self.slottable.get_reservations_ending_after(T1400)
+ rrs = self.slottable.get_reservations_ending_on_or_after(T1400)
assert set(rrs) == set([rr2,rr4,rr5])
- rrs = self.slottable.get_reservations_ending_after(T1415)
+ rrs = self.slottable.get_reservations_ending_on_or_after(T1415)
assert set(rrs) == set([rr4,rr5])
assert self.slottable.get_next_changepoint(T1255) == T1300
@@ -281,12 +371,13 @@
assert self.slottable.get_next_changepoint(T1415) == None
assert self.slottable.get_next_changepoint(T1420) == None
- self.slottable = SlotTable()
-
- self.slottable.add_node(Node(1, "test-1", FULL_NODE))
- self.slottable.add_node(Node(2, "test-2", FULL_NODE))
+ self.slottable = SlotTable([(constants.RES_CPU,ResourceTuple.SINGLE_INSTANCE),(constants.RES_MEM,ResourceTuple.SINGLE_INSTANCE)])
+ FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE = create_capacities(self.slottable)
- assert self.slottable.get_total_capacity(constants.RES_CPU) == 2.0
+ self.slottable.add_node(FULL_NODE)
+ self.slottable.add_node(FULL_NODE)
+
+ assert self.slottable.get_total_capacity(constants.RES_CPU) == 200
assert self.slottable.get_total_capacity(constants.RES_MEM) == 2048
assert self.slottable.is_empty()
@@ -344,6 +435,7 @@
assert(node.next_nodeavail == aw.changepoints[next_cp].nodes[node_id])
self.slottable, leases = sample_slottable_1()
+ FULL_NODE, HALF_NODE, QRTR_NODE, EMPT_NODE = create_capacities(self.slottable)
lease1,lease2,lease3,lease4,lease5,lease6 = leases
More information about the Haizea-commit
mailing list