def find_earliest_starting_times(self, lease, nexttime): node_ids = [node.id for node in self.resourcepool.get_nodes()] config = get_config() mechanism = config.get("transfer-mechanism") reusealg = config.get("diskimage-reuse") avoidredundant = config.get("avoid-redundant-transfers") if type(lease.software) == UnmanagedSoftwareEnvironment: earliest = {} for node in node_ids: earliest[node] = EarliestStartingTime(nexttime, EarliestStartingTime.EARLIEST_NOPREPARATION) return earliest # Figure out earliest times assuming we have to transfer the images transfer_duration = self.__estimate_image_transfer_time(lease, self.imagenode_bandwidth) if mechanism == constants.TRANSFER_UNICAST: transfer_duration *= lease.numnodes start = self.__get_next_transfer_slot(nexttime, transfer_duration) earliest = {} for node in node_ids: earliest[node] = ImageTransferEarliestStartingTime(start + transfer_duration, ImageTransferEarliestStartingTime.EARLIEST_IMAGETRANSFER) earliest[node].transfer_start = start # Check if we can reuse images if reusealg == constants.REUSE_IMAGECACHES: nodeswithimg = self.resourcepool.get_nodes_with_reusable_image(lease.software.image_id) for node in nodeswithimg: earliest[node].time = nexttime earliest[node].type = ImageTransferEarliestStartingTime.EARLIEST_REUSE # Check if we can avoid redundant transfers if avoidredundant: if mechanism == constants.TRANSFER_UNICAST: # Piggybacking not supported if unicasting # each individual image pass if mechanism == constants.TRANSFER_MULTICAST: # We can only piggyback on transfers that haven't started yet transfers = [t for t in self.transfers if t.state == ResourceReservation.STATE_SCHEDULED] for t in transfers: if t.file == lease.software.image_id: start = t.end if start > nexttime: for n in earliest: if start < earliest[n].time: earliest[n].time = start earliest[n].type = ImageTransferEarliestStartingTime.EARLIEST_PIGGYBACK earliest[n].piggybacking_on = t return earliest
def find_earliest_starting_times(self, lease, nexttime): # The earliest starting time is "nexttime" on all nodes. node_ids = [node.id for node in self.resourcepool.get_nodes()] earliest = {} for node in node_ids: earliest[node] = EarliestStartingTime( nexttime, EarliestStartingTime.EARLIEST_NOPREPARATION) return earliest
def find_earliest_starting_times(self, lease, nexttime): node_ids = [node.id for node in self.resourcepool.get_nodes()] config = get_config() mechanism = config.get("transfer-mechanism") reusealg = config.get("diskimage-reuse") avoidredundant = config.get("avoid-redundant-transfers") if type(lease.software) == UnmanagedSoftwareEnvironment: earliest = {} for node in node_ids: earliest[node] = EarliestStartingTime( nexttime, EarliestStartingTime.EARLIEST_NOPREPARATION) return earliest # Figure out earliest times assuming we have to transfer the images transfer_duration = self.__estimate_image_transfer_time( lease, self.imagenode_bandwidth) if mechanism == constants.TRANSFER_UNICAST: transfer_duration *= lease.numnodes start = self.__get_next_transfer_slot(nexttime, transfer_duration) earliest = {} for node in node_ids: earliest[node] = ImageTransferEarliestStartingTime( start + transfer_duration, ImageTransferEarliestStartingTime.EARLIEST_IMAGETRANSFER) earliest[node].transfer_start = start # Check if we can reuse images if reusealg == constants.REUSE_IMAGECACHES: nodeswithimg = self.resourcepool.get_nodes_with_reusable_image( lease.software.image_id) for node in nodeswithimg: earliest[node].time = nexttime earliest[ node].type = ImageTransferEarliestStartingTime.EARLIEST_REUSE # Check if we can avoid redundant transfers if avoidredundant: if mechanism == constants.TRANSFER_UNICAST: # Piggybacking not supported if unicasting # each individual image pass if mechanism == constants.TRANSFER_MULTICAST: # We can only piggyback on transfers that haven't started yet transfers = [ t for t in self.transfers if t.state == ResourceReservation.STATE_SCHEDULED ] for t in transfers: if t.file == lease.software.image_id: start = t.end if start > nexttime: for n in earliest: if start < earliest[n].time: earliest[n].time = start earliest[ n].type = ImageTransferEarliestStartingTime.EARLIEST_PIGGYBACK earliest[n].piggybacking_on = t return earliest
def __schedule_lease(self, lease, nexttime): """ Schedules a lease. This method orchestrates the preparation and VM scheduler to schedule a lease. Arguments: lease -- Lease to schedule. nexttime -- The next time at which the scheduler can allocate resources. """ lease_state = lease.get_state() migration = get_config().get("migration") # Determine earliest start time in each node if lease_state == Lease.STATE_PENDING or lease_state == Lease.STATE_QUEUED: # This lease might require preparation. Ask the preparation # scheduler for the earliest starting time. earliest = self.preparation_scheduler.find_earliest_starting_times( lease, nexttime) elif lease_state == Lease.STATE_SUSPENDED_PENDING or lease_state == Lease.STATE_SUSPENDED_QUEUED: # This lease may have to be migrated. # We have to ask both the preparation scheduler and the VM # scheduler what would be the earliest possible starting time # on each node, assuming we have to transfer files between # nodes. node_ids = self.slottable.nodes.keys() earliest = {} if migration == constants.MIGRATE_NO: # If migration is disabled, the earliest starting time # is simply nexttime. for node in node_ids: earliest[node] = EarliestStartingTime( nexttime, EarliestStartingTime.EARLIEST_NOPREPARATION) else: # Otherwise, we ask the preparation scheduler and the VM # scheduler how long it would take them to migrate the # lease state. prep_migr_time = self.preparation_scheduler.estimate_migration_time( lease) vm_migr_time = self.vm_scheduler.estimate_migration_time(lease) for node in node_ids: earliest[node] = EarliestStartingTime( nexttime + prep_migr_time + vm_migr_time, EarliestStartingTime.EARLIEST_MIGRATION) else: raise InconsistentLeaseStateError( lease, doing="scheduling a best-effort lease") # Now, we give the lease to the VM scheduler, along with the # earliest possible starting times. If the VM scheduler can # schedule VMs for this lease, it will return a resource reservation # that we can add to the slot table, along with a list of # leases that have to be preempted. # If the VM scheduler can't schedule the VMs, it will throw an # exception (we don't catch it here, and it is just thrown up # to the calling method. (vmrr, preemptions) = self.vm_scheduler.schedule(lease, nexttime, earliest) if vmrr == None and preemptions == None: return # If scheduling the lease involves preempting other leases, # go ahead and preempt them. if len(preemptions) > 0: self.logger.info( "Must preempt leases %s to make room for lease #%i" % ([l.id for l in preemptions], lease.id)) for l in preemptions: self.__preempt_lease(l, preemption_time=vmrr.start) l.strv_counter = l.strv_counter + 1 # Schedule lease preparation is_ready = False preparation_rrs = [] if lease_state in (Lease.STATE_SUSPENDED_PENDING, Lease.STATE_SUSPENDED_QUEUED ) and migration != constants.MIGRATE_NO: # The lease might require migration migr_rrs = self.preparation_scheduler.schedule_migration( lease, vmrr, nexttime) if len(migr_rrs) > 0: end_migr = migr_rrs[-1].end else: end_migr = nexttime migr_rrs += self.vm_scheduler.schedule_migration( lease, vmrr, end_migr) migr_rrs.reverse() for migr_rr in migr_rrs: vmrr.pre_rrs.insert(0, migr_rr) if len(migr_rrs) == 0: is_ready = True elif lease_state in (Lease.STATE_SUSPENDED_PENDING, Lease.STATE_SUSPENDED_QUEUED ) and migration == constants.MIGRATE_NO: # No migration means the lease is ready is_ready = True elif lease_state in (Lease.STATE_PENDING, Lease.STATE_QUEUED): # The lease might require initial preparation preparation_rrs, is_ready = self.preparation_scheduler.schedule( lease, vmrr, earliest) # At this point, the lease is feasible. # Commit changes by adding RRs to lease and to slot table # Add preparation RRs (if any) to lease for rr in preparation_rrs: lease.append_preparationrr(rr) # Add VMRR to lease lease.append_vmrr(vmrr) # Add resource reservations to slottable # Preparation RRs (if any) for rr in preparation_rrs: self.slottable.add_reservation(rr) # Pre-VM RRs (if any) for rr in vmrr.pre_rrs: self.slottable.add_reservation(rr) # VM self.slottable.add_reservation(vmrr) # Post-VM RRs (if any) for rr in vmrr.post_rrs: self.slottable.add_reservation(rr) # Change lease state if lease_state == Lease.STATE_PENDING or lease_state == Lease.STATE_QUEUED: lease.set_state(Lease.STATE_SCHEDULED) if is_ready: lease.set_state(Lease.STATE_READY) elif lease_state == Lease.STATE_SUSPENDED_PENDING or lease_state == Lease.STATE_SUSPENDED_QUEUED: lease.set_state(Lease.STATE_SUSPENDED_SCHEDULED) get_persistence().persist_lease(lease) lease.print_contents()
def __init__(self, time, type): EarliestStartingTime.__init__(self, time, type) self.transfer_start = None self.piggybacking_on = None