Home | History | Annotate | Download | only in network_WiFi_UpdateRouter
      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 
      5 import collections
      6 import logging
      7 
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.client.common_lib import global_config
     10 from autotest_lib.client.common_lib import utils
     11 from autotest_lib.client.common_lib.cros import dev_server
     12 from autotest_lib.client.common_lib.cros.network import ping_runner
     13 from autotest_lib.server import hosts
     14 from autotest_lib.server import site_linux_router
     15 from autotest_lib.server import test
     16 from autotest_lib.server.cros import autoupdater
     17 from autotest_lib.server.cros import dnsname_mangler
     18 from 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.
     25 StableVersion = collections.namedtuple('StableVersion',
     26                                        ['builder_version', 'release_version'])
     27 
     28 class 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