Page MenuHomeClusterLabs Projects

crm_verify.c
No OneTemporary

crm_verify.c

/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <crm_internal.h>
#include <crm/crm.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <glib.h>
#include <crm/common/xml.h>
#include <crm/common/util.h>
#include <crm/msg_xml.h>
#include <crm/cib.h>
#include <crm/pengine/status.h>
gboolean USE_LIVE_CIB = FALSE;
char *cib_save = NULL;
void usage(const char *cmd, int exit_status);
extern gboolean stage0(pe_working_set_t *data_set);
extern void cleanup_alloc_calculations(pe_working_set_t *data_set);
extern xmlNode * do_calculations(
pe_working_set_t *data_set, xmlNode *xml_input, ha_time_t *now);
static struct crm_option long_options[] = {
/* Top-level Options */
{"help", 0, 0, '?', "\tThis text"},
{"version", 0, 0, '$', "\tVersion information" },
{"verbose", 0, 0, 'V', "\tIncrease debug output\n"},
{"-spacer-", 1, 0, '-', "\nData sources:"},
{"live-check", 0, 0, 'L', "Check the configuration used by the running cluster\n"},
{"xml-file", 1, 0, 'x', "Check the configuration in the named file"},
{"xml-text", 1, 0, 'X', "Check the configuration in the supplied string"},
{"xml-pipe", 0, 0, 'p', "Check the configuration piped in via stdin"},
{"-spacer-", 1, 0, '-', "\nAdditional Options:"},
{"save-xml", 1, 0, 'S', "Save the verified XML to the named file. Most useful with -L"},
{"-spacer-", 1, 0, '-', "\nExamples:", pcmk_option_paragraph},
{"-spacer-", 1, 0, '-', "Check the consistency of the configuration in the running cluster:", pcmk_option_paragraph},
{"-spacer-", 1, 0, '-', " crm_verify --live-check", pcmk_option_example},
{"-spacer-", 1, 0, '-', "Check the consistency of the configuration in a given file and produce verbose output:", pcmk_option_paragraph},
{"-spacer-", 1, 0, '-', " crm_verify --xml-file file.xml --verbose", pcmk_option_example},
{F_CRM_DATA, 1, 0, 'X', NULL, 1}, /* legacy */
{0, 0, 0, 0}
};
int
main(int argc, char **argv)
{
xmlNode *cib_object = NULL;
xmlNode *status = NULL;
int argerr = 0;
int flag;
int option_index = 0;
pe_working_set_t data_set;
cib_t * cib_conn = NULL;
int rc = cib_ok;
gboolean xml_stdin = FALSE;
const char *xml_tag = NULL;
const char *xml_file = NULL;
const char *xml_string = NULL;
g_log_set_handler(NULL,
G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL
| G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE
| G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG
| G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL,
cl_glib_msg_handler, NULL);
/* and for good measure... - this enum is a bit field (!) */
g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/
crm_log_init_quiet(NULL, LOG_ERR, FALSE, TRUE, argc, argv);
crm_set_options("V?$X:x:pLS:", "[modifiers] data_source", long_options,
"Check a (complete) confiuration for syntax and common conceptual errors."
"\n\nChecks the well-formedness of an XML configuration, its conformance to the configured DTD/schema and for the presence of common misconfigurations."
"\n\nIt reports two classes of problems, errors and warnings."
" Errors must be fixed before the cluster will work properly."
" However, it is left up to the administrator to decide if the warnings should also be fixed.");
while (1) {
flag = crm_get_option(argc, argv, &option_index);
if (flag == -1)
break;
switch(flag) {
#ifdef HAVE_GETOPT_H
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
break;
#endif
case 'X':
crm_debug_2("Option %c => %s", flag, optarg);
xml_string = crm_strdup(optarg);
break;
case 'x':
crm_debug_2("Option %c => %s", flag, optarg);
xml_file = crm_strdup(optarg);
break;
case 'p':
xml_stdin = TRUE;
break;
case 'S':
cib_save = crm_strdup(optarg);
break;
case 'V':
alter_debug(DEBUG_INC);
break;
case 'L':
USE_LIVE_CIB = TRUE;
break;
case '$':
case '?':
crm_help(flag, LSB_EXIT_OK);
break;
default:
fprintf(stderr, "Option -%c is not yet supported\n", flag);
++argerr;
break;
}
}
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc) {
printf("%s ", argv[optind++]);
}
printf("\n");
}
if (optind > argc) {
++argerr;
}
if (argerr) {
crm_err("%d errors in option parsing", argerr);
crm_help(flag, LSB_EXIT_GENERIC);
}
crm_info("=#=#=#=#= Getting XML =#=#=#=#=");
if(USE_LIVE_CIB) {
cib_conn = cib_new();
rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command);
}
if(USE_LIVE_CIB) {
if(rc == cib_ok) {
int options = cib_scope_local|cib_sync_call;
crm_info("Reading XML from: live cluster");
rc = cib_conn->cmds->query(
cib_conn, NULL, &cib_object, options);
}
if(rc != cib_ok) {
fprintf(stderr, "Live CIB query failed: %s\n",
cib_error2string(rc));
return 3;
}
if(cib_object == NULL) {
fprintf(stderr, "Live CIB query failed: empty result\n");
return 3;
}
} else if(xml_file != NULL) {
cib_object = filename2xml(xml_file);
if(cib_object == NULL) {
fprintf(stderr,
"Couldn't parse input file: %s\n", xml_file);
return 4;
}
} else if(xml_string != NULL) {
cib_object = string2xml(xml_string);
if(cib_object == NULL) {
fprintf(stderr,
"Couldn't parse input string: %s\n", xml_string);
return 4;
}
} else if(xml_stdin) {
cib_object = stdin2xml();
if(cib_object == NULL) {
fprintf(stderr, "Couldn't parse input from STDIN.\n");
return 4;
}
} else {
fprintf(stderr, "No configuration source specified."
" Use --help for usage information.\n");
return 5;
}
xml_tag = crm_element_name(cib_object);
if(safe_str_neq(xml_tag, XML_TAG_CIB)) {
fprintf(stderr, "This tool can only check complete configurations (ie. those starting with <cib>).\n");
return 6;
}
if(cib_save != NULL) {
write_xml_file(cib_object, cib_save, FALSE);
}
status = get_object_root(XML_CIB_TAG_STATUS, cib_object);
if(status == NULL) {
create_xml_node(cib_object, XML_CIB_TAG_STATUS);
}
if(validate_xml(cib_object, NULL, FALSE) == FALSE) {
crm_config_err("CIB did not pass DTD/schema validation");
free_xml(cib_object);
cib_object = NULL;
} else if(cli_config_update(&cib_object, NULL, FALSE) == FALSE) {
crm_config_error = TRUE;
free_xml(cib_object); cib_object = NULL;
fprintf(stderr, "The cluster will NOT be able to use this configuration.\n");
fprintf(stderr, "Please manually update the configuration to conform to the %s syntax.\n",
LATEST_SCHEMA_VERSION);
}
set_working_set_defaults(&data_set);
if(cib_object == NULL) {
} else if(USE_LIVE_CIB) {
/* we will always have a status section and can do a full simulation */
do_calculations(&data_set, cib_object, NULL);
cleanup_alloc_calculations(&data_set);
} else {
data_set.now = new_ha_date(TRUE);
data_set.input = cib_object;
stage0(&data_set);
cleanup_alloc_calculations(&data_set);
}
if(crm_config_error) {
fprintf(stderr, "Errors found during check: config not valid\n");
if(crm_log_level < LOG_WARNING) {
fprintf(stderr, " -V may provide more details\n");
}
rc = 2;
} else if(crm_config_warning) {
fprintf(stderr, "Warnings found during check: config may not be valid\n");
if(crm_log_level < LOG_WARNING) {
fprintf(stderr, " Use -V for more details\n");
}
rc = 1;
}
if(USE_LIVE_CIB) {
cib_conn->cmds->signoff(cib_conn);
cib_delete(cib_conn);
}
return rc;
}

File Metadata

Mime Type
text/x-c
Expires
Tue, Oct 29, 7:03 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
942489
Default Alt Text
crm_verify.c (8 KB)

Event Timeline