This source file includes following definitions.
- new_data
 
- free_data
 
- post_connect
 
- set_node_info_data
 
- set_ping_data
 
- set_nodes_data
 
- reply_expected
 
- dispatch
 
- pcmk__controld_api_methods
 
- create_controller_request
 
- send_controller_request
 
- create_reprobe_message_data
 
- pcmk_controld_api_reprobe
 
- pcmk_controld_api_node_info
 
- pcmk_controld_api_ping
 
- pcmk_controld_api_list_nodes
 
- controller_resource_op
 
- pcmk_controld_api_fail
 
- pcmk_controld_api_refresh
 
- pcmk_controld_api_replies_expected
 
- create_hello_message
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <stdio.h>
  13 #include <stdbool.h>
  14 #include <errno.h>
  15 #include <libxml/tree.h>
  16 
  17 #include <crm/crm.h>
  18 #include <crm/msg_xml.h>
  19 #include <crm/common/xml.h>
  20 #include <crm/common/ipc.h>
  21 #include <crm/common/ipc_internal.h>
  22 #include <crm/common/ipc_controld.h>
  23 #include "crmcommon_private.h"
  24 
  25 struct controld_api_private_s {
  26     char *client_uuid;
  27     unsigned int replies_expected;
  28 };
  29 
  30 
  31 static int
  32 new_data(pcmk_ipc_api_t *api)
     
  33 {
  34     struct controld_api_private_s *private = NULL;
  35 
  36     api->api_data = calloc(1, sizeof(struct controld_api_private_s));
  37 
  38     if (api->api_data == NULL) {
  39         return errno;
  40     }
  41 
  42     private = api->api_data;
  43 
  44     
  45 
  46 
  47 
  48 
  49 
  50     private->client_uuid = pcmk__getpid_s();
  51 
  52     
  53 
  54 
  55 
  56     return pcmk_rc_ok;
  57 }
  58 
  59 static void
  60 free_data(void *data)
     
  61 {
  62     free(((struct controld_api_private_s *) data)->client_uuid);
  63     free(data);
  64 }
  65 
  66 
  67 static int
  68 post_connect(pcmk_ipc_api_t *api)
     
  69 {
  70     
  71 
  72 
  73     struct controld_api_private_s *private = api->api_data;
  74     const char *client_name = crm_system_name? crm_system_name : "client";
  75     xmlNode *hello;
  76     int rc;
  77 
  78     hello = create_hello_message(private->client_uuid, client_name,
  79                                  PCMK__CONTROLD_API_MAJOR,
  80                                  PCMK__CONTROLD_API_MINOR);
  81     rc = pcmk__send_ipc_request(api, hello);
  82     free_xml(hello);
  83     if (rc != pcmk_rc_ok) {
  84         crm_info("Could not send IPC hello to %s: %s " CRM_XS " rc=%s",
  85                  pcmk_ipc_name(api, true), pcmk_rc_str(rc), rc);
  86     } else {
  87         crm_debug("Sent IPC hello to %s", pcmk_ipc_name(api, true));
  88     }
  89     return rc;
  90 }
  91 
  92 static void
  93 set_node_info_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
     
  94 {
  95     data->reply_type = pcmk_controld_reply_info;
  96     if (msg_data == NULL) {
  97         return;
  98     }
  99     data->data.node_info.have_quorum = pcmk__xe_attr_is_true(msg_data, XML_ATTR_HAVE_QUORUM);
 100     data->data.node_info.is_remote = pcmk__xe_attr_is_true(msg_data, XML_NODE_IS_REMOTE);
 101     crm_element_value_int(msg_data, XML_ATTR_ID, &(data->data.node_info.id));
 102     data->data.node_info.uuid = crm_element_value(msg_data, XML_ATTR_UUID);
 103     data->data.node_info.uname = crm_element_value(msg_data, XML_ATTR_UNAME);
 104     data->data.node_info.state = crm_element_value(msg_data, XML_NODE_IS_PEER);
 105 }
 106 
 107 static void
 108 set_ping_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
     
 109 {
 110     data->reply_type = pcmk_controld_reply_ping;
 111     if (msg_data == NULL) {
 112         return;
 113     }
 114     data->data.ping.sys_from = crm_element_value(msg_data,
 115                                                  XML_PING_ATTR_SYSFROM);
 116     data->data.ping.fsa_state = crm_element_value(msg_data,
 117                                                   XML_PING_ATTR_CRMDSTATE);
 118     data->data.ping.result = crm_element_value(msg_data, XML_PING_ATTR_STATUS);
 119 }
 120 
 121 static void
 122 set_nodes_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
     
 123 {
 124     pcmk_controld_api_node_t *node_info;
 125 
 126     data->reply_type = pcmk_controld_reply_nodes;
 127     for (xmlNode *node = first_named_child(msg_data, XML_CIB_TAG_NODE);
 128          node != NULL; node = crm_next_same_xml(node)) {
 129 
 130         long long id_ll = 0;
 131 
 132         node_info = calloc(1, sizeof(pcmk_controld_api_node_t));
 133         crm_element_value_ll(node, XML_ATTR_ID, &id_ll);
 134         if (id_ll > 0) {
 135             node_info->id = id_ll;
 136         }
 137         node_info->uname = crm_element_value(node, XML_ATTR_UNAME);
 138         node_info->state = crm_element_value(node, XML_NODE_IN_CLUSTER);
 139         data->data.nodes = g_list_prepend(data->data.nodes, node_info);
 140     }
 141 }
 142 
 143 static bool
 144 reply_expected(pcmk_ipc_api_t *api, xmlNode *request)
     
 145 {
 146     const char *command = crm_element_value(request, F_CRM_TASK);
 147 
 148     if (command == NULL) {
 149         return false;
 150     }
 151 
 152     
 153     return !strcmp(command, CRM_OP_REPROBE)
 154            || !strcmp(command, CRM_OP_NODE_INFO)
 155            || !strcmp(command, CRM_OP_PING)
 156            || !strcmp(command, CRM_OP_LRM_FAIL)
 157            || !strcmp(command, CRM_OP_LRM_DELETE);
 158 }
 159 
 160 static bool
 161 dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
     
 162 {
 163     struct controld_api_private_s *private = api->api_data;
 164     crm_exit_t status = CRM_EX_OK;
 165     xmlNode *msg_data = NULL;
 166     const char *value = NULL;
 167     pcmk_controld_api_reply_t reply_data = {
 168         pcmk_controld_reply_unknown, NULL, NULL,
 169     };
 170 
 171     
 172 
 173 
 174 
 175 
 176 
 177 
 178 
 179 
 180 
 181 
 182 
 183 
 184 
 185     if (pcmk__str_eq(crm_element_name(reply), "ack", pcmk__str_none)) {
 186         return true; 
 187     }
 188 
 189     if (private->replies_expected > 0) {
 190         private->replies_expected--;
 191     }
 192 
 193     
 194 
 195     
 196 
 197 
 198 
 199 
 200     value = crm_element_value(reply, F_CRM_MSG_TYPE);
 201     if (pcmk__str_empty(value)
 202         || !pcmk__str_any_of(value, XML_ATTR_REQUEST, XML_ATTR_RESPONSE, NULL)) {
 203         crm_info("Unrecognizable message from controller: "
 204                  "invalid message type '%s'", pcmk__s(value, ""));
 205         status = CRM_EX_PROTOCOL;
 206         goto done;
 207     }
 208 
 209     if (pcmk__str_empty(crm_element_value(reply, XML_ATTR_REFERENCE))) {
 210         crm_info("Unrecognizable message from controller: no reference");
 211         status = CRM_EX_PROTOCOL;
 212         goto done;
 213     }
 214 
 215     value = crm_element_value(reply, F_CRM_TASK);
 216     if (pcmk__str_empty(value)) {
 217         crm_info("Unrecognizable message from controller: no command name");
 218         status = CRM_EX_PROTOCOL;
 219         goto done;
 220     }
 221 
 222     
 223 
 224     reply_data.feature_set = crm_element_value(reply, XML_ATTR_VERSION);
 225     reply_data.host_from = crm_element_value(reply, F_CRM_HOST_FROM);
 226     msg_data = get_message_xml(reply, F_CRM_DATA);
 227 
 228     if (!strcmp(value, CRM_OP_REPROBE)) {
 229         reply_data.reply_type = pcmk_controld_reply_reprobe;
 230 
 231     } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
 232         set_node_info_data(&reply_data, msg_data);
 233 
 234     } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
 235         reply_data.reply_type = pcmk_controld_reply_resource;
 236         reply_data.data.resource.node_state = msg_data;
 237 
 238     } else if (!strcmp(value, CRM_OP_PING)) {
 239         set_ping_data(&reply_data, msg_data);
 240 
 241     } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
 242         set_nodes_data(&reply_data, msg_data);
 243 
 244     } else {
 245         crm_info("Unrecognizable message from controller: unknown command '%s'",
 246                  value);
 247         status = CRM_EX_PROTOCOL;
 248     }
 249 
 250 done:
 251     pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
 252 
 253     
 254     if (pcmk__str_eq(value, PCMK__CONTROLD_CMD_NODES, pcmk__str_casei)) {
 255         g_list_free_full(reply_data.data.nodes, free);
 256     }
 257 
 258     return false; 
 259 }
 260 
 261 pcmk__ipc_methods_t *
 262 pcmk__controld_api_methods(void)
     
 263 {
 264     pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
 265 
 266     if (cmds != NULL) {
 267         cmds->new_data = new_data;
 268         cmds->free_data = free_data;
 269         cmds->post_connect = post_connect;
 270         cmds->reply_expected = reply_expected;
 271         cmds->dispatch = dispatch;
 272     }
 273     return cmds;
 274 }
 275 
 276 
 277 
 278 
 279 
 280 
 281 
 282 
 283 
 284 
 285 
 286 
 287 static xmlNode *
 288 create_controller_request(const pcmk_ipc_api_t *api, const char *op,
     
 289                           const char *node, xmlNode *msg_data)
 290 {
 291     struct controld_api_private_s *private = NULL;
 292     const char *sys_to = NULL;
 293 
 294     if (api == NULL) {
 295         return NULL;
 296     }
 297     private = api->api_data;
 298     if ((node == NULL) && !strcmp(op, CRM_OP_PING)) {
 299         sys_to = CRM_SYSTEM_DC;
 300     } else {
 301         sys_to = CRM_SYSTEM_CRMD;
 302     }
 303     return create_request(op, msg_data, node, sys_to,
 304                           (crm_system_name? crm_system_name : "client"),
 305                           private->client_uuid);
 306 }
 307 
 308 
 309 static int
 310 send_controller_request(pcmk_ipc_api_t *api, xmlNode *request,
     
 311                         bool reply_is_expected)
 312 {
 313     int rc;
 314 
 315     if (crm_element_value(request, XML_ATTR_REFERENCE) == NULL) {
 316         return EINVAL;
 317     }
 318     rc = pcmk__send_ipc_request(api, request);
 319     if ((rc == pcmk_rc_ok) && reply_is_expected) {
 320         struct controld_api_private_s *private = api->api_data;
 321 
 322         private->replies_expected++;
 323     }
 324     return rc;
 325 }
 326 
 327 static xmlNode *
 328 create_reprobe_message_data(const char *target_node, const char *router_node)
     
 329 {
 330     xmlNode *msg_data;
 331 
 332     msg_data = create_xml_node(NULL, "data_for_" CRM_OP_REPROBE);
 333     crm_xml_add(msg_data, XML_LRM_ATTR_TARGET, target_node);
 334     if ((router_node != NULL) && !pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
 335         crm_xml_add(msg_data, XML_LRM_ATTR_ROUTER_NODE, router_node);
 336     }
 337     return msg_data;
 338 }
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347 
 348 
 349 
 350 int
 351 pcmk_controld_api_reprobe(pcmk_ipc_api_t *api, const char *target_node,
     
 352                           const char *router_node)
 353 {
 354     xmlNode *request;
 355     xmlNode *msg_data;
 356     int rc = pcmk_rc_ok;
 357 
 358     if (api == NULL) {
 359         return EINVAL;
 360     }
 361     if (router_node == NULL) {
 362         router_node = target_node;
 363     }
 364     crm_debug("Sending %s IPC request to reprobe %s via %s",
 365               pcmk_ipc_name(api, true), pcmk__s(target_node, "local node"),
 366               pcmk__s(router_node, "local node"));
 367     msg_data = create_reprobe_message_data(target_node, router_node);
 368     request = create_controller_request(api, CRM_OP_REPROBE, router_node,
 369                                         msg_data);
 370     rc = send_controller_request(api, request, true);
 371     free_xml(msg_data);
 372     free_xml(request);
 373     return rc;
 374 }
 375 
 376 
 377 
 378 
 379 
 380 
 381 
 382 
 383 
 384 
 385 int
 386 pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
     
 387 {
 388     xmlNode *request;
 389     int rc = pcmk_rc_ok;
 390 
 391     request = create_controller_request(api, CRM_OP_NODE_INFO, NULL, NULL);
 392     if (request == NULL) {
 393         return EINVAL;
 394     }
 395     if (nodeid > 0) {
 396         crm_xml_set_id(request, "%lu", (unsigned long) nodeid);
 397     }
 398 
 399     rc = send_controller_request(api, request, true);
 400     free_xml(request);
 401     return rc;
 402 }
 403 
 404 
 405 
 406 
 407 
 408 
 409 
 410 
 411 
 412 
 413 int
 414 pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
     
 415 {
 416     xmlNode *request;
 417     int rc = pcmk_rc_ok;
 418 
 419     request = create_controller_request(api, CRM_OP_PING, node_name, NULL);
 420     if (request == NULL) {
 421         return EINVAL;
 422     }
 423     rc = send_controller_request(api, request, true);
 424     free_xml(request);
 425     return rc;
 426 }
 427 
 428 
 429 
 430 
 431 
 432 
 433 
 434 
 435 
 436 int
 437 pcmk_controld_api_list_nodes(pcmk_ipc_api_t *api)
     
 438 {
 439     xmlNode *request;
 440     int rc = EINVAL;
 441 
 442     request = create_controller_request(api, PCMK__CONTROLD_CMD_NODES, NULL,
 443                                         NULL);
 444     if (request != NULL) {
 445         rc = send_controller_request(api, request, true);
 446         free_xml(request);
 447     }
 448     return rc;
 449 }
 450 
 451 
 452 static int
 453 controller_resource_op(pcmk_ipc_api_t *api, const char *op,
     
 454                        const char *target_node, const char *router_node,
 455                        bool cib_only, const char *rsc_id,
 456                        const char *rsc_long_id, const char *standard,
 457                        const char *provider, const char *type)
 458 {
 459     int rc = pcmk_rc_ok;
 460     char *key;
 461     xmlNode *request, *msg_data, *xml_rsc, *params;
 462 
 463     if (api == NULL) {
 464         return EINVAL;
 465     }
 466     if (router_node == NULL) {
 467         router_node = target_node;
 468     }
 469 
 470     msg_data = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
 471 
 472     
 473 
 474 
 475 
 476     key = pcmk__transition_key(0, getpid(), 0,
 477                                "xxxxxxxx-xrsc-opxx-xcrm-resourcexxxx");
 478     crm_xml_add(msg_data, XML_ATTR_TRANSITION_KEY, key);
 479     free(key);
 480 
 481     crm_xml_add(msg_data, XML_LRM_ATTR_TARGET, target_node);
 482     if (!pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
 483         crm_xml_add(msg_data, XML_LRM_ATTR_ROUTER_NODE, router_node);
 484     }
 485 
 486     if (cib_only) {
 487         
 488         crm_xml_add(msg_data, PCMK__XA_MODE, XML_TAG_CIB);
 489     }
 490 
 491     xml_rsc = create_xml_node(msg_data, XML_CIB_TAG_RESOURCE);
 492     crm_xml_add(xml_rsc, XML_ATTR_ID, rsc_id);
 493     crm_xml_add(xml_rsc, XML_ATTR_ID_LONG, rsc_long_id);
 494     crm_xml_add(xml_rsc, XML_AGENT_ATTR_CLASS, standard);
 495     crm_xml_add(xml_rsc, XML_AGENT_ATTR_PROVIDER, provider);
 496     crm_xml_add(xml_rsc, XML_ATTR_TYPE, type);
 497 
 498     params = create_xml_node(msg_data, XML_TAG_ATTRS);
 499     crm_xml_add(params, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
 500 
 501     
 502     key = crm_meta_name(XML_ATTR_TIMEOUT);
 503     crm_xml_add(params, key, "60000");   
 504     free(key);
 505 
 506     request = create_controller_request(api, op, router_node, msg_data);
 507     rc = send_controller_request(api, request, true);
 508     free_xml(msg_data);
 509     free_xml(request);
 510     return rc;
 511 }
 512 
 513 
 514 
 515 
 516 
 517 
 518 
 519 
 520 
 521 
 522 
 523 
 524 
 525 
 526 
 527 
 528 int
 529 pcmk_controld_api_fail(pcmk_ipc_api_t *api,
     
 530                        const char *target_node, const char *router_node,
 531                        const char *rsc_id, const char *rsc_long_id,
 532                        const char *standard, const char *provider,
 533                        const char *type)
 534 {
 535     crm_debug("Sending %s IPC request to fail %s (a.k.a. %s) on %s via %s",
 536               pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
 537               pcmk__s(rsc_long_id, "no other names"),
 538               pcmk__s(target_node, "unspecified node"),
 539               pcmk__s(router_node, "unspecified node"));
 540     return controller_resource_op(api, CRM_OP_LRM_FAIL, target_node,
 541                                   router_node, false, rsc_id, rsc_long_id,
 542                                   standard, provider, type);
 543 }
 544 
 545 
 546 
 547 
 548 
 549 
 550 
 551 
 552 
 553 
 554 
 555 
 556 
 557 
 558 
 559 
 560 
 561 int
 562 pcmk_controld_api_refresh(pcmk_ipc_api_t *api, const char *target_node,
     
 563                           const char *router_node,
 564                           const char *rsc_id, const char *rsc_long_id,
 565                           const char *standard, const char *provider,
 566                           const char *type, bool cib_only)
 567 {
 568     crm_debug("Sending %s IPC request to refresh %s (a.k.a. %s) on %s via %s",
 569               pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
 570               pcmk__s(rsc_long_id, "no other names"),
 571               pcmk__s(target_node, "unspecified node"),
 572               pcmk__s(router_node, "unspecified node"));
 573     return controller_resource_op(api, CRM_OP_LRM_DELETE, target_node,
 574                                   router_node, cib_only, rsc_id, rsc_long_id,
 575                                   standard, provider, type);
 576 }
 577 
 578 
 579 
 580 
 581 
 582 
 583 
 584 
 585 unsigned int
 586 pcmk_controld_api_replies_expected(const pcmk_ipc_api_t *api)
     
 587 {
 588     struct controld_api_private_s *private = api->api_data;
 589 
 590     return private->replies_expected;
 591 }
 592 
 593 
 594 
 595 
 596 
 597 
 598 
 599 xmlNode *
 600 create_hello_message(const char *uuid, const char *client_name,
     
 601                      const char *major_version, const char *minor_version)
 602 {
 603     xmlNode *hello_node = NULL;
 604     xmlNode *hello = NULL;
 605 
 606     if (pcmk__str_empty(uuid) || pcmk__str_empty(client_name)
 607         || pcmk__str_empty(major_version) || pcmk__str_empty(minor_version)) {
 608         crm_err("Could not create IPC hello message from %s (UUID %s): "
 609                 "missing information",
 610                 client_name? client_name : "unknown client",
 611                 uuid? uuid : "unknown");
 612         return NULL;
 613     }
 614 
 615     hello_node = create_xml_node(NULL, XML_TAG_OPTIONS);
 616     if (hello_node == NULL) {
 617         crm_err("Could not create IPC hello message from %s (UUID %s): "
 618                 "Message data creation failed", client_name, uuid);
 619         return NULL;
 620     }
 621 
 622     crm_xml_add(hello_node, "major_version", major_version);
 623     crm_xml_add(hello_node, "minor_version", minor_version);
 624     crm_xml_add(hello_node, "client_name", client_name);
 625     crm_xml_add(hello_node, "client_uuid", uuid);
 626 
 627     hello = create_request(CRM_OP_HELLO, hello_node, NULL, NULL, client_name, uuid);
 628     if (hello == NULL) {
 629         crm_err("Could not create IPC hello message from %s (UUID %s): "
 630                 "Request creation failed", client_name, uuid);
 631         return NULL;
 632     }
 633     free_xml(hello_node);
 634 
 635     crm_trace("Created hello message from %s (UUID %s)", client_name, uuid);
 636     return hello;
 637 }