blob: 9588e9523155396c583140b88df3a6771f35ad70 [file] [log] [blame]
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()]