blob: f928087d712d015bfe338e4ebb28528114001bf6 [file] [log] [blame]
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -07001#!/usr/bin/env python2
Chris Sosada9632e2013-03-04 12:28:06 -08002#
3# 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
7"""Integration test to test the basic functionality of dev-install and gmerge.
8
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
12stateful partition and then runs gmerge.
13"""
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
27from chromite.lib import cros_build_lib
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -070028from chromite.lib import cros_logging as logging
Yu-Ju Hong29111982013-12-20 15:04:41 -080029from chromite.lib import dev_server_wrapper
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080030from chromite.lib import osutils
Chris Sosa928085e2013-03-08 17:25:30 -080031from chromite.lib import remote_access
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080032from chromite.lib import vm
33
Chris Sosada9632e2013-03-04 12:28:06 -080034from crostestutils.lib import mount_helper
35from crostestutils.lib import test_helper
36
37
Chris Sosada9632e2013-03-04 12:28:06 -080038class TestError(Exception):
39 """Raised on any error during testing. It being raised is a test failure."""
40
41
42class DevModeTest(object):
43 """Wrapper for dev mode tests."""
Nicolas Norvezc5a20ae2018-03-02 14:49:54 -080044
45 # qemu hardcodes 10.0.2.2 as the host from the guest's point of view
46 # https://wiki.qemu.org/Documentation/Networking#User_Networking_.28SLIRP.29
47 # When the host's eth0 IP address is also 10.0.2.*, and the guest tries to
48 # access it, the requests will be handled by qemu and never be seen by the
49 # host. Instead, let the guest always connect to 10.0.2.2.
50 HOST_IP_ADDRESS = '10.0.2.2'
51
Chris Sosada9632e2013-03-04 12:28:06 -080052 def __init__(self, image_path, board, binhost):
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080053 """Initializes DevModeTest.
54
Chris Sosada9632e2013-03-04 12:28:06 -080055 Args:
56 image_path: Filesystem path to the image to test.
57 board: Board of the image under test.
58 binhost: Binhost override. Binhost as defined here is where dev-install
59 or gmerge go to search for binary packages. By default this will
60 be set to the devserver url of the host running this script.
61 If no override i.e. the default is ok, set to None.
62 """
63 self.image_path = image_path
64 self.board = board
65 self.binhost = binhost
Chris Sosada9632e2013-03-04 12:28:06 -080066 self.tmpdir = tempfile.mkdtemp('DevModeTest')
Chris Sosada9632e2013-03-04 12:28:06 -080067 self.working_image_path = None
68 self.devserver = None
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080069 self.vm = None
70 self.device = None
Chris Sosada9632e2013-03-04 12:28:06 -080071
72 def Cleanup(self):
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080073 """Cleans up any state at the end of the test."""
Chris Sosada9632e2013-03-04 12:28:06 -080074 try:
Chris Sosada9632e2013-03-04 12:28:06 -080075 if self.devserver:
76 self.devserver.Stop()
Chris Sosada9632e2013-03-04 12:28:06 -080077 self.devserver = None
Yu-Ju Hong640d4d02014-02-20 15:52:11 -080078 if self.device:
79 self.device.Cleanup()
Yu-Ju Hong640d4d02014-02-20 15:52:11 -080080 self.device = None
Prathmesh Prabhueea4fed2017-10-27 10:25:03 -070081 if self.vm:
82 self.vm.Stop()
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080083 self.vm = None
84 osutils.RmDir(self.tmpdir, ignore_missing=True)
Chris Sosada9632e2013-03-04 12:28:06 -080085 self.tmpdir = None
86 except Exception:
Prathmesh Prabhueea4fed2017-10-27 10:25:03 -070087 logging.exception('Received error during cleanup')
Chris Sosada9632e2013-03-04 12:28:06 -080088
Chris Sosab8c2af52013-07-03 10:45:39 -070089 def _WipeDevInstall(self):
90 """Wipes the devinstall state."""
Chris Sosada9632e2013-03-04 12:28:06 -080091 r_mount_point = os.path.join(self.tmpdir, 'm')
92 s_mount_point = os.path.join(self.tmpdir, 's')
Chris Sosab8c2af52013-07-03 10:45:39 -070093 dev_image_path = os.path.join(s_mount_point, 'dev_image')
Chris Sosada9632e2013-03-04 12:28:06 -080094 mount_helper.MountImage(self.working_image_path,
95 r_mount_point, s_mount_point, read_only=False,
96 safe=True)
Chris Sosab8c2af52013-07-03 10:45:39 -070097 try:
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080098 osutils.RmDir(dev_image_path, sudo=True)
Chris Sosab8c2af52013-07-03 10:45:39 -070099 finally:
100 mount_helper.UnmountImage(r_mount_point, s_mount_point)
Chris Sosada9632e2013-03-04 12:28:06 -0800101
Chris Sosada9632e2013-03-04 12:28:06 -0800102 def PrepareTest(self):
103 """Pre-test modification to the image and env to setup test."""
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800104 logging.info('Setting up the image %s for vm testing.', self.image_path)
105 vm_path = vm.CreateVMImage(image=self.image_path, board=self.board,
Yu-Ju Hongb933bfc2014-02-19 11:15:34 -0800106 updatable=False)
Chris Sosada9632e2013-03-04 12:28:06 -0800107
108 logging.info('Making copy of the vm image %s to manipulate.', vm_path)
David James45b55dd2013-04-24 09:16:40 -0700109 self.working_image_path = os.path.join(self.tmpdir,
110 os.path.basename(vm_path))
Chris Sosada9632e2013-03-04 12:28:06 -0800111 shutil.copyfile(vm_path, self.working_image_path)
112 logging.debug('Copy of vm image stored at %s.', self.working_image_path)
113
Chris Sosab8c2af52013-07-03 10:45:39 -0700114 logging.info('Wiping /usr/local/bin from the image.')
115 self._WipeDevInstall()
Chris Sosada9632e2013-03-04 12:28:06 -0800116
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800117 self.vm = vm.VMInstance(self.working_image_path, tempdir=self.tmpdir)
118 logging.info('Starting the vm on port %d.', self.vm.port)
119 self.vm.Start()
120
121 self.device = remote_access.ChromiumOSDevice(
Yu-Ju Hong640d4d02014-02-20 15:52:11 -0800122 remote_access.LOCALHOST, port=self.vm.port, base_dir=self.tmpdir)
Chris Sosa068c1e92013-03-17 22:54:20 -0700123
Chris Sosada9632e2013-03-04 12:28:06 -0800124 if not self.binhost:
125 logging.info('Starting the devserver.')
Chris Sosaa404a382013-08-22 11:28:38 -0700126 self.devserver = dev_server_wrapper.DevServerWrapper()
127 self.devserver.Start()
Nicolas Norvezc5a20ae2018-03-02 14:49:54 -0800128 self.binhost = self.devserver.GetDevServerURL(
129 ip=self.HOST_IP_ADDRESS, port=self.devserver.port,
Chris Sosac9447962013-03-12 10:12:29 -0700130 sub_dir='static/pkgroot/%s/packages' % self.board)
Chris Sosada9632e2013-03-04 12:28:06 -0800131
132 logging.info('Using binhost %s', self.binhost)
133
134 def TestDevInstall(self):
135 """Tests that we can run dev-install and have python work afterwards."""
136 try:
137 logging.info('Running dev install in the vm.')
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800138 self.device.RunCommand(
Chris Sosada9632e2013-03-04 12:28:06 -0800139 ['bash', '-l', '-c',
140 '"/usr/bin/dev_install --yes --binhost %s"' % self.binhost])
141
142 logging.info('Verifying that python works on the image.')
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800143 self.device.RunCommand(['sudo', '-u', 'chronos', '--', 'python', '-c',
144 '"print \'hello world\'"'])
Yu-Ju Hong5ed02452014-01-30 09:05:00 -0800145 except (cros_build_lib.RunCommandError,
146 remote_access.SSHConnectionError) as e:
Chris Sosada9632e2013-03-04 12:28:06 -0800147 self.devserver.PrintLog()
148 logging.error('dev-install test failed. See devserver log above for more '
149 'details.')
150 raise TestError('dev-install test failed with: %s' % str(e))
151
Chris Sosada9632e2013-03-04 12:28:06 -0800152 def TestGmerge(self):
153 """Evaluates whether the test passed or failed."""
Chris Sosa928085e2013-03-08 17:25:30 -0800154 logging.info('Testing that gmerge works on the image after dev install.')
Chris Sosada9632e2013-03-04 12:28:06 -0800155 try:
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800156 self.device.RunCommand(
Chris Sosac9447962013-03-12 10:12:29 -0700157 ['gmerge', 'gmerge', '--accept_stable', '--usepkg',
Nicolas Norvezc5a20ae2018-03-02 14:49:54 -0800158 '--devserver_url', self.devserver.GetDevServerURL(
159 ip=self.HOST_IP_ADDRESS, port=self.devserver.port),
Chris Sosac9447962013-03-12 10:12:29 -0700160 '--board', self.board])
Yu-Ju Hong5ed02452014-01-30 09:05:00 -0800161 except (cros_build_lib.RunCommandError,
162 remote_access.SSHConnectionError) as e:
Chris Sosada9632e2013-03-04 12:28:06 -0800163 logging.error('gmerge test failed. See log for details')
164 raise TestError('gmerge test failed with: %s' % str(e))
165
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700166 def Run(self):
167 try:
168 self.PrepareTest()
169 self.TestDevInstall()
170 self.TestGmerge()
171 logging.info('All tests passed.')
172 finally:
173 self.Cleanup()
174
Chris Sosada9632e2013-03-04 12:28:06 -0800175
176def main():
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700177 parser = argparse.ArgumentParser(description=__doc__)
178 parser.add_argument('--binhost', metavar='URL',
179 help='binhost override. By default, starts up a devserver'
180 ' and uses it as the binhost.')
181 parser.add_argument('board', nargs=1, help='board to use.')
182 parser.add_argument('image_path', nargs=1, help='path to test|vm image.')
183 parser.add_argument('-v', '--verbose', default=False, action='store_true',
184 help='Print out added debugging information')
185 options = parser.parse_args()
Chris Sosada9632e2013-03-04 12:28:06 -0800186
187 test_helper.SetupCommonLoggingFormat(verbose=options.verbose)
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700188 DevModeTest(os.path.realpath(options.image_path[0]), options.board[0],
189 options.binhost).Run()
Chris Sosada9632e2013-03-04 12:28:06 -0800190
191if __name__ == '__main__':
192 main()