xref: /aosp_15_r20/external/autotest/server/site_server_job_utils.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Lint as: python2, python3
2*9c5db199SXin Li# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
3*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
4*9c5db199SXin Li# found in the LICENSE file.
5*9c5db199SXin Li
6*9c5db199SXin Li"""Utility classes used by server_job.distribute_across_machines().
7*9c5db199SXin Li
8*9c5db199SXin Litest_item: extends the basic test tuple to add include/exclude attributes and
9*9c5db199SXin Li    pre/post actions.
10*9c5db199SXin Li"""
11*9c5db199SXin Li
12*9c5db199SXin Li
13*9c5db199SXin Liimport logging, os, six.moves.queue
14*9c5db199SXin Lifrom autotest_lib.client.common_lib import error, utils
15*9c5db199SXin Lifrom autotest_lib.server import autotest, hosts, host_attributes
16*9c5db199SXin Li
17*9c5db199SXin Li
18*9c5db199SXin Liclass test_item(object):
19*9c5db199SXin Li    """Adds machine verification logic to the basic test tuple.
20*9c5db199SXin Li
21*9c5db199SXin Li    Tests can either be tuples of the existing form ('testName', {args}) or the
22*9c5db199SXin Li    extended form ('testname', {args}, {'include': [], 'exclude': [],
23*9c5db199SXin Li    'attributes': []}) where include and exclude are lists of host attribute
24*9c5db199SXin Li    labels and attributes is a list of strings. A machine must have all the
25*9c5db199SXin Li    labels in include and must not have any of the labels in exclude to be valid
26*9c5db199SXin Li    for the test. Attributes strings can include reboot_before, reboot_after,
27*9c5db199SXin Li    and server_job.
28*9c5db199SXin Li    """
29*9c5db199SXin Li
30*9c5db199SXin Li    def __init__(self, test_name, test_args, test_attribs=None):
31*9c5db199SXin Li        """Creates an instance of test_item.
32*9c5db199SXin Li
33*9c5db199SXin Li        Args:
34*9c5db199SXin Li            test_name: string, name of test to execute.
35*9c5db199SXin Li            test_args: dictionary, arguments to pass into test.
36*9c5db199SXin Li            test_attribs: Dictionary of test attributes. Valid keys are:
37*9c5db199SXin Li              include - labels a machine must have to run a test.
38*9c5db199SXin Li              exclude - labels preventing a machine from running a test.
39*9c5db199SXin Li              attributes - reboot before/after test, run test as server job.
40*9c5db199SXin Li        """
41*9c5db199SXin Li        self.test_name = test_name
42*9c5db199SXin Li        self.test_args = test_args
43*9c5db199SXin Li        self.tagged_test_name = test_name
44*9c5db199SXin Li        if test_args.get('tag'):
45*9c5db199SXin Li            self.tagged_test_name = test_name + '.' + test_args.get('tag')
46*9c5db199SXin Li
47*9c5db199SXin Li        if test_attribs is None:
48*9c5db199SXin Li            test_attribs = {}
49*9c5db199SXin Li        self.inc_set = set(test_attribs.get('include', []))
50*9c5db199SXin Li        self.exc_set = set(test_attribs.get('exclude', []))
51*9c5db199SXin Li        self.attributes = test_attribs.get('attributes', [])
52*9c5db199SXin Li
53*9c5db199SXin Li    def __str__(self):
54*9c5db199SXin Li        """Return an info string of this test."""
55*9c5db199SXin Li        params = ['%s=%s' % (k, v) for k, v in self.test_args.items()]
56*9c5db199SXin Li        msg = '%s(%s)' % (self.test_name, params)
57*9c5db199SXin Li        if self.inc_set:
58*9c5db199SXin Li            msg += ' include=%s' % [s for s in self.inc_set]
59*9c5db199SXin Li        if self.exc_set:
60*9c5db199SXin Li            msg += ' exclude=%s' % [s for s in self.exc_set]
61*9c5db199SXin Li        if self.attributes:
62*9c5db199SXin Li            msg += ' attributes=%s' % self.attributes
63*9c5db199SXin Li        return msg
64*9c5db199SXin Li
65*9c5db199SXin Li    def validate(self, machine_attributes):
66*9c5db199SXin Li        """Check if this test can run on machine with machine_attributes.
67*9c5db199SXin Li
68*9c5db199SXin Li        If the test has include attributes, a candidate machine must have all
69*9c5db199SXin Li        the attributes to be valid.
70*9c5db199SXin Li
71*9c5db199SXin Li        If the test has exclude attributes, a candidate machine cannot have any
72*9c5db199SXin Li        of the attributes to be valid.
73*9c5db199SXin Li
74*9c5db199SXin Li        Args:
75*9c5db199SXin Li            machine_attributes: set, True attributes of candidate machine.
76*9c5db199SXin Li
77*9c5db199SXin Li        Returns:
78*9c5db199SXin Li            True/False if the machine is valid for this test.
79*9c5db199SXin Li        """
80*9c5db199SXin Li        if self.inc_set is not None:
81*9c5db199SXin Li            if not self.inc_set <= machine_attributes:
82*9c5db199SXin Li                return False
83*9c5db199SXin Li        if self.exc_set is not None:
84*9c5db199SXin Li            if self.exc_set & machine_attributes:
85*9c5db199SXin Li                return False
86*9c5db199SXin Li        return True
87*9c5db199SXin Li
88*9c5db199SXin Li    def run_test(self, client_at, work_dir='.', server_job=None):
89*9c5db199SXin Li        """Runs the test on the client using autotest.
90*9c5db199SXin Li
91*9c5db199SXin Li        Args:
92*9c5db199SXin Li            client_at: Autotest instance for this host.
93*9c5db199SXin Li            work_dir: Directory to use for results and log files.
94*9c5db199SXin Li            server_job: Server_Job instance to use to runs server tests.
95*9c5db199SXin Li        """
96*9c5db199SXin Li        if 'reboot_before' in self.attributes:
97*9c5db199SXin Li            client_at.host.reboot()
98*9c5db199SXin Li
99*9c5db199SXin Li        try:
100*9c5db199SXin Li            if 'server_job' in self.attributes:
101*9c5db199SXin Li                if 'host' in self.test_args:
102*9c5db199SXin Li                    self.test_args['host'] = client_at.host
103*9c5db199SXin Li                if server_job is not None:
104*9c5db199SXin Li                    logging.info('Running Server_Job=%s', self.test_name)
105*9c5db199SXin Li                    server_job.run_test(self.test_name, **self.test_args)
106*9c5db199SXin Li                else:
107*9c5db199SXin Li                    logging.error('No Server_Job instance provided for test '
108*9c5db199SXin Li                                  '%s.', self.test_name)
109*9c5db199SXin Li            else:
110*9c5db199SXin Li                client_at.run_test(self.test_name, results_dir=work_dir,
111*9c5db199SXin Li                                   **self.test_args)
112*9c5db199SXin Li        finally:
113*9c5db199SXin Li            if 'reboot_after' in self.attributes:
114*9c5db199SXin Li                client_at.host.reboot()
115