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