• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2010 Google Inc. All Rights Reserved.
2
3__author__ = 'asharif@google.com (Ahmad Sharif)'
4
5from operator import attrgetter
6import copy
7import csv
8import threading
9import os.path
10
11from automation.common import machine
12
13DEFAULT_MACHINES_FILE = os.path.join(os.path.dirname(__file__), 'test_pool.csv')
14
15
16class MachineManager(object):
17  """Container for list of machines one can run jobs on."""
18
19  @classmethod
20  def FromMachineListFile(cls, filename):
21    # Read the file and skip header
22    csv_file = csv.reader(open(filename, 'rb'), delimiter=',', quotechar='"')
23    csv_file.next()
24
25    return cls([machine.Machine(hostname, label, cpu, int(cores), os, user)
26                for hostname, label, cpu, cores, os, user in csv_file])
27
28  def __init__(self, machines):
29    self._machine_pool = machines
30    self._lock = threading.RLock()
31
32  def _GetMachine(self, mach_spec):
33    available_pool = [m for m in self._machine_pool if mach_spec.IsMatch(m)]
34
35    if available_pool:
36      # find a machine with minimum uses
37      uses = attrgetter('uses')
38
39      mach = min(available_pool, key=uses)
40
41      if mach_spec.preferred_machines:
42        preferred_pool = [m
43                          for m in available_pool
44                          if m.hostname in mach_spec.preferred_machines]
45        if preferred_pool:
46          mach = min(preferred_pool, key=uses)
47
48      mach.Acquire(mach_spec.lock_required)
49
50      return mach
51
52  def GetMachines(self, required_machines):
53    """Acquire machines for use by a job."""
54
55    with self._lock:
56      acquired_machines = [self._GetMachine(ms) for ms in required_machines]
57
58      if not all(acquired_machines):
59        # Roll back acquires
60        while acquired_machines:
61          mach = acquired_machines.pop()
62          if mach:
63            mach.Release()
64
65      return acquired_machines
66
67  def GetMachineList(self):
68    with self._lock:
69      return copy.deepcopy(self._machine_pool)
70
71  def ReturnMachines(self, machines):
72    with self._lock:
73      for m in machines:
74        m.Release()
75
76  def __str__(self):
77    return str(self._machine_pool)
78