Ejemplo n.º 1
0
enum crmd_fsa_input
handle_message(xmlNode * msg)
{
    const char *type = NULL;

    CRM_CHECK(msg != NULL, return I_NULL);

    type = crm_element_value(msg, F_CRM_MSG_TYPE);
    if (crm_str_eq(type, XML_ATTR_REQUEST, TRUE)) {
        return handle_request(msg);

    } else if (crm_str_eq(type, XML_ATTR_RESPONSE, TRUE)) {
        handle_response(msg);
        return I_NULL;
    }

    crm_err("Unknown message type: %s", type);
    return I_NULL;
}
Ejemplo n.º 2
0
/* Exit code means? */
static int32_t
pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
{
    uint32_t id = 0;
    uint32_t flags = 0;
    const char *task = NULL;
    crm_client_t *c = crm_client_get(qbc);
    xmlNode *msg = crm_ipcs_recv(c, data, size, &id, &flags);

    crm_ipcs_send_ack(c, id, flags, "ack", __FUNCTION__, __LINE__);
    if (msg == NULL) {
        return 0;
    }

    task = crm_element_value(msg, F_CRM_TASK);
    if (crm_str_eq(task, CRM_OP_QUIT, TRUE)) {
        /* Time to quit */
        crm_notice("Shutting down in response to ticket %s (%s)",
                   crm_element_value(msg, F_CRM_REFERENCE), crm_element_value(msg, F_CRM_ORIGIN));
        pcmk_shutdown(15);

    } else if (crm_str_eq(task, CRM_OP_RM_NODE_CACHE, TRUE)) {
        /* Send to everyone */
        struct iovec *iov;
        int id = 0;
        const char *name = NULL;

        crm_element_value_int(msg, XML_ATTR_ID, &id);
        name = crm_element_value(msg, XML_ATTR_UNAME);
        crm_notice("Instructing peers to remove references to node %s/%u", name, id);

        iov = calloc(1, sizeof(struct iovec));
        iov->iov_base = dump_xml_unformatted(msg);
        iov->iov_len = 1 + strlen(iov->iov_base);
        send_cpg_iov(iov);

    } else {
        update_process_clients(c);
    }

    free_xml(msg);
    return 0;
}
Ejemplo n.º 3
0
void
unpack_instance_attributes(xmlNode * top, xmlNode * xml_obj, const char *set_name,
                           GHashTable * node_hash, GHashTable * hash, const char *always_first,
                           gboolean overwrite, crm_time_t * now)
{
    GListPtr sorted = NULL;
    GListPtr unsorted = NULL;
    const char *score = NULL;
    sorted_set_t *pair = NULL;
    struct unpack_data_s data;
    xmlNode *attr_set = NULL;

    if (xml_obj == NULL) {
        crm_trace("No instance attributes");
        return;
    }

    crm_trace("Checking for attributes");
    for (attr_set = __xml_first_child(xml_obj); attr_set != NULL; attr_set = __xml_next_element(attr_set)) {
        /* Uncertain if set_name == NULL check is strictly necessary here */
        if (set_name == NULL || crm_str_eq((const char *)attr_set->name, set_name, TRUE)) {
            pair = NULL;
            attr_set = expand_idref(attr_set, top);
            if (attr_set == NULL) {
                continue;
            }

            pair = calloc(1, sizeof(sorted_set_t));
            pair->name = ID(attr_set);
            pair->special_name = always_first;
            pair->attr_set = attr_set;

            score = crm_element_value(attr_set, XML_RULE_ATTR_SCORE);
            pair->score = char2score(score);

            unsorted = g_list_prepend(unsorted, pair);
        }
    }

    if (pair != NULL) {
        data.hash = hash;
        data.node_hash = node_hash;
        data.now = now;
        data.overwrite = overwrite;
        data.top = top;
    }

    if (unsorted) {
        sorted = g_list_sort(unsorted, sort_pairs);
        g_list_foreach(sorted, unpack_attr_set, &data);
        g_list_free_full(sorted, free);
    }
}
Ejemplo n.º 4
0
static void
populate_hash(xmlNode * nvpair_list, GHashTable * hash, gboolean overwrite, xmlNode * top)
{
    const char *name = NULL;
    const char *value = NULL;
    const char *old_value = NULL;
    xmlNode *list = nvpair_list;
    xmlNode *an_attr = NULL;

    name = crm_element_name(list->children);
    if (safe_str_eq(XML_TAG_ATTRS, name)) {
        list = list->children;
    }

    for (an_attr = __xml_first_child(list); an_attr != NULL; an_attr = __xml_next_element(an_attr)) {
        if (crm_str_eq((const char *)an_attr->name, XML_CIB_TAG_NVPAIR, TRUE)) {
            xmlNode *ref_nvpair = expand_idref(an_attr, top);

            name = crm_element_value(an_attr, XML_NVPAIR_ATTR_NAME);
            if (name == NULL) {
                name = crm_element_value(ref_nvpair, XML_NVPAIR_ATTR_NAME);
            }

            crm_trace("Setting attribute: %s", name);
            value = crm_element_value(an_attr, XML_NVPAIR_ATTR_VALUE);
            if (value == NULL) {
                value = crm_element_value(ref_nvpair, XML_NVPAIR_ATTR_VALUE);
            }

            if (name == NULL || value == NULL) {
                continue;

            }

            old_value = g_hash_table_lookup(hash, name);

            if (safe_str_eq(value, "#default")) {
                if (old_value) {
                    crm_trace("Removing value for %s (%s)", name, value);
                    g_hash_table_remove(hash, name);
                }
                continue;

            } else if (old_value == NULL) {
                g_hash_table_insert(hash, strdup(name), strdup(value));

            } else if (overwrite) {
                crm_debug("Overwriting value of %s: %s -> %s", name, old_value, value);
                g_hash_table_replace(hash, strdup(name), strdup(value));
            }
        }
    }
}
Ejemplo n.º 5
0
static int
check_group_membership(const char *usr, const char *grp)
{
    int index = 0;
    struct passwd *pwd = NULL;
    struct group *group = NULL;

    CRM_CHECK(usr != NULL, return FALSE);
    CRM_CHECK(grp != NULL, return FALSE);

    pwd = getpwnam(usr);
    if (pwd == NULL) {
        crm_err("No user named '%s' exists!", usr);
        return FALSE;
    }

    group = getgrgid(pwd->pw_gid);
    if (group != NULL && crm_str_eq(grp, group->gr_name, TRUE)) {
        return TRUE;
    }

    group = getgrnam(grp);
    if (group == NULL) {
        crm_err("No group named '%s' exists!", grp);
        return FALSE;
    }

    while (TRUE) {
        char *member = group->gr_mem[index++];

        if (member == NULL) {
            break;

        } else if (crm_str_eq(usr, member, TRUE)) {
            return TRUE;
        }
    };

    return FALSE;
}
Ejemplo n.º 6
0
static void
stonith_peer_callback(xmlNode * msg, void *private_data)
{
    const char *remote_peer = crm_element_value(msg, F_ORIG);
    const char *op = crm_element_value(msg, F_STONITH_OPERATION);

    if (crm_str_eq(op, "poke", TRUE)) {
        return;
    }

    crm_log_xml_trace(msg, "Peer[inbound]");
    stonith_command(NULL, 0, 0, msg, remote_peer);
}
Ejemplo n.º 7
0
void
cli_resource_print_cts(resource_t * rsc)
{
    GListPtr lpc = NULL;
    const char *host = NULL;
    bool needs_quorum = TRUE;
    const char *rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE);
    const char *rprov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
    const char *rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);

    if (safe_str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH)) {
        xmlNode *op = NULL;

        needs_quorum = FALSE;

        for (op = __xml_first_child(rsc->ops_xml); op != NULL; op = __xml_next(op)) {
            if (crm_str_eq((const char *)op->name, "op", TRUE)) {
                const char *name = crm_element_value(op, "name");

                if (safe_str_neq(name, CRMD_ACTION_START)) {
                    const char *value = crm_element_value(op, "requires");

                    if (safe_str_eq(value, "nothing")) {
                        needs_quorum = FALSE;
                    }
                    break;
                }
            }
        }
    }

    if (rsc->running_on != NULL && g_list_length(rsc->running_on) == 1) {
        node_t *tmp = rsc->running_on->data;

        host = tmp->details->uname;
    }

    printf("Resource: %s %s %s %s %s %s %s %s %d %lld 0x%.16llx\n",
           crm_element_name(rsc->xml), rsc->id,
           rsc->clone_name ? rsc->clone_name : rsc->id, rsc->parent ? rsc->parent->id : "NA",
           rprov ? rprov : "NA", rclass, rtype, host ? host : "NA", needs_quorum, rsc->flags,
           rsc->flags);

    for (lpc = rsc->children; lpc != NULL; lpc = lpc->next) {
        resource_t *child = (resource_t *) lpc->data;

        cli_resource_print_cts(child);
    }
}
Ejemplo n.º 8
0
int
query_node_uuid(cib_t * the_cib, const char *uname, char **uuid)
{
    int rc = pcmk_ok;
    xmlNode *a_child = NULL;
    xmlNode *xml_obj = NULL;
    xmlNode *fragment = NULL;
    const char *child_name = NULL;

    CRM_ASSERT(uname != NULL);
    CRM_ASSERT(uuid != NULL);

    rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment,
                              cib_sync_call | cib_scope_local);
    if (rc != pcmk_ok) {
        return rc;
    }

    xml_obj = fragment;
    CRM_CHECK(safe_str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES), return -ENOMSG);
    CRM_ASSERT(xml_obj != NULL);
    crm_log_xml_debug(xml_obj, "Result section");

    rc = -ENXIO;
    *uuid = NULL;

    for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) {
        if (crm_str_eq((const char *)a_child->name, XML_CIB_TAG_NODE, TRUE)) {
            child_name = crm_element_value(a_child, XML_ATTR_UNAME);
            if (safe_str_eq(uname, child_name)) {
                child_name = ID(a_child);
                if (child_name != NULL) {
                    *uuid = strdup(child_name);
                    rc = pcmk_ok;
                }
                break;
            }
        }
    }

    if (rc != pcmk_ok) {
        crm_debug("Could not map name=%s to a UUID: %s\n", uname, pcmk_strerror(rc));
    } else {
        crm_info("Mapped %s to %s", uname, *uuid);
    }

    free_xml(fragment);
    return rc;
}
Ejemplo n.º 9
0
static gboolean
migration_overrun(crm_graph_t * graph, synapse_t * synapse)
{
    GListPtr lpc = NULL;

    CRM_CHECK(synapse != NULL, return FALSE);

    if (graph->migration_limit < 0) {
        return FALSE;
    }

    for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
        crm_action_t *action = (crm_action_t *) lpc->data;

        const char *task = NULL;

        if (action->type != action_type_rsc) {
            continue;
        }

        task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);

        if (crm_str_eq(task, CRMD_ACTION_MIGRATE, TRUE)
            || crm_str_eq(task, CRMD_ACTION_MIGRATED, TRUE)) {
            const char *node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);

            int *counter = g_hash_table_lookup(graph->migrating, node);

            if (counter && *counter >= graph->migration_limit) {
                return TRUE;
            }

        }
    }
    return FALSE;
}
Ejemplo n.º 10
0
static int
send_via_callback_channel(xmlNode *msg, const char *token) 
{
    stonith_client_t *hash_client = NULL;
    enum stonith_errors rc = stonith_ok;
	
    crm_trace("Delivering msg %p to client %s", msg, token);

    if(token == NULL) {
	crm_err("No client id token, cant send message");
	if(rc == stonith_ok) {
	    rc = -1;
	}

    } else if(msg == NULL) {
	crm_err("No message to send");
	rc = -1;
	    
    } else {
	/* A client that left before we could reply is not really
	 * _our_ error.  Warn instead.
	 */
	hash_client = g_hash_table_lookup(client_list, token);
	if(hash_client == NULL) {
	    crm_warn("Cannot find client for token %s", token);
	    rc = -1;
			
	} else if (crm_str_eq(hash_client->channel_name, "remote", FALSE)) {
	    /* just hope it's alive */
		    
	} else if(hash_client->channel == NULL) {
	    crm_err("Cannot find channel for client %s", token);
	    rc = -1;
	}
    }

    if(rc == stonith_ok) {
	crm_trace("Delivering reply to client %s (%s)",
		    token, hash_client->channel_name);
	if(send_ipc_message(hash_client->channel, msg) == FALSE) {
	    crm_warn("Delivery of reply to client %s/%s failed",
		     hash_client->name, token);
	    rc = -1;
	}
    }
	
    return rc;
}
Ejemplo n.º 11
0
gboolean
test_ruleset(xmlNode * ruleset, GHashTable * node_hash, crm_time_t * now)
{
    gboolean ruleset_default = TRUE;
    xmlNode *rule = NULL;

    for (rule = __xml_first_child(ruleset); rule != NULL; rule = __xml_next_element(rule)) {
        if (crm_str_eq((const char *)rule->name, XML_TAG_RULE, TRUE)) {
            ruleset_default = FALSE;
            if (test_rule(rule, node_hash, RSC_ROLE_UNKNOWN, now)) {
                return TRUE;
            }
        }
    }

    return ruleset_default;
}
Ejemplo n.º 12
0
static int
get_cluster_node_uuid(cib_t * the_cib, const char *uname, char **uuid)
{
    int rc = pcmk_ok;
    xmlNode *a_child = NULL;
    xmlNode *xml_obj = NULL;
    xmlNode *fragment = NULL;
    const char *child_name = NULL;

    rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment,
                              cib_sync_call | cib_scope_local);
    if (rc != pcmk_ok) {
        return rc;
    }

    xml_obj = fragment;
    CRM_CHECK(safe_str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES), return -ENOMSG);
    CRM_ASSERT(xml_obj != NULL);
    crm_log_xml_debug(xml_obj, "Result section");

    rc = -ENXIO;
    *uuid = NULL;

    for (a_child = __xml_first_child(xml_obj); a_child != NULL; a_child = __xml_next(a_child)) {
        if (crm_str_eq((const char *)a_child->name, XML_CIB_TAG_NODE, TRUE)) {
            const char *node_type = crm_element_value(a_child, XML_ATTR_TYPE);
            /* Only if it's a cluster node */
            if (safe_str_eq(node_type, "remote")) {
                continue;
            }

            child_name = crm_element_value(a_child, XML_ATTR_UNAME);
            if (safe_str_eq(uname, child_name)) {
                child_name = ID(a_child);
                if (child_name != NULL) {
                    *uuid = strdup(child_name);
                    rc = pcmk_ok;
                }
                break;
            }
        }
    }

    free_xml(fragment);
    return rc;
}
Ejemplo n.º 13
0
/*!
 * \internal
 * \brief Process a CPG message (process list or manual peer cache removal)
 *
 * \param[in] handle     CPG connection (ignored)
 * \param[in] groupName  CPG group name (ignored)
 * \param[in] nodeid     ID of affected node
 * \param[in] pid        Process ID (ignored)
 * \param[in] msg        CPG XML message
 * \param[in] msg_len    Length of msg in bytes (ignored)
 */
static void
mcp_cpg_deliver(cpg_handle_t handle,
                 const struct cpg_name *groupName,
                 uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
{
    xmlNode *xml = string2xml(msg);
    const char *task = crm_element_value(xml, F_CRM_TASK);

    crm_trace("Received CPG message (%s): %.200s",
              (task? task : "process list"), msg);

    if (task == NULL) {
        if (nodeid == local_nodeid) {
            crm_info("Ignoring process list sent by peer for local node");
        } else {
            uint32_t procs = 0;
            const char *uname = crm_element_value(xml, "uname");

            crm_element_value_int(xml, "proclist", (int *)&procs);
            if (update_node_processes(nodeid, uname, procs)) {
                update_process_clients(NULL);
            }
        }

    } else if (crm_str_eq(task, CRM_OP_RM_NODE_CACHE, TRUE)) {
        int id = 0;
        const char *name = NULL;

        crm_element_value_int(xml, XML_ATTR_ID, &id);
        name = crm_element_value(xml, XML_ATTR_UNAME);
        reap_crm_member(id, name);
    }

    if (xml != NULL) {
        free_xml(xml);
    }
}
Ejemplo n.º 14
0
static gboolean
check_rsc_parameters(resource_t *rsc, node_t *node, crm_data_t *rsc_entry,
		     pe_working_set_t *data_set) 
{
	int attr_lpc = 0;
	gboolean force_restart = FALSE;
	gboolean delete_resource = FALSE;
	
	const char *value = NULL;
	const char *old_value = NULL;
	const char *attr_list[] = {
		XML_ATTR_TYPE, 
		XML_AGENT_ATTR_CLASS,
 		XML_AGENT_ATTR_PROVIDER
	};

	for(; attr_lpc < DIMOF(attr_list); attr_lpc++) {
		value = crm_element_value(rsc->xml, attr_list[attr_lpc]);
		old_value = crm_element_value(rsc_entry, attr_list[attr_lpc]);
		if(value == old_value /* ie. NULL */
		   || crm_str_eq(value, old_value, TRUE)) {
			continue;
		}
		
		force_restart = TRUE;
		crm_notice("Forcing restart of %s on %s, %s changed: %s -> %s",
			   rsc->id, node->details->uname, attr_list[attr_lpc],
			   crm_str(old_value), crm_str(value));
	}
	if(force_restart) {
		/* make sure the restart happens */
		stop_action(rsc, node, FALSE);
		set_bit(rsc->flags, pe_rsc_start_pending);
		delete_resource = TRUE;
	}
	return delete_resource;
}
Ejemplo n.º 15
0
int
main(int argc, char **argv)
{
	int argerr = 0;
	int flag;
	const char *source = NULL;
	char *admin_input_xml = NULL;
	char *admin_input_file = NULL;
	gboolean dangerous_cmd = FALSE;
	gboolean admin_input_stdin = FALSE;
	xmlNode *output = NULL;
	xmlNode *input = NULL;
	
	int option_index = 0;
	crm_log_init("cibadmin", LOG_CRIT, FALSE, FALSE, argc, argv);
	crm_set_options("V?$o:QDUCEX:t:Srwlsh:MmBfbRx:pP5N:A:uncd", "command [options] [data]", long_options,
			"Provides direct access to the cluster configuration."
			"\n\n Allows the configuration, or sections of it, to be queried, modified, replaced and deleted."
			"\n\n Where necessary, XML data will be obtained using the -X, -x, or -p options\n");

	if(argc < 2) {
		crm_help('?',LSB_EXIT_EINVAL);
	}

	while (1) {
		flag = crm_get_option(argc, argv, &option_index);
		if (flag == -1)
			break;

		switch(flag) {
			case 't':
				message_timeout_ms = atoi(optarg);
				if(message_timeout_ms < 1) {
					message_timeout_ms = 30;
				}
				break;
			case 'A':
				obj_type = crm_strdup(optarg);
				command_options |= cib_xpath;
				break;
			case 'u':
				cib_action = CIB_OP_UPGRADE;
				dangerous_cmd = TRUE;
				break;
			case 'E':
				cib_action = CIB_OP_ERASE;
				dangerous_cmd = TRUE;
				break;
			case 'Q':
				cib_action = CIB_OP_QUERY;
				break;
			case 'P':
				cib_action = CIB_OP_APPLY_DIFF;
				break;
			case 'S':
				cib_action = CIB_OP_SYNC;
				break;
			case 'U':
			case 'M':
				cib_action = CIB_OP_MODIFY;
				break;
			case 'R':
				cib_action = CIB_OP_REPLACE;
				break;
			case 'C':
				cib_action = CIB_OP_CREATE;
				break;
			case 'D':
				cib_action = CIB_OP_DELETE;
				break;
			case '5':
				cib_action = "md5-sum";
				break;
			case 'c':
				command_options |= cib_can_create;
				break;
			case 'n':
				command_options |= cib_no_children;
				break;
			case 'm':
				cib_action = CIB_OP_ISMASTER;
				command_options |= cib_scope_local;
				break;
			case 'B':
				cib_action = CIB_OP_BUMP;
				break;
			case 'r':
				dangerous_cmd = TRUE;
				cib_action = CIB_OP_SLAVE;
				break;
			case 'w':
				dangerous_cmd = TRUE;
				cib_action = CIB_OP_MASTER;
				command_options |= cib_scope_local;
				break;
			case 'V':
				command_options = command_options | cib_verbose;
				cl_log_enable_stderr(TRUE);
				alter_debug(DEBUG_INC);
				break;
			case '?':
			case '$':
				crm_help(flag, LSB_EXIT_OK);
				break;
			case 'o':
				crm_debug_2("Option %c => %s", flag, optarg);
				obj_type = crm_strdup(optarg);
				break;
			case 'X':
				crm_debug_2("Option %c => %s", flag, optarg);
				admin_input_xml = crm_strdup(optarg);
				break;
			case 'x':
				crm_debug_2("Option %c => %s", flag, optarg);
				admin_input_file = crm_strdup(optarg);
				break;
			case 'p':
				admin_input_stdin = TRUE;
				break;
			case 'h':
				host = crm_strdup(optarg);
				break;
			case 'l':
				command_options |= cib_scope_local;
				break;
			case 'd':
				cib_action = CIB_OP_DELETE;
				command_options |= cib_multiple;
				dangerous_cmd = TRUE;
				break;
			case 'b':
				dangerous_cmd = TRUE;
				command_options |= cib_inhibit_bcast;
				command_options |= cib_scope_local;
				break;
			case 's':
				command_options |= cib_sync_call;
				break;
			case 'f':
				force_flag = TRUE;
				command_options |= cib_quorum_override;
				break;
			default:
				printf("Argument code 0%o (%c)"
				       " is not (?yet?) supported\n",
				       flag, flag);
				++argerr;
				break;
		}
	}

	if (optind < argc) {
		printf("non-option ARGV-elements: ");
		while (optind < argc)
			printf("%s ", argv[optind++]);
		printf("\n");
		crm_help('?', LSB_EXIT_EINVAL);
	}

	if (optind > argc || cib_action == NULL) {
	    ++argerr;
	}
	
	if (argerr) {
		crm_help('?', LSB_EXIT_GENERIC);
	}

	if(dangerous_cmd && force_flag == FALSE) {
	    fprintf(stderr, "The supplied command is considered dangerous."
		    "  To prevent accidental destruction of the cluster,"
		    " the --force flag is required in order to proceed.\n");
	    fflush(stderr);
	    exit(LSB_EXIT_GENERIC);
	}
	
	if(admin_input_file != NULL) {
	    input = filename2xml(admin_input_file);
	    source = admin_input_file;
		
	} else if(admin_input_xml != NULL) {
	    source = "input string";
	    input = string2xml(admin_input_xml);

	} else if(admin_input_stdin) {
	    source = "STDIN";
	    input = stdin2xml();
	}
	
	if(input != NULL) {
	    crm_log_xml_debug(input, "[admin input]");

	} else if(source) {
	    fprintf(stderr, "Couldn't parse input from %s.\n", source);
	    return 1;
	}

	if(safe_str_eq(cib_action, "md5-sum")) {
	    char *digest = NULL;
	    if(input == NULL) {
		fprintf(stderr,
			"Please supply XML to process with -X, -x or -p\n");
		exit(1);
	    }
	    
	    digest = calculate_xml_digest(input, FALSE, FALSE);
	    fprintf(stderr, "Digest: ");
	    fprintf(stdout, "%s\n", crm_str(digest));
	    crm_free(digest);
	    exit(0);
	}
	
	exit_code = do_init();
	if(exit_code != cib_ok) {
		crm_err("Init failed, could not perform requested operations");
		fprintf(stderr, "Init failed, could not perform requested operations\n");
		return -exit_code;
	}	

	exit_code = do_work(input, command_options, &output);
	if (exit_code > 0) {
		/* wait for the reply by creating a mainloop and running it until
		 * the callbacks are invoked...
		 */
		request_id = exit_code;

		the_cib->cmds->register_callback(
		    the_cib, request_id, message_timeout_ms, FALSE, NULL,
		    "cibadmin_op_callback", cibadmin_op_callback);

		mainloop = g_main_new(FALSE);

		crm_debug_3("%s waiting for reply from the local CIB",
			 crm_system_name);
		
		crm_info("Starting mainloop");
		g_main_run(mainloop);
		
	} else if(exit_code < 0) {
		crm_err("Call failed: %s", cib_error2string(exit_code));
		fprintf(stderr, "Call failed: %s\n",
			cib_error2string(exit_code));
		operation_status = exit_code;

		if(exit_code == cib_dtd_validation) {
		    if(crm_str_eq(cib_action, CIB_OP_UPGRADE, TRUE)) {
			xmlNode *obj = NULL;
			int version = 0, rc = 0;
			rc = the_cib->cmds->query(the_cib, NULL, &obj, command_options);
			if(rc == cib_ok) {
			    update_validation(&obj, &version, TRUE, FALSE);
			}

		    } else if(output) {
			validate_xml_verbose(output);
		    }
		}
	}

	if(output != NULL) {
		char *buffer = dump_xml_formatted(output);
		fprintf(stdout, "%s\n", crm_str(buffer));
		crm_free(buffer);
	}

	the_cib->cmds->signoff(the_cib);
	
	crm_debug_3("%s exiting normally", crm_system_name);
	return -exit_code;
}
Ejemplo n.º 16
0
int
main(int argc, char **argv)
{
    int argerr = 0;
    int flag;
    const char *source = NULL;
    const char *admin_input_xml = NULL;
    const char *admin_input_file = NULL;
    gboolean dangerous_cmd = FALSE;
    gboolean admin_input_stdin = FALSE;
    xmlNode *output = NULL;
    xmlNode *input = NULL;

    int option_index = 0;

    crm_xml_init(); /* Sets buffer allocation strategy */
    crm_system_name = strdup("cibadmin");
    crm_set_options(NULL, "command [options] [data]", long_options,
                    "Provides direct access to the cluster configuration."
                    "\n\nAllows the configuration, or sections of it, to be queried, modified, replaced and deleted."
                    "\n\nWhere necessary, XML data will be obtained using the -X, -x, or -p options\n");

    if (argc < 2) {
        crm_help('?', EX_USAGE);
    }

    while (1) {
        flag = crm_get_option(argc, argv, &option_index);
        if (flag == -1)
            break;

        switch (flag) {
            case 't':
                message_timeout_ms = atoi(optarg);
                if (message_timeout_ms < 1) {
                    message_timeout_ms = 30;
                }
                break;
            case 'A':
                obj_type = optarg;
                command_options |= cib_xpath;
                break;
            case 'e':
                command_options |= cib_xpath_address;
                break;
            case 'u':
                cib_action = CIB_OP_UPGRADE;
                dangerous_cmd = TRUE;
                break;
            case 'E':
                cib_action = CIB_OP_ERASE;
                dangerous_cmd = TRUE;
                break;
            case 'Q':
                cib_action = CIB_OP_QUERY;
                quiet = TRUE;
                break;
            case 'P':
                cib_action = CIB_OP_APPLY_DIFF;
                break;
            case 'U':
                cib_user = optarg;
                break;
            case 'M':
                cib_action = CIB_OP_MODIFY;
                break;
            case 'R':
                cib_action = CIB_OP_REPLACE;
                break;
            case 'C':
                cib_action = CIB_OP_CREATE;
                break;
            case 'D':
                cib_action = CIB_OP_DELETE;
                break;
            case '5':
                cib_action = "md5-sum";
                break;
            case '6':
                cib_action = "md5-sum-versioned";
                break;
            case 'c':
                command_options |= cib_can_create;
                break;
            case 'n':
                command_options |= cib_no_children;
                break;
            case 'B':
                cib_action = CIB_OP_BUMP;
                break;
            case 'V':
                command_options = command_options | cib_verbose;
                bump_log_num++;
                break;
            case '?':
            case '$':
            case '!':
                crm_help(flag, EX_OK);
                break;
            case 'o':
                crm_trace("Option %c => %s", flag, optarg);
                obj_type = optarg;
                break;
            case 'X':
                crm_trace("Option %c => %s", flag, optarg);
                admin_input_xml = optarg;
                break;
            case 'x':
                crm_trace("Option %c => %s", flag, optarg);
                admin_input_file = optarg;
                break;
            case 'p':
                admin_input_stdin = TRUE;
                break;
            case 'N':
            case 'h':
                host = strdup(optarg);
                break;
            case 'l':
                command_options |= cib_scope_local;
                break;
            case 'd':
                cib_action = CIB_OP_DELETE;
                command_options |= cib_multiple;
                dangerous_cmd = TRUE;
                break;
            case 'b':
                dangerous_cmd = TRUE;
                command_options |= cib_inhibit_bcast;
                command_options |= cib_scope_local;
                break;
            case 's':
                command_options |= cib_sync_call;
                break;
            case 'f':
                force_flag = TRUE;
                command_options |= cib_quorum_override;
                break;
            case 'a':
                output = createEmptyCib(1);
                if (optind < argc) {
                    crm_xml_add(output, XML_ATTR_VALIDATION, argv[optind]);
                }
                admin_input_xml = dump_xml_formatted(output);
                fprintf(stdout, "%s\n", crm_str(admin_input_xml));
                goto bail;
                break;
            default:
                printf("Argument code 0%o (%c)" " is not (?yet?) supported\n", flag, flag);
                ++argerr;
                break;
        }
    }

    if (bump_log_num > 0) {
        quiet = FALSE;
    }
    crm_log_init(NULL, LOG_CRIT, FALSE, FALSE, argc, argv, quiet);
    while (bump_log_num > 0) {
        crm_bump_log_level(argc, argv);
        bump_log_num--;
    }

    if (optind < argc) {
        printf("non-option ARGV-elements: ");
        while (optind < argc)
            printf("%s ", argv[optind++]);
        printf("\n");
        crm_help('?', EX_USAGE);
    }

    if (optind > argc || cib_action == NULL) {
        ++argerr;
    }

    if (argerr) {
        crm_help('?', EX_USAGE);
    }

    if (dangerous_cmd && force_flag == FALSE) {
        fprintf(stderr, "The supplied command is considered dangerous."
                "  To prevent accidental destruction of the cluster,"
                " the --force flag is required in order to proceed.\n");
        fflush(stderr);
        exit_code = -EINVAL;
        goto bail;
    }

    if (admin_input_file != NULL) {
        input = filename2xml(admin_input_file);
        source = admin_input_file;

    } else if (admin_input_xml != NULL) {
        source = "input string";
        input = string2xml(admin_input_xml);

    } else if (admin_input_stdin) {
        source = "STDIN";
        input = stdin2xml();
    }

    if (input != NULL) {
        crm_log_xml_debug(input, "[admin input]");

    } else if (source) {
        fprintf(stderr, "Couldn't parse input from %s.\n", source);
        exit_code = -EINVAL;
        goto bail;
    }

    if (safe_str_eq(cib_action, "md5-sum")) {
        char *digest = NULL;

        if (input == NULL) {
            fprintf(stderr, "Please supply XML to process with -X, -x or -p\n");
            exit_code = -EINVAL;
            goto bail;
        }

        digest = calculate_on_disk_digest(input);
        fprintf(stderr, "Digest: ");
        fprintf(stdout, "%s\n", crm_str(digest));
        free(digest);
        goto bail;

    } else if (safe_str_eq(cib_action, "md5-sum-versioned")) {
        char *digest = NULL;
        const char *version = NULL;

        if (input == NULL) {
            fprintf(stderr, "Please supply XML to process with -X, -x or -p\n");
            exit_code = -EINVAL;
            goto bail;
        }

        version = crm_element_value(input, XML_ATTR_CRM_VERSION);
        digest = calculate_xml_versioned_digest(input, FALSE, TRUE, version);
        fprintf(stderr, "Versioned (%s) digest: ", version);
        fprintf(stdout, "%s\n", crm_str(digest));
        free(digest);
        goto bail;
    }

    exit_code = do_init();
    if (exit_code != pcmk_ok) {
        crm_err("Init failed, could not perform requested operations");
        fprintf(stderr, "Init failed, could not perform requested operations\n");
        return crm_exit(-exit_code);
    }

    exit_code = do_work(input, command_options, &output);
    if (exit_code > 0) {
        /* wait for the reply by creating a mainloop and running it until
         * the callbacks are invoked...
         */
        request_id = exit_code;

        the_cib->cmds->register_callback(the_cib, request_id, message_timeout_ms, FALSE, NULL,
                                         "cibadmin_op_callback", cibadmin_op_callback);

        mainloop = g_main_new(FALSE);

        crm_trace("%s waiting for reply from the local CIB", crm_system_name);

        crm_info("Starting mainloop");
        g_main_run(mainloop);

    } else if (exit_code < 0) {
        crm_err("Call failed: %s", pcmk_strerror(exit_code));
        fprintf(stderr, "Call failed: %s\n", pcmk_strerror(exit_code));
        operation_status = exit_code;

        if (exit_code == -pcmk_err_schema_validation) {
            if (crm_str_eq(cib_action, CIB_OP_UPGRADE, TRUE)) {
                xmlNode *obj = NULL;
                int version = 0, rc = 0;

                rc = the_cib->cmds->query(the_cib, NULL, &obj, command_options);
                if (rc == pcmk_ok) {
                    update_validation(&obj, &version, 0, TRUE, FALSE);
                }

            } else if (output) {
                validate_xml_verbose(output);
            }
        }
    }

    if (output != NULL) {
        print_xml_output(output);
        free_xml(output);
    }

    crm_trace("%s exiting normally", crm_system_name);

    free_xml(input);
    flag = the_cib->cmds->signoff(the_cib);
    cib_delete(the_cib);

    if(exit_code == pcmk_ok) {
        exit_code = flag;
    }
  bail:
    return crm_exit(exit_code);
}
Ejemplo n.º 17
0
gboolean
process_graph_event(xmlNode * event, const char *event_node)
{
    int rc = -1;
    int status = -1;
    int callid = -1;

    int action = -1;
    int target_rc = -1;
    int transition_num = -1;
    char *update_te_uuid = NULL;

    gboolean stop_early = FALSE;
    gboolean passed = FALSE;
    const char *id = NULL;
    const char *desc = NULL;
    const char *magic = NULL;

    CRM_ASSERT(event != NULL);

/*
<lrm_rsc_op id="rsc_east-05_last_0" operation_key="rsc_east-05_monitor_0" operation="monitor" crm-debug-origin="do_update_resource" crm_feature_set="3.0.6" transition-key="9:2:7:be2e97d9-05e2-439d-863e-48f7aecab2aa" transition-magic="0:7;9:2:7:be2e97d9-05e2-439d-863e-48f7aecab2aa" call-id="17" rc-code="7" op-status="0" interval="0" last-run="1355361636" last-rc-change="1355361636" exec-time="128" queue-time="0" op-digest="c81f5f40b1c9e859c992e800b1aa6972"/>
*/

    id = crm_element_value(event, XML_LRM_ATTR_TASK_KEY);
    crm_element_value_int(event, XML_LRM_ATTR_RC, &rc);
    crm_element_value_int(event, XML_LRM_ATTR_OPSTATUS, &status);
    crm_element_value_int(event, XML_LRM_ATTR_CALLID, &callid);

    magic = crm_element_value(event, XML_ATTR_TRANSITION_KEY);
    if (magic == NULL) {
        /* non-change */
        return FALSE;
    }

    if (decode_transition_key(magic, &update_te_uuid, &transition_num, &action, &target_rc) ==
        FALSE) {
        crm_err("Invalid event %s.%d detected: %s", id, callid, magic);
        abort_transition(INFINITY, tg_restart, "Bad event", event);
        return FALSE;
    }

    if (status == PCMK_LRM_OP_PENDING) {
        goto bail;
    }

    if (transition_num == -1) {
        desc = "initiated outside of the cluster";
        abort_transition(INFINITY, tg_restart, "Unexpected event", event);

    } else if (action < 0 || crm_str_eq(update_te_uuid, te_uuid, TRUE) == FALSE) {
        desc = "initiated by a different node";
        abort_transition(INFINITY, tg_restart, "Foreign event", event);
        stop_early = TRUE;      /* This could be an lrm status refresh */

    } else if (transition_graph->id != transition_num) {
        desc = "arrived really late";
        abort_transition(INFINITY, tg_restart, "Old event", event);
        stop_early = TRUE;      /* This could be an lrm status refresh */

    } else if (transition_graph->complete) {
        desc = "arrived late";
        abort_transition(INFINITY, tg_restart, "Inactive graph", event);

    } else if (match_graph_event(action, event, event_node, status, rc, target_rc) < 0) {
        desc = "unknown";
        abort_transition(INFINITY, tg_restart, "Unknown event", event);

    } else if (rc == target_rc) {
        passed = TRUE;
        crm_trace("Processed update to %s: %s", id, magic);
    }

    if (passed == FALSE) {
        if (update_failcount(event, event_node, rc, target_rc, transition_num == -1)) {
            /* Turns out this wasn't an lrm status refresh update aferall */
            stop_early = FALSE;
            desc = "failed";
        }
        crm_info("Detected action (%d.%d) %s.%d=%s: %s", transition_num, action, id, callid,
                 services_ocf_exitcode_str(rc), desc);
    }

  bail:
    free(update_te_uuid);
    return stop_early;
}
Ejemplo n.º 18
0
static void
tengine_stonith_notify(stonith_t * st, stonith_event_t * st_event)
{
    if(te_client_id == NULL) {
        te_client_id = crm_strdup_printf("%s.%d", crm_system_name, getpid());
    }

    if (st_event == NULL) {
        crm_err("Notify data not found");
        return;
    }

    crmd_notify_fencing_op(st_event);

    if (st_event->result == pcmk_ok && safe_str_eq("on", st_event->action)) {
        crm_notice("%s was successfully unfenced by %s (at the request of %s)",
                   st_event->target, st_event->executioner ? st_event->executioner : "<anyone>", st_event->origin);
                /* TODO: Hook up st_event->device */
        return;

    } else if (safe_str_eq("on", st_event->action)) {
        crm_err("Unfencing of %s by %s failed: %s (%d)",
                st_event->target, st_event->executioner ? st_event->executioner : "<anyone>",
                pcmk_strerror(st_event->result), st_event->result);
        return;

    } else if (st_event->result == pcmk_ok && crm_str_eq(st_event->target, fsa_our_uname, TRUE)) {
        crm_crit("We were allegedly just fenced by %s for %s!",
                 st_event->executioner ? st_event->executioner : "<anyone>", st_event->origin); /* Dumps blackbox if enabled */

        qb_log_fini(); /* Try to get the above log message to disk - somehow */

        /* Get out ASAP and do not come back up.
         *
         * Triggering a reboot is also not the worst idea either since
         * the rest of the cluster thinks we're safely down
         */

#ifdef RB_HALT_SYSTEM
        reboot(RB_HALT_SYSTEM);
#endif

        /*
         * If reboot() fails or is not supported, coming back up will
         * probably lead to a situation where the other nodes set our
         * status to 'lost' because of the fencing callback and will
         * discard subsequent election votes with:
         *
         * Election 87 (current: 5171, owner: 103): Processed vote from east-03 (Peer is not part of our cluster)
         *
         * So just stay dead, something is seriously messed up anyway.
         *
         */
        exit(100); /* None of our wrappers since we already called qb_log_fini() */
        return;
    }

    if (st_event->result == pcmk_ok &&
        safe_str_eq(st_event->operation, T_STONITH_NOTIFY_FENCE)) {
        st_fail_count_reset(st_event->target);
    }

    crm_notice("Peer %s was%s terminated (%s) by %s for %s: %s (ref=%s) by client %s",
               st_event->target, st_event->result == pcmk_ok ? "" : " not",
               st_event->action,
               st_event->executioner ? st_event->executioner : "<anyone>",
               st_event->origin, pcmk_strerror(st_event->result), st_event->id,
               st_event->client_origin ? st_event->client_origin : "<unknown>");

#if SUPPORT_CMAN
    if (st_event->result == pcmk_ok && is_cman_cluster()) {
        int local_rc = 0;
        int confirm = 0;
        char *target_copy = strdup(st_event->target);

        /* In case fenced hasn't noticed yet
         *
         * Any fencing that has been inititated will be completed by way of the fence_pcmk redirect
         */
        local_rc = fenced_external(target_copy);
        if (local_rc != 0) {
            crm_err("Could not notify CMAN that '%s' is now fenced: %d", st_event->target,
                    local_rc);
        } else {
            crm_notice("Notified CMAN that '%s' is now fenced", st_event->target);
        }

        /* In case fenced is already trying to shoot it */
        confirm = open("/var/run/cluster/fenced_override", O_NONBLOCK|O_WRONLY);
        if (confirm > 0) {
            int ignore = 0;
            int len = strlen(target_copy);

            errno = 0;
            local_rc = write(confirm, target_copy, len);
            ignore = write(confirm, "\n", 1);

            if(ignore < 0 && errno == EBADF) {
                crm_trace("CMAN not expecting %s to be fenced (yet)", st_event->target);

            } else if (local_rc < len) {
                crm_perror(LOG_ERR, "Confirmation of CMAN fencing event for '%s' failed: %d", st_event->target, local_rc);

            } else {
                fsync(confirm);
                crm_notice("Confirmed CMAN fencing event for '%s'", st_event->target);
            }
            close(confirm);
        }
        free(target_copy);
    }
#endif

    if (st_event->result == pcmk_ok) {
        crm_node_t *peer = crm_find_peer_full(0, st_event->target, CRM_GET_PEER_REMOTE | CRM_GET_PEER_CLUSTER);
        const char *uuid = NULL;
        gboolean we_are_executioner = safe_str_eq(st_event->executioner, fsa_our_uname);

        if (peer == NULL) {
            return;
        }

        uuid = crm_peer_uuid(peer);

        crm_trace("target=%s dc=%s", st_event->target, fsa_our_dc);
        if(AM_I_DC) {
            /* The DC always sends updates */
            send_stonith_update(NULL, st_event->target, uuid);

            if (st_event->client_origin && safe_str_neq(st_event->client_origin, te_client_id)) {

                /* Abort the current transition graph if it wasn't us
                 * that invoked stonith to fence someone
                 */
                crm_info("External fencing operation from %s fenced %s", st_event->client_origin, st_event->target);
                abort_transition(INFINITY, tg_restart, "External Fencing Operation", NULL);
            }

            /* Assume it was our leader if we dont currently have one */
        } else if (fsa_our_dc == NULL || safe_str_eq(fsa_our_dc, st_event->target)) {
            crm_notice("Target %s our leader %s (recorded: %s)",
                       fsa_our_dc ? "was" : "may have been", st_event->target,
                       fsa_our_dc ? fsa_our_dc : "<unset>");

            /* Given the CIB resyncing that occurs around elections,
             * have one node update the CIB now and, if the new DC is different,
             * have them do so too after the election
             */
            if (we_are_executioner) {
                send_stonith_update(NULL, st_event->target, uuid);
            }
            stonith_cleanup_list = g_list_append(stonith_cleanup_list, strdup(st_event->target));

        }

        crmd_peer_down(peer, TRUE);
     }
}
Ejemplo n.º 19
0
gboolean
group_unpack(resource_t * rsc, pe_working_set_t * data_set)
{
    xmlNode *xml_obj = rsc->xml;
    xmlNode *xml_native_rsc = NULL;
    group_variant_data_t *group_data = NULL;
    const char *group_ordered = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ORDERED);
    const char *group_colocated = g_hash_table_lookup(rsc->meta, "collocated");
    const char *clone_id = NULL;

    pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);

    group_data = calloc(1, sizeof(group_variant_data_t));
    group_data->num_children = 0;
    group_data->first_child = NULL;
    group_data->last_child = NULL;
    rsc->variant_opaque = group_data;

    group_data->ordered = TRUE;
    group_data->colocated = TRUE;

    if (group_ordered != NULL) {
        crm_str_to_boolean(group_ordered, &(group_data->ordered));
    }
    if (group_colocated != NULL) {
        crm_str_to_boolean(group_colocated, &(group_data->colocated));
    }

    clone_id = crm_element_value(rsc->xml, XML_RSC_ATTR_INCARNATION);

    for (xml_native_rsc = __xml_first_child(xml_obj); xml_native_rsc != NULL;
            xml_native_rsc = __xml_next(xml_native_rsc)) {
        if (crm_str_eq((const char *)xml_native_rsc->name, XML_CIB_TAG_RESOURCE, TRUE)) {
            resource_t *new_rsc = NULL;

            crm_xml_add(xml_native_rsc, XML_RSC_ATTR_INCARNATION, clone_id);
            if (common_unpack(xml_native_rsc, &new_rsc, rsc, data_set) == FALSE) {
                pe_err("Failed unpacking resource %s", crm_element_value(xml_obj, XML_ATTR_ID));
                if (new_rsc != NULL && new_rsc->fns != NULL) {
                    new_rsc->fns->free(new_rsc);
                }
            }

            group_data->num_children++;
            rsc->children = g_list_append(rsc->children, new_rsc);

            if (group_data->first_child == NULL) {
                group_data->first_child = new_rsc;
            }
            group_data->last_child = new_rsc;
            print_resource(LOG_DEBUG_3, "Added ", new_rsc, FALSE);
        }
    }

    if (group_data->num_children == 0) {
#if 0
        /* Bug #1287 */
        crm_config_err("Group %s did not have any children", rsc->id);
        return FALSE;
#else
        crm_config_warn("Group %s did not have any children", rsc->id);
        return TRUE;
#endif
    }

    pe_rsc_trace(rsc, "Added %d children to resource %s...", group_data->num_children, rsc->id);

    return TRUE;
}
Ejemplo n.º 20
0
static gboolean
check_action_definition(resource_t *rsc, node_t *active_node, crm_data_t *xml_op,
			pe_working_set_t *data_set)
{
	char *key = NULL;
	int interval = 0;
	const char *interval_s = NULL;
	
	gboolean did_change = FALSE;
	gboolean start_op = FALSE;

	crm_data_t *params_all = NULL;
	crm_data_t *params_restart = NULL;
	GHashTable *local_rsc_params = NULL;
	
	char *digest_all_calc = NULL;
	const char *digest_all = NULL;

	const char *restart_list = NULL;
	const char *digest_restart = NULL;
	char *digest_restart_calc = NULL;

	action_t *action = NULL;
	const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
	const char *op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION);

	CRM_CHECK(active_node != NULL, return FALSE);

	interval_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL);
	interval = crm_parse_int(interval_s, "0");
	/* we need to reconstruct the key because of the way we used to construct resource IDs */
	key = generate_op_key(rsc->id, task, interval);

	if(interval > 0) {
		crm_data_t *op_match = NULL;

		crm_debug_2("Checking parameters for %s", key);
		op_match = find_rsc_op_entry(rsc, key);

		if(op_match == NULL && data_set->stop_action_orphans) {
			/* create a cancel action */
			action_t *cancel = NULL;
			char *cancel_key = NULL;
			const char *call_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
			
			crm_info("Orphan action will be stopped: %s on %s",
				 key, active_node->details->uname);

			cancel_key = generate_op_key(
				rsc->id, CRMD_ACTION_CANCEL, interval);

			cancel = custom_action(
				rsc, cancel_key, CRMD_ACTION_CANCEL,
				active_node, FALSE, TRUE, data_set);

			add_hash_param(cancel->meta, XML_LRM_ATTR_TASK,     task);
			add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID,   call_id);
			add_hash_param(cancel->meta, XML_LRM_ATTR_INTERVAL, interval_s);

			custom_action_order(	
				rsc, stop_key(rsc), NULL,
				rsc, NULL, cancel,
				pe_order_optional, data_set);
			crm_free(key); key = NULL;
			return TRUE;

		} else if(op_match == NULL) {
			crm_debug("Orphan action detected: %s on %s",
				  key, active_node->details->uname);
			crm_free(key); key = NULL;
			return TRUE;
		}
	}

	action = custom_action(rsc, key, task, active_node, TRUE, FALSE, data_set);
	
	local_rsc_params = g_hash_table_new_full(
		g_str_hash, g_str_equal,
		g_hash_destroy_str, g_hash_destroy_str);
	
	unpack_instance_attributes(
		rsc->xml, XML_TAG_ATTR_SETS, active_node->details->attrs,
		local_rsc_params, NULL, data_set->now);
	
	params_all = create_xml_node(NULL, XML_TAG_PARAMS);
	g_hash_table_foreach(action->extra, hash2field, params_all);
	g_hash_table_foreach(rsc->parameters, hash2field, params_all);
	g_hash_table_foreach(action->meta, hash2metafield, params_all);
	g_hash_table_foreach(local_rsc_params, hash2field, params_all);

	filter_action_parameters(params_all, op_version);
	digest_all_calc = calculate_xml_digest(params_all, TRUE, FALSE);
	digest_all = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST);
	digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
	restart_list = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART);

	if(crm_str_eq(task, CRMD_ACTION_START, TRUE)) {
		start_op = TRUE;
	}
	
	if(start_op && digest_restart) {
		params_restart = copy_xml(params_all);
		if(restart_list) {
			filter_reload_parameters(params_restart, restart_list);
		}

		digest_restart_calc = calculate_xml_digest(params_restart, TRUE, FALSE);
		if(safe_str_neq(digest_restart_calc, digest_restart)) {
			did_change = TRUE;
			crm_log_xml_info(params_restart, "params:restart");
			crm_warn("Parameters to %s on %s changed: recorded %s vs. %s (restart:%s) %s",
				 key, active_node->details->uname,
				 crm_str(digest_restart), digest_restart_calc,
				 op_version, crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
			
			key = generate_op_key(rsc->id, task, interval);
			custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
			goto cleanup;
		}
	}

	if(safe_str_neq(digest_all_calc, digest_all)) {
		action_t *op = NULL;
		did_change = TRUE;
		crm_log_xml_info(params_all, "params:all");
 		crm_warn("Parameters to %s on %s changed: recorded %s vs. %s (all:%s) %s",
			 key, active_node->details->uname,
			 crm_str(digest_all), digest_all_calc, op_version,
			 crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
		
		key = generate_op_key(rsc->id, task, interval);
		op = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set);
		if(start_op && digest_restart) {
			op->allow_reload_conversion = TRUE;

		} else if(interval > 0) {
			custom_action_order(rsc, start_key(rsc), NULL,
					    NULL, crm_strdup(op->task), op,
					    pe_order_runnable_left, data_set);
		}
		
	}

  cleanup:
	free_xml(params_all);
	free_xml(params_restart);
	crm_free(digest_all_calc);
	crm_free(digest_restart_calc);
	g_hash_table_destroy(local_rsc_params);

	pe_free_action(action);
	
	return did_change;
}
Ejemplo n.º 21
0
static void
tengine_stonith_notify(stonith_t * st, const char *event, xmlNode * msg)
{
    int rc = -99;
    const char *origin = NULL;
    const char *target = NULL;
    const char *executioner = NULL;
    xmlNode *action = get_xpath_object("//st-data", msg, LOG_ERR);

    if (action == NULL) {
        crm_log_xml(LOG_ERR, "Notify data not found", msg);
        return;
    }

    crm_log_xml(LOG_DEBUG, "stonith_notify", msg);
    crm_element_value_int(msg, F_STONITH_RC, &rc);
    origin = crm_element_value(action, F_STONITH_ORIGIN);
    target = crm_element_value(action, F_STONITH_TARGET);
    executioner = crm_element_value(action, F_STONITH_DELEGATE);

    if (rc == stonith_ok && crm_str_eq(target, fsa_our_uname, TRUE)) {
        crm_err("We were alegedly just fenced by %s for %s!", executioner, origin);
        register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);

    } else if (rc == stonith_ok) {
        crm_info("Peer %s was terminated (%s) by %s for %s (ref=%s): %s",
                 target,
                 crm_element_value(action, F_STONITH_OPERATION),
                 executioner, origin,
                 crm_element_value(action, F_STONITH_REMOTE), stonith_error2string(rc));
    } else {
        crm_err("Peer %s could not be terminated (%s) by %s for %s (ref=%s): %s",
                target,
                crm_element_value(action, F_STONITH_OPERATION),
                executioner ? executioner : "<anyone>", origin,
                crm_element_value(action, F_STONITH_REMOTE), stonith_error2string(rc));
    }

#ifdef SUPPORT_CMAN
    if (rc == stonith_ok && is_cman_cluster()) {
        int local_rc = 0;
        int confirm = 0;
        char *target_copy = crm_strdup(target);

        /* In case fenced hasn't noticed yet */
        local_rc = fenced_external(target_copy);
        if (local_rc != 0) {
            crm_err("Could not notify CMAN that '%s' is now fenced: %d", target, local_rc);
        } else {
            crm_notice("Notified CMAN that '%s' is now fenced", target);
        }

        /* In case fenced is already trying to shoot it */
        confirm = open("/var/run/cluster/fenced_override", O_NONBLOCK|O_WRONLY);
        if (confirm) {
            int len = strlen(target_copy);

            errno = 0;
            local_rc = write(confirm, target_copy, len);
            write(confirm, "\n", 1);

            if(errno == EBADF) {
                crm_trace("CMAN not expecting %s to be fenced (yet)", target);

            } else if (local_rc < len) {
                crm_perror(LOG_ERR, "Confirmation of CMAN fencing event for '%s' failed: %d", target, local_rc);

            } else {
                fsync(confirm);
                crm_notice("Confirmed CMAN fencing event for '%s'", target);
            }
            close(confirm);
        }
    }
#endif

    if (rc == stonith_ok && safe_str_eq(target, origin)) {
        if (fsa_our_dc == NULL || safe_str_eq(fsa_our_dc, target)) {
            crm_notice("Target was our leader %s (recorded: %s)",
                       target, fsa_our_dc ? fsa_our_dc : "<unset>");
            /* Given the CIB resyncing that occurs around elections,
             * have one node update the CIB now and, if the new DC is different,
             * have them do so too after the election
             */
            if (safe_str_eq(executioner, fsa_our_uname)) {
                const char *uuid = get_uuid(target);

                send_stonith_update(NULL, target, uuid);
            } else {
                stonith_cleanup_list = g_list_append(stonith_cleanup_list, crm_strdup(target));
            }
        }
    }
}
Ejemplo n.º 22
0
crm_node_t *
crm_update_peer(const char *source, unsigned int id, uint64_t born, uint64_t seen, int32_t votes,
                uint32_t children, const char *uuid, const char *uname, const char *addr,
                const char *state)
{
#if SUPPORT_PLUGIN
    gboolean addr_changed = FALSE;
    gboolean votes_changed = FALSE;
#endif
    crm_node_t *node = NULL;

    id = get_corosync_id(id, uuid);
    node = crm_get_peer(id, uname);

    CRM_ASSERT(node != NULL);

    if (node->uuid == NULL) {
        if (is_openais_cluster()) {
            /* Yes, overrule whatever was passed in */
            crm_peer_uuid(node);

        } else if (uuid != NULL) {
            node->uuid = strdup(uuid);
        }
    }

    if (children > 0) {
        crm_update_peer_proc(source, node, children, state);
    }

    if (state != NULL) {
        crm_update_peer_state(source, node, state, seen);
    }
#if SUPPORT_HEARTBEAT
    if (born != 0) {
        node->born = born;
    }
#endif

#if SUPPORT_PLUGIN
    /* These were only used by the plugin */
    if (born != 0) {
        node->born = born;
    }

    if (votes > 0 && node->votes != votes) {
        votes_changed = TRUE;
        node->votes = votes;
    }

    if (addr != NULL) {
        if (node->addr == NULL || crm_str_eq(node->addr, addr, FALSE) == FALSE) {
            addr_changed = TRUE;
            free(node->addr);
            node->addr = strdup(addr);
        }
    }
    if (addr_changed || votes_changed) {
        crm_info("%s: Node %s: id=%u state=%s addr=%s%s votes=%d%s born=" U64T " seen=" U64T
                 " proc=%.32x", source, node->uname, node->id, node->state,
                 node->addr, addr_changed ? " (new)" : "", node->votes,
                 votes_changed ? " (new)" : "", node->born, node->last_seen, node->processes);
    }
#endif

    return node;
}
Ejemplo n.º 23
0
static void
tengine_stonith_notify(stonith_t * st, stonith_event_t * st_event)
{
    static char *client_id = NULL;
    if(client_id == NULL) {
        client_id = g_strdup_printf("%s.%d", crm_system_name, getpid());
    }

    if (st_event == NULL) {
        crm_err("Notify data not found");
        return;
    }

    if (st_event->result == pcmk_ok && crm_str_eq(st_event->target, fsa_our_uname, TRUE)) {
        crm_err("We were alegedly just fenced by %s for %s!", st_event->executioner,
                st_event->origin);
        register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);
        return;
    }

    if (st_event->result == pcmk_ok &&
        safe_str_eq(st_event->operation, T_STONITH_NOTIFY_FENCE)) {
        reset_st_fail_count(st_event->target);
    }

    crm_notice("Peer %s was%s terminated (%s) by %s for %s: %s (ref=%s) by client %s",
               st_event->target, st_event->result == pcmk_ok ? "" : " not",
               st_event->action,
               st_event->executioner ? st_event->executioner : "<anyone>",
               st_event->origin, pcmk_strerror(st_event->result), st_event->id,
               st_event->client_origin ? st_event->client_origin : "<unknown>");

#if SUPPORT_CMAN
    if (st_event->result == pcmk_ok && is_cman_cluster()) {
        int local_rc = 0;
        char *target_copy = strdup(st_event->target);

        /* In case fenced hasn't noticed yet
         *
         * Any fencing that has been inititated will be completed by way of the fence_pcmk redirect
         */
        local_rc = fenced_external(target_copy);
        if (local_rc != 0) {
            crm_err("Could not notify CMAN that '%s' is now fenced: %d", st_event->target,
                    local_rc);
        } else {
            crm_notice("Notified CMAN that '%s' is now fenced", st_event->target);
        }
        free(target_copy);
    }
#endif

     if (st_event->result == pcmk_ok) {
         const char *uuid = get_uuid(st_event->target);
        gboolean we_are_executioner = safe_str_eq(st_event->executioner, fsa_our_uname);

        crm_trace("target=%s dc=%s", st_event->target, fsa_our_dc);
        if(AM_I_DC) {
            /* The DC always sends updates */
            send_stonith_update(NULL, st_event->target, uuid);

            if (st_event->client_origin && safe_str_neq(st_event->client_origin, client_id)) {

                /* Abort the current transition graph if it wasn't us
                 * that invoked stonith to fence someone
                 */
                crm_info("External fencing operation from %s fenced %s", st_event->client_origin, st_event->target);
                abort_transition(INFINITY, tg_restart, "External Fencing Operation", NULL);
            }

            /* Assume it was our leader if we dont currently have one */
        } else if (fsa_our_dc == NULL || safe_str_eq(fsa_our_dc, st_event->target)) {
            crm_notice("Target %s our leader %s (recorded: %s)",
                       fsa_our_dc ? "was" : "may have been", st_event->target,
                       fsa_our_dc ? fsa_our_dc : "<unset>");

            /* Given the CIB resyncing that occurs around elections,
             * have one node update the CIB now and, if the new DC is different,
             * have them do so too after the election
             */
            if (we_are_executioner) {
                send_stonith_update(NULL, st_event->target, uuid);
            }
            stonith_cleanup_list = g_list_append(stonith_cleanup_list, strdup(st_event->target));

        }
     }
}
Ejemplo n.º 24
0
void
cib_notify_client(gpointer key, gpointer value, gpointer user_data)
{

	IPC_Channel *ipc_client = NULL;
	xmlNode *update_msg = user_data;
	cib_client_t *client = value;
	const char *type = NULL;
	gboolean is_pre = FALSE;
	gboolean is_post = FALSE;	
	gboolean is_confirm = FALSE;
	gboolean is_replace = FALSE;
	gboolean is_diff = FALSE;
	gboolean do_send = FALSE;

	int qlen = 0;
	int max_qlen = 500;
	
	CRM_DEV_ASSERT(client != NULL);
	CRM_DEV_ASSERT(update_msg != NULL);

	type = crm_element_value(update_msg, F_SUBTYPE);
	CRM_DEV_ASSERT(type != NULL);

	if(client == NULL) {
		crm_warn("Skipping NULL client");
		return;

	} else if(client->channel == NULL) {
		crm_warn("Skipping client with NULL channel");
		return;

	} else if(client->name == NULL) {
		crm_debug_2("Skipping unnammed client / comamnd channel");
		return;
	}
	
	if(safe_str_eq(type, T_CIB_PRE_NOTIFY)) {
		is_pre = TRUE;
		
	} else if(safe_str_eq(type, T_CIB_POST_NOTIFY)) {
		is_post = TRUE;

	} else if(safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) {
		is_confirm = TRUE;

	} else if(safe_str_eq(type, T_CIB_DIFF_NOTIFY)) {
		is_diff = TRUE;

	} else if(safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) {
		is_replace = TRUE;
	}	

	ipc_client = client->channel;
	if (FALSE == crm_str_eq(client->channel_name, "remote", FALSE)) {
	    qlen = ipc_client->send_queue->current_qlen;
	    max_qlen = ipc_client->send_queue->max_qlen;
	}

#if 1
	/* get_chan_status() causes memory to be allocated that isnt free'd
	 *   until the message is read (which messes up the memory stats) 
	 */
	if(client->pre_notify && is_pre) {
		if(qlen < (int)(0.4 * max_qlen)) {
			do_send = TRUE;
		} else {
			crm_warn("Throttling pre-notifications due to"
				 " high load: queue=%d (max=%d)",
				 qlen, max_qlen);
		}
		 
	} else if(client->post_notify && is_post) {
		if(qlen < (int)(0.7 * max_qlen)) {
			do_send = TRUE;
		} else {
			crm_warn("Throttling post-notifications due to"
				 " extreme load: queue=%d (max=%d)",
				 qlen, max_qlen);
		}

		/* these are critical */
	} else
#endif
		if(client->diffs && is_diff) {
		do_send = TRUE;

	} else if(client->confirmations && is_confirm) {
		do_send = TRUE;

	} else if(client->replace && is_replace) {
		do_send = TRUE;
	}

	if(do_send) {
		if (crm_str_eq(client->channel_name, "remote", FALSE)) {
		    crm_debug("Sent %s notification to client %s/%s",
			      is_confirm?"Confirmation":is_post?"Post":"Pre",
			      client->name, client->id);
		    cib_send_remote_msg(client->channel, update_msg, client->encrypted);

		} else if(ipc_client->send_queue->current_qlen >= ipc_client->send_queue->max_qlen) {
			/* We never want the CIB to exit because our client is slow */
			crm_crit("%s-notification of client %s/%s failed - queue saturated",
				 is_confirm?"Confirmation":is_post?"Post":"Pre",
				 client->name, client->id);
			
		} else if(send_ipc_message(ipc_client, update_msg) == FALSE) {
			crm_warn("Notification of client %s/%s failed",
				 client->name, client->id);
		}
	}
}
gboolean
cib_action_update(crm_action_t *action, int status, int op_rc)
{
	char *op_id  = NULL;
	char *code   = NULL;
	char *digest = NULL;
	xmlNode *tmp      = NULL;
	xmlNode *params   = NULL;
	xmlNode *state    = NULL;
	xmlNode *rsc      = NULL;
	xmlNode *xml_op   = NULL;
	xmlNode *action_rsc = NULL;

	enum cib_errors rc = cib_ok;

	const char *name   = NULL;
	const char *value  = NULL;
	const char *rsc_id = NULL;
	const char *task   = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
	const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
	const char *task_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
	const char *target_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID);

	int call_options = cib_quorum_override|cib_scope_local;

	if(status == LRM_OP_PENDING) {
	    crm_debug("%s %d: Recording pending operation %s on %s",
		     crm_element_name(action->xml), action->id, task_uuid, target);
	} else {
	    crm_warn("%s %d: %s on %s timed out",
		     crm_element_name(action->xml), action->id, task_uuid, target);
	}
	
	action_rsc = find_xml_node(action->xml, XML_CIB_TAG_RESOURCE, TRUE);
	if(action_rsc == NULL) {
		return FALSE;
	}
	
	rsc_id = ID(action_rsc);
	CRM_CHECK(rsc_id != NULL,
		  crm_log_xml_err(action->xml, "Bad:action");
		  return FALSE);
	
/*
  update the CIB

<node_state id="hadev">
      <lrm>
        <lrm_resources>
          <lrm_resource id="rsc2" last_op="start" op_code="0" target="hadev"/>
*/

	state = create_xml_node(NULL, XML_CIB_TAG_STATE);

	crm_xml_add(state, XML_ATTR_UUID,  target_uuid);
	crm_xml_add(state, XML_ATTR_UNAME, target);
	
	rsc = create_xml_node(state, XML_CIB_TAG_LRM);
	crm_xml_add(rsc, XML_ATTR_ID, target_uuid);

	rsc = create_xml_node(rsc,   XML_LRM_TAG_RESOURCES);
	rsc = create_xml_node(rsc,   XML_LRM_TAG_RESOURCE);
	crm_xml_add(rsc, XML_ATTR_ID, rsc_id);

	name = XML_ATTR_TYPE;
	value = crm_element_value(action_rsc, name);
	crm_xml_add(rsc, name, value);
	name = XML_AGENT_ATTR_CLASS;
	value = crm_element_value(action_rsc, name);
	crm_xml_add(rsc, name, value);
	name = XML_AGENT_ATTR_PROVIDER;
	value = crm_element_value(action_rsc, name);
	crm_xml_add(rsc, name, value);

	xml_op = create_xml_node(rsc, XML_LRM_TAG_RSC_OP);	
	crm_xml_add(xml_op, XML_ATTR_ID, task);
	
	op_id = generate_op_key(rsc_id, task, action->interval);
	crm_xml_add(xml_op, XML_ATTR_ID, op_id);
	crm_free(op_id);
	
	crm_xml_add_int(xml_op, XML_LRM_ATTR_CALLID, -1);
	crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task);
	crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
	crm_xml_add_int(xml_op, XML_LRM_ATTR_OPSTATUS, status);
	crm_xml_add_int(xml_op, XML_LRM_ATTR_INTERVAL, action->interval);
	crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op_rc);
	crm_xml_add(xml_op, XML_ATTR_ORIGIN, __FUNCTION__);

	if(crm_str_eq(task, CRMD_ACTION_MIGRATED, TRUE)) {
	    char *key = crm_meta_name("migrate_source_uuid");
	    xmlNode *attrs = first_named_child(action->xml, XML_TAG_ATTRS);
	    const char *host = crm_element_value(attrs, key);
	    CRM_CHECK(host != NULL, crm_log_xml_err(action->xml, "Bad Op"));
	    crm_xml_add(xml_op, CRMD_ACTION_MIGRATED, host);
	    crm_free(key);
	}	
	
	code = generate_transition_key(
	    transition_graph->id, action->id, get_target_rc(action), te_uuid);
	crm_xml_add(xml_op, XML_ATTR_TRANSITION_KEY, code);
	crm_free(code);

	code = generate_transition_magic(
		crm_element_value(xml_op, XML_ATTR_TRANSITION_KEY), status, op_rc);
	crm_xml_add(xml_op,  XML_ATTR_TRANSITION_MAGIC, code);
	crm_free(code);

	tmp = find_xml_node(action->xml, "attributes", TRUE);
	params = create_xml_node(NULL, XML_TAG_PARAMS);
	copy_in_properties(params, tmp);
	
	filter_action_parameters(params, CRM_FEATURE_SET);
	digest = calculate_xml_digest(params, TRUE, FALSE);

	/* info for now as this area has been problematic to debug */
	crm_debug("Calculated digest %s for %s (%s)\n", 
		  digest, ID(xml_op),
		  crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
	crm_log_xml(LOG_DEBUG,  "digest:source", params);

	crm_xml_add(xml_op, XML_LRM_ATTR_OP_DIGEST, digest);
	crm_free(digest);
	free_xml(params);
	
	crm_debug_3("Updating CIB with \"%s\" (%s): %s %s on %s",
		  status<0?"new action":XML_ATTR_TIMEOUT,
		  crm_element_name(action->xml), crm_str(task), rsc_id, target);
	
	rc = fsa_cib_conn->cmds->update(
		fsa_cib_conn, XML_CIB_TAG_STATUS, state, call_options);

	crm_debug_2("Updating CIB with %s action %d: %s on %s (call_id=%d)",
		  op_status2text(status), action->id, task_uuid, target, rc);

	add_cib_op_callback(fsa_cib_conn, rc, FALSE, NULL, cib_action_updated);
	free_xml(state);

	action->sent_update = TRUE;
	
	if(rc < cib_ok) {
		return FALSE;
	}

	return TRUE;
}
Ejemplo n.º 26
0
/*	A_ELECTION_COUNT	*/
void
do_election_count_vote(long long action,
                       enum crmd_fsa_cause cause,
                       enum crmd_fsa_state cur_state,
                       enum crmd_fsa_input current_input, fsa_data_t * msg_data)
{
    struct timeval your_age;
    int age;
    int election_id = -1;
    int log_level = LOG_INFO;
    gboolean use_born_on = FALSE;
    gboolean done = FALSE;
    gboolean we_loose = FALSE;
    const char *op = NULL;
    const char *vote_from = NULL;
    const char *your_version = NULL;
    const char *election_owner = NULL;
    const char *reason = "unknown";
    crm_node_t *our_node = NULL, *your_node = NULL;
    ha_msg_input_t *vote = fsa_typed_data(fsa_dt_ha_msg);

    static time_t last_election_loss = 0;

    /* if the membership copy is NULL we REALLY shouldnt be voting
     * the question is how we managed to get here.
     */

    CRM_CHECK(msg_data != NULL, return);
    CRM_CHECK(crm_peer_cache != NULL, return);
    CRM_CHECK(vote != NULL, crm_err("Bogus data from %s", msg_data->origin); return);
    CRM_CHECK(vote->msg != NULL, crm_err("Bogus data from %s", msg_data->origin); return);

    your_age.tv_sec = 0;
    your_age.tv_usec = 0;

    op = crm_element_value(vote->msg, F_CRM_TASK);
    vote_from = crm_element_value(vote->msg, F_CRM_HOST_FROM);
    your_version = crm_element_value(vote->msg, F_CRM_VERSION);
    election_owner = crm_element_value(vote->msg, F_CRM_ELECTION_OWNER);
    crm_element_value_int(vote->msg, F_CRM_ELECTION_ID, &election_id);
    crm_element_value_int(vote->msg, F_CRM_ELECTION_AGE_S, (int *)&(your_age.tv_sec));
    crm_element_value_int(vote->msg, F_CRM_ELECTION_AGE_US, (int *)&(your_age.tv_usec));

    CRM_CHECK(vote_from != NULL, vote_from = fsa_our_uname);

    your_node = crm_get_peer(0, vote_from);
    our_node = crm_get_peer(0, fsa_our_uname);

    if (voted == NULL) {
        crm_debug("Created voted hash");
        voted = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                      g_hash_destroy_str, g_hash_destroy_str);
    }

    if (is_heartbeat_cluster()) {
        use_born_on = TRUE;
    } else if (is_classic_ais_cluster()) {
        use_born_on = TRUE;
    }

    age = crm_compare_age(your_age);

    if (cur_state == S_STARTING) {
        reason = "Still starting";
        we_loose = TRUE;

    } else if (our_node == NULL || crm_is_peer_active(our_node) == FALSE) {
        reason = "We are not part of the cluster";
        log_level = LOG_ERR;
        we_loose = TRUE;

    } else if (election_id != current_election_id && crm_str_eq(fsa_our_uuid, election_owner, TRUE)) {
        log_level = LOG_DEBUG_2;
        reason = "Superceeded";
        done = TRUE;

    } else if (your_node == NULL || crm_is_peer_active(your_node) == FALSE) {
        /* Possibly we cached the message in the FSA queue at a point that it wasn't */
        reason = "Peer is not part of our cluster";
        log_level = LOG_WARNING;
        done = TRUE;

    } else if (crm_str_eq(op, CRM_OP_NOVOTE, TRUE)) {
        char *op_copy = strdup(op);
        char *uname_copy = strdup(vote_from);

        CRM_ASSERT(crm_str_eq(fsa_our_uuid, election_owner, TRUE));

        /* update the list of nodes that have voted */
        g_hash_table_replace(voted, uname_copy, op_copy);
        reason = "Recorded";
        done = TRUE;

    } else if (crm_str_eq(vote_from, fsa_our_uname, TRUE)) {
        char *op_copy = strdup(op);
        char *uname_copy = strdup(vote_from);

        CRM_ASSERT(crm_str_eq(fsa_our_uuid, election_owner, TRUE));

        /* update ourselves in the list of nodes that have voted */
        g_hash_table_replace(voted, uname_copy, op_copy);
        reason = "Recorded";
        done = TRUE;

    } else if (compare_version(your_version, CRM_FEATURE_SET) < 0) {
        reason = "Version";
        we_loose = TRUE;

    } else if (compare_version(your_version, CRM_FEATURE_SET) > 0) {
        reason = "Version";

    } else if (age < 0) {
        reason = "Uptime";
        we_loose = TRUE;

    } else if (age > 0) {
        reason = "Uptime";

        /* TODO: Check for y(our) born < 0 */
    } else if (use_born_on && your_node->born < our_node->born) {
        reason = "Born";
        we_loose = TRUE;

    } else if (use_born_on && your_node->born > our_node->born) {
        reason = "Born";

    } else if (fsa_our_uname == NULL) {
        reason = "Unknown host name";
        we_loose = TRUE;

    } else if (strcasecmp(fsa_our_uname, vote_from) > 0) {
        reason = "Host name";
        we_loose = TRUE;

    } else {
        reason = "Host name";
        CRM_ASSERT(strcmp(fsa_our_uname, vote_from) != 0);
/* cant happen...
 *	} else if(strcasecmp(fsa_our_uname, vote_from) == 0) {
 *
 * default...
 *	} else { // strcasecmp(fsa_our_uname, vote_from) < 0
 *		we win
 */
    }

    if (done) {
        do_crm_log(log_level + 1, "Election %d (current: %d, owner: %s): Processed %s from %s (%s)",
                   election_id, current_election_id, election_owner, op, vote_from, reason);

    } else if (we_loose) {
        xmlNode *novote = create_request(CRM_OP_NOVOTE, NULL, vote_from,
                                         CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL);

        do_crm_log(log_level, "Election %d (owner: %s) lost: %s from %s (%s)",
                   election_id, election_owner, op, vote_from, reason);
        update_dc(NULL);

        crm_timer_stop(election_timeout);
        if (fsa_input_register & R_THE_DC) {
            crm_trace("Give up the DC to %s", vote_from);
            register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL);

        } else if (cur_state != S_STARTING) {
            crm_trace("We werent the DC anyway");
            register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
        }

        crm_xml_add(novote, F_CRM_ELECTION_OWNER, election_owner);
        crm_xml_add_int(novote, F_CRM_ELECTION_ID, election_id);

        send_cluster_message(crm_get_peer(0, vote_from), crm_msg_crmd, novote, TRUE);
        free_xml(novote);

        fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local);

        last_election_loss = time(NULL);

    } else {
        do_crm_log(log_level, "Election %d (owner: %s) pass: %s from %s (%s)",
                   election_id, election_owner, op, vote_from, reason);

        if (last_election_loss) {
            time_t tm_now = time(NULL);

            if (tm_now - last_election_loss < (time_t) loss_dampen) {
                crm_info("Election %d ignore: We already lost an election less than %ds ago (%s)",
                         election_id, loss_dampen, ctime(&last_election_loss));
                update_dc(NULL);
                return;
            }
            last_election_loss = 0;
        }

        register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
        g_hash_table_destroy(voted);
        voted = NULL;
    }
}
Ejemplo n.º 27
0
crm_node_t *
crm_update_peer(const char *source, unsigned int id, uint64_t born, uint64_t seen, int32_t votes, uint32_t children,
                const char *uuid, const char *uname, const char *addr, const char *state)
{
    gboolean addr_changed = FALSE;
    gboolean state_changed = FALSE;
    gboolean procs_changed = FALSE;
    gboolean votes_changed = FALSE;

    crm_node_t *node = NULL;

    id = get_corosync_id(id, uuid);

    CRM_CHECK(uname != NULL || id > 0, return NULL);
    CRM_ASSERT(crm_peer_cache != NULL);
    CRM_ASSERT(crm_peer_id_cache != NULL);

    node = crm_get_peer(id, uname);
    if (node == NULL) {
        crm_trace("No node found for %d/%s", id, uname);
        node = crm_new_peer(id, uname);

        CRM_LOG_ASSERT(node != NULL);
        if (node == NULL) {
            crm_err("Insufficient information to create node %d/%s", id, uname);
            return NULL;
        }

        /* do it now so we don't get '(new)' everywhere */
        node->votes = votes;
        node->processes = children;
        if (addr) {
            node->addr = strdup(addr);
        }
    }

    if (votes > 0 && node->votes != votes) {
        votes_changed = TRUE;
        node->votes = votes;
    }

    if (node->uuid == NULL) {
        if (is_openais_cluster()) {
            /* Yes, overrule whatever was passed in */
            node->uuid = get_corosync_uuid(id, uname);

        } else if (uuid != NULL) {
            node->uuid = strdup(uuid);
        }
    }

    if (children > 0 && children != node->processes) {
        uint32_t last = node->processes;

        node->processes = children;
        procs_changed = TRUE;

        if (crm_status_callback) {
            crm_status_callback(crm_status_processes, node, &last);
        }
    }

    if (born != 0) {
        node->born = born;
    }

    if (state != NULL && safe_str_neq(node->state, state)) {
        char *last = node->state;

        node->state = strdup(state);
        state_changed = TRUE;

        if (crm_status_callback) {
            crm_status_callback(crm_status_nstate, node, last);
        }
        free(last);
    }

    if (seen != 0 && safe_str_eq(node->state, CRM_NODE_MEMBER)) {
        node->last_seen = seen;
    }

    if (addr != NULL) {
        if (node->addr == NULL || crm_str_eq(node->addr, addr, FALSE) == FALSE) {
            addr_changed = TRUE;
            free(node->addr);
            node->addr = strdup(addr);
        }
    }

    if (state_changed || addr_changed || votes_changed) {
        do_crm_log_unlikely(state_changed?LOG_NOTICE:LOG_INFO,
                   "%s: Node %s: id=%u state=%s%s addr=%s%s votes=%d%s born=" U64T " seen=" U64T
                   " proc=%.32x%s", source, node->uname, node->id, node->state, state_changed ? " (new)" : "",
                   node->addr, addr_changed ? " (new)" : "", node->votes,
                   votes_changed ? " (new)" : "", node->born, node->last_seen, node->processes,
                   procs_changed ? " (new)" : "");

    } else if (procs_changed) {
        crm_debug("%s: Node %s: id=%u seen=" U64T
                  " proc=%.32x (new)", source, node->uname, node->id, node->last_seen, node->processes);
    }

    return node;
}
Ejemplo n.º 28
0
void
abort_transition_graph(int abort_priority, enum transition_action abort_action,
                       const char *abort_text, xmlNode * reason, const char *fn, int line)
{
    int log_level = LOG_INFO;
    const char *magic = NULL;

    CRM_CHECK(transition_graph != NULL, return);

    if (reason) {
        int diff_add_updates = 0;
        int diff_add_epoch = 0;
        int diff_add_admin_epoch = 0;

        int diff_del_updates = 0;
        int diff_del_epoch = 0;
        int diff_del_admin_epoch = 0;
        xmlNode *diff = get_xpath_object("//" F_CIB_UPDATE_RESULT "//diff", reason, LOG_DEBUG_2);

        magic = crm_element_value(reason, XML_ATTR_TRANSITION_MAGIC);

        if (diff) {
            cib_diff_version_details(diff,
                                     &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
                                     &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
            if (crm_str_eq(TYPE(reason), XML_CIB_TAG_NVPAIR, TRUE)) {
                do_crm_log(log_level,
                           "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, name=%s, value=%s, magic=%s, cib=%d.%d.%d) : %s",
                           fn, line, transition_graph->complete, TYPE(reason), ID(reason),
                           NAME(reason), VALUE(reason), magic ? magic : "NA", diff_add_admin_epoch,
                           diff_add_epoch, diff_add_updates, abort_text);
            } else {
                do_crm_log(log_level,
                           "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, magic=%s, cib=%d.%d.%d) : %s",
                           fn, line, transition_graph->complete, TYPE(reason), ID(reason),
                           magic ? magic : "NA", diff_add_admin_epoch, diff_add_epoch,
                           diff_add_updates, abort_text);
            }

        } else {
            do_crm_log(log_level,
                       "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, magic=%s) : %s",
                       fn, line, transition_graph->complete, TYPE(reason), ID(reason),
                       magic ? magic : "NA", abort_text);
        }

    } else {
        do_crm_log(log_level,
                   "%s:%d - Triggered transition abort (complete=%d) : %s",
                   fn, line, transition_graph->complete, abort_text);
    }

    switch (fsa_state) {
    case S_STARTING:
    case S_PENDING:
    case S_NOT_DC:
    case S_HALT:
    case S_ILLEGAL:
    case S_STOPPING:
    case S_TERMINATE:
        do_crm_log(log_level,
                   "Abort suppressed: state=%s (complete=%d)",
                   fsa_state2string(fsa_state), transition_graph->complete);
        return;
    default:
        break;
    }

    if (magic == NULL && reason != NULL) {
        crm_log_xml(log_level + 1, "Cause", reason);
    }

    /* Make sure any queued calculations are discarded ASAP */
    crm_free(fsa_pe_ref);
    fsa_pe_ref = NULL;

    if (transition_graph->complete) {
        if (transition_timer->period_ms > 0) {
            crm_timer_start(transition_timer);
        } else {
            register_fsa_input(C_FSA_INTERNAL, I_PE_CALC, NULL);
        }
        return;
    }

    update_abort_priority(transition_graph, abort_priority, abort_action, abort_text);

    mainloop_set_trigger(transition_trigger);
}
/*	A_ELECTION_COUNT	*/
enum election_result
election_count_vote(election_t *e, xmlNode *vote, bool can_win)
{
    int age = 0;
    int election_id = -1;
    int log_level = LOG_INFO;
    gboolean use_born_on = FALSE;
    gboolean done = FALSE;
    gboolean we_loose = FALSE;
    const char *op = NULL;
    const char *from = NULL;
    const char *reason = "unknown";
    const char *election_owner = NULL;
    crm_node_t *our_node = NULL, *your_node = NULL;

    static int election_wins = 0;

    xmlNode *novote = NULL;
    time_t tm_now = time(NULL);
    static time_t expires = 0;
    static time_t last_election_loss = 0;

    /* if the membership copy is NULL we REALLY shouldn't be voting
     * the question is how we managed to get here.
     */

    CRM_CHECK(vote != NULL, return election_error);

    if(e == NULL) {
        crm_info("Not voting in election: not initialized");
        return election_lost;

    } else if(crm_peer_cache == NULL) {
        crm_info("Not voting in election: no peer cache");
        return election_lost;
    }

    op = crm_element_value(vote, F_CRM_TASK);
    from = crm_element_value(vote, F_CRM_HOST_FROM);
    election_owner = crm_element_value(vote, F_CRM_ELECTION_OWNER);
    crm_element_value_int(vote, F_CRM_ELECTION_ID, &election_id);

    your_node = crm_get_peer(0, from);
    our_node = crm_get_peer(0, e->uname);

    if (e->voted == NULL) {
        crm_debug("Created voted hash");
        e->voted = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                         g_hash_destroy_str, g_hash_destroy_str);
    }

    if (is_heartbeat_cluster()) {
        use_born_on = TRUE;
    } else if (is_classic_ais_cluster()) {
        use_born_on = TRUE;
    }

    if(can_win == FALSE) {
        reason = "Not eligible";
        we_loose = TRUE;

    } else if (our_node == NULL || crm_is_peer_active(our_node) == FALSE) {
        reason = "We are not part of the cluster";
        log_level = LOG_ERR;
        we_loose = TRUE;

    } else if (election_id != e->count && crm_str_eq(our_node->uuid, election_owner, TRUE)) {
        log_level = LOG_TRACE;
        reason = "Superseded";
        done = TRUE;

    } else if (your_node == NULL || crm_is_peer_active(your_node) == FALSE) {
        /* Possibly we cached the message in the FSA queue at a point that it wasn't */
        reason = "Peer is not part of our cluster";
        log_level = LOG_WARNING;
        done = TRUE;

    } else if (crm_str_eq(op, CRM_OP_NOVOTE, TRUE)) {
        char *op_copy = strdup(op);
        char *uname_copy = strdup(from);

        CRM_ASSERT(crm_str_eq(our_node->uuid, election_owner, TRUE));

        /* update the list of nodes that have voted */
        g_hash_table_replace(e->voted, uname_copy, op_copy);
        reason = "Recorded";
        done = TRUE;

    } else {
        struct timeval your_age;
        const char *your_version = crm_element_value(vote, F_CRM_VERSION);
        int tv_sec = 0;
        int tv_usec = 0;

        crm_element_value_int(vote, F_CRM_ELECTION_AGE_S, &tv_sec);
        crm_element_value_int(vote, F_CRM_ELECTION_AGE_US, &tv_usec);

        your_age.tv_sec = tv_sec;
        your_age.tv_usec = tv_usec;

        age = crm_compare_age(your_age);
        if (crm_str_eq(from, e->uname, TRUE)) {
            char *op_copy = strdup(op);
            char *uname_copy = strdup(from);

            CRM_ASSERT(crm_str_eq(our_node->uuid, election_owner, TRUE));

            /* update ourselves in the list of nodes that have voted */
            g_hash_table_replace(e->voted, uname_copy, op_copy);
            reason = "Recorded";
            done = TRUE;

        } else if (compare_version(your_version, CRM_FEATURE_SET) < 0) {
            reason = "Version";
            we_loose = TRUE;

        } else if (compare_version(your_version, CRM_FEATURE_SET) > 0) {
            reason = "Version";

        } else if (age < 0) {
            reason = "Uptime";
            we_loose = TRUE;

        } else if (age > 0) {
            reason = "Uptime";

            /* TODO: Check for y(our) born < 0 */
        } else if (use_born_on && your_node->born < our_node->born) {
            reason = "Born";
            we_loose = TRUE;

        } else if (use_born_on && your_node->born > our_node->born) {
            reason = "Born";

        } else if (e->uname == NULL) {
            reason = "Unknown host name";
            we_loose = TRUE;

        } else if (strcasecmp(e->uname, from) > 0) {
            reason = "Host name";
            we_loose = TRUE;

        } else {
            reason = "Host name";
            CRM_ASSERT(strcasecmp(e->uname, from) < 0);
/* can't happen...
 *	} else if(strcasecmp(e->uname, from) == 0) {
 *
 */
        }
    }

    if (expires < tm_now) {
        election_wins = 0;
        expires = tm_now + STORM_INTERVAL;

    } else if (done == FALSE && we_loose == FALSE) {
        int peers = 1 + g_hash_table_size(crm_peer_cache);

        /* If every node has to vote down every other node, thats N*(N-1) total elections
         * Allow some leway before _really_ complaining
         */
        election_wins++;
        if (election_wins > (peers * peers)) {
            crm_warn("Election storm detected: %d elections in %d seconds", election_wins,
                     STORM_INTERVAL);
            election_wins = 0;
            expires = tm_now + STORM_INTERVAL;
            crm_write_blackbox(0, NULL);
        }
    }

    if (done) {
        do_crm_log(log_level + 1, "Election %d (current: %d, owner: %s): Processed %s from %s (%s)",
                   election_id, e->count, election_owner, op, from, reason);
        return e->state;

    } else if(we_loose == FALSE) {
        do_crm_log(log_level, "Election %d (owner: %s) pass: %s from %s (%s)",
                   election_id, election_owner, op, from, reason);

        if (last_election_loss == 0
            || tm_now - last_election_loss > (time_t) loss_dampen) {

            last_election_loss = 0;
            election_timeout_stop(e);

            /* Start a new election by voting down this, and other, peers */
            e->state = election_start;
            return e->state;
        }

        crm_info("Election %d ignore: We already lost an election less than %ds ago (%s)",
                 election_id, loss_dampen, ctime(&last_election_loss));
    }

    novote = create_request(CRM_OP_NOVOTE, NULL, from,
                            CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL);

    do_crm_log(log_level, "Election %d (owner: %s) lost: %s from %s (%s)",
               election_id, election_owner, op, from, reason);

    election_timeout_stop(e);

    crm_xml_add(novote, F_CRM_ELECTION_OWNER, election_owner);
    crm_xml_add_int(novote, F_CRM_ELECTION_ID, election_id);

    send_cluster_message(your_node, crm_msg_crmd, novote, TRUE);
    free_xml(novote);

    last_election_loss = tm_now;
    e->state = election_lost;
    return e->state;
}
Ejemplo n.º 30
0
int
cib_process_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff, gboolean privileged)
{
    xmlNode *input = NULL;
    xmlNode *output = NULL;
    xmlNode *result_cib = NULL;
    xmlNode *current_cib = NULL;

#if ENABLE_ACL
    xmlNode *filtered_current_cib = NULL;
#endif

    int call_type = 0;
    int call_options = 0;
    int log_level = LOG_DEBUG_4;

    const char *op = NULL;
    const char *section = NULL;

    int rc = pcmk_ok;
    int rc2 = pcmk_ok;

    gboolean send_r_notify = FALSE;
    gboolean global_update = FALSE;
    gboolean config_changed = FALSE;
    gboolean manage_counters = TRUE;

    CRM_ASSERT(cib_status == pcmk_ok);

    *reply = NULL;
    *cib_diff = NULL;
    current_cib = the_cib;

    /* Start processing the request... */
    op = crm_element_value(request, F_CIB_OPERATION);
    crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
    rc = cib_get_operation_id(op, &call_type);

    if (rc == pcmk_ok && privileged == FALSE) {
        rc = cib_op_can_run(call_type, call_options, privileged, global_update);
    }

    rc2 = cib_op_prepare(call_type, request, &input, &section);
    if (rc == pcmk_ok) {
        rc = rc2;
    }

    if (rc != pcmk_ok) {
        crm_trace("Call setup failed: %s", pcmk_strerror(rc));
        goto done;

    } else if (cib_op_modifies(call_type) == FALSE) {
#if ENABLE_ACL
        if (acl_enabled(config_hash) == FALSE
            || acl_filter_cib(request, current_cib, current_cib, &filtered_current_cib) == FALSE) {
            rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
                                section, request, input, FALSE, &config_changed,
                                current_cib, &result_cib, NULL, &output);

        } else if (filtered_current_cib == NULL) {
            crm_debug("Pre-filtered the entire cib");
            rc = -EACCES;

        } else {
            crm_debug("Pre-filtered the queried cib according to the ACLs");
            rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
                                section, request, input, FALSE, &config_changed,
                                filtered_current_cib, &result_cib, NULL, &output);
        }
#else
        rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
                            section, request, input, FALSE, &config_changed,
                            current_cib, &result_cib, NULL, &output);

#endif

        CRM_CHECK(result_cib == NULL, free_xml(result_cib));
        goto done;
    }

    /* Handle a valid write action */
    global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE));
    if (global_update) {
        manage_counters = FALSE;
        call_options |= cib_force_diff;

        CRM_CHECK(call_type == 3 || call_type == 4, crm_err("Call type: %d", call_type);
                  crm_log_xml_err(request, "bad op"));
    }
#ifdef SUPPORT_PRENOTIFY
    if ((call_options & cib_inhibit_notify) == 0) {
        cib_pre_notify(call_options, op, the_cib, input);
    }
#endif

    if (rc == pcmk_ok) {
        if (call_options & cib_inhibit_bcast) {
            /* skip */
            crm_trace("Skipping update: inhibit broadcast");
            manage_counters = FALSE;
        }

        rc = cib_perform_op(op, call_options, cib_op_func(call_type), FALSE,
                            section, request, input, manage_counters, &config_changed,
                            current_cib, &result_cib, cib_diff, &output);

#if ENABLE_ACL
        if (acl_enabled(config_hash) == TRUE
            && acl_check_diff(request, current_cib, result_cib, *cib_diff) == FALSE) {
            rc = -EACCES;
        }
#endif

        if (rc == pcmk_ok && config_changed) {
            time_t now;
            char *now_str = NULL;
            const char *validation = crm_element_value(result_cib, XML_ATTR_VALIDATION);

            if (validation) {
                int current_version = get_schema_version(validation);
                int support_version = get_schema_version("pacemaker-1.1");

                /* Once the later schemas support the "update-*" attributes, change "==" to ">=" -- Changed */
                if (current_version >= support_version) {
                    const char *origin = crm_element_value(request, F_ORIG);

                    crm_xml_replace(result_cib, XML_ATTR_UPDATE_ORIG,
                                    origin ? origin : cib_our_uname);
                    crm_xml_replace(result_cib, XML_ATTR_UPDATE_CLIENT,
                                    crm_element_value(request, F_CIB_CLIENTNAME));
#if ENABLE_ACL
                    crm_xml_replace(result_cib, XML_ATTR_UPDATE_USER,
                                    crm_element_value(request, F_CIB_USER));
#endif
                }
            }

            now = time(NULL);
            now_str = ctime(&now);
            now_str[24] = EOS;  /* replace the newline */
            crm_xml_replace(result_cib, XML_CIB_ATTR_WRITTEN, now_str);
        }

        if (manage_counters == FALSE) {
            config_changed = cib_config_changed(current_cib, result_cib, cib_diff);
        }

        /* Always write to disk for replace ops,
         * this negates the need to detect ordering changes
         */
        if (config_changed == FALSE && crm_str_eq(CIB_OP_REPLACE, op, TRUE)) {
            config_changed = TRUE;
        }
    }

    if (rc == pcmk_ok && (call_options & cib_dryrun) == 0) {
        rc = activateCibXml(result_cib, config_changed, op);
        if (rc == pcmk_ok && cib_internal_config_changed(*cib_diff)) {
            cib_read_config(config_hash, result_cib);
        }

        if (crm_str_eq(CIB_OP_REPLACE, op, TRUE)) {
            if (section == NULL) {
                send_r_notify = TRUE;

            } else if (safe_str_eq(section, XML_TAG_CIB)) {
                send_r_notify = TRUE;

            } else if (safe_str_eq(section, XML_CIB_TAG_NODES)) {
                send_r_notify = TRUE;

            } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) {
                send_r_notify = TRUE;
            }

        } else if (crm_str_eq(CIB_OP_ERASE, op, TRUE)) {
            send_r_notify = TRUE;
        }

    } else if (rc == -pcmk_err_dtd_validation) {
        if (output != NULL) {
            crm_log_xml_info(output, "cib:output");
            free_xml(output);
        }
#if ENABLE_ACL
        {
            xmlNode *filtered_result_cib = NULL;

            if (acl_enabled(config_hash) == FALSE
                || acl_filter_cib(request, current_cib, result_cib,
                                  &filtered_result_cib) == FALSE) {
                output = result_cib;

            } else {
                crm_debug("Filtered the result cib for output according to the ACLs");
                output = filtered_result_cib;
                if (result_cib != NULL) {
                    free_xml(result_cib);
                }
            }
        }
#else
        output = result_cib;
#endif

    } else {
        free_xml(result_cib);
    }

    if ((call_options & cib_inhibit_notify) == 0) {
        const char *call_id = crm_element_value(request, F_CIB_CALLID);
        const char *client = crm_element_value(request, F_CIB_CLIENTNAME);

#ifdef SUPPORT_POSTNOTIFY
        cib_post_notify(call_options, op, input, rc, the_cib);
#endif
        cib_diff_notify(call_options, client, call_id, op, input, rc, *cib_diff);
    }

    if (send_r_notify) {
        const char *origin = crm_element_value(request, F_ORIG);

        cib_replace_notify(origin, the_cib, rc, *cib_diff);
    }

    if (rc != pcmk_ok) {
        log_level = LOG_DEBUG_4;
        if (rc == -pcmk_err_dtd_validation && global_update) {
            log_level = LOG_WARNING;
            crm_log_xml_info(input, "cib:global_update");
        }

    } else if (config_changed) {
        log_level = LOG_DEBUG_3;
        if (cib_is_master) {
            log_level = LOG_NOTICE;
        }

    } else if (cib_is_master) {
        log_level = LOG_DEBUG_2;
    }

    log_xml_diff(log_level, *cib_diff, "cib:diff");

  done:
    if ((call_options & cib_discard_reply) == 0) {
        *reply = cib_construct_reply(request, output, rc);
        crm_log_xml_trace(*reply, "cib:reply");
    }
#if ENABLE_ACL
    if (filtered_current_cib != NULL) {
        free_xml(filtered_current_cib);
    }
#endif

    if (call_type >= 0) {
        cib_op_cleanup(call_type, call_options, &input, &output);
    }
    return rc;
}