blob: 8465433ae72fac028b9fe5a6d71f74a8c3397333 [file] [log] [blame]
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +08001#!/usr/bin/python -Bu
2#
3# Copyright (c) 2014 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"""Factory toolkit installer.
8
9The factory toolkit is a self-extracting shellball containing factory test
10related files and this installer. This installer is invoked when the toolkit
11is deployed and is responsible for installing files.
12"""
13
14
15import argparse
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +080016from contextlib import contextmanager
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080017import os
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080018import sys
Jon Salz4f3ade52014-02-20 17:55:09 +080019import tempfile
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080020
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +080021import factory_common # pylint: disable=W0611
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080022from cros.factory.test import factory
Vic Yang196d5242014-08-05 13:51:35 +080023from cros.factory.test import utils
Jon Salz25590302014-07-11 16:07:20 +080024from cros.factory.tools import install_symlinks
Rong Chang6d65fad2014-08-22 16:00:12 +080025from cros.factory.utils import file_utils
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +080026from cros.factory.utils.process_utils import Spawn
Hung-Te Lincdc2a042014-08-27 13:05:16 +080027from cros.factory.utils.sys_utils import MountPartition
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080028
29
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +080030INSTALLER_PATH = 'usr/local/factory/py/toolkit/installer.py'
Rong Chang6d65fad2014-08-22 16:00:12 +080031MAKESELF_SHELL = '/bin/sh'
32TOOLKIT_NAME = 'install_factory_toolkit.run'
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +080033
Jon Salz4f3ade52014-02-20 17:55:09 +080034# Short and sweet help header for the executable generated by makeself.
35HELP_HEADER = """
36Installs the factory toolkit, transforming a test image into a factory test
37image. You can:
38
39- Install the factory toolkit on a CrOS device that is running a test
40 image. To do this, copy install_factory_toolkit.run to the device and
41 run it. The factory tests will then come up on the next boot.
42
43 rsync -a install_factory_toolkit.run crosdevice:/tmp
44 ssh crosdevice '/tmp/install_factory_toolkit.run && sync && reboot'
45
46- Modify a test image, turning it into a factory test image. When you
47 use the image on a device, the factory tests will come up.
48
49 install_factory_toolkit.run chromiumos_test_image.bin
50"""
51
52HELP_HEADER_ADVANCED = """
53- (advanced) Modify a mounted stateful partition, turning it into a factory
54 test image. This is equivalent to the previous command:
55
56 mount_partition -rw chromiumos_test_image.bin 1 /mnt/stateful
57 install_factory_toolkit.run /mnt/stateful
58 umount /mnt/stateful
59
60- (advanced) Unpack the factory toolkit, modify a file, and then repack it.
61
62 # Unpack but don't actually install
63 install_factory_toolkit.run --target /tmp/toolkit --noexec
64 # Edit some files in /tmp/toolkit
65 emacs /tmp/toolkit/whatever
66 # Repack
67 install_factory_toolkit.run -- --repack /tmp/toolkit \\
68 --pack-into /path/to/new/install_factory_toolkit.run
69"""
70
71# The makeself-generated header comes next. This is a little confusing,
72# so explain.
73HELP_HEADER_MAKESELF = """
74For complete usage information and advanced operations, run
75"install_factory_toolkit.run -- --help" (note the extra "--").
76
77Following is the help message from makeself, which was used to create
78this self-extracting archive.
79
80-----
81"""
82
Vic Yang196d5242014-08-05 13:51:35 +080083# The method to determine whether running on Chrome OS device or not.
84# Override this for unit testing.
85_in_cros_device = utils.in_cros_device
86
Vic Yangdb1e20e2014-10-05 12:10:33 +080087SERVER_FILE_MASK = [
88 # Exclude Umpire server but keep Umpire client
89 '--include', 'py/umpire/__init__.*',
90 '--include', 'py/umpire/common.*',
91 '--include', 'py/umpire/client',
92 '--include', 'py/umpire/client/**',
93 '--exclude', 'py/umpire/**',
94
95 # Lumberjack is only used on Umpire server
96 '--exclude', 'py/lumberjack'
97]
98
Jon Salz4f3ade52014-02-20 17:55:09 +080099
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800100class FactoryToolkitInstaller():
101 """Factory toolkit installer.
102
103 Args:
104 src: Source path containing usr/ and var/.
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800105 dest: Installation destination path. Set this to the mount point of the
106 stateful partition if patching a test image.
107 no_enable: True to not install the tag file.
108 system_root: The path to the root of the file system. This must be left
109 as its default value except for unit testing.
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800110 """
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800111
Jon Salzb7e44262014-05-07 15:53:37 +0800112 # Whether to sudo when rsyncing; set to False for testing.
113 _sudo = True
114
Peter Ammon948b7172014-07-15 12:43:06 -0700115 def __init__(self, src, dest, no_enable, enable_presenter,
Vic Yang7039f422014-07-07 15:38:13 -0700116 enable_device, system_root='/'):
Jon Salz4f3ade52014-02-20 17:55:09 +0800117 self._src = src
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800118 self._system_root = system_root
119 if dest == self._system_root:
120 self._usr_local_dest = os.path.join(dest, 'usr', 'local')
121 self._var_dest = os.path.join(dest, 'var')
Jon Salz4f3ade52014-02-20 17:55:09 +0800122
123 # Make sure we're on a CrOS device.
Vic Yang196d5242014-08-05 13:51:35 +0800124 if not _in_cros_device():
Jon Salz4f3ade52014-02-20 17:55:09 +0800125 sys.stderr.write(
Vic Yang196d5242014-08-05 13:51:35 +0800126 "ERROR: You're not on a CrOS device (for more details, please\n"
Hung-Te Lin56b18402015-01-16 14:52:30 +0800127 'check utils.py:in_cros_device), so you must specify a test\n'
128 'image or a mounted stateful partition on which to install the\n'
129 'factory toolkit. Please run\n'
130 '\n'
131 ' install_factory_toolkit.run -- --help\n'
132 '\n'
133 'for help.\n')
Jon Salz4f3ade52014-02-20 17:55:09 +0800134 sys.exit(1)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800135 if os.getuid() != 0:
Jon Salz4f3ade52014-02-20 17:55:09 +0800136 raise Exception('You must be root to install the factory toolkit on a '
137 'CrOS device.')
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800138 else:
139 self._usr_local_dest = os.path.join(dest, 'dev_image')
140 self._var_dest = os.path.join(dest, 'var_overlay')
141 if (not os.path.exists(self._usr_local_dest) or
142 not os.path.exists(self._var_dest)):
143 raise Exception(
144 'The destination path %s is not a stateful partition!' % dest)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800145
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800146 self._dest = dest
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800147 self._usr_local_src = os.path.join(src, 'usr', 'local')
148 self._var_src = os.path.join(src, 'var')
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800149 self._no_enable = no_enable
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800150 self._tag_file = os.path.join(self._usr_local_dest, 'factory', 'enabled')
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800151
Peter Ammon948b7172014-07-15 12:43:06 -0700152 self._enable_presenter = enable_presenter
153 self._presenter_tag_file = os.path.join(self._usr_local_dest, 'factory',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800154 'init', 'run_goofy_presenter')
Vic Yang7039f422014-07-07 15:38:13 -0700155
156 self._enable_device = enable_device
Ricky Liangd7716912014-07-10 11:52:24 +0800157 self._device_tag_file = os.path.join(self._usr_local_dest, 'factory',
158 'init', 'run_goofy_device')
Vic Yang7039f422014-07-07 15:38:13 -0700159
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800160 if (not os.path.exists(self._usr_local_src) or
161 not os.path.exists(self._var_src)):
162 raise Exception(
163 'This installer must be run from within the factory toolkit!')
164
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800165 def WarningMessage(self, target_test_image=None):
Jon Salz4f3ade52014-02-20 17:55:09 +0800166 with open(os.path.join(self._src, 'VERSION')) as f:
167 ret = f.read()
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800168 if target_test_image:
Jon Salz4f3ade52014-02-20 17:55:09 +0800169 ret += (
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800170 '\n'
171 '\n'
Jon Salz4f3ade52014-02-20 17:55:09 +0800172 '*** You are about to patch the factory toolkit into:\n'
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800173 '*** %s\n'
174 '***' % target_test_image)
175 else:
Jon Salz4f3ade52014-02-20 17:55:09 +0800176 ret += (
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800177 '\n'
178 '\n'
Jon Salz4f3ade52014-02-20 17:55:09 +0800179 '*** You are about to install the factory toolkit to:\n'
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800180 '*** %s\n'
181 '***' % self._dest)
182 if self._dest == self._system_root:
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800183 if self._no_enable:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800184 ret += (
185 '\n*** Factory tests will be disabled after this process is '
186 'done, but\n*** you can enable them by creating the factory '
187 'enabled tag:\n*** %s\n***' % self._tag_file)
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800188 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800189 ret += (
190 '\n*** After this process is done, your device will start '
191 'factory\n*** tests on the next reboot.\n***\n*** Factory '
192 'tests can be disabled by deleting the factory enabled\n*** '
193 'tag:\n*** %s\n***' % self._tag_file)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800194 return ret
195
Vic Yang7039f422014-07-07 15:38:13 -0700196 def _SetTagFile(self, name, path, enabled):
197 """Install or remove a tag file."""
198 if enabled:
199 print '*** Installing %s enabled tag...' % name
200 Spawn(['touch', path], sudo=True, log=True, check_call=True)
Ricky Liang8c88a122014-07-11 21:21:22 +0800201 Spawn(['chmod', 'go+r', path], sudo=True, log=True, check_call=True)
Vic Yang7039f422014-07-07 15:38:13 -0700202 else:
203 print '*** Removing %s enabled tag...' % name
204 Spawn(['rm', '-f', path], sudo=True, log=True, check_call=True)
205
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800206 def Install(self):
207 print '*** Installing factory toolkit...'
Jon Salzb7e44262014-05-07 15:53:37 +0800208 for src, dest in ((self._usr_local_src, self._usr_local_dest),
209 (self._var_src, self._var_dest)):
210 # Change the source directory to root, and add group/world read
211 # permissions. This is necessary because when the toolkit was
212 # unpacked, the user may not have been root so the permessions
213 # may be hosed. This is skipped for testing.
Peter Ammon5ac58422014-06-09 14:45:50 -0700214 # --force is necessary to allow goofy directory from prior
215 # toolkit installations to be overwritten by the goofy symlink.
Ricky Liang5e95be22014-07-09 12:52:07 +0800216 try:
217 if self._sudo:
218 Spawn(['chown', '-R', 'root', src],
219 sudo=True, log=True, check_call=True)
220 Spawn(['chmod', '-R', 'go+rX', src],
221 sudo=True, log=True, check_call=True)
222 print '*** %s -> %s' % (src, dest)
Hung-Te Lin56b18402015-01-16 14:52:30 +0800223 Spawn(['rsync', '-a', '--force'] + SERVER_FILE_MASK +
Vic Yangdb1e20e2014-10-05 12:10:33 +0800224 [src + '/', dest], sudo=self._sudo, log=True,
225 check_output=True, cwd=src)
Ricky Liang5e95be22014-07-09 12:52:07 +0800226 finally:
227 # Need to change the source directory back to the original user, or the
228 # script in makeself will fail to remove the temporary source directory.
229 if self._sudo:
230 myuser = os.environ.get('USER')
231 Spawn(['chown', '-R', myuser, src],
232 sudo=True, log=True, check_call=True)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800233
Jon Salz25590302014-07-11 16:07:20 +0800234 print '*** Installing symlinks...'
235 install_symlinks.InstallSymlinks(
236 '../factory/bin',
237 os.path.join(self._usr_local_dest, 'bin'),
238 install_symlinks.MODE_FULL,
239 sudo=self._sudo)
240
241 print '*** Removing factory-mini...'
242 Spawn(['rm', '-rf', os.path.join(self._usr_local_dest, 'factory-mini')],
243 sudo=self._sudo, log=True, check_call=True)
244
Vic Yang7039f422014-07-07 15:38:13 -0700245 self._SetTagFile('factory', self._tag_file, not self._no_enable)
Peter Ammon948b7172014-07-15 12:43:06 -0700246 self._SetTagFile('presenter', self._presenter_tag_file,
247 self._enable_presenter)
Vic Yang7039f422014-07-07 15:38:13 -0700248 self._SetTagFile('device', self._device_tag_file, self._enable_device)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800249
250 print '*** Installation completed.'
251
252
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800253@contextmanager
254def DummyContext(arg):
255 """A context manager that simply yields its argument."""
256 yield arg
257
258
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800259def PrintBuildInfo(src_root):
260 """Print build information."""
261 info_file = os.path.join(src_root, 'REPO_STATUS')
262 if not os.path.exists(info_file):
263 raise OSError('Build info file not found!')
264 with open(info_file, 'r') as f:
265 print f.read()
266
267
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800268def PackFactoryToolkit(src_root, output_path, enable_device, enable_presenter):
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800269 """Packs the files containing this script into a factory toolkit."""
270 with open(os.path.join(src_root, 'VERSION'), 'r') as f:
271 version = f.read().strip()
Jon Salz4f3ade52014-02-20 17:55:09 +0800272 with tempfile.NamedTemporaryFile() as help_header:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800273 help_header.write(version + '\n' + HELP_HEADER + HELP_HEADER_MAKESELF)
Jon Salz4f3ade52014-02-20 17:55:09 +0800274 help_header.flush()
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800275 cmd = [os.path.join(src_root, 'makeself.sh'), '--bzip2', '--nox11',
Jon Salz4f3ade52014-02-20 17:55:09 +0800276 '--help-header', help_header.name,
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800277 src_root, output_path, version, INSTALLER_PATH, '--in-exe']
278 if not enable_device:
279 cmd.append('--no-enable-device')
280 if not enable_presenter:
281 cmd.append('--no-enable-presenter')
282 Spawn(cmd, check_call=True, log=True)
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800283 print ('\n'
Hung-Te Lin56b18402015-01-16 14:52:30 +0800284 ' Factory toolkit generated at %s.\n'
285 '\n'
286 ' To install factory toolkit on a live device running a test image,\n'
287 ' copy this to the device and execute it as root.\n'
288 '\n'
289 ' Alternatively, the factory toolkit can be used to patch a test\n'
290 ' image. For more information, run:\n'
291 ' %s --help\n'
292 '\n' % (output_path, output_path))
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800293
294
Rong Chang6d65fad2014-08-22 16:00:12 +0800295def InitUmpire(exe_path, src_root, target_board):
296 """Inits Umpire server environment."""
297 if exe_path is None:
298 parent_cmdline = open('/proc/%s/cmdline' % os.getppid(),
299 'r').read().rstrip('\0').split('\0')
300
301 if parent_cmdline > 1 and parent_cmdline[0] == MAKESELF_SHELL:
302 # Get parent script name from parent process.
303 exe_path = parent_cmdline[1]
304 else:
305 # Set to default.
306 exe_path = TOOLKIT_NAME
307
308 if not exe_path.startswith('/'):
309 exe_path = os.path.join(os.environ.get('OLDPWD'), exe_path)
310
311 with file_utils.TempDirectory() as nano_bundle:
312 bundle_toolkit_dir = os.path.join(nano_bundle, 'factory_toolkit')
313 os.mkdir(bundle_toolkit_dir)
314 os.symlink(exe_path, os.path.join(bundle_toolkit_dir,
315 os.path.basename(exe_path)))
316 umpire_bin = os.path.join(src_root, 'usr', 'local', 'factory', 'bin',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800317 'umpire')
Rong Chang6d65fad2014-08-22 16:00:12 +0800318 Spawn([umpire_bin, 'init', '--board', target_board, nano_bundle],
319 check_call=True, log=True)
320 print ('\n'
Hung-Te Lin56b18402015-01-16 14:52:30 +0800321 ' Umpire initialized successfully. Upstart service is running:\n'
322 ' umpire BOARD=%(board)s.\n'
323 ' For more information, please check umpire command line:\n'
324 '\n'
325 ' umpire-%(board)s --help (if your id is in umpire group)\n'
326 ' or sudo umpire-%(board)s --help\n'
327 '\n' % {'board': target_board})
Rong Chang6d65fad2014-08-22 16:00:12 +0800328
329
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800330def main():
Jon Salz4f3ade52014-02-20 17:55:09 +0800331 import logging
332 logging.basicConfig(level=logging.INFO)
333
334 # In order to determine which usage message to show, first determine
335 # whether we're in the self-extracting archive. Do this first
336 # because we need it to even parse the arguments.
337 if '--in-exe' in sys.argv:
338 sys.argv = [x for x in sys.argv if x != '--in-exe']
339 in_archive = True
340 else:
341 in_archive = False
342
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800343 parser = argparse.ArgumentParser(
Jon Salz4f3ade52014-02-20 17:55:09 +0800344 description=HELP_HEADER + HELP_HEADER_ADVANCED,
345 usage=('install_factory_toolkit.run -- [options]' if in_archive
346 else None),
347 formatter_class=argparse.RawDescriptionHelpFormatter)
Hung-Te Lin56b18402015-01-16 14:52:30 +0800348 parser.add_argument(
349 'dest', nargs='?', default='/',
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800350 help='A test image or the mount point of the stateful partition. '
351 "If omitted, install to live system, i.e. '/'.")
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800352 parser.add_argument('--no-enable', '-n', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800353 help="Don't enable factory tests after installing")
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800354 parser.add_argument('--yes', '-y', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800355 help="Don't ask for confirmation")
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800356 parser.add_argument('--build-info', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800357 help='Print build information and exit')
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800358 parser.add_argument('--pack-into', metavar='NEW_TOOLKIT',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800359 help='Pack the files into a new factory toolkit')
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800360 parser.add_argument('--repack', metavar='UNPACKED_TOOLKIT',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800361 help='Repack from previously unpacked toolkit')
Vic Yang7039f422014-07-07 15:38:13 -0700362
Peter Ammon948b7172014-07-15 12:43:06 -0700363 parser.add_argument('--enable-presenter', dest='enable_presenter',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800364 action='store_true',
365 help='Run goofy in presenter mode on startup')
Peter Ammon948b7172014-07-15 12:43:06 -0700366 parser.add_argument('--no-enable-presenter', dest='enable_presenter',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800367 action='store_false', help=argparse.SUPPRESS)
Vic Yang423c2722014-09-24 16:05:06 +0800368 parser.set_defaults(enable_presenter=True)
Vic Yang7039f422014-07-07 15:38:13 -0700369
370 parser.add_argument('--enable-device', dest='enable_device',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800371 action='store_true',
372 help='Run goofy in device mode on startup')
Vic Yang7039f422014-07-07 15:38:13 -0700373 parser.add_argument('--no-enable-device', dest='enable_device',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800374 action='store_false', help=argparse.SUPPRESS)
Vic Yang423c2722014-09-24 16:05:06 +0800375 parser.set_defaults(enable_device=True)
376
Rong Chang6d65fad2014-08-22 16:00:12 +0800377 parser.add_argument('--init-umpire-board', dest='umpire_board',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800378 nargs='?', default=None,
379 help='Locally install Umpire server for specific board')
Rong Chang6d65fad2014-08-22 16:00:12 +0800380 parser.add_argument('--exe-path', dest='exe_path',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800381 nargs='?', default=None,
382 help='Current self-extracting archive pathname')
Vic Yang7039f422014-07-07 15:38:13 -0700383
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800384 args = parser.parse_args()
385
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800386 src_root = factory.FACTORY_PATH
387 for _ in xrange(3):
388 src_root = os.path.dirname(src_root)
389
Rong Chang6d65fad2014-08-22 16:00:12 +0800390 # --init-umpire-board creates a nano bundle, then calls umpire command
391 # line utility to install the server code and upstart configurations.
392 if args.umpire_board:
393 InitUmpire(args.exe_path, src_root, args.umpire_board)
394 return
395
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800396 # --pack-into may be called directly so this must be done before changing
397 # working directory to OLDPWD.
398 if args.pack_into and args.repack is None:
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800399 PackFactoryToolkit(src_root, args.pack_into, args.enable_device,
400 args.enable_presenter)
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800401 return
402
Jon Salz4f3ade52014-02-20 17:55:09 +0800403 if not in_archive:
404 # If you're not in the self-extracting archive, you're not allowed to
405 # do anything except the above --pack-into call.
406 parser.error('Not running from install_factory_toolkit.run; '
407 'only --pack-into (without --repack) is allowed')
408
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800409 # Change to original working directory in case the user specifies
410 # a relative path.
411 # TODO: Use USER_PWD instead when makeself is upgraded
412 os.chdir(os.environ['OLDPWD'])
413
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800414 if args.repack:
415 if args.pack_into is None:
416 parser.error('Must specify --pack-into when using --repack.')
417 Spawn([os.path.join(args.repack, INSTALLER_PATH),
418 '--pack-into', args.pack_into], check_call=True, log=True)
419 return
420
421 if args.build_info:
422 PrintBuildInfo(src_root)
423 return
424
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800425 if not os.path.exists(args.dest):
426 parser.error('Destination %s does not exist!' % args.dest)
427
428 patch_test_image = os.path.isfile(args.dest)
429
430 with (MountPartition(args.dest, 1, rw=True) if patch_test_image
431 else DummyContext(args.dest)) as dest:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800432 installer = FactoryToolkitInstaller(
433 src_root, dest, args.no_enable, args.enable_presenter,
434 args.enable_device)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800435
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800436 print installer.WarningMessage(args.dest if patch_test_image else None)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800437
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800438 if not args.yes:
439 answer = raw_input('*** Continue? [y/N] ')
440 if not answer or answer[0] not in 'yY':
441 sys.exit('Aborting.')
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800442
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800443 installer.Install()
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800444
445if __name__ == '__main__':
446 main()