Skip to content

Commit

Permalink
Merge pull request #1411 from kgaillot/1.1
Browse files Browse the repository at this point in the history
Backport fixes from master branch
  • Loading branch information
kgaillot committed Jan 24, 2018
2 parents 8a70419 + 7c322f4 commit cc9e69e
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 15 deletions.
22 changes: 17 additions & 5 deletions crmd/membership.c
Expand Up @@ -438,12 +438,24 @@ crm_update_quorum(gboolean quorum, gboolean force_update)
fsa_register_cib_callback(call_id, FALSE, NULL, cib_quorum_update_complete);
free_xml(update);

/* If a node not running any resources is cleanly shut down and drops us
* below quorum, we won't necessarily abort the transition, so abort it
* here to be safe.
/* Quorum changes usually cause a new transition via other activity:
* quorum gained via a node joining will abort via the node join,
* and quorum lost via a node leaving will usually abort via resource
* activity and/or fencing.
*
* However, it is possible that nothing else causes a transition (e.g.
* someone forces quorum via corosync-cmaptcl, or quorum is lost due to
* a node in standby shutting down cleanly), so here ensure a new
* transition is triggered.
*/
if (quorum == FALSE) {
abort_transition(INFINITY, tg_restart, "Quorum loss", NULL);
if (quorum) {
/* If quorum was gained, abort after a short delay, in case multiple
* nodes are joining around the same time, so the one that brings us
* to quorum doesn't cause all the remaining ones to be fenced.
*/
abort_after_delay(INFINITY, tg_restart, "Quorum gained", 5000);
} else {
abort_transition(INFINITY, tg_restart, "Quorum lost", NULL);
}
}
fsa_has_quorum = quorum;
Expand Down
48 changes: 46 additions & 2 deletions crmd/te_utils.c
Expand Up @@ -530,6 +530,46 @@ trigger_graph_processing(const char *fn, int line)
mainloop_set_trigger(transition_trigger);
}

static struct abort_timer_s {
bool aborted;
guint id;
int priority;
enum transition_action action;
const char *text;
} abort_timer = { 0, };

static gboolean
abort_timer_popped(gpointer data)
{
if (abort_timer.aborted == FALSE) {
abort_transition(abort_timer.priority, abort_timer.action,
abort_timer.text, NULL);
}
abort_timer.id = 0;
return FALSE; // do not immediately reschedule timer
}

/*!
* \internal
* \brief Abort transition after delay, if not already aborted in that time
*
* \param[in] abort_text Must be literal string
*/
void
abort_after_delay(int abort_priority, enum transition_action abort_action,
const char *abort_text, guint delay_ms)
{
if (abort_timer.id) {
// Timer already in progress, stop and reschedule
g_source_remove(abort_timer.id);
}
abort_timer.aborted = FALSE;
abort_timer.priority = abort_priority;
abort_timer.action = abort_action;
abort_timer.text = abort_text;
abort_timer.id = g_timeout_add(delay_ms, abort_timer_popped, NULL);
}

void
abort_transition_graph(int abort_priority, enum transition_action abort_action,
const char *abort_text, xmlNode * reason, const char *fn, int line)
Expand Down Expand Up @@ -557,6 +597,8 @@ abort_transition_graph(int abort_priority, enum transition_action abort_action,
break;
}

abort_timer.aborted = TRUE;

/* Make sure any queued calculations are discarded ASAP */
free(fsa_pe_ref);
fsa_pe_ref = NULL;
Expand Down Expand Up @@ -660,10 +702,12 @@ abort_transition_graph(int abort_priority, enum transition_action abort_action,
(transition_graph->complete? "true" : "false"));

} else {
const char *id = ID(reason);

do_crm_log(level, "Transition aborted by %s.%s '%s': %s "
CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
TYPE(reason), ID(reason), (op? op : "change"), abort_text,
add[0], add[1], add[2], fn, line, path,
TYPE(reason), (id? id : ""), (op? op : "change"),
abort_text, add[0], add[1], add[2], fn, line, path,
(transition_graph->complete? "true" : "false"));
}
}
Expand Down
2 changes: 2 additions & 0 deletions crmd/tengine.h
Expand Up @@ -59,6 +59,8 @@ extern void notify_crmd(crm_graph_t * graph);
# include <te_callbacks.h>

extern void trigger_graph_processing(const char *fn, int line);
void abort_after_delay(int abort_priority, enum transition_action abort_action,
const char *abort_text, guint delay_ms);
extern void abort_transition_graph(int abort_priority, enum transition_action abort_action,
const char *abort_text, xmlNode * reason, const char *fn,
int line);
Expand Down
14 changes: 11 additions & 3 deletions pengine/container.c
Expand Up @@ -486,10 +486,18 @@ container_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc, rsc_colocatio
} else {
node_t *chosen = tuple->docker->fns->location(tuple->docker, NULL, FALSE);

if (chosen != NULL && is_set_recursive(tuple->docker, pe_rsc_block, TRUE) == FALSE) {
pe_rsc_trace(rsc, "Allowing %s: %s %d", constraint->id, chosen->details->uname, chosen->weight);
allocated_rhs = g_list_prepend(allocated_rhs, chosen);
if (chosen == NULL || is_set_recursive(tuple->docker, pe_rsc_block, TRUE)) {
continue;
}
if(constraint->role_rh >= RSC_ROLE_MASTER && tuple->child == NULL) {
continue;
}
if(constraint->role_rh >= RSC_ROLE_MASTER && tuple->child->next_role < RSC_ROLE_MASTER) {
continue;
}

pe_rsc_trace(rsc, "Allowing %s: %s %d", constraint->id, chosen->details->uname, chosen->weight);
allocated_rhs = g_list_prepend(allocated_rhs, chosen);
}
}

Expand Down
21 changes: 16 additions & 5 deletions tools/crm_resource_runtime.c
Expand Up @@ -1343,10 +1343,19 @@ cli_resource_restart(resource_t * rsc, const char *host, int timeout_ms, cib_t *
return rc;
}

#define action_is_pending(action) \
((is_set((action)->flags, pe_action_optional) == FALSE) \
&& (is_set((action)->flags, pe_action_runnable) == TRUE) \
&& (is_set((action)->flags, pe_action_pseudo) == FALSE))
static inline int action_is_pending(action_t *action)
{
if(is_set(action->flags, pe_action_optional)) {
return FALSE;
} else if(is_set(action->flags, pe_action_runnable) == FALSE) {
return FALSE;
} else if(is_set(action->flags, pe_action_pseudo)) {
return FALSE;
} else if(safe_str_eq("notify", action->task)) {
return FALSE;
}
return TRUE;
}

/*!
* \internal
Expand All @@ -1362,7 +1371,9 @@ actions_are_pending(GListPtr actions)
GListPtr action;

for (action = actions; action != NULL; action = action->next) {
if (action_is_pending((action_t *) action->data)) {
action_t *a = (action_t *)action->data;
if (action_is_pending(a)) {
crm_notice("Waiting for %s (flags=0x%.8x)", a->uuid, a->flags);
return TRUE;
}
}
Expand Down

0 comments on commit cc9e69e

Please sign in to comment.