# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import collections
import logging

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import global_config
from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.cros import dev_server
from autotest_lib.client.common_lib.cros.network import ping_runner
from autotest_lib.server import hosts
from autotest_lib.server import site_linux_router
from autotest_lib.server import test
from autotest_lib.server.cros import dnsname_mangler
from autotest_lib.server.cros import provisioner
from autotest_lib.server.cros.network import wifi_test_context_manager


# Stable versions come from the builders.
# The builder version is used to build the URL of the corresponding image
# in Google Storage.
# The image version is a line from /etc/lsb-release in the corresponding image.
StableVersion = collections.namedtuple('StableVersion',
                                       ['builder_version', 'release_version'])

class network_WiFi_UpdateRouter(test.test):
    """Updates a router to the most recent stable version.

    This is not a test per se, since it does not test client behavior.  However
    it is advantageous to write this as a test so that we can schedule it to
    run periodically via the same infrastructure we use to run tests.

    Note that this test is very much patterned on provision_QuickProvision.

    """
    version = 1

    STABLE_VERSIONS = {
        ## crbug.com/1098024: these are left here as documentation of what the
        # last stable version is, but the current updater code does not support
        # them.
        'whirlwind': StableVersion('whirlwind-test-ap-tryjob/R85-13310.60.0-b4641849',
                                   '13310.60.2020_08_25_0212'),
        'gale': StableVersion('gale-test-ap-tryjob/R85-13310.54.0-b4637444',
                              '13310.54.2020_08_19_1536'),
    }

    # List of files to remove.
    FILES_TO_REMOVE = ['/var/spool/crash/*', '/tmp/*',
                       '/var/lib/metrics/uma-events']


    def get_release_version(self, host):
        result = host.run('cat /etc/lsb-release')
        for line in result.stdout.splitlines():
            if line.startswith('CHROMEOS_RELEASE_VERSION='):
                return line.split('=', 1)[1]


    def get_update_url(self, ds_url, image):
        CONFIG = global_config.global_config
        IMAGE_URL_PATTERN = CONFIG.get_config_value(
                'CROS', 'image_url_pattern', type=str)
        return IMAGE_URL_PATTERN % (ds_url, image)


    def warmup(self, raw_cmdline_args):
        """Possibly parse the router hostname from the commandline.

        @param raw_cmdline_args raw input from autotest.

        """
        cmdline_args = utils.args_to_dict(raw_cmdline_args)
        logging.info('Running wifi test with commandline arguments: %r',
                     cmdline_args)
        self._router_hostname_from_cmdline = cmdline_args.get(
                wifi_test_context_manager.WiFiTestContextManager. \
                        CMDLINE_ROUTER_ADDR)


    def freeup_disk_space(self, device_host):
        """Remove files to free up disk space.

        @param device_host: router / pcap host object

        """
        for path in self.FILES_TO_REMOVE:
            device_host.run('rm -rf %s' % path, ignore_status=True)


    def run_once(self, host, is_pcap=False):
        """Update router / packet capture associated with host.

        @param host DUT connected to AP/Pcap that needs update

        """
        if is_pcap:
            device_hostname = dnsname_mangler.get_pcap_addr(
                    client_hostname=host.hostname)
        else:
            device_hostname = site_linux_router.build_router_hostname(
                client_hostname=host.hostname,
                router_hostname=self._router_hostname_from_cmdline)

        ping_helper = ping_runner.PingRunner()
        if not ping_helper.simple_ping(device_hostname):
            # Pcap devices aren't always present. Just claim Not Applicable if
            # we couldn't find it.
            e = error.TestNAError if is_pcap else error.TestError
            raise e('%s not found / is down.' % device_hostname)

        # Use CrosHost for all router/pcap hosts and avoid host detection.
        # Host detection would use JetstreamHost for Whirlwind routers.
        # JetstreamHost assumes ap-daemons are running.
        # Testbed routers run the testbed-ap profile with no ap-daemons.
        # TODO(ecgh): crbug.com/757075 Fix testbed-ap JetstreamHost detection.
        device_host = hosts.create_host(device_hostname,
                                        host_class=hosts.CrosHost,
                                        allow_failure=True)
        # Remove un-wanted files to freeup diskspace before starting update.
        self.freeup_disk_space(device_host)
        self.update_device(device_host)


    def update_device(self, device_host):
        """Update router and pcap associated with host.

        @param device_host: router / pcap host object
        @param device_board: router / pcap board name

        """
        device_board = device_host.get_board().split(':', 1)[1]
        desired = self.STABLE_VERSIONS.get(device_board, None)
        if desired is None:
            raise error.TestFail('No stable version found for %s with board=%s.'
                                 % (device_host.hostname, device_board))

        logging.info('Checking whether %s is at the latest stable version: %s',
                     device_host.hostname, desired.release_version)
        current_release_version = self.get_release_version(device_host)
        if desired.release_version == current_release_version:
            raise error.TestNAError('%s is already at latest version %s.' %
                                    (device_host.hostname,
                                     desired.release_version))

        logging.info('Updating %s to image %s from %s',
                     device_host.hostname, desired.release_version,
                     current_release_version)
        try:
            ds = dev_server.ImageServer.resolve(desired.builder_version,
                                                device_host.hostname)
        except dev_server.DevServerException as e:
            logging.error(e)
            raise error.TestFail(str(e))

        url = self.get_update_url(ds.url(), desired.builder_version)
        provisioner.ChromiumOSProvisioner(url,
                                          host=device_host).run_provision()
