root/tools/stonith_admin.c

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

DEFINITIONS

This source file includes following definitions.
  1. add_env_params
  2. add_stonith_device
  3. add_tolerance
  4. add_stonith_params
  5. set_tag
  6. build_arg_context
  7. request_fencing
  8. main

   1 /*
   2  * Copyright 2009-2023 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 <sys/param.h>
  13 #include <stdio.h>
  14 #include <sys/types.h>
  15 #include <sys/stat.h>
  16 #include <unistd.h>
  17 #include <sys/utsname.h>
  18 
  19 #include <errno.h>
  20 #include <fcntl.h>
  21 #include <stdbool.h>
  22 #include <stdlib.h>
  23 #include <string.h>
  24 
  25 #include <crm/crm.h>
  26 #include <crm/msg_xml.h>
  27 #include <crm/common/ipc.h>
  28 #include <crm/cluster/internal.h>
  29 #include <crm/common/cmdline_internal.h>
  30 #include <crm/common/output_internal.h>
  31 
  32 #include <crm/stonith-ng.h>
  33 #include <crm/fencing/internal.h>
  34 #include <crm/cib.h>
  35 #include <crm/pengine/status.h>
  36 
  37 #include <crm/common/xml.h>
  38 #include <pacemaker-internal.h>
  39 
  40 #define SUMMARY "stonith_admin - Access the Pacemaker fencing API"
  41 
  42 char action = 0;
  43 
  44 struct {
  45     gboolean as_nodeid;
  46     gboolean broadcast;
  47     gboolean cleanup;
  48     gboolean installed;
  49     gboolean metadata;
  50     gboolean registered;
  51     gboolean validate_cfg;
  52     stonith_key_value_t *devices;
  53     stonith_key_value_t *params;
  54     int fence_level;
  55     int timeout ;
  56     int tolerance;
  57     int delay;
  58     char *agent;
  59     char *confirm_host;
  60     char *fence_host;
  61     char *history;
  62     char *last_fenced;
  63     char *query;
  64     char *reboot_host;
  65     char *register_dev;
  66     char *register_level;
  67     char *targets;
  68     char *terminate;
  69     char *unfence_host;
  70     char *unregister_dev;
  71     char *unregister_level;
  72 } options = {
  73     .timeout = 120,
  74     .delay = 0
  75 };
  76 
  77 gboolean add_env_params(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
  78 gboolean add_stonith_device(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
  79 gboolean add_stonith_params(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
  80 gboolean add_tolerance(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
  81 gboolean set_tag(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
  82 
  83 #define INDENT "                                    "
  84 
  85 /* *INDENT-OFF* */
  86 static GOptionEntry defn_entries[] = {
  87     { "register", 'R', 0, G_OPTION_ARG_STRING, &options.register_dev,
  88       "Register the named stonith device. Requires: --agent.\n"
  89       INDENT "Optional: --option, --env-option.",
  90       "DEVICE" },
  91     { "deregister", 'D', 0, G_OPTION_ARG_STRING, &options.unregister_dev,
  92       "De-register the named stonith device.",
  93       "DEVICE" },
  94     { "register-level", 'r', 0, G_OPTION_ARG_STRING, &options.register_level,
  95       "Register a stonith level for the named target,\n"
  96       INDENT "specified as one of NAME, @PATTERN, or ATTR=VALUE.\n"
  97       INDENT "Requires: --index and one or more --device entries.",
  98       "TARGET" },
  99     { "deregister-level", 'd', 0, G_OPTION_ARG_STRING, &options.unregister_level,
 100       "Unregister a stonith level for the named target,\n"
 101       INDENT "specified as for --register-level. Requires: --index",
 102       "TARGET" },
 103 
 104     { NULL }
 105 };
 106 
 107 static GOptionEntry query_entries[] = {
 108     { "list", 'l', 0, G_OPTION_ARG_STRING, &options.terminate,
 109       "List devices that can terminate the specified host.\n"
 110       INDENT "Optional: --timeout",
 111       "HOST" },
 112     { "list-registered", 'L', 0, G_OPTION_ARG_NONE, &options.registered,
 113       "List all registered devices. Optional: --timeout.",
 114       NULL },
 115     { "list-installed", 'I', 0, G_OPTION_ARG_NONE, &options.installed,
 116       "List all installed devices. Optional: --timeout.",
 117       NULL },
 118     { "list-targets", 's', 0, G_OPTION_ARG_STRING, &options.targets,
 119       "List the targets that can be fenced by the\n"
 120       INDENT "named device. Optional: --timeout.",
 121       "DEVICE" },
 122     { "metadata", 'M', 0, G_OPTION_ARG_NONE, &options.metadata,
 123       "Show agent metadata. Requires: --agent.\n"
 124       INDENT "Optional: --timeout.",
 125       NULL },
 126     { "query", 'Q', 0, G_OPTION_ARG_STRING, &options.query,
 127       "Check the named device's status. Optional: --timeout.",
 128       "DEVICE" },
 129     { "history", 'H', 0, G_OPTION_ARG_STRING, &options.history,
 130       "Show last successful fencing operation for named node\n"
 131       INDENT "(or '*' for all nodes). Optional: --timeout, --cleanup,\n"
 132       INDENT "--quiet (show only the operation's epoch timestamp),\n"
 133       INDENT "--verbose (show all recorded and pending operations),\n"
 134       INDENT "--broadcast (update history from all nodes available).",
 135       "NODE" },
 136     { "last", 'h', 0, G_OPTION_ARG_STRING, &options.last_fenced,
 137       "Indicate when the named node was last fenced.\n"
 138       INDENT "Optional: --as-node-id.",
 139       "NODE" },
 140     { "validate", 'K', 0, G_OPTION_ARG_NONE, &options.validate_cfg,
 141       "Validate a fence device configuration.\n"
 142       INDENT "Requires: --agent. Optional: --option, --env-option,\n"
 143       INDENT "--quiet (print no output, only return status).",
 144       NULL },
 145 
 146     { NULL }
 147 };
 148 
 149 static GOptionEntry fence_entries[] = {
 150     { "fence", 'F', 0, G_OPTION_ARG_STRING, &options.fence_host,
 151       "Fence named host. Optional: --timeout, --tolerance, --delay.",
 152       "HOST" },
 153     { "unfence", 'U', 0, G_OPTION_ARG_STRING, &options.unfence_host,
 154       "Unfence named host. Optional: --timeout, --tolerance, --delay.",
 155       "HOST" },
 156     { "reboot", 'B', 0, G_OPTION_ARG_STRING, &options.reboot_host,
 157       "Reboot named host. Optional: --timeout, --tolerance, --delay.",
 158       "HOST" },
 159     { "confirm", 'C', 0, G_OPTION_ARG_STRING, &options.confirm_host,
 160       "Tell cluster that named host is now safely down.",
 161       "HOST", },
 162 
 163     { NULL }
 164 };
 165 
 166 static GOptionEntry addl_entries[] = {
 167     { "cleanup", 'c', 0, G_OPTION_ARG_NONE, &options.cleanup,
 168       "Cleanup wherever appropriate. Requires --history.",
 169       NULL },
 170     { "broadcast", 'b', 0, G_OPTION_ARG_NONE, &options.broadcast,
 171       "Broadcast wherever appropriate.",
 172       NULL },
 173     { "agent", 'a', 0, G_OPTION_ARG_STRING, &options.agent,
 174       "The agent to use (for example, fence_xvm;\n"
 175       INDENT "with --register, --metadata, --validate).",
 176       "AGENT" },
 177     { "option", 'o', 0, G_OPTION_ARG_CALLBACK, add_stonith_params,
 178       "Specify a device configuration parameter as NAME=VALUE\n"
 179       INDENT "(may be specified multiple times; with --register,\n"
 180       INDENT "--validate).",
 181       "PARAM" },
 182     { "env-option", 'e', 0, G_OPTION_ARG_CALLBACK, add_env_params,
 183       "Specify a device configuration parameter with the\n"
 184       INDENT "specified name, using the value of the\n"
 185       INDENT "environment variable of the same name prefixed with\n"
 186       INDENT "OCF_RESKEY_ (may be specified multiple times;\n"
 187       INDENT "with --register, --validate).",
 188       "PARAM" },
 189     { "tag", 'T', 0, G_OPTION_ARG_CALLBACK, set_tag,
 190       "Identify fencing operations in logs with the specified\n"
 191       INDENT "tag; useful when multiple entities might invoke\n"
 192       INDENT "stonith_admin (used with most commands).",
 193       "TAG" },
 194     { "device", 'v', 0, G_OPTION_ARG_CALLBACK, add_stonith_device,
 195       "Device ID (with --register-level, device to associate with\n"
 196       INDENT "a given host and level; may be specified multiple times)"
 197 #if SUPPORT_CIBSECRETS
 198       "\n" INDENT "(with --validate, name to use to load CIB secrets)"
 199 #endif
 200       ".",
 201       "DEVICE" },
 202     { "index", 'i', 0, G_OPTION_ARG_INT, &options.fence_level,
 203       "The stonith level (1-9) (with --register-level,\n"
 204       INDENT "--deregister-level).",
 205       "LEVEL" },
 206     { "timeout", 't', 0, G_OPTION_ARG_INT, &options.timeout,
 207       "Operation timeout in seconds (default 120;\n"
 208       INDENT "used with most commands).",
 209       "SECONDS" },
 210     { "delay", 'y', 0, G_OPTION_ARG_INT, &options.delay,
 211       "Apply a fencing delay in seconds. Any static/random delays from\n"
 212       INDENT "pcmk_delay_base/max will be added, otherwise all\n"
 213       INDENT "disabled with the value -1\n"
 214       INDENT "(default 0; with --fence, --reboot, --unfence).",
 215       "SECONDS" },
 216     { "as-node-id", 'n', 0, G_OPTION_ARG_NONE, &options.as_nodeid,
 217       "(Advanced) The supplied node is the corosync node ID\n"
 218       INDENT "(with --last).",
 219       NULL },
 220     { "tolerance", 0, 0, G_OPTION_ARG_CALLBACK, add_tolerance,
 221       "(Advanced) Do nothing if an equivalent --fence request\n"
 222       INDENT "succeeded less than this many seconds earlier\n"
 223       INDENT "(with --fence, --unfence, --reboot).",
 224       "SECONDS" },
 225 
 226     { NULL }
 227 };
 228 /* *INDENT-ON* */
 229 
 230 static pcmk__supported_format_t formats[] = {
 231     PCMK__SUPPORTED_FORMAT_HTML,
 232     PCMK__SUPPORTED_FORMAT_NONE,
 233     PCMK__SUPPORTED_FORMAT_TEXT,
 234     PCMK__SUPPORTED_FORMAT_XML,
 235     { NULL, NULL, NULL }
 236 };
 237 
 238 static const int st_opts = st_opt_sync_call | st_opt_allow_suicide;
 239 
 240 static char *name = NULL;
 241 
 242 gboolean
 243 add_env_params(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     /* [previous][next][first][last][top][bottom][index][help] */
 244     char *key = crm_strdup_printf("OCF_RESKEY_%s", optarg);
 245     const char *env = getenv(key);
 246     gboolean retval = TRUE;
 247 
 248     if (env == NULL) {
 249         g_set_error(error, PCMK__EXITC_ERROR, CRM_EX_INVALID_PARAM, "Invalid option: -e %s", optarg);
 250         retval = FALSE;
 251     } else {
 252         crm_info("Got: '%s'='%s'", optarg, env);
 253         options.params = stonith_key_value_add(options.params, optarg, env);
 254     }
 255 
 256     free(key);
 257     return retval;
 258 }
 259 
 260 gboolean
 261 add_stonith_device(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     /* [previous][next][first][last][top][bottom][index][help] */
 262     options.devices = stonith_key_value_add(options.devices, NULL, optarg);
 263     return TRUE;
 264 }
 265 
 266 gboolean
 267 add_tolerance(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     /* [previous][next][first][last][top][bottom][index][help] */
 268     options.tolerance = crm_get_msec(optarg) / 1000;
 269     return TRUE;
 270 }
 271 
 272 gboolean
 273 add_stonith_params(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     /* [previous][next][first][last][top][bottom][index][help] */
 274     char *name = NULL;
 275     char *value = NULL;
 276     int rc = 0;
 277     gboolean retval = TRUE;
 278 
 279     crm_info("Scanning: -o %s", optarg);
 280 
 281     rc = pcmk__scan_nvpair(optarg, &name, &value);
 282 
 283     if (rc != 2) {
 284         rc = pcmk_legacy2rc(rc);
 285         g_set_error(error, PCMK__RC_ERROR, rc, "Invalid option: -o %s: %s", optarg, pcmk_rc_str(rc));
 286         retval = FALSE;
 287     } else {
 288         crm_info("Got: '%s'='%s'", name, value);
 289         options.params = stonith_key_value_add(options.params, name, value);
 290     }
 291 
 292     free(name);
 293     free(value);
 294     return retval;
 295 }
 296 
 297 gboolean
 298 set_tag(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     /* [previous][next][first][last][top][bottom][index][help] */
 299     free(name);
 300     name = crm_strdup_printf("%s.%s", crm_system_name, optarg);
 301     return TRUE;
 302 }
 303 
 304 static GOptionContext *
 305 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
     /* [previous][next][first][last][top][bottom][index][help] */
 306     GOptionContext *context = NULL;
 307 
 308     GOptionEntry extra_prog_entries[] = {
 309         { "quiet", 'q', 0, G_OPTION_ARG_NONE, &(args->quiet),
 310           "Be less descriptive in output.",
 311           NULL },
 312 
 313         { NULL }
 314     };
 315 
 316     context = pcmk__build_arg_context(args, "text (default), html, xml", group, NULL);
 317 
 318     /* Add the -q option, which cannot be part of the globally supported options
 319      * because some tools use that flag for something else.
 320      */
 321     pcmk__add_main_args(context, extra_prog_entries);
 322 
 323     pcmk__add_arg_group(context, "definition", "Device Definition Commands:",
 324                         "Show device definition help", defn_entries);
 325     pcmk__add_arg_group(context, "queries", "Queries:",
 326                         "Show query help", query_entries);
 327     pcmk__add_arg_group(context, "fence", "Fencing Commands:",
 328                         "Show fence help", fence_entries);
 329     pcmk__add_arg_group(context, "additional", "Additional Options:",
 330                         "Show additional options", addl_entries);
 331     return context;
 332 }
 333 
 334 // \return Standard Pacemaker return code
 335 static int
 336 request_fencing(stonith_t *st, const char *target, const char *command,
     /* [previous][next][first][last][top][bottom][index][help] */
 337                 GError **error)
 338 {
 339     char *reason = NULL;
 340     int rc = pcmk__request_fencing(st, target, command, name,
 341                                    options.timeout * 1000,
 342                                    options.tolerance * 1000,
 343                                    options.delay, &reason);
 344 
 345     if (rc != pcmk_rc_ok) {
 346         const char *rc_str = pcmk_rc_str(rc);
 347         const char *what = "fence";
 348 
 349         if (strcmp(command, PCMK_ACTION_ON) == 0) {
 350             what = "unfence";
 351         }
 352 
 353         // If reason is identical to return code string, don't display it twice
 354         if (pcmk__str_eq(rc_str, reason, pcmk__str_none)) {
 355             free(reason);
 356             reason = NULL;
 357         }
 358 
 359         g_set_error(error, PCMK__RC_ERROR, rc,
 360                     "Couldn't %s %s: %s%s%s%s",
 361                     what, target, rc_str,
 362                     ((reason == NULL)? "" : " ("),
 363                     ((reason == NULL)? "" : reason),
 364                     ((reason == NULL)? "" : ")"));
 365     }
 366     free(reason);
 367     return rc;
 368 }
 369 
 370 int
 371 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 372 {
 373     int rc = 0;
 374     crm_exit_t exit_code = CRM_EX_OK;
 375     bool no_connect = false;
 376     bool required_agent = false;
 377 
 378     char *target = NULL;
 379     const char *device = NULL;
 380     stonith_t *st = NULL;
 381 
 382     GError *error = NULL;
 383 
 384     pcmk__output_t *out = NULL;
 385 
 386     GOptionGroup *output_group = NULL;
 387     pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
 388     gchar **processed_args = pcmk__cmdline_preproc(argv, "adehilorstvyBCDFHQRTU");
 389     GOptionContext *context = build_arg_context(args, &output_group);
 390 
 391     pcmk__register_formats(output_group, formats);
 392     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
 393         exit_code = CRM_EX_USAGE;
 394         goto done;
 395     }
 396 
 397     pcmk__cli_init_logging("stonith_admin", args->verbosity);
 398 
 399     if (name == NULL) {
 400         name = strdup(crm_system_name);
 401     }
 402 
 403     rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
 404     if (rc != pcmk_rc_ok) {
 405         exit_code = CRM_EX_ERROR;
 406         g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s",
 407                     args->output_ty, pcmk_rc_str(rc));
 408         goto done;
 409     }
 410 
 411     stonith__register_messages(out);
 412 
 413     if (args->version) {
 414         out->version(out, false);
 415         goto done;
 416     }
 417 
 418     if (options.validate_cfg) {
 419         required_agent = true;
 420         no_connect = true;
 421         action = 'K';
 422     }
 423 
 424     if (options.installed) {
 425         no_connect = true;
 426         action = 'I';
 427     }
 428 
 429     if (options.registered) {
 430         action = 'L';
 431     }
 432 
 433     if (options.register_dev != NULL) {
 434         required_agent = true;
 435         action = 'R';
 436         device = options.register_dev;
 437     }
 438 
 439     if (options.query != NULL) {
 440         action = 'Q';
 441         device = options.query;
 442     }
 443 
 444     if (options.unregister_dev != NULL) {
 445         action = 'D';
 446         device = options.unregister_dev;
 447     }
 448 
 449     if (options.targets != NULL) {
 450         action = 's';
 451         device = options.targets;
 452     }
 453 
 454     if (options.terminate != NULL) {
 455         action = 'L';
 456         target = options.terminate;
 457     }
 458 
 459     if (options.metadata) {
 460         no_connect = true;
 461         required_agent = true;
 462         action = 'M';
 463     }
 464 
 465     if (options.reboot_host != NULL) {
 466         no_connect = true;
 467         action = 'B';
 468         target = options.reboot_host;
 469         crm_log_args(argc, argv);
 470     }
 471 
 472     if (options.fence_host != NULL) {
 473         no_connect = true;
 474         action = 'F';
 475         target = options.fence_host;
 476         crm_log_args(argc, argv);
 477     }
 478 
 479     if (options.unfence_host != NULL) {
 480         no_connect = true;
 481         action = 'U';
 482         target = options.unfence_host;
 483         crm_log_args(argc, argv);
 484     }
 485 
 486     if (options.confirm_host != NULL) {
 487         action = 'C';
 488         target = options.confirm_host;
 489         crm_log_args(argc, argv);
 490     }
 491 
 492     if (options.last_fenced != NULL) {
 493         action = 'h';
 494         target = options.last_fenced;
 495     }
 496 
 497     if (options.history != NULL) {
 498         action = 'H';
 499         target = options.history;
 500     }
 501 
 502     if (options.register_level != NULL) {
 503         action = 'r';
 504         target = options.register_level;
 505     }
 506 
 507     if (options.unregister_level != NULL) {
 508         action = 'd';
 509         target = options.unregister_level;
 510     }
 511 
 512     if (action == 0) {
 513         char *help = g_option_context_get_help(context, TRUE, NULL);
 514 
 515         out->err(out, "%s", help);
 516         g_free(help);
 517         exit_code = CRM_EX_USAGE;
 518         goto done;
 519     }
 520 
 521     if (required_agent && options.agent == NULL) {
 522         char *help = g_option_context_get_help(context, TRUE, NULL);
 523 
 524         out->err(out, "Please specify an agent to query using -a,--agent [value]");
 525         out->err(out, "%s", help);
 526         g_free(help);
 527         exit_code = CRM_EX_USAGE;
 528         goto done;
 529     }
 530 
 531     out->quiet = args->quiet;
 532 
 533     st = stonith_api_new();
 534     if (st == NULL) {
 535         rc = -ENOMEM;
 536     } else if (!no_connect) {
 537         rc = st->cmds->connect(st, name, NULL);
 538     }
 539     if (rc < 0) {
 540         out->err(out, "Could not connect to fencer: %s", pcmk_strerror(rc));
 541         exit_code = CRM_EX_DISCONNECT;
 542         goto done;
 543     }
 544 
 545     switch (action) {
 546         case 'I':
 547             rc = pcmk__fence_installed(out, st, options.timeout*1000);
 548             if (rc != pcmk_rc_ok) {
 549                 out->err(out, "Failed to list installed devices: %s", pcmk_rc_str(rc));
 550             }
 551 
 552             break;
 553 
 554         case 'L':
 555             rc = pcmk__fence_registered(out, st, target, options.timeout*1000);
 556             if (rc != pcmk_rc_ok) {
 557                 out->err(out, "Failed to list registered devices: %s", pcmk_rc_str(rc));
 558             }
 559 
 560             break;
 561 
 562         case 'Q':
 563             rc = st->cmds->monitor(st, st_opts, device, options.timeout);
 564             if (rc != pcmk_rc_ok) {
 565                 rc = st->cmds->list(st, st_opts, device, NULL, options.timeout);
 566             }
 567             rc = pcmk_legacy2rc(rc);
 568             break;
 569 
 570         case 's':
 571             rc = pcmk__fence_list_targets(out, st, device, options.timeout*1000);
 572             if (rc != pcmk_rc_ok) {
 573                 out->err(out, "Couldn't list targets: %s", pcmk_rc_str(rc));
 574             }
 575 
 576             break;
 577 
 578         case 'R':
 579             rc = st->cmds->register_device(st, st_opts, device, NULL, options.agent,
 580                                            options.params);
 581             rc = pcmk_legacy2rc(rc);
 582             if (rc != pcmk_rc_ok) {
 583                 out->err(out, "Can't register device %s using agent %s: %s",
 584                          device, options.agent, pcmk_rc_str(rc));
 585             }
 586             break;
 587 
 588         case 'D':
 589             rc = st->cmds->remove_device(st, st_opts, device);
 590             rc = pcmk_legacy2rc(rc);
 591             if (rc != pcmk_rc_ok) {
 592                 out->err(out, "Can't unregister device %s: %s",
 593                          device, pcmk_rc_str(rc));
 594             }
 595             break;
 596 
 597         case 'd':
 598             rc = pcmk__fence_unregister_level(st, target, options.fence_level);
 599             if (rc != pcmk_rc_ok) {
 600                 out->err(out, "Can't unregister topology level %d for %s: %s",
 601                          options.fence_level, target, pcmk_rc_str(rc));
 602             }
 603             break;
 604 
 605         case 'r':
 606             rc = pcmk__fence_register_level(st, target, options.fence_level, options.devices);
 607             if (rc != pcmk_rc_ok) {
 608                 out->err(out, "Can't register topology level %d for %s: %s",
 609                          options.fence_level, target, pcmk_rc_str(rc));
 610             }
 611             break;
 612 
 613         case 'M':
 614             rc = pcmk__fence_metadata(out, st, options.agent, options.timeout*1000);
 615             if (rc != pcmk_rc_ok) {
 616                 out->err(out, "Can't get fence agent meta-data: %s",
 617                          pcmk_rc_str(rc));
 618             }
 619 
 620             break;
 621 
 622         case 'C':
 623             rc = st->cmds->confirm(st, st_opts, target);
 624             rc = pcmk_legacy2rc(rc);
 625             break;
 626 
 627         case 'B':
 628             rc = request_fencing(st, target, PCMK_ACTION_REBOOT, &error);
 629             break;
 630 
 631         case 'F':
 632             rc = request_fencing(st, target, PCMK_ACTION_OFF, &error);
 633             break;
 634 
 635         case 'U':
 636             rc = request_fencing(st, target, PCMK_ACTION_ON, &error);
 637             break;
 638 
 639         case 'h':
 640             rc = pcmk__fence_last(out, target, options.as_nodeid);
 641             break;
 642 
 643         case 'H':
 644             rc = pcmk__fence_history(out, st, target, options.timeout*1000, args->verbosity,
 645                                      options.broadcast, options.cleanup);
 646             break;
 647 
 648         case 'K':
 649             device = options.devices ? options.devices->key : NULL;
 650             rc = pcmk__fence_validate(out, st, options.agent, device, options.params,
 651                                         options.timeout*1000);
 652             break;
 653     }
 654 
 655     crm_info("Command returned: %s (%d)", pcmk_rc_str(rc), rc);
 656     exit_code = pcmk_rc2exitc(rc);
 657 
 658   done:
 659     g_strfreev(processed_args);
 660     pcmk__free_arg_context(context);
 661 
 662     pcmk__output_and_clear_error(&error, out);
 663 
 664     if (out != NULL) {
 665         out->finish(out, exit_code, true, NULL);
 666         pcmk__output_free(out);
 667     }
 668     pcmk__unregister_formats();
 669     free(name);
 670     stonith_key_value_freeall(options.params, 1, 1);
 671 
 672     if (st != NULL) {
 673         st->cmds->disconnect(st);
 674         stonith_api_delete(st);
 675     }
 676 
 677     return exit_code;
 678 }

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