blob: 99fa03d92ff562460a85bf887814c4b4b55ab0f0 [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
16import factory_common # pylint: disable=W0611
17import os
18import subprocess
19import sys
20
21from cros.factory.test import factory
22
23
24class FactoryToolkitInstaller():
25 """Factory toolkit installer.
26
27 Args:
28 src: Source path containing usr/ and var/.
29 args: Arguments including
30 dest: Installation destination path. Set this to the mount point of the
31 stateful partition if patching a test image.
32 patch_test_image: True if patching a test image.
33 """
34 def __init__(self, src, args):
35 if args.patch_test_image:
36 self._usr_local_dest = os.path.join(args.dest, 'dev_image', 'local')
37 self._var_dest = os.path.join(args.dest, 'var_overlay')
38 if (not os.path.exists(self._usr_local_dest) or
39 not os.path.exists(self._var_dest)):
40 raise Exception(
41 'The destination path %s is not a stateful partition!' % args.dest)
42 else:
43 self._usr_local_dest = os.path.join(args.dest, 'usr', 'local')
44 self._var_dest = os.path.join(args.dest, 'var')
45 if os.getuid() != 0:
46 raise Exception('Must be root to install on live machine!')
47 if not os.path.exists('/etc/lsb-release'):
48 raise Exception('/etc/lsb-release is missing. '
49 'Are you running this in chroot?')
50
51 self._patch_test_image = args.patch_test_image
52 self._dest = args.dest
53 self._usr_local_src = os.path.join(src, 'usr', 'local')
54 self._var_src = os.path.join(src, 'var')
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +080055 self._no_enable = args.no_enable
56 self._tag_file = os.path.join(self._usr_local_dest, 'factory', 'enabled')
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080057
58 if (not os.path.exists(self._usr_local_src) or
59 not os.path.exists(self._var_src)):
60 raise Exception(
61 'This installer must be run from within the factory toolkit!')
62
63 def WarningMessage(self):
64 ret = (
65 '\n'
66 '\n'
67 '*** You are about to install factory toolkit to:\n'
68 '*** %s\n'
69 '***' % self._dest)
70 if self._dest == '/':
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +080071 if self._no_enable:
72 ret += ('\n'
73 '*** Factory tests will be disabled after this process is done, but\n'
74 '*** you can enable them by creating factory enabled tag:\n'
75 '*** %s\n'
76 '***' % self._tag_file)
77 else:
78 ret += ('\n'
79 '*** After this process is done, your device will start factory\n'
80 '*** tests on the next reboot.\n'
81 '***\n'
82 '*** Factory tests can be disabled by deleting factory enabled tag:\n'
83 '*** %s\n'
84 '***' % self._tag_file)
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +080085 return ret
86
87 def _Rsync(self, src, dest):
88 print '*** %s -> %s' % (src, dest)
89 subprocess.check_call(['rsync', '-a', src + '/', dest])
90
91 def Install(self):
92 print '*** Installing factory toolkit...'
93 self._Rsync(self._usr_local_src, self._usr_local_dest)
94 self._Rsync(self._var_src, self._var_dest)
95
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +080096 if self._no_enable:
97 print '*** Removing factory enabled tag...'
98 try:
99 os.unlink(self._tag_file)
100 except OSError:
101 pass
102 else:
103 print '*** Installing factory enabled tag...'
104 open(self._tag_file, 'w').close()
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800105
106 print '*** Installation completed.'
107
108
109def main():
110 parser = argparse.ArgumentParser(
111 description='Factory toolkit installer.')
112 parser.add_argument('--dest', '-d', default='/',
113 help='Destination path. Mount point of stateful partition if patching '
114 'a test image.')
115 parser.add_argument('--patch-test-image', '-p', action='store_true',
116 help='Patching a test image instead of installing to live system.')
Vic (Chun-Ju) Yang7cc3e672014-01-20 14:06:39 +0800117 parser.add_argument('--no-enable', '-n', action='store_true',
118 help="Don't enable factory tests after installing")
Vic (Chun-Ju) Yang296871a2014-01-13 12:05:18 +0800119 parser.add_argument('--yes', '-y', action='store_true',
120 help="Don't ask for confirmation")
121 args = parser.parse_args()
122
123 try:
124 src_root = factory.FACTORY_PATH
125 for _ in xrange(3):
126 src_root = os.path.dirname(src_root)
127 installer = FactoryToolkitInstaller(src_root, args)
128 except Exception as e:
129 parser.error(e.message)
130
131 print installer.WarningMessage()
132
133 if not args.yes:
134 answer = raw_input('*** Continue? [y/N] ')
135 if not answer or answer[0] not in 'yY':
136 sys.exit('Aborting.')
137
138 installer.Install()
139
140if __name__ == '__main__':
141 main()