root/tools/cibadmin.c

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

DEFINITIONS

This source file includes following definitions.
  1. print_xml_output
  2. report_schema_unchanged
  3. main
  4. do_work
  5. do_init
  6. cibadmin_op_callback

   1 /*
   2  * Copyright 2004-2020 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 #include <stdio.h>
  12 #include <crm/crm.h>
  13 #include <crm/msg_xml.h>
  14 #include <crm/common/xml.h>
  15 #include <crm/common/ipc.h>
  16 #include <crm/cib/internal.h>
  17 
  18 static int message_timeout_ms = 30;
  19 static int command_options = 0;
  20 static int request_id = 0;
  21 static int bump_log_num = 0;
  22 
  23 static const char *host = NULL;
  24 static const char *cib_user = NULL;
  25 static const char *cib_action = NULL;
  26 static const char *obj_type = NULL;
  27 
  28 static cib_t *the_cib = NULL;
  29 static GMainLoop *mainloop = NULL;
  30 static gboolean force_flag = FALSE;
  31 static crm_exit_t exit_code = CRM_EX_OK;
  32 
  33 int do_init(void);
  34 int do_work(xmlNode *input, int command_options, xmlNode **output);
  35 void cibadmin_op_callback(xmlNode *msg, int call_id, int rc, xmlNode *output,
  36                           void *user_data);
  37 
  38 static pcmk__cli_option_t long_options[] = {
  39     // long option, argument type, storage, short option, description, flags
  40     {
  41         "help", no_argument, NULL, '?',
  42         "\tThis text", pcmk__option_default
  43     },
  44     {
  45         "version", no_argument, NULL, '$',
  46         "\tVersion information", pcmk__option_default
  47     },
  48     {
  49         "verbose", no_argument, NULL, 'V',
  50         "\tIncrease debug output\n", pcmk__option_default
  51     },
  52 
  53     {
  54         "-spacer-", no_argument, NULL, '-',
  55         "Commands:", pcmk__option_default
  56     },
  57     {
  58         "upgrade", no_argument, NULL, 'u',
  59         "\tUpgrade the configuration to the latest syntax", pcmk__option_default
  60     },
  61     {
  62         "query", no_argument, NULL, 'Q',
  63         "\tQuery the contents of the CIB", pcmk__option_default
  64     },
  65     {
  66         "erase", no_argument, NULL, 'E',
  67         "\tErase the contents of the whole CIB", pcmk__option_default
  68     },
  69     {
  70         "bump", no_argument, NULL, 'B',
  71         "\tIncrease the CIB's epoch value by 1", pcmk__option_default
  72     },
  73     {
  74         "create", no_argument, NULL, 'C',
  75         "\tCreate an object in the CIB (will fail if object already exists)",
  76         pcmk__option_default
  77     },
  78     {
  79         "modify", no_argument, NULL, 'M',
  80         "\tFind object somewhere in CIB's XML tree and update it "
  81             "(fails if object does not exist unless -c is also specified)",
  82         pcmk__option_default
  83     },
  84     {
  85         "patch", no_argument, NULL, 'P',
  86         "\tSupply an update in the form of an XML diff (see crm_diff(8))",
  87         pcmk__option_default
  88     },
  89     {
  90         "replace", no_argument, NULL, 'R',
  91         "\tRecursively replace an object in the CIB", pcmk__option_default
  92     },
  93     {
  94         "delete", no_argument, NULL, 'D',
  95         "\tDelete first object matching supplied criteria "
  96             "(for example, <op id=\"rsc1_op1\" name=\"monitor\"/>)",
  97         pcmk__option_default
  98     },
  99     {
 100         "-spacer-", no_argument, NULL, '-',
 101         "\n\tThe XML element name and all attributes must match "
 102             "in order for the element to be deleted.\n",
 103         pcmk__option_default
 104     },
 105     {
 106         "delete-all", no_argument, NULL, 'd',
 107         "When used with --xpath, remove all matching objects in the "
 108             "configuration instead of just the first one",
 109         pcmk__option_default
 110     },
 111     {
 112         "empty", no_argument, NULL, 'a',
 113         "\tOutput an empty CIB", pcmk__option_default
 114     },
 115     {
 116         "md5-sum", no_argument, NULL, '5',
 117         "\tCalculate the on-disk CIB digest", pcmk__option_default
 118     },
 119     {
 120         "md5-sum-versioned", no_argument, NULL, '6',
 121         "Calculate an on-the-wire versioned CIB digest", pcmk__option_default
 122     },
 123     {
 124         "blank", no_argument, NULL, '-',
 125         NULL, pcmk__option_hidden
 126     },
 127 
 128     {
 129         "-spacer-", required_argument, NULL, '-',
 130         "\nAdditional options:", pcmk__option_default
 131     },
 132     {
 133         "force", no_argument, NULL, 'f',
 134         NULL, pcmk__option_default
 135     },
 136     {
 137         "timeout", required_argument, NULL, 't',
 138         "Time (in seconds) to wait before declaring the operation failed",
 139         pcmk__option_default
 140     },
 141     {
 142         "user", required_argument, NULL, 'U',
 143         "Run the command with permissions of the named user (valid only for "
 144             "the root and " CRM_DAEMON_USER " accounts)",
 145         pcmk__option_default
 146     },
 147     {
 148         "sync-call", no_argument, NULL, 's',
 149         "Wait for call to complete before returning", pcmk__option_default
 150     },
 151     {
 152         "local", no_argument, NULL, 'l',
 153         "\tCommand takes effect locally (should be used only for queries)",
 154         pcmk__option_default
 155     },
 156     {
 157         "allow-create", no_argument, NULL, 'c',
 158         "(Advanced) Allow target of --modify/-M to be created "
 159             "if it does not exist",
 160         pcmk__option_default
 161     },
 162     {
 163         "no-children", no_argument, NULL, 'n',
 164         "(Advanced) When querying an object, do not include its children "
 165             "in the result",
 166         pcmk__option_default
 167     },
 168     {
 169         "no-bcast", no_argument, NULL, 'b',
 170         NULL, pcmk__option_hidden
 171     },
 172 
 173     {
 174         "-spacer-", no_argument, NULL, '-',
 175         "\nData:", pcmk__option_default
 176     },
 177     {
 178         "xml-text", required_argument, NULL, 'X',
 179         "Retrieve XML from the supplied string", pcmk__option_default
 180     },
 181     {
 182         "xml-file", required_argument, NULL, 'x',
 183         "Retrieve XML from the named file", pcmk__option_default
 184     },
 185     {
 186         "xml-pipe", no_argument, NULL, 'p',
 187         "Retrieve XML from stdin\n", pcmk__option_default
 188     },
 189 
 190     {
 191         "scope", required_argument, NULL, 'o',
 192         "Limit scope of operation to specific section of CIB",
 193         pcmk__option_default
 194     },
 195     {
 196         "-spacer-", no_argument, NULL, '-',
 197         "\tValid values: configuration, nodes, resources, constraints, "
 198             "crm_config, rsc_defaults, op_defaults, acls, fencing-topology, "
 199             "tags, alerts",
 200         pcmk__option_default
 201     },
 202 
 203     {
 204         "xpath", required_argument, NULL, 'A',
 205         "A valid XPath to use instead of --scope/-o", pcmk__option_default
 206     },
 207     {
 208         "node-path", no_argument, NULL, 'e',
 209         "When performing XPath queries, return path of any matches found",
 210         pcmk__option_default
 211     },
 212     {
 213         "-spacer-", no_argument, NULL, '-',
 214         "\t(for example, \"/cib/configuration/resources/clone[@id='ms_RH1_SCS']"
 215             "/primitive[@id='prm_RH1_SCS']\")",
 216         pcmk__option_paragraph
 217     },
 218     {
 219         "node", required_argument, NULL, 'N',
 220         "(Advanced) Send command to the specified host", pcmk__option_default
 221     },
 222     {
 223         "-spacer-", no_argument, NULL, '!',
 224         NULL, pcmk__option_hidden
 225     },
 226     {
 227         "-spacer-", no_argument, NULL, '-',
 228         "\n\nExamples:\n", pcmk__option_default
 229     },
 230     {
 231         "-spacer-", no_argument, NULL, '-',
 232         "Query the configuration from the local node:", pcmk__option_paragraph
 233     },
 234     {
 235         "-spacer-", no_argument, NULL, '-',
 236         " cibadmin --query --local", pcmk__option_example
 237     },
 238 
 239     {
 240         "-spacer-", no_argument, NULL, '-',
 241         "Query just the cluster options configuration:", pcmk__option_paragraph
 242     },
 243     {
 244         "-spacer-", no_argument, NULL, '-',
 245         " cibadmin --query --scope crm_config", pcmk__option_example
 246     },
 247 
 248     {
 249         "-spacer-", no_argument, NULL, '-',
 250         "Query all 'target-role' settings:", pcmk__option_paragraph
 251     },
 252     {
 253         "-spacer-", no_argument, NULL, '-',
 254         " cibadmin --query --xpath \"//nvpair[@name='target-role']\"",
 255         pcmk__option_example
 256     },
 257 
 258     {
 259         "-spacer-", no_argument, NULL, '-',
 260         "Remove all 'is-managed' settings:", pcmk__option_paragraph
 261     },
 262     {
 263         "-spacer-", no_argument, NULL, '-',
 264         " cibadmin --delete-all --xpath \"//nvpair[@name='is-managed']\"",
 265         pcmk__option_example
 266     },
 267 
 268     {
 269         "-spacer-", no_argument, NULL, '-',
 270         "Remove the resource named 'old':", pcmk__option_paragraph
 271     },
 272     {
 273         "-spacer-", no_argument, NULL, '-',
 274         " cibadmin --delete --xml-text '<primitive id=\"old\"/>'",
 275         pcmk__option_example
 276     },
 277     {
 278         "-spacer-", no_argument, NULL, '-',
 279         "Remove all resources from the configuration:", pcmk__option_paragraph
 280     },
 281     {
 282         "-spacer-", no_argument, NULL, '-',
 283         " cibadmin --replace --scope resources --xml-text '<resources/>'",
 284         pcmk__option_example
 285     },
 286     {
 287         "-spacer-", no_argument, NULL, '-',
 288         "Replace complete configuration with contents of $HOME/pacemaker.xml:",
 289         pcmk__option_paragraph
 290     },
 291     {
 292         "-spacer-", no_argument, NULL, '-',
 293         " cibadmin --replace --xml-file $HOME/pacemaker.xml",
 294         pcmk__option_example
 295     },
 296     {
 297         "-spacer-", no_argument, NULL, '-',
 298         "Replace constraints section of configuration with contents of "
 299             "$HOME/constraints.xml:",
 300         pcmk__option_paragraph
 301     },
 302     {
 303         "-spacer-", no_argument, NULL, '-',
 304         " cibadmin --replace --scope constraints --xml-file "
 305             "$HOME/constraints.xml",
 306         pcmk__option_example
 307     },
 308     {
 309         "-spacer-", no_argument, NULL, '-',
 310         "Increase configuration version to prevent old configurations from "
 311             "being loaded accidentally:",
 312         pcmk__option_paragraph
 313     },
 314     {
 315         "-spacer-", no_argument, NULL, '-',
 316         " cibadmin --modify --xml-text '<cib admin_epoch=\"admin_epoch++\"/>'",
 317         pcmk__option_example
 318     },
 319     {
 320         "-spacer-", no_argument, NULL, '-',
 321         "Edit the configuration with your favorite $EDITOR:",
 322         pcmk__option_paragraph
 323     },
 324     {
 325         "-spacer-", no_argument, NULL, '-',
 326         " cibadmin --query > $HOME/local.xml", pcmk__option_example
 327     },
 328     {
 329         "-spacer-", no_argument, NULL, '-',
 330         " $EDITOR $HOME/local.xml", pcmk__option_example
 331     },
 332     {
 333         "-spacer-", no_argument, NULL, '-',
 334         " cibadmin --replace --xml-file $HOME/local.xml", pcmk__option_example
 335     },
 336     {
 337         "-spacer-", no_argument, NULL, '-',
 338         "SEE ALSO:", pcmk__option_default
 339     },
 340     {
 341         "-spacer-", no_argument, NULL, '-',
 342         " crm(8), pcs(8), crm_shadow(8), crm_diff(8)", pcmk__option_default
 343     },
 344     {
 345         "host", required_argument, NULL, 'h',
 346         "deprecated", pcmk__option_hidden
 347     },
 348     { 0, 0, 0, 0 }
 349 };
 350 
 351 static void
 352 print_xml_output(xmlNode * xml)
     /* [previous][next][first][last][top][bottom][index][help] */
 353 {
 354     char *buffer;
 355 
 356     if (!xml) {
 357         return;
 358     } else if (xml->type != XML_ELEMENT_NODE) {
 359         return;
 360     }
 361 
 362     if (command_options & cib_xpath_address) {
 363         const char *id = crm_element_value(xml, XML_ATTR_ID);
 364 
 365         if (pcmk__str_eq((const char *)xml->name, "xpath-query", pcmk__str_casei)) {
 366             xmlNode *child = NULL;
 367 
 368             for (child = xml->children; child; child = child->next) {
 369                 print_xml_output(child);
 370             }
 371 
 372         } else if (id) {
 373             printf("%s\n", id);
 374         }
 375 
 376     } else {
 377         buffer = dump_xml_formatted(xml);
 378         fprintf(stdout, "%s", crm_str(buffer));
 379         free(buffer);
 380     }
 381 }
 382 
 383 // Upgrade requested but already at latest schema
 384 static void
 385 report_schema_unchanged(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 386 {
 387     const char *err = pcmk_strerror(pcmk_err_schema_unchanged);
 388 
 389     crm_info("Upgrade unnecessary: %s\n", err);
 390     printf("Upgrade unnecessary: %s\n", err);
 391     exit_code = CRM_EX_OK;
 392 }
 393 
 394 int
 395 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 396 {
 397     int argerr = 0;
 398     int rc = pcmk_ok;
 399     int flag;
 400     const char *source = NULL;
 401     const char *admin_input_xml = NULL;
 402     const char *admin_input_file = NULL;
 403     gboolean dangerous_cmd = FALSE;
 404     gboolean admin_input_stdin = FALSE;
 405     xmlNode *output = NULL;
 406     xmlNode *input = NULL;
 407 
 408     int option_index = 0;
 409 
 410     pcmk__cli_init_logging("cibadmin", 0);
 411     set_crm_log_level(LOG_CRIT);
 412     pcmk__set_cli_options(NULL, "<command> [options]", long_options,
 413                           "query and edit the Pacemaker configuration");
 414 
 415     if (argc < 2) {
 416         pcmk__cli_help('?', CRM_EX_USAGE);
 417     }
 418 
 419     while (1) {
 420         flag = pcmk__next_cli_option(argc, argv, &option_index, NULL);
 421         if (flag == -1)
 422             break;
 423 
 424         switch (flag) {
 425             case 't':
 426                 message_timeout_ms = atoi(optarg);
 427                 if (message_timeout_ms < 1) {
 428                     message_timeout_ms = 30;
 429                 }
 430                 break;
 431             case 'A':
 432                 obj_type = optarg;
 433                 cib__set_call_options(command_options, crm_system_name,
 434                                       cib_xpath);
 435                 break;
 436             case 'e':
 437                 cib__set_call_options(command_options, crm_system_name,
 438                                       cib_xpath_address);
 439                 break;
 440             case 'u':
 441                 cib_action = CIB_OP_UPGRADE;
 442                 dangerous_cmd = TRUE;
 443                 break;
 444             case 'E':
 445                 cib_action = CIB_OP_ERASE;
 446                 dangerous_cmd = TRUE;
 447                 break;
 448             case 'Q':
 449                 cib_action = CIB_OP_QUERY;
 450                 break;
 451             case 'P':
 452                 cib_action = CIB_OP_APPLY_DIFF;
 453                 break;
 454             case 'U':
 455                 cib_user = optarg;
 456                 break;
 457             case 'M':
 458                 cib_action = CIB_OP_MODIFY;
 459                 break;
 460             case 'R':
 461                 cib_action = CIB_OP_REPLACE;
 462                 break;
 463             case 'C':
 464                 cib_action = CIB_OP_CREATE;
 465                 break;
 466             case 'D':
 467                 cib_action = CIB_OP_DELETE;
 468                 break;
 469             case '5':
 470                 cib_action = "md5-sum";
 471                 break;
 472             case '6':
 473                 cib_action = "md5-sum-versioned";
 474                 break;
 475             case 'c':
 476                 cib__set_call_options(command_options, crm_system_name,
 477                                       cib_can_create);
 478                 break;
 479             case 'n':
 480                 cib__set_call_options(command_options, crm_system_name,
 481                                       cib_no_children);
 482                 break;
 483             case 'B':
 484                 cib_action = CIB_OP_BUMP;
 485                 crm_log_args(argc, argv);
 486                 break;
 487             case 'V':
 488                 cib__set_call_options(command_options, crm_system_name,
 489                                       cib_verbose);
 490                 bump_log_num++;
 491                 break;
 492             case '?':
 493             case '$':
 494             case '!':
 495                 pcmk__cli_help(flag, CRM_EX_OK);
 496                 break;
 497             case 'o':
 498                 crm_trace("Option %c => %s", flag, optarg);
 499                 obj_type = optarg;
 500                 break;
 501             case 'X':
 502                 crm_trace("Option %c => %s", flag, optarg);
 503                 admin_input_xml = optarg;
 504                 crm_log_args(argc, argv);
 505                 break;
 506             case 'x':
 507                 crm_trace("Option %c => %s", flag, optarg);
 508                 admin_input_file = optarg;
 509                 crm_log_args(argc, argv);
 510                 break;
 511             case 'p':
 512                 admin_input_stdin = TRUE;
 513                 crm_log_args(argc, argv);
 514                 break;
 515             case 'N':
 516             case 'h':
 517                 host = strdup(optarg);
 518                 break;
 519             case 'l':
 520                 cib__set_call_options(command_options, crm_system_name,
 521                                       cib_scope_local);
 522                 break;
 523             case 'd':
 524                 cib_action = CIB_OP_DELETE;
 525                 cib__set_call_options(command_options, crm_system_name,
 526                                       cib_multiple);
 527                 dangerous_cmd = TRUE;
 528                 break;
 529             case 'b':
 530                 dangerous_cmd = TRUE;
 531                 cib__set_call_options(command_options, crm_system_name,
 532                                       cib_inhibit_bcast|cib_scope_local);
 533                 break;
 534             case 's':
 535                 cib__set_call_options(command_options, crm_system_name,
 536                                       cib_sync_call);
 537                 break;
 538             case 'f':
 539                 force_flag = TRUE;
 540                 cib__set_call_options(command_options, crm_system_name,
 541                                       cib_quorum_override);
 542                 crm_log_args(argc, argv);
 543                 break;
 544             case 'a':
 545                 output = createEmptyCib(1);
 546                 if (optind < argc) {
 547                     crm_xml_add(output, XML_ATTR_VALIDATION, argv[optind]);
 548                 }
 549                 admin_input_xml = dump_xml_formatted(output);
 550                 fprintf(stdout, "%s\n", crm_str(admin_input_xml));
 551                 crm_exit(CRM_EX_OK);
 552                 break;
 553             default:
 554                 printf("Argument code 0%o (%c)" " is not (?yet?) supported\n", flag, flag);
 555                 ++argerr;
 556                 break;
 557         }
 558     }
 559 
 560     while (bump_log_num > 0) {
 561         crm_bump_log_level(argc, argv);
 562         bump_log_num--;
 563     }
 564 
 565     if (optind < argc) {
 566         printf("non-option ARGV-elements: ");
 567         while (optind < argc)
 568             printf("%s ", argv[optind++]);
 569         printf("\n");
 570         pcmk__cli_help('?', CRM_EX_USAGE);
 571     }
 572 
 573     if (optind > argc || cib_action == NULL) {
 574         ++argerr;
 575     }
 576 
 577     if (argerr) {
 578         pcmk__cli_help('?', CRM_EX_USAGE);
 579     }
 580 
 581     if (dangerous_cmd && force_flag == FALSE) {
 582         fprintf(stderr, "The supplied command is considered dangerous."
 583                 "  To prevent accidental destruction of the cluster,"
 584                 " the --force flag is required in order to proceed.\n");
 585         fflush(stderr);
 586         crm_exit(CRM_EX_UNSAFE);
 587     }
 588 
 589     if (admin_input_file != NULL) {
 590         input = filename2xml(admin_input_file);
 591         source = admin_input_file;
 592 
 593     } else if (admin_input_xml != NULL) {
 594         source = "input string";
 595         input = string2xml(admin_input_xml);
 596 
 597     } else if (admin_input_stdin) {
 598         source = "STDIN";
 599         input = stdin2xml();
 600     }
 601 
 602     if (input != NULL) {
 603         crm_log_xml_debug(input, "[admin input]");
 604 
 605     } else if (source) {
 606         fprintf(stderr, "Couldn't parse input from %s.\n", source);
 607         crm_exit(CRM_EX_CONFIG);
 608     }
 609 
 610     if (pcmk__str_eq(cib_action, "md5-sum", pcmk__str_casei)) {
 611         char *digest = NULL;
 612 
 613         if (input == NULL) {
 614             fprintf(stderr, "Please supply XML to process with -X, -x or -p\n");
 615             crm_exit(CRM_EX_USAGE);
 616         }
 617 
 618         digest = calculate_on_disk_digest(input);
 619         fprintf(stderr, "Digest: ");
 620         fprintf(stdout, "%s\n", crm_str(digest));
 621         free(digest);
 622         free_xml(input);
 623         crm_exit(CRM_EX_OK);
 624 
 625     } else if (pcmk__str_eq(cib_action, "md5-sum-versioned", pcmk__str_casei)) {
 626         char *digest = NULL;
 627         const char *version = NULL;
 628 
 629         if (input == NULL) {
 630             fprintf(stderr, "Please supply XML to process with -X, -x or -p\n");
 631             crm_exit(CRM_EX_USAGE);
 632         }
 633 
 634         version = crm_element_value(input, XML_ATTR_CRM_VERSION);
 635         digest = calculate_xml_versioned_digest(input, FALSE, TRUE, version);
 636         fprintf(stderr, "Versioned (%s) digest: ", version);
 637         fprintf(stdout, "%s\n", crm_str(digest));
 638         free(digest);
 639         free_xml(input);
 640         crm_exit(CRM_EX_OK);
 641     }
 642 
 643     rc = do_init();
 644     if (rc != pcmk_ok) {
 645         crm_err("Init failed, could not perform requested operations");
 646         fprintf(stderr, "Init failed, could not perform requested operations\n");
 647         free_xml(input);
 648         crm_exit(crm_errno2exit(rc));
 649     }
 650 
 651     rc = do_work(input, command_options, &output);
 652     if (rc > 0) {
 653         /* wait for the reply by creating a mainloop and running it until
 654          * the callbacks are invoked...
 655          */
 656         request_id = rc;
 657 
 658         the_cib->cmds->register_callback(the_cib, request_id, message_timeout_ms, FALSE, NULL,
 659                                          "cibadmin_op_callback", cibadmin_op_callback);
 660 
 661         mainloop = g_main_loop_new(NULL, FALSE);
 662 
 663         crm_trace("%s waiting for reply from the local CIB", crm_system_name);
 664 
 665         crm_info("Starting mainloop");
 666         g_main_loop_run(mainloop);
 667 
 668     } else if ((rc == -pcmk_err_schema_unchanged)
 669                && pcmk__str_eq(cib_action, CIB_OP_UPGRADE, pcmk__str_none)) {
 670         report_schema_unchanged();
 671 
 672     } else if (rc < 0) {
 673         crm_err("Call failed: %s", pcmk_strerror(rc));
 674         fprintf(stderr, "Call failed: %s\n", pcmk_strerror(rc));
 675 
 676         if (rc == -pcmk_err_schema_validation) {
 677             if (pcmk__str_eq(cib_action, CIB_OP_UPGRADE, pcmk__str_none)) {
 678                 xmlNode *obj = NULL;
 679                 int version = 0, rc = 0;
 680 
 681                 rc = the_cib->cmds->query(the_cib, NULL, &obj, command_options);
 682                 if (rc == pcmk_ok) {
 683                     update_validation(&obj, &version, 0, TRUE, FALSE);
 684                 }
 685 
 686             } else if (output) {
 687                 validate_xml_verbose(output);
 688             }
 689         }
 690         exit_code = crm_errno2exit(rc);
 691     }
 692 
 693     if (output != NULL) {
 694         print_xml_output(output);
 695         free_xml(output);
 696     }
 697 
 698     crm_trace("%s exiting normally", crm_system_name);
 699 
 700     free_xml(input);
 701     rc = the_cib->cmds->signoff(the_cib);
 702     if (exit_code == CRM_EX_OK) {
 703         exit_code = crm_errno2exit(rc);
 704     }
 705     cib_delete(the_cib);
 706 
 707     crm_exit(exit_code);
 708 }
 709 
 710 int
 711 do_work(xmlNode * input, int call_options, xmlNode ** output)
     /* [previous][next][first][last][top][bottom][index][help] */
 712 {
 713     /* construct the request */
 714     the_cib->call_timeout = message_timeout_ms;
 715     if (strcasecmp(CIB_OP_REPLACE, cib_action) == 0
 716         && pcmk__str_eq(crm_element_name(input), XML_TAG_CIB, pcmk__str_casei)) {
 717         xmlNode *status = get_object_root(XML_CIB_TAG_STATUS, input);
 718 
 719         if (status == NULL) {
 720             create_xml_node(input, XML_CIB_TAG_STATUS);
 721         }
 722     }
 723 
 724     if (cib_action != NULL) {
 725         crm_trace("Passing \"%s\" to variant_op...", cib_action);
 726         return cib_internal_op(the_cib, cib_action, host, obj_type, input, output, call_options, cib_user);
 727 
 728     } else {
 729         crm_err("You must specify an operation");
 730     }
 731     return -EINVAL;
 732 }
 733 
 734 int
 735 do_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 736 {
 737     int rc = pcmk_ok;
 738 
 739     the_cib = cib_new();
 740     rc = the_cib->cmds->signon(the_cib, crm_system_name, cib_command);
 741     if (rc != pcmk_ok) {
 742         crm_err("Could not connect to the CIB: %s", pcmk_strerror(rc));
 743         fprintf(stderr, "Could not connect to the CIB: %s\n",
 744                 pcmk_strerror(rc));
 745     }
 746 
 747     return rc;
 748 }
 749 
 750 void
 751 cibadmin_op_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 752 {
 753     exit_code = crm_errno2exit(rc);
 754 
 755     if (rc == -pcmk_err_schema_unchanged) {
 756         report_schema_unchanged();
 757 
 758     } else if (rc != pcmk_ok) {
 759         crm_warn("Call %s failed (%d): %s", cib_action, rc, pcmk_strerror(rc));
 760         fprintf(stderr, "Call %s failed (%d): %s\n", cib_action, rc, pcmk_strerror(rc));
 761         print_xml_output(output);
 762 
 763     } else if (pcmk__str_eq(cib_action, CIB_OP_QUERY, pcmk__str_casei) && output == NULL) {
 764         crm_err("Query returned no output");
 765         crm_log_xml_err(msg, "no output");
 766 
 767     } else if (output == NULL) {
 768         crm_info("Call passed");
 769 
 770     } else {
 771         crm_info("Call passed");
 772         print_xml_output(output);
 773     }
 774 
 775     if (call_id == request_id) {
 776         g_main_loop_quit(mainloop);
 777 
 778     } else {
 779         crm_info("Message was not the response we were looking for (%d vs. %d)",
 780                  call_id, request_id);
 781     }
 782 }

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