blob: 7ff36beebaf89016aec8416fcdce5aac109bc8a3 [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
Wei-Ning Huang4855e792015-06-11 15:33:39 +080018import shutil
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080019import sys
Jon Salz4f3ade52014-02-20 17:55:09 +080020import tempfile
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080021
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +080022import factory_common # pylint: disable=W0611
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080023from cros.factory.test import factory
Vic Yang196d5242014-08-05 13:51:35 +080024from cros.factory.test import utils
Jon Salz25590302014-07-11 16:07:20 +080025from cros.factory.tools import install_symlinks
Rong Chang6d65fad2014-08-22 16:00:12 +080026from cros.factory.utils import file_utils
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +080027from cros.factory.utils.process_utils import Spawn
Hung-Te Lincdc2a042014-08-27 13:05:16 +080028from cros.factory.utils.sys_utils import MountPartition
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080029
30
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +080031INSTALLER_PATH = 'usr/local/factory/py/toolkit/installer.py'
Rong Chang6d65fad2014-08-22 16:00:12 +080032MAKESELF_SHELL = '/bin/sh'
33TOOLKIT_NAME = 'install_factory_toolkit.run'
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +080034
Jon Salz4f3ade52014-02-20 17:55:09 +080035# Short and sweet help header for the executable generated by makeself.
36HELP_HEADER = """
37Installs the factory toolkit, transforming a test image into a factory test
38image. You can:
39
40- Install the factory toolkit on a CrOS device that is running a test
41 image. To do this, copy install_factory_toolkit.run to the device and
42 run it. The factory tests will then come up on the next boot.
43
44 rsync -a install_factory_toolkit.run crosdevice:/tmp
45 ssh crosdevice '/tmp/install_factory_toolkit.run && sync && reboot'
46
47- Modify a test image, turning it into a factory test image. When you
48 use the image on a device, the factory tests will come up.
49
50 install_factory_toolkit.run chromiumos_test_image.bin
51"""
52
53HELP_HEADER_ADVANCED = """
54- (advanced) Modify a mounted stateful partition, turning it into a factory
55 test image. This is equivalent to the previous command:
56
57 mount_partition -rw chromiumos_test_image.bin 1 /mnt/stateful
58 install_factory_toolkit.run /mnt/stateful
59 umount /mnt/stateful
60
61- (advanced) Unpack the factory toolkit, modify a file, and then repack it.
62
63 # Unpack but don't actually install
64 install_factory_toolkit.run --target /tmp/toolkit --noexec
65 # Edit some files in /tmp/toolkit
66 emacs /tmp/toolkit/whatever
67 # Repack
68 install_factory_toolkit.run -- --repack /tmp/toolkit \\
69 --pack-into /path/to/new/install_factory_toolkit.run
70"""
71
72# The makeself-generated header comes next. This is a little confusing,
73# so explain.
74HELP_HEADER_MAKESELF = """
75For complete usage information and advanced operations, run
76"install_factory_toolkit.run -- --help" (note the extra "--").
77
78Following is the help message from makeself, which was used to create
79this self-extracting archive.
80
81-----
82"""
83
Vic Yang196d5242014-08-05 13:51:35 +080084# The method to determine whether running on Chrome OS device or not.
85# Override this for unit testing.
86_in_cros_device = utils.in_cros_device
87
Vic Yangdb1e20e2014-10-05 12:10:33 +080088SERVER_FILE_MASK = [
89 # Exclude Umpire server but keep Umpire client
90 '--include', 'py/umpire/__init__.*',
91 '--include', 'py/umpire/common.*',
92 '--include', 'py/umpire/client',
93 '--include', 'py/umpire/client/**',
94 '--exclude', 'py/umpire/**',
95
96 # Lumberjack is only used on Umpire server
97 '--exclude', 'py/lumberjack'
98]
99
Jon Salz4f3ade52014-02-20 17:55:09 +0800100
Hung-Te Lin7b596ff2015-01-16 20:19:15 +0800101class FactoryToolkitInstaller(object):
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800102 """Factory toolkit installer.
103
104 Args:
105 src: Source path containing usr/ and var/.
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800106 dest: Installation destination path. Set this to the mount point of the
107 stateful partition if patching a test image.
108 no_enable: True to not install the tag file.
109 system_root: The path to the root of the file system. This must be left
110 as its default value except for unit testing.
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800111 """
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800112
Jon Salzb7e44262014-05-07 15:53:37 +0800113 # Whether to sudo when rsyncing; set to False for testing.
114 _sudo = True
115
Peter Ammon948b7172014-07-15 12:43:06 -0700116 def __init__(self, src, dest, no_enable, enable_presenter,
Vic Yang70fdae92015-02-17 19:21:08 -0800117 enable_device, non_cros=False, system_root='/'):
Jon Salz4f3ade52014-02-20 17:55:09 +0800118 self._src = src
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800119 self._system_root = system_root
120 if dest == self._system_root:
121 self._usr_local_dest = os.path.join(dest, 'usr', 'local')
122 self._var_dest = os.path.join(dest, 'var')
Jon Salz4f3ade52014-02-20 17:55:09 +0800123
124 # Make sure we're on a CrOS device.
Vic Yang70fdae92015-02-17 19:21:08 -0800125 if not non_cros and not _in_cros_device():
Jon Salz4f3ade52014-02-20 17:55:09 +0800126 sys.stderr.write(
Vic Yang196d5242014-08-05 13:51:35 +0800127 "ERROR: You're not on a CrOS device (for more details, please\n"
Hung-Te Lin56b18402015-01-16 14:52:30 +0800128 'check utils.py:in_cros_device), so you must specify a test\n'
129 'image or a mounted stateful partition on which to install the\n'
130 'factory toolkit. Please run\n'
131 '\n'
132 ' install_factory_toolkit.run -- --help\n'
133 '\n'
Vic Yang70fdae92015-02-17 19:21:08 -0800134 'for help.\n'
135 '\n'
136 'If you want to install the presenter on a non-CrOS host,\n'
137 'please run\n'
138 '\n'
139 ' install_factory_toolkit.run -- \\\n'
140 ' --non-cros --no-enable-device --enable-presenter\n'
141 '\n')
Jon Salz4f3ade52014-02-20 17:55:09 +0800142 sys.exit(1)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800143 if os.getuid() != 0:
Jon Salz4f3ade52014-02-20 17:55:09 +0800144 raise Exception('You must be root to install the factory toolkit on a '
145 'CrOS device.')
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800146 else:
147 self._usr_local_dest = os.path.join(dest, 'dev_image')
148 self._var_dest = os.path.join(dest, 'var_overlay')
149 if (not os.path.exists(self._usr_local_dest) or
150 not os.path.exists(self._var_dest)):
151 raise Exception(
152 'The destination path %s is not a stateful partition!' % dest)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800153
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800154 self._dest = dest
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800155 self._usr_local_src = os.path.join(src, 'usr', 'local')
156 self._var_src = os.path.join(src, 'var')
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800157 self._no_enable = no_enable
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800158 self._tag_file = os.path.join(self._usr_local_dest, 'factory', 'enabled')
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800159
Peter Ammon948b7172014-07-15 12:43:06 -0700160 self._enable_presenter = enable_presenter
161 self._presenter_tag_file = os.path.join(self._usr_local_dest, 'factory',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800162 'init', 'run_goofy_presenter')
Vic Yang7039f422014-07-07 15:38:13 -0700163
164 self._enable_device = enable_device
Ricky Liangd7716912014-07-10 11:52:24 +0800165 self._device_tag_file = os.path.join(self._usr_local_dest, 'factory',
166 'init', 'run_goofy_device')
Vic Yang7039f422014-07-07 15:38:13 -0700167
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800168 if (not os.path.exists(self._usr_local_src) or
169 not os.path.exists(self._var_src)):
170 raise Exception(
171 'This installer must be run from within the factory toolkit!')
172
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800173 def WarningMessage(self, target_test_image=None):
Jon Salz4f3ade52014-02-20 17:55:09 +0800174 with open(os.path.join(self._src, 'VERSION')) as f:
175 ret = f.read()
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800176 if target_test_image:
Jon Salz4f3ade52014-02-20 17:55:09 +0800177 ret += (
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800178 '\n'
179 '\n'
Jon Salz4f3ade52014-02-20 17:55:09 +0800180 '*** You are about to patch the factory toolkit into:\n'
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800181 '*** %s\n'
182 '***' % target_test_image)
183 else:
Jon Salz4f3ade52014-02-20 17:55:09 +0800184 ret += (
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800185 '\n'
186 '\n'
Jon Salz4f3ade52014-02-20 17:55:09 +0800187 '*** You are about to install the factory toolkit to:\n'
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800188 '*** %s\n'
189 '***' % self._dest)
190 if self._dest == self._system_root:
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800191 if self._no_enable:
Hung-Te Lin7b596ff2015-01-16 20:19:15 +0800192 ret += ('\n*** Factory tests will be disabled after this process is '
Hung-Te Lin56b18402015-01-16 14:52:30 +0800193 'done, but\n*** you can enable them by creating the factory '
194 'enabled tag:\n*** %s\n***' % self._tag_file)
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800195 else:
Hung-Te Lin7b596ff2015-01-16 20:19:15 +0800196 ret += ('\n*** After this process is done, your device will start '
Hung-Te Lin56b18402015-01-16 14:52:30 +0800197 'factory\n*** tests on the next reboot.\n***\n*** Factory '
198 'tests can be disabled by deleting the factory enabled\n*** '
199 'tag:\n*** %s\n***' % self._tag_file)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800200 return ret
201
Vic Yang7039f422014-07-07 15:38:13 -0700202 def _SetTagFile(self, name, path, enabled):
203 """Install or remove a tag file."""
204 if enabled:
205 print '*** Installing %s enabled tag...' % name
206 Spawn(['touch', path], sudo=True, log=True, check_call=True)
Ricky Liang8c88a122014-07-11 21:21:22 +0800207 Spawn(['chmod', 'go+r', path], sudo=True, log=True, check_call=True)
Vic Yang7039f422014-07-07 15:38:13 -0700208 else:
209 print '*** Removing %s enabled tag...' % name
210 Spawn(['rm', '-f', path], sudo=True, log=True, check_call=True)
211
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800212 def Install(self):
213 print '*** Installing factory toolkit...'
Jon Salzb7e44262014-05-07 15:53:37 +0800214 for src, dest in ((self._usr_local_src, self._usr_local_dest),
215 (self._var_src, self._var_dest)):
216 # Change the source directory to root, and add group/world read
217 # permissions. This is necessary because when the toolkit was
218 # unpacked, the user may not have been root so the permessions
219 # may be hosed. This is skipped for testing.
Peter Ammon5ac58422014-06-09 14:45:50 -0700220 # --force is necessary to allow goofy directory from prior
221 # toolkit installations to be overwritten by the goofy symlink.
Ricky Liang5e95be22014-07-09 12:52:07 +0800222 try:
223 if self._sudo:
224 Spawn(['chown', '-R', 'root', src],
225 sudo=True, log=True, check_call=True)
226 Spawn(['chmod', '-R', 'go+rX', src],
227 sudo=True, log=True, check_call=True)
228 print '*** %s -> %s' % (src, dest)
Hung-Te Lin56b18402015-01-16 14:52:30 +0800229 Spawn(['rsync', '-a', '--force'] + SERVER_FILE_MASK +
Vic Yangdb1e20e2014-10-05 12:10:33 +0800230 [src + '/', dest], sudo=self._sudo, log=True,
231 check_output=True, cwd=src)
Ricky Liang5e95be22014-07-09 12:52:07 +0800232 finally:
233 # Need to change the source directory back to the original user, or the
234 # script in makeself will fail to remove the temporary source directory.
235 if self._sudo:
236 myuser = os.environ.get('USER')
237 Spawn(['chown', '-R', myuser, src],
238 sudo=True, log=True, check_call=True)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800239
Jon Salz25590302014-07-11 16:07:20 +0800240 print '*** Installing symlinks...'
241 install_symlinks.InstallSymlinks(
242 '../factory/bin',
243 os.path.join(self._usr_local_dest, 'bin'),
244 install_symlinks.MODE_FULL,
245 sudo=self._sudo)
246
247 print '*** Removing factory-mini...'
248 Spawn(['rm', '-rf', os.path.join(self._usr_local_dest, 'factory-mini')],
249 sudo=self._sudo, log=True, check_call=True)
250
Vic Yang7039f422014-07-07 15:38:13 -0700251 self._SetTagFile('factory', self._tag_file, not self._no_enable)
Peter Ammon948b7172014-07-15 12:43:06 -0700252 self._SetTagFile('presenter', self._presenter_tag_file,
253 self._enable_presenter)
Vic Yang7039f422014-07-07 15:38:13 -0700254 self._SetTagFile('device', self._device_tag_file, self._enable_device)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800255
256 print '*** Installation completed.'
257
258
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800259@contextmanager
260def DummyContext(arg):
261 """A context manager that simply yields its argument."""
262 yield arg
263
264
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800265def PrintBuildInfo(src_root):
266 """Print build information."""
267 info_file = os.path.join(src_root, 'REPO_STATUS')
268 if not os.path.exists(info_file):
269 raise OSError('Build info file not found!')
270 with open(info_file, 'r') as f:
271 print f.read()
272
273
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800274def PackFactoryToolkit(src_root, output_path, enable_device, enable_presenter):
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800275 """Packs the files containing this script into a factory toolkit."""
276 with open(os.path.join(src_root, 'VERSION'), 'r') as f:
277 version = f.read().strip()
Jon Salz4f3ade52014-02-20 17:55:09 +0800278 with tempfile.NamedTemporaryFile() as help_header:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800279 help_header.write(version + '\n' + HELP_HEADER + HELP_HEADER_MAKESELF)
Jon Salz4f3ade52014-02-20 17:55:09 +0800280 help_header.flush()
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800281 cmd = [os.path.join(src_root, 'makeself.sh'), '--bzip2', '--nox11',
Jon Salz4f3ade52014-02-20 17:55:09 +0800282 '--help-header', help_header.name,
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800283 src_root, output_path, version, INSTALLER_PATH, '--in-exe']
284 if not enable_device:
285 cmd.append('--no-enable-device')
286 if not enable_presenter:
287 cmd.append('--no-enable-presenter')
288 Spawn(cmd, check_call=True, log=True)
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800289 print ('\n'
Hung-Te Lin56b18402015-01-16 14:52:30 +0800290 ' Factory toolkit generated at %s.\n'
291 '\n'
292 ' To install factory toolkit on a live device running a test image,\n'
293 ' copy this to the device and execute it as root.\n'
294 '\n'
295 ' Alternatively, the factory toolkit can be used to patch a test\n'
296 ' image. For more information, run:\n'
297 ' %s --help\n'
298 '\n' % (output_path, output_path))
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800299
300
Rong Chang6d65fad2014-08-22 16:00:12 +0800301def InitUmpire(exe_path, src_root, target_board):
302 """Inits Umpire server environment."""
303 if exe_path is None:
304 parent_cmdline = open('/proc/%s/cmdline' % os.getppid(),
305 'r').read().rstrip('\0').split('\0')
306
307 if parent_cmdline > 1 and parent_cmdline[0] == MAKESELF_SHELL:
308 # Get parent script name from parent process.
309 exe_path = parent_cmdline[1]
310 else:
311 # Set to default.
312 exe_path = TOOLKIT_NAME
313
314 if not exe_path.startswith('/'):
315 exe_path = os.path.join(os.environ.get('OLDPWD'), exe_path)
316
317 with file_utils.TempDirectory() as nano_bundle:
318 bundle_toolkit_dir = os.path.join(nano_bundle, 'factory_toolkit')
319 os.mkdir(bundle_toolkit_dir)
320 os.symlink(exe_path, os.path.join(bundle_toolkit_dir,
321 os.path.basename(exe_path)))
322 umpire_bin = os.path.join(src_root, 'usr', 'local', 'factory', 'bin',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800323 'umpire')
Rong Chang6d65fad2014-08-22 16:00:12 +0800324 Spawn([umpire_bin, 'init', '--board', target_board, nano_bundle],
325 check_call=True, log=True)
326 print ('\n'
Hung-Te Lin56b18402015-01-16 14:52:30 +0800327 ' Umpire initialized successfully. Upstart service is running:\n'
328 ' umpire BOARD=%(board)s.\n'
329 ' For more information, please check umpire command line:\n'
330 '\n'
331 ' umpire-%(board)s --help (if your id is in umpire group)\n'
332 ' or sudo umpire-%(board)s --help\n'
333 '\n' % {'board': target_board})
Rong Chang6d65fad2014-08-22 16:00:12 +0800334
335
Wei-Ning Huang4855e792015-06-11 15:33:39 +0800336def ExtractOverlord(src_root, output_dir):
337 output_dir = os.path.join(output_dir, 'overlord')
338 try:
339 os.makedirs(output_dir)
340 except OSError as e:
341 print str(e)
342 return
343
344 # Copy overlord binary and resource files
345 shutil.copyfile(os.path.join(src_root, 'usr/bin/overlordd'),
346 os.path.join(output_dir, 'overlordd'))
347 shutil.copytree(os.path.join(src_root, 'usr/share/overlord/app'),
348 os.path.join(output_dir, 'app'))
349
350 # Give overlordd execution permission
351 os.chmod(os.path.join(output_dir, 'overlordd'), 0755)
352 print "Extarcted overlord under '%s'" % output_dir
353
354
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800355def main():
Jon Salz4f3ade52014-02-20 17:55:09 +0800356 import logging
357 logging.basicConfig(level=logging.INFO)
358
359 # In order to determine which usage message to show, first determine
360 # whether we're in the self-extracting archive. Do this first
361 # because we need it to even parse the arguments.
362 if '--in-exe' in sys.argv:
363 sys.argv = [x for x in sys.argv if x != '--in-exe']
364 in_archive = True
365 else:
366 in_archive = False
367
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800368 parser = argparse.ArgumentParser(
Jon Salz4f3ade52014-02-20 17:55:09 +0800369 description=HELP_HEADER + HELP_HEADER_ADVANCED,
370 usage=('install_factory_toolkit.run -- [options]' if in_archive
371 else None),
372 formatter_class=argparse.RawDescriptionHelpFormatter)
Hung-Te Lin56b18402015-01-16 14:52:30 +0800373 parser.add_argument(
374 'dest', nargs='?', default='/',
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800375 help='A test image or the mount point of the stateful partition. '
376 "If omitted, install to live system, i.e. '/'.")
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800377 parser.add_argument('--no-enable', '-n', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800378 help="Don't enable factory tests after installing")
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800379 parser.add_argument('--yes', '-y', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800380 help="Don't ask for confirmation")
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800381 parser.add_argument('--build-info', action='store_true',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800382 help='Print build information and exit')
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800383 parser.add_argument('--pack-into', metavar='NEW_TOOLKIT',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800384 help='Pack the files into a new factory toolkit')
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800385 parser.add_argument('--repack', metavar='UNPACKED_TOOLKIT',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800386 help='Repack from previously unpacked toolkit')
Vic Yang7039f422014-07-07 15:38:13 -0700387
Peter Ammon948b7172014-07-15 12:43:06 -0700388 parser.add_argument('--enable-presenter', dest='enable_presenter',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800389 action='store_true',
390 help='Run goofy in presenter mode on startup')
Peter Ammon948b7172014-07-15 12:43:06 -0700391 parser.add_argument('--no-enable-presenter', dest='enable_presenter',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800392 action='store_false', help=argparse.SUPPRESS)
Vic Yang423c2722014-09-24 16:05:06 +0800393 parser.set_defaults(enable_presenter=True)
Vic Yang7039f422014-07-07 15:38:13 -0700394
Vic Yang70fdae92015-02-17 19:21:08 -0800395 parser.add_argument('--non-cros', dest='non_cros',
396 action='store_true',
397 help='Install on non-ChromeOS host.')
398
Vic Yang7039f422014-07-07 15:38:13 -0700399 parser.add_argument('--enable-device', dest='enable_device',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800400 action='store_true',
401 help='Run goofy in device mode on startup')
Vic Yang7039f422014-07-07 15:38:13 -0700402 parser.add_argument('--no-enable-device', dest='enable_device',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800403 action='store_false', help=argparse.SUPPRESS)
Vic Yang423c2722014-09-24 16:05:06 +0800404 parser.set_defaults(enable_device=True)
405
Rong Chang6d65fad2014-08-22 16:00:12 +0800406 parser.add_argument('--init-umpire-board', dest='umpire_board',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800407 nargs='?', default=None,
408 help='Locally install Umpire server for specific board')
Rong Chang6d65fad2014-08-22 16:00:12 +0800409 parser.add_argument('--exe-path', dest='exe_path',
Hung-Te Lin56b18402015-01-16 14:52:30 +0800410 nargs='?', default=None,
411 help='Current self-extracting archive pathname')
Wei-Ning Huang4855e792015-06-11 15:33:39 +0800412 parser.add_argument('--extract-overlord', dest='extract_overlord',
413 metavar='OUTPUT_DIR', type=str, default=None,
414 help='Extract overlord from the toolkit')
Vic Yang7039f422014-07-07 15:38:13 -0700415
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800416 args = parser.parse_args()
417
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800418 src_root = factory.FACTORY_PATH
419 for _ in xrange(3):
420 src_root = os.path.dirname(src_root)
421
Rong Chang6d65fad2014-08-22 16:00:12 +0800422 # --init-umpire-board creates a nano bundle, then calls umpire command
423 # line utility to install the server code and upstart configurations.
424 if args.umpire_board:
425 InitUmpire(args.exe_path, src_root, args.umpire_board)
426 return
427
Wei-Ning Huang4855e792015-06-11 15:33:39 +0800428 if args.extract_overlord is not None:
429 ExtractOverlord(src_root, args.extract_overlord)
430 return
431
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800432 # --pack-into may be called directly so this must be done before changing
433 # working directory to OLDPWD.
434 if args.pack_into and args.repack is None:
Wei-Ning Huangb723d7f2014-11-17 17:26:32 +0800435 PackFactoryToolkit(src_root, args.pack_into, args.enable_device,
436 args.enable_presenter)
Vic (Chun-Ju) Yang98b4fbc2014-02-18 19:32:32 +0800437 return
438
Jon Salz4f3ade52014-02-20 17:55:09 +0800439 if not in_archive:
440 # If you're not in the self-extracting archive, you're not allowed to
441 # do anything except the above --pack-into call.
442 parser.error('Not running from install_factory_toolkit.run; '
443 'only --pack-into (without --repack) is allowed')
444
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800445 # Change to original working directory in case the user specifies
446 # a relative path.
447 # TODO: Use USER_PWD instead when makeself is upgraded
448 os.chdir(os.environ['OLDPWD'])
449
Vic (Chun-Ju) Yangb7388f72014-02-19 15:22:58 +0800450 if args.repack:
451 if args.pack_into is None:
452 parser.error('Must specify --pack-into when using --repack.')
453 Spawn([os.path.join(args.repack, INSTALLER_PATH),
454 '--pack-into', args.pack_into], check_call=True, log=True)
455 return
456
457 if args.build_info:
458 PrintBuildInfo(src_root)
459 return
460
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800461 if not os.path.exists(args.dest):
462 parser.error('Destination %s does not exist!' % args.dest)
463
464 patch_test_image = os.path.isfile(args.dest)
465
466 with (MountPartition(args.dest, 1, rw=True) if patch_test_image
467 else DummyContext(args.dest)) as dest:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800468 installer = FactoryToolkitInstaller(
469 src_root, dest, args.no_enable, args.enable_presenter,
Vic Yang70fdae92015-02-17 19:21:08 -0800470 args.enable_device, args.non_cros)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800471
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800472 print installer.WarningMessage(args.dest if patch_test_image else None)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800473
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800474 if not args.yes:
475 answer = raw_input('*** Continue? [y/N] ')
476 if not answer or answer[0] not in 'yY':
477 sys.exit('Aborting.')
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800478
Vic (Chun-Ju) Yang469592b2014-02-18 19:15:41 +0800479 installer.Install()
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800480
481if __name__ == '__main__':
482 main()