blob: 4015f918d9e73c9bb565e08489a3dd486186313d [file] [log] [blame]
#!/usr/bin/python
from benchmark import Benchmark
from collections import defaultdict
# Find Label for a DUT. This is done by iterating all the labels (usually < 10)
# and compare each lable's image with Dut's image (how?) and also check DUT's
# name against labels' remote (if presented). This could return None if a DUT
# has an image that is not listed in any label.
def FindLabelForDut(dut)
# ...
pass
class DUT(object):
# Device under test.
# name_ - the hostname/ip of the machine
# label_ - the corresponding label or None.
# board_ - board (optional)
def __init__(self, name, board):
self.name_ = name
# Maybe None before any reimaging happens.
self.label_ = FindLabelForDut(self)
def ReImage(self, label):
call_utility_function_to_reimage(self, label)
self.label_ = label
class TestPiece(object):
# Minimal units to be scheduled
# benchmark - as described in benchmark.py module
# nth - each TestPiece may run many times, this is the idx
# label - TestPiece run against
def __init__(self, benchmark, nth, label):
self.benchmark_ = benchmark
self.nth_ = nth
self.label_ = label
class TestPiecePool(object):
# label_tpl_map_ - label to TestPiece list mapping.
# label_num_map_ - label to num of deployment mapping.
def __init__(self, test_piece_list):
self.label_tpl_map_ = defaultdict(lambda: [])
self.label_num_map_ = defaultdict(lambda: 0)
for tp in test_piece_list:
self.label_tpl_map_[tp.label_].append(tp)
self.label_num_map_[tp.label_] = 0
# This is usually called by multiple threads.
def GetTestPiece(self, dut):
tp = GetTestPieceInternal(self, dut)
while tp is None:
# The current dut image does not match any experiment labels,
# request reimage.
label = self.FindReImageCandidate(self)
if lable is None:
# We don't have any label that this machine can reimage to. On
# return, the dut thread will finish.
return None
dut.ReImage(label)
tp = GetTestPieceInternal(self, dut)
return tp
def _GetTestPieceInternal(self, dut):
if dut.label_ is not None and dut.label_ in self.label_tpl_map_:
tp_list = self.label_tpl_map_[dut.label_]
tp = None
##### Lock on tp_list
if len(tp_list):
tp = tp_list.pop()
if not len(tp_list):
#### Lock on self.label_tpl_map_
del self.label_tpl_map_[dut.label]
#### Unlock on self.label_tpl_map_
##### Unlock on tp_list
return tp
return None
def _FindReImageCandidate(self, dut):
# We will pick up the image desc with minimal deployment number.
minlabel, minnum = None, 999999
for label, num in self.label_num_map_.iteritems():
if (num < minnum and len(self.label_tpl_map_[label]) > 0 and
label.remote is None or dut.name_ in label.remote):
minlabel = label
minnum = num
if minlabel is not None:
#### Lock on self.label_num_map_
self.label_num_map_[minlabel] += 1
#### Unlock on self.label_num_map_
# minlabel may be None
return minlabel