Skip to content

Commit

Permalink
Merge branch '1.1' of github.com:ClusterLabs/pacemaker into 1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
beekhof committed Apr 13, 2015
2 parents 64c8833 + d768c39 commit dec0b68
Show file tree
Hide file tree
Showing 38 changed files with 681 additions and 204 deletions.
4 changes: 4 additions & 0 deletions cib/io.c
Expand Up @@ -78,6 +78,8 @@ retrieveCib(const char *filename, const char *sigfile)
{
xmlNode *root = NULL;

crm_info("Reading cluster configuration file %s (digest: %s)",
filename, sigfile);
switch (cib_file_read_and_verify(filename, sigfile, &root)) {
case -pcmk_err_cib_corrupt:
crm_warn("Continuing but %s will NOT be used.", filename);
Expand Down Expand Up @@ -230,6 +232,8 @@ readCibXmlFile(const char *dir, const char *file, gboolean discard_status)
filename = crm_strdup_printf("%s/%s", cib_root, namelist[lpc]->d_name);
sigfile = crm_concat(filename, "sig", '.');

crm_info("Reading cluster configuration file %s (digest: %s)",
filename, sigfile);
if (cib_file_read_and_verify(filename, sigfile, &root) < 0) {
crm_warn("Continuing but %s will NOT be used.", filename);
} else {
Expand Down
67 changes: 53 additions & 14 deletions extra/resources/docker-wrapper
Expand Up @@ -31,6 +31,8 @@

#######################################################################

CONF_PREFIX="pcmk_docker"

meta_data() {
cat <<END
<?xml version="1.0"?>
Expand All @@ -44,24 +46,33 @@ Docker technology wrapper for pacemaker remote.
<shortdesc lang="en">docker wrapper</shortdesc>
<parameters>
<parameter name="pcmk_docker_image" required="1" >
<parameter name="${CONF_PREFIX}_image" required="1" >
<longdesc lang="en">
Docker image to run resources within
</longdesc>
<shortdesc lang="en">docker image</shortdesc>
<content type="string" default="" />
</parameter>
<parameter name="pcmk_docker_privileged" >
<parameter name="${CONF_PREFIX}_privileged" >
<longdesc lang="en">
Give resources within container access to cluster resources
such as the CIB and the ability to manage cluster attributes.
NOTE: Do not confuse this with the docker run command's
'--priviledged' option which gives a container permission
to access system devices. To toggle the docker run option,
set --priviledged=true as part of the ${CONF_PREFIS}_run_opts
arguments. The ${CONF_PREFIX}_privileged option only pertains
to whether or not the container has access to the cluster's
CIB or not. Some multistate resources need to be able to write
values to the cib, which would require enabling ${CONF_PREFIX}_privileged
</longdesc>
<shortdesc lang="en">is privileged</shortdesc>
<content type="string" default="false" />
</parameter>
<parameter name="pcmk_docker_run_opts" required="0" unique="0">
<parameter name="${CONF_PREFIX}_run_opts" required="0" unique="0">
<longdesc lang="en">
Add options to be appended to the 'docker run' command which is used
when creating the container during the start action. This option allows
Expand All @@ -78,6 +89,16 @@ agent will set --name using the resource's instance name
<content type="string"/>
</parameter>
<parameter name="${CONF_PREFIX}_reuse" required="0" unique="0">
<longdesc lang="en">
Allow the container to be reused after stopping the container. By default
containers are removed after stop. With the reuse option containers
will persist after the container stops.
</longdesc>
<shortdesc lang="en">reuse container</shortdesc>
<content type="boolean"/>
</parameter>
</parameters>
<actions>
Expand Down Expand Up @@ -113,6 +134,10 @@ fi
RSC_STATE_DIR="${HA_RSCTMP}/docker-wrapper/${CONTAINER}-data/"
RSC_STATE_FILE="$RSC_STATE_DIR/$OCF_RESOURCE_INSTANCE.state"
CONNECTION_FAILURE=0
HOST_LOG_DIR="${HA_RSCTMP}/docker-wrapper/${CONTAINER}-logs"
HOST_LOG_FILE="$HOST_LOG_DIR/pacemaker.log"
GUEST_LOG_DIR="/var/log/pcmk"
GUEST_LOG_FILE="$GUEST_LOG_DIR/pacemaker.log"

pcmk_docker_wrapper_usage() {
cat <<END
Expand Down Expand Up @@ -181,18 +206,18 @@ separate_args()
key="$(echo $line | awk -F= '{print $1}' | sed 's/^OCF_RESKEY_//g')"
val="$(echo $line | awk -F= '{print $2}')"
KEY_VAL_STR="$KEY_VAL_STR -k '$key' -v '$val'"
done < <(printenv | grep "^OCF.*" | grep -v "^OCF_RESKEY_pcmk_docker_.*")
done < <(printenv | grep "^OCF.*" | grep -v "^OCF_RESKEY_${CONF_PREFIX}_.*")

# sanitize args for DOCKER agent's consumption
while read -r line;
do
env="$(echo $line | awk -F= '{print $1}')"
val="$(echo $line | awk -F= '{print $2}')"
key="$(echo "$env" | sed 's/^OCF_RESKEY_pcmk_docker/OCF_RESKEY/g')"
key="$(echo "$env" | sed "s/^OCF_RESKEY_${CONF_PREFIX}/OCF_RESKEY/g")"
export $key="$val"
done < <(printenv | grep "^OCF_RESKEY_pcmk_docker_.*")
done < <(printenv | grep "^OCF_RESKEY_${CONF_PREFIX}_.*")

if ocf_is_true $OCF_RESKEY_pcmk_docker_privileged ; then
if ocf_is_true $OCF_RESKEY_privileged ; then
export OCF_RESKEY_run_cmd="/usr/sbin/pacemaker_remoted"
# on start set random port to run_opts
# write port to state file... or potentially get from ps? maybe docker info or inspect as well?
Expand Down Expand Up @@ -270,15 +295,17 @@ client_action()
agent_type="$agent_type -P $PROVIDER"
fi

if ocf_is_true $OCF_RESKEY_pcmk_docker_privileged ; then
if ocf_is_true $OCF_RESKEY_privileged ; then
if [ -z "$PORT" ]; then
get_active_port
fi
export PCMK_logfile=$HOST_LOG_FILE
ocf_log info "$CLIENT -c 'exec' -S '127.0.0.1' -p '$PORT' -a '$action' -r '$OCF_RESOURCE_INSTANCE' -n '$CONTAINER' '$agent_type' $KEY_VAL_STR "
eval $CLIENT -c 'exec' -S '127.0.0.1' -p '$PORT' -a '$action' -r '$OCF_RESOURCE_INSTANCE' -n '$CONTAINER' '$agent_type' $KEY_VAL_STR
else
export PCMK_logfile=$GUEST_LOG_FILE
ocf_log info "$CLIENT -c \"exec\" -a $action -r \"$OCF_RESOURCE_INSTANCE\" $agent_type $KEY_VAL_STR"
echo "$CLIENT -c \"exec\" -a $action -r \"$OCF_RESOURCE_INSTANCE\" $agent_type $KEY_VAL_STR " | nsenter --target $(docker inspect --format {{.State.Pid}} ${CONTAINER}) --mount --uts --ipc --net --pid 2>&1
echo "$CLIENT -c \"exec\" -a $action -r \"$OCF_RESOURCE_INSTANCE\" $agent_type $KEY_VAL_STR " | nsenter --target $(docker inspect --format {{.State.Pid}} ${CONTAINER}) --mount --uts --ipc --net --pid
fi
rc=$?

Expand All @@ -289,7 +316,7 @@ client_action()
poke_remote()
{
# verifies daemon in container is active
if ocf_is_true $OCF_RESKEY_pcmk_docker_privileged ; then
if ocf_is_true $OCF_RESKEY_privileged ; then
get_active_port
ocf_log info "Attempting to contect $CONTAINER on port $PORT"
$CLIENT -c "poke" -S "127.0.0.1" -p $PORT -n $CONTAINER
Expand All @@ -308,8 +335,10 @@ start_container()
return $rc
fi

export OCF_RESKEY_run_opts="-e PCMK_debug=yes -e PCMK_logfile=/var/log/pacemaker.log $OCF_RESKEY_run_opts"
if ocf_is_true $OCF_RESKEY_pcmk_docker_privileged ; then
mkdir -p $HOST_LOG_DIR
export OCF_RESKEY_run_opts="-e PCMK_logfile=$GUEST_LOG_FILE $OCF_RESKEY_run_opts"
export OCF_RESKEY_run_opts="-v $HOST_LOG_DIR:$GUEST_LOG_DIR $OCF_RESKEY_run_opts"
if ocf_is_true $OCF_RESKEY_privileged ; then
if ! [ -f "/etc/pacemaker/authkey" ]; then
# generate an authkey if it doesn't exist.
mkdir -p /etc/pacemaker/
Expand All @@ -332,7 +361,11 @@ start_container()
$DOCKER_AGENT start
rc=$?
if [ $rc -ne $OCF_SUCCESS ]; then
ocf_exit_reason "Docker container failed to start"

docker ps > /dev/null 2>&1
if [ $? -ne 0 ]; then
ocf_exit_reason "docker daemon is inactive."
fi
return $rc
fi

Expand All @@ -356,7 +389,12 @@ pcmk_docker_wrapper_start() {
fi

pcmk_docker_wrapper_monitor
return $?
rc=$?
if [ $rc -eq $OCF_SUCCESS ]; then
ocf_log notice "$OCF_RESOURCE_INSTANCE started successfully. Container's logfile can be found at $HOST_LOG_FILE"
fi

return $rc
}

stop_container()
Expand Down Expand Up @@ -446,6 +484,7 @@ pcmk_docker_wrapper_stop() {
}

pcmk_docker_wrapper_validate() {
check_binary docker

if [ -z "$CLASS" ] || [ -z "$TYPE" ]; then
ocf_exit_reason "Update pacemaker to a version that supports container wrappers."
Expand Down
5 changes: 3 additions & 2 deletions lib/cib/cib_file.c
Expand Up @@ -145,7 +145,6 @@ cib_file_read_and_verify(const char *filename, const char *sigfile, xmlNode **ro
}

/* Parse XML */
crm_info("Reading cluster configuration file %s", filename);
local_root = filename2xml(filename);
if (local_root == NULL) {
crm_warn("Cluster configuration file %s is corrupt (unparseable as XML)", filename);
Expand All @@ -158,7 +157,6 @@ cib_file_read_and_verify(const char *filename, const char *sigfile, xmlNode **ro
}

/* Verify that digests match */
crm_debug("Verifying cluster configuration signature from %s", sigfile);
if (cib_file_verify_digest(local_root, sigfile) == FALSE) {
free(local_sigfile);
free_xml(local_root);
Expand Down Expand Up @@ -369,6 +367,7 @@ cib_file_write_with_digest(xmlNode *cib_root, const char *cib_dirname,
&& (tmp_cib != NULL) && (tmp_digest != NULL));

/* Ensure the admin didn't modify the existing CIB underneath us */
crm_trace("Reading cluster configuration file %s", cib_path);
rc = cib_file_read_and_verify(cib_path, NULL, NULL);
if ((rc != pcmk_ok) && (rc != -ENOENT)) {
crm_err("%s was manually modified while the cluster was active!",
Expand Down Expand Up @@ -439,6 +438,8 @@ cib_file_write_with_digest(xmlNode *cib_root, const char *cib_dirname,
crm_debug("Wrote digest %s to disk", digest);

/* Verify that what we wrote is sane */
crm_info("Reading cluster configuration file %s (digest: %s)",
tmp_cib, tmp_digest);
rc = cib_file_read_and_verify(tmp_cib, tmp_digest, NULL);
CRM_ASSERT(rc == 0);

Expand Down
5 changes: 4 additions & 1 deletion lib/pengine/clone.c
Expand Up @@ -450,7 +450,10 @@ clone_print(resource_t * rsc, const char *pre_text, long options, void *print_da
if (location) {
enum rsc_role_e a_role = child_rsc->fns->state(child_rsc, TRUE);

if (a_role > RSC_ROLE_SLAVE) {
if (location->details->online == FALSE && location->details->unclean) {
print_full = TRUE;

} else if (a_role > RSC_ROLE_SLAVE) {
/* And active on a single node as master */
master_list = g_list_append(master_list, location);

Expand Down
65 changes: 47 additions & 18 deletions lib/pengine/complex.c
Expand Up @@ -337,6 +337,50 @@ add_template_rsc(xmlNode * xml_obj, pe_working_set_t * data_set)
return TRUE;
}

static void
handle_rsc_isolation(resource_t *rsc)
{
resource_t *top = uber_parent(rsc);
resource_t *iso = rsc;
const char *wrapper = NULL;
const char *value;

/* check for isolation wrapper mapping if the parent doesn't have one set
* isolation mapping is enabled by default. For safety, we are allowing isolation
* to be disabled by setting the meta attr, isolation=false. */
value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ISOLATION);
if (top->isolation_wrapper == NULL && (value == NULL || crm_is_true(value))) {
if (g_hash_table_lookup(rsc->meta, "pcmk_docker_image")) {
wrapper = "docker-wrapper";
}
/* add more isolation technologies here as we expand */
} else if (top->isolation_wrapper) {
goto set_rsc_opts;
}

if (wrapper == NULL) {
return;
}

/* if this is a cloned primitive/group, go head and set the isolation wrapper at
* at the clone level. this is really the only sane thing to do in this situation.
* This allows someone to clone an isolated resource without having to shuffle
* around the isolation attributes to the clone parent */
if (top == rsc->parent && top->variant >= pe_clone) {
iso = top;
}

iso->isolation_wrapper = wrapper;
set_bit(top->flags, pe_rsc_unique);

set_rsc_opts:
clear_bit(rsc->flags, pe_rsc_allow_migrate);
set_bit(rsc->flags, pe_rsc_unique);
if (top->variant >= pe_clone) {
add_hash_param(rsc->meta, XML_RSC_ATTR_UNIQUE, XML_BOOLEAN_TRUE);
}
}

gboolean
common_unpack(xmlNode * xml_obj, resource_t ** rsc,
resource_t * parent, pe_working_set_t * data_set)
Expand Down Expand Up @@ -496,26 +540,11 @@ common_unpack(xmlNode * xml_obj, resource_t ** rsc,

pe_rsc_trace((*rsc), "Options for %s", (*rsc)->id);

top = uber_parent(*rsc);

/* check for isolation wrapper mapping if the parent doesn't have one set
* isolation mapping is enabled by default. For safety, we are allowing isolation
* to be disabled by setting the meta attr, isolation=false. */
value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_ISOLATION);
if (top->isolation_wrapper == NULL && (value == NULL || crm_is_true(value))) {
if (g_hash_table_lookup((*rsc)->meta, "pcmk_docker_image")) {
(*rsc)->isolation_wrapper = "docker-wrapper";
clear_bit((*rsc)->flags, pe_rsc_allow_migrate);
}
/* add more isolation technologies here as we expand */
}
if (top->isolation_wrapper) {
/* never allow resources with an isolation wrapper migrate */
clear_bit((*rsc)->flags, pe_rsc_allow_migrate);
}
handle_rsc_isolation(*rsc);

top = uber_parent(*rsc);
value = g_hash_table_lookup((*rsc)->meta, XML_RSC_ATTR_UNIQUE);
if (crm_is_true(value) || top->variant < pe_clone || (*rsc)->isolation_wrapper) {
if (crm_is_true(value) || top->variant < pe_clone) {
set_bit((*rsc)->flags, pe_rsc_unique);
}

Expand Down
20 changes: 12 additions & 8 deletions lib/pengine/native.c
Expand Up @@ -487,9 +487,9 @@ native_print(resource_t * rsc, const char *pre_text, long options, void *print_d
offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED ");
}
if(rsc->role > RSC_ROLE_SLAVE && is_set(rsc->flags, pe_rsc_failed)) {
offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s ", role2text(rsc->role));
offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s", role2text(rsc->role));
} else if(is_set(rsc->flags, pe_rsc_failed)) {
offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED ");
offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED");
} else {
const char *rsc_state = NULL;

Expand All @@ -514,32 +514,36 @@ native_print(resource_t * rsc, const char *pre_text, long options, void *print_d
offset += snprintf(buffer + offset, LINE_MAX - offset, "(target-role:%s) ", target_role);
}
}
offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", rsc_state);
offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_state);
}

if(node) {
offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", node->details->uname);
offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", node->details->uname);

if (node->details->online == FALSE && node->details->unclean) {
offset += snprintf(buffer + offset, LINE_MAX - offset, " (UNCLEAN)");
}
}

if (options & pe_print_pending) {
const char *pending_task = native_pending_task(rsc);

if (pending_task) {
offset += snprintf(buffer + offset, LINE_MAX - offset, "(%s) ", pending_task);
offset += snprintf(buffer + offset, LINE_MAX - offset, " (%s)", pending_task);
}
}

if(is_not_set(rsc->flags, pe_rsc_managed)) {
offset += snprintf(buffer + offset, LINE_MAX - offset, "(unmanaged) ");
offset += snprintf(buffer + offset, LINE_MAX - offset, " (unmanaged)");
}
if(is_set(rsc->flags, pe_rsc_failure_ignored)) {
offset += snprintf(buffer + offset, LINE_MAX - offset, "(failure ignored)");
offset += snprintf(buffer + offset, LINE_MAX - offset, " (failure ignored)");
}

if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) {
const char *desc = crm_element_value(rsc->xml, XML_ATTR_DESC);
if(desc) {
offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", desc);
offset += snprintf(buffer + offset, LINE_MAX - offset, " %s", desc);
}
}

Expand Down
2 changes: 1 addition & 1 deletion lrmd/remote_ctl.c
Expand Up @@ -489,7 +489,7 @@ main(int argc, char **argv)
if (optind > argc) {
++argerr;
}
crm_log_init("remote_client", LOG_INFO, TRUE, options.verbose ? TRUE : FALSE, argc, argv, FALSE);
crm_log_init("remote_client", LOG_INFO, FALSE, options.verbose ? TRUE : FALSE, argc, argv, FALSE);

/* if we can't perform an api_call or listen for events,
* there is nothing to do */
Expand Down
3 changes: 3 additions & 0 deletions mcp/pacemaker.combined.upstart.in
Expand Up @@ -2,6 +2,9 @@
#
# Starts Corosync cluster engine and Pacemaker cluster manager.

# if you use automatic start, uncomment the line below.
#start on started local and runlevel [2345]

stop on runlevel [0123456]
kill timeout 3600
respawn
Expand Down

0 comments on commit dec0b68

Please sign in to comment.