diff --git a/daemons/controld/controld_control.c b/daemons/controld/controld_control.c index 1ddcada..1705c14 100644 --- a/daemons/controld/controld_control.c +++ b/daemons/controld/controld_control.c @@ -626,7 +626,7 @@ static pcmk__cluster_option_t crmd_opts[] = { // Already documented in libpe_status (other values must be kept identical) { - "no-quorum-policy", NULL, "enum", "stop, freeze, ignore, suicide", + "no-quorum-policy", NULL, "enum", "stop, freeze, ignore, demote, suicide", "stop", pcmk__valid_quorum, NULL, NULL }, { diff --git a/include/crm/pengine/pe_types.h b/include/crm/pengine/pe_types.h index ed5eb12..f3cb4ef 100644 --- a/include/crm/pengine/pe_types.h +++ b/include/crm/pengine/pe_types.h @@ -61,7 +61,8 @@ enum pe_quorum_policy { no_quorum_freeze, no_quorum_stop, no_quorum_ignore, - no_quorum_suicide + no_quorum_suicide, + no_quorum_demote }; enum node_type { diff --git a/lib/common/options.c b/lib/common/options.c index 9399642..9e041c9 100644 --- a/lib/common/options.c +++ b/lib/common/options.c @@ -407,6 +407,7 @@ pcmk__valid_quorum(const char *value) return safe_str_eq(value, "stop") || safe_str_eq(value, "freeze") || safe_str_eq(value, "ignore") + || safe_str_eq(value, "demote") || safe_str_eq(value, "suicide"); } diff --git a/lib/pengine/common.c b/lib/pengine/common.c index f4f2106..37f287b 100644 --- a/lib/pengine/common.c +++ b/lib/pengine/common.c @@ -54,7 +54,7 @@ static pcmk__cluster_option_t pe_opts[] = { * long description */ { - "no-quorum-policy", NULL, "enum", "stop, freeze, ignore, suicide", + "no-quorum-policy", NULL, "enum", "stop, freeze, ignore, demote, suicide", "stop", pcmk__valid_quorum, "What to do when the cluster does not have quorum", NULL diff --git a/lib/pengine/pe_output.c b/lib/pengine/pe_output.c index 75bf0d5..ad469ab 100644 --- a/lib/pengine/pe_output.c +++ b/lib/pengine/pe_output.c @@ -729,6 +729,11 @@ pe__cluster_options_html(pcmk__output_t *out, va_list args) { out->list_item(out, NULL, "No quorum policy: Stop ALL resources"); break; + case no_quorum_demote: + out->list_item(out, NULL, "No quorum policy: Demote promotable " + "resources and stop all other resources"); + break; + case no_quorum_ignore: out->list_item(out, NULL, "No quorum policy: Ignore"); break; @@ -785,6 +790,11 @@ pe__cluster_options_text(pcmk__output_t *out, va_list args) { out->list_item(out, NULL, "No quorum policy: Stop ALL resources"); break; + case no_quorum_demote: + out->list_item(out, NULL, "No quorum policy: Demote promotable " + "resources and stop all other resources"); + break; + case no_quorum_ignore: out->list_item(out, NULL, "No quorum policy: Ignore"); break; @@ -817,6 +827,10 @@ pe__cluster_options_xml(pcmk__output_t *out, va_list args) { xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "stop"); break; + case no_quorum_demote: + xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "demote"); + break; + case no_quorum_ignore: xmlSetProp(node, (pcmkXmlStr) "no-quorum-policy", (pcmkXmlStr) "ignore"); break; diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c index a219805..a480680 100644 --- a/lib/pengine/unpack.c +++ b/lib/pengine/unpack.c @@ -268,6 +268,9 @@ unpack_config(xmlNode * config, pe_working_set_t * data_set) } else if (safe_str_eq(value, "freeze")) { data_set->no_quorum_policy = no_quorum_freeze; + } else if (safe_str_eq(value, "demote")) { + data_set->no_quorum_policy = no_quorum_demote; + } else if (safe_str_eq(value, "suicide")) { if (is_set(data_set->flags, pe_flag_stonith_enabled)) { int do_panic = 0; @@ -297,6 +300,10 @@ unpack_config(xmlNode * config, pe_working_set_t * data_set) case no_quorum_stop: crm_debug("On loss of quorum: Stop ALL resources"); break; + case no_quorum_demote: + crm_debug("On loss of quorum: " + "Demote promotable resources and stop other resources"); + break; case no_quorum_suicide: crm_notice("On loss of quorum: Fence all remaining nodes"); break; diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c index 5d6b836..f8b631a 100644 --- a/lib/pengine/utils.c +++ b/lib/pengine/utils.c @@ -488,6 +488,20 @@ effective_quorum_policy(pe_resource_t *rsc, pe_working_set_t *data_set) if (is_set(data_set->flags, pe_flag_have_quorum)) { policy = no_quorum_ignore; + + } else if (data_set->no_quorum_policy == no_quorum_demote) { + switch (rsc->role) { + case RSC_ROLE_MASTER: + case RSC_ROLE_SLAVE: + if (rsc->next_role > RSC_ROLE_SLAVE) { + rsc->next_role = RSC_ROLE_SLAVE; + } + policy = no_quorum_ignore; + break; + default: + policy = no_quorum_stop; + break; + } } return policy; }