1# Copyright (c) 2012 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import Queue
7import time
8import traceback
9
10from autotest_lib.client.common_lib.cros.network import ap_constants
11from autotest_lib.server.cros.ap_configurators import ap_configurator
12from threading import Thread
13
14# Maximum configurators to run at once
15THREAD_MAX = 15
16
17
18class APCartridge(object):
19    """Class to run multiple configurators in parallel."""
20
21
22    def __init__(self):
23        self.cartridge = Queue.Queue()
24
25
26    def push_configurators(self, configurators):
27        """Adds multiple configurators to the cartridge.
28
29        @param configurators: a list of configurator objects.
30        """
31        for configurator in configurators:
32            self.cartridge.put(configurator)
33
34
35    def push_configurator(self, configurator):
36        """Adds a configurator to the cartridge.
37
38        @param configurator: a configurator object.
39        """
40        self.cartridge.put(configurator)
41
42
43    def _apply_settings(self, broken_pdus):
44        while True:
45            configurator = self.cartridge.get()
46            try:
47                # Don't run this thread if the PDU in question was found to be
48                # down by any previous thread.
49                if configurator.pdu in broken_pdus:
50                   configurator.configuration_success = ap_constants.PDU_FAIL
51                   raise ap_configurator.PduNotResponding(configurator.pdu)
52                configurator.apply_settings()
53            except ap_configurator.PduNotResponding as e:
54                if configurator.pdu not in broken_pdus:
55                    broken_pdus.append(configurator.pdu)
56            except Exception:
57                configurator.configuration_success = ap_constants.CONFIG_FAIL
58                trace = ''.join(traceback.format_exc())
59                configurator.store_config_failure(trace)
60                logging.error('Configuration failed for AP: %s\n%s',
61                               configurator.name, trace)
62            finally:
63                configurator.reset_command_list()
64                logging.info('Configuration of AP %s complete.',
65                              configurator.name)
66                self.cartridge.task_done()
67
68
69    def run_configurators(self, broken_pdus):
70        """Runs apply_settings for all configurators in the cartridge.
71
72        @param broken_pdus: List of all the PDUs that are down.
73        """
74        for i in range(THREAD_MAX):
75            t = Thread(target=self._apply_settings,args=(broken_pdus,))
76            t.daemon = True
77            t.start()
78        self.cartridge.join()
79