• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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