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/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) {
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) {
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)
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
140
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
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
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
177 if (pcmk__str_eq(options.input_xml, "-", pcmk__str_none)) {
178 input = pcmk__xml_read(NULL);
179
180 if (input == NULL) {
181 exit_code = CRM_EX_DATAERR;
182 g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
183 "Couldn't parse input from STDIN");
184 goto done;
185 }
186 } else if (options.input_xml != NULL) {
187 input = pcmk__xml_parse(options.input_xml);
188
189 if (input == NULL) {
190 exit_code = CRM_EX_DATAERR;
191 g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
192 "Couldn't parse input string: %s", options.input_xml);
193 goto done;
194 }
195 }
196
197
198
199
200
201 switch(options.mode) {
202 case crm_rule_mode_check:
203 rc = pcmk__check_rules(out, input, rule_date,
204 (const char **) options.rules);
205 exit_code = pcmk_rc2exitc(rc);
206 break;
207
208 default:
209 break;
210 }
211
212 done:
213 g_strfreev(processed_args);
214 pcmk__free_arg_context(context);
215
216 crm_time_free(rule_date);
217 free_xml(input);
218
219 pcmk__output_and_clear_error(&error, out);
220
221 if (out != NULL) {
222 out->finish(out, exit_code, true, NULL);
223 pcmk__output_free(out);
224 }
225
226 pcmk__unregister_formats();
227 return crm_exit(exit_code);
228 }