diff --git a/heartbeat/openstack-info b/heartbeat/openstack-info index c88c338dd..0d6dc985e 100755 --- a/heartbeat/openstack-info +++ b/heartbeat/openstack-info @@ -1,265 +1,289 @@ #!/bin/sh # # # OCF resource agent to set attributes from Openstack instance details. # It records (in the CIB) various attributes of a node # # Copyright (c) 2018 Mathieu Grzybek # All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Further, this software is distributed without any warranty that it is # free of the rightful claim of any third person regarding infringement # or the like. Any license provided herein, whether implied or # otherwise, applies only to this software file. Patent licenses, if # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs # Defaults OCF_RESKEY_pidfile_default="$HA_RSCTMP/OSInfo-${OCF_RESOURCE_HOSTNAME}" OCF_RESKEY_delay_default="0" OCF_RESKEY_clone_default="0" +OCF_RESKEY_curlcli_default="/usr/bin/curl" OCF_RESKEY_openstackcli_default="/usr/bin/openstack" +OCF_RESKEY_pythoncli_default="/usr/libexec/platform-python" +: ${OCF_RESKEY_curlcli=${OCF_RESKEY_curlcli_default}} : ${OCF_RESKEY_openstackcli=${OCF_RESKEY_openstackcli_default}} +: ${OCF_RESKEY_pythoncli=${OCF_RESKEY_pythoncli_default}} : ${OCF_RESKEY_pidfile=${OCF_RESKEY_pidfile_default}} : ${OCF_RESKEY_delay=${OCF_RESKEY_delay_default}} : ${OCF_RESKEY_clone=${OCF_RESKEY_clone_default}} ####################################################################### meta_data() { cat < 1.0 OCF resource agent to set attributes from Openstack instance details. It records (in the CIB) various attributes of a node. Sample output: openstack_az : nova openstack_flavor : c1.small openstack_id : 60ac4343-5828-49b1-8aac-7c69b1417f31 openstack_ports : 7960d889-9750-4160-bf41-c69a41ad72d9:96530d18-57a3-4718-af32-30f2a74c22a2,b0e55a06-bd75-468d-8baa-22cfeb65799f:a55ae917-8016-4b1e-8ffa-04311b9dc7d6 The layout of openstack_ports is a comma-separated list of tuples "subnet_id:port_id". Records various node attributes in the CIB PID file PID file Interval to allow values to stabilize Dampening Delay Valid Openstack credentials as openrc file from api_access/openrc. openrc file + + +Path to command line cURL binary. + +Path to cURL binary + + + Path to command line tools for openstack. Path to Openstack CLI tool + + +Path to command line Python interpreter. + +Path to Python interpreter + + + END } ####################################################################### OSInfoStats() { local result local value local node local node_id . $OCF_RESKEY_openrc - node=$(crm_node -n|awk -F. '{print $1}') - - result=$($OCF_RESKEY_openstackcli server list \ - --format value --column ID --column Name \ - | grep $node) + # Nova data: server ID + node_id=$($OCF_RESKEY_curlcli \ + -s http://169.254.169.254/openstack/latest/meta_data.json | + $OCF_RESKEY_pythoncli -m json.tool | + grep -P '\"uuid\": \".*\",$' | + grep -P -o '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}') if [ $? -ne 0 ] ; then - ocf_exit_reason "cannot find $node in instances list" + ocf_exit_reason "Cannot find server ID" exit $OCF_ERR_GENERIC fi - node_id=$(echo $result|awk '{print $1}') - # Nova data: flavor, AZ… - result=$($OCF_RESKEY_openstackcli server show \ + ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_id -v "$node_id" + + # Nova data: flavor + value=$($OCF_RESKEY_openstackcli server show \ --format value \ --column flavor \ - --column OS-EXT-AZ:availability_zone \ - $node_id | tr '\n' ' ') + $node_id) - ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_id -v $node_id + ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_flavor -v "$value" - value=$(echo $result|awk '{print $2}') - ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_flavor -v $value + # Nova data: availability zone + value=$($OCF_RESKEY_openstackcli server show \ + --format value \ + --column OS-EXT-AZ:availability_zone \ + $node_id) - value=$(echo $result|awk '{print $1}') - ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_az -v $value + ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_az -v "$value" # Network data: ports - result=$($OCF_RESKEY_openstackcli port list \ + value="" + for port_id in $($OCF_RESKEY_openstackcli port list \ --format value \ - --column device_id \ --column id \ - --column "Fixed IP Addresses" \ - | awk "/^$node_id/ {gsub(\"subnet_id='\",\"\");gsub(\"'\",\"\");print \$NF\":\"\$2}" | tr '\n' ' ') - - value="" - for p in $result ; do - if [ -z "$value" ] ; then - value="$p" - else - value="$value,$p" - fi + --server $node_id); do + subnet_id=$($OCF_RESKEY_openstackcli port show \ + --format json \ + --column fixed_ips \ + ${port_id} | grep -P '\"subnet_id\": \".*\",$' | + grep -P -o '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}') + value+="${subnet_id}:${port_id}," done + value=$(echo ${value} | sed -e 's/,$//g') + ${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" 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 } OSInfo_usage() { cat < $OCF_RESKEY_pidfile OSInfoStats exit $OCF_SUCCESS } OSInfo_stop() { rm -f $OCF_RESKEY_pidfile ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_id ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_flavor ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_az ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_ports ${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 } OSInfo_monitor() { if [ -f "$OCF_RESKEY_pidfile" ] ; then OSInfoStats exit $OCF_RUNNING fi exit $OCF_NOT_RUNNING } OSInfo_validate() { + check_binary "$OCF_RESKEY_curlcli" check_binary "$OCF_RESKEY_openstackcli" + check_binary "$OCF_RESKEY_pythoncli" if [ -z "$OCF_RESKEY_openrc" ]; then ocf_exit_reason "openrc parameter not set" return $OCF_ERR_CONFIGURED fi if [ ! -f "$OCF_RESKEY_openrc" ] ; then ocf_exit_reason "openrc file not found" return $OCF_ERR_CONFIGURED fi return $OCF_SUCCESS } if [ $# -ne 1 ]; then OSInfo_usage exit $OCF_ERR_ARGS fi if [ x != x${OCF_RESKEY_delay} ]; then OCF_RESKEY_delay="-d ${OCF_RESKEY_delay}" fi case $__OCF_ACTION in meta-data) meta_data exit $OCF_SUCCESS ;; start) OSInfo_start ;; stop) OSInfo_stop ;; monitor) OSInfo_monitor ;; validate-all) OSInfo_validate ;; usage|help) OSInfo_usage exit $OCF_SUCCESS ;; *) OSInfo_usage exit $OCF_ERR_UNIMPLEMENTED ;; esac exit $?