autoupdate_EndToEndTest.py revision 03901089c0db27508a6b2ff61ae8b75eba77cf37
10ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 20ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold# Use of this source code is governed by a BSD-style license that can be 30ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold# found in the LICENSE file. 40ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 50ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldimport json 60ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldimport logging 70ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldimport socket 80ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldimport subprocess 903901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnoldimport tempfile 100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldimport time 110ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldimport urllib2 120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldimport urlparse 1303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 1403901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnoldfrom autotest_lib.client.common_lib import error, global_config, site_utils 150ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldfrom autotest_lib.client.common_lib.cros import autoupdater, dev_server 160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldfrom autotest_lib.server import test 170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 190ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnolddef _wait(secs, desc=None): 200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Emits a log message and sleeps for a given number of seconds.""" 210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold msg = 'waiting %s seconds' % secs 220ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if desc: 230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold msg += ' (%s)' % desc 240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info(msg) 250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold time.sleep(secs) 260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldclass ExpectedUpdateEvent(object): 290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Defines an expected event in a host update process.""" 300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def __init__(self, event_type=None, event_result=None, version=None, 310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold previous_version=None): 320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._expected_attrs = { 330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'event_type': event_type, 340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'event_result': event_result, 350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'version': version, 360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'previous_version': previous_version, 370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold } 380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def __str__(self): 410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return ' '.join(['%s=%s' % (attr_name, attr_val or 'any') 420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold for attr_name, attr_val 430ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold in self._expected_attrs.iteritems()]) 440ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 450ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 460ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def verify(self, actual_event): 470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Verify the attributes of an actual event. 480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 490ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @params actual_event: a dictionary containing event attributes 500ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 510ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @return True if all attributes as expected, False otherwise. 520ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return all([self._verify_attr(attr_name, expected_attr_val, 550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold actual_event.get(attr_name)) 560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold for attr_name, expected_attr_val 570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold in self._expected_attrs.iteritems() if expected_attr_val]) 580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _verify_attr(self, attr_name, expected_attr_val, actual_attr_val): 610ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Verifies that an actual log event attributes matches expected on. 620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 630ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param attr_name: name of the attribute to verify 640ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param expected_attr_val: expected attribute value 650ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param actual_attr_val: actual attribute value 660ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 670ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @return True if actual value is present and matches, False otherwise. 680ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 690ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 700ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not (actual_attr_val and 710ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold str(actual_attr_val) == str(expected_attr_val)): 720ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.error( 730ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'actual %s (%s) not as expected (%s)', 740ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold attr_name, actual_attr_val, expected_attr_val) 750ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return False 760ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 770ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return True 780ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 790ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 800ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldclass ExpectedUpdateEventChain(object): 810ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Defines a chain of expected update events.""" 820ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def __init__(self, *expected_event_chain_args): 830ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Initialize the chain object. 840ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 850ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param expected_event_chain_args: list of tuples arguments, each 860ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold containing a timeout (in seconds) and an ExpectedUpdateEvent 870ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold object. 880ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 890ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 900ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._expected_event_chain = expected_event_chain_args 910ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 920ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 930ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _format_event_with_timeout(self, timeout, expected_event): 940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return ('%s %s' % 950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (expected_event, 960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ('within %s seconds' % timeout) if timeout 970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else 'indefinitely')) 980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1000ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def __str__(self): 1010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return ('[%s]' % 1020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ', '.join( 1030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold [self._format_event_with_timeout(timeout, expected_event) 1040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold for timeout, expected_event 1050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold in self._expected_event_chain])) 1060ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1080ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def __repr__(self): 1090ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return str(self._expected_event_chain) 1100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1110ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def verify(self, get_next_event): 1130ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Verifies that an actual stream of events complies. 1140ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1150ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param get_next_event: a function returning the next event 1160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @return True if chain was satisfied, False otherwise. 1180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1190ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 1200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold for timeout, expected_event in self._expected_event_chain: 1210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info( 1220ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'expecting %s', 1230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._format_event_with_timeout(timeout, expected_event)) 1240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not self._verify_event_with_timeout( 1250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold timeout, expected_event, get_next_event): 1260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return False 1270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return True 1280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _verify_event_with_timeout(self, timeout, expected_event, 1310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold get_next_event): 1320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Verify an expected event occurs within a given timeout. 1330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param timeout: specified in seconds 1350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param expected_event: an expected event specification 1360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param get_next_event: function returning the next event in a stream 1370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @return True if event complies, False otherwise. 1390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 1410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold base_timestamp = curr_timestamp = time.time() 1420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold expired_timestamp = base_timestamp + timeout 1430ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold while curr_timestamp <= expired_timestamp: 1440ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold new_event = get_next_event() 1450ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if new_event: 1460ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('event received after %s seconds', 1470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold curr_timestamp - base_timestamp) 1480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return expected_event.verify(new_event) 1490ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1500ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # No new events, sleep for one second only (so we don't miss 1510ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # events at the end of the allotted timeout). 1520ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold time.sleep(1) 1530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold curr_timestamp = time.time() 1540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.error('timeout expired') 1560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return False 1570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldclass UpdateEventLogVerifier(object): 1600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Verifies update event chains on a devserver update log.""" 16103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold def __init__(self, event_log_url, url_request_timeout=None): 1620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._event_log_url = event_log_url 16303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold self._url_request_timeout = url_request_timeout 1640ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._event_log = [] 1650ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._num_consumed_events = 0 1660ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1670ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1680ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def verify_expected_event_chain(self, expected_event_chain): 1690ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Verify a given event chain.""" 1700ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return expected_event_chain.verify(self._get_next_log_event) 1710ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1720ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1730ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _get_next_log_event(self): 1740ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Returns the next event in an event log. 1750ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1760ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold Uses the URL handed to it during initialization to obtain the host log 1770ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold from a devserver. If new events are encountered, the first of them is 1780ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold consumed and returned. 1790ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1800ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @return The next new event in the host log, as reported by devserver; 18103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold None if no such event was found or an error occurred. 1820ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1830ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 1840ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # (Re)read event log from devserver, if necessary. 1850ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if len(self._event_log) <= self._num_consumed_events: 18603901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold try: 18703901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold if self._url_request_timeout: 18803901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold conn = urllib2.urlopen(self._event_log_url, 18903901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold timeout=self._url_request_timeout) 19003901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold else: 19103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold conn = urllib2.urlopen(self._event_log_url) 19203901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold except urllib2.URLError, e: 19303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold logging.warning('urlopen failed: %s', e) 19403901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold return None 19503901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 1960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_log_resp = conn.read() 1970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold conn.close() 1980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._event_log = json.loads(event_log_resp) 1990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 20003901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold # Return next new event, if one is found. 2010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if len(self._event_log) > self._num_consumed_events: 2020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold new_event = self._event_log[self._num_consumed_events] 2030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._num_consumed_events += 1 2040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('consumed new event: %s', new_event) 2050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return new_event 2060ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2080ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldclass OmahaDevserver(object): 2090ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Spawns a test-private devserver instance.""" 2100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_FOR_DEVSERVER_STARTED_SECONDS = 15 21103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold _WAIT_SLEEP_INTERVAL = 1 2120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2130ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 21403901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold def __init__(self, omaha_host, devserver_dir, dut_ip_addr, 21503901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold update_payload_lorry_url): 2160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Starts a private devserver instance, operating at Omaha capacity. 2170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param omaha_host: host address where the devserver is spawned. 21903901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold @param devserver_dir: path to the devserver source directory 2200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param dut_ip_addr: the IP address of the client DUT, used for deriving 2210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold a unique port number. 2220ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param update_payload_lorry_url: URL to provision for update requests. 2230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @raise error.TestError when things go wrong. 2250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 2270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # First, obtain the target URL base / image strings. 2280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not update_payload_lorry_url: 2290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestError('missing update payload url') 2300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold update_payload_url_base, update_payload_path, _ = self._split_url( 2310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold update_payload_lorry_url) 2320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Second, compute a unique port for the DUT update checks to use, based 2340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # on the DUT's IP address. 2350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._omaha_port = self._get_unique_port(dut_ip_addr) 2360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.debug('dut ip addr: %s => omaha/devserver port: %d', 2370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold dut_ip_addr, self._omaha_port) 2380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Invoke the Omaha/devserver. 2400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold cmdlist = [ 24103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold './devserver.py', 2420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold '--archive_dir=static/', 2430ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold '--payload=%s' % update_payload_path, 2440ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold '--port=%d' % self._omaha_port, 2450ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold '--remote_payload', 2460ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold '--urlbase=%s' % update_payload_url_base, 2470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold '--max_updates=1', 2480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold '--host_log', 2490ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ] 25003901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold logging.info('launching omaha/devserver on %s (%s): %s', 25103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold omaha_host, devserver_dir, ' '.join(cmdlist)) 2520ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # TODO(garnold) invoke omaha/devserver remotely! The host needs to be 2530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # either globally known to all DUTs, or inferrable based on the DUT's 2540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # own IP address, or otherwise provisioned to it. 2550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold is_omaha_devserver_local = ( 2560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold omaha_host in ['localhost', socket.gethostname()]) 2570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not is_omaha_devserver_local: 2580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestError( 2590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'remote omaha/devserver invocation unsupported yet') 2600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # We are using subprocess directly (as opposed to existing util 2610ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # wrappers like utils.run() or utils.BgJob) because we need to be able 2620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # to terminate the subprocess once the test finishes. 26303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold devserver_output_namedtemp = tempfile.NamedTemporaryFile() 26403901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold self._devserver = subprocess.Popen( 26503901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold cmdlist, stdin=subprocess.PIPE, 26603901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold stdout=devserver_output_namedtemp.file, 26703901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold stderr=subprocess.STDOUT, cwd=devserver_dir or None) 2680ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold timeout = self._WAIT_FOR_DEVSERVER_STARTED_SECONDS 26903901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold devserver_output_log = [] 27003901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold with open(devserver_output_namedtemp.name, 'r') as devserver_output: 27103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold while timeout > 0 and self._devserver.returncode is None: 27203901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold time.sleep(self._WAIT_SLEEP_INTERVAL) 27303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold timeout -= self._WAIT_SLEEP_INTERVAL 27403901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold devserver_started = False 27503901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold while not devserver_started: 27603901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold line = devserver_output.readline() 27703901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold if not line: 27803901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold break 27903901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold log_line = '[devserver]' + line.rstrip('\n') 28003901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold logging.debug(log_line) 28103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold devserver_output_log.append(log_line) 28203901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold devserver_started = 'Bus STARTED' in line 28303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold else: 2840ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold break 2850ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else: 28603901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold raise error.TestError( 28703901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 'omaha/devserver not running, error log:\n%s' % 28803901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold '\n'.join(devserver_output_log)) 2890ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2900ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._omaha_host = site_utils.externalize_host(omaha_host) 2910ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2920ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2930ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @staticmethod 2940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _split_url(url): 2950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Splits a URL into the URL base, path and file name.""" 2960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold split_url = urlparse.urlsplit(url) 2970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold url_base = urlparse.urlunsplit( 2980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold [split_url.scheme, split_url.netloc, '', '', '']) 2990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold url_path = url_file = '' 3000ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if split_url.path: 3010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold url_path, url_file = split_url.path.rsplit('/', 1) 3020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return url_base, url_path.lstrip('/'), url_file 3030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @staticmethod 3060ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _get_unique_port(dut_ip_addr): 3070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Compute a unique IP port based on the DUT's IP address. 3080ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3090ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold We need a mapping that can be mirrored by a DUT running an official 3100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold image, based only on the DUT's own state. Here, we simply take the two 3110ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold least significant bytes in the DUT's IPv4 address and bitwise-OR them 3120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold with 0xc0000, resulting in a 16-bit IP port within the 3130ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold private/unallocated range. Using the least significant bytes of the IP 3140ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold address guarantees (sort of) that we'll have a unique mapping in a 3150ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold small lab setting. 3160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 3180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ip_addr_bytes = [int(byte_str) for byte_str in dut_ip_addr.split('.')] 3190ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return (((ip_addr_bytes[2] << 8) | ip_addr_bytes[3] | 0x8000) & ~0x4000) 3200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3220ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def get_netloc(self): 3230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not self._devserver: 3240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestError('no running omaha/devserver') 3250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return '%s:%s' % (self._omaha_host, self._omaha_port) 3260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def kill(self): 3290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Kill private devserver, wait for it to die.""" 3300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not self._devserver: 3310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestError('no running omaha/devserver') 3320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('killing omaha/devserver') 3330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._devserver.terminate() 3340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._devserver.communicate() 3350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._devserver = None 3360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldclass autoupdate_EndToEndTest(test.test): 3390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Complete update test between two Chrome OS releases. 3400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold Performs an end-to-end test of updating a ChromeOS device from one version 3420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold to another. This script requires a running (possibly remote) servod 3430ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold instance connected to an actual servo board, which controls the DUT. It 3440ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold also assumes that a corresponding target (update) image was staged for 3450ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold download on the central Lorry/devserver. 3460ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold The test performs the following steps: 3480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3490ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 0. Stages the source image and target update payload on the central 3500ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold Lorry/devserver. 3510ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 1. Spawns a private Omaha/devserver instance, configured to return the 3520ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold target (update) image URL in response for an update check. 3530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 2. Connects to servod. 3540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold a. Resets the DUT to a known initial state. 3550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold b. Installs a source image on the DUT via recovery. 3560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3. Reboots the DUT with the new image. 3570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4. Triggers an update check at the DUT. 3580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5. Watches as the DUT obtains an update and applies it. 3590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6. Repeats 3-5, ensuring that the next update check shows the new image 3600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold version. 3610ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 3630ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold version = 1 3640ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3650ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Timeout periods, given in seconds. 3660ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_AFTER_SHUTDOWN_SECONDS = 10 3670ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_AFTER_UPDATE_SECONDS = 20 3680ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_FOR_USB_INSTALL_SECONDS = 4 * 60 3690ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_FOR_MP_RECOVERY_SECONDS = 8 * 60 3700ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_FOR_INITIAL_UPDATE_CHECK_SECONDS = 12 * 60 3710ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_FOR_DOWNLOAD_STARTED_SECONDS = 2 * 60 3720ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_FOR_DOWNLOAD_COMPLETED_SECONDS = 5 * 60 3730ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_FOR_UPDATE_COMPLETED_SECONDS = 4 * 60 3740ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _WAIT_FOR_UPDATE_CHECK_AFTER_REBOOT_SECONDS = 15 * 60 37503901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold _DEVSERVER_HOSTLOG_REQUEST_TIMEOUT_SECONDS = 30 3760ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3770ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Omaha event types/results, from update_engine/omaha_request_action.h 3780ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_TYPE_UNKNOWN = 0 3790ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_TYPE_DOWNLOAD_COMPLETE = 1 3800ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_TYPE_INSTALL_COMPLETE = 2 3810ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_TYPE_UPDATE_COMPLETE = 3 3820ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_TYPE_DOWNLOAD_STARTED = 13 3830ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_TYPE_DOWNLOAD_FINISHED = 14 3840ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_RESULT_ERROR = 0 3850ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_RESULT_SUCCESS = 1 3860ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_RESULT_SUCCESS_REBOOT = 2 3870ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold EVENT_RESULT_UPDATE_DEFERRED = 9 3880ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3890ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3900ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _servo_dut_power_up(self, host, is_dev_mode): 3910ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Powers up the DUT, optionally simulating a Ctrl-D key press.""" 3920ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold host.servo.power_short_press() 3930ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_dev_mode: 3940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold host.servo.pass_devmode() 3950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 3970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _servo_dut_reboot(self, host, is_dev_mode, is_using_test_images, 3980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold is_disable_usb_hub=False): 3990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Reboots a DUT. 4000ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param host: a host object 4020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param is_dev_mode: whether or not the DUT is in dev mode 4030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param is_using_test_images: whether or not a test image should be 4040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold assumed 4050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param is_disable_usb_hub: disabled the servo USB hub in between power 4060ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold off/on cycles; this is useful when (for example) a USB booted 4070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold device need not see the attached USB key after the reboot. 4080ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4090ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @raise error.TestFail if DUT fails to reboot. 4100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4110ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 4120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('rebooting dut') 4130ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold host.servo.power_long_press() 4140ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _wait(self._WAIT_AFTER_SHUTDOWN_SECONDS, 'after shutdown') 4150ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_disable_usb_hub: 4160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold host.servo.disable_usb_hub() 4170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._servo_dut_power_up(host, is_dev_mode) 4180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_using_test_images: 4190ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not host.wait_up(timeout=host.BOOT_TIMEOUT): 4200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestFail( 4210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'dut %s failed to boot after %d secs' % 4220ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (host.ip, host.BOOT_TIMEOUT)) 4230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else: 4240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # TODO(garnold) chromium-os:33766: implement waiting for MP-signed 4250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # images; ideas include waiting for a ping reply, or using a GPIO 4260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # signal. 4270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold pass 4280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _install_mp_image(self, host, lorry_image_url, is_dev_mode): 4310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Installs an MP-signed recovery image on a DUT. 4320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param host: a host object 4340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param lorry_image_url: URL of the image on a Lorry/devserver 4350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param is_dev_nmode: whether or not the DUT is in dev mode 4360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 4380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Flash DUT with source image version, using recovery. 4390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('installing source mp-signed image via recovery: %s', 4400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_image_url) 4410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold host.servo.install_recovery_image( 4420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_image_url, 4430ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold wait_timeout=self._WAIT_FOR_MP_RECOVERY_SECONDS) 4440ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4450ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Reboot the DUT after installation. 4460ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._servo_dut_reboot(host, is_dev_mode, False, 4470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold is_disable_usb_hub=True) 4480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4490ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4500ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _install_test_image(self, host, lorry_image_url, is_dev_mode): 4510ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Installs a test image on a DUT, booted via recovery. 4520ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param host: a host object 4540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param lorry_image_url: URL of the image on a Lorry/devserver 4550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param is_dev_nmode: whether or not the DUT is in dev mode 4560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @raise error.TestFail if DUT cannot boot the test image from USB; 4580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold AutotestHostRunError if failed to run the install command on the 4590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold DUT. 4600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4610ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 4620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('installing source test image via recovery: %s', 4630ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_image_url) 4640ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold host.servo.install_recovery_image(lorry_image_url) 4650ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('waiting for image to boot') 4660ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not host.wait_up(timeout=host.USB_BOOT_TIMEOUT): 4670ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestFail( 4680ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'dut %s boot from usb timed out after %d secs' % 4690ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (host, host.USB_BOOT_TIMEOUT)) 4700ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('installing new image onto ssd') 4710ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold try: 4720ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold cmd_result = host.run( 4730ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'chromeos-install --yes', 4740ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold timeout=self._WAIT_FOR_USB_INSTALL_SECONDS, 4750ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold stdout_tee=None, stderr_tee=None) 4760ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold except AutotestHostRunError, e: 4770ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Dump stdout (with stderr) to the error log. 4780ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.error('command failed, stderr:\n' + cmd_result.stderr) 4790ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise 4800ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4810ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Reboot the DUT after installation. 4820ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._servo_dut_reboot(host, is_dev_mode, True, 4830ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold is_disable_usb_hub=True) 4840ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4850ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4860ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def _trigger_test_update(self, host, omaha_netloc): 4870ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Trigger an update check on a test image. 4880ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4890ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold Uses update_engine_client via SSH. This is an async call, hence a very 4900ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold short timeout. 4910ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4920ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param host: a host object 4930ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param omaha_netloc: the network location of the Omaha/devserver 4940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (http://host:port) 4950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @raise RootFSUpdateError if anything went wrong. 4970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 4980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 4990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold omaha_update_url = urlparse.urlunsplit( 5000ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ['http', omaha_netloc, '/update', '', '']) 5010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold updater = autoupdater.ChromiumOSUpdater(omaha_update_url, host=host) 5020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold updater.trigger_update() 5030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def stage_image(self, lorry_devserver, image_uri, board, release, branch, 5060ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold is_using_test_images): 5070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Stage a Chrome OS image on Lorry/devserver. 5080ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5090ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @return URL of the staged image on the server. 5100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5110ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @raise error.TestError if there's a problem with staging. 5120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5130ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 5140ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold staged_url = None 5150ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_using_test_images: 5160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # For this call, we just need the URL path up to the image.zip file 5170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # (exclusive). 5180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold image_uri_path = urlparse.urlsplit(image_uri).path.partition( 5190ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'image.zip')[0].strip('/') 5200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold try: 5210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_devserver.trigger_test_image_download(image_uri_path) 5220ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold staged_url = lorry_devserver.get_test_image_url( 5230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold board, release, branch) 5240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold except dev_server.DevServerException, e: 5250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestError( 52603901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 'failed to stage source test image: %s' % e) 5270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else: 5280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # TODO(garnold) chromium-os:33766: implement staging of MP-signed 5290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # images. 5300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold pass 5310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not staged_url: 5330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestError('staged source test image url missing') 5340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return staged_url 5350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def stage_payload(self, lorry_devserver, payload_uri, board, release, 5380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold branch, is_using_test_images, is_delta, is_nton): 5390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Stage an update target payload on Lorry/devserver. 5400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @return URL of the staged payload on the server. 5420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5430ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @raise error.TestError if there's a problem with staging. 5440ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5450ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 5460ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold staged_url = None 5470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_using_test_images: 5480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # For this call, we'll need the URL path without the payload file 5490ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # name. 5500ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold payload_uri_path = urlparse.urlsplit(payload_uri).path.rsplit( 5510ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold '/', 1)[0].strip('/') 5520ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold try: 5530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_devserver.trigger_download(payload_uri_path) 5540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_delta: 5550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold staged_url = lorry_devserver.get_delta_payload_url( 5560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'nton' if is_nton else 'mton', 5570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold board, release, branch) 5580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else: 5590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold staged_url = lorry_devserver.get_full_payload_url( 5600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold board, release, branch) 5610ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold except dev_server.DevServerException, e: 5620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestError( 56303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 'failed to stage target test payload: %s' % e) 5640ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else: 5650ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # TODO(garnold) chromium-os:33766: implement staging of MP-signed 5660ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # images. 5670ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold pass 5680ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5690ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not staged_url: 5700ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestError('staged target test payload url missing') 5710ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold return staged_url 5720ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5730ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5740ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold def run_once(self, host, test_conf): 5750ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """Performs a complete auto update test. 5760ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5770ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param host: a host object representing the DUT 5780ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @param test_conf: a dictionary containing test configuration values 5790ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5800ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold @raise error.TestError if anything went wrong with setting up the test; 5810ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold error.TestFail if any part of the test has failed. 5820ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 5830ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold """ 5840ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold is_using_test_images = test_conf.get('image_type') != 'mp' 5850ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold omaha_host = test_conf.get('omaha_host') 5860ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 587d70e0c8bd47ea824c5a84c5565a46690d64e4aa6Gilad Arnold # Check whether the DUT is in dev mode. 588d70e0c8bd47ea824c5a84c5565a46690d64e4aa6Gilad Arnold is_dev_mode = host.servo.get('dev_mode') == 'on' 589d70e0c8bd47ea824c5a84c5565a46690d64e4aa6Gilad Arnold 5900ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Stage source images and update payloads on lorry/devserver. We use 5910ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # the payload URI as argument for the lab's devserver load-balancing 5920ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # mechanism. 5930ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_devserver = dev_server.ImageServer.resolve( 5940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['target_payload_uri']) 5950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('staging image and payload on lorry/devserver (%s)', 5960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_devserver.url()) 5970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['source_image_lorry_url'] = self.stage_image( 5980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_devserver, test_conf['source_image_uri'], 5990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['board'], test_conf['source_release'], 6000ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['source_branch'], is_using_test_images) 6010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['target_payload_lorry_url'] = self.stage_payload( 6020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold lorry_devserver, test_conf['target_payload_uri'], 6030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['board'], test_conf['target_release'], 6040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['target_branch'], is_using_test_images, 6050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['update_type'] == 'delta', 6060ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf['target_release'] == test_conf['source_release']) 6070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 60803901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold # Get the devserver directory from autotest config. 60903901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold devserver_dir = global_config.global_config.get_config_value( 61003901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 'CROS', 'devserver_dir', default=None) 61103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold if devserver_dir is None: 61203901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold raise error.TestError( 61303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 'path to devserver source tree not provided; please define ' 61403901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 'devserver_dir under [CROS] in your shadow_config.ini') 61503901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold 6160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Launch Omaha/devserver. 6170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold try: 6180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._omaha_devserver = OmahaDevserver( 61903901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold omaha_host, devserver_dir, host.ip, 6200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold test_conf.get('target_payload_lorry_url')) 6210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold except error.TestError, e: 62203901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold logging.error('failed to start omaha/devserver: %s', e) 6230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise 6240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold try: 6260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Install source image (test vs MP). 6270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_using_test_images: 6280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._install_test_image( 6290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold host, test_conf['source_image_lorry_url'], 6300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold is_dev_mode) 6310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else: 6320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._install_mp_image(test_conf['source_image_lorry_url'], 6330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold is_dev_mode) 6340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold omaha_netloc = self._omaha_devserver.get_netloc() 6360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Trigger an update (test vs MP). 6380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_using_test_images: 6390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._trigger_test_update(host, omaha_netloc) 6400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else: 6410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # TODO(garnold) chromium-os:33766: use GPIOs to trigger an 6420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # update. 6430ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold pass 6440ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6450ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Track update progress. 6460ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold omaha_hostlog_url = urlparse.urlunsplit( 6470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ['http', omaha_netloc, '/api/hostlog', 'ip=' + host.ip, '']) 6480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold logging.info('polling update progress from omaha/devserver: %s', 6490ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold omaha_hostlog_url) 65003901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold log_verifier = UpdateEventLogVerifier( 65103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold omaha_hostlog_url, 65203901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold self._DEVSERVER_HOSTLOG_REQUEST_TIMEOUT_SECONDS) 6530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Verify chain of events in a successful update process. 6550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold chain = ExpectedUpdateEventChain( 6560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (self._WAIT_FOR_INITIAL_UPDATE_CHECK_SECONDS, 6570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ExpectedUpdateEvent( 6580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold version=test_conf['source_release'])), 6590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (self._WAIT_FOR_DOWNLOAD_STARTED_SECONDS, 6600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ExpectedUpdateEvent( 6610ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_type=self.EVENT_TYPE_DOWNLOAD_STARTED, 6620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_result=self.EVENT_RESULT_SUCCESS, 6630ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold version=test_conf['source_release'])), 6640ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (self._WAIT_FOR_DOWNLOAD_COMPLETED_SECONDS, 6650ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ExpectedUpdateEvent( 6660ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_type=self.EVENT_TYPE_DOWNLOAD_FINISHED, 6670ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_result=self.EVENT_RESULT_SUCCESS, 6680ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold version=test_conf['source_release'])), 6690ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (self._WAIT_FOR_UPDATE_COMPLETED_SECONDS, 6700ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ExpectedUpdateEvent( 6710ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_type=self.EVENT_TYPE_UPDATE_COMPLETE, 6720ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_result=self.EVENT_RESULT_SUCCESS, 6730ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold version=test_conf['source_release']))) 6740ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not log_verifier.verify_expected_event_chain(chain): 6750ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestFail( 6760ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'could not verify that update was successful') 6770ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6780ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Wait after an update completion (safety margin). 6790ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold _wait(self._WAIT_AFTER_UPDATE_SECONDS, 'after update completion') 6800ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6810ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Reboot the DUT after the update. 6820ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._servo_dut_reboot(host, is_dev_mode, is_using_test_images) 6830ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6840ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Trigger a second update check (again, test vs MP). 6850ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if is_using_test_images: 6860ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._trigger_test_update(host, omaha_netloc) 6870ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold else: 6880ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # TODO(garnold) chromium-os:33766: use GPIOs to trigger an 6890ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # update. 6900ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold pass 6910ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 6920ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Observe post-reboot update check, which should indicate that the 6930ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # image version has been updated. Note that the previous version 6940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # is currently not reported by AU, as one may have expected; had it 6950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # been reported, we should have included 6960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # expect_previous_version=test_conf['source_release'] as well. 6970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold chain = ExpectedUpdateEventChain( 6980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold (self._WAIT_FOR_UPDATE_CHECK_AFTER_REBOOT_SECONDS, 6990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold ExpectedUpdateEvent( 7000ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_type=self.EVENT_TYPE_UPDATE_COMPLETE, 7010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold event_result=self.EVENT_RESULT_SUCCESS_REBOOT, 7020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold version=test_conf['target_release']))) 7030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold if not log_verifier.verify_expected_event_chain(chain): 7040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestFail('could not verify that machine rebooted ' 7050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 'after update') 7060ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 7070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold except error.TestFail: 7080ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise 7090ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold except Exception, e: 7100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold # Convert any other exception into a test failure. 7110ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold raise error.TestFail(str(e)) 7120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 7130ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold finally: 7140ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold self._omaha_devserver.kill() 7150ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold 716