Exemplo n.º 1
0
static void
cib_handle_remote_msg(crm_client_t * client, xmlNode * command)
{
    const char *value = NULL;

    value = crm_element_name(command);
    if (safe_str_neq(value, "cib_command")) {
        crm_log_xml_trace(command, "Bad command: ");
        return;
    }

    if (client->name == NULL) {
        value = crm_element_value(command, F_CLIENTNAME);
        if (value == NULL) {
            client->name = strdup(client->id);
        } else {
            client->name = strdup(value);
        }
    }

    if (client->userdata == NULL) {
        value = crm_element_value(command, F_CIB_CALLBACK_TOKEN);
        if (value != NULL) {
            client->userdata = strdup(value);
            crm_trace("Callback channel for %s is %s", client->id, (char*)client->userdata);

        } else {
            client->userdata = strdup(client->id);
        }
    }

    /* unset dangerous options */
    xml_remove_prop(command, F_ORIG);
    xml_remove_prop(command, F_CIB_HOST);
    xml_remove_prop(command, F_CIB_GLOBAL_UPDATE);

    crm_xml_add(command, F_TYPE, T_CIB);
    crm_xml_add(command, F_CIB_CLIENTID, client->id);
    crm_xml_add(command, F_CIB_CLIENTNAME, client->name);
#if ENABLE_ACL
    crm_xml_add(command, F_CIB_USER, client->user);
#endif

    if (crm_element_value(command, F_CIB_CALLID) == NULL) {
        char *call_uuid = crm_generate_uuid();

        /* fix the command */
        crm_xml_add(command, F_CIB_CALLID, call_uuid);
        free(call_uuid);
    }

    if (crm_element_value(command, F_CIB_CALLOPTS) == NULL) {
        crm_xml_add_int(command, F_CIB_CALLOPTS, 0);
    }

    crm_log_xml_trace(command, "Remote command: ");
    cib_common_callback_worker(0, 0, command, client, TRUE);
}
Exemplo n.º 2
0
/*!
 * \brief Replace an XML attribute with specified name and (possibly NULL) value
 *
 * \param[in,out] node   XML node to modify
 * \param[in]     name   Attribute name to set
 * \param[in]     value  Attribute value to set
 *
 * \return New value on success, \c NULL otherwise
 * \note This does nothing if node or name is \c NULL or empty.
 */
const char *
crm_xml_replace(xmlNode *node, const char *name, const char *value)
{
    bool dirty = FALSE;
    xmlAttr *attr = NULL;
    const char *old_value = NULL;

    CRM_CHECK(node != NULL, return NULL);
    CRM_CHECK(name != NULL && name[0] != 0, return NULL);

    old_value = crm_element_value(node, name);

    /* Could be re-setting the same value */
    CRM_CHECK(old_value != value, return value);

    if (pcmk__check_acl(node, name, xpf_acl_write) == FALSE) {
        /* Create a fake object linked to doc->_private instead? */
        crm_trace("Cannot replace %s=%s to %s", name, value, node->name);
        return NULL;

    } else if (old_value && !value) {
        xml_remove_prop(node, name);
        return NULL;
    }

    if (pcmk__tracking_xml_changes(node, FALSE)) {
        if (!old_value || !value || !strcmp(old_value, value)) {
            dirty = TRUE;
        }
    }

    attr = xmlSetProp(node, (const xmlChar *)name, (const xmlChar *)value);
    if (dirty) {
        pcmk__mark_xml_attr_dirty(attr);
    }
    CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
    return (char *) attr->children->content;
}
Exemplo n.º 3
0
static void
forward_request(xmlNode * request, cib_client_t * cib_client, int call_options)
{
    const char *op = crm_element_value(request, F_CIB_OPERATION);
    const char *host = crm_element_value(request, F_CIB_HOST);

    crm_xml_add(request, F_CIB_DELEGATED, cib_our_uname);

    if (host != NULL) {
        crm_trace("Forwarding %s op to %s", op, host);
        send_cluster_message(host, crm_msg_cib, request, FALSE);

    } else {
        crm_trace("Forwarding %s op to master instance", op);
        send_cluster_message(NULL, crm_msg_cib, request, FALSE);
    }

    /* Return the request to its original state */
    xml_remove_prop(request, F_CIB_DELEGATED);

    if (call_options & cib_discard_reply) {
        crm_trace("Client not interested in reply");
    }
}
Exemplo n.º 4
0
gboolean
cib_remote_msg(int csock, gpointer data)
{
    const char *value = NULL;
    xmlNode *command = NULL;
    cib_client_t *client = data;

    crm_trace("%s callback", client->encrypted ? "secure" : "clear-text");

    command = cib_recv_remote_msg(client->channel, client->encrypted);
    if (command == NULL) {
        return FALSE;
    }

    value = crm_element_name(command);
    if (safe_str_neq(value, "cib_command")) {
        crm_log_xml(LOG_MSG, "Bad command: ", command);
        goto bail;
    }

    if (client->name == NULL) {
        value = crm_element_value(command, F_CLIENTNAME);
        if (value == NULL) {
            client->name = crm_strdup(client->id);
        } else {
            client->name = crm_strdup(value);
        }
    }

    if (client->callback_id == NULL) {
        value = crm_element_value(command, F_CIB_CALLBACK_TOKEN);
        if (value != NULL) {
            client->callback_id = crm_strdup(value);
            crm_debug_2("Callback channel for %s is %s", client->id, client->callback_id);

        } else {
            client->callback_id = crm_strdup(client->id);
        }
    }

    /* unset dangerous options */
    xml_remove_prop(command, F_ORIG);
    xml_remove_prop(command, F_CIB_HOST);
    xml_remove_prop(command, F_CIB_GLOBAL_UPDATE);

    crm_xml_add(command, F_TYPE, T_CIB);
    crm_xml_add(command, F_CIB_CLIENTID, client->id);
    crm_xml_add(command, F_CIB_CLIENTNAME, client->name);
#if ENABLE_ACL
    crm_xml_add(command, F_CIB_USER, client->user);
#endif

    if (crm_element_value(command, F_CIB_CALLID) == NULL) {
        cl_uuid_t call_id;
        char call_uuid[UU_UNPARSE_SIZEOF];

        /* fix the command */
        cl_uuid_generate(&call_id);
        cl_uuid_unparse(&call_id, call_uuid);
        crm_xml_add(command, F_CIB_CALLID, call_uuid);
    }

    if (crm_element_value(command, F_CIB_CALLOPTS) == NULL) {
        crm_xml_add_int(command, F_CIB_CALLOPTS, 0);
    }

    crm_log_xml(LOG_MSG, "Remote command: ", command);
    cib_common_callback_worker(command, client, FALSE, TRUE);
  bail:
    free_xml(command);
    command = NULL;
    return TRUE;
}
Exemplo n.º 5
0
void
filter_action_parameters(xmlNode *param_set, const char *version) 
{
	char *key = NULL;
	char *timeout = NULL;
	char *interval = NULL;
#if CRM_DEPRECATED_SINCE_2_0_5
	const char *filter_205[] = {
		XML_ATTR_TE_TARGET_RC,
		XML_ATTR_LRM_PROBE,
		XML_RSC_ATTR_START,
		XML_RSC_ATTR_NOTIFY,
		XML_RSC_ATTR_UNIQUE,
		XML_RSC_ATTR_MANAGED,
		XML_RSC_ATTR_PRIORITY,
		XML_RSC_ATTR_MULTIPLE,
		XML_RSC_ATTR_STICKINESS,
		XML_RSC_ATTR_FAIL_STICKINESS,
		XML_RSC_ATTR_TARGET_ROLE,

/* ignore clone fields */
		XML_RSC_ATTR_INCARNATION, 
		XML_RSC_ATTR_INCARNATION_MAX, 
		XML_RSC_ATTR_INCARNATION_NODEMAX,
		XML_RSC_ATTR_MASTER_MAX,
		XML_RSC_ATTR_MASTER_NODEMAX,
		
/* old field names */
		"role",
		"crm_role",
		"te-target-rc",
		
/* ignore notify fields */
 		"notify_stop_resource",
 		"notify_stop_uname",
 		"notify_start_resource",
 		"notify_start_uname",
 		"notify_active_resource",
 		"notify_active_uname",
 		"notify_inactive_resource",
 		"notify_inactive_uname",
 		"notify_promote_resource",
 		"notify_promote_uname",
 		"notify_demote_resource",
 		"notify_demote_uname",
 		"notify_master_resource",
 		"notify_master_uname",
 		"notify_slave_resource",
 		"notify_slave_uname"		
	};
#endif
	
	const char *attr_filter[] = {
		XML_ATTR_ID,
		XML_ATTR_CRM_VERSION,
		XML_LRM_ATTR_OP_DIGEST,
	};

	gboolean do_delete = FALSE;
	int lpc = 0;
	static int meta_len = 0;
	if(meta_len == 0) {
		meta_len  = strlen(CRM_META);
	}	
	
	if(param_set == NULL) {
		return;
	}

#if CRM_DEPRECATED_SINCE_2_0_5
 	if(version == NULL || compare_version("1.0.5", version) > 0) {
		for(lpc = 0; lpc < DIMOF(filter_205); lpc++) {
			xml_remove_prop(param_set, filter_205[lpc]); 
		}
	}
#endif

	for(lpc = 0; lpc < DIMOF(attr_filter); lpc++) {
		xml_remove_prop(param_set, attr_filter[lpc]); 
	}

	key = crm_meta_name(XML_LRM_ATTR_INTERVAL);
	interval = crm_element_value_copy(param_set, key);
	crm_free(key);

	key = crm_meta_name(XML_ATTR_TIMEOUT);
	timeout = crm_element_value_copy(param_set, key);
	
	xml_prop_iter(param_set, prop_name, prop_value,      
		      do_delete = FALSE;
		      if(strncasecmp(prop_name, CRM_META, meta_len) == 0) {
			      do_delete = TRUE;
		      }

		      if(do_delete) {
			      xml_remove_prop(param_set, prop_name);
		      }
		);
Exemplo n.º 6
0
void
attrd_peer_update(crm_node_t *peer, xmlNode *xml, const char *host, bool filter)
{
    bool changed = FALSE;
    attribute_t *a;
    attribute_value_t *v = NULL;
    int dampen = 0;

    const char *op = crm_element_value(xml, F_ATTRD_TASK);
    const char *attr = crm_element_value(xml, F_ATTRD_ATTRIBUTE);
    const char *value = crm_element_value(xml, F_ATTRD_VALUE);
    const char *dvalue = crm_element_value(xml, F_ATTRD_DAMPEN);

    if (attr == NULL) {
        crm_warn("Peer update did not specify attribute");
        return;
    }

    a = g_hash_table_lookup(attributes, attr);
    if(a == NULL) {
        if (op == NULL /* The xml children from an ATTRD_OP_SYNC_RESPONSE have no F_ATTRD_TASK */
            || safe_str_eq(op, ATTRD_OP_UPDATE)
            || safe_str_eq(op, ATTRD_OP_UPDATE_BOTH)) {
            a = create_attribute(xml);
        } else {
            crm_warn("Update error (attribute %s not found)", attr);
            return;
        }
    }
    
    if (op == NULL /* The xml children from an ATTRD_OP_SYNC_RESPONSE have no F_ATTRD_TASK */
        || safe_str_eq(op, ATTRD_OP_UPDATE_BOTH)
        || safe_str_eq(op, ATTRD_OP_UPDATE_DELAY)) {
        if (dvalue) {
            dampen = crm_get_msec(dvalue); 
            if (dampen >= 0) {
                if (a->timeout_ms != dampen) {
                    mainloop_timer_stop(a->timer);
                    mainloop_timer_del(a->timer);
                    a->timeout_ms = dampen;
                    if (dampen > 0) {
                        a->timer = mainloop_timer_add(a->id, a->timeout_ms, FALSE, attribute_timer_cb, a);
                        crm_info("Update attribute %s with delay %dms (%s)", a->id, dampen, dvalue);
                    } else {
                        a->timer = NULL;
                        crm_info("Update attribute %s with not delay", a->id);
                    }
                    //if dampen is changed, attrd writes in a current value immediately.
                    write_or_elect_attribute(a);
                    if (safe_str_eq(op, ATTRD_OP_UPDATE_DELAY)) {
                        return;
                    }
                } else {
                    if (safe_str_eq(op, ATTRD_OP_UPDATE_DELAY)) {
                        crm_trace("Unchanged attribute %s with delay %dms (%s).(ATTRD_OP_UPDATE_DELAY)", a->id, dampen, dvalue);
                        return;
                    }
                }
            } else {
                crm_warn("Update error (A positive number is necessary for delay parameter. attribute %s : %dms (%s))", a->id, dampen, dvalue);
                return;
            }
        } else {
            crm_warn("Update error (delay parameter is necessary for the update of the attribute %s)", a->id);
            return;
        }
    }

    if(host == NULL) {
        GHashTableIter vIter;
        g_hash_table_iter_init(&vIter, a->values);

        crm_debug("Setting %s for all hosts to %s", attr, value);

        xml_remove_prop(xml, F_ATTRD_HOST_ID);
        while (g_hash_table_iter_next(&vIter, (gpointer *) & host, NULL)) {
            attrd_peer_update(peer, xml, host, filter);
        }
        return;
    }

    v = attrd_lookup_or_create_value(a->values, host, xml);

    if(filter
              && safe_str_neq(v->current, value)
              && safe_str_eq(host, attrd_cluster->uname)) {
        xmlNode *sync = create_xml_node(NULL, __FUNCTION__);
        crm_notice("%s[%s]: local value '%s' takes priority over '%s' from %s",
                   a->id, host, v->current, value, peer->uname);

        crm_xml_add(sync, F_ATTRD_TASK, ATTRD_OP_SYNC_RESPONSE);
        v = g_hash_table_lookup(a->values, host);
        build_attribute_xml(sync, a->id, a->set, a->uuid, a->timeout_ms, a->user, a->is_private,
                            v->nodename, v->nodeid, v->current);

        crm_xml_add_int(sync, F_ATTRD_WRITER, election_state(writer));
        send_attrd_message(peer, sync);
        free_xml(sync);

    } else if(safe_str_neq(v->current, value)) {
        crm_info("Setting %s[%s]: %s -> %s from %s", attr, host, v->current, value, peer->uname);
        free(v->current);
        if(value) {
            v->current = strdup(value);
        } else {
            v->current = NULL;
        }
        changed = TRUE;
    } else {
        crm_trace("Unchanged %s[%s] from %s is %s", attr, host, peer->uname, value);
    }

    a->changed |= changed;

    if(changed) {
        if(a->timer) {
            crm_trace("Delayed write out (%dms) for %s", a->timeout_ms, a->id);
            mainloop_timer_start(a->timer);
        } else {
            write_or_elect_attribute(a);
        }
    }

    /* this only involves cluster nodes. */
    if(v->nodeid == 0 && (v->is_remote == FALSE)) {
        if(crm_element_value_int(xml, F_ATTRD_HOST_ID, (int*)&v->nodeid) == 0) {
            /* Create the name/id association */
            crm_node_t *peer = crm_get_peer(v->nodeid, host);
            crm_trace("We know %s's node id now: %s", peer->uname, peer->uuid);
            if(election_state(writer) == election_won) {
                write_attributes(FALSE, TRUE);
                return;
            }
        }
    }
}
Exemplo n.º 7
0
static int
update_cib_object(xmlNode * parent, xmlNode * update)
{
    int result = pcmk_ok;
    xmlNode *target = NULL;
    xmlNode *a_child = NULL;
    const char *replace = NULL;
    const char *object_id = NULL;
    const char *object_name = NULL;

    CRM_CHECK(update != NULL, return -EINVAL);
    CRM_CHECK(parent != NULL, return -EINVAL);

    object_name = crm_element_name(update);
    CRM_CHECK(object_name != NULL, return -EINVAL);

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

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

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

    if (target == NULL) {
        target = create_xml_node(parent, object_name);
    }

    crm_trace("Found node <%s id=%s> to update", crm_str(object_name), crm_str(object_id));

    replace = crm_element_value(update, XML_CIB_ATTR_REPLACE);
    if (replace != NULL) {
        xmlNode *remove = NULL;
        int last = 0, lpc = 0, len = 0;

        len = strlen(replace);
        while (lpc <= len) {
            if (replace[lpc] == ',' || replace[lpc] == 0) {
                char *replace_item = NULL;

                if (last == lpc) {
                    /* nothing to do */
                    last = lpc + 1;
                    goto incr;
                }

                replace_item = calloc(1, lpc - last + 1);
                memcpy(replace_item, replace + last, lpc - last);

                remove = find_xml_node(target, replace_item, FALSE);
                if (remove != NULL) {
                    crm_trace("Replacing node <%s> in <%s>",
                              replace_item, crm_element_name(target));
                    free_xml(remove);
                    remove = NULL;
                }
                free(replace_item);
                last = lpc + 1;
            }
  incr:
            lpc++;
        }
        xml_remove_prop(update, XML_CIB_ATTR_REPLACE);
        xml_remove_prop(target, XML_CIB_ATTR_REPLACE);
    }

    copy_in_properties(target, update);

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

    for (a_child = __xml_first_child(update); a_child != NULL; a_child = __xml_next(a_child)) {
        int tmp_result = 0;

        crm_trace("Updating child <%s id=%s>", crm_element_name(a_child), ID(a_child));

        tmp_result = update_cib_object(target, a_child);

        /*  only the first error is likely to be interesting */
        if (tmp_result != pcmk_ok) {
            crm_err("Error updating child <%s id=%s>", crm_element_name(a_child), ID(a_child));

            if (result == pcmk_ok) {
                result = tmp_result;
            }
        }
    }

    crm_trace("Finished with <%s id=%s>", crm_str(object_name), crm_str(object_id));

    return result;
}
Exemplo n.º 8
0
void
attrd_peer_update(crm_node_t *peer, xmlNode *xml, const char *host, bool filter)
{
    bool changed = FALSE;
    attribute_value_t *v = NULL;

    const char *attr = crm_element_value(xml, F_ATTRD_ATTRIBUTE);
    const char *value = crm_element_value(xml, F_ATTRD_VALUE);

    attribute_t *a = g_hash_table_lookup(attributes, attr);

    if(a == NULL) {
        a = create_attribute(xml);
    }

    if(host == NULL) {
        GHashTableIter vIter;
        g_hash_table_iter_init(&vIter, a->values);

        crm_debug("Setting %s for all hosts to %s", attr, value);

        xml_remove_prop(xml, F_ATTRD_HOST_ID);
        while (g_hash_table_iter_next(&vIter, (gpointer *) & host, NULL)) {
            attrd_peer_update(peer, xml, host, filter);
        }
        return;
    }

    v = g_hash_table_lookup(a->values, host);

    if(v == NULL) {
        v = calloc(1, sizeof(attribute_value_t));
        v->nodename = strdup(host);
        crm_element_value_int(xml, F_ATTRD_IS_REMOTE, &v->is_remote);
        g_hash_table_replace(a->values, v->nodename, v);

        if (v->is_remote == TRUE) {
            crm_remote_peer_cache_add(host);
        }
    }

    if(filter
              && safe_str_neq(v->current, value)
              && safe_str_eq(host, attrd_cluster->uname)) {
        xmlNode *sync = create_xml_node(NULL, __FUNCTION__);
        crm_notice("%s[%s]: local value '%s' takes priority over '%s' from %s",
                   a->id, host, v->current, value, peer->uname);

        crm_xml_add(sync, F_ATTRD_TASK, "sync-response");
        v = g_hash_table_lookup(a->values, host);
        build_attribute_xml(sync, a->id, a->set, a->uuid, a->timeout_ms, a->user, v->nodename, v->nodeid, v->current);

        crm_xml_add_int(sync, F_ATTRD_WRITER, election_state(writer));
        send_attrd_message(peer, sync);
        free_xml(sync);

    } else if(safe_str_neq(v->current, value)) {
        crm_info("Setting %s[%s]: %s -> %s from %s", attr, host, v->current, value, peer->uname);
        free(v->current);
        if(value) {
            v->current = strdup(value);
        } else {
            v->current = NULL;
        }
        changed = TRUE;

    } else {
        crm_trace("Unchanged %s[%s] from %s is %s", attr, host, peer->uname, value);
    }

    a->changed |= changed;

    if(changed) {
        if(a->timer) {
            crm_trace("Delayed write out (%dms) for %s", a->timeout_ms, a->id);
            mainloop_timer_start(a->timer);
        } else {
            write_or_elect_attribute(a);
        }
    }

    /* this only involves cluster nodes. */
    if(v->nodeid == 0 && (v->is_remote == FALSE)) {
        if(crm_element_value_int(xml, F_ATTRD_HOST_ID, (int*)&v->nodeid) == 0) {
            /* Create the name/id association */
            crm_node_t *peer = crm_get_peer(v->nodeid, host);
            crm_trace("We know %s's node id now: %s", peer->uname, peer->uuid);
            if(election_state(writer) == election_won) {
                write_attributes(FALSE, TRUE);
                return;
            }
        }
    }
}
Exemplo n.º 9
0
int
main(int argc, char **argv)
{
	crm_data_t *cib_object = NULL;
	crm_data_t *status = NULL;
	int argerr = 0;
	int flag;
		
	pe_working_set_t data_set;
	cib_t *	cib_conn = NULL;
	int rc = cib_ok;
	
	gboolean xml_stdin = FALSE;
	const char *xml_file = NULL;
	const char *xml_string = NULL;
	
	crm_system_name = basename(argv[0]);
	
	g_log_set_handler(NULL,
			  G_LOG_LEVEL_ERROR      | G_LOG_LEVEL_CRITICAL
			  | G_LOG_LEVEL_WARNING  | G_LOG_LEVEL_MESSAGE
			  | G_LOG_LEVEL_INFO     | G_LOG_LEVEL_DEBUG
			  | G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL,
			  cl_glib_msg_handler, NULL);

	/* and for good measure... - this enum is a bit field (!) */
	g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/
	
	cl_log_set_entity(crm_system_name);
	cl_log_set_facility(HA_LOG_FACILITY);
	cl_log_enable_stderr(TRUE);
	set_crm_log_level(LOG_ERR);
	
	CL_SIGNAL(DEBUG_INC, alter_debug);
	CL_SIGNAL(DEBUG_DEC, alter_debug);
	
	while (1) {
#ifdef HAVE_GETOPT_H
		int option_index = 0;
		static struct option long_options[] = {
			/* Top-level Options */
			{F_CRM_DATA,    1, 0, 'X'},
			{"dtd-file",    1, 0, 'D'},
			{"xml-file",    1, 0, 'x'},
			{"xml-pipe",    0, 0, 'p'},
			{"save-xml",    1, 0, 'S'},
			{"live-check",  0, 0, 'L'},
			{"help", 0, 0, '?'},
      
			{0, 0, 0, 0}
		};
#endif
    
#ifdef HAVE_GETOPT_H
		flag = getopt_long(argc, argv, OPTARGS,
				   long_options, &option_index);
#else
		flag = getopt(argc, argv, OPTARGS);
#endif
		if (flag == -1)
			break;
    
		switch(flag) {
#ifdef HAVE_GETOPT_H
			case 0:
				printf("option %s", long_options[option_index].name);
				if (optarg)
					printf(" with arg %s", optarg);
				printf("\n");
    
				break;
#endif
      
			case 'D':
				crm_debug_2("Option %c => %s", flag, optarg);
				dtd_file = optarg;
				break;

			case 'X':
				crm_debug_2("Option %c => %s", flag, optarg);
				xml_string = crm_strdup(optarg);
				break;
			case 'x':
				crm_debug_2("Option %c => %s", flag, optarg);
				xml_file = crm_strdup(optarg);
				break;
			case 'p':
				xml_stdin = TRUE;
				break;
			case 'S':
				cib_save = crm_strdup(optarg);
				break;
			case 'V':
				alter_debug(DEBUG_INC);
				break;
			case 'L':
				USE_LIVE_CIB = TRUE;
				break;
			case '?':
				usage(crm_system_name, LSB_EXIT_GENERIC);
				break;
			default:
				printf("?? getopt returned character code 0%o ??\n", flag);
				++argerr;
				break;
		}
	}
  
	if (optind < argc) {
		printf("non-option ARGV-elements: ");
		while (optind < argc) {
			printf("%s ", argv[optind++]);
		}
		printf("\n");
	}
  
	if (optind > argc) {
		++argerr;
	}
  
	if (argerr) {
		crm_err("%d errors in option parsing", argerr);
		usage(crm_system_name, LSB_EXIT_GENERIC);
	}
  
	crm_info("=#=#=#=#= Getting XML =#=#=#=#=");

	if(USE_LIVE_CIB) {
		cib_conn = cib_new();
		rc = cib_conn->cmds->signon(
			cib_conn, crm_system_name, cib_command_synchronous);
	}
	
	
	if(USE_LIVE_CIB) {
		if(rc == cib_ok) {
			int options = cib_scope_local|cib_sync_call;
			crm_info("Reading XML from: live cluster");
			rc = cib_conn->cmds->query(
 				cib_conn, NULL, &cib_object, options);
		}

		
		if(rc != cib_ok) {
			fprintf(stderr, "Live CIB query failed: %s\n",
				cib_error2string(rc));
			return 3;
		}
		if(cib_object == NULL) {
			fprintf(stderr, "Live CIB query failed: empty result\n");
			return 3;
		}
	
	} else if(xml_file != NULL) {
		FILE *xml_strm = fopen(xml_file, "r");
		cib_object = file2xml(xml_strm, FALSE);
		if(cib_object == NULL) {
			fprintf(stderr,
				"Couldn't parse input file: %s\n", xml_file);
			return 1;
		}
		fclose(xml_strm);
		
	} else if(xml_string != NULL) {
		cib_object = string2xml(xml_string);
		if(cib_object == NULL) {
			fprintf(stderr,
				"Couldn't parse input string: %s\n", xml_string);
			return 1;
		}
	} else if(xml_stdin) {
		cib_object = stdin2xml();
		if(cib_object == NULL) {
			fprintf(stderr, "Couldn't parse input from STDIN.\n");
			return 1;
		}

	} else {
		fprintf(stderr, "No configuration source specified."
			"  Use --help for usage information.\n");
		return 3;
	}
	
	if(cib_save != NULL) {
		write_xml_file(cib_object, cib_save, FALSE);
	}
	
	status = get_object_root(XML_CIB_TAG_STATUS, cib_object);
	if(status == NULL) {
		create_xml_node(cib_object, XML_CIB_TAG_STATUS);
	}
	
#if CRM_DEPRECATED_SINCE_2_0_4
	xml_child_iter_filter(status, node_state, XML_CIB_TAG_STATE,
		       xml_remove_prop(node_state, XML_CIB_TAG_LRM);
		);
Exemplo n.º 10
0
void
attrd_peer_update(crm_node_t *peer, xmlNode *xml, const char *host, bool filter)
{
    bool update_both = FALSE;
    attribute_t *a;
    attribute_value_t *v = NULL;
    gboolean is_force_write = FALSE;

    const char *op = crm_element_value(xml, F_ATTRD_TASK);
    const char *attr = crm_element_value(xml, F_ATTRD_ATTRIBUTE);
    const char *value = crm_element_value(xml, F_ATTRD_VALUE);
    crm_element_value_int(xml, F_ATTRD_IS_FORCE_WRITE, &is_force_write);

    if (attr == NULL) {
        crm_warn("Could not update attribute: peer did not specify name");
        return;
    }

    update_both = ((op == NULL) // ATTRD_OP_SYNC_RESPONSE has no F_ATTRD_TASK
                   || safe_str_eq(op, ATTRD_OP_UPDATE_BOTH));

    // Look up or create attribute entry
    a = g_hash_table_lookup(attributes, attr);
    if (a == NULL) {
        if (update_both || safe_str_eq(op, ATTRD_OP_UPDATE)) {
            a = create_attribute(xml);
        } else {
            crm_warn("Could not update %s: attribute not found", attr);
            return;
        }
    }

    // Update attribute dampening
    if (update_both || safe_str_eq(op, ATTRD_OP_UPDATE_DELAY)) {
        const char *dvalue = crm_element_value(xml, F_ATTRD_DAMPEN);
        int dampen = 0;

        if (dvalue == NULL) {
            crm_warn("Could not update %s: peer did not specify value for delay",
                     attr);
            return;
        }

        dampen = crm_get_msec(dvalue);
        if (dampen < 0) {
            crm_warn("Could not update %s: invalid delay value %dms (%s)",
                     attr, dampen, dvalue);
            return;
        }

        if (a->timeout_ms != dampen) {
            mainloop_timer_del(a->timer);
            a->timeout_ms = dampen;
            if (dampen > 0) {
                a->timer = mainloop_timer_add(attr, a->timeout_ms, FALSE,
                                              attribute_timer_cb, a);
                crm_info("Update attribute %s delay to %dms (%s)",
                         attr, dampen, dvalue);
            } else {
                a->timer = NULL;
                crm_info("Update attribute %s to remove delay", attr);
            }

            /* If dampening changed, do an immediate write-out,
             * otherwise repeated dampening changes would prevent write-outs
             */
            write_or_elect_attribute(a);
        }

        if (!update_both) {
            return;
        }
    }

    // If no host was specified, update all hosts recursively
    if (host == NULL) {
        GHashTableIter vIter;

        crm_debug("Setting %s for all hosts to %s", attr, value);
        xml_remove_prop(xml, F_ATTRD_HOST_ID);
        g_hash_table_iter_init(&vIter, a->values);
        while (g_hash_table_iter_next(&vIter, (gpointer *) & host, NULL)) {
            attrd_peer_update(peer, xml, host, filter);
        }
        return;
    }

    // Update attribute value for one host

    v = attrd_lookup_or_create_value(a->values, host, xml);

    if (filter && safe_str_neq(v->current, value)
        && safe_str_eq(host, attrd_cluster->uname)) {

        xmlNode *sync = create_xml_node(NULL, __FUNCTION__);

        crm_notice("%s[%s]: local value '%s' takes priority over '%s' from %s",
                   attr, host, v->current, value, peer->uname);

        crm_xml_add(sync, F_ATTRD_TASK, ATTRD_OP_SYNC_RESPONSE);
        v = g_hash_table_lookup(a->values, host);
        build_attribute_xml(sync, attr, a->set, a->uuid, a->timeout_ms, a->user,
                            a->is_private, v->nodename, v->nodeid, v->current, FALSE);

        attrd_xml_add_writer(sync);

        /* Broadcast in case any other nodes had the inconsistent value */
        send_attrd_message(NULL, sync);
        free_xml(sync);

    } else if (safe_str_neq(v->current, value)) {
        crm_info("Setting %s[%s]: %s -> %s from %s",
                 attr, host, v->current, value, peer->uname);
        free(v->current);
        v->current = (value? strdup(value) : NULL);
        a->changed = TRUE;

        // Write out new value or start dampening timer
        if (a->timeout_ms && a->timer) {
            crm_trace("Delayed write out (%dms) for %s", a->timeout_ms, attr);
            mainloop_timer_start(a->timer);
        } else {
            write_or_elect_attribute(a);
        }

    } else {
        if (is_force_write && a->timeout_ms && a->timer) {
            /* Save forced writing and set change flag. */
            /* The actual attribute is written by Writer after election. */
            crm_trace("Unchanged %s[%s] from %s is %s(Set the forced write flag)", attr, host, peer->uname, value);
            a->force_write = TRUE;
        } else {
            crm_trace("Unchanged %s[%s] from %s is %s", attr, host, peer->uname, value);
        }
    }

    /* Set the seen flag for attribute processing held only in the own node. */
    v->seen = TRUE;

    /* If this is a cluster node whose node ID we are learning, remember it */
    if ((v->nodeid == 0) && (v->is_remote == FALSE)
        && (crm_element_value_int(xml, F_ATTRD_HOST_ID, (int*)&v->nodeid) == 0)) {

        crm_node_t *known_peer = crm_get_peer(v->nodeid, host);

        crm_trace("Learned %s has node id %s",
                  known_peer->uname, known_peer->uuid);
        if (attrd_election_won()) {
            write_attributes(FALSE, FALSE);
        }
    }
}
Exemplo n.º 11
0
int
main(int argc, char **argv)
{
    gboolean apply = FALSE;
    gboolean raw_1 = FALSE;
    gboolean raw_2 = FALSE;
    gboolean use_stdin = FALSE;
    gboolean as_cib = FALSE;
    gboolean no_version = FALSE;
    int argerr = 0;
    int flag;
    xmlNode *object_1 = NULL;
    xmlNode *object_2 = NULL;
    xmlNode *output = NULL;
    const char *xml_file_1 = NULL;
    const char *xml_file_2 = NULL;

    int option_index = 0;

    crm_log_cli_init("crm_diff");
    crm_set_options(NULL, "original_xml operation [options]", long_options,
                    "A utility for comparing Pacemaker configurations (XML format)\n\n"
                    "The tool produces a custom (diff-like) output which it can also apply like a patch\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 'o':
                xml_file_1 = optarg;
                break;
            case 'O':
                xml_file_1 = optarg;
                raw_1 = TRUE;
                break;
            case 'n':
                xml_file_2 = optarg;
                break;
            case 'N':
                xml_file_2 = optarg;
                raw_2 = TRUE;
                break;
            case 'p':
                xml_file_2 = optarg;
                apply = TRUE;
                break;
            case 's':
                use_stdin = TRUE;
                break;
            case 'c':
                as_cib = TRUE;
                break;
            case 'u':
                no_version = TRUE;
                break;
            case 'V':
                crm_bump_log_level(argc, argv);
                break;
            case '?':
            case '$':
                crm_help(flag, EX_OK);
                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");
    }

    if (optind > argc) {
        ++argerr;
    }

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

    if (raw_1) {
        object_1 = string2xml(xml_file_1);

    } else if (use_stdin) {
        fprintf(stderr, "Input first XML fragment:");
        object_1 = stdin2xml();

    } else if (xml_file_1 != NULL) {
        object_1 = filename2xml(xml_file_1);
    }

    if (raw_2) {
        object_2 = string2xml(xml_file_2);

    } else if (use_stdin) {
        fprintf(stderr, "Input second XML fragment:");
        object_2 = stdin2xml();

    } else if (xml_file_2 != NULL) {
        object_2 = filename2xml(xml_file_2);
    }

    if (object_1 == NULL) {
        fprintf(stderr, "Could not parse the first XML fragment\n");
        return 1;
    }
    if (object_2 == NULL) {
        fprintf(stderr, "Could not parse the second XML fragment\n");
        return 1;
    }

    if (apply) {
        int rc;

        output = copy_xml(object_1);
        rc = xml_apply_patchset(output, object_2, as_cib);
        if(rc != pcmk_ok) {
            fprintf(stderr, "Could not apply patch: %s\n", pcmk_strerror(rc));
            return rc;
        }
    } else {
        xml_track_changes(object_2, NULL, object_2, FALSE);
        xml_calculate_changes(object_1, object_2);
        crm_log_xml_debug(object_2, xml_file_2?xml_file_2:"target");

        output = xml_create_patchset(0, object_1, object_2, NULL, FALSE);

        xml_log_changes(LOG_INFO, __FUNCTION__, object_2);
        xml_accept_changes(object_2);

        if (output) {
            patchset_process_digest(output, object_1, object_2, as_cib);
        }

        if(as_cib && output) {
            int add[] = { 0, 0, 0 };
            int del[] = { 0, 0, 0 };

            const char *fmt = NULL;
            const char *digest = NULL;

            xml_patch_versions(output, add, del);
            fmt = crm_element_value(output, "format");
            digest = crm_element_value(output, XML_ATTR_DIGEST);

            if (add[2] != del[2] || add[1] != del[1] || add[0] != del[0]) {
                crm_info("Patch: --- %d.%d.%d %s", del[0], del[1], del[2], fmt);
                crm_info("Patch: +++ %d.%d.%d %s", add[0], add[1], add[2], digest);
            }

        } else if (output && no_version) {
            int format = 1;

            crm_element_value_int(output, "format", &format);
            if (format == 2) {
                xmlNode *version_xml = find_xml_node(output, "version", FALSE);

                if (version_xml) {
                    free_xml(version_xml);
                }

            } else {
                int i = 0;

                const char *tags[] = {
                    XML_TAG_DIFF_REMOVED,
                    XML_TAG_DIFF_ADDED,
                };

                const char *vfields[] = {
                    XML_ATTR_GENERATION_ADMIN,
                    XML_ATTR_GENERATION,
                    XML_ATTR_NUMUPDATES,
                };

                for (i = 0; i < DIMOF(tags); i++) {
                    xmlNode *tmp = NULL;

                    tmp = find_xml_node(output, tags[i], FALSE);
                    if (tmp) {
                        int lpc = 0;

                        for (lpc = 0; lpc < DIMOF(vfields); lpc++) {
                            xml_remove_prop(tmp, vfields[lpc]);
                        }

                        tmp = find_xml_node(tmp, XML_TAG_CIB, FALSE);
                        if (tmp) {
                            for (lpc = 0; lpc < DIMOF(vfields); lpc++) {
                                xml_remove_prop(tmp, vfields[lpc]);
                            }
                        }
                    }
                }
            }
        }
        xml_log_patchset(LOG_NOTICE, __FUNCTION__, output);
    }

    if (output != NULL) {
        char *buffer = dump_xml_formatted(output);

        fprintf(stdout, "%s\n", crm_str(buffer));
        free(buffer);

        fflush(stdout);

        if (apply) {
            const char *version = crm_element_value(output, XML_ATTR_CRM_VERSION);

            buffer = calculate_xml_versioned_digest(output, FALSE, TRUE, version);
            crm_trace("Digest: %s\n", crm_str(buffer));
            free(buffer);
        }
    }

    free_xml(object_1);
    free_xml(object_2);
    free_xml(output);

    if (apply == FALSE && output != NULL) {
        return 1;
    }

    return 0;
}