Skip to content

Instantly share code, notes, and snippets.

@mbaldessari
Last active September 12, 2017 15:20
Show Gist options
  • Save mbaldessari/74d696df9b9b5f697e3cab127a6dc24f to your computer and use it in GitHub Desktop.
Save mbaldessari/74d696df9b9b5f697e3cab127a6dc24f to your computer and use it in GitHub Desktop.
#!/bin/bash
# by Damien Ciabrini & Michele Baldessari
# This function takes the resource name as a parameter and returns
# "clone", "master", "primitive" or exits with 1
function get_resource_type() {
local clone_count
local master_count
local primitive_count
local bundle_count
local resource_name
resource_name=$1
clone_count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resources/clone[@multi_state='false']/resource[@id='$resource_name']/@id)" -)
master_count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resources/clone[@multi_state='true']/resource[@id='$resource_name']/@id)" -)
primitive_count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resources/resource[@id='$resource_name']/@id)" -)
bundle_count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resources/bundle[@id='$resource_name']/@id)" -)
if [ $clone_count -gt 0 ]; then
echo "clone";
elif [ $master_count -gt 0 ]; then
echo "master";
elif [ $primitive_count -gt 0 ]; then
echo "primitive";
elif [ $bundle_count -gt 0 ]; then
echo "bundle"
else
echo "unrecognized resource type for $resource (c:$clone_count m:$master_count p:$primitive_count)"
exit 1
fi
}
# This function takes a resource name (the resource must be of master
# type) and returns the master-max attribute if present or 1 if the
# attribute is not present. It exists 1 in case of errors.
function get_master_max() {
local resource_name
local ret
local status
resource_name=$1
ret=$(crm_resource -r $resource_name --meta -g master-max 2>/dev/null)
status=$?
if [ $status -eq 0 ]; then
echo $ret
elif [ $status -eq 6 ]; then
echo 1
else
echo "Error fetching master max for $resource"
exit 1
fi
}
# This function takes a resource name which should be of type "clone"
# and returns the clone-max attribute if present. If clone-max is not
# present it returns the number of nodes which have the property
# "$resourcename-role" set to true (composable ha). If that number is
# 0 (pre-composable ha), we count the number of nodes in the cluster
# We return -1 in case of errors
function get_clone_count() {
local count
local resource_name
local ret
local rolename
local status
resource_name=$1
rolename="${resource_name}-role"
ret=$(crm_resource -r $resource_name --meta -g clone-max 2>/dev/null)
status=$?
if [ $status -eq 0 ]; then
echo $ret
elif [ $status -eq 6 ]; then
# if there are no $rolename properties it means we are in pre-composable HA and we need
# to use the number of corosync nodes
count=$(pcs property | grep -c "$rolename=true")
if [ $count = "0" ]; then
# FIXME what happens if pacemaker remote is configured
count=$(crm_node -l | wc -l)
echo $count
else
echo $count
fi
else
echo -1
fi
}
function get_bundle_replicas() {
cibadmin --query --xpath "//resources/bundle[@id='$1']/docker" | xmllint --xpath "string(/docker/@replicas)" -
}
function get_bundle_masters() {
cibadmin --query --xpath "//resources/bundle[@id='$1']/docker" | xmllint --xpath "string(/docker/@masters)" -
}
# Returns empty if the bundle has no primitive inside it (e.g. haproxy)
function get_bundle_primitive_name() {
cibadmin --query --xpath "//resources/bundle[@id='$1']" | xmllint --xpath "string(/bundle/primitive/@id)" -
}
function resource_active() {
echo "$1 is active"
exit 0
}
function resource_not_active() {
echo "$1 is inactive"
exit 0
}
# Takes the resource name as an argument and does the following:
# a) master/slave resources
# returns active only if the needed number of masters is set
# e.g. galera needs to be master on all nodes where galera is supposed
# to run (that is == to the number of controllers in pre-composable ha
# and the number of nodes with galera-role=true properties set
# in composable ha)
# redis will need to have master on only one node
# b) cloned resources
# returns active if the resource is started on the needed nodes
# e.g. same as master/slave resources the needed number of nodes is
# equal to the cluster nodes in pre-composable and to the haproxy-role
# property count in composable ha
# c) primitive resources
# returns active if the resource is started on one node
# e.g. A/P resources like cinder-volume, VIPs
function is_resource_active() {
local count
local master_max
local resource_name
local resource_type
local to_be_count
resource_name=$1
resource_type=$(get_resource_type $resource)
if [ $resource_type = "master" ]; then
master_max=$(get_master_max $resource)
count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resource[@id='$resource_name' and @orphaned='false' and @failed='false' and @active='true' and @role='Master'])" -)
if [ $count -eq $master_max ]; then
resource_active $resource_name
else
resource_not_active $resource_name
fi
elif [ $resource_type = "clone" ]; then
to_be_count=$(get_clone_count $resource)
count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resource[@id='$resource_name' and @orphaned='false' and @failed='false' and @active='true' and @role='Started'])" -)
if [ $to_be_count -eq $count ]; then
resource_active $resource_name
else
resource_not_active $resource_name
fi
elif [ $resource_type = "primitive" ]; then
count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resource[@id='$resource_name' and @orphaned='false' and @failed='false' and @active='true' and @role='Started'])" -)
if [ $count -eq 1 ]; then
resource_active $resource_name
else
resource_not_active $resource_name
fi
elif [ $resource_type = "bundle" ]; then
# we check that count of replicas is the active number of bundles of the bundle
# if replicas == counted active bundles
# fetch the primitive inside the bundle
#if $(contains_primitive $resource_name); then
primitive_name=$(get_bundle_primitive_name $resource_name)
if [ ! -z "$primitive_name" ]; then
expected_count=$(get_bundle_masters $resource_name)
if [ ! -z "$expected_count" ]; then
# master/slave
count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resource[@id='$primitive_name' and @orphaned='false' and @failed='false' and @active='true' and @role='Master'])" -)
if [ $count -eq $expected_count ]; then
resource_active $resource_name
else
resource_not_active $resource_name
fi
else
# clone
expected_count=$(get_bundle_replicas $resource_name)
count=$(crm_mon -r --as-xml | xmllint --xpath "count(//resource[@id='$primitive_name' and @orphaned='false' and @failed='false' and @active='true' and @role='Started'])" -)
if [ $count -eq $expected_count ]; then
resource_active $resource_name
else
resource_not_active $resource_name
fi
fi
else
# no primitive
expected_count=$(get_bundle_replicas $resource_name)
count=$(crm_mon -r --as-xml | xmllint --xpath "count(//bundle[@id='$resource_name']/replica/resource[@orphaned='false' and @failed='false' and @active='true' and @role='Started'])" -)
if [ $count -eq $expected_count ]; then
resource_active $resource_name
else
resource_not_active $resource_name
fi
fi
fi
}
resource=$1
is_resource_active $resource
@beekhof
Copy link

beekhof commented Mar 2, 2017

looks sane to me
you skipped groups, but we don't use them in OSP

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment