root/tools/crm_rule.c

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

DEFINITIONS

This source file includes following definitions.
  1. mode_cb
  2. build_arg_context
  3. main

   1 /*
   2  * Copyright 2019-2022 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <crm/common/cmdline_internal.h>
  13 #include <crm/common/output_internal.h>
  14 #include <crm/common/iso8601.h>
  15 #include <crm/msg_xml.h>
  16 #include <crm/pengine/rules_internal.h>
  17 #include <crm/pengine/status.h>
  18 #include <pacemaker-internal.h>
  19 
  20 #include <sys/stat.h>
  21 
  22 #define SUMMARY "evaluate rules from the Pacemaker configuration"
  23 
  24 static pcmk__supported_format_t formats[] = {
  25     PCMK__SUPPORTED_FORMAT_NONE,
  26     PCMK__SUPPORTED_FORMAT_TEXT,
  27     PCMK__SUPPORTED_FORMAT_XML,
  28     { NULL, NULL, NULL }
  29 };
  30 
  31 enum crm_rule_mode {
  32     crm_rule_mode_none,
  33     crm_rule_mode_check
  34 };
  35 
  36 struct {
  37     char *date;
  38     char *input_xml;
  39     enum crm_rule_mode mode;
  40     gchar **rules;
  41 } options = {
  42     .mode = crm_rule_mode_none
  43 };
  44 
  45 static gboolean mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
  46 
  47 static GOptionEntry mode_entries[] = {
  48     { "check", 'c', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, mode_cb,
  49       "Check whether a rule is in effect",
  50       NULL },
  51 
  52     { NULL }
  53 };
  54 
  55 static GOptionEntry data_entries[] = {
  56     { "xml-text", 'X', 0, G_OPTION_ARG_STRING, &options.input_xml,
  57       "Use argument for XML (or stdin if '-')",
  58       NULL },
  59 
  60     { NULL }
  61 };
  62 
  63 static GOptionEntry addl_entries[] = {
  64     { "date", 'd', 0, G_OPTION_ARG_STRING, &options.date,
  65       "Whether the rule is in effect on a given date",
  66       NULL },
  67     { "rule", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &options.rules,
  68       "The ID of the rule to check (may be specified multiple times)",
  69       NULL },
  70 
  71     { NULL }
  72 };
  73 
  74 static gboolean
  75 mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     /* [previous][next][first][last][top][bottom][index][help] */
  76     if (strcmp(option_name, "c")) {
  77         options.mode = crm_rule_mode_check;
  78     }
  79 
  80     return TRUE;
  81 }
  82 
  83 static GOptionContext *
  84 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
     /* [previous][next][first][last][top][bottom][index][help] */
  85     GOptionContext *context = NULL;
  86 
  87     context = pcmk__build_arg_context(args, "text (default), xml", group, NULL);
  88 
  89     pcmk__add_arg_group(context, "modes", "Modes (mutually exclusive):",
  90                         "Show modes of operation", mode_entries);
  91     pcmk__add_arg_group(context, "data", "Data:",
  92                         "Show data options", data_entries);
  93     pcmk__add_arg_group(context, "additional", "Additional Options:",
  94                         "Show additional options", addl_entries);
  95     return context;
  96 }
  97 
  98 int
  99 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 100 {
 101     crm_time_t *rule_date = NULL;
 102     xmlNode *input = NULL;
 103 
 104     int rc = pcmk_rc_ok;
 105     crm_exit_t exit_code = CRM_EX_OK;
 106 
 107     GError *error = NULL;
 108 
 109     pcmk__output_t *out = NULL;
 110 
 111     GOptionGroup *output_group = NULL;
 112     pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
 113     GOptionContext *context = build_arg_context(args, &output_group);
 114     gchar **processed_args = pcmk__cmdline_preproc(argv, "drX");
 115 
 116     pcmk__register_formats(output_group, formats);
 117     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
 118         exit_code = CRM_EX_USAGE;
 119         goto done;
 120     }
 121 
 122     pcmk__cli_init_logging("crm_rule", args->verbosity);
 123 
 124     rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
 125     if (rc != pcmk_rc_ok) {
 126         exit_code = CRM_EX_ERROR;
 127         g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s",
 128                     args->output_ty, pcmk_rc_str(rc));
 129         goto done;
 130     }
 131 
 132     pcmk__register_lib_messages(out);
 133 
 134     if (args->version) {
 135         out->version(out, false);
 136         goto done;
 137     }
 138 
 139     /* Check command line arguments before opening a connection to
 140      * the CIB manager or doing anything else important.
 141      */
 142     switch(options.mode) {
 143         case crm_rule_mode_check:
 144             if (options.rules == NULL) {
 145                 exit_code = CRM_EX_USAGE;
 146                 g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "--check requires use of --rule=");
 147                 goto done;
 148             }
 149 
 150             break;
 151 
 152         default:
 153             exit_code = CRM_EX_USAGE;
 154             g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "No mode operation given");
 155             goto done;
 156             break;
 157     }
 158 
 159     /* Set up some defaults. */
 160     rule_date = crm_time_new(options.date);
 161     if (rule_date == NULL) {
 162         if (options.date != NULL) {
 163             exit_code = CRM_EX_DATAERR;
 164             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 165                         "Invalid date specified: '%s'", options.date);
 166 
 167         } else {
 168             // Should never happen
 169             exit_code = CRM_EX_OSERR;
 170             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 171                         "No --date given and can't determine current date");
 172         }
 173         goto done;
 174     }
 175 
 176     // Parse the input XML specified by the command-line options, if any
 177     if (pcmk__str_eq(options.input_xml, "-", pcmk__str_casei)) {
 178         input = stdin2xml();
 179 
 180         if (input == NULL) {
 181             exit_code = CRM_EX_DATAERR;
 182             g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Couldn't parse input from STDIN\n");
 183             goto done;
 184         }
 185     } else if (options.input_xml != NULL) {
 186         input = string2xml(options.input_xml);
 187 
 188         if (input == NULL) {
 189             exit_code = CRM_EX_DATAERR;
 190             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 191                         "Couldn't parse input string: %s\n", options.input_xml);
 192             goto done;
 193         }
 194     }
 195 
 196     /* Now do whichever operation mode was asked for.  There's only one at the
 197      * moment so this looks a little silly, but I expect there will be more
 198      * modes in the future.
 199      */
 200     switch(options.mode) {
 201         case crm_rule_mode_check:
 202             rc = pcmk__check_rules(out, input, rule_date,
 203                                    (const char **) options.rules);
 204             exit_code = pcmk_rc2exitc(rc);
 205             break;
 206 
 207         default:
 208             break;
 209     }
 210 
 211 done:
 212     g_strfreev(processed_args);
 213     pcmk__free_arg_context(context);
 214 
 215     crm_time_free(rule_date);
 216     free_xml(input);
 217 
 218     pcmk__output_and_clear_error(error, out);
 219 
 220     if (out != NULL) {
 221         out->finish(out, exit_code, true, NULL);
 222         pcmk__output_free(out);
 223     }
 224 
 225     return crm_exit(exit_code);
 226 }

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