You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.9 KiB
153 lines
4.9 KiB
import image_chromeos |
|
import lock_machine |
|
import sys |
|
import threading |
|
import time |
|
from cros_utils import command_executer |
|
from cros_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)
|
|
|