| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python2.6 | |
| 2 | |
| 3 # Copyright (c) 2010 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 """This module is responsible for generate a stateful update payload.""" | |
| 8 | |
| 9 import logging | |
| 10 import optparse | |
| 11 import os | |
| 12 import subprocess | |
| 13 import tempfile | |
| 14 | |
| 15 STATEFUL_FILE = 'stateful.tgz' | |
| 16 | |
| 17 | |
| 18 def GenerateStatefulPayload(image_path, output_directory, logger): | |
| 19 """Generates a stateful update payload given a full path to an image. | |
| 20 | |
| 21 Args: | |
| 22 image_path: Full path to the image. | |
| 23 output_directory: Path to the directory to leave the resulting output. | |
| 24 logger: logging instance. | |
| 25 """ | |
| 26 logger.info('Generating stateful update file.') | |
| 27 from_dir = os.path.dirname(image_path) | |
| 28 image = os.path.basename(image_path) | |
| 29 output_gz = os.path.join(output_directory, STATEFUL_FILE) | |
| 30 crosutils_dir = os.path.dirname(__file__) | |
| 31 | |
| 32 # Temporary directories for this function. | |
| 33 rootfs_dir = tempfile.mkdtemp(suffix='rootfs', prefix='tmp') | |
| 34 stateful_dir = tempfile.mkdtemp(suffix='stateful', prefix='tmp') | |
| 35 | |
| 36 # Mount the image to pull out the important directories. | |
| 37 try: | |
| 38 # Only need stateful partition, but this saves us having to manage our | |
| 39 # own loopback device. | |
| 40 subprocess.check_call(['%s/mount_gpt_image.sh' % crosutils_dir, | |
| 41 '--from=%s' % from_dir, | |
| 42 '--image=%s' % image, | |
| 43 '--read_only', | |
| 44 '--rootfs_mountpt=%s' % rootfs_dir, | |
| 45 '--stateful_mountpt=%s' % stateful_dir, | |
| 46 ]) | |
| 47 logger.info('Tarring up /usr/local and /var!') | |
| 48 subprocess.check_call(['sudo', | |
| 49 'tar', | |
| 50 '-czf', | |
| 51 output_gz, | |
| 52 '--directory=%s' % stateful_dir, | |
| 53 '--hard-dereference', | |
| 54 '--transform=s,^dev_image,dev_image_new,', | |
| 55 '--transform=s,^var,var_new,', | |
| 56 'dev_image', | |
| 57 'var', | |
| 58 ]) | |
| 59 except: | |
| 60 logger.error('Failed to create stateful update file') | |
| 61 raise | |
| 62 finally: | |
| 63 # Unmount best effort regardless. | |
| 64 subprocess.call(['%s/mount_gpt_image.sh' % crosutils_dir, | |
| 65 '--unmount', | |
| 66 '--rootfs_mountpt=%s' % rootfs_dir, | |
| 67 '--stateful_mountpt=%s' % stateful_dir, | |
| 68 ]) | |
| 69 # Clean up our directories. | |
| 70 os.rmdir(rootfs_dir) | |
| 71 os.rmdir(stateful_dir) | |
| 72 | |
| 73 logger.info('Successfully generated %s' % output_gz) | |
| 74 | |
| 75 | |
| 76 def main(): | |
| 77 logging.basicConfig(level=logging.INFO) | |
| 78 logger = logging.getLogger(os.path.basename(__file__)) | |
| 79 parser = optparse.OptionParser() | |
| 80 parser.add_option('-i', '--image_path', | |
| 81 help='The image to generate the stateful update for.') | |
| 82 parser.add_option('-o', '--output_dir', | |
| 83 help='The path to the directory to output the update file.') | |
| 84 options, unused_args = parser.parse_args() | |
| 85 if not options.image_path: | |
| 86 parser.error('Missing image for stateful payload generator') | |
| 87 if not options.output_dir: | |
| 88 parser.error('Missing output directory for the payload generator') | |
| 89 | |
| 90 GenerateStatefulPayload(os.path.abspath(options.image_path), | |
| 91 options.output_dir, logger) | |
| 92 | |
| 93 | |
| 94 if __name__ == '__main__': | |
| 95 main() | |
| OLD | NEW |