| import image_chromeos |
| import lock_machine |
| import sys |
| import threading |
| import time |
| from utils import command_executer |
| from utils import logger |
| |
| |
| class CrosMachine(object): |
| |
| def __init__(self, name): |
| self.name = name |
| self.image = None |
| self.checksum = None |
| self.locked = False |
| self.released_time = time.time() |
| self.autotest_run = None |
| |
| def __str__(self): |
| l = [] |
| l.append(self.name) |
| l.append(str(self.image)) |
| l.append(str(self.checksum)) |
| l.append(str(self.locked)) |
| l.append(str(self.released_time)) |
| return ', '.join(l) |
| |
| |
| class MachineManagerSingleton(object): |
| _instance = None |
| _lock = threading.RLock() |
| _all_machines = [] |
| _machines = [] |
| image_lock = threading.Lock() |
| num_reimages = 0 |
| chromeos_root = None |
| no_lock = False |
| |
| def __new__(cls, *args, **kwargs): |
| with cls._lock: |
| if not cls._instance: |
| cls._instance = super(MachineManagerSingleton, cls).__new__(cls, *args, |
| **kwargs) |
| return cls._instance |
| |
| def TryToLockMachine(self, cros_machine): |
| with self._lock: |
| assert cros_machine, "Machine can't be None" |
| for m in self._machines: |
| assert m.name != cros_machine.name, ('Tried to double-lock %s' % |
| cros_machine.name) |
| if self.no_lock: |
| locked = True |
| else: |
| locked = lock_machine.Machine(cros_machine.name).Lock(True, sys.argv[0]) |
| if locked: |
| ce = command_executer.GetCommandExecuter() |
| command = 'cat %s' % image_chromeos.checksum_file |
| ret, out, err = ce.CrosRunCommandWOutput( |
| command, |
| chromeos_root=self.chromeos_root, |
| machine=cros_machine.name) |
| if ret == 0: |
| cros_machine.checksum = out.strip() |
| self._machines.append(cros_machine) |
| else: |
| logger.GetLogger().LogOutput("Warning: Couldn't lock: %s" % |
| cros_machine.name) |
| |
| # This is called from single threaded mode. |
| def AddMachine(self, machine_name): |
| with self._lock: |
| for m in self._all_machines: |
| assert m.name != machine_name, 'Tried to double-add %s' % machine_name |
| self._all_machines.append(CrosMachine(machine_name)) |
| |
| def AcquireMachine(self, image_checksum): |
| with self._lock: |
| # Lazily external lock machines |
| if not self._machines: |
| for m in self._all_machines: |
| self.TryToLockMachine(m) |
| assert self._machines, ('Could not lock any machine in %s' % |
| self._all_machines) |
| |
| ### for m in self._machines: |
| ### if (m.locked and time.time() - m.released_time < 10 and |
| ### m.checksum == image_checksum): |
| ### return None |
| for m in [machine for machine in self._machines if not machine.locked]: |
| if m.checksum == image_checksum: |
| m.locked = True |
| m.autotest_run = threading.current_thread() |
| return m |
| for m in [machine for machine in self._machines if not machine.locked]: |
| if not m.checksum: |
| m.locked = True |
| m.autotest_run = threading.current_thread() |
| return m |
| for m in [machine for machine in self._machines if not machine.locked]: |
| if time.time() - m.released_time > 20: |
| m.locked = True |
| m.autotest_run = threading.current_thread() |
| return m |
| return None |
| |
| def ReleaseMachine(self, machine): |
| with self._lock: |
| for m in self._machines: |
| if machine.name == m.name: |
| assert m.locked == True, 'Tried to double-release %s' % m.name |
| m.released_time = time.time() |
| m.locked = False |
| m.status = 'Available' |
| break |
| |
| def __del__(self): |
| with self._lock: |
| # Unlock all machines. |
| for m in self._machines: |
| if not self.no_lock: |
| assert lock_machine.Machine(m.name).Unlock(True) == True, ( |
| "Couldn't unlock machine: %s" % m.name) |
| |
| def __str__(self): |
| with self._lock: |
| l = ['MachineManager Status:'] |
| for m in self._machines: |
| l.append(str(m)) |
| return '\n'.join(l) |
| |
| def AsString(self): |
| with self._lock: |
| stringify_fmt = '%-30s %-10s %-4s %-25s %-32s' |
| header = stringify_fmt % ('Machine', 'Thread', 'Lock', 'Status', |
| 'Checksum') |
| table = [header] |
| for m in self._machines: |
| if m.autotest_run: |
| autotest_name = m.autotest_run.name |
| autotest_status = m.autotest_run.status |
| else: |
| autotest_name = '' |
| autotest_status = '' |
| |
| try: |
| machine_string = stringify_fmt % (m.name, autotest_name, m.locked, |
| autotest_status, m.checksum) |
| except: |
| machine_string = '' |
| table.append(machine_string) |
| return 'Machine Status:\n%s' % '\n'.join(table) |