#!/bin/sh # # # OCF resource agent to move a virtual address in an Openstack tenant. # # Copyright (c) 2018 Mathieu GRZYBEK # Based on code of Markus Guertler # 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 . ${OCF_FUNCTIONS_DIR}/openstack-common.sh # Defaults ####################################################################### USAGE="usage: $0 {start|stop|status|meta-data}"; ############################################################################### ############################################################################### # # Functions # ############################################################################### metadata() { cat < 1.0 Resource Agent to move a virtual IP address from an instance to another one by adding an allowed-address pair associated with an instance port. It relies on attributes given by openstack-info resource agent (openstack_ports, openstack_id attributes). The attribute called "openstack_virtual_ip" is updated. Move a virtual IP END common_meta_data cat < Virtual IP Address. IP Address Subnet Identifier to use to attach the address. Subnet ID END } osvip_port_id() { # Get port_id from subnet_id 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}") echo ${node_port_id} } osvip_validate() { check_binary "$OCF_RESKEY_openstackcli" get_config ${HA_SBIN_DIR}/attrd_updater --query -n openstack_ports -N $(crm_node -n) > /dev/null 2>&1 if [ $? -ne 0 ] && ! ocf_is_probe; then ocf_log warn "attr_updater failed to get openstack_ports attribute of node $OCF_RESOURCE_INSTANCE" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } osvip_monitor() { local result node_port_id=$(osvip_port_id) result=$(run_openstackcli "port show \ --format value \ --column allowed_address_pairs \ ${node_port_id}") if echo "$result" | grep -q "$OCF_RESKEY_ip"; then ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -n openstack_virtual_ip -v $OCF_RESKEY_ip return $OCF_SUCCESS fi ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -D -n openstack_virtual_ip ocf_log warn "$OCF_RESKEY_ip is not attached to any fixed address" return $OCF_NOT_RUNNING } osvip_stop() { node_port_id=$(osvip_port_id) ocf_log info "Bringing down IP address $OCF_RESKEY_ip" osvip_monitor if [ $? = $OCF_NOT_RUNNING ]; then ocf_log info "Address $OCF_RESKEY_ip already down" return $OCF_SUCCESS fi mac_address=$(run_openstackcli "port show \ --format value \ --column mac_address \ $node_port_id") echo "${mac_address}" | grep -q -P "^([0-9a-f]{2}:){5}[0-9a-f]{2}$" if [ $? -ne 0 ]; then ocf_log error "MAC address '${mac_address}' is not valid." return $OCF_ERR_GENERIC fi if ! run_openstackcli "port unset \ --allowed-address \ ip-address=$OCF_RESKEY_ip,mac-address=${mac_address} \ $node_port_id"; then return $OCF_ERR_GENERIC fi osvip_monitor if [ $? != $OCF_NOT_RUNNING ]; then ocf_log error "Couldn't unset IP address $OCF_RESKEY_ip." return $OCF_ERR_GENERIC fi ocf_log info "Successfully brought down $OCF_RESKEY_ip" return $OCF_SUCCESS } osvip_start() { node_port_id=$(osvip_port_id) osvip_monitor if [ $? = $OCF_SUCCESS ]; then ocf_log info "$OCF_RESKEY_ip already started" return $OCF_SUCCESS fi ocf_log info "Moving IP address $OCF_RESKEY_ip to port ID $node_port_id" run_openstackcli "port set \ --allowed-address ip-address=$OCF_RESKEY_ip \ $node_port_id" if [ $? != $OCF_SUCCESS ]; then ocf_log error "$OCF_RESKEY_ip Cannot be set to port $node_port_id" return $OCF_ERR_GENERIC fi osvip_monitor if [ $? != $OCF_SUCCESS ]; then ocf_log error "$OCF_RESKEY_ip Cannot be set to port $node_port_id" return $OCF_ERR_GENERIC fi ocf_log info "Successfully brought up $OCF_RESKEY_ip" return $OCF_SUCCESS } ############################################################################### # # MAIN # ############################################################################### case $__OCF_ACTION in meta-data) metadata exit $OCF_SUCCESS ;; usage|help) echo $USAGE exit $OCF_SUCCESS ;; esac if ! ocf_is_root; then ocf_log err "You must be root for $__OCF_ACTION operation." exit $OCF_ERR_PERM fi case $__OCF_ACTION in start) osvip_validate || exit $? osvip_start;; stop) osvip_validate || exit $? osvip_stop;; monitor) osvip_validate || exit $? osvip_monitor;; validate-all) osvip_validate ;; *) echo $USAGE exit $OCF_ERR_UNIMPLEMENTED ;; esac exit $?