blob: 99f54fb70be23e73dc15137dce2a9aa862b6514d [file] [log] [blame]
Dale Curtis2468a322011-04-21 10:31:25 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Sean O'Connor5346e4e2010-08-12 18:49:24 +02002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Sean O'Connor6fa1dea2010-04-12 13:19:16 -07004
Dale Curtisa94c19c2011-05-02 15:05:17 -07005from autotest_lib.client.bin import utils
Eric Li538b7042010-12-03 16:12:28 -08006from autotest_lib.client.common_lib import global_config
7from autotest_lib.client.common_lib.cros import autoupdater
Sean O'Connor6fa1dea2010-04-12 13:19:16 -07008from autotest_lib.server import autoserv_parser
Dale Curtisb478f172011-04-12 14:51:14 -07009from autotest_lib.server import site_remote_power
Sean O'Connor6fa1dea2010-04-12 13:19:16 -070010from autotest_lib.server.hosts import base_classes
11
Sean O'Connor5346e4e2010-08-12 18:49:24 +020012
Sean O'Connor6fa1dea2010-04-12 13:19:16 -070013parser = autoserv_parser.autoserv_parser
Sean O'Connor6fa1dea2010-04-12 13:19:16 -070014
Dale Curtisa94c19c2011-05-02 15:05:17 -070015# Time to wait for new kernel to be marked successful.
16_KERNEL_UPDATE_TIMEOUT = 60
17
Dale Curtis53d55862011-05-16 12:17:59 -070018# Ephemeral file to indicate that an update has just occurred.
19_JUST_UPDATED_FLAG = '/tmp/just_updated'
20
Sean O'Connor6fa1dea2010-04-12 13:19:16 -070021
22class ChromiumOSHost(base_classes.Host):
23 """ChromiumOSHost is a special subclass of SSHHost that supports
Sean O'Connor5346e4e2010-08-12 18:49:24 +020024 additional install methods.
Sean O'Connor6fa1dea2010-04-12 13:19:16 -070025 """
26 def __initialize(self, hostname, *args, **dargs):
27 """
28 Construct a ChromiumOSHost object
29
30 Args:
31 hostname: network hostname or address of remote machine
32 """
33 super(ChromiumOSHost, self)._initialize(hostname, *args, **dargs)
34
35
Dale Curtis53d55862011-05-16 12:17:59 -070036 def machine_install(self, update_url=None, force_update=False):
Sean O'Connorcee51432010-06-04 14:48:41 -070037 if parser.options.image:
Dale Curtis2468a322011-04-21 10:31:25 -070038 update_url = parser.options.image
Sean O'Connorcee51432010-06-04 14:48:41 -070039 elif not update_url:
Dale Curtisa94c19c2011-05-02 15:05:17 -070040 raise autoupdater.ChromiumOSError(
41 'Update failed. No update URL provided.')
Eric Li67b7ed52011-04-04 16:40:24 -070042
Dale Curtisa94c19c2011-05-02 15:05:17 -070043 # Attempt to update the system.
44 updater = autoupdater.ChromiumOSUpdater(update_url, host=self)
Dale Curtis53d55862011-05-16 12:17:59 -070045 if updater.run_update(force_update):
Dale Curtisa94c19c2011-05-02 15:05:17 -070046 # Figure out active and inactive kernel.
47 active_kernel, inactive_kernel = updater.get_kernel_state()
Eric Li67b7ed52011-04-04 16:40:24 -070048
Dale Curtisa94c19c2011-05-02 15:05:17 -070049 # Ensure inactive kernel has higher priority than active.
50 if (updater.get_kernel_priority(inactive_kernel)
51 < updater.get_kernel_priority(active_kernel)):
52 raise autoupdater.ChromiumOSError(
53 'Update failed. The priority of the inactive kernel'
54 ' partition is less than that of the active kernel'
55 ' partition.')
56
57 # Updater has returned, successfully, reboot the host.
58 self.reboot(timeout=60, wait=True)
59
60 # Following the reboot, verify the correct version.
61 updater.check_version()
62
63 # Figure out newly active kernel.
64 new_active_kernel, _ = updater.get_kernel_state()
65
66 # Ensure that previously inactive kernel is now the active kernel.
67 if new_active_kernel != inactive_kernel:
68 raise autoupdater.ChromiumOSError(
69 'Update failed. New kernel partition is not active after'
70 ' boot.')
71
Dale Curtisde2a3842011-05-31 12:50:18 -070072 # Wait until tries == 0 and success, or until timeout.
73 utils.poll_for_condition(
74 lambda: (updater.get_kernel_tries(new_active_kernel) == 0
75 and updater.get_kernel_success(new_active_kernel)),
76 exception=autoupdater.ChromiumOSError(
77 'Update failed. Timed out waiting for system to mark'
78 ' new kernel as successful.'),
79 timeout=_KERNEL_UPDATE_TIMEOUT, sleep_interval=5)
Dale Curtisfb2b9f22011-02-14 16:11:25 -080080
Dale Curtis8b9e6612011-05-06 15:10:35 -070081 # TODO(dalecurtis): Hack for R12 builds to make sure BVT runs of
82 # platform_Shutdown pass correctly.
Dale Curtisf57a25f2011-05-24 14:40:55 -070083 if updater.update_version.startswith('0.12'):
Dale Curtis8b9e6612011-05-06 15:10:35 -070084 self.reboot(timeout=60, wait=True)
85
Dale Curtis1770db52011-05-23 14:53:45 -070086 # Mark host as recently updated. Hosts are rebooted at the end of
87 # every test cycle which will remove the file.
88 self.run('touch %s' % _JUST_UPDATED_FLAG)
89
Dale Curtisfb2b9f22011-02-14 16:11:25 -080090 # Clean up any old autotest directories which may be lying around.
91 for path in global_config.global_config.get_config_value(
92 'AUTOSERV', 'client_autodir_paths', type=list):
93 self.run('rm -rf ' + path)
Dale Curtisb478f172011-04-12 14:51:14 -070094
Dale Curtis53d55862011-05-16 12:17:59 -070095
96 def has_just_updated(self):
97 """Indicates whether the host was updated within this boot."""
98 # Check for the existence of the just updated flag file.
99 return self.run(
100 '[ -f %s ] && echo T || echo F'
101 % _JUST_UPDATED_FLAG).stdout.strip() == 'T'
102
Dale Curtisb478f172011-04-12 14:51:14 -0700103
104 def cleanup(self):
105 """Special cleanup method to make sure hosts always get power back."""
106 super(ChromiumOSHost, self).cleanup()
107 remote_power = site_remote_power.RemotePower(self.hostname)
108 if remote_power:
109 remote_power.set_power_on()
Dale Curtis2468a322011-04-21 10:31:25 -0700110
111
112 def verify(self):
113 """Override to ensure only our version of verify_software() is run."""
114 self.verify_hardware()
115 self.verify_connectivity()
116 self.__verify_software()
117
118
119 def __verify_software(self):
120 """Ensure the stateful partition has space for Autotest and updates.
121
122 Similar to what is done by AbstractSSH, except instead of checking the
123 Autotest installation path, just check the stateful partition.
124
125 Checking the stateful partition is preferable in case it has been wiped,
126 resulting in an Autotest installation path which doesn't exist and isn't
127 writable. We still want to pass verify in this state since the partition
128 will be recovered with the next install.
129 """
130 super(ChromiumOSHost, self).verify_software()
131 self.check_diskspace(
132 '/mnt/stateful_partition',
133 global_config.global_config.get_config_value(
134 'SERVER', 'gb_diskspace_required', type=int,
135 default=20))