# Copyright 2010 Google Inc. All Rights Reserved.
__author__ = 'asharif@google.com (Ahmad Sharif)'
from operator import attrgetter
import copy
import csv
import threading
import os.path
from automation.common import machine
DEFAULT_MACHINES_FILE = os.path.join(os.path.dirname(__file__), 'test_pool.csv')
class MachineManager(object):
"""Container for list of machines one can run jobs on."""
@classmethod
def FromMachineListFile(cls, filename):
# Read the file and skip header
csv_file = csv.reader(open(filename, 'rb'), delimiter=',', quotechar='"')
csv_file.next()
return cls([machine.Machine(hostname, label, cpu, int(cores), os, user)
for hostname, label, cpu, cores, os, user in csv_file])
def __init__(self, machines):
self._machine_pool = machines
self._lock = threading.RLock()
def _GetMachine(self, mach_spec):
available_pool = [m for m in self._machine_pool if mach_spec.IsMatch(m)]
if available_pool:
# find a machine with minimum uses
uses = attrgetter('uses')
mach = min(available_pool, key=uses)
if mach_spec.preferred_machines:
preferred_pool = [m
for m in available_pool
if m.hostname in mach_spec.preferred_machines]
if preferred_pool:
mach = min(preferred_pool, key=uses)
mach.Acquire(mach_spec.lock_required)
return mach
def GetMachines(self, required_machines):
"""Acquire machines for use by a job."""
with self._lock:
acquired_machines = [self._GetMachine(ms) for ms in required_machines]
if not all(acquired_machines):
# Roll back acquires
while acquired_machines:
mach = acquired_machines.pop()
if mach:
mach.Release()
return acquired_machines
def GetMachineList(self):
with self._lock:
return copy.deepcopy(self._machine_pool)
def ReturnMachines(self, machines):
with self._lock:
for m in machines:
m.Release()
def __str__(self):
return str(self._machine_pool)