Skip to content

Commit

Permalink
Merge pull request #1228 from mgrzybek/openstack-agents
Browse files Browse the repository at this point in the history
[openstack agents] Volume re-attaching, v3 API, get hostname from corosync
  • Loading branch information
oalbrigt committed Jun 7, 2019
2 parents 571ed61 + caaa215 commit d18126a
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 39 deletions.
201 changes: 172 additions & 29 deletions heartbeat/openstack-cinder-volume
Expand Up @@ -27,7 +27,6 @@
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#


#######################################################################
# Initialization:

Expand All @@ -36,8 +35,14 @@

# Defaults
OCF_RESKEY_openstackcli_default="/usr/bin/openstack"
OCF_RESKEY_node_id_cache_file_default="/tmp/node_id"
OCF_RESKEY_volume_local_check_default="true"

export attached_server_id=""

: ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}}
: ${OCF_RESKEY_node_id_cache_file=${OCF_RESKEY_node_id_cache_file_default}}
: ${OCF_RESKEY_volume_local_check=${OCF_RESKEY_volume_local_check_default}}

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

Expand Down Expand Up @@ -74,6 +79,26 @@ Path to command line tools for openstack.
<content type="string" default="${OCF_RESKEY_openstackcli_default}" />
</parameter>
<parameter name="node_id_cache_file">
<longdesc lang="en">
Path to Node ID cache file, used to avoid Openstack API calls:
1. Is the local file written?
2. Is openstack_id available as a node attribute?
3. Can we get it from the API?
</longdesc>
<shortdesc lang="en">Path to Node ID cache file</shortdesc>
<content type="string" default="${OCF_RESKEY_node_id_cache_file_default}" />
</parameter>
<parameter name="volume_local_check">
<longdesc lang="en">
This option allows the cluster to monitor the cinder volume presence without
calling the API.
</longdesc>
<shortdesc lang="en">Monitor cinder volume locally</shortdesc>
<content type="boolean" default="${OCF_RESKEY_volume_local_check_default}" />
</parameter>
<parameter name="openrc" required="1">
<longdesc lang="en">
Valid Openstack credentials as openrc file from api_access/openrc.
Expand Down Expand Up @@ -103,8 +128,82 @@ Cinder volume identifier to use to attach the bloc storage.
END
}

#
# This is used to get the node ID from different sources:
# 1. Is the local file written?
# 2. Is openstack_id available as a node attribute?
# 3. Can we get it from the API?
#
# When the ID is retrieved, the local cache file is written.
# This prevents the agent to call the API each time the agent is used.
#
_get_node_id() {
local crm_node
local node
local node_id
local result

crm_node=$(crm_node -n)

#
# Use local cache
#
if [ -f $OCF_RESKEY_node_id_cache_file ] ; then
node_id=$(cat $OCF_RESKEY_node_id_cache_file)

if [ ! -z "$node_id" ] ; then
echo $node_id
return
fi
fi

#
# Query the attributes database
#
node_id=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_id -N $crm_node \
| tr ' ' '\n' \
| awk -F= '/value=/ {gsub("\"","");print $NF}')

if [ ! -z "$node_id" ] ; then
echo $node_id | awk '{print $1}'
echo $node_id | awk '{print $1}' > $OCF_RESKEY_node_id_cache_file
return
fi

#
# Use the API
#
node=$(crm_node -n | awk -F. '{print $1}')

result=$($OCF_RESKEY_openstackcli server list \
--format value --column ID --column Name \
| grep $node)

if [ $? -eq 0 ] ; then
echo $result | awk '{print $1}'
echo $result | awk '{print $1}' > $OCF_RESKEY_node_id_cache_file
return
fi

ocf_exit_reason "openstack_id attribute must be set for node $crm_node"
return $OCF_ERR_CONFIGURED
}

osvol_validate() {
local node_id

check_binary "$OCF_RESKEY_openstackcli"
check_binary "awk"
check_binary "tr"

. $OCF_RESKEY_openrc

node_id=$(_get_node_id)

if [ -z "$node_id" ] ; then
ocf_exit_reason "openstack_id attribute must be set for node $crm_node"
return $OCF_ERR_CONFIGURED
fi

if [ -z "$OCF_RESKEY_openrc" ]; then
ocf_exit_reason "openrc parameter not set"
Expand All @@ -116,39 +215,58 @@ osvol_validate() {
return $OCF_ERR_CONFIGURED
fi

. $OCF_RESKEY_openrc

if ! $OCF_RESKEY_openstackcli volume list|grep -q $OCF_RESKEY_volume_id ; then
ocf_exit_reason "Volume $OCF_RESKEY_volume_id not found"
return $OCF_ERR_CONFIGURED
fi

return $OCF_SUCCESS
}

osvol_monitor() {
local result
local attached_server_id
local node_id
local short_volume_id
local fdisk_command

if ocf_is_true $OCF_RESKEY_volume_local_check ; then
#
# Is the volue attached?
# We check the local devices
#
short_volume_id=$(echo $OCF_RESKEY_volume_id | awk '{print substr($0, 0, 20)}')
if uname | grep -q Linux ; then
fdisk_command="fdisk -l"
else
fdisk_command="fdisk"
fi

# Is the volue attached?
result=$($OCF_RESKEY_openstackcli volume show \
--column status \
--column attachments \
--format value \
$OCF_RESKEY_volume_id)

if [[ "$result" =~ "available" ]] ; then
ocf_log warn "$OCF_RESKEY_volume_id is not attached to any instance"
return $OCF_NOT_RUNNING
$fdisk_command /dev/disk/by-id/virtio-$short_volume_id 1>/dev/null 2>&1
if [ $? -eq 0 ] ; then
return $OCF_SUCCESS
else
ocf_log warn "$OCF_RESKEY_volume_id is not attached to instance $(_get_node_id)"
return $OCF_NOT_RUNNING
fi
else
attached_server_id=$(echo $result|head -n1|awk -F "'" '{print $4}')
ocf_log info "$OCF_RESKEY_volume_id is attached to instance $attached_server_id"
node_id=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_id -N $HOSTNAME \
| awk '{gsub("value=","") ; gsub("\"","") ; print $NF}')

if [ "$node_id" != "$attached_server_id" ] ; then
#
# Is the volue attached?
# We use the API
#
result=$($OCF_RESKEY_openstackcli volume show \
--column status \
--column attachments \
--format value \
$OCF_RESKEY_volume_id)

if echo "$result" | grep -q available ; then
ocf_log warn "$OCF_RESKEY_volume_id is not attached to any instance"
return $OCF_NOT_RUNNING
else
export attached_server_id=$(echo $result|head -n1|awk -F "'" '{print $4}')
ocf_log info "$OCF_RESKEY_volume_id is attached to instance $attached_server_id"

# Compare node_id and the id of the node the volume is attached to
node_id=$(_get_node_id)

if [ "$node_id" != "$attached_server_id" ] ; then
return $OCF_NOT_RUNNING
fi
fi
fi

Expand All @@ -158,14 +276,20 @@ osvol_monitor() {
osvol_stop() {
local node_id

#
# Is the volume already attached?
#
osvol_monitor
if [ $? = $OCF_NOT_RUNNING ]; then
ocf_log info "Volume $OCF_RESKEY_volume_id already available"
return $OCF_SUCCESS
fi

node_id=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_id -N $HOSTNAME \
| awk '{gsub("value=","") ; gsub("\"","") ; print $NF}')
node_id=$(_get_node_id)

#
# Unmout the volume
#
if ! $OCF_RESKEY_openstackcli server remove volume $node_id $OCF_RESKEY_volume_id ; then
ocf_log error "Couldn't remove volume $OCF_RESKEY_volume_id from instance $node_id"
return $OCF_ERR_GENERIC
Expand All @@ -178,14 +302,33 @@ osvol_stop() {
osvol_start() {
local node_id

#
# Is the volume already attached?
#
osvol_monitor
if [ $? = $OCF_SUCCESS ]; then
ocf_log info "$OCF_RESKEY_volume_id already attached"
return $OCF_SUCCESS
fi

node_id=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_id -N $HOSTNAME \
| awk '{gsub("value=","") ; gsub("\"","") ; print $NF}')
#
# Unmout it from another node
# TODO: make it optional in case multi-attachment is allowed by Cinder
#
if [ ! -z $attached_server_id ] ; then
if ! $OCF_RESKEY_openstackcli server remove volume $attached_server_id $OCF_RESKEY_volume_id ; then
ocf_log error "Couldn't remove volume $OCF_RESKEY_volume_id from instance $attached_server_id"
return $OCF_ERR_GENERIC
fi
fi

export attached_server_id=""

node_id=$(_get_node_id)

#
# Attach the volume
#
$OCF_RESKEY_openstackcli server add volume $node_id $OCF_RESKEY_volume_id
if [ $? != $OCF_SUCCESS ]; then
ocf_log error "Couldn't add volume $OCF_RESKEY_volume_id to instance $node_id"
Expand Down
18 changes: 12 additions & 6 deletions heartbeat/openstack-floating-ip
Expand Up @@ -132,7 +132,7 @@ osflip_validate() {
return $OCF_ERR_CONFIGURED
fi

${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $HOSTNAME > /dev/null 2>&1
${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $(crm_node -n) > /dev/null 2>&1
if [ $? -ne 0 ] ; then
ocf_log warn "attr_updater failed to get openstack_ports attribute of node $OCF_RESOURCE_INSTANCE"
return $OCF_ERR_GENERIC
Expand All @@ -147,8 +147,10 @@ osflip_monitor() {
local node_port_ids
local port
local buffer
local crm_node

node_port_ids=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $HOSTNAME \
crm_node=$(crm_node -n)
node_port_ids=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $crm_node \
| awk -F= '{gsub("\"","");print $NF}' \
| tr ',' ' ' \
| awk -F: '{print $NF}')
Expand All @@ -162,13 +164,13 @@ osflip_monitor() {
for port in $node_port_ids ; do
if echo $result | grep -q $port ; then
floating_ip=$(echo $result | awk '/floating_ip_address/ {print $2}')
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_floating_ip -v $floating_ip
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n openstack_floating_ip -v $floating_ip

return $OCF_SUCCESS
fi
done

${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_floating_ip
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -S state -n openstack_floating_ip
ocf_log warn "$OCF_RESKEY_ip_id is not attached to any fixed address"
return $OCF_NOT_RUNNING
}
Expand Down Expand Up @@ -207,9 +209,13 @@ osflip_start() {
fi

# Get port_id from subnet_id
node_port_ids=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $HOSTNAME \
node_port_ids=$(${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $(crm_node -n) \
| awk '{gsub("value=","") ; gsub("\"","") ; print $NF}')
node_port_id=$(echo $node_port_ids|tr ',' '\n'|awk -F: "/$OCF_RESKEY_subnet_id/ {print \$2}")

node_port_id=$(echo $node_port_ids \
| tr ',' '\n' \
| awk -F: "/$OCF_RESKEY_subnet_id/ {print \$2}")

ocf_log info "Moving IP address $OCF_RESKEY_ip_id to port ID $node_port_id"

$OCF_RESKEY_openstackcli floating ip set --port $node_port_id $OCF_RESKEY_ip_id
Expand Down
26 changes: 22 additions & 4 deletions heartbeat/openstack-info
Expand Up @@ -115,6 +115,10 @@ OSInfoStats() {
--format value --column ID --column Name \
| grep $node)

if [ $? -ne 0 ] ; then
ocf_exit_reason "cannot find $node in instances list"
exit $OCF_ERR_GENERIC
fi
node_id=$(echo $result|awk '{print $1}')

# Nova data: flavor, AZ…
Expand Down Expand Up @@ -148,14 +152,26 @@ OSInfoStats() {
value="$value,$p"
fi
done
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_ports -v $value
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_ports -v "$value"

if [ ! -z "$OS_REGION_NAME" ] ; then
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_region -v $OS_REGION_NAME
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_region -v "$OS_REGION_NAME"
fi

if [ ! -z "$OS_TENANT_ID" ] ; then
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_tenant_id -v "$OS_TENANT_ID"

if [ ! -z "$OS_TENANT_NAME" ] ; then
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_tenant_name -v "$OS_TENANT_NAME"
fi
else
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_project_id -v "$OS_PROJECT_ID"

if [ ! -z "$OS_PROJECT_NAME" ] ; then
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_project_name -v "$OS_PROJECT_NAME"
fi
fi

${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_tenant_name -v $OS_TENANT_NAME
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_tenant_id -v $OS_TENANT_ID
}

OSInfo_usage() {
Expand All @@ -181,6 +197,8 @@ OSInfo_stop() {
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_region
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_tenant_id
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_tenant_name
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_project_id
${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_project_name
exit $OCF_SUCCESS
}

Expand Down

0 comments on commit d18126a

Please sign in to comment.