1# Copyright (c) 2014 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 collections 6import logging 7 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.common_lib import global_config 10from autotest_lib.client.common_lib import utils 11from autotest_lib.client.common_lib.cros import dev_server 12from autotest_lib.client.common_lib.cros.network import ping_runner 13from autotest_lib.server import hosts 14from autotest_lib.server import site_linux_router 15from autotest_lib.server import test 16from autotest_lib.server.cros import autoupdater 17from autotest_lib.server.cros import dnsname_mangler 18from autotest_lib.server.cros.network import wifi_test_context_manager 19 20 21# Stable versions come from the builders. 22# The builder version is used to build the URL of the corresponding image 23# in Google Storage. 24# The image version is a line from /etc/lsb-release in the corresponding image. 25StableVersion = collections.namedtuple('StableVersion', 26 ['builder_version', 'release_version']) 27 28class network_WiFi_UpdateRouter(test.test): 29 """Updates a router to the most recent stable version. 30 31 This is not a test per se, since it does not test client behavior. However 32 it is advantageous to write this as a test so that we can schedule it to 33 run periodically via the same infrastructure we use to run tests. 34 35 Note that this test is very much patterned on provision_AutoUpdate. 36 37 """ 38 version = 1 39 40 STABLE_VERSIONS = { 41 'stumpy': StableVersion('trybot-stumpy-test-ap/R47-7424.0.0-b10', 42 '7424.0.2015_09_03_1514'), 43 'panther': StableVersion('trybot-panther-test-ap/R47-7424.0.0-b10', 44 '7424.0.2015_09_03_1532'), 45 'whirlwind': StableVersion('trybot-whirlwind-test-ap-tryjob/' 46 'R65-10323.83.0-c40829', 47 '10323.83.2018_04_30_1605'), 48 'gale': StableVersion('gale-test-ap-tryjob/R69-10895.21.0-b2832790', 49 '10895.21.2018_08_10_1013'), 50 } 51 52 53 def get_release_version(self, host): 54 result = host.run('cat /etc/lsb-release') 55 for line in result.stdout.splitlines(): 56 if line.startswith('CHROMEOS_RELEASE_VERSION='): 57 return line.split('=', 1)[1] 58 59 60 def get_update_url(self, ds_url, image): 61 CONFIG = global_config.global_config 62 IMAGE_URL_PATTERN = CONFIG.get_config_value( 63 'CROS', 'image_url_pattern', type=str) 64 return IMAGE_URL_PATTERN % (ds_url, image) 65 66 67 def warmup(self, raw_cmdline_args): 68 """Possibly parse the router hostname from the commandline. 69 70 @param raw_cmdline_args raw input from autotest. 71 72 """ 73 cmdline_args = utils.args_to_dict(raw_cmdline_args) 74 logging.info('Running wifi test with commandline arguments: %r', 75 cmdline_args) 76 self._router_hostname_from_cmdline = cmdline_args.get( 77 wifi_test_context_manager.WiFiTestContextManager. \ 78 CMDLINE_ROUTER_ADDR) 79 80 81 def run_once(self, host, is_pcap=False): 82 """Update router / packet capture associated with host. 83 84 @param host DUT connected to AP/Pcap that needs update 85 86 """ 87 if is_pcap: 88 device_hostname = dnsname_mangler.get_pcap_addr( 89 client_hostname=host.hostname) 90 else: 91 device_hostname = site_linux_router.build_router_hostname( 92 client_hostname=host.hostname, 93 router_hostname=self._router_hostname_from_cmdline) 94 95 ping_helper = ping_runner.PingRunner() 96 if not ping_helper.simple_ping(device_hostname): 97 # Pcap devices aren't always present. Just claim Not Applicable if 98 # we couldn't find it. 99 e = error.TestNAError if is_pcap else error.TestError 100 raise e('%s not found / is down.' % device_hostname) 101 102 # Use CrosHost for all router/pcap hosts and avoid host detection. 103 # Host detection would use JetstreamHost for Whirlwind routers. 104 # JetstreamHost assumes ap-daemons are running. 105 # Testbed routers run the testbed-ap profile with no ap-daemons. 106 # TODO(ecgh): crbug.com/757075 Fix testbed-ap JetstreamHost detection. 107 device_host = hosts.create_host(device_hostname, 108 host_class=hosts.CrosHost, 109 allow_failure=True) 110 self.update_device(device_host) 111 112 113 def update_device(self, device_host): 114 """Update router and pcap associated with host. 115 116 @param device_host: router / pcap host object 117 @param device_board: router / pcap board name 118 119 """ 120 device_board = device_host.get_board().split(':', 1)[1] 121 desired = self.STABLE_VERSIONS.get(device_board, None) 122 if desired is None: 123 raise error.TestFail('No stable version found for %s with board=%s.' 124 % (device_host.hostname, device_board)) 125 126 logging.info('Checking whether %s is at the latest stable version: %s', 127 device_host.hostname, desired.release_version) 128 current_release_version = self.get_release_version(device_host) 129 if desired.release_version == current_release_version: 130 raise error.TestNAError('%s is already at latest version %s.' % 131 (device_host.hostname, 132 desired.release_version)) 133 134 logging.info('Updating %s to image %s from %s', 135 device_host.hostname, desired.release_version, 136 current_release_version) 137 logging.info('Staging artifacts.') 138 try: 139 ds = dev_server.ImageServer.resolve(desired.builder_version, 140 device_host.hostname) 141 ds.stage_artifacts(desired.builder_version, 142 ['full_payload', 'stateful']) 143 except dev_server.DevServerException as e: 144 logging.error(e) 145 raise error.TestFail(str(e)) 146 147 url = self.get_update_url(ds.url(), desired.builder_version) 148 autoupdater.ChromiumOSUpdater(url, host=device_host).run_update() 149