2
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This software is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* You should have received a copy of the GNU General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
#include <crm_internal.h>
21
#include <sys/param.h>
23
#include <sys/types.h>
31
#include <crm/msg_xml.h>
33
#include <crm/common/xml.h>
41
void usage(const char *cmd, int exit_status);
43
struct cib_func_entry {
50
static struct cib_func_entry cib_pipe_ops[] = {
51
{CIB_OP_QUERY, TRUE, cib_process_query},
52
{CIB_OP_MODIFY, FALSE, cib_process_modify},
53
{CIB_OP_APPLY_DIFF, FALSE, cib_process_diff},
54
{CIB_OP_BUMP, FALSE, cib_process_bump},
55
{CIB_OP_REPLACE, FALSE, cib_process_replace},
56
{CIB_OP_CREATE, FALSE, cib_process_create},
57
{CIB_OP_DELETE, FALSE, cib_process_delete},
58
{CIB_OP_ERASE, FALSE, cib_process_erase},
62
#define OPTARGS "V?o:QDUCEX:t:MBfRx:P5S$"
65
main(int argc, char **argv)
71
int max_msg_types = DIMOF(cib_pipe_ops);
73
int command_options = 0;
74
gboolean changed = FALSE;
75
gboolean force_flag = FALSE;
76
gboolean dangerous_cmd = FALSE;
79
const char *section = NULL;
80
const char *input_xml = NULL;
81
const char *input_file = NULL;
82
const char *cib_action = NULL;
84
xmlNode *input = NULL;
85
xmlNode *output = NULL;
86
xmlNode *result_cib = NULL;
87
xmlNode *current_cib = NULL;
89
gboolean query = FALSE;
95
static struct option long_options[] = {
96
{CIB_OP_ERASE, 0, 0, 'E'},
97
{CIB_OP_QUERY, 0, 0, 'Q'},
98
{CIB_OP_CREATE, 0, 0, 'C'},
99
{CIB_OP_REPLACE, 0, 0, 'R'},
100
{CIB_OP_UPDATE, 0, 0, 'U'},
101
{CIB_OP_MODIFY, 0, 0, 'M'},
102
{"patch", 0, 0, 'P'},
103
{CIB_OP_DELETE, 0, 0, 'D'},
104
{CIB_OP_BUMP, 0, 0, 'B'},
105
{"md5-sum", 0, 0, '5'},
107
{"force", 0, 0, 'f'},
108
{"xml-file", 1, 0, 'x'},
109
{"xml-text", 1, 0, 'X'},
110
{"xml-save", 1, 0, 'S'},
111
{"obj_type", 1, 0, 'o'},
113
{"version", 0, 0, '$'},
114
{"verbose", 0, 0, 'V'},
121
crm_log_init_quiet(NULL, LOG_ERR, FALSE, FALSE, argc, argv);
125
flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index);
127
flag = getopt(argc, argv, OPTARGS);
134
cib_action = CIB_OP_ERASE;
135
dangerous_cmd = TRUE;
138
cib_action = CIB_OP_QUERY;
141
cib_action = CIB_OP_APPLY_DIFF;
144
cib_action = CIB_OP_SYNC;
148
cib_action = CIB_OP_MODIFY;
151
cib_action = CIB_OP_REPLACE;
154
cib_action = CIB_OP_CREATE;
157
cib_action = CIB_OP_DELETE;
160
cib_action = "md5-sum";
163
cib_action = CIB_OP_DELETE_ALT;
166
cib_action = CIB_OP_ISMASTER;
167
command_options |= cib_scope_local;
170
cib_action = CIB_OP_BUMP;
173
crm_trace("Option %c => %s", flag, optarg);
174
section = crm_strdup(optarg);
177
crm_trace("Option %c => %s", flag, optarg);
178
input_file = crm_strdup(optarg);
181
crm_trace("Option %c => %s", flag, optarg);
182
input_xml = crm_strdup(optarg);
186
command_options |= cib_quorum_override;
189
crm_bump_log_level();
191
case '?': /* Help message */
192
usage(crm_system_name, LSB_EXIT_OK);
194
case '$': /* Version message */
195
crm_help(flag, LSB_EXIT_OK);
203
if (cib_action == NULL) {
212
usage(crm_system_name, LSB_EXIT_GENERIC);
215
if (dangerous_cmd && force_flag == FALSE) {
216
fprintf(stderr, "The supplied command is considered dangerous."
217
" To prevent accidental destruction of the cluster,"
218
" the --force flag is required in order to proceed.\n");
220
usage(crm_system_name, LSB_EXIT_GENERIC);
223
if (input_file != NULL) {
224
input = filename2xml(input_file);
226
fprintf(stderr, "Couldn't parse input file: %s\n", input_file);
230
} else if (input_xml != NULL) {
231
input = string2xml(input_xml);
233
fprintf(stderr, "Couldn't parse input string: %s\n", input_xml);
238
if (input && safe_str_eq(cib_action, CIB_OP_QUERY)) {
239
current_cib = copy_xml(input);
242
current_cib = stdin2xml();
243
if (current_cib == NULL && safe_str_neq(cib_action, CIB_OP_ERASE)) {
244
fprintf(stderr, "Couldn't parse existing CIB from STDIN.\n");
249
if (current_cib == NULL) {
250
current_cib = createEmptyCib();
252
result_cib = copy_xml(current_cib);
254
if (safe_str_eq(cib_action, "md5-sum")) {
257
digest = calculate_on_disk_digest(current_cib);
258
fprintf(stdout, "%s\n", crm_str(digest));
263
/* read local config file */
264
if (cib_action == NULL) {
265
crm_err("No operation specified");
266
return cib_operation;
269
for (lpc = 0; lpc < max_msg_types; lpc++) {
270
if (safe_str_eq(cib_action, cib_pipe_ops[lpc].op)) {
271
fn = &(cib_pipe_ops[lpc].fn);
272
query = cib_pipe_ops[lpc].read_only;
278
rc = cib_NOTSUPPORTED;
280
rc = cib_perform_op(cib_action, command_options, fn, query,
281
section, NULL, input, TRUE, &changed,
282
current_cib, &result_cib, NULL, &output);
286
fprintf(stderr, "Call failed: %s\n", cib_error2string(rc));
287
fprintf(stdout, "%c", 0);
291
crm_log_args(argc, argv);
294
buffer = dump_xml_formatted(output);
296
buffer = dump_xml_formatted(result_cib);
299
fprintf(stdout, "%s\n", buffer);
307
usage(const char *cmd, int exit_status)
311
stream = exit_status ? stderr : stdout;
313
fprintf(stream, "usage: %s -Q -(x|X)\n", cmd);
314
fprintf(stream, "usage: %s -Q -(x|X) | %s [-%s] | %s [-%s] | ...\n",
315
cmd, cmd, OPTARGS, cmd, OPTARGS);
316
fprintf(stream, "usage: cibadmin -Q | %s [-%s] | %s [-%s] | ...\n",
317
cmd, OPTARGS, cmd, OPTARGS);
319
fprintf(stream, "\nOptions\n");
320
fprintf(stream, "\t--%s (-%c) <type>\tobject type being operated on\n", "obj_type", 'o');
321
fprintf(stream, "\t\tValid values are:" " nodes, resources, constraints, crm_config, status\n");
322
fprintf(stream, "\t--%s (-%c)\tturn on debug info."
323
" additional instance increase verbosity\n", "verbose", 'V');
324
fprintf(stream, "\t--%s (-%c)\tthis help message\n", "help", '?');
326
fprintf(stream, "\nCommands\n");
327
fprintf(stream, "\t--%s (-%c)\tErase the contents of the whole CIB\n", CIB_OP_ERASE, 'E');
328
fprintf(stream, "\t--%s (-%c)\t\n", CIB_OP_QUERY, 'Q');
329
fprintf(stream, "\t--%s (-%c)\tCreate an object that does not yet exist\n", CIB_OP_CREATE, 'C');
330
fprintf(stream, "\t--%s (-%c)\tRecursivly update an object in the CIB\n", CIB_OP_UPDATE, 'U');
332
"\t--%s (-%c)\tFind the object somewhere in the CIB's XML tree and update it as --"
333
CIB_OP_UPDATE " would\n", CIB_OP_MODIFY, 'M');
334
fprintf(stream, "\t--%s (-%c)\tRecursivly replace an object in the CIB\n", CIB_OP_REPLACE, 'R');
335
fprintf(stream, "\t--%s (-%c)\t\n", CIB_OP_DELETE, 'D');
336
fprintf(stream, "\t\t\tDelete the first object matching the supplied criteria\n");
337
fprintf(stream, "\t\t\tEg. <op id=\"rsc1_op1\" name=\"monitor\"/>\n");
339
"\t\t\tThe tagname and all attributes must match in order for the element to be deleted\n");
341
fprintf(stream, "\t--%s (-%c)\t\n", CIB_OP_BUMP, 'B');
342
fprintf(stream, "\t--%s (-%c)\t\tCalculate the configuration's digest.\n", "md5-sum", '5');
343
fprintf(stream, "\nXML data\n");
344
fprintf(stream, "\t--%s (-%c) <filename>\tRetrieve XML from the named file\n", "xml-file", 'x');
345
fprintf(stream, "\t--%s (-%c) <string>\tRetrieve XML from the supplied string\n",
347
fprintf(stream, "\t--%s (-%c) <filename>\tSave the XML output to the named file\n",
349
fprintf(stream, "\nNOTE: The current CIB is assumed to be passed in via stdin,"
350
" unless -Q is used in which case -x or -X are also acceptable\n");