# vim: set fileencoding=utf-8 : import yaml class WorkerSlotModel: def __init__ (self, slots, worker, env): self._slots = slots self._worker = worker self._env = env # generated properties, public, read-only self.slotNames = set (slots.keys ()) assert len (self.slotNames) == len (slots.keys ()), "slot names must be unique" self.workerNames = set (worker.keys ()) assert len (self.workerNames) == len (worker.keys ()), "worker names must be unique" self.minTotalSlots = self._env.get ('minSlots', 0) self.maxTotalSlots = self._env.get ('maxSlots', len (self.slotNames)) # sanity-checks # min workers per slot must be smaller than total number of workers for s in self.slotNames: assert self.minWorker (s) <= len (self.workerNames), "Min workers per slot must be <= total workers" @classmethod def fromYaml (obj, fd): """ Import from YAML file. Structured like this: """ data = yaml.load (fd) o = obj (data['slots'], data['worker'], data.get ('env', {})) return o def available (self, worker, slot): """ Is worker available for slot? """ return self.priority (worker, slot) is not None def priority (self, worker, slot): """ Get worker’s preferences/priority for slot, priority is higher for smaller numbers and must be >= 1 """ return self._worker[worker]['prio'].get (slot, None) def maxSlots (self, worker): """ Get max number of slots to assign to worker. Defaults to 1. """ return self._worker[worker].get ('slots', {}).get ('max', 1) def minSlots (self, worker): """ Get min number of slots to assign to worker. Defaults to 1. """ return self._worker[worker].get ('slots', {}).get ('min', 1) def maxWorker (self, slot): """ Get max number of worker for slot, defaults to #worker """ return self._slots[slot].get ('max', len (self.workerNames)) def minWorker (self, slot): """ Get min number of worker for slot. Defaults to 0. """ return self._slots[slot].get ('min', 0) def dump (self, fd): yaml.dump ({'worker': self._worker, 'slots': self._slots, 'env': self._env}, fd)