blob: 581b4eabc7af39dea4e6afde1c8b6e38efd91971 [file] [log] [blame]
Caroline Ticef6ef4392017-04-06 17:16:05 -07001#!/usr/bin/env python2
Ahmad Sharif70de27b2011-06-15 17:51:24 -07002#
3# Copyright 2011 Google Inc. All Rights Reserved.
Ahmad Sharif70de27b2011-06-15 17:51:24 -07004"""Script to image a ChromeOS device.
5
6This script images a remote ChromeOS device with a specific image."
7"""
8
Caroline Tice88272d42016-01-13 09:48:29 -08009from __future__ import print_function
10
Luis Lozanof2a3ef42015-12-15 13:49:30 -080011__author__ = 'asharif@google.com (Ahmad Sharif)'
Ahmad Sharif70de27b2011-06-15 17:51:24 -070012
Caroline Tice88272d42016-01-13 09:48:29 -080013import argparse
Ahmad Sharif70de27b2011-06-15 17:51:24 -070014import filecmp
Caroline Ticed0f7a732018-03-02 16:31:17 -080015import getpass
Ahmad Sharif70de27b2011-06-15 17:51:24 -070016import glob
Ahmad Sharif70de27b2011-06-15 17:51:24 -070017import os
Ahmad Shariff395c262012-10-09 17:48:09 -070018import re
Ahmad Sharif70de27b2011-06-15 17:51:24 -070019import shutil
20import sys
21import tempfile
Ahmad Sharif4467f002012-12-20 12:09:49 -080022import time
23
Caroline Tice88272d42016-01-13 09:48:29 -080024from cros_utils import command_executer
25from cros_utils import locks
26from cros_utils import logger
27from cros_utils import misc
28from cros_utils.file_utils import FileUtils
Ahmad Sharif70de27b2011-06-15 17:51:24 -070029
Luis Lozanof2a3ef42015-12-15 13:49:30 -080030checksum_file = '/usr/local/osimage_checksum_file'
31lock_file = '/tmp/image_chromeos_lock/image_chromeos_lock'
32
Ahmad Sharif70de27b2011-06-15 17:51:24 -070033
34def Usage(parser, message):
Caroline Tice88272d42016-01-13 09:48:29 -080035 print('ERROR: %s' % message)
Ahmad Sharif70de27b2011-06-15 17:51:24 -070036 parser.print_help()
37 sys.exit(0)
38
Ahmad Shariff395c262012-10-09 17:48:09 -070039
cmtice13909242014-03-11 13:38:07 -070040def CheckForCrosFlash(chromeos_root, remote, log_level):
41 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
cmtice0cc4e772014-01-30 15:52:37 -080042
Luis Lozano54db5382015-05-20 15:57:19 -070043 # Check to see if remote machine has cherrypy, ctypes
44 command = "python -c 'import cherrypy, ctypes'"
Caroline Ticef6ef4392017-04-06 17:16:05 -070045 ret = cmd_executer.CrosRunCommand(
46 command, chromeos_root=chromeos_root, machine=remote)
Han Shen96d936c2015-03-25 12:03:12 -070047 logger.GetLogger().LogFatalIf(
Caroline Tice88272d42016-01-13 09:48:29 -080048 ret == 255, 'Failed ssh to %s (for checking cherrypy)' % remote)
Luis Lozano54db5382015-05-20 15:57:19 -070049 logger.GetLogger().LogFatalIf(
Caroline Tice88272d42016-01-13 09:48:29 -080050 ret != 0, "Failed to find cherrypy or ctypes on remote '{}', "
Luis Lozanof2a3ef42015-12-15 13:49:30 -080051 'cros flash cannot work.'.format(remote))
Luis Lozano54db5382015-05-20 15:57:19 -070052
cmtice0cc4e772014-01-30 15:52:37 -080053
Manoj Gupta1282e842017-05-17 12:57:56 -070054def DisableCrosBeeps(chromeos_root, remote, log_level):
55 """Disable annoying chromebooks beeps after reboots."""
56 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
57
58 command = '/usr/share/vboot/bin/set_gbb_flags.sh 0x1'
59 logger.GetLogger().LogOutput('Trying to disable beeping.')
60
61 ret, o, _ = cmd_executer.CrosRunCommandWOutput(
62 command, chromeos_root=chromeos_root, machine=remote)
63 if ret != 0:
64 logger.GetLogger().LogOutput(o)
65 logger.GetLogger().LogOutput('Failed to disable beeps.')
66
67
Caroline Ticed0f7a732018-03-02 16:31:17 -080068def FindChromeOSImage(image_file, chromeos_root):
69 """Find path for ChromeOS image inside chroot.
70
71 This function could be called with image paths that are either inside
72 or outside the chroot. In either case the path needs to be translated
73 to an real/absolute path inside the chroot.
74 Example input paths:
75 /usr/local/google/home/uname/chromeos/chroot/tmp/my-test-images/image
76 ~/trunk/src/build/images/board/latest/image
77 /tmp/peppy-release/R67-1235.0.0/image
78
79 Corresponding example output paths:
80 /tmp/my-test-images/image
81 /home/uname/trunk/src/build/images/board/latest/image
82 /tmp/peppy-release/R67-1235.0,0/image
83 """
84
85 # Get the name of the user, for "/home/<user>" part of the path.
86 whoami = getpass.getuser()
87 # Get the full path for the chroot dir, including 'chroot'
88 real_chroot_dir = os.path.join(os.path.realpath(chromeos_root), 'chroot')
89 # Get the full path for the chromeos root, excluding 'chroot'
90 real_chromeos_root = os.path.realpath(chromeos_root)
91
92 # If path name starts with real_chroot_dir, remove that piece, but assume
93 # the rest of the path is correct.
94 if image_file.find(real_chroot_dir) != -1:
95 chroot_image = image_file[len(real_chroot_dir):]
96 # If path name starts with chromeos_root, excluding 'chroot', replace the
97 # chromeos_root with the prefix: '/home/<username>/trunk'.
98 elif image_file.find(real_chromeos_root) != -1:
99 chroot_image = image_file[len(real_chromeos_root):]
100 chroot_image = '/home/%s/trunk%s' % (whoami, chroot_image)
101 # Else assume the path is already internal, so leave it alone.
102 else:
103 chroot_image = image_file
104
105 return chroot_image
106
107
Ahmad Sharif4467f002012-12-20 12:09:49 -0800108def DoImage(argv):
Han Shenba649282015-08-05 17:19:55 -0700109 """Image ChromeOS."""
Ahmad Sharif4467f002012-12-20 12:09:49 -0800110
Caroline Tice88272d42016-01-13 09:48:29 -0800111 parser = argparse.ArgumentParser()
Caroline Ticef6ef4392017-04-06 17:16:05 -0700112 parser.add_argument(
113 '-c',
114 '--chromeos_root',
115 dest='chromeos_root',
116 help='Target directory for ChromeOS installation.')
Caroline Tice88272d42016-01-13 09:48:29 -0800117 parser.add_argument('-r', '--remote', dest='remote', help='Target device.')
118 parser.add_argument('-i', '--image', dest='image', help='Image binary file.')
Caroline Ticef6ef4392017-04-06 17:16:05 -0700119 parser.add_argument(
120 '-b', '--board', dest='board', help='Target board override.')
121 parser.add_argument(
122 '-f',
123 '--force',
124 dest='force',
125 action='store_true',
126 default=False,
127 help='Force an image even if it is non-test.')
128 parser.add_argument(
129 '-n',
130 '--no_lock',
131 dest='no_lock',
132 default=False,
133 action='store_true',
134 help='Do not attempt to lock remote before imaging. '
135 'This option should only be used in cases where the '
136 'exclusive lock has already been acquired (e.g. in '
137 'a script that calls this one).')
138 parser.add_argument(
139 '-l',
140 '--logging_level',
141 dest='log_level',
142 default='verbose',
143 help='Amount of logging to be used. Valid levels are '
144 "'quiet', 'average', and 'verbose'.")
Caroline Tice88272d42016-01-13 09:48:29 -0800145 parser.add_argument('-a', '--image_args', dest='image_args')
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700146
Caroline Tice88272d42016-01-13 09:48:29 -0800147 options = parser.parse_args(argv[1:])
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700148
cmtice13909242014-03-11 13:38:07 -0700149 if not options.log_level in command_executer.LOG_LEVEL:
150 Usage(parser, "--logging_level must be 'quiet', 'average' or 'verbose'")
151 else:
152 log_level = options.log_level
153
154 # Common initializations
155 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
156 l = logger.GetLogger()
157
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700158 if options.chromeos_root is None:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800159 Usage(parser, '--chromeos_root must be set')
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700160
161 if options.remote is None:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800162 Usage(parser, '--remote must be set')
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700163
164 options.chromeos_root = os.path.expanduser(options.chromeos_root)
165
166 if options.board is None:
167 board = cmd_executer.CrosLearnBoard(options.chromeos_root, options.remote)
168 else:
169 board = options.board
170
171 if options.image is None:
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700172 images_dir = misc.GetImageDir(options.chromeos_root, board)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800173 image = os.path.join(images_dir, 'latest', 'chromiumos_test_image.bin')
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700174 if not os.path.exists(image):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800175 image = os.path.join(images_dir, 'latest', 'chromiumos_image.bin')
David Sharpa20e0302016-01-25 16:00:02 -0800176 is_xbuddy_image = False
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700177 else:
178 image = options.image
David Sharpa20e0302016-01-25 16:00:02 -0800179 is_xbuddy_image = image.startswith('xbuddy://')
180 if not is_xbuddy_image:
cmtice0cc4e772014-01-30 15:52:37 -0800181 image = os.path.expanduser(image)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700182
David Sharpa20e0302016-01-25 16:00:02 -0800183 if not is_xbuddy_image:
cmtice0cc4e772014-01-30 15:52:37 -0800184 image = os.path.realpath(image)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700185
David Sharpa20e0302016-01-25 16:00:02 -0800186 if not os.path.exists(image) and not is_xbuddy_image:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800187 Usage(parser, 'Image file: ' + image + ' does not exist!')
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700188
cmticee5bc63b2015-05-27 16:59:37 -0700189 try:
190 should_unlock = False
191 if not options.no_lock:
192 try:
Caroline Tice88272d42016-01-13 09:48:29 -0800193 _ = locks.AcquireLock(
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800194 list(options.remote.split()), options.chromeos_root)
cmticee5bc63b2015-05-27 16:59:37 -0700195 should_unlock = True
196 except Exception as e:
Caroline Tice9099a782016-07-22 16:28:12 -0700197 raise RuntimeError('Error acquiring machine: %s' % str(e))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700198
cmticee5bc63b2015-05-27 16:59:37 -0700199 reimage = False
200 local_image = False
David Sharpa20e0302016-01-25 16:00:02 -0800201 if not is_xbuddy_image:
cmticee5bc63b2015-05-27 16:59:37 -0700202 local_image = True
203 image_checksum = FileUtils().Md5File(image, log_level=log_level)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700204
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800205 command = 'cat ' + checksum_file
Caroline Tice88272d42016-01-13 09:48:29 -0800206 ret, device_checksum, _ = cmd_executer.CrosRunCommandWOutput(
Caroline Ticef6ef4392017-04-06 17:16:05 -0700207 command, chromeos_root=options.chromeos_root, machine=options.remote)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700208
cmticee5bc63b2015-05-27 16:59:37 -0700209 device_checksum = device_checksum.strip()
210 image_checksum = str(image_checksum)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700211
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800212 l.LogOutput('Image checksum: ' + image_checksum)
213 l.LogOutput('Device checksum: ' + device_checksum)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700214
cmticee5bc63b2015-05-27 16:59:37 -0700215 if image_checksum != device_checksum:
Caroline Ticef6ef4392017-04-06 17:16:05 -0700216 [found, located_image] = LocateOrCopyImage(
217 options.chromeos_root, image, board=board)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700218
cmticee5bc63b2015-05-27 16:59:37 -0700219 reimage = True
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800220 l.LogOutput('Checksums do not match. Re-imaging...')
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700221
Caroline Ticed0f7a732018-03-02 16:31:17 -0800222 chroot_image = FindChromeOSImage(located_image, options.chromeos_root)
223
cmticee5bc63b2015-05-27 16:59:37 -0700224 is_test_image = IsImageModdedForTest(options.chromeos_root,
Caroline Ticed0f7a732018-03-02 16:31:17 -0800225 chroot_image, log_level)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700226
cmticee5bc63b2015-05-27 16:59:37 -0700227 if not is_test_image and not options.force:
Caroline Tice88272d42016-01-13 09:48:29 -0800228 logger.GetLogger().LogFatal('Have to pass --force to image a '
229 'non-test image!')
cmtice0cc4e772014-01-30 15:52:37 -0800230 else:
cmticee5bc63b2015-05-27 16:59:37 -0700231 reimage = True
232 found = True
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800233 l.LogOutput('Using non-local image; Re-imaging...')
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700234
cmticee5bc63b2015-05-27 16:59:37 -0700235 if reimage:
236 # If the device has /tmp mounted as noexec, image_to_live.sh can fail.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800237 command = 'mount -o remount,rw,exec /tmp'
Caroline Ticef6ef4392017-04-06 17:16:05 -0700238 cmd_executer.CrosRunCommand(
239 command, chromeos_root=options.chromeos_root, machine=options.remote)
cmticeb1340082014-01-13 13:22:37 -0800240
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800241 real_src_dir = os.path.join(
242 os.path.realpath(options.chromeos_root), 'src')
243 real_chroot_dir = os.path.join(
244 os.path.realpath(options.chromeos_root), 'chroot')
cmticee5bc63b2015-05-27 16:59:37 -0700245 if local_image:
246 if located_image.find(real_src_dir) != 0:
247 if located_image.find(real_chroot_dir) != 0:
Caroline Tice9099a782016-07-22 16:28:12 -0700248 raise RuntimeError('Located image: %s not in chromeos_root: %s' %
249 (located_image, options.chromeos_root))
cmticee5bc63b2015-05-27 16:59:37 -0700250 else:
251 chroot_image = located_image[len(real_chroot_dir):]
252 else:
253 chroot_image = os.path.join(
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800254 '~/trunk/src', located_image[len(real_src_dir):].lstrip('/'))
cmticee5bc63b2015-05-27 16:59:37 -0700255
256 # Check to see if cros flash will work for the remote machine.
257 CheckForCrosFlash(options.chromeos_root, options.remote, log_level)
258
Manoj Gupta1282e842017-05-17 12:57:56 -0700259 # Disable the annoying chromebook beeps after reboot.
260 DisableCrosBeeps(options.chromeos_root, options.remote, log_level)
261
Caroline Ticef6ef4392017-04-06 17:16:05 -0700262 cros_flash_args = [
Manoj Gupta1282e842017-05-17 12:57:56 -0700263 'cros', 'flash',
264 '--board=%s' % board, '--clobber-stateful', options.remote
Caroline Ticef6ef4392017-04-06 17:16:05 -0700265 ]
cmticee5bc63b2015-05-27 16:59:37 -0700266 if local_image:
David Sharpa20e0302016-01-25 16:00:02 -0800267 cros_flash_args.append(chroot_image)
cmticee5bc63b2015-05-27 16:59:37 -0700268 else:
David Sharpa20e0302016-01-25 16:00:02 -0800269 cros_flash_args.append(image)
cmticee5bc63b2015-05-27 16:59:37 -0700270
David Sharpa20e0302016-01-25 16:00:02 -0800271 command = ' '.join(cros_flash_args)
cmticee5bc63b2015-05-27 16:59:37 -0700272
273 # Workaround for crosbug.com/35684.
274 os.chmod(misc.GetChromeOSKeyFile(options.chromeos_root), 0600)
cmticeb1340082014-01-13 13:22:37 -0800275
David Sharpa20e0302016-01-25 16:00:02 -0800276 if log_level == 'average':
277 cmd_executer.SetLogLevel('verbose')
cmticee5bc63b2015-05-27 16:59:37 -0700278 retries = 0
David Sharpa20e0302016-01-25 16:00:02 -0800279 while True:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800280 if log_level == 'quiet':
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800281 l.LogOutput('CMD : %s' % command)
Caroline Ticef6ef4392017-04-06 17:16:05 -0700282 ret = cmd_executer.ChrootRunCommand(
283 options.chromeos_root, command, command_timeout=1800)
David Sharpa20e0302016-01-25 16:00:02 -0800284 if ret == 0 or retries >= 2:
285 break
286 retries += 1
287 if log_level == 'quiet':
288 l.LogOutput('Imaging failed. Retry # %d.' % retries)
cmtice13909242014-03-11 13:38:07 -0700289
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800290 if log_level == 'average':
cmticee5bc63b2015-05-27 16:59:37 -0700291 cmd_executer.SetLogLevel(log_level)
cmtice0cc4e772014-01-30 15:52:37 -0800292
cmticee5bc63b2015-05-27 16:59:37 -0700293 if found == False:
294 temp_dir = os.path.dirname(located_image)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800295 l.LogOutput('Deleting temp image dir: %s' % temp_dir)
cmticee5bc63b2015-05-27 16:59:37 -0700296 shutil.rmtree(temp_dir)
297
Caroline Tice88272d42016-01-13 09:48:29 -0800298 logger.GetLogger().LogFatalIf(ret, 'Image command failed')
cmticee5bc63b2015-05-27 16:59:37 -0700299
300 # Unfortunately cros_image_to_target.py sometimes returns early when the
301 # machine isn't fully up yet.
Caroline Tice88272d42016-01-13 09:48:29 -0800302 ret = EnsureMachineUp(options.chromeos_root, options.remote, log_level)
cmticee5bc63b2015-05-27 16:59:37 -0700303
Caroline Tice88272d42016-01-13 09:48:29 -0800304 # If this is a non-local image, then the ret returned from
cmticee5bc63b2015-05-27 16:59:37 -0700305 # EnsureMachineUp is the one that will be returned by this function;
Caroline Tice88272d42016-01-13 09:48:29 -0800306 # in that case, make sure the value in 'ret' is appropriate.
307 if not local_image and ret == True:
308 ret = 0
cmticee5bc63b2015-05-27 16:59:37 -0700309 else:
Caroline Tice88272d42016-01-13 09:48:29 -0800310 ret = 1
cmticee5bc63b2015-05-27 16:59:37 -0700311
312 if local_image:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800313 if log_level == 'average':
314 l.LogOutput('Verifying image.')
315 command = 'echo %s > %s && chmod -w %s' % (image_checksum,
Caroline Ticef6ef4392017-04-06 17:16:05 -0700316 checksum_file, checksum_file)
Caroline Tice88272d42016-01-13 09:48:29 -0800317 ret = cmd_executer.CrosRunCommand(
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800318 command,
319 chromeos_root=options.chromeos_root,
320 machine=options.remote)
Caroline Tice88272d42016-01-13 09:48:29 -0800321 logger.GetLogger().LogFatalIf(ret, 'Writing checksum failed.')
cmticee5bc63b2015-05-27 16:59:37 -0700322
Caroline Ticed0f7a732018-03-02 16:31:17 -0800323 chroot_image = FindChromeOSImage(image, options.chromeos_root)
324 successfully_imaged = VerifyChromeChecksum(
325 options.chromeos_root, chroot_image, options.remote, log_level)
cmticee5bc63b2015-05-27 16:59:37 -0700326 logger.GetLogger().LogFatalIf(not successfully_imaged,
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800327 'Image verification failed!')
cmticee5bc63b2015-05-27 16:59:37 -0700328 TryRemountPartitionAsRW(options.chromeos_root, options.remote,
329 log_level)
330 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800331 l.LogOutput('Checksums match. Skipping reimage')
Caroline Tice88272d42016-01-13 09:48:29 -0800332 return ret
cmticee5bc63b2015-05-27 16:59:37 -0700333 finally:
334 if should_unlock:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800335 locks.ReleaseLock(list(options.remote.split()), options.chromeos_root)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700336
337
338def LocateOrCopyImage(chromeos_root, image, board=None):
339 l = logger.GetLogger()
340 if board is None:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800341 board_glob = '*'
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700342 else:
343 board_glob = board
344
345 chromeos_root_realpath = os.path.realpath(chromeos_root)
346 image = os.path.realpath(image)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800347
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800348 if image.startswith('%s/' % chromeos_root_realpath):
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700349 return [True, image]
350
351 # First search within the existing build dirs for any matching files.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800352 images_glob = ('%s/src/build/images/%s/*/*.bin' % (chromeos_root_realpath,
353 board_glob))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700354 images_list = glob.glob(images_glob)
355 for potential_image in images_list:
356 if filecmp.cmp(potential_image, image):
Caroline Ticef6ef4392017-04-06 17:16:05 -0700357 l.LogOutput('Found matching image %s in chromeos_root.' % potential_image)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700358 return [True, potential_image]
cmtice13909242014-03-11 13:38:07 -0700359 # We did not find an image. Copy it in the src dir and return the copied
360 # file.
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700361 if board is None:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800362 board = ''
363 base_dir = ('%s/src/build/images/%s' % (chromeos_root_realpath, board))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700364 if not os.path.isdir(base_dir):
365 os.makedirs(base_dir)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800366 temp_dir = tempfile.mkdtemp(prefix='%s/tmp' % base_dir)
367 new_image = '%s/%s' % (temp_dir, os.path.basename(image))
368 l.LogOutput('No matching image found. Copying %s to %s' % (image, new_image))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700369 shutil.copyfile(image, new_image)
370 return [False, new_image]
371
372
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800373def GetImageMountCommand(chromeos_root, image, rootfs_mp, stateful_mp):
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700374 image_dir = os.path.dirname(image)
375 image_file = os.path.basename(image)
Caroline Ticed0f7a732018-03-02 16:31:17 -0800376 mount_command = ('cd ~/trunk/src/scripts &&'
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800377 './mount_gpt_image.sh --from=%s --image=%s'
378 ' --safe --read_only'
379 ' --rootfs_mountpt=%s'
Caroline Ticed0f7a732018-03-02 16:31:17 -0800380 ' --stateful_mountpt=%s' % (image_dir, image_file, rootfs_mp,
381 stateful_mp))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700382 return mount_command
383
384
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800385def MountImage(chromeos_root,
386 image,
387 rootfs_mp,
388 stateful_mp,
389 log_level,
Caroline Ticed0f7a732018-03-02 16:31:17 -0800390 unmount=False,
391 extra_commands=''):
cmtice13909242014-03-11 13:38:07 -0700392 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800393 command = GetImageMountCommand(chromeos_root, image, rootfs_mp, stateful_mp)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700394 if unmount:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800395 command = '%s --unmount' % command
Caroline Ticed0f7a732018-03-02 16:31:17 -0800396 if extra_commands:
397 command = '%s ; %s' % (command, extra_commands)
398 ret, out, _ = cmd_executer.ChrootRunCommandWOutput(chromeos_root, command)
Caroline Tice88272d42016-01-13 09:48:29 -0800399 logger.GetLogger().LogFatalIf(ret, 'Mount/unmount command failed!')
Caroline Ticed0f7a732018-03-02 16:31:17 -0800400 return out
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700401
402
cmtice13909242014-03-11 13:38:07 -0700403def IsImageModdedForTest(chromeos_root, image, log_level):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800404 if log_level != 'verbose':
405 log_level = 'quiet'
Caroline Ticed0f7a732018-03-02 16:31:17 -0800406 command = 'mktemp -d'
407 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
408 _, rootfs_mp, _ = cmd_executer.ChrootRunCommandWOutput(chromeos_root, command)
409 _, stateful_mp, _ = cmd_executer.ChrootRunCommandWOutput(
410 chromeos_root, command)
411 rootfs_mp = rootfs_mp.strip()
412 stateful_mp = stateful_mp.strip()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800413 lsb_release_file = os.path.join(rootfs_mp, 'etc/lsb-release')
Caroline Ticed0f7a732018-03-02 16:31:17 -0800414 extra = (
415 'grep CHROMEOS_RELEASE_DESCRIPTION %s | grep -i test' % lsb_release_file)
416 output = MountImage(
417 chromeos_root,
418 image,
419 rootfs_mp,
420 stateful_mp,
421 log_level,
422 extra_commands=extra)
423 is_test_image = re.search('test', output, re.IGNORECASE)
Caroline Ticef6ef4392017-04-06 17:16:05 -0700424 MountImage(
425 chromeos_root, image, rootfs_mp, stateful_mp, log_level, unmount=True)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700426 return is_test_image
427
428
cmtice13909242014-03-11 13:38:07 -0700429def VerifyChromeChecksum(chromeos_root, image, remote, log_level):
Caroline Ticed0f7a732018-03-02 16:31:17 -0800430 command = 'mktemp -d'
cmtice13909242014-03-11 13:38:07 -0700431 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
Caroline Ticed0f7a732018-03-02 16:31:17 -0800432 _, rootfs_mp, _ = cmd_executer.ChrootRunCommandWOutput(chromeos_root, command)
433 _, stateful_mp, _ = cmd_executer.ChrootRunCommandWOutput(
434 chromeos_root, command)
435 rootfs_mp = rootfs_mp.strip()
436 stateful_mp = stateful_mp.strip()
437 chrome_file = '%s/opt/google/chrome/chrome' % rootfs_mp
438 extra = 'md5sum %s' % chrome_file
439 out = MountImage(
440 chromeos_root,
441 image,
442 rootfs_mp,
443 stateful_mp,
444 log_level,
445 extra_commands=extra)
446 image_chrome_checksum = out.strip().split()[0]
Caroline Ticef6ef4392017-04-06 17:16:05 -0700447 MountImage(
448 chromeos_root, image, rootfs_mp, stateful_mp, log_level, unmount=True)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700449
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800450 command = 'md5sum /opt/google/chrome/chrome'
Caroline Ticef6ef4392017-04-06 17:16:05 -0700451 [_, o, _] = cmd_executer.CrosRunCommandWOutput(
452 command, chromeos_root=chromeos_root, machine=remote)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700453 device_chrome_checksum = o.split()[0]
454 if image_chrome_checksum.strip() == device_chrome_checksum.strip():
455 return True
456 else:
457 return False
458
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800459
Luis Lozanof81680c2013-03-15 14:44:13 -0700460# Remount partition as writable.
461# TODO: auto-detect if an image is built using --noenable_rootfs_verification.
cmtice13909242014-03-11 13:38:07 -0700462def TryRemountPartitionAsRW(chromeos_root, remote, log_level):
Luis Lozanof81680c2013-03-15 14:44:13 -0700463 l = logger.GetLogger()
cmtice13909242014-03-11 13:38:07 -0700464 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800465 command = 'sudo mount -o remount,rw /'
Caroline Tice88272d42016-01-13 09:48:29 -0800466 ret = cmd_executer.CrosRunCommand(\
467 command, chromeos_root=chromeos_root, machine=remote,
468 terminated_timeout=10)
469 if ret:
Luis Lozanof81680c2013-03-15 14:44:13 -0700470 ## Safely ignore.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800471 l.LogWarning('Failed to remount partition as rw, '
472 'probably the image was not built with '
Luis Lozanof81680c2013-03-15 14:44:13 -0700473 "\"--noenable_rootfs_verification\", "
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800474 'you can safely ignore this.')
Luis Lozanof81680c2013-03-15 14:44:13 -0700475 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800476 l.LogOutput('Re-mounted partition as writable.')
Luis Lozanof81680c2013-03-15 14:44:13 -0700477
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700478
cmtice13909242014-03-11 13:38:07 -0700479def EnsureMachineUp(chromeos_root, remote, log_level):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800480 l = logger.GetLogger()
cmtice13909242014-03-11 13:38:07 -0700481 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
Ahmad Sharif4467f002012-12-20 12:09:49 -0800482 timeout = 600
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800483 magic = 'abcdefghijklmnopqrstuvwxyz'
484 command = 'echo %s' % magic
Ahmad Sharif4467f002012-12-20 12:09:49 -0800485 start_time = time.time()
486 while True:
487 current_time = time.time()
488 if current_time - start_time > timeout:
Caroline Ticef6ef4392017-04-06 17:16:05 -0700489 l.LogError(
490 'Timeout of %ss reached. Machine still not up. Aborting.' % timeout)
Ahmad Sharif4467f002012-12-20 12:09:49 -0800491 return False
Caroline Ticef6ef4392017-04-06 17:16:05 -0700492 ret = cmd_executer.CrosRunCommand(
493 command, chromeos_root=chromeos_root, machine=remote)
Caroline Tice88272d42016-01-13 09:48:29 -0800494 if not ret:
Ahmad Sharif4467f002012-12-20 12:09:49 -0800495 return True
496
497
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800498if __name__ == '__main__':
cmticee5bc63b2015-05-27 16:59:37 -0700499 retval = DoImage(sys.argv)
500 sys.exit(retval)