[haizea-commit] r596 - in branches/TP2.0/src/haizea/core: . scheduler scheduler/preparation_schedulers
haizea-commit at mailman.cs.uchicago.edu
haizea-commit at mailman.cs.uchicago.edu
Fri Jul 3 03:47:05 CDT 2009
Author: borja
Date: 2009-07-03 03:46:59 -0500 (Fri, 03 Jul 2009)
New Revision: 596
Modified:
branches/TP2.0/src/haizea/core/manager.py
branches/TP2.0/src/haizea/core/scheduler/lease_scheduler.py
branches/TP2.0/src/haizea/core/scheduler/mapper.py
branches/TP2.0/src/haizea/core/scheduler/policy.py
branches/TP2.0/src/haizea/core/scheduler/preparation_schedulers/unmanaged.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
Log:
Very basic advance reservations (without preemptions) are working in TP2.0. Lots of other stuff is still broken.
Modified: branches/TP2.0/src/haizea/core/manager.py
===================================================================
--- branches/TP2.0/src/haizea/core/manager.py 2009-07-02 17:49:43 UTC (rev 595)
+++ branches/TP2.0/src/haizea/core/manager.py 2009-07-03 08:46:59 UTC (rev 596)
@@ -44,7 +44,7 @@
from haizea.core.scheduler.lease_scheduler import LeaseScheduler
from haizea.core.scheduler.vm_scheduler import VMScheduler
from haizea.core.scheduler.slottable import SlotTable
-from haizea.core.scheduler.policy import Policy
+from haizea.core.scheduler.policy import SimplePolicy
from haizea.core.scheduler.resourcepool import ResourcePool, ResourcePoolWithReusableImages
from haizea.core.leases import Lease
from haizea.core.rpcserver import RPCServer
@@ -144,6 +144,9 @@
slottable = SlotTable()
for n in resourcepool.get_nodes() + resourcepool.get_aux_nodes():
slottable.add_node(n)
+
+ # Policy engine
+ self.policy = SimplePolicy(slottable)
# Preparation scheduler
if preparation_type == constants.PREPARATION_UNMANAGED:
@@ -157,9 +160,6 @@
# Lease Scheduler
self.scheduler = LeaseScheduler(vm_scheduler, preparation_scheduler, slottable)
- # Policy engine
- #self.policy = Policy()
-
# Lease request frontends
if clock == constants.CLOCK_SIMULATED:
# In pure simulation, we can only use the tracefile frontend
@@ -656,16 +656,7 @@
if nextprematureend != None:
newtime = min(nextprematureend, newtime)
-
- if nextchangepoint == newtime:
- # Note that, above, we just "peeked" the next changepoint in the slottable.
- # If it turns out we're skipping to that point in time, then we need to
- # "get" it (this is because changepoints in the slottable are cached to
- # minimize access to the slottable. This optimization turned out to
- # be more trouble than it's worth and will probably be removed sometime
- # soon.
- newtime = self.manager.scheduler.slottable.getNextChangePoint(newtime)
-
+
# If there's no more leases in the system, and no more pending requests,
# then we're done.
if not self.manager.exists_leases_in_rm() and not tracefrontend.exists_more_requests():
Modified: branches/TP2.0/src/haizea/core/scheduler/lease_scheduler.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/lease_scheduler.py 2009-07-02 17:49:43 UTC (rev 595)
+++ branches/TP2.0/src/haizea/core/scheduler/lease_scheduler.py 2009-07-03 08:46:59 UTC (rev 596)
@@ -481,18 +481,18 @@
# Deployment RRs (if any)
for rr in preparation_rrs:
- self.slottable.addReservation(rr)
+ self.slottable.add_reservation(rr)
# Pre-VM RRs (if any)
for rr in vmrr.pre_rrs:
- self.slottable.addReservation(rr)
+ self.slottable.add_reservation(rr)
# VM
- self.slottable.addReservation(vmrr)
+ self.slottable.add_reservation(vmrr)
# Post-VM RRs (if any)
for rr in vmrr.post_rrs:
- self.slottable.addReservation(rr)
+ self.slottable.add_reservation(rr)
if lease_state == Lease.STATE_PENDING or lease_state == Lease.STATE_QUEUED:
lease.set_state(Lease.STATE_SCHEDULED)
@@ -626,7 +626,7 @@
Arguments:
rr -- Reservation that ended
"""
- self.slottable.removeReservation(rr)
+ self.slottable.remove_reservation(rr)
def _handle_end_lease(self, l):
@@ -641,7 +641,7 @@
self.preparation_scheduler.cleanup(l)
self.completed_leases.add(l)
self.leases.remove(l)
- if isinstance(l, BestEffortLease):
+ if l.get_type() == Lease.BEST_EFFORT:
get_accounting().incr_counter(constants.COUNTER_BESTEFFORTCOMPLETED, l.id)
Modified: branches/TP2.0/src/haizea/core/scheduler/mapper.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/mapper.py 2009-07-02 17:49:43 UTC (rev 595)
+++ branches/TP2.0/src/haizea/core/scheduler/mapper.py 2009-07-03 08:46:59 UTC (rev 596)
@@ -45,9 +45,6 @@
vnodes.reverse()
leases = aw.get_leases_until(end)
mapping = {}
- print "pnodes:", pnodes
- print "vnodes:", vnodes
- print "leases:", [l.id for l in leases]
leases = self.policy.sort_leases(lease, leases)
preemptable_leases = leases
preempting = []
@@ -93,7 +90,7 @@
preempting.append(preemptable_leases.pop())
if len(mapping) != len(requested_resources):
- return None
+ return None, None, None
else:
return mapping, maxend, preempting
Modified: branches/TP2.0/src/haizea/core/scheduler/policy.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/policy.py 2009-07-02 17:49:43 UTC (rev 595)
+++ branches/TP2.0/src/haizea/core/scheduler/policy.py 2009-07-03 08:46:59 UTC (rev 596)
@@ -40,3 +40,16 @@
# def get_host_score(self, node):
# abstract()
+
+class SimplePolicy(Policy):
+ def __init__(self, slottable):
+ Policy.__init__(self, slottable)
+
+ def get_lease_preemptability_score(self, preemptor, preemptee):
+ if preemptor.get_type() == Lease.ADVANCE_RESERVATION and preemptee.get_type() == Lease.BEST_EFFORT:
+ return 1
+ else:
+ return -1
+
+ def accept_lease(self, lease):
+ return True
Modified: branches/TP2.0/src/haizea/core/scheduler/preparation_schedulers/unmanaged.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/preparation_schedulers/unmanaged.py 2009-07-02 17:49:43 UTC (rev 595)
+++ branches/TP2.0/src/haizea/core/scheduler/preparation_schedulers/unmanaged.py 2009-07-03 08:46:59 UTC (rev 596)
@@ -28,7 +28,7 @@
# Add dummy disk images
def schedule(self, lease, vmrr, nexttime):
for (vnode, pnode) in vmrr.nodes.items():
- self.resourcepool.add_diskimage(pnode, lease.diskimage_id, lease.diskimage_size, lease.id, vnode)
+ self.resourcepool.add_diskimage(pnode, "foobar", 100, lease.id, vnode)
return [], True
def find_earliest_starting_times(self, lease, nexttime):
Modified: branches/TP2.0/src/haizea/core/scheduler/resourcepool.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/resourcepool.py 2009-07-02 17:49:43 UTC (rev 595)
+++ branches/TP2.0/src/haizea/core/scheduler/resourcepool.py 2009-07-03 08:46:59 UTC (rev 596)
@@ -42,9 +42,9 @@
for (vnode, pnode) in rr.nodes.items():
node = self.get_node(pnode)
- diskimage = node.get_diskimage(lease.id, vnode, lease.diskimage_id)
+ #diskimage = node.get_diskimage(lease.id, vnode, lease.diskimage_id)
start_action.vnodes[vnode].pnode = node.enactment_info
- start_action.vnodes[vnode].diskimage = diskimage.filename
+ #start_action.vnodes[vnode].diskimage = diskimage.filename
start_action.vnodes[vnode].resources = rr.resources_in_pnode[pnode]
try:
Modified: branches/TP2.0/src/haizea/core/scheduler/slottable.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/slottable.py 2009-07-02 17:49:43 UTC (rev 595)
+++ branches/TP2.0/src/haizea/core/scheduler/slottable.py 2009-07-03 08:46:59 UTC (rev 596)
@@ -224,7 +224,6 @@
def __init__(self):
self.logger = logging.getLogger("SLOT")
self.nodes = NodeList()
- self.reservations = []
self.reservations_by_start = []
self.reservations_by_end = []
self.__dirty()
@@ -441,6 +440,28 @@
return self.awcache
+ def sanity_check(self):
+ # Get checkpoints
+ changepoints = set()
+ for rr in [x.value for x in self.reservations_by_start]:
+ changepoints.add(rr.start)
+ changepoints.add(rr.end)
+ changepoints = list(changepoints)
+ changepoints.sort()
+
+ offending_node = None
+ offending_cp = None
+ offending_capacity = None
+
+ for cp in changepoints:
+ avail = self.get_availability(cp)
+ for node in avail:
+ for resource in avail[node].capacity._res:
+ if resource < 0:
+ return False, node, cp, avail[node].capacity
+
+ return True, None, None, None
+
# ONLY for simulation
def get_next_premature_end(self, after):
from haizea.core.scheduler.vm_scheduler import VMResourceReservation
@@ -475,6 +496,7 @@
allnodes = set([i+1 for i in range(len(self.nodes.nodelist))])
nodes = {}
reservations = self.get_reservations_at(time)
+
# Find how much resources are available on each node
for r in reservations:
for node in r.resources_in_pnode:
Modified: branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py 2009-07-02 17:49:43 UTC (rev 595)
+++ branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py 2009-07-03 08:46:59 UTC (rev 596)
@@ -17,10 +17,11 @@
# -------------------------------------------------------------------------- #
import haizea.common.constants as constants
-from haizea.common.utils import round_datetime_delta, round_datetime, estimate_transfer_time, pretty_nodemap, get_config, get_clock
+from haizea.common.utils import round_datetime_delta, round_datetime, estimate_transfer_time, pretty_nodemap, get_config, get_clock, get_policy
from haizea.core.leases import Lease
from haizea.core.scheduler.slottable import ResourceReservation, ResourceTuple
from haizea.core.scheduler import ReservationEventHandler, RescheduleLeaseException, NormalEndLeaseException, EnactmentError, NotSchedulableException, InconsistentScheduleError, InconsistentLeaseStateError
+from haizea.core.scheduler.mapper import GreedyMapper
from operator import attrgetter, itemgetter
from mx.DateTime import TimeDelta
@@ -37,6 +38,7 @@
def __init__(self, slottable, resourcepool):
self.slottable = slottable
self.resourcepool = resourcepool
+ self.mapper = GreedyMapper(self.slottable, get_policy())
self.logger = logging.getLogger("VMSCHED")
self.handlers = {}
@@ -78,145 +80,40 @@
self.numbesteffortres = 0
def schedule(self, lease, nexttime, earliest):
- if isinstance(lease, BestEffortLease):
- (vmrr, preemptions) = self.vm_scheduler.fit_asap(lease, nexttime, earliest)
- elif isinstance(lease, ARLease):
- (vmrr, preemptions) = self.vm_scheduler.fit_exact(lease, preemptible=False, canpreempt=True)
- elif isinstance(lease, ImmediateLease):
- (vmrr, preemptions) = self.vm_scheduler.fit_asap(lease, nexttime, earliest, allow_reservation_in_future=False)
+ if lease.get_type() == Lease.BEST_EFFORT:
+ return self.__schedule_asap(lease, nexttime, earliest)
+ elif lease.get_type() == Lease.ADVANCE_RESERVATION:
+ return self.__schedule_exact(lease, nexttime, earliest)
+ elif lease.get_type() == Lease.IMMEDIATE:
+ return self.__schedule_asap(lease, nexttime, earliest)
- def fit(self, requested_resources, start, end, strictend):
- lease_id = leasereq.id
- start = leasereq.start.requested
- end = leasereq.start.requested + leasereq.duration.requested + self.__estimate_shutdown_time(leasereq)
- diskImageID = leasereq.diskimage_id
- numnodes = leasereq.numnodes
- resreq = leasereq.requested_resources
-
- availabilitywindow = self.slottable.availabilitywindow
-
- availabilitywindow.initWindow(start, resreq, canpreempt=canpreempt)
- availabilitywindow.printContents(withpreemption = False)
- availabilitywindow.printContents(withpreemption = True)
-
- mustpreempt = False
- unfeasiblewithoutpreemption = False
+ def __schedule_exact(self, lease, nexttime, earliest):
+ start = lease.start.requested
+ end = start + lease.duration.requested
+ mapping, actualend, preemptions = self.mapper.map(lease,
+ lease.requested_resources,
+ start,
+ end,
+ strictend = True)
+ if mapping == None:
+ raise NotSchedulableException, "Not enough resources in specified interval"
- fitatstart = availabilitywindow.fitAtStart(canpreempt = False)
- if fitatstart < numnodes:
- if not canpreempt:
- raise NotSchedulableException, "Not enough resources in specified interval"
- else:
- unfeasiblewithoutpreemption = True
- feasibleend, canfitnopreempt = availabilitywindow.findPhysNodesForVMs(numnodes, end, strictend=True, canpreempt = False)
- fitatend = sum([n for n in canfitnopreempt.values()])
- if fitatend < numnodes:
- if not canpreempt:
- raise NotSchedulableException, "Not enough resources in specified interval"
- else:
- unfeasiblewithoutpreemption = True
-
- canfitpreempt = None
- if canpreempt:
- fitatstart = availabilitywindow.fitAtStart(canpreempt = True)
- if fitatstart < numnodes:
- raise NotSchedulableException, "Not enough resources in specified interval"
- feasibleendpreempt, canfitpreempt = availabilitywindow.findPhysNodesForVMs(numnodes, end, strictend=True, canpreempt = True)
- fitatend = sum([n for n in canfitpreempt.values()])
- if fitatend < numnodes:
- raise NotSchedulableException, "Not enough resources in specified interval"
- else:
- if unfeasiblewithoutpreemption:
- mustpreempt = True
- else:
- mustpreempt = False
-
- # At this point we know if the lease is feasible, and if
- # will require preemption.
- if not mustpreempt:
- self.logger.debug("The VM reservations for this lease are feasible without preemption.")
- else:
- self.logger.debug("The VM reservations for this lease are feasible but will require preemption.")
-
- # merge canfitnopreempt and canfitpreempt
- canfit = {}
- for node in canfitnopreempt:
- vnodes = canfitnopreempt[node]
- canfit[node] = [vnodes, vnodes]
- for node in canfitpreempt:
- vnodes = canfitpreempt[node]
- if canfit.has_key(node):
- canfit[node][1] = vnodes
- else:
- canfit[node] = [0, vnodes]
-
- orderednodes = self.__choose_nodes(canfit, start, canpreempt, avoidpreempt)
-
- self.logger.debug("Node ordering: %s" % orderednodes)
-
- # vnode -> pnode
- nodeassignment = {}
-
- # pnode -> resourcetuple
+ # Create VM resource reservations
res = {}
- # physnode -> how many vnodes
- preemptions = {}
+ for (vnode,pnode) in mapping.items():
+ vnode_res = lease.requested_resources[vnode]
+ if res.has_key(pnode):
+ res[pnode].incr(vnode_res)
+ else:
+ res[pnode] = ResourceTuple.copy(vnode_res)
- vnode = 1
- if avoidpreempt:
- # First pass, without preemption
- for physnode in orderednodes:
- canfitinnode = canfit[physnode][0]
- for i in range(1, canfitinnode+1):
- nodeassignment[vnode] = physnode
- if res.has_key(physnode):
- res[physnode].incr(resreq)
- else:
- res[physnode] = ResourceTuple.copy(resreq)
- canfit[physnode][0] -= 1
- canfit[physnode][1] -= 1
- vnode += 1
- if vnode > numnodes:
- break
- if vnode > numnodes:
- break
-
- # Second pass, with preemption
- if mustpreempt or not avoidpreempt:
- for physnode in orderednodes:
- canfitinnode = canfit[physnode][1]
- for i in range(1, canfitinnode+1):
- nodeassignment[vnode] = physnode
- if res.has_key(physnode):
- res[physnode].incr(resreq)
- else:
- res[physnode] = ResourceTuple.copy(resreq)
- canfit[physnode][1] -= 1
- vnode += 1
- # Check if this will actually result in a preemption
- if canfit[physnode][0] == 0:
- if preemptions.has_key(physnode):
- preemptions[physnode].incr(resreq)
- else:
- preemptions[physnode] = ResourceTuple.copy(resreq)
- else:
- canfit[physnode][0] -= 1
- if vnode > numnodes:
- break
- if vnode > numnodes:
- break
-
- if vnode <= numnodes:
- raise InconsistentScheduleError, "Availability window indicated that request is feasible, but could not fit it"
-
- # Create VM resource reservations
- vmrr = VMResourceReservation(leasereq, start, end, nodeassignment, res, False)
+ vmrr = VMResourceReservation(lease, start, end, mapping, res, False)
vmrr.state = ResourceReservation.STATE_SCHEDULED
self.__schedule_shutdown(vmrr)
- preemptions = self.__find_preemptable_leases(preemptions, vmrr.start, vmrr.end)
+
return vmrr, preemptions
@@ -971,9 +868,8 @@
l.duration.accumulate_duration(diff)
rr.state = ResourceReservation.STATE_DONE
- if isinstance(l, BestEffortLease):
- if rr.backfill_reservation == True:
- self.numbesteffortres -= 1
+ if rr.backfill_reservation == True:
+ self.numbesteffortres -= 1
self.logger.vdebug("LEASE-%i After:" % l.id)
l.print_contents()
More information about the Haizea-commit
mailing list