installer/photonInstaller.py
f4d17450
 #! /usr/bin/python2
 #
 #    Copyright (C) 2015 vmware inc.
 #
 #    Author: Mahmoud Bassiouny <mbassiouny@vmware.com>
 
 from optparse import OptionParser
 from installer import Installer
 import crypt
 import random
 import string
 import subprocess
 import sys
 import os
 from jsonwrapper import JsonWrapper
bb884b5b
 from packageselector import PackageSelector
2cfb758d
 import json
f4d17450
 
 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()
c3771c35
             partitions_data['boot'] = partitions_data['root']
             partitions_data['bootdirectory'] = '/boot/'
f4d17450
             count += 1
5d05cfcc
 
c3771c35
     if count == 2:
         partitions_data['partitions'] = [{'path': partitions_data['root'], 'mountpoint': '/', 'filesystem': 'ext4'}]
 
f4d17450
     return partitions_data, count == 2
5d05cfcc
 
c1a6582a
 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):
4d6a578d
     json_wrapper_option_list = JsonWrapper(build_install_option)
     option_list_json = json_wrapper_option_list.read()
dc0dfc30
     options_sorted = option_list_json.items()
4d6a578d
     packages = []
     for install_option in options_sorted:
07751fba
         if install_option[0] != "iso":
2cbd5a80
             file_path = os.path.join(output_data_path, install_option[1]["file"])
07751fba
             json_wrapper_package_list = JsonWrapper(file_path)
             package_list_json = json_wrapper_package_list.read()
             packages = packages + package_list_json["packages"]
4d6a578d
     return packages
f4d17450
 
c1a6582a
     #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']
75ad8e92
                 rpm_list.append(pkg_to_rpm_map[k]['debugrpm'])
c1a6582a
             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
 
2f46569e
 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"):
7322111a
             file_list = file_list + map(lambda filename: os.path.join(base_path, filename), install_option[1].get("additional-files"))
2f46569e
     return file_list
 
07751fba
 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"
 
c1a6582a
 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()
 
75ad8e92
 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()
 
f4d17450
 if __name__ == '__main__':
     usage = "Usage: %prog [options] <config file> <tools path>"
     parser = OptionParser(usage)
 
     parser.add_option("-i", "--iso-path",  dest="iso_path")
2cfb758d
     parser.add_option("-j", "--src-iso-path",  dest="src_iso_path")
75ad8e92
     parser.add_option("-k", "--debug-iso-path",  dest="debug_iso_path")
f4d17450
     parser.add_option("-v", "--vmdk-path", dest="vmdk_path")
     parser.add_option("-w",  "--working-directory",  dest="working_directory", default="/mnt/photon-root")
b422b988
     parser.add_option("-l",  "--log-path",  dest="log_path", default="../stage/LOGS")
6b3c4668
     parser.add_option("-r",  "--rpm-path",  dest="rpm_path", default="../stage/RPMS")
2cfb758d
     parser.add_option("-x",  "--srpm-path",  dest="srpm_path", default="../stage/SRPMS")
2cbd5a80
     parser.add_option("-o", "--output-data-path", dest="output_data_path", default="../stage/common/data/")
f4d17450
     parser.add_option("-f", "--force", action="store_true", dest="force", default=False)
5d05cfcc
     parser.add_option("-p", "--package-list-file", dest="package_list_file", default="../common/data/build_install_options_all.json")
2f46569e
     parser.add_option("-m", "--stage-path", dest="stage_path", default="../stage")
6860f77c
     parser.add_option("-s", "--json-data-path", dest="json_data_path", default="../stage/common/data/")
b94a5dc5
     parser.add_option("-d", "--pkg-to-rpm-map-file", dest="pkg_to_rpm_map_file", default="../stage/pkg_info.json")
     parser.add_option("-c", "--pkg-to-be-copied-conf-file", dest="pkg_to_be_copied_conf_file")
2cfb758d
 
f4d17450
     (options,  args) = parser.parse_args()
c1a6582a
     # 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)
f4d17450
 
c1a6582a
     if options.src_iso_path:
b94a5dc5
         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)
c1a6582a
         make_src_iso(options.working_directory, options.src_iso_path, rpm_list)
f4d17450
 
c1a6582a
     else:
         if options.iso_path:
             # Check the arguments
             if (len(args)) != 0:
                 parser.error("Incorrect arguments")
             config = {}
             config['iso_system'] = True
             config['vmdk_install'] = False
             config['type'] = 'iso'
 
         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['iso_system'] = False
             config['vmdk_install'] = True
f4d17450
 
         else:
c1a6582a
             # Check the arguments
             if (len(args)) != 1:
                 parser.error("Incorrect arguments")
f4d17450
 
c1a6582a
             # Read the conf file
             config = (JsonWrapper(args[0])).read()
bb884b5b
 
c1a6582a
             config['iso_system'] = False
             config['vmdk_install'] = False
4d6a578d
 
f7ba3634
         config["pkg_to_rpm_map_file"] = options.pkg_to_rpm_map_file
c1a6582a
         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)]))
f4d17450
 
c1a6582a
         # 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()
57342c05
 
c1a6582a
         packages = []
         packages = PackageSelector.get_packages_to_install(options_sorted, config['type'], options.output_data_path)
f4d17450
 
c1a6582a
         config['packages'] = packages
f4d17450
 
c1a6582a
         if (os.path.isdir(options.working_directory)):
             process = subprocess.Popen(['rm', '-rf', options.working_directory])
             retval = process.wait()
f4d17450
 
c1a6582a
         process = subprocess.Popen(['mkdir', '-p', os.path.join(options.working_directory, "photon-chroot")])
f4d17450
         retval = process.wait()
 
c1a6582a
         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:
75ad8e92
             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))
c1a6582a
             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()
 
75ad8e92
         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)
 
c1a6582a
         # 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
75ad8e92
         if (options.iso_path or options.vmdk_path or options.debug_iso_path):
c1a6582a
             process = subprocess.Popen(['rm', '-rf', options.working_directory])
             retval = process.wait()