def runTest(self): handler = KickstartHandler() self.assertEqual(str(handler), "") handler = KickstartHandler() handler.registerCommand('autopart', F23_AutoPart) handler.registerCommand('btrfs', F17_BTRFS) handler.registerData('BTRFSData', F23_BTRFSData) handler.registerData('ZFCPData', F14_ZFCPData) self.assertEqual(len(handler.commands.keys()), 2) self.assertTrue(isinstance(handler.commands['autopart'], F23_AutoPart)) self.assertTrue(isinstance(handler.commands['btrfs'], F17_BTRFS)) self.assertTrue(hasattr(handler, 'BTRFSData')) self.assertEqual(getattr(handler, 'BTRFSData'), F23_BTRFSData) self.assertTrue(hasattr(handler, 'ZFCPData')) self.assertEqual(getattr(handler, 'ZFCPData'), F14_ZFCPData) handler = KickstartHandler() handler.registerCommand('cdrom', FC3_Cdrom) handler.version = F25 parser = KickstartParser(handler) parser.readKickstartFromString("cdrom") self.assertEqual(str(handler), "# Use CDROM installation media\ncdrom\n")
def test_templates(dbo, share_dir): """ Try depsolving each of the the templates and report any errors :param dbo: dnf base object :type dbo: dnf.Base :returns: List of template types and errors :rtype: List of errors Return a list of templates and errors encountered or an empty list """ template_errors = [] for compose_type in compose_types(share_dir): # Read the kickstart template for this type ks_template_path = joinpaths(share_dir, "composer", compose_type) + ".ks" ks_template = open(ks_template_path, "r").read() # How much space will the packages in the default template take? ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString(ks_template + "\n%end\n") pkgs = [(name, "*") for name in ks.handler.packages.packageList] grps = [grp.name for grp in ks.handler.packages.groupList] try: _ = projects_depsolve(dbo, pkgs, grps) except ProjectsError as e: template_errors.append("Error depsolving %s: %s" % (compose_type, str(e))) return template_errors
def runTest(self): handler = KickstartHandler() self.assertEqual(str(handler), "") handler = KickstartHandler() handler.registerCommand('autopart', F23_AutoPart) handler.registerCommand('btrfs', F17_BTRFS) handler.registerData('BTRFSData', F23_BTRFSData) handler.registerData('ZFCPData', F14_ZFCPData) self.assertEqual(len(handler.commands.keys()), 2) self.assertTrue(isinstance(handler.commands['autopart'], F23_AutoPart)) self.assertTrue(isinstance(handler.commands['btrfs'], F17_BTRFS)) self.assertTrue(hasattr(handler, 'BTRFSData')) self.assertEqual(getattr(handler, 'BTRFSData'), F23_BTRFSData) self.assertTrue(hasattr(handler, 'ZFCPData')) self.assertEqual(getattr(handler, 'ZFCPData'), F14_ZFCPData) handler = KickstartHandler() handler.registerCommand('cdrom', FC3_Cdrom) handler.version = F25 parser = KickstartParser(handler) parser.readKickstartFromString("cdrom") self.assertEqual(str(handler), "# Use CDROM installation media\ncdrom\n")
def test_no_network(self): """Test a kickstart with missing network command""" opts = DataHolder(no_virt=True, make_fsimage=False, make_pxe_live=False) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" "part / --size=4096\n" "shutdown\n") errors = check_kickstart(ks, opts) self.assertTrue("The kickstart must activate networking" in errors[0])
def test_disk_size_align(self): """Test aligning the disk size""" opts = DataHolder(no_virt=True, make_fsimage=False, make_iso=False, make_pxe_live=False, image_size_align=1024) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" "network --bootproto=dhcp --activate\n" "repo --name=other --baseurl=http://dl.fedoraproject.com\n" "part / --size=4096\n" "shutdown\n") self.assertEqual(calculate_disk_size(opts, ks), 5120)
def test_good_ks_virt(self): """Test a good kickstart with virt""" opts = DataHolder(no_virt=False, make_fsimage=False, make_pxe_live=False) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" "network --bootproto=dhcp --activate\n" "repo --name=other --baseurl=http://dl.fedoraproject.com\n" "part / --size=4096\n" "shutdown\n") self.assertEqual(check_kickstart(ks, opts), [])
def runTest(self): # F33 has no warnings handler = makeVersion(version=F33) parser = KickstartParser(handler) with warnings.catch_warnings(record=True) as w: parser.readKickstartFromString(self.ks) self.assertEqual(len(w), 0) # F34 warns about deprecation with self.assertWarns(KickstartDeprecationWarning): self.parser.readKickstartFromString(self.ks)
def test_shutdown_virt(self): """Test a kickstart with reboot instead of shutdown""" opts = DataHolder(no_virt=False, make_fsimage=True, make_pxe_live=False) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" "network --bootproto=dhcp --activate\n" "repo --name=other --baseurl=http://dl.fedoraproject.com\n" "part / --size=4096\n" "reboot\n") errors = check_kickstart(ks, opts) self.assertTrue("must include shutdown when using virt" in errors[0])
def test_autopart(self): """Test a kickstart with autopart""" opts = DataHolder(no_virt=True, make_fsimage=True, make_pxe_live=False) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("url --url=http://dl.fedoraproject.com\n" "network --bootproto=dhcp --activate\n" "repo --name=other --baseurl=http://dl.fedoraproject.com\n" "autopart\n" "shutdown\n") errors = check_kickstart(ks, opts) self.assertTrue("Filesystem images must use a single" in errors[0])
def test_nomethod_novirt(self): """Test a kickstart with repo and no url""" opts = DataHolder(no_virt=True, make_fsimage=False, make_pxe_live=False) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString("network --bootproto=dhcp --activate\n" "repo --name=other --baseurl=http://dl.fedoraproject.com\n" "part / --size=4096\n" "shutdown\n") errors = check_kickstart(ks, opts) self.assertTrue("Only url, nfs and ostreesetup" in errors[0]) self.assertTrue("repo can only be used with the url" in errors[1])
def runTest(self): for version, command_map in control.commandMap.items(): handler = makeVersion(version) parser = KickstartParser(handler) for command_name, command_class in command_map.items(): if not issubclass(command_class, RemovedCommand): continue # Make sure that using the removed command raises an error with self.assertRaises(KickstartParseError): parser.readKickstartFromString(command_name)
def runTest(self): for version, command_map in control.commandMap.items(): handler = makeVersion(version) parser = KickstartParser(handler) for command_name, command_class in command_map.items(): if not issubclass(command_class, DeprecatedCommand): continue with warnings.catch_warnings(record=True): # The deprecated commands should be ignored with # a warning when they are parsed. Make sure that # they will not cause any errors. parser.readKickstartFromString(command_name)
def runTest(self): for version, command_map in control.commandMap.items(): handler = makeVersion(version) parser = KickstartParser(handler) for command_name, command_class in command_map.items(): if not issubclass(command_class, DeprecatedCommand): continue with warnings.catch_warnings(record=True): # The deprecated commands should be ignored with # a warning when they are parsed. Make sure that # they will not cause any errors. parser.readKickstartFromString(command_name)
def displaymode_test(self): """Test a kickstart with displaymode set""" opts = DataHolder(no_virt=True, make_fsimage=False, make_pxe_live=False) ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString( "url --url=http://dl.fedoraproject.com\n" "network --bootproto=dhcp --activate\n" "repo --name=other --baseurl=http://dl.fedoraproject.com\n" "part / --size=4096\n" "shutdown\n" "graphical\n") errors = check_kickstart(ks, opts) self.assertTrue("must not set a display mode" in errors[0])
def runTest(self): for version, command_map in control.commandMap.items(): handler = makeVersion(version) parser = KickstartParser(handler) for command_name, command_class in command_map.items(): if not issubclass(command_class, DeprecatedCommand): continue if issubclass(command_class, RemovedCommand): continue with warnings.catch_warnings(record=True): # The deprecated commands should be ignored with # a warning when they are parsed. Make sure that # they will not cause any errors. with self.assertWarns(KickstartDeprecationWarning) as cm: parser.readKickstartFromString(command_name) # Check the warning message. expected = " {} command has been deprecated ".format( command_name) self.assertIn(expected, str(cm.warning))
def bootloader_append(line, kernel_append): """ Insert the kernel_append string into the --append argument :param line: The bootloader ... line :type line: str :param kernel_append: The arguments to append to the --append section :type kernel_append: str Using pykickstart to process the line is the best way to make sure it is parsed correctly, and re-assembled for inclusion into the final kickstart """ ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString(line) if ks.handler.bootloader.appendLine: ks.handler.bootloader.appendLine += " %s" % kernel_append else: ks.handler.bootloader.appendLine = kernel_append # Converting back to a string includes a comment, return just the bootloader line return str(ks.handler.bootloader).splitlines()[-1]
def start_build(cfg, dnflock, gitlock, branch, recipe_name, compose_type, test_mode=0): """ Start the build :param cfg: Configuration object :type cfg: ComposerConfig :param dnflock: Lock and YumBase for depsolving :type dnflock: YumLock :param recipe: The recipe to build :type recipe: str :param compose_type: The type of output to create from the recipe :type compose_type: str :returns: Unique ID for the build that can be used to track its status :rtype: str """ share_dir = cfg.get("composer", "share_dir") lib_dir = cfg.get("composer", "lib_dir") # Make sure compose_type is valid if compose_type not in compose_types(share_dir): raise RuntimeError("Invalid compose type (%s), must be one of %s" % (compose_type, compose_types(share_dir))) # Some image types (live-iso) need extra packages for composer to execute the output template with dnflock.lock: extra_pkgs = get_extra_pkgs(dnflock.dbo, share_dir, compose_type) log.debug("Extra packages needed for %s: %s", compose_type, extra_pkgs) with gitlock.lock: (commit_id, recipe) = read_recipe_and_id(gitlock.repo, branch, recipe_name) # Combine modules and packages and depsolve the list module_nver = recipe.module_nver package_nver = recipe.package_nver package_nver.extend([(name, '*') for name in extra_pkgs]) projects = sorted(set(module_nver + package_nver), key=lambda p: p[0].lower()) deps = [] log.info("depsolving %s", recipe["name"]) try: # This can possibly update repodata and reset the YumBase object. with dnflock.lock_check: (installed_size, deps) = projects_depsolve_with_size(dnflock.dbo, projects, recipe.group_names, with_core=False) except ProjectsError as e: log.error("start_build depsolve: %s", str(e)) raise RuntimeError("Problem depsolving %s: %s" % (recipe["name"], str(e))) # Read the kickstart template for this type ks_template_path = joinpaths(share_dir, "composer", compose_type) + ".ks" ks_template = open(ks_template_path, "r").read() # How much space will the packages in the default template take? ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString(ks_template + "\n%end\n") pkgs = [(name, "*") for name in ks.handler.packages.packageList] grps = [grp.name for grp in ks.handler.packages.groupList] try: with dnflock.lock: (template_size, _) = projects_depsolve_with_size( dnflock.dbo, pkgs, grps, with_core=not ks.handler.packages.nocore) except ProjectsError as e: log.error("start_build depsolve: %s", str(e)) raise RuntimeError("Problem depsolving %s: %s" % (recipe["name"], str(e))) log.debug("installed_size = %d, template_size=%d", installed_size, template_size) # Minimum LMC disk size is 1GiB, and anaconda bumps the estimated size up by 10% (which doesn't always work). installed_size = int((installed_size + template_size)) * 1.2 log.debug("/ partition size = %d", installed_size) # Create the results directory build_id = str(uuid4()) results_dir = joinpaths(lib_dir, "results", build_id) os.makedirs(results_dir) # Write the recipe commit hash commit_path = joinpaths(results_dir, "COMMIT") with open(commit_path, "w") as f: f.write(commit_id) # Write the original recipe recipe_path = joinpaths(results_dir, "blueprint.toml") with open(recipe_path, "w") as f: f.write(recipe.toml()) # Write the frozen recipe frozen_recipe = recipe.freeze(deps) recipe_path = joinpaths(results_dir, "frozen.toml") with open(recipe_path, "w") as f: f.write(frozen_recipe.toml()) # Write out the dependencies to the results dir deps_path = joinpaths(results_dir, "deps.toml") with open(deps_path, "w") as f: f.write(toml.dumps({"packages": deps})) # Save a copy of the original kickstart shutil.copy(ks_template_path, results_dir) with dnflock.lock: repos = list(dnflock.dbo.repos.iter_enabled()) if not repos: raise RuntimeError("No enabled repos, canceling build.") # Create the git rpms, if any, and return the path to the repo under results_dir gitrpm_repo = create_gitrpm_repo(results_dir, recipe) # Create the final kickstart with repos and package list ks_path = joinpaths(results_dir, "final-kickstart.ks") with open(ks_path, "w") as f: ks_url = repo_to_ks(repos[0], "url") log.debug("url = %s", ks_url) f.write('url %s\n' % ks_url) for idx, r in enumerate(repos[1:]): ks_repo = repo_to_ks(r, "baseurl") log.debug("repo composer-%s = %s", idx, ks_repo) f.write('repo --name="composer-%s" %s\n' % (idx, ks_repo)) if gitrpm_repo: log.debug("repo gitrpms = %s", gitrpm_repo) f.write('repo --name="gitrpms" --baseurl="file://%s"\n' % gitrpm_repo) # Setup the disk for booting # TODO Add GPT and UEFI boot support f.write('clearpart --all --initlabel\n') # Write the root partition and it's size in MB (rounded up) f.write('part / --size=%d\n' % ceil(installed_size / 1024**2)) # Some customizations modify the template before writing it f.write(customize_ks_template(ks_template, recipe)) for d in deps: f.write(dep_nevra(d) + "\n") # Include the rpms from the gitrpm repo directory if gitrpm_repo: for rpm in glob(os.path.join(gitrpm_repo, "*.rpm")): f.write(os.path.basename(rpm)[:-4] + "\n") f.write("%end\n") # Other customizations can be appended to the kickstart add_customizations(f, recipe) # Setup the config to pass to novirt_install log_dir = joinpaths(results_dir, "logs/") cfg_args = compose_args(compose_type) # Get the title, project, and release version from the host if not os.path.exists("/etc/os-release"): log.error( "/etc/os-release is missing, cannot determine product or release version" ) os_release = flatconfig("/etc/os-release") log.debug("os_release = %s", dict(os_release.items())) cfg_args["title"] = os_release.get("PRETTY_NAME", "") cfg_args["project"] = os_release.get("NAME", "") cfg_args["releasever"] = os_release.get("VERSION_ID", "") cfg_args["volid"] = "" cfg_args["extra_boot_args"] = get_kernel_append(recipe) cfg_args.update({ "compression": "xz", "compress_args": [], "ks": [ks_path], "logfile": log_dir, "timeout": 60, # 60 minute timeout }) with open(joinpaths(results_dir, "config.toml"), "w") as f: f.write(toml.dumps(cfg_args)) # Set the initial status open(joinpaths(results_dir, "STATUS"), "w").write("WAITING") # Set the test mode, if requested if test_mode > 0: open(joinpaths(results_dir, "TEST"), "w").write("%s" % test_mode) write_timestamp(results_dir, TS_CREATED) log.info("Adding %s (%s %s) to compose queue", build_id, recipe["name"], compose_type) os.symlink(results_dir, joinpaths(lib_dir, "queue/new/", build_id)) return build_id
break # All internal commands start with a ., so if that's the beginning of the # line, we need to dispatch ourselves. if line.startswith("."): words = line.split() if words[0] in internalCommands: try: internalCommands[words[0]].execute(ksparser) except EOFError: # ".quit" was typed, time to quit. break else: print(_("Internal command %s not recognized.") % words[0]) continue # Now process the line of input as if it were a kickstart file - just an # extremely short one. try: ksparser.readKickstartFromString(line) except KickstartError as e: print(e) # And finally, print the output kickstart file. if opts.output: with open(opts.output, "w") as fd: fd.write(str(ksparser.handler)) else: print("\n" + str(ksparser.handler))
def main(): ## ## OPTION PROCESSING ## op = argparse.ArgumentParser() op.add_argument("-i", "--input", dest="input", help=_("a basis file to use for seeding the kickstart data (optional)")) op.add_argument("-o", "--output", dest="output", help=_("the location to write the finished kickstart file, or stdout if not given")) op.add_argument("-v", "--version", dest="version", default=DEVEL, help=_("version of kickstart syntax to validate against")) opts = op.parse_args(sys.argv[1:]) ## ## SETTING UP PYKICKSTART ## try: kshandler = makeVersion(opts.version) except KickstartVersionError: print(_("The version %s is not supported by pykickstart") % opts.version) sys.exit(1) ksparser = KickstartParser(kshandler, followIncludes=True, errorsAreFatal=False) if opts.input: try: processedFile = preprocessKickstart(opts.input) ksparser.readKickstart(processedFile) os.remove(processedFile) except KickstartError as e: # Errors should just dump you to the prompt anyway. print(_("Warning: The following error occurred when processing the input file:\n%s\n") % e) internalCommands = {".clear": ClearCommand(), ".show": ShowCommand(), ".quit": QuitCommand()} ## ## SETTING UP READLINE ## readline.parse_and_bind("tab: complete") readline.set_completer(KickstartCompleter(kshandler, internalCommands).complete) # Since everything in kickstart looks like a command line arg, we need to # remove '-' from the delimiter string. delims = readline.get_completer_delims() readline.set_completer_delims(delims.replace('-', '')) ## ## REPL ## print("Press ^D to exit.") while True: try: line = six.moves.input("ks> ") # pylint: disable=no-member except EOFError: # ^D was hit, time to quit. break except KeyboardInterrupt: # ^C was hit, time to quit. Don't be like other programs. break # All internal commands start with a ., so if that's the beginning of the # line, we need to dispatch ourselves. if line.startswith("."): words = line.split() if words[0] in internalCommands: try: internalCommands[words[0]].execute(ksparser) except EOFError: # ".quit" was typed, time to quit. break else: print(_("Internal command %s not recognized.") % words[0]) continue # Now process the line of input as if it were a kickstart file - just an # extremely short one. try: ksparser.readKickstartFromString(line) except KickstartError as e: print(e) # And finally, print the output kickstart file. if opts.output: with open(opts.output, "w") as fd: fd.write(str(ksparser.handler)) else: print("\n" + str(ksparser.handler))
def start_build(cfg, dnflock, gitlock, branch, recipe_name, compose_type, test_mode=0): """ Start the build :param cfg: Configuration object :type cfg: ComposerConfig :param dnflock: Lock and YumBase for depsolving :type dnflock: YumLock :param recipe: The recipe to build :type recipe: str :param compose_type: The type of output to create from the recipe :type compose_type: str :returns: Unique ID for the build that can be used to track its status :rtype: str """ share_dir = cfg.get("composer", "share_dir") lib_dir = cfg.get("composer", "lib_dir") # Make sure compose_type is valid if compose_type not in compose_types(share_dir): raise RuntimeError("Invalid compose type (%s), must be one of %s" % (compose_type, compose_types(share_dir))) with gitlock.lock: (commit_id, recipe) = read_recipe_and_id(gitlock.repo, branch, recipe_name) # Combine modules and packages and depsolve the list # TODO include the version/glob in the depsolving module_nver = recipe.module_nver package_nver = recipe.package_nver projects = sorted(set(module_nver + package_nver), key=lambda p: p[0].lower()) deps = [] try: with dnflock.lock: (installed_size, deps) = projects_depsolve_with_size(dnflock.dbo, projects, with_core=False) except ProjectsError as e: log.error("start_build depsolve: %s", str(e)) raise RuntimeError("Problem depsolving %s: %s" % (recipe["name"], str(e))) # Read the kickstart template for this type ks_template_path = joinpaths(share_dir, "composer", compose_type) + ".ks" ks_template = open(ks_template_path, "r").read() # How much space will the packages in the default template take? ks_version = makeVersion() ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) ks.readKickstartFromString(ks_template + "\n%end\n") ks_projects = [(name, "*") for name in ks.handler.packages.packageList] try: with dnflock.lock: (template_size, _) = projects_depsolve_with_size( dnflock.dbo, ks_projects, with_core=not ks.handler.packages.nocore) except ProjectsError as e: log.error("start_build depsolve: %s", str(e)) raise RuntimeError("Problem depsolving %s: %s" % (recipe["name"], str(e))) log.debug("installed_size = %d, template_size=%d", installed_size, template_size) # Minimum LMC disk size is 1GiB, and anaconda bumps the estimated size up by 10% (which doesn't always work). # XXX BUT Anaconda has a bug, it won't execute a kickstart on a disk smaller than 3000 MB # XXX There is an upstream patch pending, but until then, use that as the minimum installed_size = max(3e9, int((installed_size + template_size))) * 1.2 log.debug("/ partition size = %d", installed_size) # Create the results directory build_id = str(uuid4()) results_dir = joinpaths(lib_dir, "results", build_id) os.makedirs(results_dir) # Write the recipe commit hash commit_path = joinpaths(results_dir, "COMMIT") with open(commit_path, "w") as f: f.write(commit_id) # Write the original recipe recipe_path = joinpaths(results_dir, "blueprint.toml") with open(recipe_path, "w") as f: f.write(recipe.toml()) # Write the frozen recipe frozen_recipe = recipe.freeze(deps) recipe_path = joinpaths(results_dir, "frozen.toml") with open(recipe_path, "w") as f: f.write(frozen_recipe.toml()) # Write out the dependencies to the results dir deps_path = joinpaths(results_dir, "deps.toml") with open(deps_path, "w") as f: f.write(toml.dumps({"packages": deps})) # Save a copy of the original kickstart shutil.copy(ks_template_path, results_dir) with dnflock.lock: repos = list(dnflock.dbo.repos.iter_enabled()) if not repos: raise RuntimeError("No enabled repos, canceling build.") # Create the final kickstart with repos and package list ks_path = joinpaths(results_dir, "final-kickstart.ks") with open(ks_path, "w") as f: ks_url = repo_to_ks(repos[0], "url") log.debug("url = %s", ks_url) f.write('url %s\n' % ks_url) for idx, r in enumerate(repos[1:]): ks_repo = repo_to_ks(r, "baseurl") log.debug("repo composer-%s = %s", idx, ks_repo) f.write('repo --name="composer-%s" %s\n' % (idx, ks_repo)) # Write the root partition and it's size in MB (rounded up) f.write('part / --fstype="ext4" --size=%d\n' % ceil(installed_size / 1024**2)) f.write(ks_template) for d in deps: f.write(dep_nevra(d) + "\n") f.write("%end\n") add_customizations(f, recipe) # Setup the config to pass to novirt_install log_dir = joinpaths(results_dir, "logs/") cfg_args = compose_args(compose_type) # Get the title, project, and release version from the host if not os.path.exists("/etc/os-release"): log.error( "/etc/os-release is missing, cannot determine product or release version" ) os_release = SimpleConfigFile("/etc/os-release") os_release.read() log.debug("os_release = %s", os_release) cfg_args["title"] = os_release.get("PRETTY_NAME") cfg_args["project"] = os_release.get("NAME") cfg_args["releasever"] = os_release.get("VERSION_ID") cfg_args["volid"] = "" cfg_args.update({ "compression": "xz", "compress_args": [], "ks": [ks_path], "logfile": log_dir, "timeout": 60, # 60 minute timeout }) with open(joinpaths(results_dir, "config.toml"), "w") as f: f.write(toml.dumps(cfg_args)) # Set the initial status open(joinpaths(results_dir, "STATUS"), "w").write("WAITING") # Set the test mode, if requested if test_mode > 0: open(joinpaths(results_dir, "TEST"), "w").write("%s" % test_mode) log.info("Adding %s (%s %s) to compose queue", build_id, recipe["name"], compose_type) os.symlink(results_dir, joinpaths(lib_dir, "queue/new/", build_id)) return build_id
break # All internal commands start with a ., so if that's the beginning of the # line, we need to dispatch ourselves. if line.startswith("."): words = line.split() if words[0] in internalCommands: try: internalCommands[words[0]].execute(ksparser) except EOFError: # ".quit" was typed, time to quit. break else: print(_("Internal command %s not recognized.") % words[0]) continue # Now process the line of input as if it were a kickstart file - just an # extremely short one. try: ksparser.readKickstartFromString(line) except KickstartError as e: print(e) # And finally, print the output kickstart file. if opts.output: with open(opts.output, "w") as fd: fd.write(str(ksparser.handler)) else: print("\n" + str(ksparser.handler))
def main(argv=None): ## ## OPTION PROCESSING ## op = argparse.ArgumentParser() op.add_argument("-i", "--input", dest="input", help=_("a basis file to use for seeding the kickstart data (optional)")) op.add_argument("-o", "--output", dest="output", help=_("the location to write the finished kickstart file, or stdout if not given")) op.add_argument("-v", "--version", dest="version", default=DEVEL, help=_("version of kickstart syntax to validate against")) opts = op.parse_args(argv) ## ## SETTING UP PYKICKSTART ## try: kshandler = makeVersion(opts.version) except KickstartVersionError: print(_("The version %s is not supported by pykickstart") % opts.version) return 1 ksparser = KickstartParser(kshandler, followIncludes=True, errorsAreFatal=False) if opts.input: try: processedFile = preprocessKickstart(opts.input) ksparser.readKickstart(processedFile) os.remove(processedFile) except KickstartError as e: # Errors should just dump you to the prompt anyway. print(_("Warning: The following error occurred when processing the input file:\n%s\n") % e) internalCommands = {".clear": ClearCommand(), ".show": ShowCommand(), ".quit": QuitCommand()} ## ## SETTING UP READLINE ## readline.parse_and_bind("tab: complete") readline.set_completer(KickstartCompleter(kshandler, internalCommands).complete) # Since everything in kickstart looks like a command line arg, we need to # remove '-' from the delimiter string. delims = readline.get_completer_delims() readline.set_completer_delims(delims.replace('-', '')) ## ## REPL ## print("Press ^D to exit.") while True: try: line = six.moves.input("ks> ") # pylint: disable=no-member except EOFError: # ^D was hit, time to quit. break except KeyboardInterrupt: # ^C was hit, time to quit. Don't be like other programs. break # All internal commands start with a ., so if that's the beginning of the # line, we need to dispatch ourselves. if line.startswith("."): words = line.split() if words[0] in internalCommands: try: internalCommands[words[0]].execute(ksparser) except EOFError: # ".quit" was typed, time to quit. break else: print(_("Internal command %s not recognized.") % words[0]) continue # Now process the line of input as if it were a kickstart file - just an # extremely short one. try: ksparser.readKickstartFromString(line) except KickstartError as e: print(e) # And finally, print the output kickstart file. if opts.output: with open(opts.output, "w") as fd: fd.write(str(ksparser.handler)) else: print("\n" + str(ksparser.handler)) return 0