blob: 2790b001413833f5f9a733000345dda2881fff4e [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')
55
56 if (not os.path.exists(self._usr_local_src) or
57 not os.path.exists(self._var_src)):
58 raise Exception(
59 'This installer must be run from within the factory toolkit!')
60
61 def WarningMessage(self):
62 ret = (
63 '\n'
64 '\n'
65 '*** You are about to install factory toolkit to:\n'
66 '*** %s\n'
67 '***' % self._dest)
68 if self._dest == '/':
69 ret += ('\n'
70 '*** After this process is done, your device will start factory tests\n'
71 '*** on the next reboot.\n'
72 '***\n'
73 '*** Factory tests can be disabled by deleting factory enabled tag:\n'
74 '*** /usr/local/factory/enabled\n'
75 '***')
76 return ret
77
78 def _Rsync(self, src, dest):
79 print '*** %s -> %s' % (src, dest)
80 subprocess.check_call(['rsync', '-a', src + '/', dest])
81
82 def Install(self):
83 print '*** Installing factory toolkit...'
84 self._Rsync(self._usr_local_src, self._usr_local_dest)
85 self._Rsync(self._var_src, self._var_dest)
86
87 print '*** Installing factory enabled tag...'
88 open(os.path.join(self._usr_local_dest, 'factory', 'enabled'), 'w').close()
89
90 print '*** Installation completed.'
91
92
93def main():
94 parser = argparse.ArgumentParser(
95 description='Factory toolkit installer.')
96 parser.add_argument('--dest', '-d', default='/',
97 help='Destination path. Mount point of stateful partition if patching '
98 'a test image.')
99 parser.add_argument('--patch-test-image', '-p', action='store_true',
100 help='Patching a test image instead of installing to live system.')
101 parser.add_argument('--yes', '-y', action='store_true',
102 help="Don't ask for confirmation")
103 args = parser.parse_args()
104
105 try:
106 src_root = factory.FACTORY_PATH
107 for _ in xrange(3):
108 src_root = os.path.dirname(src_root)
109 installer = FactoryToolkitInstaller(src_root, args)
110 except Exception as e:
111 parser.error(e.message)
112
113 print installer.WarningMessage()
114
115 if not args.yes:
116 answer = raw_input('*** Continue? [y/N] ')
117 if not answer or answer[0] not in 'yY':
118 sys.exit('Aborting.')
119
120 installer.Install()
121
122if __name__ == '__main__':
123 main()