This source file includes following definitions.
- main
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <libgen.h>
18 #include <time.h>
19
20 #include <sys/param.h>
21 #include <sys/types.h>
22
23 #include <crm/crm.h>
24 #include <crm/msg_xml.h>
25 #include <crm/common/xml.h>
26 #include <crm/common/ipc.h>
27 #include <crm/common/util.h>
28 #include <crm/cluster.h>
29
30 #include <crm/cib.h>
31 #include <crm/cib/internal.h>
32 #include <crm/common/attrd_internal.h>
33 #include <sys/utsname.h>
34
35 gboolean BE_QUIET = FALSE;
36 char command = 'G';
37
38 const char *dest_uname = NULL;
39 char *dest_node = NULL;
40 char *set_name = NULL;
41 char *attr_id = NULL;
42 char *attr_name = NULL;
43 char *attr_pattern = NULL;
44 const char *type = NULL;
45 const char *rsc_id = NULL;
46 const char *attr_value = NULL;
47 const char *attr_default = NULL;
48 const char *set_type = NULL;
49
50 static pcmk__cli_option_t long_options[] = {
51
52 {
53 "help", no_argument, NULL, '?',
54 "\tThis text", pcmk__option_default
55 },
56 {
57 "version", no_argument, NULL, '$',
58 "\tVersion information", pcmk__option_default
59 },
60 {
61 "verbose", no_argument, NULL, 'V',
62 "\tIncrease debug output", pcmk__option_default
63 },
64 {
65 "quiet", no_argument, NULL, 'q',
66 "\tPrint only the value on stdout\n", pcmk__option_default
67 },
68 {
69 "name", required_argument, NULL, 'n',
70 "Name of the attribute/option to operate on", pcmk__option_default
71 },
72 {
73 "pattern", required_argument, NULL, 'P',
74 "Pattern matching names of attributes (only with -v/-D and -l reboot)",
75 pcmk__option_default
76 },
77 {
78 "-spacer-", no_argument, NULL, '-',
79 "\nCommands:", pcmk__option_default
80 },
81 {
82 "query", no_argument, NULL, 'G',
83 "\tQuery the current value of the attribute/option",
84 pcmk__option_default
85 },
86 {
87 "update", required_argument, NULL, 'v',
88 "Update the value of the attribute/option", pcmk__option_default
89 },
90 {
91 "delete", no_argument, NULL, 'D',
92 "\tDelete the attribute/option", pcmk__option_default
93 },
94 {
95 "-spacer-", no_argument, NULL, '-',
96 "\nAdditional Options:", pcmk__option_default
97 },
98 {
99 "node", required_argument, NULL, 'N',
100 "Set a node attribute for named node (instead of a cluster option). "
101 "See also: -l",
102 pcmk__option_default
103 },
104 {
105 "type", required_argument, NULL, 't',
106 "Which part of the configuration to update/delete/query the option in",
107 pcmk__option_default
108 },
109 {
110 "-spacer-", no_argument, NULL, '-',
111 "\t\t\tValid values: crm_config, rsc_defaults, op_defaults, tickets",
112 pcmk__option_default
113 },
114 {
115 "lifetime", required_argument, NULL, 'l',
116 "Lifetime of the node attribute", pcmk__option_default
117 },
118 {
119 "-spacer-", no_argument, NULL, '-',
120 "\t\t\tValid values: reboot, forever", pcmk__option_default
121 },
122 {
123 "utilization", no_argument, NULL, 'z',
124 "Set an utilization attribute for the node.", pcmk__option_default
125 },
126 {
127 "set-name", required_argument, NULL, 's',
128 "(Advanced) The attribute set in which to place the value",
129 pcmk__option_default
130 },
131 {
132 "id", required_argument, NULL, 'i',
133 "\t(Advanced) The ID used to identify the attribute",
134 pcmk__option_default
135 },
136 {
137 "default", required_argument, NULL, 'd',
138 "(Advanced) Default value to display if none is found in configuration",
139 pcmk__option_default
140 },
141 {
142 "inhibit-policy-engine", no_argument, NULL, '!',
143 NULL, pcmk__option_hidden
144 },
145
146
147 {
148 "quiet", no_argument, NULL, 'Q',
149 NULL, pcmk__option_hidden
150 },
151 {
152 "node-uname", required_argument, NULL, 'U',
153 NULL, pcmk__option_hidden
154 },
155 {
156 "get-value", no_argument, NULL, 'G',
157 NULL, pcmk__option_hidden
158 },
159 {
160 "delete-attr", no_argument, NULL, 'D',
161 NULL, pcmk__option_hidden
162 },
163 {
164 "attr-value", required_argument, NULL, 'v',
165 NULL, pcmk__option_hidden
166 },
167 {
168 "attr-name", required_argument, NULL, 'n',
169 NULL, pcmk__option_hidden
170 },
171 {
172 "attr-id", required_argument, NULL, 'i',
173 NULL, pcmk__option_hidden
174 },
175
176 {
177 "-spacer-", no_argument, NULL, '-',
178 "\nExamples:", pcmk__option_paragraph
179 },
180 {
181 "-spacer-", no_argument, NULL, '-',
182 "Add new node attribute called 'location' with the value of 'office' "
183 "for host 'myhost':",
184 pcmk__option_paragraph
185 },
186 {
187 "-spacer-", no_argument, NULL, '-',
188 " crm_attribute --node myhost --name location --update office",
189 pcmk__option_example
190 },
191 {
192 "-spacer-", no_argument, NULL, '-',
193 "Query the value of the 'location' node attribute for host 'myhost':",
194 pcmk__option_paragraph
195 },
196 {
197 "-spacer-", no_argument, NULL, '-',
198 " crm_attribute --node myhost --name location --query",
199 pcmk__option_example
200 },
201 {
202 "-spacer-", no_argument, NULL, '-',
203 "Change the value of the 'location' node attribute for host 'myhost':",
204 pcmk__option_paragraph
205 },
206 {
207 "-spacer-", no_argument, NULL, '-',
208 " crm_attribute --node myhost --name location --update backoffice",
209 pcmk__option_example
210 },
211 {
212 "-spacer-", no_argument, NULL, '-',
213 "Delete the 'location' node attribute for host 'myhost':",
214 pcmk__option_paragraph
215 },
216 {
217 "-spacer-", no_argument, NULL, '-',
218 " crm_attribute --node myhost --name location --delete",
219 pcmk__option_example
220 },
221 {
222 "-spacer-", no_argument, NULL, '-',
223 "Query the value of the cluster-delay cluster option:",
224 pcmk__option_paragraph
225 },
226 {
227 "-spacer-", no_argument, NULL, '-',
228 " crm_attribute --type crm_config --name cluster-delay --query",
229 pcmk__option_example
230 },
231 {
232 "-spacer-", no_argument, NULL, '-',
233 "Query value of the \"cluster-delay\" cluster option and print only "
234 "the value:",
235 pcmk__option_paragraph
236 },
237 {
238 "-spacer-", no_argument, NULL, '-',
239 " crm_attribute --type crm_config --name cluster-delay --query --quiet",
240 pcmk__option_example
241 },
242 { 0, 0, 0, 0 }
243 };
244
245 int
246 main(int argc, char **argv)
247 {
248 cib_t *the_cib = NULL;
249 int rc = pcmk_ok;
250
251 int cib_opts = cib_sync_call;
252 int argerr = 0;
253 int flag;
254
255 int option_index = 0;
256 int is_remote_node = 0;
257
258 bool try_attrd = true;
259 int attrd_opts = pcmk__node_attr_none;
260
261 crm_log_cli_init("crm_attribute");
262 pcmk__set_cli_options(NULL, "-n <attribute> <command> [options]",
263 long_options,
264 "query and update Pacemaker cluster options "
265 "and node attributes");
266
267 if (argc < 2) {
268 pcmk__cli_help('?', CRM_EX_USAGE);
269 }
270
271 while (1) {
272 flag = pcmk__next_cli_option(argc, argv, &option_index, NULL);
273 if (flag == -1)
274 break;
275
276 switch (flag) {
277 case 'V':
278 crm_bump_log_level(argc, argv);
279 break;
280 case '$':
281 case '?':
282 pcmk__cli_help(flag, CRM_EX_OK);
283 break;
284 case 'G':
285 command = flag;
286 attr_value = optarg;
287 break;
288 case 'D':
289 case 'v':
290 command = flag;
291 attr_value = optarg;
292 crm_log_args(argc, argv);
293 break;
294 case 'q':
295 case 'Q':
296 BE_QUIET = TRUE;
297 break;
298 case 'U':
299 case 'N':
300 dest_uname = strdup(optarg);
301 break;
302 case 's':
303 set_name = strdup(optarg);
304 break;
305 case 'l':
306 case 't':
307 type = optarg;
308 break;
309 case 'z':
310 type = XML_CIB_TAG_NODES;
311 set_type = XML_TAG_UTILIZATION;
312 break;
313 case 'n':
314 attr_name = strdup(optarg);
315 break;
316 case 'P':
317 attr_pattern = strdup(optarg);
318 break;
319 case 'i':
320 attr_id = strdup(optarg);
321 break;
322 case 'r':
323 rsc_id = optarg;
324 break;
325 case 'd':
326 attr_default = optarg;
327 break;
328 case '!':
329 crm_warn("Inhibiting notifications for this update");
330 cib__set_call_options(cib_opts, crm_system_name,
331 cib_inhibit_notify);
332 break;
333 default:
334 printf("Argument code 0%o (%c) is not (?yet?) supported\n", flag, flag);
335 ++argerr;
336 break;
337 }
338 }
339
340 if (optind < argc) {
341 printf("non-option ARGV-elements: ");
342 while (optind < argc)
343 printf("%s ", argv[optind++]);
344 printf("\n");
345 }
346
347 if (optind > argc) {
348 ++argerr;
349 }
350
351 if (argerr) {
352 pcmk__cli_help('?', CRM_EX_USAGE);
353 }
354
355 the_cib = cib_new();
356 rc = the_cib->cmds->signon(the_cib, crm_system_name, cib_command);
357
358 if (rc != pcmk_ok) {
359 fprintf(stderr, "Could not connect to the CIB: %s\n",
360 pcmk_strerror(rc));
361 crm_exit(crm_errno2exit(rc));
362 }
363
364 if (type == NULL && dest_uname != NULL) {
365 type = "forever";
366 }
367
368 if (pcmk__str_eq(type, "reboot", pcmk__str_casei)) {
369 type = XML_CIB_TAG_STATUS;
370
371 } else if (pcmk__str_eq(type, "forever", pcmk__str_casei)) {
372 type = XML_CIB_TAG_NODES;
373 }
374
375 if (type == NULL && dest_uname == NULL) {
376
377 type = XML_CIB_TAG_CRMCONFIG;
378
379 } else if (pcmk__str_eq(type, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
380 } else if (!pcmk__str_eq(type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
381
382
383
384
385 dest_uname = pcmk__node_attr_target(dest_uname);
386 if (dest_uname == NULL) {
387 dest_uname = get_local_node_name();
388 }
389
390 rc = query_node_uuid(the_cib, dest_uname, &dest_node, &is_remote_node);
391 if (pcmk_ok != rc) {
392 fprintf(stderr, "Could not map name=%s to a UUID\n", dest_uname);
393 the_cib->cmds->signoff(the_cib);
394 cib_delete(the_cib);
395 crm_exit(crm_errno2exit(rc));
396 }
397 }
398
399 if ((command == 'D') && (attr_name == NULL) && (attr_pattern == NULL)) {
400 fprintf(stderr, "Error: must specify attribute name or pattern to delete\n");
401 crm_exit(CRM_EX_USAGE);
402 }
403
404 if (attr_pattern) {
405 if (((command != 'v') && (command != 'D'))
406 || !pcmk__str_eq(type, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
407
408 fprintf(stderr, "Error: pattern can only be used with till-reboot update or delete\n");
409 crm_exit(CRM_EX_USAGE);
410 }
411 command = 'u';
412 free(attr_name);
413 attr_name = attr_pattern;
414 }
415
416
417 try_attrd = pcmk__str_eq(type, XML_CIB_TAG_STATUS, pcmk__str_casei);
418
419
420 if (getenv("CIB_file") || getenv("CIB_shadow")) {
421 try_attrd = FALSE;
422 }
423
424 if (is_remote_node) {
425 attrd_opts = pcmk__node_attr_remote;
426 }
427 if (((command == 'v') || (command == 'D') || (command == 'u')) && try_attrd
428 && (pcmk__node_attr_request(NULL, command, dest_uname, attr_name,
429 attr_value, type, set_name, NULL, NULL,
430 attrd_opts) == pcmk_rc_ok)) {
431 crm_info("Update %s=%s sent via pacemaker-attrd",
432 attr_name, ((command == 'D')? "<none>" : attr_value));
433
434 } else if (command == 'D') {
435 rc = delete_attr_delegate(the_cib, cib_opts, type, dest_node, set_type, set_name,
436 attr_id, attr_name, attr_value, TRUE, NULL);
437
438 if (rc == -ENXIO) {
439
440
441
442
443 rc = pcmk_ok;
444 }
445
446 } else if (command == 'v') {
447 CRM_LOG_ASSERT(type != NULL);
448 CRM_LOG_ASSERT(attr_name != NULL);
449 CRM_LOG_ASSERT(attr_value != NULL);
450
451 rc = update_attr_delegate(the_cib, cib_opts, type, dest_node, set_type, set_name,
452 attr_id, attr_name, attr_value, TRUE, NULL, is_remote_node ? "remote" : NULL);
453
454 } else {
455
456 char *read_value = NULL;
457
458 rc = read_attr_delegate(the_cib, type, dest_node, set_type, set_name,
459 attr_id, attr_name, &read_value, TRUE, NULL);
460
461 if (rc == -ENXIO && attr_default) {
462 read_value = strdup(attr_default);
463 rc = pcmk_ok;
464 }
465
466 crm_info("Read %s=%s %s%s",
467 attr_name, crm_str(read_value), set_name ? "in " : "", set_name ? set_name : "");
468
469 if (rc == -ENOTUNIQ) {
470
471 rc = pcmk_ok;
472
473 } else if (BE_QUIET == FALSE) {
474 fprintf(stdout, "%s%s %s%s %s%s value=%s\n",
475 type ? "scope=" : "", type ? type : "",
476 attr_id ? "id=" : "", attr_id ? attr_id : "",
477 attr_name ? "name=" : "", attr_name ? attr_name : "",
478 read_value ? read_value : "(null)");
479
480 } else if (read_value != NULL) {
481 fprintf(stdout, "%s\n", read_value);
482 }
483 free(read_value);
484 }
485
486 if (rc == -ENOTUNIQ) {
487 printf("Please choose from one of the matches above and supply the 'id' with --attr-id\n");
488
489 } else if (rc != pcmk_ok) {
490 fprintf(stderr, "Error performing operation: %s\n", pcmk_strerror(rc));
491 }
492
493 the_cib->cmds->signoff(the_cib);
494 cib_delete(the_cib);
495 crm_exit(crm_errno2exit(rc));
496 }