blob: 69c6aedf685033d47f8b39f1bffe82dd9f8be53d [file] [log] [blame]
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -07001#!/usr/bin/env python2
Achuith Bhandarkar78010f72019-01-03 17:21:52 -08002# -*- coding: utf-8 -*-
Chris Sosada9632e2013-03-04 12:28:06 -08003# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
Mike Frysingerdb50f4f2019-02-24 19:52:59 -05007"""Integration test to test the basic functionality of dev-install.
Chris Sosada9632e2013-03-04 12:28:06 -08008
9This module contains a test that runs some sanity integration tests against
10a VM. First it starts a VM test image and turns it into a base image by wiping
11all of the stateful partition. Once done, runs dev_install to restore the
Mike Frysingerdb50f4f2019-02-24 19:52:59 -050012stateful partition.
Chris Sosada9632e2013-03-04 12:28:06 -080013"""
14
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -070015from __future__ import print_function
16
17import argparse
Chris Sosada9632e2013-03-04 12:28:06 -080018import os
19import shutil
Chris Sosada9632e2013-03-04 12:28:06 -080020import sys
21import tempfile
22
23import constants
24sys.path.append(constants.SOURCE_ROOT)
25sys.path.append(constants.CROS_PLATFORM_ROOT)
26
Achuith Bhandarkar78010f72019-01-03 17:21:52 -080027from chromite.lib import constants as chromite_constants
Chris Sosada9632e2013-03-04 12:28:06 -080028from chromite.lib import cros_build_lib
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -070029from chromite.lib import cros_logging as logging
Yu-Ju Hong29111982013-12-20 15:04:41 -080030from chromite.lib import dev_server_wrapper
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080031from chromite.lib import osutils
Chris Sosa928085e2013-03-08 17:25:30 -080032from chromite.lib import remote_access
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080033from chromite.lib import vm
34
Chris Sosada9632e2013-03-04 12:28:06 -080035from crostestutils.lib import mount_helper
36from crostestutils.lib import test_helper
37
38
Chris Sosada9632e2013-03-04 12:28:06 -080039class TestError(Exception):
40 """Raised on any error during testing. It being raised is a test failure."""
41
42
43class DevModeTest(object):
44 """Wrapper for dev mode tests."""
Nicolas Norvezc5a20ae2018-03-02 14:49:54 -080045
46 # qemu hardcodes 10.0.2.2 as the host from the guest's point of view
47 # https://wiki.qemu.org/Documentation/Networking#User_Networking_.28SLIRP.29
48 # When the host's eth0 IP address is also 10.0.2.*, and the guest tries to
49 # access it, the requests will be handled by qemu and never be seen by the
50 # host. Instead, let the guest always connect to 10.0.2.2.
51 HOST_IP_ADDRESS = '10.0.2.2'
52
Chris Sosada9632e2013-03-04 12:28:06 -080053 def __init__(self, image_path, board, binhost):
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080054 """Initializes DevModeTest.
55
Chris Sosada9632e2013-03-04 12:28:06 -080056 Args:
57 image_path: Filesystem path to the image to test.
58 board: Board of the image under test.
59 binhost: Binhost override. Binhost as defined here is where dev-install
Mike Frysingerdb50f4f2019-02-24 19:52:59 -050060 go to search for binary packages. By default this will
Chris Sosada9632e2013-03-04 12:28:06 -080061 be set to the devserver url of the host running this script.
62 If no override i.e. the default is ok, set to None.
63 """
64 self.image_path = image_path
65 self.board = board
66 self.binhost = binhost
Chris Sosada9632e2013-03-04 12:28:06 -080067 self.tmpdir = tempfile.mkdtemp('DevModeTest')
Chris Sosada9632e2013-03-04 12:28:06 -080068 self.working_image_path = None
69 self.devserver = None
Achuith Bhandarkar518c8e22018-06-08 19:42:04 +000070 self.device = None
Achuith Bhandarkar78010f72019-01-03 17:21:52 -080071 self.port = None
Chris Sosada9632e2013-03-04 12:28:06 -080072
73 def Cleanup(self):
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080074 """Cleans up any state at the end of the test."""
Chris Sosada9632e2013-03-04 12:28:06 -080075 try:
Chris Sosada9632e2013-03-04 12:28:06 -080076 if self.devserver:
77 self.devserver.Stop()
Chris Sosada9632e2013-03-04 12:28:06 -080078 self.devserver = None
Achuith Bhandarkar518c8e22018-06-08 19:42:04 +000079 if self.device:
80 self.device.Cleanup()
81 self.device = None
Achuith Bhandarkar78010f72019-01-03 17:21:52 -080082 if self.port:
83 cros_build_lib.RunCommand(['./cros_vm', '--stop',
84 '--ssh-port=%d' % self.port],
85 cwd=chromite_constants.CHROMITE_BIN_DIR,
86 error_code_ok=True)
87 self.port = None
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080088 osutils.RmDir(self.tmpdir, ignore_missing=True)
Chris Sosada9632e2013-03-04 12:28:06 -080089 self.tmpdir = None
90 except Exception:
Prathmesh Prabhueea4fed2017-10-27 10:25:03 -070091 logging.exception('Received error during cleanup')
Chris Sosada9632e2013-03-04 12:28:06 -080092
Chris Sosab8c2af52013-07-03 10:45:39 -070093 def _WipeDevInstall(self):
94 """Wipes the devinstall state."""
Achuith Bhandarkar85928c42019-04-18 17:02:27 -070095 logging.info('Wiping /usr/local/bin from the image.')
Chris Sosada9632e2013-03-04 12:28:06 -080096 r_mount_point = os.path.join(self.tmpdir, 'm')
97 s_mount_point = os.path.join(self.tmpdir, 's')
Chris Sosab8c2af52013-07-03 10:45:39 -070098 dev_image_path = os.path.join(s_mount_point, 'dev_image')
Chris Sosada9632e2013-03-04 12:28:06 -080099 mount_helper.MountImage(self.working_image_path,
100 r_mount_point, s_mount_point, read_only=False,
101 safe=True)
Chris Sosab8c2af52013-07-03 10:45:39 -0700102 try:
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800103 osutils.RmDir(dev_image_path, sudo=True)
Chris Sosab8c2af52013-07-03 10:45:39 -0700104 finally:
105 mount_helper.UnmountImage(r_mount_point, s_mount_point)
Chris Sosada9632e2013-03-04 12:28:06 -0800106
Chris Sosada9632e2013-03-04 12:28:06 -0800107 def PrepareTest(self):
108 """Pre-test modification to the image and env to setup test."""
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800109 logging.info('Setting up the image %s for vm testing.', self.image_path)
110 vm_path = vm.CreateVMImage(image=self.image_path, board=self.board,
Yu-Ju Hongb933bfc2014-02-19 11:15:34 -0800111 updatable=False)
Chris Sosada9632e2013-03-04 12:28:06 -0800112
113 logging.info('Making copy of the vm image %s to manipulate.', vm_path)
David James45b55dd2013-04-24 09:16:40 -0700114 self.working_image_path = os.path.join(self.tmpdir,
115 os.path.basename(vm_path))
Chris Sosada9632e2013-03-04 12:28:06 -0800116 shutil.copyfile(vm_path, self.working_image_path)
117 logging.debug('Copy of vm image stored at %s.', self.working_image_path)
118
Chris Sosab8c2af52013-07-03 10:45:39 -0700119 self._WipeDevInstall()
Chris Sosada9632e2013-03-04 12:28:06 -0800120
Achuith Bhandarkar78010f72019-01-03 17:21:52 -0800121 self.port = remote_access.GetUnusedPort()
122 logging.info('Starting the vm on port %d.', self.port)
123 vm_cmd = ['./cros_vm', '--ssh-port=%d' % self.port,
124 '--image-path=%s' % self.working_image_path, '--start']
125 cros_build_lib.RunCommand(vm_cmd, cwd=chromite_constants.CHROMITE_BIN_DIR)
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800126
Achuith Bhandarkar518c8e22018-06-08 19:42:04 +0000127 self.device = remote_access.ChromiumOSDevice(
Achuith Bhandarkar78010f72019-01-03 17:21:52 -0800128 remote_access.LOCALHOST, port=self.port, base_dir=self.tmpdir)
Achuith Bhandarkar85928c42019-04-18 17:02:27 -0700129 if not self.device.MountRootfsReadWrite():
130 raise TestError('Failed to make rootfs writeable')
Achuith Bhandarkar518c8e22018-06-08 19:42:04 +0000131
Chris Sosada9632e2013-03-04 12:28:06 -0800132 if not self.binhost:
133 logging.info('Starting the devserver.')
Chris Sosaa404a382013-08-22 11:28:38 -0700134 self.devserver = dev_server_wrapper.DevServerWrapper()
135 self.devserver.Start()
Nicolas Norvezc5a20ae2018-03-02 14:49:54 -0800136 self.binhost = self.devserver.GetDevServerURL(
137 ip=self.HOST_IP_ADDRESS, port=self.devserver.port,
Chris Sosac9447962013-03-12 10:12:29 -0700138 sub_dir='static/pkgroot/%s/packages' % self.board)
Chris Sosada9632e2013-03-04 12:28:06 -0800139
140 logging.info('Using binhost %s', self.binhost)
141
142 def TestDevInstall(self):
143 """Tests that we can run dev-install and have python work afterwards."""
144 try:
145 logging.info('Running dev install in the vm.')
Achuith Bhandarkar518c8e22018-06-08 19:42:04 +0000146 self.device.RunCommand(
Chris Sosada9632e2013-03-04 12:28:06 -0800147 ['bash', '-l', '-c',
148 '"/usr/bin/dev_install --yes --binhost %s"' % self.binhost])
149
150 logging.info('Verifying that python works on the image.')
Achuith Bhandarkar85928c42019-04-18 17:02:27 -0700151 # crbug.com/955147: /usr/local/bin/python symlink doesn't exist.
152 # Use python-wrapper instead.
153 self.device.RunCommand(['sudo', '-u', 'chronos', '--', 'python-wrapper',
154 '-c', '"print \'hello world\'"'])
Yu-Ju Hong5ed02452014-01-30 09:05:00 -0800155 except (cros_build_lib.RunCommandError,
156 remote_access.SSHConnectionError) as e:
Chris Sosada9632e2013-03-04 12:28:06 -0800157 self.devserver.PrintLog()
158 logging.error('dev-install test failed. See devserver log above for more '
159 'details.')
160 raise TestError('dev-install test failed with: %s' % str(e))
161
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700162 def Run(self):
163 try:
164 self.PrepareTest()
165 self.TestDevInstall()
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700166 logging.info('All tests passed.')
167 finally:
168 self.Cleanup()
169
Chris Sosada9632e2013-03-04 12:28:06 -0800170
171def main():
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700172 parser = argparse.ArgumentParser(description=__doc__)
173 parser.add_argument('--binhost', metavar='URL',
174 help='binhost override. By default, starts up a devserver'
175 ' and uses it as the binhost.')
176 parser.add_argument('board', nargs=1, help='board to use.')
177 parser.add_argument('image_path', nargs=1, help='path to test|vm image.')
178 parser.add_argument('-v', '--verbose', default=False, action='store_true',
179 help='Print out added debugging information')
180 options = parser.parse_args()
Chris Sosada9632e2013-03-04 12:28:06 -0800181
182 test_helper.SetupCommonLoggingFormat(verbose=options.verbose)
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700183 DevModeTest(os.path.realpath(options.image_path[0]), options.board[0],
184 options.binhost).Run()
Chris Sosada9632e2013-03-04 12:28:06 -0800185
186if __name__ == '__main__':
187 main()