root/tools/crm_attribute.c

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

DEFINITIONS

This source file includes following definitions.
  1. main

   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 
  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     // long option, argument type, storage, short option, description, flags
  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     /* legacy */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* we're updating cluster options - don't populate dest_node */
 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         /* If we are being called from a resource agent via the cluster,
 382          * the correct local node name will be passed as an environment
 383          * variable. Otherwise, we have to ask the cluster.
 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     // Only go through attribute manager for transient attributes
 417     try_attrd = pcmk__str_eq(type, XML_CIB_TAG_STATUS, pcmk__str_casei);
 418 
 419     // Don't try to contact attribute manager if we're using a file as CIB
 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             /* Nothing to delete...
 440              * which means it's not there...
 441              * which is what the admin wanted
 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 {                    /* query */
 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             // Multiple matches (already displayed) are not error for queries
 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 }

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