mirror of
https://github.com/flatcar/scripts.git
synced 2025-08-08 05:26:58 +02:00
These errors on extraction if you don't have the original targets of the links on the image (i.e. if the stateful_partition gets wiped). Change-Id: Id5d3f770830de6165613d506733c04edefccd3fb BUG=chromium-os:9103 TEST=Ran update, wiped partition, ran stateful_update and ran bvt's. Review URL: http://codereview.chromium.org/4882006
96 lines
3.4 KiB
Python
Executable File
96 lines
3.4 KiB
Python
Executable File
#!/usr/bin/python2.6
|
|
|
|
# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""This module is responsible for generate a stateful update payload."""
|
|
|
|
import logging
|
|
import optparse
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
|
|
STATEFUL_FILE = 'stateful.tgz'
|
|
|
|
|
|
def GenerateStatefulPayload(image_path, output_directory, logger):
|
|
"""Generates a stateful update payload given a full path to an image.
|
|
|
|
Args:
|
|
image_path: Full path to the image.
|
|
output_directory: Path to the directory to leave the resulting output.
|
|
logger: logging instance.
|
|
"""
|
|
logger.info('Generating stateful update file.')
|
|
from_dir = os.path.dirname(image_path)
|
|
image = os.path.basename(image_path)
|
|
output_gz = os.path.join(output_directory, STATEFUL_FILE)
|
|
crosutils_dir = os.path.dirname(__file__)
|
|
|
|
# Temporary directories for this function.
|
|
rootfs_dir = tempfile.mkdtemp(suffix='rootfs', prefix='tmp')
|
|
stateful_dir = tempfile.mkdtemp(suffix='stateful', prefix='tmp')
|
|
|
|
# Mount the image to pull out the important directories.
|
|
try:
|
|
# Only need stateful partition, but this saves us having to manage our
|
|
# own loopback device.
|
|
subprocess.check_call(['%s/mount_gpt_image.sh' % crosutils_dir,
|
|
'--from=%s' % from_dir,
|
|
'--image=%s' % image,
|
|
'--read_only',
|
|
'--rootfs_mountpt=%s' % rootfs_dir,
|
|
'--stateful_mountpt=%s' % stateful_dir,
|
|
])
|
|
logger.info('Tarring up /usr/local and /var!')
|
|
subprocess.check_call(['sudo',
|
|
'tar',
|
|
'-czf',
|
|
output_gz,
|
|
'--directory=%s' % stateful_dir,
|
|
'--hard-dereference',
|
|
'--transform=s,^dev_image,dev_image_new,',
|
|
'--transform=s,^var,var_new,',
|
|
'dev_image',
|
|
'var',
|
|
])
|
|
except:
|
|
logger.error('Failed to create stateful update file')
|
|
raise
|
|
finally:
|
|
# Unmount best effort regardless.
|
|
subprocess.call(['%s/mount_gpt_image.sh' % crosutils_dir,
|
|
'--unmount',
|
|
'--rootfs_mountpt=%s' % rootfs_dir,
|
|
'--stateful_mountpt=%s' % stateful_dir,
|
|
])
|
|
# Clean up our directories.
|
|
os.rmdir(rootfs_dir)
|
|
os.rmdir(stateful_dir)
|
|
|
|
logger.info('Successfully generated %s' % output_gz)
|
|
|
|
|
|
def main():
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(os.path.basename(__file__))
|
|
parser = optparse.OptionParser()
|
|
parser.add_option('-i', '--image_path',
|
|
help='The image to generate the stateful update for.')
|
|
parser.add_option('-o', '--output_dir',
|
|
help='The path to the directory to output the update file.')
|
|
options, unused_args = parser.parse_args()
|
|
if not options.image_path:
|
|
parser.error('Missing image for stateful payload generator')
|
|
if not options.output_dir:
|
|
parser.error('Missing output directory for the payload generator')
|
|
|
|
GenerateStatefulPayload(os.path.abspath(options.image_path),
|
|
options.output_dir, logger)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|