site_host_attributes.py revision cd61a4f631162aea229df90acfc0eace178705c5
1# Copyright (c) 2010 The Chromium OS 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, os, utils
6
7# Host attributes are specified a strings with the format:
8#   <key>{,<value>}?
9#
10# A machine may have a list of strings for attributes like:
11#
12#   ['has_80211n,True',
13#    'has_ssd,False',
14#    'drive_kind,string,ssd,1']
15#
16# A legal attribute has the pattern:
17#   <name>,<kind>(,<extra>)?
18#
19# Name can be any legal python identifier.  Kind may be any of 'string',
20# 'True', or 'False'.  Only if kind is string can there be extra data.
21#
22# Strings which are not legal attributes are ignored.
23#
24# Given the above list of attributes, you can use the syntax:
25#   host_attributes.drive_kind => 'ssd,1'
26#   host_attributes.has_80211n => True
27#   host_attributes.has_ssd => False
28#   host_attributes.unknown_attribute => raise KeyError
29#
30# Machine attributes can be specified in two ways.
31#
32# If you create private_host_attributes_config.py and
33# private_host_attributes there, we will use it when possible instead of
34# using the server front-end.
35#
36# Example configuration:
37#   private_host_attributes = {
38#     "myserver": ["has_80211n,True",
39#                  "has_resume_bug,False"]
40#   }
41#
42# We also consult the AFE database for its labels which are all treated
43# as host attribute strings defined above.  Illegal strings are ignored.
44#
45
46private_host_attributes = utils.import_site_symbol(
47    __file__,
48    'autotest_lib.server.private_host_attributes_config',
49    'private_host_attributes', dummy={})
50
51try:
52    settings = 'autotest_lib.frontend.settings'
53    os.environ['DJANGO_SETTINGS_MODULE'] = settings
54    from autotest_lib.frontend.afe import models
55    has_models = True
56except ImportError, e:
57    has_models = False
58
59
60_DEFAULT_ATTRIBUTES = [
61    'has_80211n,True',
62    'has_bluetooth,True',
63    'has_chromeos_firmware,False',
64    'has_resume_bug,False',
65    'has_ssd,True',
66    ]
67
68
69class HostAttributes(object):
70
71
72    def __init__(self, host):
73        """
74        Create an instance of HostAttribute for the given hostname.
75        We look up the host in both the hardcoded configuration and
76        the AFE models if they can be found.
77        """
78        self._add_attributes(_DEFAULT_ATTRIBUTES)
79        if host in private_host_attributes:
80            self._add_attributes(private_host_attributes[host])
81        if has_models:
82            host_obj = models.Host.valid_objects.get(hostname=host)
83            self._add_attributes([label.name for label in
84                                  host_obj.labels.all()])
85        for key, value in self.__dict__.items():
86            logging.info('Host attribute: %s => %s', key, value)
87
88
89    def _add_attributes(self, attributes):
90        for attribute in attributes:
91            splitnames = attribute.split(',')
92            value = ','.join(splitnames[1:])
93            if len(splitnames) == 1:
94                continue
95            if value == 'True':
96                value = True
97            elif value == 'False':
98                value = False
99            elif splitnames[1] == 'string' and len(splitnames) > 2:
100                value = ','.join(splitnames[2:])
101            else:
102                logging.info('Non-attribute string "%s" is ignored' % attribute)
103                continue
104            setattr(self, splitnames[0], value)
105