blob: 4d87e8f35e9d9ef0786863ad61ab902ca3001414 [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
Achuith Bhandarkar2b725fd2018-03-27 15:10:43 -070033from chromite.scripts import cros_vm
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080034
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
60 or gmerge go to search for binary packages. By default this will
61 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
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080070 self.vm = 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
Prathmesh Prabhueea4fed2017-10-27 10:25:03 -070078 if self.vm:
79 self.vm.Stop()
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080080 self.vm = None
81 osutils.RmDir(self.tmpdir, ignore_missing=True)
Chris Sosada9632e2013-03-04 12:28:06 -080082 self.tmpdir = None
83 except Exception:
Prathmesh Prabhueea4fed2017-10-27 10:25:03 -070084 logging.exception('Received error during cleanup')
Chris Sosada9632e2013-03-04 12:28:06 -080085
Chris Sosab8c2af52013-07-03 10:45:39 -070086 def _WipeDevInstall(self):
87 """Wipes the devinstall state."""
Chris Sosada9632e2013-03-04 12:28:06 -080088 r_mount_point = os.path.join(self.tmpdir, 'm')
89 s_mount_point = os.path.join(self.tmpdir, 's')
Chris Sosab8c2af52013-07-03 10:45:39 -070090 dev_image_path = os.path.join(s_mount_point, 'dev_image')
Chris Sosada9632e2013-03-04 12:28:06 -080091 mount_helper.MountImage(self.working_image_path,
92 r_mount_point, s_mount_point, read_only=False,
93 safe=True)
Chris Sosab8c2af52013-07-03 10:45:39 -070094 try:
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -080095 osutils.RmDir(dev_image_path, sudo=True)
Chris Sosab8c2af52013-07-03 10:45:39 -070096 finally:
97 mount_helper.UnmountImage(r_mount_point, s_mount_point)
Chris Sosada9632e2013-03-04 12:28:06 -080098
Chris Sosada9632e2013-03-04 12:28:06 -080099 def PrepareTest(self):
100 """Pre-test modification to the image and env to setup test."""
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800101 logging.info('Setting up the image %s for vm testing.', self.image_path)
102 vm_path = vm.CreateVMImage(image=self.image_path, board=self.board,
Yu-Ju Hongb933bfc2014-02-19 11:15:34 -0800103 updatable=False)
Chris Sosada9632e2013-03-04 12:28:06 -0800104
105 logging.info('Making copy of the vm image %s to manipulate.', vm_path)
David James45b55dd2013-04-24 09:16:40 -0700106 self.working_image_path = os.path.join(self.tmpdir,
107 os.path.basename(vm_path))
Chris Sosada9632e2013-03-04 12:28:06 -0800108 shutil.copyfile(vm_path, self.working_image_path)
109 logging.debug('Copy of vm image stored at %s.', self.working_image_path)
110
Chris Sosab8c2af52013-07-03 10:45:39 -0700111 logging.info('Wiping /usr/local/bin from the image.')
112 self._WipeDevInstall()
Chris Sosada9632e2013-03-04 12:28:06 -0800113
Achuith Bhandarkar2b725fd2018-03-27 15:10:43 -0700114 vm_opts = cros_vm.VM.GetParser().parse_args(
115 ['--image-path', self.working_image_path, '--vm-dir',
116 os.path.join(self.tmpdir, 'cros_vm')])
117 self.vm = cros_vm.VM(vm_opts)
118 logging.info('Starting the vm on port %d.', self.vm.ssh_port)
Yu-Ju Honga1dfbf52014-01-31 10:23:03 -0800119 self.vm.Start()
120
Chris Sosada9632e2013-03-04 12:28:06 -0800121 if not self.binhost:
122 logging.info('Starting the devserver.')
Chris Sosaa404a382013-08-22 11:28:38 -0700123 self.devserver = dev_server_wrapper.DevServerWrapper()
124 self.devserver.Start()
Nicolas Norvezc5a20ae2018-03-02 14:49:54 -0800125 self.binhost = self.devserver.GetDevServerURL(
126 ip=self.HOST_IP_ADDRESS, port=self.devserver.port,
Chris Sosac9447962013-03-12 10:12:29 -0700127 sub_dir='static/pkgroot/%s/packages' % self.board)
Chris Sosada9632e2013-03-04 12:28:06 -0800128
129 logging.info('Using binhost %s', self.binhost)
130
131 def TestDevInstall(self):
132 """Tests that we can run dev-install and have python work afterwards."""
133 try:
134 logging.info('Running dev install in the vm.')
Achuith Bhandarkar2b725fd2018-03-27 15:10:43 -0700135 self.vm.RemoteCommand(
Chris Sosada9632e2013-03-04 12:28:06 -0800136 ['bash', '-l', '-c',
137 '"/usr/bin/dev_install --yes --binhost %s"' % self.binhost])
138
139 logging.info('Verifying that python works on the image.')
Achuith Bhandarkar2b725fd2018-03-27 15:10:43 -0700140 self.vm.RemoteCommand(['sudo', '-u', 'chronos', '--', 'python', '-c',
141 '"print \'hello world\'"'])
Yu-Ju Hong5ed02452014-01-30 09:05:00 -0800142 except (cros_build_lib.RunCommandError,
143 remote_access.SSHConnectionError) as e:
Chris Sosada9632e2013-03-04 12:28:06 -0800144 self.devserver.PrintLog()
145 logging.error('dev-install test failed. See devserver log above for more '
146 'details.')
147 raise TestError('dev-install test failed with: %s' % str(e))
148
Chris Sosada9632e2013-03-04 12:28:06 -0800149 def TestGmerge(self):
150 """Evaluates whether the test passed or failed."""
Chris Sosa928085e2013-03-08 17:25:30 -0800151 logging.info('Testing that gmerge works on the image after dev install.')
Chris Sosada9632e2013-03-04 12:28:06 -0800152 try:
Achuith Bhandarkar2b725fd2018-03-27 15:10:43 -0700153 self.vm.RemoteCommand(
Chris Sosac9447962013-03-12 10:12:29 -0700154 ['gmerge', 'gmerge', '--accept_stable', '--usepkg',
Nicolas Norvezc5a20ae2018-03-02 14:49:54 -0800155 '--devserver_url', self.devserver.GetDevServerURL(
156 ip=self.HOST_IP_ADDRESS, port=self.devserver.port),
Chris Sosac9447962013-03-12 10:12:29 -0700157 '--board', self.board])
Yu-Ju Hong5ed02452014-01-30 09:05:00 -0800158 except (cros_build_lib.RunCommandError,
159 remote_access.SSHConnectionError) as e:
Chris Sosada9632e2013-03-04 12:28:06 -0800160 logging.error('gmerge test failed. See log for details')
161 raise TestError('gmerge test failed with: %s' % str(e))
162
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700163 def Run(self):
164 try:
165 self.PrepareTest()
166 self.TestDevInstall()
167 self.TestGmerge()
168 logging.info('All tests passed.')
169 finally:
170 self.Cleanup()
171
Chris Sosada9632e2013-03-04 12:28:06 -0800172
173def main():
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700174 parser = argparse.ArgumentParser(description=__doc__)
175 parser.add_argument('--binhost', metavar='URL',
176 help='binhost override. By default, starts up a devserver'
177 ' and uses it as the binhost.')
178 parser.add_argument('board', nargs=1, help='board to use.')
179 parser.add_argument('image_path', nargs=1, help='path to test|vm image.')
180 parser.add_argument('-v', '--verbose', default=False, action='store_true',
181 help='Print out added debugging information')
182 options = parser.parse_args()
Chris Sosada9632e2013-03-04 12:28:06 -0800183
184 test_helper.SetupCommonLoggingFormat(verbose=options.verbose)
Achuith Bhandarkarb6bc33d2018-03-28 00:16:47 -0700185 DevModeTest(os.path.realpath(options.image_path[0]), options.board[0],
186 options.binhost).Run()
Chris Sosada9632e2013-03-04 12:28:06 -0800187
188if __name__ == '__main__':
189 main()