#!/usr/bin/python3 import os import re import shutil import tarfile import lzma as xz import fileinput from argparse import ArgumentParser import json import types from utils import Utils import ovagenerator def createOutputArtifact(raw_image_path, config, src_root, tools_bin_path): photon_release_ver = os.environ['PHOTON_RELEASE_VER'] photon_build_num = os.environ['PHOTON_BUILD_NUM'] image_name = config.get('image_name', 'photon-' + config['image_type'] + '-' + photon_release_ver + '-' + photon_build_num) photon_docker_image = config['installer'].get('photon_docker_image', 'photon:latest') new_name = [] if type(raw_image_path) is not list: raw_image_path = [raw_image_path] img_path = os.path.dirname(os.path.realpath(raw_image_path[0])) # Rename gce image to disk.raw if config['image_type'] == "gce": new_name.append(img_path + '/disk.raw') else: for img_num in range(len(raw_image_path)): new_name.append(img_path + '/' + image_name + '' + str(img_num) + '.raw') for img_num, raw_img in enumerate(raw_image_path): shutil.move(raw_img, new_name[img_num]) raw_image = new_name compressed = True # Only for artifactype='ova', multidisk support is applicable # For other artifacttype, only one disk support (i.e. raw_image[0]) if config['artifacttype'] == 'tgz': print("Generating the tar.gz artifact ...") outputfile = (img_path + '/' + image_name + '.tar.gz') compressed = generateCompressedFile(raw_image[0], outputfile, "w:gz") elif config['artifacttype'] == 'xz': print("Generating the xz artifact ...") outputfile = (img_path + '/' + image_name + '.xz') compressed = generateCompressedFile(raw_image[0], outputfile, "w:xz") elif 'vhd' in config['artifacttype']: relrawpath = os.path.relpath(raw_image[0], src_root) vhdname = ('/' + image_name + '.vhd') dockerenv = False print("check if inside docker env") if Utils.runshellcommand("grep -c docker /proc/self/cgroup || :").rstrip() != '0': dockerenv = True print("Converting raw disk to vhd ...") cmd = "tdnf install -y qemu-img > /dev/null 2>&1; qemu-img info -f raw --output json {}" if not dockerenv: cmd = "docker run -v {}:/mnt:rw {} /bin/bash -c '" + cmd + "'" cmd = cmd.format(src_root, photon_docker_image, '/mnt/' + relrawpath) else: cmd = cmd.format(raw_image[0]) info_output = Utils.runshellcommand(cmd) mbsize = 1024 * 1024 mbroundedsize = ((int(json.loads(info_output)["virtual-size"])/mbsize + 1) * mbsize) cmd = "tdnf install -y qemu-img > /dev/null 2>&1; qemu-img resize -f raw {} {}" if not dockerenv: cmd = "docker run -v {}:/mnt:rw {} /bin/bash -c '" + cmd + "'" cmd = cmd.format(src_root, photon_docker_image, '/mnt/' + relrawpath, mbroundedsize) else: cmd = cmd.format(raw_image[0], mbroundedsize) Utils.runshellcommand(cmd) cmd = "tdnf install -y qemu-img > /dev/null 2>&1; qemu-img convert {} -O " + \ "vpc -o subformat=fixed,force_size {}" if not dockerenv: cmd = "docker run -v {}:/mnt:rw {} /bin/bash -c '" + cmd + "'" cmd = cmd.format(src_root, photon_docker_image, '/mnt/' + relrawpath, '/mnt/' + os.path.dirname(relrawpath) + vhdname) else: cmd = cmd.format(raw_image[0], os.path.dirname(raw_image[0]) + vhdname) Utils.runshellcommand(cmd) if config['artifacttype'] == 'vhd.gz': outputfile = (img_path + '/' + image_name + '.vhd.tar.gz') compressed = generateCompressedFile(img_path + vhdname, outputfile, "w:gz") # remove raw image and call the vhd as raw image os.remove(raw_image[0]) raw_image = img_path + vhdname elif config['artifacttype'] == 'ova': ovagenerator.create_ova_image(raw_image, tools_bin_path, config) elif config['artifacttype'] == 'raw': pass else: raise ValueError("Unknown output format") if not compressed: print("ERROR: Image compression failed!") # Leave the raw disk around if compression failed return if not config['keeprawdisk']: if type(raw_image) is list: for raw_img in raw_image: os.remove(raw_img) else: os.remove(raw_image) def generateCompressedFile(inputfile, outputfile, formatstring): try: if formatstring == "w:xz": in_file = open(inputfile, 'rb') in_data = in_file.read() out_file = open(inputfile+".xz", 'wb') out_file.write(xz.compress(in_data)) in_file.close() out_file.close() else: tarout = tarfile.open(outputfile, formatstring) tarout.add(inputfile, arcname=os.path.basename(inputfile)) tarout.close() except Exception as e: print(e) return False return True if __name__ == '__main__': parser = ArgumentParser() parser.add_argument("-r", "--raw-image-path", dest="raw_image_path") parser.add_argument("-c", "--config-path", dest="config_path") parser.add_argument("-t", "--tools-bin-path", dest="tools_bin_path") parser.add_argument("-s", "--src-root", dest="src_root") options = parser.parse_args() if options.config_path: config = Utils.jsonread(options.config_path) else: raise Exception("No config file defined") createOutputArtifact( options.raw_image_path, config, options.src_root, options.tools_bin_path )