blob: aa8824b67a85679a13c2d4fa229a0533f43647c8 [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
246 # Check to see if cros flash will work for the remote machine.
247 CheckForCrosFlash(options.chromeos_root, options.remote, log_level)
248
Manoj Gupta1282e842017-05-17 12:57:56 -0700249 # Disable the annoying chromebook beeps after reboot.
250 DisableCrosBeeps(options.chromeos_root, options.remote, log_level)
251
Caroline Ticef6ef4392017-04-06 17:16:05 -0700252 cros_flash_args = [
Manoj Gupta1282e842017-05-17 12:57:56 -0700253 'cros', 'flash',
254 '--board=%s' % board, '--clobber-stateful', options.remote
Caroline Ticef6ef4392017-04-06 17:16:05 -0700255 ]
cmticee5bc63b2015-05-27 16:59:37 -0700256 if local_image:
David Sharpa20e0302016-01-25 16:00:02 -0800257 cros_flash_args.append(chroot_image)
cmticee5bc63b2015-05-27 16:59:37 -0700258 else:
David Sharpa20e0302016-01-25 16:00:02 -0800259 cros_flash_args.append(image)
cmticee5bc63b2015-05-27 16:59:37 -0700260
David Sharpa20e0302016-01-25 16:00:02 -0800261 command = ' '.join(cros_flash_args)
cmticee5bc63b2015-05-27 16:59:37 -0700262
263 # Workaround for crosbug.com/35684.
264 os.chmod(misc.GetChromeOSKeyFile(options.chromeos_root), 0600)
cmticeb1340082014-01-13 13:22:37 -0800265
David Sharpa20e0302016-01-25 16:00:02 -0800266 if log_level == 'average':
267 cmd_executer.SetLogLevel('verbose')
cmticee5bc63b2015-05-27 16:59:37 -0700268 retries = 0
David Sharpa20e0302016-01-25 16:00:02 -0800269 while True:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800270 if log_level == 'quiet':
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800271 l.LogOutput('CMD : %s' % command)
Caroline Ticef6ef4392017-04-06 17:16:05 -0700272 ret = cmd_executer.ChrootRunCommand(
273 options.chromeos_root, command, command_timeout=1800)
David Sharpa20e0302016-01-25 16:00:02 -0800274 if ret == 0 or retries >= 2:
275 break
276 retries += 1
277 if log_level == 'quiet':
278 l.LogOutput('Imaging failed. Retry # %d.' % retries)
cmtice13909242014-03-11 13:38:07 -0700279
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800280 if log_level == 'average':
cmticee5bc63b2015-05-27 16:59:37 -0700281 cmd_executer.SetLogLevel(log_level)
cmtice0cc4e772014-01-30 15:52:37 -0800282
Caroline Tice88272d42016-01-13 09:48:29 -0800283 logger.GetLogger().LogFatalIf(ret, 'Image command failed')
cmticee5bc63b2015-05-27 16:59:37 -0700284
285 # Unfortunately cros_image_to_target.py sometimes returns early when the
286 # machine isn't fully up yet.
Caroline Tice88272d42016-01-13 09:48:29 -0800287 ret = EnsureMachineUp(options.chromeos_root, options.remote, log_level)
cmticee5bc63b2015-05-27 16:59:37 -0700288
Caroline Tice88272d42016-01-13 09:48:29 -0800289 # If this is a non-local image, then the ret returned from
cmticee5bc63b2015-05-27 16:59:37 -0700290 # EnsureMachineUp is the one that will be returned by this function;
Caroline Tice88272d42016-01-13 09:48:29 -0800291 # in that case, make sure the value in 'ret' is appropriate.
292 if not local_image and ret == True:
293 ret = 0
cmticee5bc63b2015-05-27 16:59:37 -0700294 else:
Caroline Tice88272d42016-01-13 09:48:29 -0800295 ret = 1
cmticee5bc63b2015-05-27 16:59:37 -0700296
297 if local_image:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800298 if log_level == 'average':
299 l.LogOutput('Verifying image.')
300 command = 'echo %s > %s && chmod -w %s' % (image_checksum,
Caroline Ticef6ef4392017-04-06 17:16:05 -0700301 checksum_file, checksum_file)
Caroline Tice88272d42016-01-13 09:48:29 -0800302 ret = cmd_executer.CrosRunCommand(
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800303 command,
304 chromeos_root=options.chromeos_root,
305 machine=options.remote)
Caroline Tice88272d42016-01-13 09:48:29 -0800306 logger.GetLogger().LogFatalIf(ret, 'Writing checksum failed.')
cmticee5bc63b2015-05-27 16:59:37 -0700307
Caroline Ticed0f7a732018-03-02 16:31:17 -0800308 successfully_imaged = VerifyChromeChecksum(
309 options.chromeos_root, chroot_image, options.remote, log_level)
cmticee5bc63b2015-05-27 16:59:37 -0700310 logger.GetLogger().LogFatalIf(not successfully_imaged,
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800311 'Image verification failed!')
cmticee5bc63b2015-05-27 16:59:37 -0700312 TryRemountPartitionAsRW(options.chromeos_root, options.remote,
313 log_level)
Gabriel Marine2a920a2018-05-16 11:31:07 -0700314
315 if found == False:
316 temp_dir = os.path.dirname(located_image)
317 l.LogOutput('Deleting temp image dir: %s' % temp_dir)
318 shutil.rmtree(temp_dir)
cmticee5bc63b2015-05-27 16:59:37 -0700319 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800320 l.LogOutput('Checksums match. Skipping reimage')
Caroline Tice88272d42016-01-13 09:48:29 -0800321 return ret
cmticee5bc63b2015-05-27 16:59:37 -0700322 finally:
323 if should_unlock:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800324 locks.ReleaseLock(list(options.remote.split()), options.chromeos_root)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700325
326
327def LocateOrCopyImage(chromeos_root, image, board=None):
328 l = logger.GetLogger()
329 if board is None:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800330 board_glob = '*'
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700331 else:
332 board_glob = board
333
334 chromeos_root_realpath = os.path.realpath(chromeos_root)
335 image = os.path.realpath(image)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800336
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800337 if image.startswith('%s/' % chromeos_root_realpath):
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700338 return [True, image]
339
340 # First search within the existing build dirs for any matching files.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800341 images_glob = ('%s/src/build/images/%s/*/*.bin' % (chromeos_root_realpath,
342 board_glob))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700343 images_list = glob.glob(images_glob)
344 for potential_image in images_list:
345 if filecmp.cmp(potential_image, image):
Caroline Ticef6ef4392017-04-06 17:16:05 -0700346 l.LogOutput('Found matching image %s in chromeos_root.' % potential_image)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700347 return [True, potential_image]
cmtice13909242014-03-11 13:38:07 -0700348 # We did not find an image. Copy it in the src dir and return the copied
349 # file.
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700350 if board is None:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800351 board = ''
352 base_dir = ('%s/src/build/images/%s' % (chromeos_root_realpath, board))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700353 if not os.path.isdir(base_dir):
354 os.makedirs(base_dir)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800355 temp_dir = tempfile.mkdtemp(prefix='%s/tmp' % base_dir)
356 new_image = '%s/%s' % (temp_dir, os.path.basename(image))
357 l.LogOutput('No matching image found. Copying %s to %s' % (image, new_image))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700358 shutil.copyfile(image, new_image)
359 return [False, new_image]
360
361
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800362def GetImageMountCommand(chromeos_root, image, rootfs_mp, stateful_mp):
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700363 image_dir = os.path.dirname(image)
364 image_file = os.path.basename(image)
Caroline Ticed0f7a732018-03-02 16:31:17 -0800365 mount_command = ('cd ~/trunk/src/scripts &&'
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800366 './mount_gpt_image.sh --from=%s --image=%s'
367 ' --safe --read_only'
368 ' --rootfs_mountpt=%s'
Caroline Ticed0f7a732018-03-02 16:31:17 -0800369 ' --stateful_mountpt=%s' % (image_dir, image_file, rootfs_mp,
370 stateful_mp))
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700371 return mount_command
372
373
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800374def MountImage(chromeos_root,
375 image,
376 rootfs_mp,
377 stateful_mp,
378 log_level,
Caroline Ticed0f7a732018-03-02 16:31:17 -0800379 unmount=False,
380 extra_commands=''):
cmtice13909242014-03-11 13:38:07 -0700381 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
Ahmad Sharif0dcbc4b2012-02-02 16:37:18 -0800382 command = GetImageMountCommand(chromeos_root, image, rootfs_mp, stateful_mp)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700383 if unmount:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800384 command = '%s --unmount' % command
Caroline Ticed0f7a732018-03-02 16:31:17 -0800385 if extra_commands:
386 command = '%s ; %s' % (command, extra_commands)
387 ret, out, _ = cmd_executer.ChrootRunCommandWOutput(chromeos_root, command)
Caroline Tice88272d42016-01-13 09:48:29 -0800388 logger.GetLogger().LogFatalIf(ret, 'Mount/unmount command failed!')
Caroline Ticed0f7a732018-03-02 16:31:17 -0800389 return out
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700390
391
cmtice13909242014-03-11 13:38:07 -0700392def IsImageModdedForTest(chromeos_root, image, log_level):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800393 if log_level != 'verbose':
394 log_level = 'quiet'
Caroline Ticed0f7a732018-03-02 16:31:17 -0800395 command = 'mktemp -d'
396 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
397 _, rootfs_mp, _ = cmd_executer.ChrootRunCommandWOutput(chromeos_root, command)
398 _, stateful_mp, _ = cmd_executer.ChrootRunCommandWOutput(
399 chromeos_root, command)
400 rootfs_mp = rootfs_mp.strip()
401 stateful_mp = stateful_mp.strip()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800402 lsb_release_file = os.path.join(rootfs_mp, 'etc/lsb-release')
Caroline Ticed0f7a732018-03-02 16:31:17 -0800403 extra = (
404 'grep CHROMEOS_RELEASE_DESCRIPTION %s | grep -i test' % lsb_release_file)
405 output = MountImage(
406 chromeos_root,
407 image,
408 rootfs_mp,
409 stateful_mp,
410 log_level,
411 extra_commands=extra)
412 is_test_image = re.search('test', output, re.IGNORECASE)
Caroline Ticef6ef4392017-04-06 17:16:05 -0700413 MountImage(
414 chromeos_root, image, rootfs_mp, stateful_mp, log_level, unmount=True)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700415 return is_test_image
416
417
cmtice13909242014-03-11 13:38:07 -0700418def VerifyChromeChecksum(chromeos_root, image, remote, log_level):
Caroline Ticed0f7a732018-03-02 16:31:17 -0800419 command = 'mktemp -d'
cmtice13909242014-03-11 13:38:07 -0700420 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
Caroline Ticed0f7a732018-03-02 16:31:17 -0800421 _, rootfs_mp, _ = cmd_executer.ChrootRunCommandWOutput(chromeos_root, command)
422 _, stateful_mp, _ = cmd_executer.ChrootRunCommandWOutput(
423 chromeos_root, command)
424 rootfs_mp = rootfs_mp.strip()
425 stateful_mp = stateful_mp.strip()
426 chrome_file = '%s/opt/google/chrome/chrome' % rootfs_mp
427 extra = 'md5sum %s' % chrome_file
428 out = MountImage(
429 chromeos_root,
430 image,
431 rootfs_mp,
432 stateful_mp,
433 log_level,
434 extra_commands=extra)
435 image_chrome_checksum = out.strip().split()[0]
Caroline Ticef6ef4392017-04-06 17:16:05 -0700436 MountImage(
437 chromeos_root, image, rootfs_mp, stateful_mp, log_level, unmount=True)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700438
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800439 command = 'md5sum /opt/google/chrome/chrome'
Caroline Ticef6ef4392017-04-06 17:16:05 -0700440 [_, o, _] = cmd_executer.CrosRunCommandWOutput(
441 command, chromeos_root=chromeos_root, machine=remote)
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700442 device_chrome_checksum = o.split()[0]
443 if image_chrome_checksum.strip() == device_chrome_checksum.strip():
444 return True
445 else:
446 return False
447
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800448
Luis Lozanof81680c2013-03-15 14:44:13 -0700449# Remount partition as writable.
450# TODO: auto-detect if an image is built using --noenable_rootfs_verification.
cmtice13909242014-03-11 13:38:07 -0700451def TryRemountPartitionAsRW(chromeos_root, remote, log_level):
Luis Lozanof81680c2013-03-15 14:44:13 -0700452 l = logger.GetLogger()
cmtice13909242014-03-11 13:38:07 -0700453 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800454 command = 'sudo mount -o remount,rw /'
Caroline Tice88272d42016-01-13 09:48:29 -0800455 ret = cmd_executer.CrosRunCommand(\
456 command, chromeos_root=chromeos_root, machine=remote,
457 terminated_timeout=10)
458 if ret:
Luis Lozanof81680c2013-03-15 14:44:13 -0700459 ## Safely ignore.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800460 l.LogWarning('Failed to remount partition as rw, '
461 'probably the image was not built with '
Luis Lozanof81680c2013-03-15 14:44:13 -0700462 "\"--noenable_rootfs_verification\", "
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800463 'you can safely ignore this.')
Luis Lozanof81680c2013-03-15 14:44:13 -0700464 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800465 l.LogOutput('Re-mounted partition as writable.')
Luis Lozanof81680c2013-03-15 14:44:13 -0700466
Ahmad Sharif70de27b2011-06-15 17:51:24 -0700467
cmtice13909242014-03-11 13:38:07 -0700468def EnsureMachineUp(chromeos_root, remote, log_level):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800469 l = logger.GetLogger()
cmtice13909242014-03-11 13:38:07 -0700470 cmd_executer = command_executer.GetCommandExecuter(log_level=log_level)
Ahmad Sharif4467f002012-12-20 12:09:49 -0800471 timeout = 600
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800472 magic = 'abcdefghijklmnopqrstuvwxyz'
473 command = 'echo %s' % magic
Ahmad Sharif4467f002012-12-20 12:09:49 -0800474 start_time = time.time()
475 while True:
476 current_time = time.time()
477 if current_time - start_time > timeout:
Caroline Ticef6ef4392017-04-06 17:16:05 -0700478 l.LogError(
479 'Timeout of %ss reached. Machine still not up. Aborting.' % timeout)
Ahmad Sharif4467f002012-12-20 12:09:49 -0800480 return False
Caroline Ticef6ef4392017-04-06 17:16:05 -0700481 ret = cmd_executer.CrosRunCommand(
482 command, chromeos_root=chromeos_root, machine=remote)
Caroline Tice88272d42016-01-13 09:48:29 -0800483 if not ret:
Ahmad Sharif4467f002012-12-20 12:09:49 -0800484 return True
485
486
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800487if __name__ == '__main__':
cmticee5bc63b2015-05-27 16:59:37 -0700488 retval = DoImage(sys.argv)
489 sys.exit(retval)