예제 #1
0
    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
예제 #2
0
 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
예제 #3
0
    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()
예제 #5
0
 def __init__(self, time, type):
     EarliestStartingTime.__init__(self, time, type)
     self.transfer_start = None
     self.piggybacking_on = None
예제 #6
0
 def __init__(self, time, type):
     EarliestStartingTime.__init__(self, time, type)
     self.transfer_start = None
     self.piggybacking_on = None