def config_backup(lib, argv, modifiers): """ Options: * --force - overwrite file if already exists """ del lib modifiers.ensure_only_supported("--force") if len(argv) > 1: usage.config(["backup"]) sys.exit(1) outfile_name = None if argv: outfile_name = argv[0] if not outfile_name.endswith(".tar.bz2"): outfile_name += ".tar.bz2" tar_data = config_backup_local() if outfile_name: ok, message = utils.write_file(outfile_name, tar_data, permissions=0o600, binary=True) if not ok: utils.err(message) else: # in python3 stdout accepts str so we need to use buffer sys.stdout.buffer.write(tar_data)
def config_backup(argv): if len(argv) > 1: usage.config(["backup"]) sys.exit(1) outfile_name = None if argv: outfile_name = argv[0] if not outfile_name.endswith(".tar.bz2"): outfile_name += ".tar.bz2" tar_data = config_backup_local() if outfile_name: ok, message = utils.write_file(outfile_name, tar_data, permissions=0o600, binary=True) if not ok: utils.err(message) else: # in python3 stdout accepts str so we need to use buffer if hasattr(sys.stdout, "buffer"): sys.stdout.buffer.write(tar_data) else: sys.stdout.write(tar_data)
def config_backup(lib, argv, modifiers): """ Options: * --force - overwrite file if already exists """ del lib modifiers.ensure_only_supported("--force") if len(argv) > 1: usage.config(["backup"]) sys.exit(1) outfile_name = None if argv: outfile_name = argv[0] if not outfile_name.endswith(".tar.bz2"): outfile_name += ".tar.bz2" tar_data = config_backup_local() if outfile_name: ok, message = utils.write_file( outfile_name, tar_data, permissions=0o600, binary=True ) if not ok: utils.err(message) else: # in python3 stdout accepts str so we need to use buffer sys.stdout.buffer.write(tar_data)
def config_checkpoint_view(argv): if len(argv) != 1: usage.config(["checkpoint", "view"]) sys.exit(1) utils.usefile = True utils.filename = os.path.join(settings.cib_dir, "cib-%s.raw" % argv[0]) if not os.path.isfile(utils.filename): utils.err("unable to read the checkpoint") config_show_cib()
def config_checkpoint_diff(lib, argv, modifiers): """ Commandline options: * -f - CIB file """ modifiers.ensure_only_supported("-f") if len(argv) != 2: usage.config(["checkpoint diff"]) sys.exit(1) if argv[0] == argv[1]: utils.err("cannot diff a checkpoint against itself") errors = [] checkpoints_lines = [] for checkpoint in argv: if checkpoint == "live": lines = _config_show_cib_lines(lib) if not lines: errors.append("unable to read live configuration") else: checkpoints_lines.append(lines) else: loaded, lines = _checkpoint_to_lines(lib, checkpoint) if not loaded: errors.append( "unable to read checkpoint '{0}'".format(checkpoint) ) else: checkpoints_lines.append(lines) if errors: utils.err("\n".join(errors)) print( "Differences between {0} (-) and {1} (+):".format( *[ "live configuration" if label == "live" else f"checkpoint {label}" for label in argv ] ) ) print( "\n".join( [ line.rstrip() for line in difflib.Differ().compare( checkpoints_lines[0], checkpoints_lines[1] ) ] ) )
def config_checkpoint_restore(argv): if len(argv) != 1: usage.config(["checkpoint", "restore"]) sys.exit(1) cib_path = os.path.join(settings.cib_dir, "cib-%s.raw" % argv[0]) try: snapshot_dom = parse(cib_path) except Exception as e: utils.err("unable to read the checkpoint: %s" % e) utils.replace_cib_configuration(snapshot_dom)
def config_checkpoint_view(lib, argv, modifiers): """ Options: no options """ modifiers.ensure_only_supported() if len(argv) != 1: usage.config(["checkpoint view"]) sys.exit(1) loaded, lines = _checkpoint_to_lines(lib, argv[0]) if not loaded: utils.err("unable to read the checkpoint") print("\n".join(lines))
def config_checkpoint_view(lib, argv, modifiers): """ Options: no options """ modifiers.ensure_only_supported() if len(argv) != 1: usage.config(["checkpoint", "view"]) sys.exit(1) utils.usefile = True utils.filename = os.path.join(settings.cib_dir, "cib-%s.raw" % argv[0]) if not os.path.isfile(utils.filename): utils.err("unable to read the checkpoint") config_show_cib(lib)
def config_cmd(lib, argv, modifiers): create_router( { "help": lambda _lib, _argv, _modifiers: usage.config(_argv), "show": config_show, "backup": config_backup, "restore": config_restore, "checkpoint": create_router( { "list": config_checkpoint_list, "view": config_checkpoint_view, "restore": config_checkpoint_restore, "diff": config_checkpoint_diff, }, ["config", "checkpoint"], default_cmd="list"), "import-cman": config_import_cman, "export": create_router( { "pcs-commands": config_export_pcs_commands, "pcs-commands-verbose": lambda _lib, _argv, _modifiers: config_export_pcs_commands( _lib, _argv, _modifiers, verbose=True) }, ["config", "export"]) }, ["config"], default_cmd="show", )(lib, argv, modifiers)
def config_checkpoint_restore(dummy_lib, argv, modifiers): """ Options: * -f - CIB file, a checkpoint will be restored into a specified file """ modifiers.ensure_only_supported("-f") if len(argv) != 1: usage.config(["checkpoint", "restore"]) sys.exit(1) cib_path = os.path.join(settings.cib_dir, "cib-%s.raw" % argv[0]) try: snapshot_dom = parse(cib_path) except Exception as e: utils.err("unable to read the checkpoint: %s" % e) utils.replace_cib_configuration(snapshot_dom)
def config_checkpoint_restore(lib, argv, modifiers): """ Options: * -f - CIB file, a checkpoint will be restored into a specified file """ # pylint: disable=broad-except del lib modifiers.ensure_only_supported("-f") if len(argv) != 1: usage.config(["checkpoint restore"]) sys.exit(1) cib_path = os.path.join(settings.cib_dir, "cib-%s.raw" % argv[0]) try: snapshot_dom = parse(cib_path) except Exception as e: utils.err("unable to read the checkpoint: %s" % e) utils.replace_cib_configuration(snapshot_dom)
def config_restore(lib, argv, modifiers): """ Options: * --local - restore config only on local node * --request-timeout - timeout for HTTP requests, used only if --local was not defined or user is not root """ del lib modifiers.ensure_only_supported("--local", "--request-timeout") if len(argv) > 1: usage.config(["restore"]) sys.exit(1) infile_name = infile_obj = None if argv: infile_name = argv[0] if not infile_name: # in python3 stdin returns str so we need to use buffer infile_obj = BytesIO(sys.stdin.buffer.read()) if os.getuid() == 0: if modifiers.get("--local"): config_restore_local(infile_name, infile_obj) else: config_restore_remote(infile_name, infile_obj) else: new_argv = ["config", "restore"] new_stdin = None if modifiers.get("--local"): new_argv.append("--local") if infile_name: new_argv.append(os.path.abspath(infile_name)) else: new_stdin = infile_obj.read() err_msgs, exitcode, std_out, std_err = utils.call_local_pcsd( new_argv, new_stdin ) if err_msgs: for msg in err_msgs: utils.err(msg, False) sys.exit(1) print(std_out) sys.stderr.write(std_err) sys.exit(exitcode)
def config_restore(lib, argv, modifiers): """ Options: * --local - restore config only on local node * --request-timeout - timeout for HTTP requests, used only if --local was not defined or user is not root """ del lib modifiers.ensure_only_supported("--local", "--request-timeout") if len(argv) > 1: usage.config(["restore"]) sys.exit(1) infile_name = infile_obj = None if argv: infile_name = argv[0] if not infile_name: # in python3 stdin returns str so we need to use buffer infile_obj = BytesIO(sys.stdin.buffer.read()) if os.getuid() == 0: if modifiers.get("--local"): config_restore_local(infile_name, infile_obj) else: config_restore_remote(infile_name, infile_obj) else: new_argv = ['config', 'restore'] new_stdin = None if modifiers.get("--local"): new_argv.append('--local') if infile_name: new_argv.append(os.path.abspath(infile_name)) else: new_stdin = infile_obj.read() err_msgs, exitcode, std_out, std_err = utils.call_local_pcsd( new_argv, new_stdin ) if err_msgs: for msg in err_msgs: utils.err(msg, False) sys.exit(1) print(std_out) sys.stderr.write(std_err) sys.exit(exitcode)
def config_checkpoint_diff(lib, argv, modifiers): """ Commandline options: * -f - CIB file """ modifiers.ensure_only_supported("-f") if len(argv) != 2: usage.config(["checkpoint diff"]) sys.exit(1) if argv[0] == argv[1]: utils.err("cannot diff a checkpoint against itself") errors = [] checkpoints_lines = [] for checkpoint in argv: if checkpoint == "live": lines = _config_show_cib_lines(lib) if not lines: errors.append("unable to read live configuration") else: checkpoints_lines.append(lines) else: loaded, lines = _checkpoint_to_lines(lib, checkpoint) if not loaded: errors.append( "unable to read checkpoint '{0}'".format(checkpoint) ) else: checkpoints_lines.append(lines) if errors: utils.err("\n".join(errors)) print("Differences between {0} (-) and {1} (+):".format(*[ "live configuration" if label == "live" else f"checkpoint {label}" for label in argv ])) print("\n".join([ line.rstrip() for line in difflib.Differ().compare( checkpoints_lines[0], checkpoints_lines[1] )] ))
def config_cmd(lib, argv, modifiers): if len(argv) == 0: config_show(lib, argv, modifiers) return try: sub_cmd = argv.pop(0) if sub_cmd == "help": usage.config(argv) elif sub_cmd == "show": config_show(lib, argv, modifiers) elif sub_cmd == "backup": config_backup(lib, argv, modifiers) elif sub_cmd == "restore": config_restore(lib, argv, modifiers) elif sub_cmd == "checkpoint": if not argv: config_checkpoint_list(lib, argv, modifiers) elif argv[0] == "view": config_checkpoint_view(lib, argv[1:], modifiers) elif argv[0] == "restore": config_checkpoint_restore(lib, argv[1:], modifiers) else: raise CmdLineInputError() elif sub_cmd == "import-cman": config_import_cman(lib, argv, modifiers) elif sub_cmd == "export": if not argv: raise CmdLineInputError() elif argv[0] == "pcs-commands": config_export_pcs_commands(lib, argv[1:], modifiers) elif argv[0] == "pcs-commands-verbose": config_export_pcs_commands(lib, argv[1:], modifiers, verbose=True) else: raise CmdLineInputError() else: raise CmdLineInputError() except LibraryError as e: utils.process_library_reports(e.args) except CmdLineInputError as e: utils.exit_on_cmdline_input_errror(e, "config", sub_cmd)
def config_cmd(argv): if len(argv) == 0: config_show(argv) return sub_cmd = argv.pop(0) if sub_cmd == "help": usage.config(argv) elif sub_cmd == "show": config_show(argv) elif sub_cmd == "backup": config_backup(argv) elif sub_cmd == "restore": config_restore(argv) elif sub_cmd == "checkpoint": if not argv: config_checkpoint_list() elif argv[0] == "view": config_checkpoint_view(argv[1:]) elif argv[0] == "restore": config_checkpoint_restore(argv[1:]) else: usage.config(["checkpoint"]) sys.exit(1) elif sub_cmd == "import-cman": config_import_cman(argv) elif sub_cmd == "export": if not argv: usage.config(["export"]) sys.exit(1) elif argv[0] == "pcs-commands": config_export_pcs_commands(argv[1:]) elif argv[0] == "pcs-commands-verbose": config_export_pcs_commands(argv[1:], True) else: usage.config(["export"]) sys.exit(1) else: usage.config() sys.exit(1)
def config_restore(argv): if len(argv) > 1: usage.config(["restore"]) sys.exit(1) infile_name = infile_obj = None if argv: infile_name = argv[0] if not infile_name: # in python3 stdin returns str so we need to use buffer if hasattr(sys.stdin, "buffer"): infile_obj = BytesIO(sys.stdin.buffer.read()) else: infile_obj = BytesIO(sys.stdin.read()) if os.getuid() == 0: if "--local" in utils.pcs_options: config_restore_local(infile_name, infile_obj) else: config_restore_remote(infile_name, infile_obj) else: new_argv = ['config', 'restore'] new_stdin = None if '--local' in utils.pcs_options: new_argv.append('--local') if infile_name: new_argv.append(os.path.abspath(infile_name)) else: new_stdin = infile_obj.read() err_msgs, exitcode, std_out, std_err = utils.call_local_pcsd( new_argv, True, new_stdin ) if err_msgs: for msg in err_msgs: utils.err(msg, False) sys.exit(1) print(std_out) sys.stderr.write(std_err) sys.exit(exitcode)
def config_backup(argv): if len(argv) > 1: usage.config(["backup"]) sys.exit(1) outfile_name = None if argv: outfile_name = argv[0] if not outfile_name.endswith(".tar.bz2"): outfile_name += ".tar.bz2" tar_data = config_backup_local() if outfile_name: ok, message = utils.write_file( outfile_name, tar_data, permissions=0o600, binary=True ) if not ok: utils.err(message) else: # in python3 stdout accepts str so we need to use buffer if hasattr(sys.stdout, "buffer"): sys.stdout.buffer.write(tar_data) else: sys.stdout.write(tar_data)
def config_import_cman(lib, argv, modifiers): """ Options: * --force - skip checks, overwrite files * --interactive - interactive issue resolving * --request-timeout - effective only when ouput is not specified """ # pylint: disable=no-member del lib modifiers.ensure_only_supported( "--force", "interactive", "--request-timeout", ) if no_clufter: utils.err( "Unable to perform a CMAN cluster conversion due to missing " "python-clufter package" ) clufter_supports_corosync3 = hasattr(clufter.facts, "cluster_pcs_camelback") # prepare convertor options cluster_conf = settings.cluster_conf_file dry_run_output = None output_format = "corosync.conf" dist = None invalid_args = False for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "input": cluster_conf = value elif name == "output": dry_run_output = value elif name == "output-format": if value in ( "corosync.conf", "pcs-commands", "pcs-commands-verbose", ): output_format = value else: invalid_args = True elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True if ( output_format not in ("pcs-commands", "pcs-commands-verbose") and (dry_run_output and not dry_run_output.endswith(".tar.bz2")) ): dry_run_output += ".tar.bz2" if invalid_args or not dry_run_output: usage.config(["import-cman"]) sys.exit(1) debug = modifiers.get("--debug") force = modifiers.get("--force") interactive = modifiers.get("--interactive") if dist is not None: if not clufter_supports_corosync3: utils.err( "Unable to perform a CMAN cluster conversion due to clufter " "not supporting Corosync 3. Please, upgrade clufter packages." ) if not clufter.facts.cluster_pcs_camelback("linux", dist.split(",")): utils.err("dist does not match output-format") elif output_format == "corosync.conf": dist = _get_linux_dist() else: # for output-format=pcs-command[-verbose] dist = _get_linux_dist() clufter_args = { "input": str(cluster_conf), "cib": {"passin": "bytestring"}, "nocheck": force, "batch": True, "sys": "linux", "dist": dist, } if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if output_format == "corosync.conf": clufter_args["coro"] = {"passin": "struct"} cmd_name = "ccs2pcs-camelback" elif output_format in ("pcs-commands", "pcs-commands-verbose"): clufter_args["output"] = {"passin": "bytestring"} clufter_args["start_wait"] = "60" clufter_args["tmp_cib"] = "tmp-cib.xml" clufter_args["force"] = force clufter_args["text_width"] = "80" clufter_args["silent"] = True clufter_args["noguidance"] = True if output_format == "pcs-commands-verbose": clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False if clufter.facts.cluster_pcs_flatiron("linux", dist.split(",")): cmd_name = "ccs2pcscmd-flatiron" elif clufter.facts.cluster_pcs_needle("linux", dist.split(",")): cmd_name = "ccs2pcscmd-needle" elif ( clufter_supports_corosync3 and clufter.facts.cluster_pcs_camelback("linux", dist.split(",")) ): cmd_name = "ccs2pcscmd-camelback" else: utils.err( "unrecognized dist, try something recognized" + " (e. g. rhel,6.8 or redhat,7.3 or debian,7 or ubuntu,trusty)" ) clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to import cluster configuration" ) # save commands if output_format in ("pcs-commands", "pcs-commands-verbose"): ok, message = utils.write_file( dry_run_output, clufter_args_obj.output["passout"].decode() ) if not ok: utils.err(message) return # put new config files into tarball file_list = config_backup_path_list() for file_item in file_list.values(): file_item["attrs"]["uname"] = "root" file_item["attrs"]["gname"] = "root" file_item["attrs"]["uid"] = 0 file_item["attrs"]["gid"] = 0 file_item["attrs"]["mode"] = 0o600 tar_data = BytesIO() try: tarball = tarfile.open(fileobj=tar_data, mode="w|bz2") config_backup_add_version_to_tarball(tarball) utils.tar_add_file_data( tarball, clufter_args_obj.cib["passout"], "cib.xml", **file_list["cib.xml"]["attrs"] ) # put uidgid into separate files fmt_simpleconfig = clufter.format_manager.FormatManager.init_lookup( 'simpleconfig' ).plugins['simpleconfig'] corosync_struct = [] uidgid_list = [] for section in clufter_args_obj.coro["passout"][2]: if section[0] == "uidgid": uidgid_list.append(section[1]) else: corosync_struct.append(section) corosync_conf_data = fmt_simpleconfig( "struct", ("corosync", (), corosync_struct) )("bytestring") utils.tar_add_file_data( tarball, corosync_conf_data, "corosync.conf", **file_list["corosync.conf"]["attrs"] ) for uidgid in uidgid_list: uid = "" gid = "" for item in uidgid: if item[0] == "uid": uid = item[1] if item[0] == "gid": gid = item[1] filename = utils.get_uid_gid_file_name(uid, gid) uidgid_data = fmt_simpleconfig( "struct", ("corosync", (), [("uidgid", uidgid, None)]) )("bytestring") utils.tar_add_file_data( tarball, uidgid_data, "uidgid.d/" + filename, **file_list["uidgid.d"]["attrs"] ) tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to create tarball: %s" % e) tar_data.seek(0) #save tarball / remote restore if dry_run_output: ok, message = utils.write_file( dry_run_output, tar_data.read(), permissions=0o600, binary=True ) if not ok: utils.err(message) else: config_restore_remote(None, tar_data) tar_data.close()
def config_export_pcs_commands(lib, argv, modifiers, verbose=False): """ Options: * --force - skip checks, overwrite files * --interactive - interactive issue resolving * -f - CIB file * --corosync_conf """ del lib modifiers.ensure_only_supported( "--force", "--interactive", "-f", "--corosync_conf" ) if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package" ) # parse options debug = modifiers.get("--debug") force = modifiers.get("--force") interactive = modifiers.get("--interactive") invalid_args = False output_file = None dist = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True # check options if invalid_args: usage.config(["export pcs-commands"]) sys.exit(1) # complete optional options if dist is None: dist = _get_linux_dist() # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", "dist": dist, "coro": settings.corosync_conf_file, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if output_file: clufter_args["output"] = {"passin": "bytestring"} else: clufter_args["output"] = "-" if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-camelback" # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration" ) # save commands if not printed to stdout by clufter if output_file: # pylint: disable=no-member ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"].decode() ) if not ok: utils.err(message)
def config_export_pcs_commands(argv, verbose=False): if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package") # parse options debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options invalid_args = False output_file = None dist = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True # check options if invalid_args: usage.config(["export", "pcs-commands"]) sys.exit(1) # complete optional options if dist is None: dist = ",".join(platform.linux_distribution(full_distribution_name=0)) # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", "dist": dist, "coro": settings.corosync_conf_file, "ccs": settings.cluster_conf_file, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if output_file: clufter_args["output"] = {"passin": "bytestring"} else: clufter_args["output"] = "-" if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-flatiron" if utils.is_rhel6( ) else "pcs2pcscmd-needle" # run convertor run_clufter(cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration") # save commands if not printed to stdout by clufter if output_file: ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"].decode()) if not ok: utils.err(message)
def config_import_cman(argv): if no_clufter: utils.err("Unable to perform a CMAN cluster conversion due to missing python-clufter package") # prepare convertor options cluster_conf = settings.cluster_conf_file dry_run_output = None output_format = "cluster.conf" if utils.is_rhel6() else "corosync.conf" dist = None invalid_args = False for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "input": cluster_conf = value elif name == "output": dry_run_output = value elif name == "output-format": if value in ( "cluster.conf", "corosync.conf", "pcs-commands", "pcs-commands-verbose", ): output_format = value else: invalid_args = True elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True if ( output_format not in ("pcs-commands", "pcs-commands-verbose") and (dry_run_output and not dry_run_output.endswith(".tar.bz2")) ): dry_run_output += ".tar.bz2" if invalid_args or not dry_run_output: usage.config(["import-cman"]) sys.exit(1) debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options if dist is not None: if output_format == "cluster.conf": if not clufter.facts.cluster_pcs_flatiron("linux", dist.split(",")): utils.err("dist does not match output-format") elif output_format == "corosync.conf": if not clufter.facts.cluster_pcs_needle("linux", dist.split(",")): utils.err("dist does not match output-format") elif ( (output_format == "cluster.conf" and utils.is_rhel6()) or (output_format == "corosync.conf" and not utils.is_rhel6()) ): dist = ",".join(platform.linux_distribution(full_distribution_name=0)) elif output_format == "cluster.conf": dist = "redhat,6.7,Santiago" elif output_format == "corosync.conf": dist = "redhat,7.1,Maipo" else: # for output-format=pcs-command[-verbose] dist = ",".join(platform.linux_distribution(full_distribution_name=0)) clufter_args = { "input": str(cluster_conf), "cib": {"passin": "bytestring"}, "nocheck": force, "batch": True, "sys": "linux", "dist": dist, # Make it work on RHEL6 as well for sure "color": "always" if sys.stdout.isatty() else "never" } if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if output_format == "cluster.conf": clufter_args["ccs_pcmk"] = {"passin": "bytestring"} cmd_name = "ccs2pcs-flatiron" elif output_format == "corosync.conf": clufter_args["coro"] = {"passin": "struct"} cmd_name = "ccs2pcs-needle" elif output_format in ("pcs-commands", "pcs-commands-verbose"): clufter_args["output"] = {"passin": "bytestring"} clufter_args["start_wait"] = "60" clufter_args["tmp_cib"] = "tmp-cib.xml" clufter_args["force"] = force clufter_args["text_width"] = "80" clufter_args["silent"] = True clufter_args["noguidance"] = True if output_format == "pcs-commands-verbose": clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False if clufter.facts.cluster_pcs_flatiron("linux", dist.split(",")): cmd_name = "ccs2pcscmd-flatiron" elif clufter.facts.cluster_pcs_needle("linux", dist.split(",")): cmd_name = "ccs2pcscmd-needle" else: utils.err( "unrecognized dist, try something recognized" + " (e. g. rhel,6.8 or redhat,7.3 or debian,7 or ubuntu,trusty)" ) clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to import cluster configuration" ) # save commands if output_format in ("pcs-commands", "pcs-commands-verbose"): ok, message = utils.write_file( dry_run_output, clufter_args_obj.output["passout"] ) if not ok: utils.err(message) return # put new config files into tarball file_list = config_backup_path_list( force_rhel6=(output_format == "cluster.conf") ) for file_item in file_list.values(): file_item["attrs"]["uname"] = "root" file_item["attrs"]["gname"] = "root" file_item["attrs"]["uid"] = 0 file_item["attrs"]["gid"] = 0 file_item["attrs"]["mode"] = 0o600 tar_data = BytesIO() try: tarball = tarfile.open(fileobj=tar_data, mode="w|bz2") config_backup_add_version_to_tarball(tarball) utils.tar_add_file_data( tarball, clufter_args_obj.cib["passout"].encode("utf-8"), "cib.xml", **file_list["cib.xml"]["attrs"] ) if output_format == "cluster.conf": utils.tar_add_file_data( tarball, clufter_args_obj.ccs_pcmk["passout"].encode("utf-8"), "cluster.conf", **file_list["cluster.conf"]["attrs"] ) else: # put uidgid into separate files fmt_simpleconfig = clufter.format_manager.FormatManager.init_lookup( 'simpleconfig' ).plugins['simpleconfig'] corosync_struct = [] uidgid_list = [] for section in clufter_args_obj.coro["passout"][2]: if section[0] == "uidgid": uidgid_list.append(section[1]) else: corosync_struct.append(section) corosync_conf_data = fmt_simpleconfig( "struct", ("corosync", (), corosync_struct) )("bytestring") utils.tar_add_file_data( tarball, corosync_conf_data.encode("utf-8"), "corosync.conf", **file_list["corosync.conf"]["attrs"] ) for uidgid in uidgid_list: uid = "" gid = "" for item in uidgid: if item[0] == "uid": uid = item[1] if item[0] == "gid": gid = item[1] filename = utils.get_uid_gid_file_name(uid, gid) uidgid_data = fmt_simpleconfig( "struct", ("corosync", (), [("uidgid", uidgid, None)]) )("bytestring") utils.tar_add_file_data( tarball, uidgid_data.encode("utf-8"), "uidgid.d/" + filename, **file_list["uidgid.d"]["attrs"] ) tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to create tarball: %s" % e) tar_data.seek(0) #save tarball / remote restore if dry_run_output: ok, message = utils.write_file( dry_run_output, tar_data.read(), permissions=0o600, binary=True ) if not ok: utils.err(message) else: config_restore_remote(None, tar_data) tar_data.close()
def config_import_cman(lib, argv, modifiers): """ Options: * --force - skip checks, overwrite files * --interactive - interactive issue resolving * --request-timeout - effective only when ouput is not specified """ # pylint: disable=no-member del lib modifiers.ensure_only_supported( "--force", "interactive", "--request-timeout", ) if no_clufter: utils.err("Unable to perform a CMAN cluster conversion due to missing " "python-clufter package") clufter_supports_corosync3 = hasattr(clufter.facts, "cluster_pcs_camelback") # prepare convertor options cluster_conf = settings.cluster_conf_file dry_run_output = None output_format = "corosync.conf" dist = None invalid_args = False for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "input": cluster_conf = value elif name == "output": dry_run_output = value elif name == "output-format": if value in ( "corosync.conf", "pcs-commands", "pcs-commands-verbose", ): output_format = value else: invalid_args = True elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True if output_format not in ("pcs-commands", "pcs-commands-verbose") and ( dry_run_output and not dry_run_output.endswith(".tar.bz2")): dry_run_output += ".tar.bz2" if invalid_args or not dry_run_output: usage.config(["import-cman"]) sys.exit(1) debug = modifiers.get("--debug") force = modifiers.get("--force") interactive = modifiers.get("--interactive") if dist is not None: if not clufter_supports_corosync3: utils.err( "Unable to perform a CMAN cluster conversion due to clufter " "not supporting Corosync 3. Please, upgrade clufter packages.") if not clufter.facts.cluster_pcs_camelback("linux", dist.split(",")): utils.err("dist does not match output-format") elif output_format == "corosync.conf": dist = _get_linux_dist() else: # for output-format=pcs-command[-verbose] dist = _get_linux_dist() clufter_args = { "input": str(cluster_conf), "cib": { "passin": "bytestring" }, "nocheck": force, "batch": True, "sys": "linux", "dist": dist, } if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if output_format == "corosync.conf": clufter_args["coro"] = {"passin": "struct"} cmd_name = "ccs2pcs-camelback" elif output_format in ("pcs-commands", "pcs-commands-verbose"): clufter_args["output"] = {"passin": "bytestring"} clufter_args["start_wait"] = "60" clufter_args["tmp_cib"] = "tmp-cib.xml" clufter_args["force"] = force clufter_args["text_width"] = "80" clufter_args["silent"] = True clufter_args["noguidance"] = True if output_format == "pcs-commands-verbose": clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False if clufter.facts.cluster_pcs_flatiron("linux", dist.split(",")): cmd_name = "ccs2pcscmd-flatiron" elif clufter.facts.cluster_pcs_needle("linux", dist.split(",")): cmd_name = "ccs2pcscmd-needle" elif clufter_supports_corosync3 and clufter.facts.cluster_pcs_camelback( "linux", dist.split(",")): cmd_name = "ccs2pcscmd-camelback" else: utils.err( "unrecognized dist, try something recognized" + " (e. g. rhel,6.8 or redhat,7.3 or debian,7 or ubuntu,trusty)") clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to import cluster configuration", ) # save commands if output_format in ("pcs-commands", "pcs-commands-verbose"): ok, message = utils.write_file( dry_run_output, clufter_args_obj.output["passout"].decode()) if not ok: utils.err(message) return # put new config files into tarball file_list = config_backup_path_list() for file_item in file_list.values(): file_item["attrs"]["uname"] = "root" file_item["attrs"]["gname"] = "root" file_item["attrs"]["uid"] = 0 file_item["attrs"]["gid"] = 0 file_item["attrs"]["mode"] = 0o600 tar_data = BytesIO() try: tarball = tarfile.open(fileobj=tar_data, mode="w|bz2") config_backup_add_version_to_tarball(tarball) utils.tar_add_file_data( tarball, clufter_args_obj.cib["passout"], "cib.xml", **file_list["cib.xml"]["attrs"], ) # put uidgid into separate files fmt_simpleconfig = clufter.format_manager.FormatManager.init_lookup( "simpleconfig").plugins["simpleconfig"] corosync_struct = [] uidgid_list = [] for section in clufter_args_obj.coro["passout"][2]: if section[0] == "uidgid": uidgid_list.append(section[1]) else: corosync_struct.append(section) corosync_conf_data = fmt_simpleconfig( "struct", ("corosync", (), corosync_struct))("bytestring") utils.tar_add_file_data( tarball, corosync_conf_data, "corosync.conf", **file_list["corosync.conf"]["attrs"], ) for uidgid in uidgid_list: uid = "" gid = "" for item in uidgid: if item[0] == "uid": uid = item[1] if item[0] == "gid": gid = item[1] filename = utils.get_uid_gid_file_name(uid, gid) uidgid_data = fmt_simpleconfig( "struct", ("corosync", (), [("uidgid", uidgid, None)]))("bytestring") utils.tar_add_file_data( tarball, uidgid_data, "uidgid.d/" + filename, **file_list["uidgid.d"]["attrs"], ) tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to create tarball: %s" % e) tar_data.seek(0) # save tarball / remote restore if dry_run_output: ok, message = utils.write_file(dry_run_output, tar_data.read(), permissions=0o600, binary=True) if not ok: utils.err(message) else: config_restore_remote(None, tar_data) tar_data.close()
from pcs import ( config, usage, ) from pcs.cli.common.routing import create_router config_cmd = create_router( { "help": lambda lib, argv, modifiers: usage.config(argv), "show": config.config_show, "backup": config.config_backup, "restore": config.config_restore, "checkpoint": create_router( { "list": config.config_checkpoint_list, "view": config.config_checkpoint_view, "restore": config.config_checkpoint_restore, "diff": config.config_checkpoint_diff, }, ["config", "checkpoint"], default_cmd="list"), "import-cman": config.config_import_cman, "export": create_router( { "pcs-commands":
def config_export_pcs_commands(argv, verbose=False): if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package" ) # parse options debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options invalid_args = False output_file = None dist = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True # check options if invalid_args: usage.config(["export", "pcs-commands"]) sys.exit(1) # complete optional options if dist is None: dist = ",".join(platform.linux_distribution(full_distribution_name=0)) # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", "dist": dist, # Make it work on RHEL6 as well for sure "color": "always" if sys.stdout.isatty() else "never", "coro": settings.corosync_conf_file, "ccs": settings.cluster_conf_file, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if output_file: clufter_args["output"] = {"passin": "bytestring"} else: clufter_args["output"] = "-" if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-flatiron" if utils.is_rhel6() else "pcs2pcscmd-needle" # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration" ) # save commands if not printed to stdout by clufter if output_file: ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"] ) if not ok: utils.err(message)
from pcs import ( config, usage, ) from pcs.cli.common.routing import create_router config_cmd = create_router( { "help": lambda lib, argv, modifiers: usage.config(argv), "show": config.config_show, "backup": config.config_backup, "restore": config.config_restore, "checkpoint": create_router( { "list": config.config_checkpoint_list, "view": config.config_checkpoint_view, "restore": config.config_checkpoint_restore, "diff": config.config_checkpoint_diff, }, ["config", "checkpoint"], default_cmd="list" ), "import-cman": config.config_import_cman, "export": create_router( { "pcs-commands": config.config_export_pcs_commands, "pcs-commands-verbose": lambda lib, argv, modifiers: config.config_export_pcs_commands( lib, argv, modifiers, verbose=True )
def config_export_pcs_commands(lib, argv, modifiers, verbose=False): """ Options: * --force - skip checks, overwrite files * --interactive - interactive issue resolving * -f - CIB file * --corosync_conf """ del lib modifiers.ensure_only_supported("--force", "--interactive", "-f", "--corosync_conf") if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package") # parse options debug = modifiers.get("--debug") force = modifiers.get("--force") interactive = modifiers.get("--interactive") invalid_args = False output_file = None dist = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True # check options if invalid_args: usage.config(["export pcs-commands"]) sys.exit(1) # complete optional options if dist is None: dist = _get_linux_dist() # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", "dist": dist, "coro": settings.corosync_conf_file, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if output_file: clufter_args["output"] = {"passin": "bytestring"} else: clufter_args["output"] = "-" if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-camelback" # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration", ) # save commands if not printed to stdout by clufter if output_file: # pylint: disable=no-member ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"].decode()) if not ok: utils.err(message)
from pcs import ( config, usage, ) from pcs.cli.common.routing import create_router config_cmd = create_router( { "help": lambda lib, argv, modifiers: print(usage.config(argv)), "show": config.config_show, "backup": config.config_backup, "restore": config.config_restore, "checkpoint": create_router( { "list": config.config_checkpoint_list, "view": config.config_checkpoint_view, "restore": config.config_checkpoint_restore, "diff": config.config_checkpoint_diff, }, ["config", "checkpoint"], default_cmd="list", ), }, ["config"], default_cmd="show", )