root/daemons/fenced/cts-fence-helper.c

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

DEFINITIONS

This source file includes following definitions.
  1. mode_cb
  2. mainloop_test_done
  3. dispatch_helper
  4. st_callback
  5. st_global_callback
  6. passive_test
  7. run_fence_failure_test
  8. run_fence_failure_rollover_test
  9. run_standard_test
  10. sanity_tests
  11. standard_dev_test
  12. mainloop_callback
  13. register_callback_helper
  14. test_async_fence_pass
  15. test_async_fence_custom_timeout
  16. test_async_fence_timeout
  17. test_async_monitor
  18. test_register_async_devices
  19. try_mainloop_connect
  20. iterate_mainloop_tests
  21. trigger_iterate_mainloop_tests
  22. test_shutdown
  23. mainloop_tests
  24. build_arg_context
  25. main

   1 /*
   2  * Copyright 2009-2023 the Pacemaker project contributors
   3  *
   4  * This source code is licensed under the GNU General Public License version 2
   5  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   6  */
   7 
   8 #include <crm_internal.h>
   9 
  10 #include <sys/param.h>
  11 #include <stdio.h>
  12 #include <sys/time.h>
  13 #include <sys/types.h>
  14 #include <sys/stat.h>
  15 #include <unistd.h>
  16 #include <sys/utsname.h>
  17 
  18 #include <stdlib.h>
  19 #include <errno.h>
  20 #include <fcntl.h>
  21 
  22 #include <crm/crm.h>
  23 #include <crm/msg_xml.h>
  24 #include <crm/common/ipc.h>
  25 #include <crm/cluster/internal.h>
  26 
  27 #include <crm/stonith-ng.h>
  28 #include <crm/fencing/internal.h>
  29 #include <crm/common/agents.h>
  30 #include <crm/common/cmdline_internal.h>
  31 #include <crm/common/xml.h>
  32 
  33 #include <crm/common/mainloop.h>
  34 
  35 #define SUMMARY "cts-fence-helper - inject commands into the Pacemaker fencer and watch for events"
  36 
  37 static GMainLoop *mainloop = NULL;
  38 static crm_trigger_t *trig = NULL;
  39 static int mainloop_iter = 0;
  40 static pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
  41 
  42 typedef void (*mainloop_test_iteration_cb) (int check_event);
  43 
  44 #define MAINLOOP_DEFAULT_TIMEOUT 2
  45 
  46 enum test_modes {
  47     test_standard = 0,  // test using a specific developer environment
  48     test_passive,       // watch notifications only
  49     test_api_sanity,    // sanity-test stonith client API using fence_dummy
  50     test_api_mainloop,  // sanity-test mainloop code with async responses
  51 };
  52 
  53 struct {
  54     enum test_modes mode;
  55 } options = {
  56     .mode = test_standard
  57 };
  58 
  59 static gboolean
  60 mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     /* [previous][next][first][last][top][bottom][index][help] */
  61     if (pcmk__str_any_of(option_name, "--mainloop_api_test", "-m", NULL)) {
  62         options.mode = test_api_mainloop;
  63     } else if (pcmk__str_any_of(option_name, "--api_test", "-t", NULL)) {
  64         options.mode = test_api_sanity;
  65     } else if (pcmk__str_any_of(option_name, "--passive", "-p", NULL)) {
  66         options.mode = test_passive;
  67     }
  68 
  69     return TRUE;
  70 }
  71 
  72 static GOptionEntry entries[] = {
  73     { "mainloop_api_test", 'm', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, mode_cb,
  74       NULL, NULL,
  75     },
  76 
  77     { "api_test", 't', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, mode_cb,
  78       NULL, NULL,
  79     },
  80 
  81     { "passive", 'p', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, mode_cb,
  82       NULL, NULL,
  83     },
  84 
  85     { NULL }
  86 };
  87 
  88 static stonith_t *st = NULL;
  89 static struct pollfd pollfd;
  90 static const int st_opts = st_opt_sync_call;
  91 static int expected_notifications = 0;
  92 static int verbose = 0;
  93 
  94 static void
  95 mainloop_test_done(const char *origin, bool pass)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97     if (pass) {
  98         crm_info("SUCCESS - %s", origin);
  99         mainloop_iter++;
 100         mainloop_set_trigger(trig);
 101         result.execution_status = PCMK_EXEC_DONE;
 102         result.exit_status = CRM_EX_OK;
 103     } else {
 104         crm_err("FAILURE - %s (%d: %s)", origin, result.exit_status,
 105                 pcmk_exec_status_str(result.execution_status));
 106         crm_exit(CRM_EX_ERROR);
 107     }
 108 }
 109 
 110 
 111 static void
 112 dispatch_helper(int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114     int rc;
 115 
 116     crm_debug("Looking for notification");
 117     pollfd.events = POLLIN;
 118     while (true) {
 119         rc = poll(&pollfd, 1, timeout); /* wait 10 minutes, -1 forever */
 120         if (rc > 0) {
 121             if (!stonith_dispatch(st)) {
 122                 break;
 123             }
 124         } else {
 125             break;
 126         }
 127     }
 128 }
 129 
 130 static void
 131 st_callback(stonith_t * st, stonith_event_t * e)
     /* [previous][next][first][last][top][bottom][index][help] */
 132 {
 133     char *desc = NULL;
 134 
 135     if (st->state == stonith_disconnected) {
 136         crm_exit(CRM_EX_DISCONNECT);
 137     }
 138 
 139     desc = stonith__event_description(e);
 140     crm_notice("%s", desc);
 141     free(desc);
 142 
 143     if (expected_notifications) {
 144         expected_notifications--;
 145     }
 146 }
 147 
 148 static void
 149 st_global_callback(stonith_t * stonith, stonith_callback_data_t * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151     crm_notice("Call %d exited %d: %s (%s)",
 152                data->call_id, stonith__exit_status(data),
 153                stonith__execution_status(data),
 154                pcmk__s(stonith__exit_reason(data), "unspecified reason"));
 155 }
 156 
 157 static void
 158 passive_test(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160     int rc = 0;
 161 
 162     rc = st->cmds->connect(st, crm_system_name, &pollfd.fd);
 163     if (rc != pcmk_ok) {
 164         stonith_api_delete(st);
 165         crm_exit(CRM_EX_DISCONNECT);
 166     }
 167     st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback);
 168     st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback);
 169     st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback);
 170     st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback);
 171     st->cmds->register_callback(st, 0, 120, st_opt_timeout_updates, NULL, "st_global_callback",
 172                                 st_global_callback);
 173 
 174     dispatch_helper(600 * 1000);
 175 }
 176 
 177 #define single_test(cmd, str, num_notifications, expected_rc) \
 178 { \
 179     int rc = 0; \
 180     rc = cmd; \
 181     expected_notifications = 0;  \
 182     if (num_notifications) { \
 183         expected_notifications = num_notifications; \
 184         dispatch_helper(500);  \
 185     } \
 186     if (rc != expected_rc) { \
 187         crm_err("FAILURE - expected rc %d != %d(%s) for cmd - %s", expected_rc, rc, pcmk_strerror(rc), str); \
 188         crm_exit(CRM_EX_ERROR); \
 189     } else if (expected_notifications) { \
 190         crm_err("FAILURE - expected %d notifications, got only %d for cmd - %s", \
 191             num_notifications, num_notifications - expected_notifications, str); \
 192         crm_exit(CRM_EX_ERROR); \
 193     } else { \
 194         if (verbose) {                   \
 195             crm_info("SUCCESS - %s: %d", str, rc);    \
 196         } else {   \
 197             crm_debug("SUCCESS - %s: %d", str, rc);    \
 198         }                          \
 199     } \
 200 }\
 201 
 202 static void
 203 run_fence_failure_test(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205     stonith_key_value_t *params = NULL;
 206 
 207     params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP,
 208                                    "false_1_node1=1,2 false_1_node2=3,4");
 209     params = stonith_key_value_add(params, "mode", "fail");
 210 
 211     single_test(st->
 212                 cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_dummy", params),
 213                 "Register device1 for failure test", 1, 0);
 214 
 215     single_test(st->cmds->fence(st, st_opts, "false_1_node2", PCMK_ACTION_OFF,
 216                                 3, 0),
 217                 "Fence failure results off", 1, -ENODATA);
 218 
 219     single_test(st->cmds->fence(st, st_opts, "false_1_node2",
 220                                 PCMK_ACTION_REBOOT, 3, 0),
 221                 "Fence failure results reboot", 1, -ENODATA);
 222 
 223     single_test(st->cmds->remove_device(st, st_opts, "test-id1"),
 224                 "Remove device1 for failure test", 1, 0);
 225 
 226     stonith_key_value_freeall(params, 1, 1);
 227 }
 228 
 229 static void
 230 run_fence_failure_rollover_test(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232     stonith_key_value_t *params = NULL;
 233 
 234     params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP,
 235                                    "false_1_node1=1,2 false_1_node2=3,4");
 236     params = stonith_key_value_add(params, "mode", "fail");
 237 
 238     single_test(st->
 239                 cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_dummy", params),
 240                 "Register device1 for rollover test", 1, 0);
 241     stonith_key_value_freeall(params, 1, 1);
 242     params = NULL;
 243     params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP,
 244                                    "false_1_node1=1,2 false_1_node2=3,4");
 245     params = stonith_key_value_add(params, "mode", "pass");
 246 
 247     single_test(st->
 248                 cmds->register_device(st, st_opts, "test-id2", "stonith-ng", "fence_dummy", params),
 249                 "Register device2 for rollover test", 1, 0);
 250 
 251     single_test(st->cmds->fence(st, st_opts, "false_1_node2", PCMK_ACTION_OFF,
 252                                 3, 0),
 253                 "Fence rollover results off", 1, 0);
 254 
 255     /* Expect -ENODEV because fence_dummy requires 'on' to be executed on target */
 256     single_test(st->cmds->fence(st, st_opts, "false_1_node2", PCMK_ACTION_ON, 3,
 257                                 0),
 258                 "Fence rollover results on", 1, -ENODEV);
 259 
 260     single_test(st->cmds->remove_device(st, st_opts, "test-id1"),
 261                 "Remove device1 for rollover tests", 1, 0);
 262 
 263     single_test(st->cmds->remove_device(st, st_opts, "test-id2"),
 264                 "Remove device2 for rollover tests", 1, 0);
 265 
 266     stonith_key_value_freeall(params, 1, 1);
 267 }
 268 
 269 static void
 270 run_standard_test(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272     stonith_key_value_t *params = NULL;
 273 
 274     params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP,
 275                                    "false_1_node1=1,2 false_1_node2=3,4");
 276     params = stonith_key_value_add(params, "mode", "pass");
 277     params = stonith_key_value_add(params, "mock_dynamic_hosts", "false_1_node1 false_1_node2");
 278 
 279     single_test(st->
 280                 cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_dummy", params),
 281                 "Register", 1, 0);
 282     stonith_key_value_freeall(params, 1, 1);
 283     params = NULL;
 284 
 285     single_test(st->cmds->list(st, st_opts, "test-id", NULL, 1),
 286                 PCMK_ACTION_LIST, 1, 0);
 287 
 288     single_test(st->cmds->monitor(st, st_opts, "test-id", 1), "Monitor", 1, 0);
 289 
 290     single_test(st->cmds->status(st, st_opts, "test-id", "false_1_node2", 1),
 291                 "Status false_1_node2", 1, 0);
 292 
 293     single_test(st->cmds->status(st, st_opts, "test-id", "false_1_node1", 1),
 294                 "Status false_1_node1", 1, 0);
 295 
 296     single_test(st->cmds->fence(st, st_opts, "unknown-host", PCMK_ACTION_OFF,
 297                                 1, 0),
 298                 "Fence unknown-host (expected failure)", 0, -ENODEV);
 299 
 300     single_test(st->cmds->fence(st, st_opts, "false_1_node1", PCMK_ACTION_OFF,
 301                                 1, 0),
 302                 "Fence false_1_node1", 1, 0);
 303 
 304     /* Expect -ENODEV because fence_dummy requires 'on' to be executed on target */
 305     single_test(st->cmds->fence(st, st_opts, "false_1_node1", PCMK_ACTION_ON, 1,
 306                                 0),
 307                 "Unfence false_1_node1", 1, -ENODEV);
 308 
 309     /* Confirm that an invalid level index is rejected */
 310     single_test(st->cmds->register_level(st, st_opts, "node1", 999, params),
 311                 "Attempt to register an invalid level index", 0, -EINVAL);
 312 
 313     single_test(st->cmds->remove_device(st, st_opts, "test-id"), "Remove test-id", 1, 0);
 314 
 315     stonith_key_value_freeall(params, 1, 1);
 316 }
 317 
 318 static void
 319 sanity_tests(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 320 {
 321     int rc = 0;
 322 
 323     rc = st->cmds->connect(st, crm_system_name, &pollfd.fd);
 324     if (rc != pcmk_ok) {
 325         stonith_api_delete(st);
 326         crm_exit(CRM_EX_DISCONNECT);
 327     }
 328     st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback);
 329     st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback);
 330     st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback);
 331     st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback);
 332     st->cmds->register_callback(st, 0, 120, st_opt_timeout_updates, NULL, "st_global_callback",
 333                                 st_global_callback);
 334 
 335     crm_info("Starting API Sanity Tests");
 336     run_standard_test();
 337     run_fence_failure_test();
 338     run_fence_failure_rollover_test();
 339     crm_info("Sanity Tests Passed");
 340 }
 341 
 342 static void
 343 standard_dev_test(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 344 {
 345     int rc = 0;
 346     char *tmp = NULL;
 347     stonith_key_value_t *params = NULL;
 348 
 349     rc = st->cmds->connect(st, crm_system_name, &pollfd.fd);
 350     if (rc != pcmk_ok) {
 351         stonith_api_delete(st);
 352         crm_exit(CRM_EX_DISCONNECT);
 353     }
 354 
 355     params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP,
 356                                    "some-host=pcmk-7 true_1_node1=3,4");
 357 
 358     rc = st->cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_xvm", params);
 359     crm_debug("Register: %d", rc);
 360 
 361     rc = st->cmds->list(st, st_opts, "test-id", &tmp, 10);
 362     crm_debug("List: %d output: %s", rc, tmp ? tmp : "<none>");
 363 
 364     rc = st->cmds->monitor(st, st_opts, "test-id", 10);
 365     crm_debug("Monitor: %d", rc);
 366 
 367     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node2", 10);
 368     crm_debug("Status false_1_node2: %d", rc);
 369 
 370     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node1", 10);
 371     crm_debug("Status false_1_node1: %d", rc);
 372 
 373     rc = st->cmds->fence(st, st_opts, "unknown-host", PCMK_ACTION_OFF, 60, 0);
 374     crm_debug("Fence unknown-host: %d", rc);
 375 
 376     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node1", 10);
 377     crm_debug("Status false_1_node1: %d", rc);
 378 
 379     rc = st->cmds->fence(st, st_opts, "false_1_node1", PCMK_ACTION_OFF, 60, 0);
 380     crm_debug("Fence false_1_node1: %d", rc);
 381 
 382     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node1", 10);
 383     crm_debug("Status false_1_node1: %d", rc);
 384 
 385     rc = st->cmds->fence(st, st_opts, "false_1_node1", PCMK_ACTION_ON, 10, 0);
 386     crm_debug("Unfence false_1_node1: %d", rc);
 387 
 388     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node1", 10);
 389     crm_debug("Status false_1_node1: %d", rc);
 390 
 391     rc = st->cmds->fence(st, st_opts, "some-host", PCMK_ACTION_OFF, 10, 0);
 392     crm_debug("Fence alias: %d", rc);
 393 
 394     rc = st->cmds->status(st, st_opts, "test-id", "some-host", 10);
 395     crm_debug("Status alias: %d", rc);
 396 
 397     rc = st->cmds->fence(st, st_opts, "false_1_node1", PCMK_ACTION_ON, 10, 0);
 398     crm_debug("Unfence false_1_node1: %d", rc);
 399 
 400     rc = st->cmds->remove_device(st, st_opts, "test-id");
 401     crm_debug("Remove test-id: %d", rc);
 402 
 403     stonith_key_value_freeall(params, 1, 1);
 404 }
 405 
 406 static void
 407  iterate_mainloop_tests(gboolean event_ready);
 408 
 409 static void
 410 mainloop_callback(stonith_t * stonith, stonith_callback_data_t * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 411 {
 412     pcmk__set_result(&result, stonith__exit_status(data),
 413                      stonith__execution_status(data),
 414                      stonith__exit_reason(data));
 415     iterate_mainloop_tests(TRUE);
 416 }
 417 
 418 static int
 419 register_callback_helper(int callid)
     /* [previous][next][first][last][top][bottom][index][help] */
 420 {
 421     return st->cmds->register_callback(st,
 422                                        callid,
 423                                        MAINLOOP_DEFAULT_TIMEOUT,
 424                                        st_opt_timeout_updates, NULL, "callback", mainloop_callback);
 425 }
 426 
 427 static void
 428 test_async_fence_pass(int check_event)
     /* [previous][next][first][last][top][bottom][index][help] */
 429 {
 430     int rc = 0;
 431 
 432     if (check_event) {
 433         mainloop_test_done(__func__, (result.exit_status == CRM_EX_OK));
 434         return;
 435     }
 436 
 437     rc = st->cmds->fence(st, 0, "true_1_node1", PCMK_ACTION_OFF,
 438                          MAINLOOP_DEFAULT_TIMEOUT, 0);
 439     if (rc < 0) {
 440         crm_err("fence failed with rc %d", rc);
 441         mainloop_test_done(__func__, false);
 442     }
 443     register_callback_helper(rc);
 444     /* wait for event */
 445 }
 446 
 447 #define CUSTOM_TIMEOUT_ADDITION 10
 448 static void
 449 test_async_fence_custom_timeout(int check_event)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451     int rc = 0;
 452     static time_t begin = 0;
 453 
 454     if (check_event) {
 455         uint32_t diff = (time(NULL) - begin);
 456 
 457         if (result.execution_status != PCMK_EXEC_TIMEOUT) {
 458             mainloop_test_done(__func__, false);
 459         } else if (diff < CUSTOM_TIMEOUT_ADDITION + MAINLOOP_DEFAULT_TIMEOUT) {
 460             crm_err
 461                 ("Custom timeout test failed, callback expiration should be updated to %d, actual timeout was %d",
 462                  CUSTOM_TIMEOUT_ADDITION + MAINLOOP_DEFAULT_TIMEOUT, diff);
 463             mainloop_test_done(__func__, false);
 464         } else {
 465             mainloop_test_done(__func__, true);
 466         }
 467         return;
 468     }
 469     begin = time(NULL);
 470 
 471     rc = st->cmds->fence(st, 0, "custom_timeout_node1", PCMK_ACTION_OFF,
 472                          MAINLOOP_DEFAULT_TIMEOUT, 0);
 473     if (rc < 0) {
 474         crm_err("fence failed with rc %d", rc);
 475         mainloop_test_done(__func__, false);
 476     }
 477     register_callback_helper(rc);
 478     /* wait for event */
 479 }
 480 
 481 static void
 482 test_async_fence_timeout(int check_event)
     /* [previous][next][first][last][top][bottom][index][help] */
 483 {
 484     int rc = 0;
 485 
 486     if (check_event) {
 487         mainloop_test_done(__func__,
 488                            (result.execution_status == PCMK_EXEC_NO_FENCE_DEVICE));
 489         return;
 490     }
 491 
 492     rc = st->cmds->fence(st, 0, "false_1_node2", PCMK_ACTION_OFF,
 493                          MAINLOOP_DEFAULT_TIMEOUT, 0);
 494     if (rc < 0) {
 495         crm_err("fence failed with rc %d", rc);
 496         mainloop_test_done(__func__, false);
 497     }
 498     register_callback_helper(rc);
 499     /* wait for event */
 500 }
 501 
 502 static void
 503 test_async_monitor(int check_event)
     /* [previous][next][first][last][top][bottom][index][help] */
 504 {
 505     int rc = 0;
 506 
 507     if (check_event) {
 508         mainloop_test_done(__func__, (result.exit_status == CRM_EX_OK));
 509         return;
 510     }
 511 
 512     rc = st->cmds->monitor(st, 0, "false_1", MAINLOOP_DEFAULT_TIMEOUT);
 513     if (rc < 0) {
 514         crm_err("monitor failed with rc %d", rc);
 515         mainloop_test_done(__func__, false);
 516     }
 517 
 518     register_callback_helper(rc);
 519     /* wait for event */
 520 }
 521 
 522 static void
 523 test_register_async_devices(int check_event)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525     char buf[16] = { 0, };
 526     stonith_key_value_t *params = NULL;
 527 
 528     params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP,
 529                                    "false_1_node1=1,2");
 530     params = stonith_key_value_add(params, "mode", "fail");
 531     st->cmds->register_device(st, st_opts, "false_1", "stonith-ng", "fence_dummy", params);
 532     stonith_key_value_freeall(params, 1, 1);
 533 
 534     params = NULL;
 535     params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP,
 536                                    "true_1_node1=1,2");
 537     params = stonith_key_value_add(params, "mode", "pass");
 538     st->cmds->register_device(st, st_opts, "true_1", "stonith-ng", "fence_dummy", params);
 539     stonith_key_value_freeall(params, 1, 1);
 540 
 541     params = NULL;
 542     params = stonith_key_value_add(params, PCMK_STONITH_HOST_MAP,
 543                                    "custom_timeout_node1=1,2");
 544     params = stonith_key_value_add(params, "mode", "fail");
 545     params = stonith_key_value_add(params, "delay", "1000");
 546     snprintf(buf, sizeof(buf) - 1, "%d", MAINLOOP_DEFAULT_TIMEOUT + CUSTOM_TIMEOUT_ADDITION);
 547     params = stonith_key_value_add(params, "pcmk_off_timeout", buf);
 548     st->cmds->register_device(st, st_opts, "false_custom_timeout", "stonith-ng", "fence_dummy",
 549                               params);
 550     stonith_key_value_freeall(params, 1, 1);
 551 
 552     mainloop_test_done(__func__, true);
 553 }
 554 
 555 static void
 556 try_mainloop_connect(int check_event)
     /* [previous][next][first][last][top][bottom][index][help] */
 557 {
 558     int rc = stonith_api_connect_retry(st, crm_system_name, 10);
 559 
 560     if (rc == pcmk_ok) {
 561         mainloop_test_done(__func__, true);
 562         return;
 563     }
 564     crm_err("API CONNECTION FAILURE");
 565     mainloop_test_done(__func__, false);
 566 }
 567 
 568 static void
 569 iterate_mainloop_tests(gboolean event_ready)
     /* [previous][next][first][last][top][bottom][index][help] */
 570 {
 571     static mainloop_test_iteration_cb callbacks[] = {
 572         try_mainloop_connect,
 573         test_register_async_devices,
 574         test_async_monitor,
 575         test_async_fence_pass,
 576         test_async_fence_timeout,
 577         test_async_fence_custom_timeout,
 578     };
 579 
 580     if (mainloop_iter == (sizeof(callbacks) / sizeof(mainloop_test_iteration_cb))) {
 581         /* all tests ran, everything passed */
 582         crm_info("ALL MAINLOOP TESTS PASSED!");
 583         crm_exit(CRM_EX_OK);
 584     }
 585 
 586     callbacks[mainloop_iter] (event_ready);
 587 }
 588 
 589 static gboolean
 590 trigger_iterate_mainloop_tests(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 591 {
 592     iterate_mainloop_tests(FALSE);
 593     return TRUE;
 594 }
 595 
 596 static void
 597 test_shutdown(int nsig)
     /* [previous][next][first][last][top][bottom][index][help] */
 598 {
 599     int rc = 0;
 600 
 601     if (st) {
 602         rc = st->cmds->disconnect(st);
 603         crm_info("Disconnect: %d", rc);
 604 
 605         crm_debug("Destroy");
 606         stonith_api_delete(st);
 607     }
 608 
 609     if (rc) {
 610         crm_exit(CRM_EX_ERROR);
 611     }
 612 }
 613 
 614 static void
 615 mainloop_tests(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 616 {
 617     trig = mainloop_add_trigger(G_PRIORITY_HIGH, trigger_iterate_mainloop_tests, NULL);
 618     mainloop_set_trigger(trig);
 619     mainloop_add_signal(SIGTERM, test_shutdown);
 620 
 621     crm_info("Starting");
 622     mainloop = g_main_loop_new(NULL, FALSE);
 623     g_main_loop_run(mainloop);
 624 }
 625 
 626 static GOptionContext *
 627 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
     /* [previous][next][first][last][top][bottom][index][help] */
 628     GOptionContext *context = NULL;
 629 
 630     context = pcmk__build_arg_context(args, NULL, group, NULL);
 631     pcmk__add_main_args(context, entries);
 632     return context;
 633 }
 634 
 635 int
 636 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 637 {
 638     GError *error = NULL;
 639     crm_exit_t exit_code = CRM_EX_OK;
 640 
 641     pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
 642     gchar **processed_args = pcmk__cmdline_preproc(argv, NULL);
 643     GOptionContext *context = build_arg_context(args, NULL);
 644 
 645     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
 646         exit_code = CRM_EX_USAGE;
 647         goto done;
 648     }
 649 
 650     /* We have to use crm_log_init here to set up the logging because there's
 651      * different handling for daemons vs. command line programs, and
 652      * pcmk__cli_init_logging is set up to only handle the latter.
 653      */
 654     crm_log_init(NULL, LOG_INFO, TRUE, (verbose? TRUE : FALSE), argc, argv,
 655                  FALSE);
 656 
 657     for (int i = 0; i < args->verbosity; i++) {
 658         crm_bump_log_level(argc, argv);
 659     }
 660 
 661     st = stonith_api_new();
 662     if (st == NULL) {
 663         exit_code = CRM_EX_DISCONNECT;
 664         g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
 665                     "Could not connect to fencer: API memory allocation failed");
 666         goto done;
 667     }
 668 
 669     switch (options.mode) {
 670         case test_standard:
 671             standard_dev_test();
 672             break;
 673         case test_passive:
 674             passive_test();
 675             break;
 676         case test_api_sanity:
 677             sanity_tests();
 678             break;
 679         case test_api_mainloop:
 680             mainloop_tests();
 681             break;
 682     }
 683 
 684     test_shutdown(0);
 685 
 686 done:
 687     g_strfreev(processed_args);
 688     pcmk__free_arg_context(context);
 689 
 690     pcmk__output_and_clear_error(&error, NULL);
 691     crm_exit(exit_code);
 692 }

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