Пример #1
0
static GList *
__xml_acl_parse_entry(xmlNode *acl_top, xmlNode *acl_entry, GList *acls)
{
    xmlNode *child = NULL;

    for (child = __xml_first_child(acl_entry); child;
         child = __xml_next(child)) {
        const char *tag = crm_element_name(child);
        const char *kind = crm_element_value(child, XML_ACL_ATTR_KIND);

        if (strcmp(XML_ACL_TAG_PERMISSION, tag) == 0){
            tag = kind;
        }

        crm_trace("Processing %s %p", tag, child);
        if (tag == NULL) {
            CRM_ASSERT(tag != NULL);

        } else if (strcmp(XML_ACL_TAG_ROLE_REF, tag) == 0
                   || strcmp(XML_ACL_TAG_ROLE_REFv1, tag) == 0) {
            const char *ref_role = crm_element_value(child, XML_ATTR_ID);

            if (ref_role) {
                xmlNode *role = NULL;

                for (role = __xml_first_child(acl_top); role;
                     role = __xml_next(role)) {
                    if (!strcmp(XML_ACL_TAG_ROLE, (const char *) role->name)) {
                        const char *role_id = crm_element_value(role,
                                                                XML_ATTR_ID);

                        if (role_id && strcmp(ref_role, role_id) == 0) {
                            crm_debug("Unpacking referenced role: %s", role_id);
                            acls = __xml_acl_parse_entry(acl_top, role, acls);
                            break;
                        }
                    }
                }
            }

        } else if (strcmp(XML_ACL_TAG_READ, tag) == 0) {
            acls = __xml_acl_create(child, acls, xpf_acl_read);

        } else if (strcmp(XML_ACL_TAG_WRITE, tag) == 0) {
            acls = __xml_acl_create(child, acls, xpf_acl_write);

        } else if (strcmp(XML_ACL_TAG_DENY, tag) == 0) {
            acls = __xml_acl_create(child, acls, xpf_acl_deny);

        } else {
            crm_warn("Unknown ACL entry: %s/%s", tag, kind);
        }
    }

    return acls;
}
Пример #2
0
void
attrd_peer_message(crm_node_t *peer, xmlNode *xml)
{
    const char *op = crm_element_value(xml, F_ATTRD_TASK);
    const char *election_op = crm_element_value(xml, F_CRM_TASK);
    const char *host = crm_element_value(xml, F_ATTRD_HOST);
    bool peer_won = FALSE;

    if (election_op) {
        attrd_handle_election_op(peer, xml);
        return;
    }

    if (attrd_shutting_down()) {
        /* If we're shutting down, we want to continue responding to election
         * ops as long as we're a cluster member (because our vote may be
         * needed). Ignore all other messages.
         */
        return;
    }

    peer_won = attrd_check_for_new_writer(peer, xml);

    if (safe_str_eq(op, ATTRD_OP_UPDATE) || safe_str_eq(op, ATTRD_OP_UPDATE_BOTH) || safe_str_eq(op, ATTRD_OP_UPDATE_DELAY)) {
        attrd_peer_update(peer, xml, host, FALSE);

    } else if (safe_str_eq(op, ATTRD_OP_SYNC)) {
        attrd_peer_sync(peer, xml);

    } else if (safe_str_eq(op, ATTRD_OP_PEER_REMOVE)) {
        attrd_peer_remove(host, TRUE, peer->uname);

    } else if (safe_str_eq(op, ATTRD_OP_CLEAR_FAILURE)) {
        /* It is not currently possible to receive this as a peer command,
         * but will be, if we one day enable propagating this operation.
         */
        attrd_peer_clear_failure(peer, xml);

    } else if (safe_str_eq(op, ATTRD_OP_SYNC_RESPONSE)
              && safe_str_neq(peer->uname, attrd_cluster->uname)) {
        xmlNode *child = NULL;

        crm_info("Processing %s from %s", op, peer->uname);

        /* Clear the seen flag for attribute processing held only in the own node. */
        if (peer_won) {
            clear_attribute_value_seen();
        }

        for (child = __xml_first_child(xml); child != NULL; child = __xml_next(child)) {
            host = crm_element_value(child, F_ATTRD_HOST);
            attrd_peer_update(peer, child, host, TRUE);
        }

        if (peer_won) {
            /* Synchronize if there is an attribute held only by own node that Writer does not have. */
            attrd_current_only_attribute_update(peer, xml);
        }
    }
}
Пример #3
0
int
cib_process_delete(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
    xmlNode *obj_root = NULL;

    crm_trace("Processing \"%s\" event", op);

    if (options & cib_xpath) {
        return cib_process_xpath(op, options, section, req, input,
                                 existing_cib, result_cib, answer);
    }

    if (input == NULL) {
        crm_err("Cannot perform modification with no data");
        return -EINVAL;
    }

    obj_root = get_object_root(section, *result_cib);
    if(safe_str_eq(crm_element_name(input), section)) {
        xmlNode *child = NULL;
        for(child = __xml_first_child(input); child; child = __xml_next(child)) {
            if (replace_xml_child(NULL, obj_root, child, TRUE) == FALSE) {
                crm_trace("No matching object to delete: %s=%s", child->name, ID(child));
            }
        }

    } else if (replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) {
            crm_trace("No matching object to delete: %s=%s", input->name, ID(input));
    }

    return pcmk_ok;
}
Пример #4
0
int
do_find_node_list(xmlNode * xml_node)
{
    int found = 0;
    xmlNode *node = NULL;
    xmlNode *nodes = get_object_root(XML_CIB_TAG_NODES, xml_node);

    for (node = __xml_first_child(nodes); node != NULL; node = __xml_next(node)) {
        if (crm_str_eq((const char *)node->name, XML_CIB_TAG_NODE, TRUE)) {

            if (BASH_EXPORT) {
                printf("export %s=%s\n",
                       crm_element_value(node, XML_ATTR_UNAME),
                       crm_element_value(node, XML_ATTR_ID));
            } else {
                printf("%s node: %s (%s)\n",
                       crm_element_value(node, XML_ATTR_TYPE),
                       crm_element_value(node, XML_ATTR_UNAME),
                       crm_element_value(node, XML_ATTR_ID));
            }
            found++;
        }
    }

    if (found == 0) {
        printf("NO nodes configured\n");
    }

    return found;
}
Пример #5
0
static void process_resource_updates(
    const char *node, xmlNode *xml, xmlNode *change, const char *op, const char *xpath) 
{
    xmlNode *cIter = NULL;
    xmlNode *rsc = NULL;
    xmlNode *rsc_op = NULL;
    int num_resources = 0;

    if(xml == NULL) {
        return;

    } else if(strcmp((const char*)xml->name, XML_CIB_TAG_LRM) == 0) {
        xml = first_named_child(xml, XML_LRM_TAG_RESOURCES);
        crm_trace("Got %p in %s", xml, XML_CIB_TAG_LRM);
    }

    CRM_ASSERT(strcmp((const char*)xml->name, XML_LRM_TAG_RESOURCES) == 0);

    for(cIter = xml->children; cIter; cIter = cIter->next) {
        num_resources++;
    }

    if(num_resources > 1) {
        /*
         * Check for and fast-track the processing of LRM refreshes
         * In large clusters this can result in _huge_ speedups
         *
         * Unfortunately we can only do so when there are no pending actions
         * Otherwise we could miss updates we're waiting for and stall
         *
         */

        crm_debug("Detected LRM refresh - %d resources updated", num_resources);
        crm_log_xml_trace(change, "lrm-refresh");
        abort_transition(INFINITY, tg_restart, "LRM Refresh", NULL);
        return;
    }

    for (rsc = __xml_first_child(xml); rsc != NULL; rsc = __xml_next(rsc)) {
        crm_trace("Processing %s", ID(rsc));
        for (rsc_op = __xml_first_child(rsc); rsc_op != NULL; rsc_op = __xml_next(rsc_op)) {
            crm_trace("Processing %s", ID(rsc_op));
            process_graph_event(rsc_op, node);
        }
    }
}
Пример #6
0
static void
process_lrm_resource_diff(xmlNode *lrm_resource, const char *node)
{
    for (xmlNode *rsc_op = __xml_first_child(lrm_resource); rsc_op != NULL;
         rsc_op = __xml_next(rsc_op)) {
        process_graph_event(rsc_op, node);
    }
}
Пример #7
0
static void
process_status_diff(xmlNode *status, xmlNode *change, const char *op,
                    const char *xpath)
{
    for (xmlNode *state = __xml_first_child(status); state != NULL;
         state = __xml_next(state)) {
        process_node_state_diff(state, change, op, xpath);
    }
}
Пример #8
0
void
print_xml_diff(FILE * where, xmlNode * diff)
{
    char *buffer = NULL;
    xmlNode *child = NULL;
    int max = 1024, len = 0;
    gboolean is_first = TRUE;
    xmlNode *added = find_xml_node(diff, "diff-added", FALSE);
    xmlNode *removed = find_xml_node(diff, "diff-removed", FALSE);

    is_first = TRUE;
    for (child = __xml_first_child(removed); child != NULL; child = __xml_next(child)) {
        len = 0;
        max = 1024;
        crm_free(buffer);
        crm_malloc0(buffer, max);

        if (is_first) {
            is_first = FALSE;
        } else {
            fprintf(where, " --- \n");
        }

        CRM_CHECK(dump_data_element(0, &buffer, &max, &len, "-", child, TRUE) >= 0, continue);
        fprintf(where, "%s", buffer);
    }

    is_first = TRUE;
    for (child = __xml_first_child(added); child != NULL; child = __xml_next(child)) {
        len = 0;
        max = 1024;
        crm_free(buffer);
        crm_malloc0(buffer, max);

        if (is_first) {
            is_first = FALSE;
        } else {
            fprintf(where, " +++ \n");
        }

        CRM_CHECK(dump_data_element(0, &buffer, &max, &len, "+", child, TRUE) >= 0, continue);
        fprintf(where, "%s", buffer);
    }
}
Пример #9
0
static int
delete_cib_object(xmlNode * parent, xmlNode * delete_spec)
{
    const char *object_name = NULL;
    const char *object_id = NULL;
    xmlNode *equiv_node = NULL;
    int result = pcmk_ok;

    if (delete_spec != NULL) {
        object_name = crm_element_name(delete_spec);
    }
    object_id = crm_element_value(delete_spec, XML_ATTR_ID);

    crm_trace("Processing: <%s id=%s>", crm_str(object_name), crm_str(object_id));

    if (delete_spec == NULL) {
        result = -EINVAL;

    } else if (parent == NULL) {
        result = -EINVAL;

    } else if (object_id == NULL) {
        /*  placeholder object */
        equiv_node = find_xml_node(parent, object_name, FALSE);

    } else {
        equiv_node = find_entity(parent, object_name, object_id);
    }

    if (result != pcmk_ok) {
        ;                       /* nothing */

    } else if (equiv_node == NULL) {
        result = pcmk_ok;

    } else if (xml_has_children(delete_spec) == FALSE) {
        /*  only leaves are deleted */
        crm_debug("Removing leaf: <%s id=%s>", crm_str(object_name), crm_str(object_id));
        free_xml(equiv_node);
        equiv_node = NULL;

    } else {
        xmlNode *child = NULL;

        for (child = __xml_first_child(delete_spec); child != NULL; child = __xml_next(child)) {
            int tmp_result = delete_cib_object(equiv_node, child);

            /*  only the first error is likely to be interesting */
            if (tmp_result != pcmk_ok && result == pcmk_ok) {
                result = tmp_result;
            }
        }
    }

    return result;
}
Пример #10
0
static void
process_remote_node_action(crm_action_t *action, xmlNode *event)
{
    xmlNode *child = NULL;

    /* The whole point of this function is to detect when a remote-node
     * is integrated into the cluster, and abort the transition if that remote-node
     * was fenced earlier in the transition. This allows a new transition to be
     * generated so resources can be placed on the new node.
     */

    if (crm_remote_peer_cache_size() == 0) {
        return;
    } else if (action->type != action_type_rsc) {
        return;
    } else if (action->failed || action->confirmed == FALSE) {
        return;
    } else if (safe_str_neq(crm_element_value(action->xml, XML_LRM_ATTR_TASK), "start")) {
        return;
    }

    for (child = __xml_first_child(action->xml); child != NULL; child = __xml_next(child)) {
        const char *provider;
        const char *type;
        const char *rsc;
        crm_node_t *remote_peer;

        if (safe_str_neq(crm_element_name(child), XML_CIB_TAG_RESOURCE)) {
            continue;
        }

        provider = crm_element_value(child, XML_AGENT_ATTR_PROVIDER);
        type = crm_element_value(child, XML_ATTR_TYPE);
        rsc = ID(child);

        if (safe_str_neq(provider, "pacemaker") || safe_str_neq(type, "remote") || rsc == NULL) {
            break;
        }

        remote_peer = crm_get_peer_full(0, rsc, CRM_GET_PEER_REMOTE);
        if (remote_peer == NULL) {
            break;
        }

        /* A remote node will be placed in the "lost" state after
         * it has been successfully fenced.  After successfully connecting
         * to a remote-node after being fenced, we need to abort the transition
         * so resources can be placed on the newly integrated remote-node */
        if (safe_str_eq(remote_peer->state, CRM_NODE_LOST)) {
            abort_transition(INFINITY, tg_restart, "Remote-node re-discovered.", event);
        }

        return;
    }
}
Пример #11
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));
            }
        }
    }
}
Пример #12
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);
    }
}
Пример #13
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;
}
Пример #14
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);
    }
}
Пример #15
0
void
pcmk__post_process_acl(xmlNode *xml)
{
    xmlNode *cIter = __xml_first_child(xml);
    xml_private_t *p = xml->_private;

    if (is_set(p->flags, xpf_created)) {
        xmlAttr *xIter = NULL;
        char *path = xml_get_path(xml);

        /* Always allow new scaffolding (e.g. node with no attributes or only an
         * 'id'), except in the ACLs section
         */

        for (xIter = xml->properties; xIter != NULL; xIter = xIter->next) {
            const char *prop_name = (const char *)xIter->name;

            if (!strcmp(prop_name, XML_ATTR_ID)
                && !strstr(path, "/"XML_CIB_TAG_ACLS"/")) {
                /* Delay the acl check */
                continue;

            } else if (pcmk__check_acl(xml, NULL, xpf_acl_write)) {
                crm_trace("Creation of %s=%s is allowed",
                          crm_element_name(xml), ID(xml));
                break;

            } else {
                crm_trace("Cannot add new node %s at %s",
                          crm_element_name(xml), path);

                if (xml != xmlDocGetRootElement(xml->doc)) {
                    xmlUnlinkNode(xml);
                    xmlFreeNode(xml);
                }
                free(path);
                return;
            }
        }
        free(path);
    }

    while (cIter != NULL) {
        xmlNode *child = cIter;
        cIter = __xml_next(cIter); /* In case it is free'd */
        pcmk__post_process_acl(child);
    }
}
Пример #16
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;
}
Пример #17
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;
}
Пример #18
0
/*!
 * \brief Retrieve XML attributes as a hash table
 *
 * Given an XML element, this will look for any \<attributes> element child,
 * creating a hash table of (newly allocated string) name/value pairs taken
 * first from the attributes element's NAME=VALUE XML attributes, and then
 * from any \<param name=NAME value=VALUE> children of attributes.
 *
 * \param[in]  XML node to parse
 *
 * \return Hash table with name/value pairs
 * \note It is the caller's responsibility to free the result using
 *       \c g_hash_table_destroy().
 */
GHashTable *
xml2list(xmlNode *parent)
{
    xmlNode *child = NULL;
    xmlAttrPtr pIter = NULL;
    xmlNode *nvpair_list = NULL;
    GHashTable *nvpair_hash = crm_str_table_new();

    CRM_CHECK(parent != NULL, return nvpair_hash);

    nvpair_list = find_xml_node(parent, XML_TAG_ATTRS, FALSE);
    if (nvpair_list == NULL) {
        crm_trace("No attributes in %s", crm_element_name(parent));
        crm_log_xml_trace(parent, "No attributes for resource op");
    }

    crm_log_xml_trace(nvpair_list, "Unpacking");

    for (pIter = pcmk__first_xml_attr(nvpair_list); pIter != NULL;
         pIter = pIter->next) {

        const char *p_name = (const char *)pIter->name;
        const char *p_value = pcmk__xml_attr_value(pIter);

        crm_trace("Added %s=%s", p_name, p_value);

        g_hash_table_insert(nvpair_hash, strdup(p_name), strdup(p_value));
    }

    for (child = __xml_first_child(nvpair_list); child != NULL;
         child = __xml_next(child)) {

        if (strcmp((const char *)child->name, XML_TAG_PARAM) == 0) {
            const char *key = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
            const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);

            crm_trace("Added %s=%s", key, value);
            if (key != NULL && value != NULL) {
                g_hash_table_insert(nvpair_hash, strdup(key), strdup(value));
            }
        }
    }

    return nvpair_hash;
}
Пример #19
0
void
pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
{
#if ENABLE_ACL
    xml_private_t *p = NULL;

    if ((target == NULL) || (target->doc == NULL)
        || (target->doc->_private == NULL)) {
        return;
    }

    p = target->doc->_private;
    if (pcmk_acl_required(user) == FALSE) {
        crm_trace("no acls needed for '%s'", user);

    } else if (p->acls == NULL) {
        xmlNode *acls = get_xpath_object("//" XML_CIB_TAG_ACLS,
                                         source, LOG_TRACE);

        free(p->user);
        p->user = strdup(user);

        if (acls) {
            xmlNode *child = NULL;

            for (child = __xml_first_child(acls); child;
                 child = __xml_next(child)) {
                const char *tag = crm_element_name(child);

                if (!strcmp(tag, XML_ACL_TAG_USER)
                    || !strcmp(tag, XML_ACL_TAG_USERv1)) {
                    const char *id = crm_element_value(child, XML_ATTR_ID);

                    if (id && strcmp(id, user) == 0) {
                        crm_debug("Unpacking ACLs for %s", id);
                        p->acls = __xml_acl_parse_entry(acls, child, p->acls);
                    }
                }
            }
        }
    }
#endif
}
Пример #20
0
/*!
 * \internal
 * \brief Convert xml fence-history to a hash-table like stonith_remote_op_list
 *
 * \param[in] history   Fence-history in xml
 *
 * \return Fence-history as hash-table
 */
static GHashTable *
stonith_xml_history_to_list(xmlNode *history)
{
    xmlNode *xml_op = NULL;
    GHashTable *rv = NULL;

    init_stonith_remote_op_hash_table(&rv);

    CRM_LOG_ASSERT(rv != NULL);

    for (xml_op = __xml_first_child(history); xml_op != NULL;
         xml_op = __xml_next(xml_op)) {
        remote_fencing_op_t *op = NULL;
        char *id = crm_element_value_copy(xml_op, F_STONITH_REMOTE_OP_ID);
        int completed, state;

        if (!id) {
            crm_warn("History to convert to hashtable has no id in entry");
            continue;
        }

        crm_trace("Attaching op %s to hashtable", id);

        op = calloc(1, sizeof(remote_fencing_op_t));

        op->id = id;
        op->target = crm_element_value_copy(xml_op, F_STONITH_TARGET);
        op->action = crm_element_value_copy(xml_op, F_STONITH_ACTION);
        op->originator = crm_element_value_copy(xml_op, F_STONITH_ORIGIN);
        op->delegate = crm_element_value_copy(xml_op, F_STONITH_DELEGATE);
        op->client_name = crm_element_value_copy(xml_op, F_STONITH_CLIENTNAME);
        crm_element_value_int(xml_op, F_STONITH_DATE, &completed);
        op->completed = (time_t) completed;
        crm_element_value_int(xml_op, F_STONITH_STATE, &state);
        op->state = (enum op_state) state;

        g_hash_table_replace(rv, id, op);
        CRM_LOG_ASSERT(g_hash_table_lookup(rv, id) != NULL);
    }

    return rv;
}
Пример #21
0
static void
process_resource_updates(const char *node, xmlNode *xml, xmlNode *change,
                         const char *op, const char *xpath)
{
    xmlNode *rsc = NULL;

    if (xml == NULL) {
        return;

    } else if (strcmp((const char*)xml->name, XML_CIB_TAG_LRM) == 0) {
        xml = first_named_child(xml, XML_LRM_TAG_RESOURCES);
        crm_trace("Got %p in %s", xml, XML_CIB_TAG_LRM);
    }

    CRM_ASSERT(strcmp((const char*)xml->name, XML_LRM_TAG_RESOURCES) == 0);

    /*
     * Updates by, or in response to, TE actions will never contain updates
     * for more than one resource at a time, so such updates indicate an
     * LRM refresh.
     *
     * In that case, start a new transition rather than check each result
     * individually, which can result in _huge_ speedups in large clusters.
     *
     * Unfortunately, we can only do so when there are no pending actions.
     * Otherwise, we could mistakenly throw away those results here, and
     * the cluster will stall waiting for them and time out the operation.
     */
    if ((transition_graph->pending == 0)
        && xml->children && xml->children->next) {

        crm_log_xml_trace(change, "lrm-refresh");
        abort_transition(INFINITY, tg_restart, "History refresh", NULL);
        return;
    }

    for (rsc = __xml_first_child(xml); rsc != NULL; rsc = __xml_next(rsc)) {
        crm_trace("Processing %s", ID(rsc));
        process_lrm_resource_diff(rsc, node);
    }
}
Пример #22
0
gboolean
test_rule(xmlNode * rule, GHashTable * node_hash, enum rsc_role_e role, crm_time_t * now)
{
    xmlNode *expr = NULL;
    gboolean test = TRUE;
    gboolean empty = TRUE;
    gboolean passed = TRUE;
    gboolean do_and = TRUE;
    const char *value = NULL;

    rule = expand_idref(rule, NULL);
    value = crm_element_value(rule, XML_RULE_ATTR_BOOLEAN_OP);
    if (safe_str_eq(value, "or")) {
        do_and = FALSE;
        passed = FALSE;
    }

    crm_trace("Testing rule %s", ID(rule));
    for (expr = __xml_first_child(rule); expr != NULL; expr = __xml_next_element(expr)) {
        test = test_expression(expr, node_hash, role, now);
        empty = FALSE;

        if (test && do_and == FALSE) {
            crm_trace("Expression %s/%s passed", ID(rule), ID(expr));
            return TRUE;

        } else if (test == FALSE && do_and) {
            crm_trace("Expression %s/%s failed", ID(rule), ID(expr));
            return FALSE;
        }
    }

    if (empty) {
        crm_err("Invalid Rule %s: rules must contain at least one expression", ID(rule));
    }

    crm_trace("Rule %s %s", ID(rule), passed ? "passed" : "failed");
    return passed;
}
Пример #23
0
/* rc = TRUE if orig_cib has been filtered
 * That means '*result' rather than 'xml' should be exploited afterwards
 */
static bool
__xml_purge_attributes(xmlNode *xml)
{
    xmlNode *child = NULL;
    xmlAttr *xIter = NULL;
    bool readable_children = FALSE;
    xml_private_t *p = xml->_private;

    if (__xml_acl_mode_test(p->flags, xpf_acl_read)) {
        crm_trace("%s[@id=%s] is readable", crm_element_name(xml), ID(xml));
        return TRUE;
    }

    xIter = xml->properties;
    while (xIter != NULL) {
        xmlAttr *tmp = xIter;
        const char *prop_name = (const char *)xIter->name;

        xIter = xIter->next;
        if (strcmp(prop_name, XML_ATTR_ID) == 0) {
            continue;
        }

        xmlUnsetProp(xml, tmp->name);
    }

    child = __xml_first_child(xml);
    while ( child != NULL ) {
        xmlNode *tmp = child;

        child = __xml_next(child);
        readable_children |= __xml_purge_attributes(tmp);
    }

    if (readable_children == FALSE) {
        free_xml(xml); /* Nothing readable under here, purge completely */
    }
    return readable_children;
}
Пример #24
0
void
cli_resource_print_cts_constraints(pe_working_set_t * data_set)
{
    xmlNode *xml_obj = NULL;
    xmlNode *lifetime = NULL;
    xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input);

    for (xml_obj = __xml_first_child(cib_constraints); xml_obj != NULL;
         xml_obj = __xml_next(xml_obj)) {
        const char *id = crm_element_value(xml_obj, XML_ATTR_ID);

        if (id == NULL) {
            continue;
        }

        lifetime = first_named_child(xml_obj, "lifetime");

        if (test_ruleset(lifetime, NULL, data_set->now) == FALSE) {
            continue;
        }

        if (safe_str_eq(XML_CONS_TAG_RSC_DEPEND, crm_element_name(xml_obj))) {
            printf("Constraint %s %s %s %s %s %s %s\n",
                   crm_element_name(xml_obj),
                   cons_string(crm_element_value(xml_obj, XML_ATTR_ID)),
                   cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE)),
                   cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET)),
                   cons_string(crm_element_value(xml_obj, XML_RULE_ATTR_SCORE)),
                   cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_ROLE)),
                   cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET_ROLE)));

        } else if (safe_str_eq(XML_CONS_TAG_RSC_LOCATION, crm_element_name(xml_obj))) {
            /* unpack_location(xml_obj, data_set); */
        }
    }
}
Пример #25
0
/*!
 * \internal
 * \brief Parse node UUID from search result
 *
 * \param[in]  result     XML search result
 * \param[out] uuid       If non-NULL, where to store parsed UUID
 * \param[out] is_remote  If non-NULL, set TRUE if result is remote node
 *
 * \return pcmk_ok if UUID was successfully parsed, -ENXIO otherwise
 */
static int
get_uuid_from_result(xmlNode *result, char **uuid, int *is_remote)
{
    int rc = -ENXIO;
    const char *tag;
    const char *parsed_uuid = NULL;
    int parsed_is_remote = FALSE;

    if (result == NULL) {
        return rc;
    }

    /* If there are multiple results, the first is sufficient */
    tag = (const char *) (result->name);
    if (safe_str_eq(tag, "xpath-query")) {
        result = __xml_first_child(result);
        tag = (const char *) (result->name);
    }

    if (safe_str_eq(tag, XML_CIB_TAG_NODE)) {
        /* Result is <node> tag from <nodes> section */

        if (safe_str_eq(crm_element_value(result, XML_ATTR_TYPE), "remote")) {
            parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
            parsed_is_remote = TRUE;
        } else {
            parsed_uuid = ID(result);
            parsed_is_remote = FALSE;
        }

    } else if (safe_str_eq(tag, XML_CIB_TAG_RESOURCE)) {
        /* Result is <primitive> for ocf:pacemaker:remote resource */

        parsed_uuid = ID(result);
        parsed_is_remote = TRUE;

    } else if (safe_str_eq(tag, XML_CIB_TAG_NVPAIR)) {
        /* Result is remote-node parameter of <primitive> for guest node */

        parsed_uuid = crm_element_value(result, XML_NVPAIR_ATTR_VALUE);
        parsed_is_remote = TRUE;

    } else if (safe_str_eq(tag, XML_CIB_TAG_STATE)) {
        /* Result is <node_state> tag from <status> section */

        parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
        crm_element_value_int(result, F_ATTRD_IS_REMOTE, &parsed_is_remote);
    }

    if (parsed_uuid) {
        if (uuid) {
            *uuid = strdup(parsed_uuid);
        }
        if (is_remote) {
            *is_remote = parsed_is_remote;
        }
        rc = pcmk_ok;
    }

    return rc;
}
Пример #26
0
/**
 * This is the main function to send a trap to tell a resource's status is changed.
 * This function is called when a change occurs on the cib information.
 * First, it parses a received xml message, and if the msg tells that the status of
 * a resource changes, it sends a trap to SNMP manager via Net-SNMP daemon.
 * Note1: It sends a trap when the resouce [stopped|started|been Slave|been Master].
 *        And it sends a trap only when the execution of RA method is succeeded.
 * Note2: If an error occurs in this function, set the variable "err_occurs" to tell
 *        that to the handler. (see: handle_cib_msg())
 */
static void
hbagentv2_update_diff(const char *event, crm_data_t *msg)
{

    /*implement parsing the diff and send a trap */
	/*
    const char *op = NULL;
	*/
    crm_data_t *diff = NULL;
    const char *set_name = NULL;

    crm_data_t *change_set = NULL;
    crm_data_t *lrm_rsc = NULL;
    const char *node_id    = NULL;
    const char *rsc_id    = NULL;
    const char *rsc_op_id    = NULL;
    const char *rc_code = NULL;
    const char *t_magic = NULL;
    const char *operation = NULL;
    char tmp_op_str[MAX_OP_STR_LEN];
    char tmp_rc_str[MAX_RCCODE_STR_LEN];
    char *tmp = tmp_op_str;

#if HAVE_DECL___XML_NEXT
    crm_data_t *node_state = NULL;
#endif

    /* Initialize err flag. */
    err_occurs = 0;

    if (!msg) {
        cl_log(LOG_ERR, "cib message is NULL.");
        err_occurs = 1;
        return;
    }
	/*
    op = cl_get_string(msg, F_CIB_OPERATION);
	*/
    diff = get_message_xml(msg, F_CIB_UPDATE_RESULT);
    if (!diff) {
        cl_log(LOG_ERR, "update result is NULL.");
        return;
    }

    /* for debug */
    /*
    {
        FILE * fp;
        fp = fopen("/tmp/msgdiff.out", "a");
        debugPrint(diff, 0, fp);
        fclose(fp);
    }
    */

    /*
     * start to get the following information from difference of cib xml.
     *   <lrm_rsc_op operation="xxx" rc_code="yyy">
     */

    /* get the head pointer of <status> */
    set_name = "diff-added"; /* we need the cib info only which have been updated. */
    change_set = find_xml_node(diff, set_name, FALSE);
    change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE);
    change_set = find_xml_node(change_set, XML_CIB_TAG_STATUS, FALSE);
    if (!change_set) {
        /* There is no information of <status> */
        free_xml(diff);
        return;
    }

#if !HAVE_DECL___XML_NEXT
    xml_child_iter_filter(
        change_set, node_state, XML_CIB_TAG_STATE,
#else
    for(node_state = __xml_first_child(change_set); node_state != NULL; node_state = __xml_next(node_state)) {
        crm_data_t *lrm_rsc_op = NULL;

    if(STRNCMP_CONST((const char *)node_state->name, XML_CIB_TAG_STATE) != 0) {
        continue;
    }
#endif

        /* get the node id at which the resources changed */
        node_id = crm_element_value(node_state, XML_ATTR_ID);
        if (!node_id) {
            /* There is no information of <node_status> */
            free_xml(diff);
            return;
        }
        if (myuuid != NULL && STRNCMP_CONST(node_id, myuuid) != 0) {
            /* This change is not at my node */
            free_xml(diff);
            return;
        }

        /* get the head pointer of <lrm_resource>  */
        lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
        lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE);
        if (!lrm_rsc) {
            /* There is no information of <lrm_resources> */
            free_xml(diff);
            return; 
        }
        lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCE, FALSE);
        if (!lrm_rsc) {
            /* There is no information of <lrm_resource> */
            free_xml(diff);
            return; 
        }

        /*
         * now, get the head pointer of <lrm_rsc_op>,
         * and parse it's resource id, operation,  and rc_code.
         */
#if !HAVE_DECL___XML_NEXT
        xml_child_iter_filter(
            lrm_rsc, lrm_rsc_op, XML_LRM_TAG_RSC_OP,
#else
        for(lrm_rsc_op = __xml_first_child(lrm_rsc); lrm_rsc_op != NULL; lrm_rsc_op = __xml_next(lrm_rsc_op)) {
        if(STRNCMP_CONST((const char *)lrm_rsc_op->name, XML_LRM_TAG_RSC_OP) != 0) {
            continue;
        }
#endif

            rsc_id = crm_element_value(lrm_rsc, XML_ATTR_ID);
            operation = crm_element_value(lrm_rsc_op, XML_LRM_ATTR_TASK);
            rc_code = crm_element_value(lrm_rsc_op, XML_LRM_ATTR_RC);
            rsc_op_id = crm_element_value(lrm_rsc_op, XML_ATTR_ID);
            t_magic = crm_element_value(lrm_rsc_op, XML_ATTR_TRANSITION_MAGIC);
#if !HAVE_DECL___XML_NEXT
            ); /* end of xml_child_iter_filter(lrm_rsc) */
        ); /* end of xml_child_iter_filter(change_set) */
#else
            }
Пример #27
0
void
attrd_peer_message(crm_node_t *peer, xmlNode *xml)
{
    int peer_state = 0;
    const char *op = crm_element_value(xml, F_ATTRD_TASK);
    const char *election_op = crm_element_value(xml, F_CRM_TASK);

    if(election_op) {
        enum election_result rc = 0;

        crm_xml_add(xml, F_CRM_HOST_FROM, peer->uname);
        rc = election_count_vote(writer, xml, TRUE);
        switch(rc) {
            case election_start:
                free(peer_writer);
                peer_writer = NULL;
                election_vote(writer);
                break;
            case election_lost:
                free(peer_writer);
                peer_writer = strdup(peer->uname);
                break;
            default:
                election_check(writer);
                break;
        }
        return;
    }

    crm_element_value_int(xml, F_ATTRD_WRITER, &peer_state);
    if(election_state(writer) == election_won
       && peer_state == election_won
       && safe_str_neq(peer->uname, attrd_cluster->uname)) {
        crm_notice("Detected another attribute writer: %s", peer->uname);
        election_vote(writer);

    } else if(peer_state == election_won) {
        if(peer_writer == NULL) {
            peer_writer = strdup(peer->uname);
            crm_notice("Recorded attribute writer: %s", peer->uname);

        } else if(safe_str_neq(peer->uname, peer_writer)) {
            crm_notice("Recorded new attribute writer: %s (was %s)", peer->uname, peer_writer);
            free(peer_writer);
            peer_writer = strdup(peer->uname);
        }
    }

    if(safe_str_eq(op, "update")) {
        attrd_peer_update(peer, xml, FALSE);

    } else if(safe_str_eq(op, "sync")) {
        attrd_peer_sync(peer, xml);

    } else if(safe_str_eq(op, "peer-remove")) {
        const char *host = crm_element_value(xml, F_ATTRD_HOST);
        attrd_peer_remove(host, peer->uname);

    } else if(safe_str_eq(op, "sync-response")
              && safe_str_neq(peer->uname, attrd_cluster->uname)) {
        xmlNode *child = NULL;

        crm_notice("Processing %s from %s", op, peer->uname);
        for (child = __xml_first_child(xml); child != NULL; child = __xml_next(child)) {
            attrd_peer_update(peer, child, TRUE);
        }
    }
}
Пример #28
0
void
attrd_peer_message(crm_node_t *peer, xmlNode *xml)
{
    int peer_state = 0;
    const char *v = crm_element_value(xml, F_ATTRD_VERSION);
    const char *op = crm_element_value(xml, F_ATTRD_TASK);
    const char *election_op = crm_element_value(xml, F_CRM_TASK);
    const char *host = crm_element_value(xml, F_ATTRD_HOST);

    if(election_op) {
        enum election_result rc = 0;

        crm_xml_add(xml, F_CRM_HOST_FROM, peer->uname);
        rc = election_count_vote(writer, xml, TRUE);
        switch(rc) {
            case election_start:
                free(peer_writer);
                peer_writer = NULL;
                election_vote(writer);
                break;
            case election_lost:
                free(peer_writer);
                peer_writer = strdup(peer->uname);
                break;
            default:
                election_check(writer);
                break;
        }
        return;

    } else if(v == NULL) {
        /* From the non-atomic version */
        if (safe_str_eq(op, ATTRD_OP_UPDATE)) {
            const char *name = crm_element_value(xml, F_ATTRD_ATTRIBUTE);

            crm_trace("Compatibility update of %s from %s", name, peer->uname);
            attrd_peer_update(peer, xml, host, FALSE);

        } else if (safe_str_eq(op, ATTRD_OP_FLUSH)) {
            const char *name = crm_element_value(xml, F_ATTRD_ATTRIBUTE);
            attribute_t *a = g_hash_table_lookup(attributes, name);

            if(a) {
                crm_trace("Compatibility write-out of %s for %s from %s", a->id, op, peer->uname);
                write_or_elect_attribute(a);
            }

        } else if (safe_str_eq(op, ATTRD_OP_REFRESH)) {
            GHashTableIter aIter;
            attribute_t *a = NULL;

            g_hash_table_iter_init(&aIter, attributes);
            while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
                crm_trace("Compatibility write-out of %s for %s from %s", a->id, op, peer->uname);
                write_or_elect_attribute(a);
            }
        }
    }

    crm_element_value_int(xml, F_ATTRD_WRITER, &peer_state);
    if(election_state(writer) == election_won
       && peer_state == election_won
       && safe_str_neq(peer->uname, attrd_cluster->uname)) {
        crm_notice("Detected another attribute writer: %s", peer->uname);
        election_vote(writer);

    } else if(peer_state == election_won) {
        if(peer_writer == NULL) {
            peer_writer = strdup(peer->uname);
            crm_notice("Recorded attribute writer: %s", peer->uname);

        } else if(safe_str_neq(peer->uname, peer_writer)) {
            crm_notice("Recorded new attribute writer: %s (was %s)", peer->uname, peer_writer);
            free(peer_writer);
            peer_writer = strdup(peer->uname);
        }
    }

    if (safe_str_eq(op, ATTRD_OP_UPDATE) || safe_str_eq(op, ATTRD_OP_UPDATE_BOTH) || safe_str_eq(op, ATTRD_OP_UPDATE_DELAY)) {
        attrd_peer_update(peer, xml, host, FALSE);

    } else if (safe_str_eq(op, ATTRD_OP_SYNC)) {
        attrd_peer_sync(peer, xml);

    } else if (safe_str_eq(op, ATTRD_OP_PEER_REMOVE)) {
        attrd_peer_remove(host, TRUE, peer->uname);

    } else if (safe_str_eq(op, ATTRD_OP_SYNC_RESPONSE)
              && safe_str_neq(peer->uname, attrd_cluster->uname)) {
        xmlNode *child = NULL;

        crm_info("Processing %s from %s", op, peer->uname);
        for (child = __xml_first_child(xml); child != NULL; child = __xml_next(child)) {
            host = crm_element_value(child, F_ATTRD_HOST);
            attrd_peer_update(peer, child, host, TRUE);
        }
    }
}
Пример #29
0
extern int
find_nvpair_attr_delegate(cib_t * the_cib, const char *attr, const char *section,
                          const char *node_uuid, const char *attr_set_type, const char *set_name,
                          const char *attr_id, const char *attr_name, gboolean to_console,
                          char **value, const char *user_name)
{
    int offset = 0;
    static int xpath_max = 1024;
    int rc = pcmk_ok;

    char *xpath_string = NULL;
    xmlNode *xml_search = NULL;
    const char *set_type = NULL;
    const char *node_type = NULL;

    if (attr_set_type) {
        set_type = attr_set_type;
    } else {
        set_type = XML_TAG_ATTR_SETS;
    }

    CRM_ASSERT(value != NULL);
    *value = NULL;

    if (safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) {
        node_uuid = NULL;
        set_type = XML_CIB_TAG_PROPSET;

    } else if (safe_str_eq(section, XML_CIB_TAG_OPCONFIG)
               || safe_str_eq(section, XML_CIB_TAG_RSCCONFIG)) {
        node_uuid = NULL;
        set_type = XML_TAG_META_SETS;

    } else if (safe_str_eq(section, XML_CIB_TAG_TICKETS)) {
        node_uuid = NULL;
        section = XML_CIB_TAG_STATUS;
        node_type = XML_CIB_TAG_TICKETS;

    } else if (node_uuid == NULL) {
        return -EINVAL;
    }

    xpath_string = calloc(1, xpath_max);
    offset += snprintf(xpath_string + offset, xpath_max - offset, "%s", get_object_path(section));

    if (safe_str_eq(node_type, XML_CIB_TAG_TICKETS)) {
        offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s", node_type);

    } else if (node_uuid) {
        const char *node_type = XML_CIB_TAG_NODE;

        if (safe_str_eq(section, XML_CIB_TAG_STATUS)) {
            node_type = XML_CIB_TAG_STATE;
            set_type = XML_TAG_TRANSIENT_NODEATTRS;
        }
        offset +=
            snprintf(xpath_string + offset, xpath_max - offset, "//%s[@id='%s']", node_type,
                     node_uuid);
    }

    if (set_name) {
        offset +=
            snprintf(xpath_string + offset, xpath_max - offset, "//%s[@id='%s']", set_type,
                     set_name);
    } else {
        offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s", set_type);
    }

    offset += snprintf(xpath_string + offset, xpath_max - offset, "//nvpair[");
    if (attr_id) {
        offset += snprintf(xpath_string + offset, xpath_max - offset, "@id='%s'", attr_id);
    }

    if (attr_name) {
        if (attr_id) {
            offset += snprintf(xpath_string + offset, xpath_max - offset, " and ");
        }
        offset += snprintf(xpath_string + offset, xpath_max - offset, "@name='%s'", attr_name);
    }
    offset += snprintf(xpath_string + offset, xpath_max - offset, "]");

    rc = cib_internal_op(the_cib, CIB_OP_QUERY, NULL, xpath_string, NULL, &xml_search,
                         cib_sync_call | cib_scope_local | cib_xpath, user_name);

    if (rc != pcmk_ok) {
        crm_trace("Query failed for attribute %s (section=%s, node=%s, set=%s, xpath=%s): %s",
                  attr_name, section, crm_str(node_uuid), crm_str(set_name), xpath_string,
                  pcmk_strerror(rc));
        goto done;
    }

    crm_log_xml_debug(xml_search, "Match");
    if (xml_has_children(xml_search)) {
        xmlNode *child = NULL;

        rc = -EINVAL;
        attr_msg(LOG_WARNING, "Multiple attributes match name=%s", attr_name);

        for (child = __xml_first_child(xml_search); child != NULL; child = __xml_next(child)) {
            attr_msg(LOG_INFO, "  Value: %s \t(id=%s)",
                     crm_element_value(child, XML_NVPAIR_ATTR_VALUE), ID(child));
        }

    } else {
        const char *tmp = crm_element_value(xml_search, attr);

        if (tmp) {
            *value = strdup(tmp);
        }
    }

  done:
    free(xpath_string);
    free_xml(xml_search);
    return rc;
}
Пример #30
0
int
process_remote_stonith_query(xmlNode * msg)
{
    int devices = 0;
    gboolean host_is_target = FALSE;
    const char *id = NULL;
    const char *host = NULL;
    remote_fencing_op_t *op = NULL;
    st_query_result_t *result = NULL;
    uint32_t active = fencing_active_peers();
    xmlNode *dev = get_xpath_object("//@" F_STONITH_REMOTE_OP_ID, msg, LOG_ERR);
    xmlNode *child = NULL;

    CRM_CHECK(dev != NULL, return -EPROTO);

    id = crm_element_value(dev, F_STONITH_REMOTE_OP_ID);
    CRM_CHECK(id != NULL, return -EPROTO);

    dev = get_xpath_object("//@st-available-devices", msg, LOG_ERR);
    CRM_CHECK(dev != NULL, return -EPROTO);
    crm_element_value_int(dev, "st-available-devices", &devices);

    op = g_hash_table_lookup(remote_op_list, id);
    if (op == NULL) {
        crm_debug("Unknown or expired remote op: %s", id);
        return -EOPNOTSUPP;
    }

    op->replies++;
    host = crm_element_value(msg, F_ORIG);
    host_is_target = safe_str_eq(host, op->target);

    if (devices <= 0) {
        /* If we're doing 'known' then we might need to fire anyway */
        crm_trace("Query result from %s (%d devices)", host, devices);
        if(op->state == st_query && (op->replies >= op->replies_expected || op->replies >= active)) {
            crm_info("All queries have arrived, continuing (%d, %d, %d) ", op->replies_expected, active, op->replies);
            call_remote_stonith(op, NULL);
        }
        return pcmk_ok;

    } else if (host_is_target) {
        if (op->call_options & st_opt_allow_suicide) {
            crm_trace("Allowing %s to potentialy fence itself", op->target);
        } else {
            crm_info("Ignoring reply from %s, hosts are not permitted to commit suicide",
                     op->target);
            return pcmk_ok;
        }
    }

    crm_info("Query result %d of %d from %s (%d devices)", op->replies, op->replies_expected, host, devices);
    result = calloc(1, sizeof(st_query_result_t));
    result->host = strdup(host);
    result->devices = devices;
    result->custom_action_timeouts = g_hash_table_new_full(crm_str_hash, g_str_equal, free, NULL);
    result->verified_devices = g_hash_table_new_full(crm_str_hash, g_str_equal, free, NULL);

    for (child = __xml_first_child(dev); child != NULL; child = __xml_next(child)) {
        const char *device = ID(child);
        int action_timeout = 0;
        int verified = 0;

        if (device) {
            result->device_list = g_list_prepend(result->device_list, strdup(device));
            crm_element_value_int(child, F_STONITH_ACTION_TIMEOUT, &action_timeout);
            crm_element_value_int(child, F_STONITH_DEVICE_VERIFIED, &verified);
            if (action_timeout) {
                crm_trace("Peer %s with device %s returned action timeout %d",
                          result->host, device, action_timeout);
                g_hash_table_insert(result->custom_action_timeouts,
                                    strdup(device), GINT_TO_POINTER(action_timeout));
            }
            if (verified) {
                crm_trace("Peer %s has confirmed a verified device %s", result->host, device);
                g_hash_table_insert(result->verified_devices,
                                    strdup(device), GINT_TO_POINTER(verified));
            }
        }
    }

    CRM_CHECK(devices == g_list_length(result->device_list),
              crm_err("Mis-match: Query claimed to have %d devices but %d found", devices,
                      g_list_length(result->device_list)));

    op->query_results = g_list_insert_sorted(op->query_results, result, sort_peers);

    if (is_set(op->call_options, st_opt_topology)) {
        /* If we start the fencing before all the topology results are in,
         * it is possible fencing levels will be skipped because of the missing
         * query results. */
        if (op->state == st_query && all_topology_devices_found(op)) {
            /* All the query results are in for the topology, start the fencing ops. */
            crm_trace("All topology devices found");
            call_remote_stonith(op, result);

        } else if(op->state == st_query && (op->replies >= op->replies_expected || op->replies >= active)) {
            crm_info("All topology queries have arrived, continuing (%d, %d, %d) ", op->replies_expected, active, op->replies);
            call_remote_stonith(op, NULL);
        }

    } else if (op->state == st_query) {
        /* We have a result for a non-topology fencing op that looks promising,
         * go ahead and start fencing before query timeout */
        if (host_is_target == FALSE && g_hash_table_size(result->verified_devices)) {
            /* we have a verified device living on a peer that is not the target */
            crm_trace("Found %d verified devices", g_hash_table_size(result->verified_devices));
            call_remote_stonith(op, result);

        } else if (safe_str_eq(op->action, "on")) {
            crm_trace("Unfencing %s", op->target);
            call_remote_stonith(op, result);

        } else if(op->replies >= op->replies_expected || op->replies >= active) {
            crm_info("All queries have arrived, continuing (%d, %d, %d) ", op->replies_expected, active, op->replies);
            call_remote_stonith(op, NULL);

        } else {
            crm_trace("Waiting for more peer results before launching fencing operation");
        }

    } else if (op->state == st_done) {
        crm_info("Discarding query result from %s (%d devices): Operation is in state %d",
                 result->host, result->devices, op->state);
    }

    return pcmk_ok;
}