#! /usr/bin/python3 # # Copyright (C) 2015 vmware inc. # # Author: Mahmoud Bassiouny from argparse import ArgumentParser from installer import Installer import crypt import random import string import subprocess import sys import os from jsonwrapper import JsonWrapper from packageselector import PackageSelector def query_yes_no(question, default="no"): valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} if default is None: prompt = " [y/n] " elif default == "yes": prompt = " [Y/n] " elif default == "no": prompt = " [y/N] " else: raise ValueError("invalid default answer: '%s'" % default) while True: sys.stdout.write(question + prompt) choice = raw_input().lower().strip() if default is not None and choice == '': return valid[default] elif choice in valid: return valid[choice] else: sys.stdout.write("Please respond with 'yes' or 'no' " "(or 'y' or 'n').\n") def create_vmdk_and_partition(config, vmdk_path): partitions_data = {} firmware = "bios" if 'boot' in config and config['boot'] == 'efi': firmware = "efi" process = subprocess.Popen(['./mk-setup-vmdk.sh', '-rp', config['size']['root'], '-sp', config['size']['swap'], '-n', vmdk_path, '-fm', firmware, '-m'], stdout=subprocess.PIPE) count = 0 while True: line = process.stdout.readline().decode() if line == '': retval = process.poll() if retval is not None: break sys.stdout.write(line) if line.startswith("DISK_DEVICE="): partitions_data['disk'] = line.replace("DISK_DEVICE=", "").strip() count += 1 elif line.startswith("ROOT_PARTITION="): partitions_data['root'] = line.replace("ROOT_PARTITION=", "").strip() partitions_data['boot'] = partitions_data['root'] partitions_data['bootdirectory'] = '/boot/' count += 1 if count == 2: partitions_data['partitions'] = [{'path': partitions_data['root'], 'mountpoint': '/', 'filesystem': 'ext4'}] return partitions_data, count == 2 def get_file_name_with_last_folder(filename): basename = os.path.basename(filename) dirname = os.path.dirname(filename) lastfolder = os.path.basename(dirname) name = os.path.join(lastfolder, basename) return name def create_pkg_list_to_copy_to_iso(build_install_option, output_data_path): json_wrapper_option_list = JsonWrapper(build_install_option) option_list_json = json_wrapper_option_list.read() options_sorted = option_list_json.items() packages = [] for install_option in options_sorted: if install_option[0] != "iso": file_path = os.path.join(output_data_path, install_option[1]["file"]) json_wrapper_package_list = JsonWrapper(file_path) package_list_json = json_wrapper_package_list.read() packages = packages + package_list_json["packages"] return packages #copy_flags 1: add the rpm file for the package # 2: add debuginfo rpm file for the package. # 4: add src rpm file for the package def create_rpm_list_to_be_copied_to_iso(pkg_to_rpm_map_file, build_install_option, copy_flags, output_data_path): packages = [] if build_install_option is None: packages = [] else: packages = create_pkg_list_to_copy_to_iso(build_install_option, output_data_path) rpm_list = [] json_pkg_to_rpm_map = JsonWrapper(pkg_to_rpm_map_file) pkg_to_rpm_map = json_pkg_to_rpm_map.read() for k in pkg_to_rpm_map: if build_install_option is None or k in packages: if not pkg_to_rpm_map[k]['rpm'] is None and bool(copy_flags & 1): filename = pkg_to_rpm_map[k]['rpm'] rpm_list.append(get_file_name_with_last_folder(filename)) if not pkg_to_rpm_map[k]['debugrpm'] is None and bool(copy_flags & 2): filename = pkg_to_rpm_map[k]['debugrpm'] rpm_list.append(pkg_to_rpm_map[k]['debugrpm']) if not pkg_to_rpm_map[k]['sourcerpm'] is None and bool(copy_flags & 4): rpm_list.append(pkg_to_rpm_map[k]['sourcerpm']) return rpm_list def create_additional_file_list_to_copy_in_iso(base_path, build_install_option): json_wrapper_option_list = JsonWrapper(build_install_option) option_list_json = json_wrapper_option_list.read() options_sorted = option_list_json.items() file_list = [] for install_option in options_sorted: if "additional-files" in install_option[1]: file_list = file_list + list(map( lambda filename: os.path.join(base_path, filename), install_option[1].get("additional-files"))) return file_list def get_live_cd_status_string(build_install_option): json_wrapper_option_list = JsonWrapper(build_install_option) option_list_json = json_wrapper_option_list.read() options_sorted = option_list_json.items() file_list = [] for install_option in options_sorted: if "live-cd" in install_option[1]: if install_option[1].get("live-cd") == True: return "true" return "false" def make_src_iso(working_directory, src_iso_path, rpm_list): if os.path.isdir(working_directory): process = subprocess.Popen(['rm', '-rf', working_directory]) retval = process.wait() process = subprocess.Popen(['mkdir', '-p', os.path.join(working_directory, "SRPMS")]) retval = process.wait() for aaa in rpm_list: if os.path.isfile(aaa): process = subprocess.Popen(['cp', aaa, os.path.join(working_directory, "SRPMS")]) retval = process.wait() process = subprocess.Popen(['mkisofs', '-r', '-o', src_iso_path, working_directory]) retval = process.wait() process = subprocess.Popen(['rm', '-rf', options.working_directory]) retval = process.wait() def make_debug_iso(working_directory, debug_iso_path, rpm_list): if os.path.isdir(working_directory): process = subprocess.Popen(['rm', '-rf', working_directory]) retval = process.wait() process = subprocess.Popen(['mkdir', '-p', os.path.join(working_directory, "DEBUGRPMS")]) retval = process.wait() for aaa in rpm_list: if os.path.isfile(aaa): dirname = os.path.dirname(aaa) lastfolder = os.path.basename(dirname) dest_working_directory = os.path.join(working_directory, "DEBUGRPMS", lastfolder) if not os.path.isdir(dest_working_directory): process = subprocess.Popen(['mkdir', dest_working_directory]) retval = process.wait() process = subprocess.Popen(['cp', aaa, dest_working_directory]) retval = process.wait() process = subprocess.Popen(['mkisofs', '-r', '-o', debug_iso_path, working_directory]) retval = process.wait() process = subprocess.Popen(['rm', '-rf', options.working_directory]) retval = process.wait() if __name__ == '__main__': usage = "Usage: %prog [options] " parser = ArgumentParser(usage) parser.add_argument("-i", "--iso-path", dest="iso_path") parser.add_argument("-j", "--src-iso-path", dest="src_iso_path") parser.add_argument("-k", "--debug-iso-path", dest="debug_iso_path") parser.add_argument("-v", "--vmdk-path", dest="vmdk_path") parser.add_argument("-w", "--working-directory", dest="working_directory", default="/mnt/photon-root") parser.add_argument("-l", "--log-path", dest="log_path", default="../stage/LOGS") parser.add_argument("-r", "--rpm-path", dest="rpm_path", default="../stage/RPMS") parser.add_argument("-x", "--srpm-path", dest="srpm_path", default="../stage/SRPMS") parser.add_argument("-o", "--output-data-path", dest="output_data_path", default="../stage/common/data/") parser.add_argument("-f", "--force", action="store_true", dest="force", default=False) parser.add_argument("-p", "--package-list-file", dest="package_list_file", default="../common/data/build_install_options_all.json") parser.add_argument("-m", "--stage-path", dest="stage_path", default="../stage") parser.add_argument("-s", "--json-data-path", dest="json_data_path", default="../stage/common/data/") parser.add_argument("-d", "--pkg-to-rpm-map-file", dest="pkg_to_rpm_map_file", default="../stage/pkg_info.json") parser.add_argument("-c", "--pkg-to-be-copied-conf-file", dest="pkg_to_be_copied_conf_file") parser.add_argument('configfile', nargs='?') options = parser.parse_args() # Cleanup the working directory if not options.force: proceed = query_yes_no("This will remove everything under {0}. " + "Are you sure?".format(options.working_directory)) if not proceed: sys.exit(0) if options.src_iso_path: rpm_list = create_rpm_list_to_be_copied_to_iso(options.pkg_to_rpm_map_file, options.pkg_to_be_copied_conf_file, 4, options.output_data_path) make_src_iso(options.working_directory, options.src_iso_path, rpm_list) else: if options.iso_path: # Check the arguments if options.configfile: parser.error("Incorrect arguments") config = {} config['iso_system'] = True config['vmdk_install'] = False config['type'] = 'iso' elif options.vmdk_path: # Check the arguments if not options.configfile: parser.error("Incorrect arguments") # Read the conf file config = (JsonWrapper(options.configfile)).read() config['disk'], success = create_vmdk_and_partition(config, options.vmdk_path) if not success: print("Unexpected failure, please check the logs") sys.exit(1) config['iso_system'] = False config['vmdk_install'] = True else: # Check the arguments if not options.configfile: parser.error("Incorrect arguments") # Read the conf file config = (JsonWrapper(options.configfile)).read() config['iso_system'] = False config['vmdk_install'] = False config["pkg_to_rpm_map_file"] = options.pkg_to_rpm_map_file if 'password' in config: # crypt the password if needed if config['password']['crypted']: config['password'] = config['password']['text'] else: config['password'] = crypt.crypt( config['password']['text'], "$6$" + "".join([random.choice( string.ascii_letters + string.digits) for _ in range(16)])) # Check the installation type json_wrapper_option_list = JsonWrapper(options.package_list_file) option_list_json = json_wrapper_option_list.read() options_sorted = option_list_json.items() packages = [] packages = PackageSelector.get_packages_to_install(options_sorted, config['type'], options.output_data_path) config['packages'] = packages if os.path.isdir(options.working_directory): process = subprocess.Popen(['rm', '-rf', options.working_directory]) retval = process.wait() process = subprocess.Popen(['mkdir', '-p', os.path.join(options.working_directory, "photon-chroot")]) retval = process.wait() config['working_directory'] = options.working_directory # Run the installer package_installer = Installer(config, rpm_path=options.rpm_path, log_path=options.log_path) package_installer.install(None) # Making the iso if needed if options.iso_path: rpm_list = " ".join( create_rpm_list_to_be_copied_to_iso( options.pkg_to_rpm_map_file, options.pkg_to_be_copied_conf_file, 1, options.output_data_path)) files_to_copy = " ".join( create_additional_file_list_to_copy_in_iso( os.path.abspath(options.stage_path), options.package_list_file)) live_cd = get_live_cd_status_string(options.package_list_file) process = subprocess.Popen(['./mk-install-iso.sh', '-w', options.working_directory, options.iso_path, options.rpm_path, options.package_list_file, rpm_list, options.stage_path, files_to_copy, live_cd, options.json_data_path]) retval = process.wait() if options.debug_iso_path: debug_rpm_list = create_rpm_list_to_be_copied_to_iso( options.pkg_to_rpm_map_file, options.pkg_to_be_copied_conf_file, 2, options.output_data_path) make_debug_iso(options.working_directory, options.debug_iso_path, debug_rpm_list) # Cleaning up for vmdk if 'vmdk_install' in config and config['vmdk_install']: process = subprocess.Popen(['./mk-clean-vmdk.sh', config['disk']['disk']]) process.wait() #Clean up the working directories if options.iso_path or options.vmdk_path or options.debug_iso_path: process = subprocess.Popen(['rm', '-rf', options.working_directory]) retval = process.wait()