This source file includes following definitions.
- mode_cb
- build_arg_context
- main
1
2
3
4
5
6
7
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) {
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) {
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)
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
139
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
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
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
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
197
198
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 }