#! /usr/bin/python2 # # Copyright (C) 2015 vmware inc. # # Author: Mahmoud Bassiouny from optparse import OptionParser from installer import Installer import crypt import random import string import subprocess import sys import os from jsonwrapper import JsonWrapper from packageselector import PackageSelector import json 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 partition_disk(disk): partitions_data = {} partitions_data['disk'] = disk partitions_data['root'] = disk + '2' partitions_data['swap'] = disk + '3' # Clear the disk process = subprocess.Popen(['sgdisk', '-z', partitions_data['disk']]) retval = process.wait() # 1: grub, 2: swap, 3: filesystem process = subprocess.Popen(['sgdisk', '-n', '1::+2M', '-n', '3:-3G:', '-n', '2:', '-p', partitions_data['disk']]) retval = process.wait() # Add the grub flags process = subprocess.Popen(['sgdisk', '-t1:ef02', partitions_data['disk']]) retval = process.wait() # format the swap process = subprocess.Popen(['mkswap', partitions_data['swap']]) retval = process.wait() # format the file system process = subprocess.Popen(['mkfs', '-t', 'ext4', partitions_data['root']]) retval = process.wait() return partitions_data def create_vmdk_and_partition(config, vmdk_path): partitions_data = {} process = subprocess.Popen(['./mk-setup-vmdk.sh', '-rp', config['size']['root'], '-sp', config['size']['swap'], '-n', vmdk_path, '-m'], stdout=subprocess.PIPE) count = 0 for line in iter(process.stdout.readline, ''): 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 create_rpm_list_to_copy_in_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 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 install_option[1].has_key("additional-files"): file_list = file_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 install_option[1].has_key("live-cd"): if install_option[1].get("live-cd") == True: return "true" return "false" def generate_pkginfo_text_file(list_rpms, pkg_info_json_file_path, pkg_info_text_file_path): if not os.path.isfile(pkg_info_json_file_path): return pkg_info_json_file = open(pkg_info_json_file_path,'r') data = json.load(pkg_info_json_file) pkg_info_json_file.close() list_lines = [] list_lines.append("#%{name},%{version},%{release},%{arch},%{sourcerpm}\n") for rpm in list_rpms: if data.has_key(rpm): list_lines.append(data[rpm]["name"]+","+data[rpm]["version"]+","+data[rpm]["release"]+","+data[rpm]["arch"]+","+data[rpm]["sourcerpm"]+"\n") pkg_info_text_file = open(pkg_info_text_file_path,'w') pkg_info_text_file.writelines(list_lines) pkg_info_text_file.close() if __name__ == '__main__': usage = "Usage: %prog [options] " parser = OptionParser(usage) parser.add_option("-i", "--iso-path", dest="iso_path") parser.add_option("-j", "--src-iso-path", dest="src_iso_path") parser.add_option("-v", "--vmdk-path", dest="vmdk_path") parser.add_option("-w", "--working-directory", dest="working_directory", default="/mnt/photon-root") parser.add_option("-l", "--log-path", dest="log_path", default="../stage/LOGS") parser.add_option("-r", "--rpm-path", dest="rpm_path", default="../stage/RPMS") parser.add_option("-x", "--srpm-path", dest="srpm_path", default="../stage/SRPMS") parser.add_option("-o", "--output-data-path", dest="output_data_path", default="../stage/common/data/") parser.add_option("-f", "--force", action="store_true", dest="force", default=False) parser.add_option("-p", "--package-list-file", dest="package_list_file", default="../common/data/build_install_options_all.json") parser.add_option("-m", "--stage-path", dest="stage_path", default="../stage") parser.add_option("-c", "--dracut-configuration", dest="dracut_configuration_file", default="../common/data/dracut_configuration.json") parser.add_option("-s", "--json-data-path", dest="json_data_path", default="../stage/common/data/") parser.add_option("-u", "--pkginfo-json-file", dest="pkginfo_json_file", default="../common/data/pkg_info.json") parser.add_option("-z", "--pkginfo-txt-file", dest="pkginfo_txt_file", default="../stage/pkg_info.txt") (options, args) = parser.parse_args() if options.iso_path or options.src_iso_path: # Check the arguments if (len(args)) != 0: parser.error("Incorrect arguments") config = {} config['iso_system'] = True config['vmdk_install'] = False elif options.vmdk_path: # Check the arguments if (len(args)) != 1: parser.error("Incorrect arguments") # Read the conf file config = (JsonWrapper(args[0])).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['initrd_dir'] = "/boot" config['iso_system'] = False config['vmdk_install'] = True else: # Check the arguments if (len(args)) != 1: parser.error("Incorrect arguments") # Read the conf file config = (JsonWrapper(args[0])).read() config['iso_system'] = False config['vmdk_install'] = False 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() base_path = os.path.dirname(options.package_list_file) packages = [] additional_files_to_copy_from_stage_to_iso = [] if config['iso_system'] == True: for install_option in options_sorted: if install_option[0] == "iso": json_wrapper_package_list = JsonWrapper(os.path.join(base_path, install_option[1]["file"])) package_list_json = json_wrapper_package_list.read() packages = package_list_json["packages"] else: packages = PackageSelector.get_packages_to_install(options_sorted, config['type'], options.output_data_path) config['packages'] = packages if options.iso_path: if os.path.isfile(options.dracut_configuration_file): json_wrapper_package_list = JsonWrapper(options.dracut_configuration_file) dracut_configuration_list_json = json_wrapper_package_list.read() config["dracut_configuration"]=dracut_configuration_list_json["dracut_configuration"] # 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 (os.path.isdir(options.working_directory)): process = subprocess.Popen(['rm', '-rf', options.working_directory]) retval = process.wait() else: process = subprocess.Popen(['mkdir', '-p', 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_copy_in_iso(options.package_list_file, 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.src_iso_path: rpm_list = " ".join(create_rpm_list_to_copy_in_iso(options.package_list_file, options.output_data_path)) process = subprocess.Popen(['./mk-src-iso.sh', '-w', options.working_directory, options.src_iso_path, options.srpm_path, rpm_list]) retval = process.wait() list_rpms = rpm_list.split(" ") list_rpms = list(set(list_rpms)) list_rpms.sort() generate_pkginfo_text_file(list_rpms, options.pkginfo_json_file, options.pkginfo_txt_file) # 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.src_iso_path): process = subprocess.Popen(['rm', '-rf', options.working_directory]) retval = process.wait()