diff options
Diffstat (limited to 'images/package_images.py')
| -rw-r--r-- | images/package_images.py | 105 | 
1 files changed, 90 insertions, 15 deletions
| diff --git a/images/package_images.py b/images/package_images.py index 3bbeac49c..d34e183fe 100644 --- a/images/package_images.py +++ b/images/package_images.py @@ -26,7 +26,28 @@ from image_package_mapping import PACKAGE_MAPPING  def parse_args():      """Setup argument parser and parse""" -    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) +    description = """UHD Image Packaging + +    Packages the contents of the current directory into archives within a directory structure that +    matches the Ettus fileserver. It also produces files containing the MD5 checksums of all image +    files, as well as a file containing the SHA256 checksums of all archive files created. + +    The script will also modify a manifest file with the information from the generated image +    packages. That is, the repositories, Git hashes, and SHA256 checksums listed in the manifest +    will be updated. + +    The script will run without any commandline arguments provided. However, some useful (crucial, +    even) information will be lacking. The suggested usage is to invoke the following command from +    the directory containing the image files + +    `python package_images.py --manifest /path/to/manifest --githash <REPO>-<GITHASH>` + +    where REPO is the repository used to create the images  (ie 'fpga'), and GITHASH is the Git +    hash of that repository used to create the images. When in doubt, please check with previous +    image package listed in the manifest. +    """ +    parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, +                                     description=description)      parser.add_argument('--md5', action="store_true", default=False,                          help="Generate MD5 files")      parser.add_argument('--sha256', action="store_true", default=False, @@ -189,6 +210,8 @@ def gen_package(pkg_targets=(), repo_and_hash="", manifest_fn=""):      sha_filenames[:] = [sha_fn for sha_fn in sha_filenames if os.path.exists(sha_fn)]      gen_sha256(sha_filenames, hash_filename="hashes.txt",                 manifest_fn=manifest_fn, repo_and_hash=repo_and_hash) +    # Return the zipfiles we've created +    return sha_filenames  def list_differences(list1, list2): @@ -200,19 +223,39 @@ def list_differences(list1, list2):      return outlist1, outlist2 -def verify_package(zip_filename, pkg_target): +def get_target_name(zip_filename): +    """Return the package target that created the given zip_filename""" +    for target, target_info in PACKAGE_MAPPING.items(): +        # First we need to strip the Git hash out of the filename +        githash = re.findall(r"-g([\d\w]{7,8})", zip_filename)[0] +        stripped_filename = os.path.basename(zip_filename.replace(githash, "{}")) +        if stripped_filename == target_info.get("package_name", ""): +            return target +    # If it doesn't match any targets +    return "" + + +def verify_package(zip_filename):      """Verify the contents of the image package match the expected list of files""" +    # First, determine which target this was built for +    pkg_target = get_target_name(zip_filename) +    if not pkg_target: +        print("Error: Could not determine package from filename", +              file=sys.stderr) +        return False +      expected_filelist = PACKAGE_MAPPING[pkg_target]['files']      with zipfile.ZipFile(zip_filename, 'r') as zip_file:          actual_filelist = zip_file.namelist()      missing, extra = list_differences(expected_filelist, actual_filelist)      if missing or extra: -        print("Error: image package does not include expected files") +        print("Error: image package does not include expected files ({})".format(pkg_target), +              file=sys.stderr)          if missing: -            print("Missing files: {}".format(missing)) +            print("Missing files: {}".format(missing), file=sys.stderr)          if extra: -            print("Extra files: {}".format(extra)) +            print("Extra files: {}".format(extra), file=sys.stderr)          return False      return True @@ -222,12 +265,27 @@ def edit_manifest_line(line, new_repo_and_hash, new_hashes_dict):      # Check each value in your dictionary of new hashes      for filename, new_hash in new_hashes_dict.items():          # If the filename with a new hash shows up in the line -        if filename in line: +        # Note: the filename has a Git hash in it, so we need to peel that off first +        full_filename_matches = re.findall(r"([\d\w]+)-g([\da-fA-F]{7,8})", filename) +        if full_filename_matches: +            # We don't really need to store the Git hash in the found filename +            stripped_filename, _ = full_filename_matches[0] +        else: +            return line + +        if stripped_filename in line:              # Replace the repo and git hash -            repo_and_hash = re.findall(r"[\w]+-[\da-fA-F]{7}", line) -            if repo_and_hash: -                repo_and_hash = repo_and_hash[0] -                line = line.replace(repo_and_hash, new_repo_and_hash) +            old_repo_and_hash_matches = re.findall(r"([\w]+)-([\da-fA-F]{7,8})", line) +            if old_repo_and_hash_matches: +                # If we did find a repo and Git hash on this line, replace them +                old_repo, old_githash = old_repo_and_hash_matches[0] +                old_repo_and_hash = "{}-{}".format(old_repo, old_githash) +                # We need to replace all instances <REPO>-<GITHASH> in this line +                line = line.replace(old_repo_and_hash, new_repo_and_hash) +                # We also need to replace -g<GITHASH> in the filename +                # Find the new repo and githash +                _, new_githash = re.findall(r"([\w]+)-([\da-fA-F]{7,8})", new_repo_and_hash)[0] +                line = line.replace(old_githash, new_githash)              # Replace the SHA256              sha = re.findall(r"[\da-fA-F]{64}", line) @@ -235,7 +293,7 @@ def edit_manifest_line(line, new_repo_and_hash, new_hashes_dict):                  sha = sha[0]                  line = line.replace(sha, new_hash) -            if not repo_and_hash or not sha: +            if not old_repo_and_hash_matches or not sha:                  print("Error: repo, hash or SHA missing in line with new file")                  print("Line: {}", format(line))              # If we found and replaced info, return the edited line @@ -248,6 +306,7 @@ def edit_manifest(manifest_fn, new_repo_and_hash, new_hash_dict):      """Edit the provided manifest file to update the githash and SHA256"""      with tempfile.NamedTemporaryFile(mode='w', dir='.', delete=False) as tmp_manifest, \              open(manifest_fn, 'r') as old_manifest: +        print("Trying to edit manifest with new repo and Git hash {}".format(new_repo_and_hash))          # Check each line in the manifest file          for line in old_manifest:              # If needed, put the new info in the line @@ -270,8 +329,12 @@ def determine_targets():          required_files = copy.deepcopy(target_info['files'])          required_files[:] = [filename for filename in required_files if '.md5' not in filename] -        if all([os.path.exists(img_file) for img_file in required_files]): +        check_required_files = [os.path.exists(img_file) for img_file in required_files] +        if all(check_required_files):              found_targets.append(target) +        elif any(check_required_files): +            print("Not all package contents present for {}".format(target), +                  file=sys.stderr)      return found_targets @@ -280,15 +343,27 @@ def main():      args = parse_args()      if args.md5 or args.sha256 or args.files or args.output:          print("Unsupported argument: only --pkg_targets is currently supported.") +    # Check the provided Git hash +    if not args.githash: +        print("Please provide --githash `<REPO>-<GITHASH>'") +        return False +    elif not re.findall(r"[\d\w]+-[\d\w]{7,8}", args.githash): +        print("--githash does not match expected form. Should be `<REPO>-<GITHASH>'") +        return False +      if args.targets:          pkg_targets = [ss.strip() for ss in args.targets.split(',')]      else:          pkg_targets = determine_targets()          print("Targets to package:\n{}".format(              "\n".join("--{}".format(pkg) for pkg in pkg_targets))) -    gen_package(pkg_targets=pkg_targets, repo_and_hash=args.githash, manifest_fn=args.manifest) -    return True + +    zip_filenames = gen_package(pkg_targets=pkg_targets, +                                repo_and_hash=args.githash, +                                manifest_fn=args.manifest) +    check_zips = [verify_package(zip_filename) for zip_filename in zip_filenames] +    return all(check_zips)  if __name__ == "__main__": -    sys.exit(main()) +    sys.exit(not main()) | 
