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-2024 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/common/xml.h>
  16 #include <crm/pengine/status.h>
  17 #include <pacemaker-internal.h>
  18 
  19 #include <sys/stat.h>
  20 
  21 #define SUMMARY "evaluate rules from the Pacemaker configuration"
  22 
  23 static pcmk__supported_format_t formats[] = {
  24     PCMK__SUPPORTED_FORMAT_NONE,
  25     PCMK__SUPPORTED_FORMAT_TEXT,
  26     PCMK__SUPPORTED_FORMAT_XML,
  27     { NULL, NULL, NULL }
  28 };
  29 
  30 enum crm_rule_mode {
  31     crm_rule_mode_none,
  32     crm_rule_mode_check
  33 };
  34 
  35 struct {
  36     char *date;
  37     char *input_xml;
  38     enum crm_rule_mode mode;
  39     gchar **rules;
  40 } options = {
  41     .mode = crm_rule_mode_none
  42 };
  43 
  44 static gboolean mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
  45 
  46 static GOptionEntry mode_entries[] = {
  47     { "check", 'c', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, mode_cb,
  48       "Check whether a rule is in effect",
  49       NULL },
  50 
  51     { NULL }
  52 };
  53 
  54 static GOptionEntry data_entries[] = {
  55     { "xml-text", 'X', 0, G_OPTION_ARG_STRING, &options.input_xml,
  56       "Use argument for XML (or stdin if '-')",
  57       NULL },
  58 
  59     { NULL }
  60 };
  61 
  62 static GOptionEntry addl_entries[] = {
  63     { "date", 'd', 0, G_OPTION_ARG_STRING, &options.date,
  64       "Whether the rule is in effect on a given date",
  65       NULL },
  66     { "rule", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &options.rules,
  67       "The ID of the rule to check (may be specified multiple times)",
  68       NULL },
  69 
  70     { NULL }
  71 };
  72 
  73 static gboolean
  74 mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     /* [previous][next][first][last][top][bottom][index][help] */
  75     if (strcmp(option_name, "c")) {
  76         options.mode = crm_rule_mode_check;
  77     }
  78 
  79     return TRUE;
  80 }
  81 
  82 static GOptionContext *
  83 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
     /* [previous][next][first][last][top][bottom][index][help] */
  84     GOptionContext *context = NULL;
  85 
  86     context = pcmk__build_arg_context(args, "text (default), xml", group, NULL);
  87 
  88     pcmk__add_arg_group(context, "modes", "Modes (mutually exclusive):",
  89                         "Show modes of operation", mode_entries);
  90     pcmk__add_arg_group(context, "data", "Data:",
  91                         "Show data options", data_entries);
  92     pcmk__add_arg_group(context, "additional", "Additional Options:",
  93                         "Show additional options", addl_entries);
  94     return context;
  95 }
  96 
  97 int
  98 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100     crm_time_t *rule_date = NULL;
 101     xmlNode *input = NULL;
 102 
 103     int rc = pcmk_rc_ok;
 104     crm_exit_t exit_code = CRM_EX_OK;
 105 
 106     GError *error = NULL;
 107 
 108     pcmk__output_t *out = NULL;
 109 
 110     GOptionGroup *output_group = NULL;
 111     pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
 112     GOptionContext *context = build_arg_context(args, &output_group);
 113     gchar **processed_args = pcmk__cmdline_preproc(argv, "drX");
 114 
 115     pcmk__register_formats(output_group, formats);
 116     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
 117         exit_code = CRM_EX_USAGE;
 118         goto done;
 119     }
 120 
 121     pcmk__cli_init_logging("crm_rule", args->verbosity);
 122 
 123     rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
 124     if (rc != pcmk_rc_ok) {
 125         exit_code = CRM_EX_ERROR;
 126         g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s",
 127                     args->output_ty, pcmk_rc_str(rc));
 128         goto done;
 129     }
 130 
 131     pcmk__register_lib_messages(out);
 132 
 133     if (args->version) {
 134         out->version(out, false);
 135         goto done;
 136     }
 137 
 138     /* Check command line arguments before opening a connection to
 139      * the CIB manager or doing anything else important.
 140      */
 141     switch(options.mode) {
 142         case crm_rule_mode_check:
 143             if (options.rules == NULL) {
 144                 exit_code = CRM_EX_USAGE;
 145                 g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "--check requires use of --rule=");
 146                 goto done;
 147             }
 148 
 149             break;
 150 
 151         default:
 152             exit_code = CRM_EX_USAGE;
 153             g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "No mode operation given");
 154             goto done;
 155             break;
 156     }
 157 
 158     /* Set up some defaults. */
 159     rule_date = crm_time_new(options.date);
 160     if (rule_date == NULL) {
 161         if (options.date != NULL) {
 162             exit_code = CRM_EX_DATAERR;
 163             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 164                         "Invalid date specified: '%s'", options.date);
 165 
 166         } else {
 167             // Should never happen
 168             exit_code = CRM_EX_OSERR;
 169             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 170                         "No --date given and can't determine current date");
 171         }
 172         goto done;
 173     }
 174 
 175     // Parse the input XML specified by the command-line options, if any
 176     if (pcmk__str_eq(options.input_xml, "-", pcmk__str_none)) {
 177         input = pcmk__xml_read(NULL);
 178 
 179         if (input == NULL) {
 180             exit_code = CRM_EX_DATAERR;
 181             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 182                         "Couldn't parse input from STDIN");
 183             goto done;
 184         }
 185     } else if (options.input_xml != NULL) {
 186         input = pcmk__xml_parse(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", 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     pcmk__xml_free(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     pcmk__unregister_formats();
 226     return crm_exit(exit_code);
 227 }

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