root/tools/crm_verify.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. main

   1 
   2 /* 
   3  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
   4  * 
   5  * This program is free software; you can redistribute it and/or
   6  * modify it under the terms of the GNU General Public
   7  * License as published by the Free Software Foundation; either
   8  * version 2 of the License, or (at your option) any later version.
   9  * 
  10  * This software is distributed in the hope that it will be useful,
  11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13  * General Public License for more details.
  14  * 
  15  * You should have received a copy of the GNU General Public
  16  * License along with this library; if not, write to the Free Software
  17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  18  */
  19 
  20 #include <crm_internal.h>
  21 #include <crm/crm.h>
  22 
  23 #include <stdio.h>
  24 #include <sys/types.h>
  25 #include <unistd.h>
  26 
  27 #include <stdlib.h>
  28 #include <errno.h>
  29 #include <fcntl.h>
  30 #include <libgen.h>
  31 #include <glib.h>
  32 
  33 #include <crm/common/xml.h>
  34 #include <crm/common/util.h>
  35 #include <crm/msg_xml.h>
  36 #include <crm/cib.h>
  37 #include <crm/pengine/status.h>
  38 
  39 gboolean USE_LIVE_CIB = FALSE;
  40 char *cib_save = NULL;
  41 void usage(const char *cmd, int exit_status);
  42 extern gboolean stage0(pe_working_set_t * data_set);
  43 extern void cleanup_alloc_calculations(pe_working_set_t * data_set);
  44 extern xmlNode *do_calculations(pe_working_set_t * data_set, xmlNode * xml_input, crm_time_t * now);
  45 
  46 /* *INDENT-OFF* */
  47 static struct crm_option long_options[] = {
  48     /* Top-level Options */
  49     {"help",           0, 0, '?', "\tThis text"},
  50     {"version",        0, 0, '$', "\tVersion information"  },
  51     {"verbose",        0, 0, 'V', "\tIncrease debug output\n"},
  52     
  53     {"-spacer-",        1, 0, '-', "\nData sources:"},
  54     {"live-check",  0, 0, 'L', "Check the configuration used by the running cluster\n"},
  55     {"xml-file",    1, 0, 'x', "Check the configuration in the named file"},
  56     {"xml-text",    1, 0, 'X', "Check the configuration in the supplied string"},
  57     {"xml-pipe",    0, 0, 'p', "Check the configuration piped in via stdin"},
  58 
  59     {"-spacer-",    1, 0, '-', "\nAdditional Options:"},
  60     {"save-xml",    1, 0, 'S', "Save the verified XML to the named file.  Most useful with -L"},
  61 
  62     {"-spacer-",    1, 0, '-', "\nExamples:", pcmk_option_paragraph},
  63     {"-spacer-",    1, 0, '-', "Check the consistency of the configuration in the running cluster:", pcmk_option_paragraph},
  64     {"-spacer-",    1, 0, '-', " crm_verify --live-check", pcmk_option_example},
  65     {"-spacer-",    1, 0, '-', "Check the consistency of the configuration in a given file and produce verbose output:", pcmk_option_paragraph},
  66     {"-spacer-",    1, 0, '-', " crm_verify --xml-file file.xml --verbose", pcmk_option_example},
  67   
  68     {F_CRM_DATA,    1, 0, 'X', NULL, 1}, /* legacy */
  69     {0, 0, 0, 0}
  70 };
  71 /* *INDENT-ON* */
  72 
  73 int
  74 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
  75 {
  76     xmlNode *cib_object = NULL;
  77     xmlNode *status = NULL;
  78     int argerr = 0;
  79     int flag;
  80     int option_index = 0;
  81 
  82     pe_working_set_t data_set;
  83     cib_t *cib_conn = NULL;
  84     int rc = pcmk_ok;
  85 
  86     bool verbose = FALSE;
  87     gboolean xml_stdin = FALSE;
  88     const char *xml_tag = NULL;
  89     const char *xml_file = NULL;
  90     const char *xml_string = NULL;
  91 
  92     crm_log_cli_init("crm_verify");
  93     crm_set_options(NULL, "[modifiers] data_source", long_options,
  94                     "Check a (complete) confiuration for syntax and common conceptual errors."
  95                     "\n\nChecks the well-formedness of an XML configuration, its conformance to the configured DTD/schema and for the presence of common misconfigurations."
  96                     "\n\nIt reports two classes of problems, errors and warnings."
  97                     " Errors must be fixed before the cluster will work properly."
  98                     " However, it is left up to the administrator to decide if the warnings should also be fixed.");
  99 
 100     while (1) {
 101         flag = crm_get_option(argc, argv, &option_index);
 102         if (flag == -1)
 103             break;
 104 
 105         switch (flag) {
 106             case 'X':
 107                 crm_trace("Option %c => %s", flag, optarg);
 108                 xml_string = optarg;
 109                 break;
 110             case 'x':
 111                 crm_trace("Option %c => %s", flag, optarg);
 112                 xml_file = optarg;
 113                 break;
 114             case 'p':
 115                 xml_stdin = TRUE;
 116                 break;
 117             case 'S':
 118                 cib_save = optarg;
 119                 break;
 120             case 'V':
 121                 verbose = TRUE;
 122                 crm_bump_log_level(argc, argv);
 123                 break;
 124             case 'L':
 125                 USE_LIVE_CIB = TRUE;
 126                 break;
 127             case '$':
 128             case '?':
 129                 crm_help(flag, EX_OK);
 130                 break;
 131             default:
 132                 fprintf(stderr, "Option -%c is not yet supported\n", flag);
 133                 ++argerr;
 134                 break;
 135         }
 136     }
 137 
 138     if (optind < argc) {
 139         printf("non-option ARGV-elements: ");
 140         while (optind < argc) {
 141             printf("%s ", argv[optind++]);
 142         }
 143         printf("\n");
 144     }
 145 
 146     if (optind > argc) {
 147         ++argerr;
 148     }
 149 
 150     if (argerr) {
 151         crm_err("%d errors in option parsing", argerr);
 152         crm_help(flag, EX_USAGE);
 153     }
 154 
 155     crm_info("=#=#=#=#= Getting XML =#=#=#=#=");
 156 
 157     if (USE_LIVE_CIB) {
 158         cib_conn = cib_new();
 159         rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command);
 160     }
 161 
 162     if (USE_LIVE_CIB) {
 163         if (rc == pcmk_ok) {
 164             int options = cib_scope_local | cib_sync_call;
 165 
 166             crm_info("Reading XML from: live cluster");
 167             rc = cib_conn->cmds->query(cib_conn, NULL, &cib_object, options);
 168         }
 169 
 170         if (rc != pcmk_ok) {
 171             fprintf(stderr, "Live CIB query failed: %s\n", pcmk_strerror(rc));
 172             goto done;
 173         }
 174         if (cib_object == NULL) {
 175             fprintf(stderr, "Live CIB query failed: empty result\n");
 176             rc = -ENOMSG;
 177             goto done;
 178         }
 179 
 180     } else if (xml_file != NULL) {
 181         cib_object = filename2xml(xml_file);
 182         if (cib_object == NULL) {
 183             fprintf(stderr, "Couldn't parse input file: %s\n", xml_file);
 184             rc = -ENODATA;
 185             goto done;
 186         }
 187 
 188     } else if (xml_string != NULL) {
 189         cib_object = string2xml(xml_string);
 190         if (cib_object == NULL) {
 191             fprintf(stderr, "Couldn't parse input string: %s\n", xml_string);
 192             rc = -ENODATA;
 193             goto done;
 194         }
 195     } else if (xml_stdin) {
 196         cib_object = stdin2xml();
 197         if (cib_object == NULL) {
 198             fprintf(stderr, "Couldn't parse input from STDIN.\n");
 199             rc = -ENODATA;
 200             goto done;
 201         }
 202 
 203     } else {
 204         fprintf(stderr, "No configuration source specified."
 205                 "  Use --help for usage information.\n");
 206         rc = -ENODATA;
 207         goto done;
 208     }
 209 
 210     xml_tag = crm_element_name(cib_object);
 211     if (safe_str_neq(xml_tag, XML_TAG_CIB)) {
 212         fprintf(stderr,
 213                 "This tool can only check complete configurations (i.e. those starting with <cib>).\n");
 214         rc = -EBADMSG;
 215         goto done;
 216     }
 217 
 218     if (cib_save != NULL) {
 219         write_xml_file(cib_object, cib_save, FALSE);
 220     }
 221 
 222     status = get_object_root(XML_CIB_TAG_STATUS, cib_object);
 223     if (status == NULL) {
 224         create_xml_node(cib_object, XML_CIB_TAG_STATUS);
 225     }
 226 
 227     if (validate_xml(cib_object, NULL, FALSE) == FALSE) {
 228         crm_config_err("CIB did not pass DTD/schema validation");
 229         free_xml(cib_object);
 230         cib_object = NULL;
 231 
 232     } else if (cli_config_update(&cib_object, NULL, FALSE) == FALSE) {
 233         crm_config_error = TRUE;
 234         free_xml(cib_object);
 235         cib_object = NULL;
 236         fprintf(stderr, "The cluster will NOT be able to use this configuration.\n");
 237         fprintf(stderr, "Please manually update the configuration to conform to the %s syntax.\n",
 238                 xml_latest_schema());
 239     }
 240 
 241     set_working_set_defaults(&data_set);
 242     if (cib_object == NULL) {
 243     } else if (status != NULL || USE_LIVE_CIB) {
 244         /* live queries will always have a status section and can do a full simulation */
 245         do_calculations(&data_set, cib_object, NULL);
 246         cleanup_alloc_calculations(&data_set);
 247 
 248     } else {
 249         data_set.now = crm_time_new(NULL);
 250         data_set.input = cib_object;
 251         stage0(&data_set);
 252         cleanup_alloc_calculations(&data_set);
 253     }
 254 
 255     if (crm_config_error) {
 256         fprintf(stderr, "Errors found during check: config not valid\n");
 257         if (verbose == FALSE) {
 258             fprintf(stderr, "  -V may provide more details\n");
 259         }
 260         rc = -pcmk_err_generic;
 261 
 262     } else if (crm_config_warning) {
 263         fprintf(stderr, "Warnings found during check: config may not be valid\n");
 264         if (verbose == FALSE) {
 265             fprintf(stderr, "  Use -V for more details\n");
 266         }
 267         rc = -pcmk_err_generic;
 268     }
 269 
 270     if (USE_LIVE_CIB && cib_conn) {
 271         cib_conn->cmds->signoff(cib_conn);
 272         cib_delete(cib_conn);
 273     }
 274 
 275   done:
 276     return rc;
 277 }

/* [previous][next][first][last][top][bottom][index][help] */