Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624119
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 5a7b3825bd..62b3bc0359 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,158 +1,159 @@
#
# Copyright 2004-2019 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
include $(top_srcdir)/Makefile.common
if BUILD_SYSTEMD
systemdsystemunit_DATA = crm_mon.service
endif
noinst_HEADERS = crm_mon.h crm_resource.h
pcmkdir = $(datadir)/$(PACKAGE)
pcmk_DATA = report.common report.collector
sbin_SCRIPTS = crm_report crm_standby crm_master crm_failcount
if BUILD_CIBSECRETS
sbin_SCRIPTS += cibsecret
endif
noinst_SCRIPTS = pcmk_simtimes
-EXTRA_DIST = crm_mon.sysconfig \
+EXTRA_DIST = crm_diff.8.inc \
+ crm_mon.sysconfig \
crm_mon.8.inc \
crm_node.8.inc \
stonith_admin.8.inc
sbin_PROGRAMS = attrd_updater \
cibadmin \
crmadmin \
crm_simulate \
crm_attribute \
crm_diff \
crm_error \
crm_mon \
crm_node \
crm_resource \
crm_rule \
crm_shadow \
crm_verify \
crm_ticket \
iso8601 \
stonith_admin
if BUILD_SERVICELOG
sbin_PROGRAMS += notifyServicelogEvent
endif
if BUILD_OPENIPMI_SERVICELOG
sbin_PROGRAMS += ipmiservicelogd
endif
## SOURCES
# A few tools are just thin wrappers around crm_attribute.
# This makes their help get updated when crm_attribute changes
# (see Makefile.common).
MAN8DEPS = crm_attribute
crmadmin_SOURCES = crmadmin.c
crmadmin_LDADD = $(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
crm_error_SOURCES = crm_error.c
crm_error_LDADD = $(top_builddir)/lib/common/libcrmcommon.la
cibadmin_SOURCES = cibadmin.c
cibadmin_LDADD = $(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
crm_shadow_SOURCES = crm_shadow.c
crm_shadow_LDADD = $(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
crm_node_SOURCES = crm_node.c
crm_node_LDADD = $(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
crm_simulate_SOURCES = crm_simulate.c
crm_simulate_LDADD = $(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/pacemaker/libpacemaker.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
crm_diff_SOURCES = crm_diff.c
crm_diff_LDADD = $(top_builddir)/lib/common/libcrmcommon.la
crm_mon_SOURCES = crm_mon.c crm_mon_curses.c crm_mon_output.c crm_mon_print.c crm_mon_runtime.c crm_mon_xml.c
crm_mon_LDADD = $(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/fencing/libstonithd.la \
$(top_builddir)/lib/pacemaker/libpacemaker.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la \
$(CURSESLIBS)
crm_verify_SOURCES = crm_verify.c
crm_verify_LDADD = $(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/pacemaker/libpacemaker.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
crm_attribute_SOURCES = crm_attribute.c
crm_attribute_LDADD = $(top_builddir)/lib/cluster/libcrmcluster.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
crm_resource_SOURCES = crm_resource.c crm_resource_ban.c crm_resource_runtime.c crm_resource_print.c
crm_resource_LDADD = $(top_builddir)/lib/pengine/libpe_rules.la \
$(top_builddir)/lib/fencing/libstonithd.la \
$(top_builddir)/lib/lrmd/liblrmd.la \
$(top_builddir)/lib/services/libcrmservice.la \
$(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/pacemaker/libpacemaker.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
crm_rule_SOURCES = crm_rule.c
crm_rule_LDADD = $(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/pengine/libpe_rules.la \
$(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/common/libcrmcommon.la
iso8601_SOURCES = iso8601.c
iso8601_LDADD = $(top_builddir)/lib/common/libcrmcommon.la
attrd_updater_SOURCES = attrd_updater.c
attrd_updater_LDADD = $(top_builddir)/lib/common/libcrmcommon.la
crm_ticket_SOURCES = crm_ticket.c
crm_ticket_LDADD = $(top_builddir)/lib/pengine/libpe_rules.la \
$(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/pacemaker/libpacemaker.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/common/libcrmcommon.la
stonith_admin_SOURCES = stonith_admin.c
stonith_admin_LDADD = $(top_builddir)/lib/common/libcrmcommon.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/fencing/libstonithd.la
if BUILD_SERVICELOG
notifyServicelogEvent_SOURCES = notifyServicelogEvent.c
notifyServicelogEvent_CFLAGS = $(SERVICELOG_CFLAGS)
notifyServicelogEvent_LDADD = $(top_builddir)/lib/common/libcrmcommon.la $(SERVICELOG_LIBS)
endif
if BUILD_OPENIPMI_SERVICELOG
ipmiservicelogd_SOURCES = ipmiservicelogd.c
ipmiservicelogd_CFLAGS = $(OPENIPMI_SERVICELOG_CFLAGS) $(SERVICELOG_CFLAGS)
ipmiservicelogd_LDFLAGS = $(top_builddir)/lib/common/libcrmcommon.la $(OPENIPMI_SERVICELOG_LIBS) $(SERVICELOG_LIBS)
endif
CLEANFILES = $(man8_MANS)
diff --git a/tools/crm_diff.8.inc b/tools/crm_diff.8.inc
new file mode 100644
index 0000000000..4229cbf8f3
--- /dev/null
+++ b/tools/crm_diff.8.inc
@@ -0,0 +1,5 @@
+[synopsis]
+crm_diff original_xml operation [options]
+
+/as a patch/
+.SH OPTIONS
diff --git a/tools/crm_diff.c b/tools/crm_diff.c
index 6a03040129..8722646ea5 100644
--- a/tools/crm_diff.c
+++ b/tools/crm_diff.c
@@ -1,351 +1,394 @@
/*
* Copyright 2005-2018 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU General Public License version 2
* or later (GPLv2+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
+#include <crm/common/cmdline_internal.h>
#include <crm/common/xml.h>
#include <crm/common/ipc.h>
#include <crm/cib.h>
-/* *INDENT-OFF* */
-static struct crm_option long_options[] = {
- /* Top-level Options */
- {"help", 0, 0, '?', "\t\tThis text"},
- {"version", 0, 0, '$', "\t\tVersion information" },
- {"verbose", 0, 0, 'V', "\t\tIncrease debug output\n"},
-
- {"-spacer-", 1, 0, '-', "\nOriginal XML:"},
- {"original", 1, 0, 'o', "\tXML is contained in the named file"},
- {"original-string", 1, 0, 'O', "XML is contained in the supplied string"},
-
- {"-spacer-", 1, 0, '-', "\nOperation:"},
- {"new", 1, 0, 'n', "\tCompare the original XML to the contents of the named file"},
- {"new-string", 1, 0, 'N', "\tCompare the original XML to the contents of the supplied string"},
- {"patch", 1, 0, 'p', "\tPatch the original XML with the contents of the named file"},
-
- {"-spacer-", 1, 0, '-', "\nAdditional Options:"},
- {"cib", 0, 0, 'c', "\t\tCompare/patch the inputs as a CIB (includes versions details)"},
- {"stdin", 0, 0, 's', NULL, 1},
- {"no-version", 0, 0, 'u', "\tGenerate the difference without versions details"},
- {"-spacer-", 1, 0, '-', "\nExamples:", pcmk_option_paragraph},
- {"-spacer-", 1, 0, '-', "Obtain the two different configuration files by running cibadmin on the two cluster setups to compare:", pcmk_option_paragraph},
- {"-spacer-", 1, 0, '-', " cibadmin --query > cib-old.xml", pcmk_option_example},
- {"-spacer-", 1, 0, '-', " cibadmin --query > cib-new.xml", pcmk_option_example},
- {"-spacer-", 1, 0, '-', "Calculate and save the difference between the two files:", pcmk_option_paragraph},
- {"-spacer-", 1, 0, '-', " crm_diff --original cib-old.xml --new cib-new.xml > patch.xml", pcmk_option_example },
- {"-spacer-", 1, 0, '-', "Apply the patch to the original file:", pcmk_option_paragraph },
- {"-spacer-", 1, 0, '-', " crm_diff --original cib-old.xml --patch patch.xml > updated.xml", pcmk_option_example },
- {"-spacer-", 1, 0, '-', "Apply the patch to the running cluster:", pcmk_option_paragraph },
- {"-spacer-", 1, 0, '-', " cibadmin --patch patch.xml", pcmk_option_example },
-
- {0, 0, 0, 0}
+#define SUMMARY "Compare two Pacemaker configurations (in XML format) to produce a custom diff-like output, " \
+ "or apply such an output as a patch"
+
+struct {
+ gboolean apply;
+ gboolean as_cib;
+ gboolean no_version;
+ gboolean raw_1;
+ gboolean raw_2;
+ gboolean use_stdin;
+ char *xml_file_1;
+ char *xml_file_2;
+} options;
+
+gboolean new_string_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
+gboolean original_string_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
+gboolean patch_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
+
+static GOptionEntry original_xml_entries[] = {
+ { "original", 'o', 0, G_OPTION_ARG_STRING, &options.xml_file_1,
+ "XML is contained in the named file",
+ "FILE" },
+ { "original-string", 'O', 0, G_OPTION_ARG_CALLBACK, original_string_cb,
+ "XML is contained in the supplied string",
+ "STRING" },
+
+ { NULL }
};
-/* *INDENT-ON* */
+
+static GOptionEntry operation_entries[] = {
+ { "new", 'n', 0, G_OPTION_ARG_STRING, &options.xml_file_2,
+ "Compare the original XML to the contents of the named file",
+ "FILE" },
+ { "new-string", 'N', 0, G_OPTION_ARG_CALLBACK, new_string_cb,
+ "Compare the original XML with the contents of the supplied string",
+ "STRING" },
+ { "patch", 'p', 0, G_OPTION_ARG_CALLBACK, patch_cb,
+ "Patch the original XML with the contents of the named file",
+ "FILE" },
+
+ { NULL }
+};
+
+static GOptionEntry addl_entries[] = {
+ { "cib", 'c', 0, G_OPTION_ARG_NONE, &options.as_cib,
+ "Compare/patch the inputs as a CIB (includes versions details)",
+ NULL },
+ { "stdin", 's', 0, G_OPTION_ARG_NONE, &options.use_stdin,
+ "",
+ NULL },
+ { "no-version", 'u', 0, G_OPTION_ARG_NONE, &options.no_version,
+ "Generate the difference without versions details",
+ NULL },
+
+ { NULL }
+};
+
+gboolean
+new_string_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
+ options.raw_2 = TRUE;
+
+ if (options.xml_file_2 != NULL) {
+ free(options.xml_file_2);
+ }
+
+ options.xml_file_2 = strdup(optarg);
+ return TRUE;
+}
+
+gboolean
+original_string_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
+ options.raw_1 = TRUE;
+
+ if (options.xml_file_1 != NULL) {
+ free(options.xml_file_1);
+ }
+
+ options.xml_file_1 = strdup(optarg);
+ return TRUE;
+}
+
+gboolean
+patch_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
+ options.apply = TRUE;
+
+ if (options.xml_file_2 != NULL) {
+ free(options.xml_file_2);
+ }
+
+ options.xml_file_2 = strdup(optarg);
+ return TRUE;
+}
static void
print_patch(xmlNode *patch)
{
char *buffer = dump_xml_formatted(patch);
printf("%s\n", crm_str(buffer));
free(buffer);
fflush(stdout);
}
static int
apply_patch(xmlNode *input, xmlNode *patch, gboolean as_cib)
{
int rc;
xmlNode *output = copy_xml(input);
rc = xml_apply_patchset(output, patch, as_cib);
if (rc != pcmk_ok) {
fprintf(stderr, "Could not apply patch: %s\n", pcmk_strerror(rc));
free_xml(output);
return rc;
}
if (output != NULL) {
const char *version;
char *buffer;
print_patch(output);
version = crm_element_value(output, XML_ATTR_CRM_VERSION);
buffer = calculate_xml_versioned_digest(output, FALSE, TRUE, version);
crm_trace("Digest: %s\n", crm_str(buffer));
free(buffer);
free_xml(output);
}
return pcmk_ok;
}
static void
log_patch_cib_versions(xmlNode *patch)
{
int add[] = { 0, 0, 0 };
int del[] = { 0, 0, 0 };
const char *fmt = NULL;
const char *digest = NULL;
xml_patch_versions(patch, add, del);
fmt = crm_element_value(patch, "format");
digest = crm_element_value(patch, XML_ATTR_DIGEST);
if (add[2] != del[2] || add[1] != del[1] || add[0] != del[0]) {
crm_info("Patch: --- %d.%d.%d %s", del[0], del[1], del[2], fmt);
crm_info("Patch: +++ %d.%d.%d %s", add[0], add[1], add[2], digest);
}
}
static void
strip_patch_cib_version(xmlNode *patch, const char **vfields, size_t nvfields)
{
int format = 1;
crm_element_value_int(patch, "format", &format);
if (format == 2) {
xmlNode *version_xml = find_xml_node(patch, "version", FALSE);
if (version_xml) {
free_xml(version_xml);
}
} else {
int i = 0;
const char *tags[] = {
XML_TAG_DIFF_REMOVED,
XML_TAG_DIFF_ADDED,
};
for (i = 0; i < DIMOF(tags); i++) {
xmlNode *tmp = NULL;
int lpc;
tmp = find_xml_node(patch, tags[i], FALSE);
if (tmp) {
for (lpc = 0; lpc < nvfields; lpc++) {
xml_remove_prop(tmp, vfields[lpc]);
}
tmp = find_xml_node(tmp, XML_TAG_CIB, FALSE);
if (tmp) {
for (lpc = 0; lpc < nvfields; lpc++) {
xml_remove_prop(tmp, vfields[lpc]);
}
}
}
}
}
}
static int
generate_patch(xmlNode *object_1, xmlNode *object_2, const char *xml_file_2,
gboolean as_cib, gboolean no_version)
{
xmlNode *output = NULL;
const char *vfields[] = {
XML_ATTR_GENERATION_ADMIN,
XML_ATTR_GENERATION,
XML_ATTR_NUMUPDATES,
};
/* If we're ignoring the version, make the version information
* identical, so it isn't detected as a change. */
if (no_version) {
int lpc;
for (lpc = 0; lpc < DIMOF(vfields); lpc++) {
crm_copy_xml_element(object_1, object_2, vfields[lpc]);
}
}
xml_track_changes(object_2, NULL, object_2, FALSE);
if(as_cib) {
xml_calculate_significant_changes(object_1, object_2);
} else {
xml_calculate_changes(object_1, object_2);
}
crm_log_xml_debug(object_2, (xml_file_2? xml_file_2: "target"));
output = xml_create_patchset(0, object_1, object_2, NULL, FALSE);
xml_log_changes(LOG_INFO, __FUNCTION__, object_2);
xml_accept_changes(object_2);
if (output == NULL) {
return pcmk_ok;
}
patchset_process_digest(output, object_1, object_2, as_cib);
if (as_cib) {
log_patch_cib_versions(output);
} else if (no_version) {
strip_patch_cib_version(output, vfields, DIMOF(vfields));
}
xml_log_patchset(LOG_NOTICE, __FUNCTION__, output);
print_patch(output);
free_xml(output);
return -pcmk_err_generic;
}
+static GOptionContext *
+build_arg_context(pcmk__common_args_t *args) {
+ GOptionContext *context = NULL;
+
+ const char *description = "*Examples*\n\n"
+ "Obtain the two different configuration files by running cibadmin on the two cluster setups to compare:\n\n"
+ "\tcibadmin --query > cib-old.xml\n"
+ "\tcibadmin --query > cib-new.xml\n\n"
+ "Calculate and save the difference between the two files:\n\n"
+ "\tcrm_diff --original cib-old.xml --new cib-new.xml > patch.xml\n\n"
+ "Apply the patch to the original file:\n\n"
+ "\tcrm_diff --original cib-old.xml --patch patch.xml > updated.xml\n\n"
+ "Apply the patch to the running cluster:\n\n"
+ "\tcibadmin --patch patch.xml\n";
+
+ context = pcmk__build_arg_context(args, NULL, NULL);
+ g_option_context_set_description(context, description);
+
+ pcmk__add_arg_group(context, "xml", "Original XML:",
+ "Show original XML options", original_xml_entries);
+ pcmk__add_arg_group(context, "operation", "Operation:",
+ "Show operation options", operation_entries);
+ pcmk__add_arg_group(context, "additional", "Additional Options:",
+ "Show additional options", addl_entries);
+ return context;
+}
+
int
main(int argc, char **argv)
{
- gboolean apply = FALSE;
- gboolean raw_1 = FALSE;
- gboolean raw_2 = FALSE;
- gboolean use_stdin = FALSE;
- gboolean as_cib = FALSE;
- gboolean no_version = FALSE;
- int argerr = 0;
- int flag;
int rc = pcmk_ok;
xmlNode *object_1 = NULL;
xmlNode *object_2 = NULL;
- const char *xml_file_1 = NULL;
- const char *xml_file_2 = NULL;
- int option_index = 0;
+ pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
+
+ GError *error = NULL;
+ GOptionContext *context = NULL;
+ gchar **processed_args = NULL;
+
+ context = build_arg_context(args);
crm_log_cli_init("crm_diff");
- crm_set_options(NULL, "original_xml operation [options]", long_options,
- "crm_diff can compare two Pacemaker configurations (in XML format) to\n"
- "produce a custom diff-like output, or apply such an output as a patch\n");
- if (argc < 2) {
- crm_help('?', CRM_EX_USAGE);
- }
+ processed_args = pcmk__cmdline_preproc(argc, argv, "nopNO");
- while (1) {
- flag = crm_get_option(argc, argv, &option_index);
- if (flag == -1)
- break;
-
- switch (flag) {
- case 'o':
- xml_file_1 = optarg;
- break;
- case 'O':
- xml_file_1 = optarg;
- raw_1 = TRUE;
- break;
- case 'n':
- xml_file_2 = optarg;
- break;
- case 'N':
- xml_file_2 = optarg;
- raw_2 = TRUE;
- break;
- case 'p':
- xml_file_2 = optarg;
- apply = TRUE;
- break;
- case 's':
- use_stdin = TRUE;
- break;
- case 'c':
- as_cib = TRUE;
- break;
- case 'u':
- no_version = TRUE;
- break;
- case 'V':
- crm_bump_log_level(argc, argv);
- break;
- case '?':
- case '$':
- crm_help(flag, CRM_EX_OK);
- break;
- default:
- printf("Argument %c (0%o) is not (yet?) supported\n", flag, flag);
- ++argerr;
- break;
- }
+ if (!g_option_context_parse_strv(context, &processed_args, &error)) {
+ fprintf(stderr, "%s: %s\n", g_get_prgname(), error->message);
+ rc = CRM_EX_USAGE;
+ goto done;
}
- if (optind < argc) {
- printf("non-option ARGV-elements: ");
- while (optind < argc)
- printf("%s ", argv[optind++]);
- printf("\n");
+ for (int i = 0; i < args->verbosity; i++) {
+ crm_bump_log_level(argc, argv);
}
- if (optind > argc) {
- ++argerr;
+ if (args->version) {
+ /* FIXME: When crm_diff is converted to use formatted output, this can go. */
+ crm_help('v', CRM_EX_USAGE);
}
- if (argerr) {
- crm_help('?', CRM_EX_USAGE);
+ if (optind > argc) {
+ fprintf(stderr, "%s", g_option_context_get_help(context, TRUE, NULL));
+ rc = CRM_EX_USAGE;
+ goto done;
}
- if (apply && no_version) {
+ if (options.apply && options.no_version) {
fprintf(stderr, "warning: -u/--no-version ignored with -p/--patch\n");
- } else if (as_cib && no_version) {
+ } else if (options.as_cib && options.no_version) {
fprintf(stderr, "error: -u/--no-version incompatible with -c/--cib\n");
- return CRM_EX_USAGE;
+ rc = CRM_EX_USAGE;
+ goto done;
}
- if (raw_1) {
- object_1 = string2xml(xml_file_1);
+ if (options.raw_1) {
+ object_1 = string2xml(options.xml_file_1);
- } else if (use_stdin) {
+ } else if (options.use_stdin) {
fprintf(stderr, "Input first XML fragment:");
object_1 = stdin2xml();
- } else if (xml_file_1 != NULL) {
- object_1 = filename2xml(xml_file_1);
+ } else if (options.xml_file_1 != NULL) {
+ object_1 = filename2xml(options.xml_file_1);
}
- if (raw_2) {
- object_2 = string2xml(xml_file_2);
+ if (options.raw_2) {
+ object_2 = string2xml(options.xml_file_2);
- } else if (use_stdin) {
+ } else if (options.use_stdin) {
fprintf(stderr, "Input second XML fragment:");
object_2 = stdin2xml();
- } else if (xml_file_2 != NULL) {
- object_2 = filename2xml(xml_file_2);
+ } else if (options.xml_file_2 != NULL) {
+ object_2 = filename2xml(options.xml_file_2);
}
if (object_1 == NULL) {
fprintf(stderr, "Could not parse the first XML fragment\n");
- return CRM_EX_DATAERR;
+ rc = CRM_EX_DATAERR;
+ goto done;
}
if (object_2 == NULL) {
fprintf(stderr, "Could not parse the second XML fragment\n");
- return CRM_EX_DATAERR;
+ rc = CRM_EX_DATAERR;
+ goto done;
}
- if (apply) {
- rc = apply_patch(object_1, object_2, as_cib);
+ if (options.apply) {
+ rc = apply_patch(object_1, object_2, options.as_cib);
} else {
- rc = generate_patch(object_1, object_2, xml_file_2, as_cib, no_version);
+ rc = generate_patch(object_1, object_2, options.xml_file_2, options.as_cib, options.no_version);
}
+done:
+ pcmk__free_arg_context(context);
+ free(options.xml_file_1);
+ free(options.xml_file_2);
free_xml(object_1);
free_xml(object_2);
return crm_errno2exit(rc);
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 8, 5:57 PM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002414
Default Alt Text
(22 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment