from autotest_lib.client.common_lib import utils

class HostSchedulingUtility(object):
    """Interface to host availability information from the scheduler."""
    def hosts_in_label(self, label_id):
        """Return potentially usable hosts with the given label."""
        raise NotImplementedError


    def remove_host_from_label(self, host_id, label_id):
        """Remove this host from the internal list of usable hosts in the label.

        This is provided as an optimization -- when code gets a host from a
        label and concludes it's unusable, it can call this to avoid getting
        that host again in the future (within this tick).  This function should
        not affect correctness.
        """
        raise NotImplementedError


    def pop_host(self, host_id):
        """Remove and return a host from the internal list of available hosts.
        """
        raise NotImplementedError


    def ineligible_hosts_for_entry(self, queue_entry):
        """Get the list of hosts ineligible to run the given queue entry."""
        raise NotImplementedError


    def is_host_usable(self, host_id):
        """Determine if the host is currently usable at all."""
        raise NotImplementedError


    def is_host_eligible_for_job(self, host_id, queue_entry):
        """Determine if the host is eligible specifically for this queue entry.

        @param queue_entry: a HostQueueEntry DBObject
        """
        raise NotImplementedError


class MetahostScheduler(object):
    def can_schedule_metahost(self, queue_entry):
        """Return true if this object can schedule the given queue entry.

        At most one MetahostScheduler should return true for any given entry.

        @param queue_entry: a HostQueueEntry DBObject
        """
        raise NotImplementedError


    def schedule_metahost(self, queue_entry, scheduling_utility):
         """Schedule the given queue entry, if possible.

         This method should make necessary database changes culminating in
         assigning a host to the given queue entry in the database.  It may
         take no action if no host can be assigned currently.

         @param queue_entry: a HostQueueEntry DBObject
         @param scheduling_utility: a HostSchedulingUtility object
         """
         raise NotImplementedError


    def recovery_on_startup(self):
        """Perform any necessary recovery upon scheduler startup."""
        pass


    def tick(self):
        """Called once per scheduler cycle; any actions are allowed."""
        pass


class LabelMetahostScheduler(MetahostScheduler):
    def can_schedule_metahost(self, queue_entry):
        return bool(queue_entry.meta_host)


    def schedule_metahost(self, queue_entry, scheduling_utility):
        label_id = queue_entry.meta_host
        hosts_in_label = scheduling_utility.hosts_in_label(label_id)
        ineligible_host_ids = scheduling_utility.ineligible_hosts_for_entry(
                queue_entry)

        for host_id in hosts_in_label:
            if not scheduling_utility.is_host_usable(host_id):
                scheduling_utility.remove_host_from_label(host_id, label_id)
                continue
            if host_id in ineligible_host_ids:
                continue
            if not scheduling_utility.is_host_eligible_for_job(host_id,
                                                               queue_entry):
                continue

            # Remove the host from our cached internal state before returning
            scheduling_utility.remove_host_from_label(host_id, label_id)
            host = scheduling_utility.pop_host(host_id)
            queue_entry.set_host(host)
            return


def get_metahost_schedulers():
    return [LabelMetahostScheduler()]
