Skip to content

Commit

Permalink
Merge pull request #1219 from kgaillot/fail
Browse files Browse the repository at this point in the history
Legacy attrd improvements, plus a few minor fixes
  • Loading branch information
kgaillot committed Feb 3, 2017
2 parents 84b90b0 + 30052ab commit a39ea64
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 107 deletions.
209 changes: 124 additions & 85 deletions attrd/legacy.c
Expand Up @@ -283,6 +283,33 @@ find_hash_entry(xmlNode * msg)
return hash_entry;
}

static void
process_xml_request(xmlNode *xml)
{
attr_hash_entry_t *hash_entry = NULL;
const char *from = crm_element_value(xml, F_ORIG);
const char *op = crm_element_value(xml, F_ATTRD_TASK);
const char *host = crm_element_value(xml, F_ATTRD_HOST);
const char *ignore = crm_element_value(xml, F_ATTRD_IGNORE_LOCALLY);

if (host && safe_str_eq(host, attrd_uname)) {
crm_info("Update relayed from %s", from);
attrd_local_callback(xml);

} else if (safe_str_eq(op, ATTRD_OP_PEER_REMOVE)) {
CRM_CHECK(host != NULL, return);
crm_debug("Removing %s from peer caches for %s", host, from);
crm_remote_peer_cache_remove(host);
reap_crm_member(0, host);

} else if ((ignore == NULL) || safe_str_neq(from, attrd_uname)) {
crm_trace("%s message from %s", op, from);
hash_entry = find_hash_entry(xml);
stop_attrd_timer(hash_entry);
attrd_perform_update(hash_entry);
}
}

#if SUPPORT_HEARTBEAT
static void
attrd_ha_connection_destroy(gpointer user_data)
Expand All @@ -305,23 +332,9 @@ attrd_ha_connection_destroy(gpointer user_data)
static void
attrd_ha_callback(HA_Message * msg, void *private_data)
{
attr_hash_entry_t *hash_entry = NULL;
xmlNode *xml = convert_ha_message(NULL, msg, __FUNCTION__);
const char *from = crm_element_value(xml, F_ORIG);
const char *op = crm_element_value(xml, F_ATTRD_TASK);
const char *host = crm_element_value(xml, F_ATTRD_HOST);
const char *ignore = crm_element_value(xml, F_ATTRD_IGNORE_LOCALLY);

if (host != NULL && safe_str_eq(host, attrd_uname)) {
crm_info("Update relayed from %s", from);
attrd_local_callback(xml);

} else if (ignore == NULL || safe_str_neq(from, attrd_uname)) {
crm_info("%s message from %s", op, from);
hash_entry = find_hash_entry(xml);
stop_attrd_timer(hash_entry);
attrd_perform_update(hash_entry);
}
process_xml_request(xml);
free_xml(xml);
}

Expand Down Expand Up @@ -349,25 +362,9 @@ attrd_cs_dispatch(cpg_handle_t handle,
}

if (xml != NULL) {
attr_hash_entry_t *hash_entry = NULL;
const char *op = crm_element_value(xml, F_ATTRD_TASK);
const char *host = crm_element_value(xml, F_ATTRD_HOST);
const char *ignore = crm_element_value(xml, F_ATTRD_IGNORE_LOCALLY);

/* crm_xml_add_int(xml, F_SEQ, wrapper->id); */
crm_xml_add(xml, F_ORIG, from);

if (host != NULL && safe_str_eq(host, attrd_uname)) {
crm_notice("Update relayed from %s", from);
attrd_local_callback(xml);

} else if (ignore == NULL || safe_str_neq(from, attrd_uname)) {
crm_trace("%s message from %s", op, from);
hash_entry = find_hash_entry(xml);
stop_attrd_timer(hash_entry);
attrd_perform_update(hash_entry);
}

process_xml_request(xml);
free_xml(xml);
}

Expand Down Expand Up @@ -766,36 +763,60 @@ attrd_perform_update(attr_hash_entry_t * hash_entry)
return;
}

void
attrd_local_callback(xmlNode * msg)
/* strlen("value") */
#define plus_plus_len (5)

/*!
* \internal
* \brief Expand attribute values that use "++" or "+="
*
* \param[in] value Attribute value to expand
* \param[in] old_value Previous value of attribute
*
* \return Newly allocated string with expanded value, or NULL if not expanded
*/
static char *
expand_attr_value(const char *value, const char *old_value)
{
static int plus_plus_len = 5;
attr_hash_entry_t *hash_entry = NULL;
const char *from = crm_element_value(msg, F_ORIG);
const char *op = crm_element_value(msg, F_ATTRD_TASK);
const char *attr = crm_element_value(msg, F_ATTRD_ATTRIBUTE);
const char *value = crm_element_value(msg, F_ATTRD_VALUE);
const char *host = crm_element_value(msg, F_ATTRD_HOST);
int value_len = strlen(value);
char *expanded = NULL;

if (safe_str_eq(op, ATTRD_OP_REFRESH)) {
crm_notice("Sending full refresh (origin=%s)", from);
g_hash_table_foreach(attr_hash, update_for_hash_entry, NULL);
return;
} else if (safe_str_eq(op, ATTRD_OP_PEER_REMOVE)) {
/* The legacy code didn't understand this command - swallow silently */
return;
}
if ((value_len >= (plus_plus_len + 2))
&& (value[plus_plus_len] == '+')
&& ((value[plus_plus_len + 1] == '+')
|| (value[plus_plus_len + 1] == '='))) {

if (host != NULL && safe_str_neq(host, attrd_uname)) {
send_cluster_message(crm_get_peer(0, host), crm_msg_attrd, msg, FALSE);
return;
}
int offset = 1;
int int_value = char2score(old_value);

crm_debug("%s message from %s: %s=%s", op, from, attr, crm_str(value));
hash_entry = find_hash_entry(msg);
if (hash_entry == NULL) {
return;
if (value[plus_plus_len + 1] != '+') {
const char *offset_s = value + (plus_plus_len + 2);

offset = char2score(offset_s);
}
int_value += offset;

if (int_value > INFINITY) {
int_value = INFINITY;
}

expanded = crm_itoa(int_value);
}
return expanded;
}

/*!
* \internal
* \brief Update a single node attribute for this node
*
* \param[in] msg XML message with update
* \param[in,out] hash_entry Node attribute structure
*/
static void
update_local_attr(xmlNode *msg, attr_hash_entry_t *hash_entry)
{
const char *value = crm_element_value(msg, F_ATTRD_VALUE);
char *expanded = NULL;

if (hash_entry->uuid == NULL) {
const char *key = crm_element_value(msg, F_ATTRD_KEY);
Expand All @@ -814,44 +835,24 @@ attrd_local_callback(xmlNode * msg)
return;

} else if (value) {
int offset = 1;
int int_value = 0;
int value_len = strlen(value);

if (value_len < (plus_plus_len + 2)
|| value[plus_plus_len] != '+'
|| (value[plus_plus_len + 1] != '+' && value[plus_plus_len + 1] != '=')) {
goto set_unexpanded;
}

int_value = char2score(hash_entry->value);
if (value[plus_plus_len + 1] != '+') {
const char *offset_s = value + (plus_plus_len + 2);

offset = char2score(offset_s);
expanded = expand_attr_value(value, hash_entry->value);
if (expanded) {
crm_info("Expanded %s=%s to %s", hash_entry->id, value, expanded);
value = expanded;
}
int_value += offset;

if (int_value > INFINITY) {
int_value = INFINITY;
}

crm_info("Expanded %s=%s to %d", attr, value, int_value);
crm_xml_add_int(msg, F_ATTRD_VALUE, int_value);
value = crm_element_value(msg, F_ATTRD_VALUE);
}

set_unexpanded:
if (safe_str_eq(value, hash_entry->value) && hash_entry->timer_id) {
/* We're already waiting to set this value */
free(expanded);
return;
}

free(hash_entry->value);
hash_entry->value = NULL;
if (value != NULL) {
hash_entry->value = strdup(value);
crm_debug("New value of %s is %s", attr, value);
hash_entry->value = (expanded? expanded : strdup(value));
crm_debug("New value of %s is %s", hash_entry->id, value);
}

stop_attrd_timer(hash_entry);
Expand All @@ -861,8 +862,46 @@ attrd_local_callback(xmlNode * msg)
} else {
attrd_trigger_update(hash_entry);
}
}

return;
void
attrd_local_callback(xmlNode * msg)
{
attr_hash_entry_t *hash_entry = NULL;
const char *from = crm_element_value(msg, F_ORIG);
const char *op = crm_element_value(msg, F_ATTRD_TASK);
const char *attr = crm_element_value(msg, F_ATTRD_ATTRIBUTE);
const char *value = crm_element_value(msg, F_ATTRD_VALUE);
const char *host = crm_element_value(msg, F_ATTRD_HOST);

if (safe_str_eq(op, ATTRD_OP_REFRESH)) {
crm_notice("Sending full refresh (origin=%s)", from);
g_hash_table_foreach(attr_hash, update_for_hash_entry, NULL);
return;

} else if (safe_str_eq(op, ATTRD_OP_PEER_REMOVE)) {
if (host) {
crm_notice("Broadcasting removal of peer %s", host);
send_cluster_message(NULL, crm_msg_attrd, msg, FALSE);
}
return;

} else if (op && safe_str_neq(op, ATTRD_OP_UPDATE)) {
crm_notice("Ignoring unsupported %s request from %s", op, from);
return;
}

if (host != NULL && safe_str_neq(host, attrd_uname)) {
send_cluster_message(crm_get_peer(0, host), crm_msg_attrd, msg, FALSE);
return;
}

crm_debug("%s message from %s: %s=%s", op, from, attr, crm_str(value));
hash_entry = find_hash_entry(msg);
if (hash_entry == NULL) {
return;
}
update_local_attr(msg, hash_entry);
}

gboolean
Expand Down
30 changes: 14 additions & 16 deletions crmd/attrd.c
Expand Up @@ -31,11 +31,6 @@ update_without_attrd(const char *host_uuid, const char *name, const char *value,

call_opt = crmd_cib_smart_opt();

if (command == 'C') {
erase_status_tag(host_uuid, XML_TAG_TRANSIENT_NODEATTRS, call_opt);
return pcmk_ok;
}

crm_trace("updating status for host_uuid %s, %s=%s",
host_uuid, (name? name : "<null>"), (value? value : "<null>"));
if (value) {
Expand Down Expand Up @@ -90,27 +85,30 @@ update_attrd_helper(const char *host, const char *name, const char *value,
const char *user_name, gboolean is_remote_node,
char command)
{
gboolean rc;
int rc;
int max = 5;
int attrd_opts = attrd_opt_none;

if (is_remote_node) {
#if HAVE_ATOMIC_ATTRD
attrd_opts |= attrd_opt_remote;
#else
/* Talk directly to cib for remote nodes if it's legacy attrd */
int rc;

#if !HAVE_ATOMIC_ATTRD
/* Legacy attrd can handle remote peer remove ('C') requests,
* otherwise talk directly to cib for remote nodes.
*/

/* host is required for updating a remote node */
CRM_CHECK(host != NULL, return;);

/* remote node uname and uuid are equal */
rc = update_without_attrd(host, name, value, user_name, is_remote_node,
command);
if (rc < pcmk_ok) {
log_attrd_error(host, name, value, is_remote_node, command, rc);
if (command != 'C') {
/* remote node uname and uuid are equal */
rc = update_without_attrd(host, name, value, user_name,
is_remote_node, command);
if (rc < pcmk_ok) {
log_attrd_error(host, name, value, is_remote_node, command, rc);
}
return;
}
return;
#endif
}

Expand Down
18 changes: 13 additions & 5 deletions cts/CTStests.py
Expand Up @@ -3032,11 +3032,12 @@ def start_new_test(self, node):

ret = self.startall(None)
if not ret:
return self.failure("Setup failed, start all nodes failed.")
return self.failure("setup failed: could not start all nodes")

self.setup_env(node)
self.start_metal(node)
self.add_dummy_rsc(node)
return True

def __call__(self, node):
return self.failure("This base class is not meant to be called directly.")
Expand All @@ -3056,7 +3057,9 @@ class RemoteBasic(RemoteDriver):
def __call__(self, node):
'''Perform the 'RemoteBaremetal' test. '''

self.start_new_test(node)
if not self.start_new_test(node):
return self.failure(self.fail_string)

self.test_attributes(node)
self.cleanup_metal(node)

Expand All @@ -3074,7 +3077,9 @@ class RemoteStonithd(RemoteDriver):
def __call__(self, node):
'''Perform the 'RemoteStonithd' test. '''

self.start_new_test(node)
if not self.start_new_test(node):
return self.failure(self.fail_string)

self.fail_connection(node)
self.cleanup_metal(node)

Expand Down Expand Up @@ -3115,7 +3120,9 @@ class RemoteMigrate(RemoteDriver):
def __call__(self, node):
'''Perform the 'RemoteMigrate' test. '''

self.start_new_test(node)
if not self.start_new_test(node):
return self.failure(self.fail_string)

self.migrate_connection(node)
self.cleanup_metal(node)

Expand All @@ -3134,7 +3141,8 @@ class RemoteRscFailure(RemoteDriver):
def __call__(self, node):
'''Perform the 'RemoteRscFailure' test. '''

self.start_new_test(node)
if not self.start_new_test(node):
return self.failure(self.fail_string)

# This is an important step. We are migrating the connection
# before failing the resource. This verifies that the migration
Expand Down
2 changes: 1 addition & 1 deletion lrmd/regression.py.in
Expand Up @@ -1029,7 +1029,7 @@ if __name__ == "__main__":
test.add_sys_cmd("rm", "-f %s %s" % (state_file_expected, state_file_default))

# Register and start the resource.
test.add_cmd("-c register_rsc -r test_rsc -P heartbeat -C ocf -T Dummy "
test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy "
"-l 'NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete' "
"%s" % (self.action_timeout))
test.add_cmd("-c exec -r test_rsc -a start -t 6000 %s" % cmd_params)
Expand Down

0 comments on commit a39ea64

Please sign in to comment.