blob: a1853c98be32e459dd7cc1282375966fe1375365 [file] [log] [blame]
Simran Basic6f1f7a2012-10-16 10:47:46 -07001# Copyright (c) 2011 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 common
6import inspect, new, socket, sys
7
Simran Basibe7b65b2012-11-21 09:33:27 -08008from autotest_lib.client.bin import utils
Jiaxi Luoc342f9f2014-05-19 16:22:03 -07009from autotest_lib.cli import host, rpc
Simran Basic6f1f7a2012-10-16 10:47:46 -070010from autotest_lib.server import hosts
Jiaxi Luoc342f9f2014-05-19 16:22:03 -070011from autotest_lib.client.common_lib import error, host_protections
Simran Basic6f1f7a2012-10-16 10:47:46 -070012
13
14# In order for hosts to work correctly, some of its variables must be setup.
15hosts.factory.ssh_user = 'root'
16hosts.factory.ssh_pass = ''
17hosts.factory.ssh_port = 22
Fang Deng6bee3de2013-09-04 20:17:26 -070018hosts.factory.ssh_verbosity_flag = ''
19hosts.factory.ssh_options = ''
Simran Basic6f1f7a2012-10-16 10:47:46 -070020
21
22class site_host(host.host):
23 pass
24
25
26class site_host_create(site_host, host.host_create):
27 """
28 site_host_create subclasses host_create in host.py.
29 """
30
Jiaxi Luoc342f9f2014-05-19 16:22:03 -070031 @classmethod
32 def construct_without_parse(
33 cls, web_server, hosts, platform=None,
34 locked=False, labels=[], acls=[],
35 protection=host_protections.Protection.NO_PROTECTION):
36 """Construct an site_host_create object and fill in data from args.
37
38 Do not need to call parse after the construction.
39
40 Return an object of site_host_create ready to execute.
41
42 @param web_server: A string specifies the autotest webserver url.
43 It is needed to setup comm to make rpc.
44 @param hosts: A list of hostnames as strings.
45 @param platform: A string or None.
46 @param locked: A boolean.
47 @param labels: A list of labels as strings.
48 @param acls: A list of acls as strings.
49 @param protection: An enum defined in host_protections.
50 """
51 obj = cls()
52 obj.web_server = web_server
53 try:
54 # Setup stuff needed for afe comm.
55 obj.afe = rpc.afe_comm(web_server)
56 except rpc.AuthError, s:
57 obj.failure(str(s), fatal=True)
58 obj.hosts = hosts
59 obj.platform = platform
60 obj.locked = locked
61 obj.labels = labels
62 obj.acls = acls
63 if protection:
64 obj.data['protection'] = protection
65 return obj
66
Simran Basic6f1f7a2012-10-16 10:47:46 -070067
68 def _execute_add_one_host(self, host):
69 # Always add the hosts as locked to avoid the host
Jiaxi Luob0e6c602014-05-13 16:06:24 -070070 # being picked up by the scheduler before it's ACL'ed.
Simran Basic6f1f7a2012-10-16 10:47:46 -070071 self.data['locked'] = True
72 self.execute_rpc('add_host', hostname=host,
73 status="Ready", **self.data)
74 # If there are labels avaliable for host, use them.
75 host_info = self.host_info_map[host]
Jiaxi Luob0e6c602014-05-13 16:06:24 -070076 labels = set(self.labels)
Simran Basic6f1f7a2012-10-16 10:47:46 -070077 if host_info.labels:
Jiaxi Luob0e6c602014-05-13 16:06:24 -070078 labels.update(host_info.labels)
79 # Now add the platform label.
80 # If a platform was not provided and we were able to retrieve it
81 # from the host, use the retrieved platform.
82 platform = self.platform if self.platform else host_info.platform
83 if platform:
84 labels.add(platform)
85
Simran Basic6f1f7a2012-10-16 10:47:46 -070086 if len(labels):
Jiaxi Luob0e6c602014-05-13 16:06:24 -070087 self.execute_rpc('host_add_labels', id=host, labels=list(labels))
Simran Basic6f1f7a2012-10-16 10:47:46 -070088
89
90 def execute(self):
91 # Check to see if the platform or any other labels can be grabbed from
92 # the hosts.
93 self.host_info_map = {}
94 for host in self.hosts:
95 try:
Simran Basibe7b65b2012-11-21 09:33:27 -080096 if utils.ping(host, tries=1, deadline=1) == 0:
97 ssh_host = hosts.create_host(host)
98 host_info = host_information(host,
99 ssh_host.get_platform(),
100 ssh_host.get_labels())
101 else:
102 # Can't ping the host, use default information.
103 host_info = host_information(host, None, [])
104 except (socket.gaierror, error.AutoservRunError,
105 error.AutoservSSHTimeout):
Simran Basic6f1f7a2012-10-16 10:47:46 -0700106 # We may be adding a host that does not exist yet or we can't
Simran Basibe7b65b2012-11-21 09:33:27 -0800107 # reach due to hostname/address issues or if the host is down.
Simran Basic6f1f7a2012-10-16 10:47:46 -0700108 host_info = host_information(host, None, [])
109 self.host_info_map[host] = host_info
110 # We need to check if these labels & ACLs exist,
111 # and create them if not.
112 if self.platform:
113 self.check_and_create_items('get_labels', 'add_label',
114 [self.platform],
115 platform=True)
116 else:
117 # No platform was provided so check and create the platform label
118 # for each host.
119 platforms = []
120 for host_info in self.host_info_map.values():
121 if host_info.platform and host_info.platform not in platforms:
122 platforms.append(host_info.platform)
Jiaxi Luoc342f9f2014-05-19 16:22:03 -0700123 if platforms:
Simran Basic6f1f7a2012-10-16 10:47:46 -0700124 self.check_and_create_items('get_labels', 'add_label',
125 platforms,
126 platform=True)
127 labels_to_check_and_create = self.labels[:]
128 for host_info in self.host_info_map.values():
129 labels_to_check_and_create = (host_info.labels +
130 labels_to_check_and_create)
131 if labels_to_check_and_create:
132 self.check_and_create_items('get_labels', 'add_label',
133 labels_to_check_and_create,
134 platform=False)
135
136 if self.acls:
137 self.check_and_create_items('get_acl_groups',
138 'add_acl_group',
139 self.acls)
140
Jiaxi Luoc342f9f2014-05-19 16:22:03 -0700141 return self._execute_add_hosts()
Simran Basic6f1f7a2012-10-16 10:47:46 -0700142
143
144class host_information(object):
145 """Store host information so we don't have to keep looking it up."""
146
147
148 def __init__(self, hostname, platform, labels):
149 self.hostname = hostname
150 self.platform = platform
151 self.labels = labels
152
153
154# Any classes we don't override in host should be copied automatically
155for cls in [getattr(host, n) for n in dir(host) if not n.startswith("_")]:
156 if not inspect.isclass(cls):
157 continue
158 cls_name = cls.__name__
159 site_cls_name = 'site_' + cls_name
160 if hasattr(sys.modules[__name__], site_cls_name):
161 continue
162 bases = (site_host, cls)
163 members = {'__doc__': cls.__doc__}
164 site_cls = new.classobj(site_cls_name, bases, members)
165 setattr(sys.modules[__name__], site_cls_name, site_cls)