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

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

DEFINITIONS

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

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

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