blob: a371e7ecc66523e2677a771d6079d824c17bfc41 [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
Hung-Te Lin7b596ff2015-01-16 20:19:15 +0800100class FactoryToolkitInstaller(object):
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800101 """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 Yang70fdae92015-02-17 19:21:08 -0800116 enable_device, non_cros=False, 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 Yang70fdae92015-02-17 19:21:08 -0800124 if not non_cros and 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'
Vic Yang70fdae92015-02-17 19:21:08 -0800133 'for help.\n'
134 '\n'
135 'If you want to install the presenter on a non-CrOS host,\n'
136 'please run\n'
137 '\n'
138 ' install_factory_toolkit.run -- \\\n'
139 ' --non-cros --no-enable-device --enable-presenter\n'
140 '\n')
Jon Salz4f3ade52014-02-20 17:55:09 +0800141 sys.exit(1)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800142 if os.getuid() != 0:
Jon Salz4f3ade52014-02-20 17:55:09 +0800143 raise Exception('You must be root to install the factory toolkit on a '
144 'CrOS device.')
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800145 else:
146 self._usr_local_dest = os.path.join(dest, 'dev_image')
147 self._var_dest = os.path.join(dest, 'var_overlay')
148 if (not os.path.exists(self._usr_local_dest) or
149 not os.path.exists(self._var_dest)):
150 raise Exception(
151 'The destination path %s is not a stateful partition!' % dest)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800152
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800153 self._dest = dest
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800154 self._usr_local_src = os.path.join(src, 'usr', 'local')
155 self._var_src = os.path.join(src, 'var')
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800156 self._no_enable = no_enable
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800157 self._tag_file = os.path.join(self._usr_local_dest, 'factory', 'enabled')
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800158
Peter Ammon948b7172014-07-15 12:43:06 -0700159 self._enable_presenter = enable_presenter
160 self._presenter_tag_file = os.path.join(self._usr_local_dest, 'factory',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800161 'init', 'run_goofy_presenter')
Vic Yang7039f422014-07-07 15:38:13 -0700162
163 self._enable_device = enable_device
Ricky Liangd7716912014-07-10 11:52:24 +0800164 self._device_tag_file = os.path.join(self._usr_local_dest, 'factory',
165 'init', 'run_goofy_device')
Vic Yang7039f422014-07-07 15:38:13 -0700166
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800167 if (not os.path.exists(self._usr_local_src) or
168 not os.path.exists(self._var_src)):
169 raise Exception(
170 'This installer must be run from within the factory toolkit!')
171
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800172 def WarningMessage(self, target_test_image=None):
Jon Salz4f3ade52014-02-20 17:55:09 +0800173 with open(os.path.join(self._src, 'VERSION')) as f:
174 ret = f.read()
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800175 if target_test_image:
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 patch the factory toolkit into:\n'
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800180 '*** %s\n'
181 '***' % target_test_image)
182 else:
Jon Salz4f3ade52014-02-20 17:55:09 +0800183 ret += (
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800184 '\n'
185 '\n'
Jon Salz4f3ade52014-02-20 17:55:09 +0800186 '*** You are about to install the factory toolkit to:\n'
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800187 '*** %s\n'
188 '***' % self._dest)
189 if self._dest == self._system_root:
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800190 if self._no_enable:
Hung-Te Lin7b596ff2015-01-16 20:19:15 +0800191 ret += ('\n*** Factory tests will be disabled after this process is '
Hung-Te Lin56b18402015-01-16 14:52:30 +0800192 'done, but\n*** you can enable them by creating the factory '
193 'enabled tag:\n*** %s\n***' % self._tag_file)
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800194 else:
Hung-Te Lin7b596ff2015-01-16 20:19:15 +0800195 ret += ('\n*** After this process is done, your device will start '
Hung-Te Lin56b18402015-01-16 14:52:30 +0800196 'factory\n*** tests on the next reboot.\n***\n*** Factory '
197 'tests can be disabled by deleting the factory enabled\n*** '
198 'tag:\n*** %s\n***' % self._tag_file)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800199 return ret
200
Vic Yang7039f422014-07-07 15:38:13 -0700201 def _SetTagFile(self, name, path, enabled):
202 """Install or remove a tag file."""
203 if enabled:
204 print '*** Installing %s enabled tag...' % name
205 Spawn(['touch', path], sudo=True, log=True, check_call=True)
Ricky Liang8c88a122014-07-11 21:21:22 +0800206 Spawn(['chmod', 'go+r', path], sudo=True, log=True, check_call=True)
Vic Yang7039f422014-07-07 15:38:13 -0700207 else:
208 print '*** Removing %s enabled tag...' % name
209 Spawn(['rm', '-f', path], sudo=True, log=True, check_call=True)
210
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800211 def Install(self):
212 print '*** Installing factory toolkit...'
Jon Salzb7e44262014-05-07 15:53:37 +0800213 for src, dest in ((self._usr_local_src, self._usr_local_dest),
214 (self._var_src, self._var_dest)):
215 # Change the source directory to root, and add group/world read
216 # permissions. This is necessary because when the toolkit was
217 # unpacked, the user may not have been root so the permessions
218 # may be hosed. This is skipped for testing.
Peter Ammon5ac58422014-06-09 14:45:50 -0700219 # --force is necessary to allow goofy directory from prior
220 # toolkit installations to be overwritten by the goofy symlink.
Ricky Liang5e95be22014-07-09 12:52:07 +0800221 try:
222 if self._sudo:
223 Spawn(['chown', '-R', 'root', src],
224 sudo=True, log=True, check_call=True)
225 Spawn(['chmod', '-R', 'go+rX', src],
226 sudo=True, log=True, check_call=True)
227 print '*** %s -> %s' % (src, dest)
Hung-Te Lin56b18402015-01-16 14:52:30 +0800228 Spawn(['rsync', '-a', '--force'] + SERVER_FILE_MASK +
Vic Yangdb1e20e2014-10-05 12:10:33 +0800229 [src + '/', dest], sudo=self._sudo, log=True,
230 check_output=True, cwd=src)
Ricky Liang5e95be22014-07-09 12:52:07 +0800231 finally:
232 # Need to change the source directory back to the original user, or the
233 # script in makeself will fail to remove the temporary source directory.
234 if self._sudo:
235 myuser = os.environ.get('USER')
236 Spawn(['chown', '-R', myuser, src],
237 sudo=True, log=True, check_call=True)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800238
Jon Salz25590302014-07-11 16:07:20 +0800239 print '*** Installing symlinks...'
240 install_symlinks.InstallSymlinks(
241 '../factory/bin',
242 os.path.join(self._usr_local_dest, 'bin'),
243 install_symlinks.MODE_FULL,
244 sudo=self._sudo)
245
246 print '*** Removing factory-mini...'
247 Spawn(['rm', '-rf', os.path.join(self._usr_local_dest, 'factory-mini')],
248 sudo=self._sudo, log=True, check_call=True)
249
Vic Yang7039f422014-07-07 15:38:13 -0700250 self._SetTagFile('factory', self._tag_file, not self._no_enable)
Peter Ammon948b7172014-07-15 12:43:06 -0700251 self._SetTagFile('presenter', self._presenter_tag_file,
252 self._enable_presenter)
Vic Yang7039f422014-07-07 15:38:13 -0700253 self._SetTagFile('device', self._device_tag_file, self._enable_device)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800254
255 print '*** Installation completed.'
256
257
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800258@contextmanager
259def DummyContext(arg):
260 """A context manager that simply yields its argument."""
261 yield arg
262
263
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800264def PrintBuildInfo(src_root):
265 """Print build information."""
266 info_file = os.path.join(src_root, 'REPO_STATUS')
267 if not os.path.exists(info_file):
268 raise OSError('Build info file not found!')
269 with open(info_file, 'r') as f:
270 print f.read()
271
272
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800273def PackFactoryToolkit(src_root, output_path, enable_device, enable_presenter):
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800274 """Packs the files containing this script into a factory toolkit."""
275 with open(os.path.join(src_root, 'VERSION'), 'r') as f:
276 version = f.read().strip()
Jon Salz4f3ade52014-02-20 17:55:09 +0800277 with tempfile.NamedTemporaryFile() as help_header:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800278 help_header.write(version + '\n' + HELP_HEADER + HELP_HEADER_MAKESELF)
Jon Salz4f3ade52014-02-20 17:55:09 +0800279 help_header.flush()
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800280 cmd = [os.path.join(src_root, 'makeself.sh'), '--bzip2', '--nox11',
Jon Salz4f3ade52014-02-20 17:55:09 +0800281 '--help-header', help_header.name,
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800282 src_root, output_path, version, INSTALLER_PATH, '--in-exe']
283 if not enable_device:
284 cmd.append('--no-enable-device')
285 if not enable_presenter:
286 cmd.append('--no-enable-presenter')
287 Spawn(cmd, check_call=True, log=True)
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800288 print ('\n'
Hung-Te Lin56b18402015-01-16 14:52:30 +0800289 ' Factory toolkit generated at %s.\n'
290 '\n'
291 ' To install factory toolkit on a live device running a test image,\n'
292 ' copy this to the device and execute it as root.\n'
293 '\n'
294 ' Alternatively, the factory toolkit can be used to patch a test\n'
295 ' image. For more information, run:\n'
296 ' %s --help\n'
297 '\n' % (output_path, output_path))
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800298
299
Rong Chang6d65fad2014-08-22 16:00:12 +0800300def InitUmpire(exe_path, src_root, target_board):
301 """Inits Umpire server environment."""
302 if exe_path is None:
303 parent_cmdline = open('/proc/%s/cmdline' % os.getppid(),
304 'r').read().rstrip('\0').split('\0')
305
306 if parent_cmdline > 1 and parent_cmdline[0] == MAKESELF_SHELL:
307 # Get parent script name from parent process.
308 exe_path = parent_cmdline[1]
309 else:
310 # Set to default.
311 exe_path = TOOLKIT_NAME
312
313 if not exe_path.startswith('/'):
314 exe_path = os.path.join(os.environ.get('OLDPWD'), exe_path)
315
316 with file_utils.TempDirectory() as nano_bundle:
317 bundle_toolkit_dir = os.path.join(nano_bundle, 'factory_toolkit')
318 os.mkdir(bundle_toolkit_dir)
319 os.symlink(exe_path, os.path.join(bundle_toolkit_dir,
320 os.path.basename(exe_path)))
321 umpire_bin = os.path.join(src_root, 'usr', 'local', 'factory', 'bin',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800322 'umpire')
Rong Chang6d65fad2014-08-22 16:00:12 +0800323 Spawn([umpire_bin, 'init', '--board', target_board, nano_bundle],
324 check_call=True, log=True)
325 print ('\n'
Hung-Te Lin56b18402015-01-16 14:52:30 +0800326 ' Umpire initialized successfully. Upstart service is running:\n'
327 ' umpire BOARD=%(board)s.\n'
328 ' For more information, please check umpire command line:\n'
329 '\n'
330 ' umpire-%(board)s --help (if your id is in umpire group)\n'
331 ' or sudo umpire-%(board)s --help\n'
332 '\n' % {'board': target_board})
Rong Chang6d65fad2014-08-22 16:00:12 +0800333
334
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800335def main():
Jon Salz4f3ade52014-02-20 17:55:09 +0800336 import logging
337 logging.basicConfig(level=logging.INFO)
338
339 # In order to determine which usage message to show, first determine
340 # whether we're in the self-extracting archive. Do this first
341 # because we need it to even parse the arguments.
342 if '--in-exe' in sys.argv:
343 sys.argv = [x for x in sys.argv if x != '--in-exe']
344 in_archive = True
345 else:
346 in_archive = False
347
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800348 parser = argparse.ArgumentParser(
Jon Salz4f3ade52014-02-20 17:55:09 +0800349 description=HELP_HEADER + HELP_HEADER_ADVANCED,
350 usage=('install_factory_toolkit.run -- [options]' if in_archive
351 else None),
352 formatter_class=argparse.RawDescriptionHelpFormatter)
Hung-Te Lin56b18402015-01-16 14:52:30 +0800353 parser.add_argument(
354 'dest', nargs='?', default='/',
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800355 help='A test image or the mount point of the stateful partition. '
356 "If omitted, install to live system, i.e. '/'.")
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800357 parser.add_argument('--no-enable', '-n', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800358 help="Don't enable factory tests after installing")
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800359 parser.add_argument('--yes', '-y', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800360 help="Don't ask for confirmation")
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800361 parser.add_argument('--build-info', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800362 help='Print build information and exit')
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800363 parser.add_argument('--pack-into', metavar='NEW_TOOLKIT',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800364 help='Pack the files into a new factory toolkit')
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800365 parser.add_argument('--repack', metavar='UNPACKED_TOOLKIT',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800366 help='Repack from previously unpacked toolkit')
Vic Yang7039f422014-07-07 15:38:13 -0700367
Peter Ammon948b7172014-07-15 12:43:06 -0700368 parser.add_argument('--enable-presenter', dest='enable_presenter',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800369 action='store_true',
370 help='Run goofy in presenter mode on startup')
Peter Ammon948b7172014-07-15 12:43:06 -0700371 parser.add_argument('--no-enable-presenter', dest='enable_presenter',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800372 action='store_false', help=argparse.SUPPRESS)
Vic Yang423c2722014-09-24 16:05:06 +0800373 parser.set_defaults(enable_presenter=True)
Vic Yang7039f422014-07-07 15:38:13 -0700374
Vic Yang70fdae92015-02-17 19:21:08 -0800375 parser.add_argument('--non-cros', dest='non_cros',
376 action='store_true',
377 help='Install on non-ChromeOS host.')
378
Vic Yang7039f422014-07-07 15:38:13 -0700379 parser.add_argument('--enable-device', dest='enable_device',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800380 action='store_true',
381 help='Run goofy in device mode on startup')
Vic Yang7039f422014-07-07 15:38:13 -0700382 parser.add_argument('--no-enable-device', dest='enable_device',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800383 action='store_false', help=argparse.SUPPRESS)
Vic Yang423c2722014-09-24 16:05:06 +0800384 parser.set_defaults(enable_device=True)
385
Rong Chang6d65fad2014-08-22 16:00:12 +0800386 parser.add_argument('--init-umpire-board', dest='umpire_board',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800387 nargs='?', default=None,
388 help='Locally install Umpire server for specific board')
Rong Chang6d65fad2014-08-22 16:00:12 +0800389 parser.add_argument('--exe-path', dest='exe_path',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800390 nargs='?', default=None,
391 help='Current self-extracting archive pathname')
Vic Yang7039f422014-07-07 15:38:13 -0700392
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800393 args = parser.parse_args()
394
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800395 src_root = factory.FACTORY_PATH
396 for _ in xrange(3):
397 src_root = os.path.dirname(src_root)
398
Rong Chang6d65fad2014-08-22 16:00:12 +0800399 # --init-umpire-board creates a nano bundle, then calls umpire command
400 # line utility to install the server code and upstart configurations.
401 if args.umpire_board:
402 InitUmpire(args.exe_path, src_root, args.umpire_board)
403 return
404
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800405 # --pack-into may be called directly so this must be done before changing
406 # working directory to OLDPWD.
407 if args.pack_into and args.repack is None:
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800408 PackFactoryToolkit(src_root, args.pack_into, args.enable_device,
409 args.enable_presenter)
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800410 return
411
Jon Salz4f3ade52014-02-20 17:55:09 +0800412 if not in_archive:
413 # If you're not in the self-extracting archive, you're not allowed to
414 # do anything except the above --pack-into call.
415 parser.error('Not running from install_factory_toolkit.run; '
416 'only --pack-into (without --repack) is allowed')
417
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800418 # Change to original working directory in case the user specifies
419 # a relative path.
420 # TODO: Use USER_PWD instead when makeself is upgraded
421 os.chdir(os.environ['OLDPWD'])
422
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800423 if args.repack:
424 if args.pack_into is None:
425 parser.error('Must specify --pack-into when using --repack.')
426 Spawn([os.path.join(args.repack, INSTALLER_PATH),
427 '--pack-into', args.pack_into], check_call=True, log=True)
428 return
429
430 if args.build_info:
431 PrintBuildInfo(src_root)
432 return
433
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800434 if not os.path.exists(args.dest):
435 parser.error('Destination %s does not exist!' % args.dest)
436
437 patch_test_image = os.path.isfile(args.dest)
438
439 with (MountPartition(args.dest, 1, rw=True) if patch_test_image
440 else DummyContext(args.dest)) as dest:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800441 installer = FactoryToolkitInstaller(
442 src_root, dest, args.no_enable, args.enable_presenter,
Vic Yang70fdae92015-02-17 19:21:08 -0800443 args.enable_device, args.non_cros)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800444
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800445 print installer.WarningMessage(args.dest if patch_test_image else None)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800446
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800447 if not args.yes:
448 answer = raw_input('*** Continue? [y/N] ')
449 if not answer or answer[0] not in 'yY':
450 sys.exit('Aborting.')
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800451
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800452 installer.Install()
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800453
454if __name__ == '__main__':
455 main()