blob: ca8a79857b6e749ebc4ff22dc416f244b7c7e7ed [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):
Justin Giorgid76ed502016-06-21 10:27:52 -070023 """Required by atest's site logic."""
Simran Basic6f1f7a2012-10-16 10:47:46 -070024 pass
25
26
27class site_host_create(site_host, host.host_create):
28 """
29 site_host_create subclasses host_create in host.py.
30 """
31
Jiaxi Luoc342f9f2014-05-19 16:22:03 -070032 @classmethod
33 def construct_without_parse(
34 cls, web_server, hosts, platform=None,
Matthew Sartori68186332015-04-27 17:19:53 -070035 locked=False, lock_reason='', labels=[], acls=[],
Jiaxi Luoc342f9f2014-05-19 16:22:03 -070036 protection=host_protections.Protection.NO_PROTECTION):
37 """Construct an site_host_create object and fill in data from args.
38
39 Do not need to call parse after the construction.
40
41 Return an object of site_host_create ready to execute.
42
43 @param web_server: A string specifies the autotest webserver url.
44 It is needed to setup comm to make rpc.
45 @param hosts: A list of hostnames as strings.
46 @param platform: A string or None.
47 @param locked: A boolean.
Matthew Sartori68186332015-04-27 17:19:53 -070048 @param lock_reason: A string.
Jiaxi Luoc342f9f2014-05-19 16:22:03 -070049 @param labels: A list of labels as strings.
50 @param acls: A list of acls as strings.
51 @param protection: An enum defined in host_protections.
52 """
53 obj = cls()
54 obj.web_server = web_server
55 try:
56 # Setup stuff needed for afe comm.
57 obj.afe = rpc.afe_comm(web_server)
58 except rpc.AuthError, s:
59 obj.failure(str(s), fatal=True)
60 obj.hosts = hosts
61 obj.platform = platform
62 obj.locked = locked
Matthew Sartori68186332015-04-27 17:19:53 -070063 if locked and lock_reason.strip():
64 obj.data['lock_reason'] = lock_reason.strip()
Jiaxi Luoc342f9f2014-05-19 16:22:03 -070065 obj.labels = labels
66 obj.acls = acls
67 if protection:
68 obj.data['protection'] = protection
Kevin Chengbdedeb12016-01-12 16:28:43 -080069 # TODO(kevcheng): Update the admin page to take in serials?
70 obj.serials = None
Jiaxi Luoc342f9f2014-05-19 16:22:03 -070071 return obj
72
Simran Basic6f1f7a2012-10-16 10:47:46 -070073
74 def _execute_add_one_host(self, host):
75 # Always add the hosts as locked to avoid the host
Jiaxi Luob0e6c602014-05-13 16:06:24 -070076 # being picked up by the scheduler before it's ACL'ed.
Simran Basic6f1f7a2012-10-16 10:47:46 -070077 self.data['locked'] = True
Matthew Sartori68186332015-04-27 17:19:53 -070078 if not self.locked:
79 self.data['lock_reason'] = 'Forced lock on device creation'
Simran Basic6f1f7a2012-10-16 10:47:46 -070080 self.execute_rpc('add_host', hostname=host,
81 status="Ready", **self.data)
82 # If there are labels avaliable for host, use them.
83 host_info = self.host_info_map[host]
Jiaxi Luob0e6c602014-05-13 16:06:24 -070084 labels = set(self.labels)
Simran Basic6f1f7a2012-10-16 10:47:46 -070085 if host_info.labels:
Jiaxi Luob0e6c602014-05-13 16:06:24 -070086 labels.update(host_info.labels)
87 # Now add the platform label.
88 # If a platform was not provided and we were able to retrieve it
89 # from the host, use the retrieved platform.
90 platform = self.platform if self.platform else host_info.platform
91 if platform:
92 labels.add(platform)
93
Simran Basic6f1f7a2012-10-16 10:47:46 -070094 if len(labels):
Jiaxi Luob0e6c602014-05-13 16:06:24 -070095 self.execute_rpc('host_add_labels', id=host, labels=list(labels))
Simran Basic6f1f7a2012-10-16 10:47:46 -070096
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070097 if self.serials:
Justin Giorgid76ed502016-06-21 10:27:52 -070098 self.execute_rpc('set_host_attribute', hostname=host,
99 attribute='serials', value=','.join(self.serials))
Simran Basic6f1f7a2012-10-16 10:47:46 -0700100
101 def execute(self):
102 # Check to see if the platform or any other labels can be grabbed from
103 # the hosts.
104 self.host_info_map = {}
105 for host in self.hosts:
106 try:
Simran Basibe7b65b2012-11-21 09:33:27 -0800107 if utils.ping(host, tries=1, deadline=1) == 0:
Kevin Cheng49f7b812015-12-15 15:24:23 -0800108 if self.serials and len(self.serials) > 1:
109 host_dut = hosts.create_testbed(
110 host, adb_serials=self.serials)
111 else:
Kevin Chengd7ef5d32016-01-08 16:19:28 -0800112 adb_serial = None
113 if self.serials:
114 adb_serial = self.serials[0]
115 host_dut = hosts.create_host(host,
116 adb_serial=adb_serial)
Simran Basibe7b65b2012-11-21 09:33:27 -0800117 host_info = host_information(host,
Kevin Cheng49f7b812015-12-15 15:24:23 -0800118 host_dut.get_platform(),
119 host_dut.get_labels())
Simran Basibe7b65b2012-11-21 09:33:27 -0800120 else:
121 # Can't ping the host, use default information.
122 host_info = host_information(host, None, [])
123 except (socket.gaierror, error.AutoservRunError,
124 error.AutoservSSHTimeout):
Simran Basic6f1f7a2012-10-16 10:47:46 -0700125 # We may be adding a host that does not exist yet or we can't
Simran Basibe7b65b2012-11-21 09:33:27 -0800126 # reach due to hostname/address issues or if the host is down.
Simran Basic6f1f7a2012-10-16 10:47:46 -0700127 host_info = host_information(host, None, [])
128 self.host_info_map[host] = host_info
129 # We need to check if these labels & ACLs exist,
130 # and create them if not.
131 if self.platform:
132 self.check_and_create_items('get_labels', 'add_label',
133 [self.platform],
134 platform=True)
135 else:
136 # No platform was provided so check and create the platform label
137 # for each host.
138 platforms = []
139 for host_info in self.host_info_map.values():
140 if host_info.platform and host_info.platform not in platforms:
141 platforms.append(host_info.platform)
Jiaxi Luoc342f9f2014-05-19 16:22:03 -0700142 if platforms:
Simran Basic6f1f7a2012-10-16 10:47:46 -0700143 self.check_and_create_items('get_labels', 'add_label',
144 platforms,
145 platform=True)
146 labels_to_check_and_create = self.labels[:]
147 for host_info in self.host_info_map.values():
148 labels_to_check_and_create = (host_info.labels +
149 labels_to_check_and_create)
150 if labels_to_check_and_create:
151 self.check_and_create_items('get_labels', 'add_label',
152 labels_to_check_and_create,
153 platform=False)
154
155 if self.acls:
156 self.check_and_create_items('get_acl_groups',
157 'add_acl_group',
158 self.acls)
159
Jiaxi Luoc342f9f2014-05-19 16:22:03 -0700160 return self._execute_add_hosts()
Simran Basic6f1f7a2012-10-16 10:47:46 -0700161
162
163class host_information(object):
164 """Store host information so we don't have to keep looking it up."""
165
166
167 def __init__(self, hostname, platform, labels):
168 self.hostname = hostname
169 self.platform = platform
170 self.labels = labels
171
172
173# Any classes we don't override in host should be copied automatically
174for cls in [getattr(host, n) for n in dir(host) if not n.startswith("_")]:
175 if not inspect.isclass(cls):
176 continue
177 cls_name = cls.__name__
178 site_cls_name = 'site_' + cls_name
179 if hasattr(sys.modules[__name__], site_cls_name):
180 continue
181 bases = (site_host, cls)
182 members = {'__doc__': cls.__doc__}
183 site_cls = new.classobj(site_cls_name, bases, members)
184 setattr(sys.modules[__name__], site_cls_name, site_cls)