1# Copyright (c) 2012 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 logging
6from autotest_lib.client.bin import sysinfo
7from autotest_lib.client.common_lib import error, utils
8from autotest_lib.client.cros import constants
9from autotest_lib.server import host_attributes
10
11AUTHOR = "Chromium OS"
12NAME = "autoupdate_EndToEndTest"
13TIME = "MEDIUM"
14TEST_CATEGORY = "Functional"
15TEST_CLASS = "platform"
16TEST_TYPE = "server"
17JOB_RETRIES = 1
18BUG_TEMPLATE = {
19    'cc': ['chromeos-installer-alerts@google.com'],
20    'components': ['Internals>Installer'],
21}
22
23# Skip provision special task for AU tests.
24DEPENDENCIES = "skip_provision"
25
26# Disable server-side packaging support for this test.
27# This control file is used as the template for paygen_au_canary suite, which
28# creates the control files during paygen. Therefore, autotest server package
29# does not have these test control files for paygen_au_canary suite.
30REQUIRE_SSP = False
31
32DOC = """
33This is an end-to-end update test of Chrome OS releases. Given a test
34configuration, it will perform an end-to-end test of a Chrome OS update
35payload. A test configuration can be given as command-line arguments (see
36below) or instantiated inline as local varibles.
37
38To invoke this test locally:
39
40  test_that <DUT-IPADDR> autoupdate_EndToEndTest --args="<ARGLIST>"
41
42where ARGLIST is a whitespace separated list of the following key=value pairs.
43Values pertaining to the test case include:
44
45  name=TAG           name tag for the test (e.g. 'nmo', 'npo' or 'fsi')
46  update_type=full|delta  type of update being applied, either 'full' or 'delta'
47  source_release=REL      source image release version (e.g. 2672.0.0)
48  target_release=REL      target image release version (e.g. 2673.0.0)
49  source_payload_uri=URI  URI of the source full payload. None means don't
50                          install a source image (assume it's preinstalled).
51  source_archive_uri=URI  (optional) URI of where the artifacts for the source
52                          image (e.g.  stateful update) are located. If not
53                          provided, the test will attempt using the same
54                          location as source_payload_uri.  This is required for
55                          any test where the location of the full (source)
56                          payload is separate from that of its build artifacts
57                          (e.g. it is in gs://chromeos-releases/).
58  target_payload_uri=URI  URI of the target payload
59  target_archive_uri=URI  (optional) URI of where the artifacts for the target
60                          image (e.g. stateful update) are located. If not
61                          provided, the test will attempt using the test job's
62                          repo ID (if present), otherwise default to the same
63                          location as target_payload_uri.  Normally, this is
64                          only needed for local (non-AFE) runs where the
65                          payload location is separate from that of the build
66                          artifacts (e.g. it is in gs://chromeos-releases).
67
68
69To run locally:
701. Find the Google Storage URIs of the images you want to use during the test.
71    You can choose payloads from this bucket: gs://chromeos-releases/
72
73    Sample from gs://chromeos-releases:
74      gs://chromeos-releases/dev-channel/samus/9433.0.0/payloads/chromeos_9433.0
75      .0_samus_dev-channel_full_test.bin-1e2db02f3bd9d9ebe74dc81fc7038919
76
772. Choose the devserver you want to use.
78    This test uses a devserver to control the autoupdate. You can point to a
79    devserver on your workstation to aid debugging or you can choose to use a
80    devserver in the lab.
81
82    To start your own devserver, run this (outside the chroot):
83    src/platform/dev/devserver.py --port=8084
84
85    For a devserver running on your workstation use 127.0.0.1 as the hostname.
86    For a devserver running in the lab the port is usually 8082.
87
88    Add this line to src/third_party/autotest/files/shadow_config.ini in the [CROS] section:
89    dev_server = http://<hostname>:<port>
90
91    The devserver needs to be able to reach the DUT you choose in the next
92    section. Look up the dev_server_common.ini.erb (in repo chromeos_admin) for
93    dev_server & restricted_subnet fields to pick a devserver in the same
94    subnet with the testing DUT.
95
963. Choose the DUT you want to use for the test.
97   You can use a DUT on your desk connected to corp or you can lock a DUT
98   in the lab for use in the test.
99
1004. Setup ssh correctly.
101    You will need to setup a number of ssh keys and then copy them to
102    your chroot so that you can ssh into a devserver from there.
103
104    Run ssh-keygen to generate your id_rsa and id_rsa.pub files into ~/.ssh/
105
106    Download the testing_rsa ssh keys from here:
107    https://chromium.googlesource.com/chromiumos/chromite/+/master/ssh_keys
108    Save both to ~/.ssh
109    chmod 600 ~/.ssh/testing_rsa* (otherwise permissions are too loose and
110    will be ignored)
111
112    Add these lines to your ~/.ssh/config
113    Host *.cros
114      User root
115      IdentityFile /usr/local/google/home/<your ldap here>/.ssh/testing_rsa
116
117    You should now be able to ssh into DUTs in the lab without a password.
118
119    To ssh into lab devservers you need to download the devserver key from:
120    https://valentine.corp.google.com/#/show/1519247593151324
121
122    Save the file to ~/.ssh/devserver and run chmod 600 on it.
123    Then add these lines to your ~/.ssh/config
124
125    Host <devserver hostname>
126      User chromeos-test
127      IdentityFile %d/.ssh/devserver
128      UserKnownHostsFile /dev/null
129      StrictHostKeyChecking no
130      Protocol 2
131      PreferredAuthentications publickey
132
133    Check that you can now ssh into a lab devserver without a password.
134
135    Finally and most importantly, copy the ssh files to your chroot's .ssh
136    folder so you can ssh from there.
137
1385. Make sure you have your gsutil permissions (your .boto file).
139    Your .boto file must be available inside the chroot.
140    cp ~/.boto chroot/home/<user>/
141
142    Make sure the gsutil command is available outside the chroot (note:
143    the gsutil package in Ubuntu is not what you're looking for.)
144
1456. Kick off the test with test_that from a chroot. e.g
146      test_that <IP OF DUT> autoupdate_EndToEndTest
147      --args="target_release=10906.0.0
148      source_payload_uri='gs://chromeos-releases/canary-channel/nami/10760.0
149      .0/payloads/chromeos_10760.0.0_nami_canary-channel_full_test
150      .bin-cee25d306d164f7514e26efb34f8f57d'
151      target_payload_uri='gs://chromeos-releases/canary-channel/nami/10906.0
152      .0/payloads/chromeos_10760.0.0-10906.0.0_nami_canary-channel_delta_test
153      .bin-98f9af8d919605fc3ee1391eaa79c7e6'
154      source_release=10760.0.0 update_type=delta"
155
1567. Unlock any DUTs you locked for debugging when you are done.
157
158"""
159
160TEST_CONF_KEYS = (
161    'name', 'update_type', 'source_release', 'target_release',
162    'source_payload_uri', 'source_archive_uri', 'target_payload_uri',
163    'target_archive_uri')
164
165
166args_dict = utils.args_to_dict(args)
167
168# Create test configuration based on command-line arguments (higher precedence,
169# for test_that invocation) and local variables (lower precedence,
170# for Autotest front-end invocation).
171test_conf = {}
172for key in TEST_CONF_KEYS:
173    test_conf[key] = args_dict.get(key) or locals().get(key)
174
175
176def run_test(machine):
177    """Execute a test configuration on a given machine."""
178    host = hosts.create_host(machine)
179    # Save preserved log after autoupdate is completed.
180    job.sysinfo.add_logdir(
181        sysinfo.logdir(constants.AUTOUPDATE_PRESERVE_LOG))
182    try:
183        job.run_test(
184                "autoupdate_EndToEndTest",
185                tag='%s_%s' % (test_conf['name'], test_conf['update_type']),
186                host=host, test_conf=test_conf)
187    except Exception as e:
188        if not issubclass(type(e), error.TestBaseException):
189            error_msg = 'Received test error: %s' % e
190            logging.error(error_msg)
191            raise error.TestError(error_msg)
192
193        raise
194
195
196# Invoke parallel tests.
197parallel_simple(run_test, machines)
198