Merge "releasetools: Raise on image building errors."

am: fabb2c9792

Change-Id: Ice30d5a972e30302ae233dc2013c051ee287a0e7
This commit is contained in:
Tao Bao
2018-10-03 13:42:09 -07:00
committed by android-build-merger
4 changed files with 146 additions and 163 deletions

View File

@@ -308,9 +308,8 @@ def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
hash_seed = "hash_seed-" + uuid_seed hash_seed = "hash_seed-" + uuid_seed
image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed)) image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
succ = build_image.BuildImage(os.path.join(input_dir, what.upper()), build_image.BuildImage(
image_props, output_file.name) os.path.join(input_dir, what.upper()), image_props, output_file.name)
assert succ, "build " + what + ".img image failed"
output_file.Write() output_file.Write()
if block_list: if block_list:
@@ -361,8 +360,7 @@ def AddUserdata(output_zip):
fstab = OPTIONS.info_dict["fstab"] fstab = OPTIONS.info_dict["fstab"]
if fstab: if fstab:
image_props["fs_type"] = fstab["/data"].fs_type image_props["fs_type"] = fstab["/data"].fs_type
succ = build_image.BuildImage(user_dir, image_props, img.name) build_image.BuildImage(user_dir, image_props, img.name)
assert succ, "build userdata.img image failed"
common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict) common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict)
img.Write() img.Write()
@@ -514,8 +512,7 @@ def AddCache(output_zip):
fstab = OPTIONS.info_dict["fstab"] fstab = OPTIONS.info_dict["fstab"]
if fstab: if fstab:
image_props["fs_type"] = fstab["/cache"].fs_type image_props["fs_type"] = fstab["/cache"].fs_type
succ = build_image.BuildImage(user_dir, image_props, img.name) build_image.BuildImage(user_dir, image_props, img.name)
assert succ, "build cache.img image failed"
common.CheckSize(img.name, "cache.img", OPTIONS.info_dict) common.CheckSize(img.name, "cache.img", OPTIONS.info_dict)
img.Write() img.Write()

View File

@@ -45,6 +45,13 @@ BLOCK_SIZE = 4096
BYTES_IN_MB = 1024 * 1024 BYTES_IN_MB = 1024 * 1024
class BuildImageError(Exception):
"""An Exception raised during image building."""
def __init__(self, message):
Exception.__init__(self, message)
def RunCommand(cmd, verbose=None, env=None): def RunCommand(cmd, verbose=None, env=None):
"""Echo and run the given command. """Echo and run the given command.
@@ -76,58 +83,55 @@ def GetVerityFECSize(partition_size):
cmd = ["fec", "-s", str(partition_size)] cmd = ["fec", "-s", str(partition_size)]
output, exit_code = RunCommand(cmd, False) output, exit_code = RunCommand(cmd, False)
if exit_code != 0: if exit_code != 0:
return False, 0 raise BuildImageError("Failed to GetVerityFECSize:\n{}".format(output))
return True, int(output) return int(output)
def GetVerityTreeSize(partition_size): def GetVerityTreeSize(partition_size):
cmd = ["build_verity_tree", "-s", str(partition_size)] cmd = ["build_verity_tree", "-s", str(partition_size)]
output, exit_code = RunCommand(cmd, False) output, exit_code = RunCommand(cmd, False)
if exit_code != 0: if exit_code != 0:
return False, 0 raise BuildImageError("Failed to GetVerityTreeSize:\n{}".format(output))
return True, int(output) return int(output)
def GetVerityMetadataSize(partition_size): def GetVerityMetadataSize(partition_size):
cmd = ["build_verity_metadata.py", "size", str(partition_size)] cmd = ["build_verity_metadata.py", "size", str(partition_size)]
output, exit_code = RunCommand(cmd, False) output, exit_code = RunCommand(cmd, False)
if exit_code != 0: if exit_code != 0:
return False, 0 raise BuildImageError("Failed to GetVerityMetadataSize:\n{}".format(output))
return True, int(output) return int(output)
def GetVeritySize(partition_size, fec_supported): def GetVeritySize(partition_size, fec_supported):
success, verity_tree_size = GetVerityTreeSize(partition_size) verity_tree_size = GetVerityTreeSize(partition_size)
if not success: verity_metadata_size = GetVerityMetadataSize(partition_size)
return 0
success, verity_metadata_size = GetVerityMetadataSize(partition_size)
if not success:
return 0
verity_size = verity_tree_size + verity_metadata_size verity_size = verity_tree_size + verity_metadata_size
if fec_supported: if fec_supported:
success, fec_size = GetVerityFECSize(partition_size + verity_size) fec_size = GetVerityFECSize(partition_size + verity_size)
if not success:
return 0
return verity_size + fec_size return verity_size + fec_size
return verity_size return verity_size
def GetDiskUsage(path): def GetDiskUsage(path):
"""Return number of bytes that "path" occupies on host. """Returns the number of bytes that "path" occupies on host.
Args: Args:
path: The directory or file to calculate size on path: The directory or file to calculate size on
Returns: Returns:
True and the number of bytes if successful, The number of bytes.
False and 0 otherwise.
Raises:
BuildImageError: On error.
""" """
env = {"POSIXLY_CORRECT": "1"} env = {"POSIXLY_CORRECT": "1"}
cmd = ["du", "-s", path] cmd = ["du", "-s", path]
output, exit_code = RunCommand(cmd, verbose=False, env=env) output, exit_code = RunCommand(cmd, verbose=False, env=env)
if exit_code != 0: if exit_code != 0:
return False, 0 raise BuildImageError("Failed to get disk usage:\n{}".format(output))
# POSIX du returns number of blocks with block size 512 # POSIX du returns number of blocks with block size 512
return True, int(output.split()[0]) * 512 return int(output.split()[0]) * 512
def GetSimgSize(image_file): def GetSimgSize(image_file):
@@ -153,17 +157,24 @@ def AVBCalcMaxImageSize(avbtool, footer_type, partition_size, additional_args):
or "avbtool add_hashtree_footer". or "avbtool add_hashtree_footer".
Returns: Returns:
The maximum image size or 0 if an error occurred. The maximum image size.
Raises:
BuildImageError: On error or getting invalid image size.
""" """
cmd = [avbtool, "add_%s_footer" % footer_type, cmd = [avbtool, "add_%s_footer" % footer_type,
"--partition_size", str(partition_size), "--calc_max_image_size"] "--partition_size", str(partition_size), "--calc_max_image_size"]
cmd.extend(shlex.split(additional_args)) cmd.extend(shlex.split(additional_args))
(output, exit_code) = RunCommand(cmd) output, exit_code = RunCommand(cmd)
if exit_code != 0: if exit_code != 0:
return 0 raise BuildImageError(
else: "Failed to calculate max image size:\n{}".format(output))
return int(output) image_size = int(output)
if image_size <= 0:
raise BuildImageError(
"Invalid max image size: {}".format(output))
return image_size
def AVBCalcMinPartitionSize(image_size, size_calculator): def AVBCalcMinPartitionSize(image_size, size_calculator):
@@ -240,8 +251,8 @@ def AVBAddFooter(image_path, avbtool, footer_type, partition_size,
additional_args: Additional arguments to pass to "avbtool add_hash_footer" additional_args: Additional arguments to pass to "avbtool add_hash_footer"
or "avbtool add_hashtree_footer". or "avbtool add_hashtree_footer".
Returns: Raises:
True if the operation succeeded. BuildImageError: On error.
""" """
cmd = [avbtool, "add_%s_footer" % footer_type, cmd = [avbtool, "add_%s_footer" % footer_type,
"--partition_size", partition_size, "--partition_size", partition_size,
@@ -257,9 +268,8 @@ def AVBAddFooter(image_path, avbtool, footer_type, partition_size,
output, exit_code = RunCommand(cmd) output, exit_code = RunCommand(cmd)
if exit_code != 0: if exit_code != 0:
print("Failed to add AVB footer! Error: %s" % output) raise BuildImageError(
return False "Failed to add AVB footer:\n{}".format(output))
return True
def AdjustPartitionSizeForVerity(partition_size, fec_supported): def AdjustPartitionSizeForVerity(partition_size, fec_supported):
@@ -316,9 +326,8 @@ def BuildVerityFEC(sparse_image_path, verity_path, verity_fec_path,
verity_path, verity_fec_path] verity_path, verity_fec_path]
output, exit_code = RunCommand(cmd) output, exit_code = RunCommand(cmd)
if exit_code != 0: if exit_code != 0:
print("Could not build FEC data! Error: %s" % output) raise BuildImageError(
return False "Failed to build FEC data:\n{}".format(output))
return True
def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict): def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict):
@@ -326,12 +335,11 @@ def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict):
verity_image_path] verity_image_path]
output, exit_code = RunCommand(cmd) output, exit_code = RunCommand(cmd)
if exit_code != 0: if exit_code != 0:
print("Could not build verity tree! Error: %s" % output) raise BuildImageError(
return False "Failed to build verity tree:\n{}".format(output))
root, salt = output.split() root, salt = output.split()
prop_dict["verity_root_hash"] = root prop_dict["verity_root_hash"] = root
prop_dict["verity_salt"] = salt prop_dict["verity_salt"] = salt
return True
def BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt, def BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt,
@@ -345,9 +353,8 @@ def BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt,
cmd.append("--verity_disable") cmd.append("--verity_disable")
output, exit_code = RunCommand(cmd) output, exit_code = RunCommand(cmd)
if exit_code != 0: if exit_code != 0:
print("Could not build verity metadata! Error: %s" % output) raise BuildImageError(
return False "Failed to build verity metadata:\n{}".format(output))
return True
def Append2Simg(sparse_image_path, unsparse_image_path, error_message): def Append2Simg(sparse_image_path, unsparse_image_path, error_message):
@@ -356,49 +363,45 @@ def Append2Simg(sparse_image_path, unsparse_image_path, error_message):
Args: Args:
sparse_image_path: the path to the (sparse) image sparse_image_path: the path to the (sparse) image
unsparse_image_path: the path to the (unsparse) image unsparse_image_path: the path to the (unsparse) image
Returns:
True on success, False on failure. Raises:
BuildImageError: On error.
""" """
cmd = ["append2simg", sparse_image_path, unsparse_image_path] cmd = ["append2simg", sparse_image_path, unsparse_image_path]
output, exit_code = RunCommand(cmd) output, exit_code = RunCommand(cmd)
if exit_code != 0: if exit_code != 0:
print("%s: %s" % (error_message, output)) raise BuildImageError("{}:\n{}".format(error_message, output))
return False
return True
def Append(target, file_to_append, error_message): def Append(target, file_to_append, error_message):
"""Appends file_to_append to target.""" """Appends file_to_append to target.
Raises:
BuildImageError: On error.
"""
try: try:
with open(target, "a") as out_file, open(file_to_append, "r") as input_file: with open(target, "a") as out_file, open(file_to_append, "r") as input_file:
for line in input_file: for line in input_file:
out_file.write(line) out_file.write(line)
except IOError: except IOError:
print(error_message) raise BuildImageError(error_message)
return False
return True
def BuildVerifiedImage(data_image_path, verity_image_path, def BuildVerifiedImage(data_image_path, verity_image_path,
verity_metadata_path, verity_fec_path, verity_metadata_path, verity_fec_path,
padding_size, fec_supported): padding_size, fec_supported):
if not Append(verity_image_path, verity_metadata_path, Append(
"Could not append verity metadata!"): verity_image_path, verity_metadata_path,
return False "Could not append verity metadata!")
if fec_supported: if fec_supported:
# build FEC for the entire partition, including metadata # Build FEC for the entire partition, including metadata.
if not BuildVerityFEC(data_image_path, verity_image_path, BuildVerityFEC(
verity_fec_path, padding_size): data_image_path, verity_image_path, verity_fec_path, padding_size)
return False Append(verity_image_path, verity_fec_path, "Could not append FEC!")
if not Append(verity_image_path, verity_fec_path, "Could not append FEC!"): Append2Simg(
return False data_image_path, verity_image_path, "Could not append verity data!")
if not Append2Simg(data_image_path, verity_image_path,
"Could not append verity data!"):
return False
return True
def UnsparseImage(sparse_image_path, replace=True): def UnsparseImage(sparse_image_path, replace=True):
@@ -409,15 +412,15 @@ def UnsparseImage(sparse_image_path, replace=True):
if replace: if replace:
os.unlink(unsparse_image_path) os.unlink(unsparse_image_path)
else: else:
return True, unsparse_image_path return unsparse_image_path
inflate_command = ["simg2img", sparse_image_path, unsparse_image_path] inflate_command = ["simg2img", sparse_image_path, unsparse_image_path]
(inflate_output, exit_code) = RunCommand(inflate_command) inflate_output, exit_code = RunCommand(inflate_command)
if exit_code != 0: if exit_code != 0:
print("Error: '%s' failed with exit code %d:\n%s" % (
inflate_command, exit_code, inflate_output))
os.remove(unsparse_image_path) os.remove(unsparse_image_path)
return False, None raise BuildImageError(
return True, unsparse_image_path "Error: '{}' failed with exit code {}:\n{}".format(
inflate_command, exit_code, inflate_output))
return unsparse_image_path
def MakeVerityEnabledImage(out_file, fec_supported, prop_dict): def MakeVerityEnabledImage(out_file, fec_supported, prop_dict):
@@ -427,8 +430,10 @@ def MakeVerityEnabledImage(out_file, fec_supported, prop_dict):
out_file: the location to write the verifiable image at out_file: the location to write the verifiable image at
prop_dict: a dictionary of properties required for image creation and prop_dict: a dictionary of properties required for image creation and
verification verification
Returns:
True on success, False otherwise. Raises:
AssertionError: On invalid partition sizes.
BuildImageError: On other errors.
""" """
# get properties # get properties
image_size = int(prop_dict["image_size"]) image_size = int(prop_dict["image_size"])
@@ -440,50 +445,44 @@ def MakeVerityEnabledImage(out_file, fec_supported, prop_dict):
signer_path = prop_dict["verity_signer_cmd"] signer_path = prop_dict["verity_signer_cmd"]
signer_args = OPTIONS.verity_signer_args signer_args = OPTIONS.verity_signer_args
# make a tempdir
tempdir_name = common.MakeTempDir(suffix="_verity_images") tempdir_name = common.MakeTempDir(suffix="_verity_images")
# get partial image paths # Get partial image paths.
verity_image_path = os.path.join(tempdir_name, "verity.img") verity_image_path = os.path.join(tempdir_name, "verity.img")
verity_metadata_path = os.path.join(tempdir_name, "verity_metadata.img") verity_metadata_path = os.path.join(tempdir_name, "verity_metadata.img")
verity_fec_path = os.path.join(tempdir_name, "verity_fec.img") verity_fec_path = os.path.join(tempdir_name, "verity_fec.img")
# build the verity tree and get the root hash and salt # Build the verity tree and get the root hash and salt.
if not BuildVerityTree(out_file, verity_image_path, prop_dict): BuildVerityTree(out_file, verity_image_path, prop_dict)
return False
# build the metadata blocks # Build the metadata blocks.
root_hash = prop_dict["verity_root_hash"] root_hash = prop_dict["verity_root_hash"]
salt = prop_dict["verity_salt"] salt = prop_dict["verity_salt"]
verity_disable = "verity_disable" in prop_dict verity_disable = "verity_disable" in prop_dict
if not BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt, BuildVerityMetadata(
block_dev, signer_path, signer_key, signer_args, image_size, verity_metadata_path, root_hash, salt, block_dev, signer_path,
verity_disable): signer_key, signer_args, verity_disable)
return False
# build the full verified image # Build the full verified image.
partition_size = int(prop_dict["partition_size"]) partition_size = int(prop_dict["partition_size"])
verity_size = int(prop_dict["verity_size"]) verity_size = int(prop_dict["verity_size"])
padding_size = partition_size - image_size - verity_size padding_size = partition_size - image_size - verity_size
assert padding_size >= 0 assert padding_size >= 0
if not BuildVerifiedImage(out_file, BuildVerifiedImage(
verity_image_path, out_file, verity_image_path, verity_metadata_path, verity_fec_path,
verity_metadata_path, padding_size, fec_supported)
verity_fec_path,
padding_size,
fec_supported):
return False
return True
def ConvertBlockMapToBaseFs(block_map_file): def ConvertBlockMapToBaseFs(block_map_file):
base_fs_file = common.MakeTempFile(prefix="script_gen_", suffix=".base_fs") base_fs_file = common.MakeTempFile(prefix="script_gen_", suffix=".base_fs")
convert_command = ["blk_alloc_to_base_fs", block_map_file, base_fs_file] convert_command = ["blk_alloc_to_base_fs", block_map_file, base_fs_file]
(_, exit_code) = RunCommand(convert_command) output, exit_code = RunCommand(convert_command)
return base_fs_file if exit_code == 0 else None if exit_code != 0:
raise BuildImageError(
"Failed to call blk_alloc_to_base_fs:\n{}".format(output))
return base_fs_file
def SetUpInDirAndFsConfig(origin_in, prop_dict): def SetUpInDirAndFsConfig(origin_in, prop_dict):
@@ -547,11 +546,9 @@ def CheckHeadroom(ext4fs_output, prop_dict):
ext4fs_output: The output string from mke2fs command. ext4fs_output: The output string from mke2fs command.
prop_dict: The property dict. prop_dict: The property dict.
Returns:
The check result.
Raises: Raises:
AssertionError: On invalid input. AssertionError: On invalid input.
BuildImageError: On check failure.
""" """
assert ext4fs_output is not None assert ext4fs_output is not None
assert prop_dict.get('fs_type', '').startswith('ext4') assert prop_dict.get('fs_type', '').startswith('ext4')
@@ -569,12 +566,11 @@ def CheckHeadroom(ext4fs_output, prop_dict):
adjusted_blocks = total_blocks - headroom_blocks adjusted_blocks = total_blocks - headroom_blocks
if used_blocks > adjusted_blocks: if used_blocks > adjusted_blocks:
mount_point = prop_dict["mount_point"] mount_point = prop_dict["mount_point"]
print("Error: Not enough room on %s (total: %d blocks, used: %d blocks, " raise BuildImageError(
"headroom: %d blocks, available: %d blocks)" % ( "Error: Not enough room on {} (total: {} blocks, used: {} blocks, "
mount_point, total_blocks, used_blocks, headroom_blocks, "headroom: {} blocks, available: {} blocks)".format(
adjusted_blocks)) mount_point, total_blocks, used_blocks, headroom_blocks,
return False adjusted_blocks))
return True
def BuildImage(in_dir, prop_dict, out_file, target_out=None): def BuildImage(in_dir, prop_dict, out_file, target_out=None):
@@ -590,8 +586,8 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
under system/core/libcutils) reads device specific FS config files from under system/core/libcutils) reads device specific FS config files from
there. there.
Returns: Raises:
True iff the image is built successfully. BuildImageError: On build image failures.
""" """
in_dir, fs_config = SetUpInDirAndFsConfig(in_dir, prop_dict) in_dir, fs_config = SetUpInDirAndFsConfig(in_dir, prop_dict)
@@ -620,10 +616,8 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
if (prop_dict.get("use_dynamic_partition_size") == "true" and if (prop_dict.get("use_dynamic_partition_size") == "true" and
"partition_size" not in prop_dict): "partition_size" not in prop_dict):
# if partition_size is not defined, use output of `du' + reserved_size # If partition_size is not defined, use output of `du' + reserved_size.
success, size = GetDiskUsage(in_dir) size = GetDiskUsage(in_dir)
if not success:
return False
if OPTIONS.verbose: if OPTIONS.verbose:
print("The tree size of %s is %d MB." % (in_dir, size // BYTES_IN_MB)) print("The tree size of %s is %d MB." % (in_dir, size // BYTES_IN_MB))
size += int(prop_dict.get("partition_reserved_size", 0)) size += int(prop_dict.get("partition_reserved_size", 0))
@@ -647,8 +641,6 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
partition_size = int(prop_dict.get("partition_size")) partition_size = int(prop_dict.get("partition_size"))
image_size, verity_size = AdjustPartitionSizeForVerity( image_size, verity_size = AdjustPartitionSizeForVerity(
partition_size, verity_fec_supported) partition_size, verity_fec_supported)
if not image_size:
return False
prop_dict["image_size"] = str(image_size) prop_dict["image_size"] = str(image_size)
prop_dict["verity_size"] = str(verity_size) prop_dict["verity_size"] = str(verity_size)
@@ -656,11 +648,8 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
if avb_footer_type: if avb_footer_type:
partition_size = prop_dict["partition_size"] partition_size = prop_dict["partition_size"]
# avb_add_hash_footer_args or avb_add_hashtree_footer_args. # avb_add_hash_footer_args or avb_add_hashtree_footer_args.
max_image_size = AVBCalcMaxImageSize(avbtool, avb_footer_type, max_image_size = AVBCalcMaxImageSize(
partition_size, avb_signing_args) avbtool, avb_footer_type, partition_size, avb_signing_args)
if max_image_size <= 0:
print("AVBCalcMaxImageSize is <= 0: %d" % max_image_size)
return False
prop_dict["image_size"] = str(max_image_size) prop_dict["image_size"] = str(max_image_size)
if fs_type.startswith("ext"): if fs_type.startswith("ext"):
@@ -683,8 +672,6 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
build_command.extend(["-B", prop_dict["block_list"]]) build_command.extend(["-B", prop_dict["block_list"]])
if "base_fs_file" in prop_dict: if "base_fs_file" in prop_dict:
base_fs_file = ConvertBlockMapToBaseFs(prop_dict["base_fs_file"]) base_fs_file = ConvertBlockMapToBaseFs(prop_dict["base_fs_file"])
if base_fs_file is None:
return False
build_command.extend(["-d", base_fs_file]) build_command.extend(["-d", base_fs_file])
build_command.extend(["-L", prop_dict["mount_point"]]) build_command.extend(["-L", prop_dict["mount_point"]])
if "extfs_inode_count" in prop_dict: if "extfs_inode_count" in prop_dict:
@@ -742,16 +729,17 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
build_command.extend(["-T", str(prop_dict["timestamp"])]) build_command.extend(["-T", str(prop_dict["timestamp"])])
build_command.extend(["-L", prop_dict["mount_point"]]) build_command.extend(["-L", prop_dict["mount_point"]])
else: else:
print("Error: unknown filesystem type '%s'" % (fs_type)) raise BuildImageError(
return False "Error: unknown filesystem type: {}".format(fs_type))
(mkfs_output, exit_code) = RunCommand(build_command) mkfs_output, exit_code = RunCommand(build_command)
if exit_code != 0: if exit_code != 0:
print("Error: '%s' failed with exit code %d:\n%s" % ( try:
build_command, exit_code, mkfs_output)) du = GetDiskUsage(in_dir)
success, du = GetDiskUsage(in_dir) du_str = "{} bytes ({} MB)".format(du, du // BYTES_IN_MB)
du_str = ("%d bytes (%d MB)" % (du, du // BYTES_IN_MB) except BuildImageError as e:
) if success else "unknown" print(e, file=sys.stderr)
du_str = "unknown"
print( print(
"Out of space? The tree size of {} is {}, with reserved space of {} " "Out of space? The tree size of {} is {}, with reserved space of {} "
"bytes ({} MB).".format( "bytes ({} MB).".format(
@@ -765,28 +753,29 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
int(prop_dict["image_size"]) // BYTES_IN_MB, int(prop_dict["image_size"]) // BYTES_IN_MB,
int(prop_dict["partition_size"]), int(prop_dict["partition_size"]),
int(prop_dict["partition_size"]) // BYTES_IN_MB)) int(prop_dict["partition_size"]) // BYTES_IN_MB))
return False
raise BuildImageError(
"Error: '{}' failed with exit code {}:\n{}".format(
build_command, exit_code, mkfs_output))
# Check if there's enough headroom space available for ext4 image. # Check if there's enough headroom space available for ext4 image.
if "partition_headroom" in prop_dict and fs_type.startswith("ext4"): if "partition_headroom" in prop_dict and fs_type.startswith("ext4"):
if not CheckHeadroom(mkfs_output, prop_dict): CheckHeadroom(mkfs_output, prop_dict)
return False
if not fs_spans_partition: if not fs_spans_partition:
mount_point = prop_dict.get("mount_point") mount_point = prop_dict.get("mount_point")
image_size = int(prop_dict["image_size"]) image_size = int(prop_dict["image_size"])
sparse_image_size = GetSimgSize(out_file) sparse_image_size = GetSimgSize(out_file)
if sparse_image_size > image_size: if sparse_image_size > image_size:
print("Error: %s image size of %d is larger than partition size of " raise BuildImageError(
"%d" % (mount_point, sparse_image_size, image_size)) "Error: {} image size of {} is larger than partition size of "
return False "{}".format(mount_point, sparse_image_size, image_size))
if verity_supported and is_verity_partition: if verity_supported and is_verity_partition:
ZeroPadSimg(out_file, image_size - sparse_image_size) ZeroPadSimg(out_file, image_size - sparse_image_size)
# Create the verified image if this is to be verified. # Create the verified image if this is to be verified.
if verity_supported and is_verity_partition: if verity_supported and is_verity_partition:
if not MakeVerityEnabledImage(out_file, verity_fec_supported, prop_dict): MakeVerityEnabledImage(out_file, verity_fec_supported, prop_dict)
return False
# Add AVB HASH or HASHTREE footer (metadata). # Add AVB HASH or HASHTREE footer (metadata).
if avb_footer_type: if avb_footer_type:
@@ -796,30 +785,25 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
key_path = prop_dict.get("avb_key_path") key_path = prop_dict.get("avb_key_path")
algorithm = prop_dict.get("avb_algorithm") algorithm = prop_dict.get("avb_algorithm")
salt = prop_dict.get("avb_salt") salt = prop_dict.get("avb_salt")
if not AVBAddFooter(out_file, avbtool, avb_footer_type, AVBAddFooter(
partition_size, partition_name, key_path, out_file, avbtool, avb_footer_type, partition_size, partition_name,
algorithm, salt, avb_signing_args): key_path, algorithm, salt, avb_signing_args)
return False
if run_e2fsck and prop_dict.get("skip_fsck") != "true": if run_e2fsck and prop_dict.get("skip_fsck") != "true":
success, unsparse_image = UnsparseImage(out_file, replace=False) unsparse_image = UnsparseImage(out_file, replace=False)
if not success:
return False
# Run e2fsck on the inflated image file # Run e2fsck on the inflated image file
e2fsck_command = ["e2fsck", "-f", "-n", unsparse_image] e2fsck_command = ["e2fsck", "-f", "-n", unsparse_image]
# TODO(b/112062612): work around e2fsck failure with SANITIZE_HOST=address # TODO(b/112062612): work around e2fsck failure with SANITIZE_HOST=address
env4e2fsck = {"ASAN_OPTIONS": "detect_odr_violation=0"} env4e2fsck = {"ASAN_OPTIONS": "detect_odr_violation=0"}
(e2fsck_output, exit_code) = RunCommand(e2fsck_command, env=env4e2fsck) e2fsck_output, exit_code = RunCommand(e2fsck_command, env=env4e2fsck)
os.remove(unsparse_image) os.remove(unsparse_image)
if exit_code != 0: if exit_code != 0:
print("Error: '%s' failed with exit code %d:\n%s" % ( raise BuildImageError(
e2fsck_command, exit_code, e2fsck_output)) "Error: '{}' failed with exit code {}:\n{}".format(
return False e2fsck_command, exit_code, e2fsck_output))
return True
def ImagePropFromGlobalDict(glob_dict, mount_point): def ImagePropFromGlobalDict(glob_dict, mount_point):
@@ -1110,10 +1094,12 @@ def main(argv):
image_properties = ImagePropFromGlobalDict(glob_dict, mount_point) image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
if not BuildImage(in_dir, image_properties, out_file, target_out): try:
print("error: failed to build %s from %s" % (out_file, in_dir), BuildImage(in_dir, image_properties, out_file, target_out)
except:
print("Error: Failed to build {} from {}".format(out_file, in_dir),
file=sys.stderr) file=sys.stderr)
sys.exit(1) raise
if prop_file_out: if prop_file_out:
glob_dict_out = GlobalDictFromImageProp(image_properties, mount_point) glob_dict_out = GlobalDictFromImageProp(image_properties, mount_point)

View File

@@ -22,8 +22,8 @@ import unittest
import common import common
from build_image import ( from build_image import (
AVBCalcMinPartitionSize, BLOCK_SIZE, AVBCalcMinPartitionSize, BLOCK_SIZE, BuildImageError, CheckHeadroom,
CheckHeadroom, RunCommand, SetUpInDirAndFsConfig) RunCommand, SetUpInDirAndFsConfig)
class BuildImageTest(unittest.TestCase): class BuildImageTest(unittest.TestCase):
@@ -49,7 +49,7 @@ class BuildImageTest(unittest.TestCase):
'partition_headroom' : '4096000', 'partition_headroom' : '4096000',
'mount_point' : 'system', 'mount_point' : 'system',
} }
self.assertTrue(CheckHeadroom(self.EXT4FS_OUTPUT, prop_dict)) CheckHeadroom(self.EXT4FS_OUTPUT, prop_dict)
def test_CheckHeadroom_InsufficientHeadroom(self): def test_CheckHeadroom_InsufficientHeadroom(self):
# Required headroom: 1001 blocks. # Required headroom: 1001 blocks.
@@ -58,7 +58,8 @@ class BuildImageTest(unittest.TestCase):
'partition_headroom' : '4100096', 'partition_headroom' : '4100096',
'mount_point' : 'system', 'mount_point' : 'system',
} }
self.assertFalse(CheckHeadroom(self.EXT4FS_OUTPUT, prop_dict)) self.assertRaises(
BuildImageError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
def test_CheckHeadroom_WrongFsType(self): def test_CheckHeadroom_WrongFsType(self):
prop_dict = { prop_dict = {
@@ -98,14 +99,14 @@ class BuildImageTest(unittest.TestCase):
'partition_headroom' : '40960', 'partition_headroom' : '40960',
'mount_point' : 'system', 'mount_point' : 'system',
} }
self.assertTrue(CheckHeadroom(ext4fs_output, prop_dict)) CheckHeadroom(ext4fs_output, prop_dict)
prop_dict = { prop_dict = {
'fs_type' : 'ext4', 'fs_type' : 'ext4',
'partition_headroom' : '413696', 'partition_headroom' : '413696',
'mount_point' : 'system', 'mount_point' : 'system',
} }
self.assertFalse(CheckHeadroom(ext4fs_output, prop_dict)) self.assertRaises(BuildImageError, CheckHeadroom, ext4fs_output, prop_dict)
def test_SetUpInDirAndFsConfig_SystemRootImageTrue_NonSystem(self): def test_SetUpInDirAndFsConfig_SystemRootImageTrue_NonSystem(self):
prop_dict = { prop_dict = {

View File

@@ -139,8 +139,7 @@ class ValidateTargetFilesTest(unittest.TestCase):
'verity_signer_cmd' : 'verity_signer', 'verity_signer_cmd' : 'verity_signer',
'verity_size' : str(verity_size), 'verity_size' : str(verity_size),
} }
self.assertTrue( build_image.MakeVerityEnabledImage(output_file, verity_fec, prop_dict)
build_image.MakeVerityEnabledImage(output_file, verity_fec, prop_dict))
def test_ValidateVerifiedBootImages_systemImage(self): def test_ValidateVerifiedBootImages_systemImage(self):
input_tmp = common.MakeTempDir() input_tmp = common.MakeTempDir()