diff --git a/heartbeat/aliyun-vpc-move-ip b/heartbeat/aliyun-vpc-move-ip index a57bbfe34..46e997910 100755 --- a/heartbeat/aliyun-vpc-move-ip +++ b/heartbeat/aliyun-vpc-move-ip @@ -1,311 +1,344 @@ #!/bin/sh # # OCF resource agent to move an IP address within a VPC in the Aliyun # Based on code of Markus Guertler (GitHub AWS-VPC-move-IP) # Based on code of Adam Gandelman (GitHub ec2-resource-agents/elasticip) # ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs # Parameter defaults OCF_RESKEY_address_default="" OCF_RESKEY_routing_table_default="" OCF_RESKEY_interface_default="eth0" OCF_RESKEY_profile_default="default" +OCF_RESKEY_endpoint_default="vpc.aliyuncs.com" +OCF_RESKEY_aliyuncli_default="aliyuncli" + : ${OCF_RESKEY_address=${OCF_RESKEY_address_default}} : ${OCF_RESKEY_routing_table=${OCF_RESKEY_routing_table_default}} : ${OCF_RESKEY_interface=${OCF_RESKEY_interface_default}} : ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}} +: ${OCF_RESKEY_endpoint=${OCF_RESKEY_endpoint_default}} +: ${OCF_RESKEY_aliyuncli=${OCF_RESKEY_aliyuncli_default}} ####################################################################### -# aliyuncli doesnt work without HOME parameter +# aliyun cli doesnt work without HOME parameter export HOME="/root" USAGE="usage: $0 {start|stop|status|meta-data}"; + +if [[ "${OCF_RESKEY_aliyuncli##*/}" == 'aliyuncli' ]]; then + OUTPUT="text" + EXECUTING='{ print $3 }' + IFS_=" " + ENDPOINT="" +elif [[ "${OCF_RESKEY_aliyuncli##*/}" == 'aliyun' ]]; then + OUTPUT="table cols=InstanceId,DestinationCidrBlock rows=RouteTables.RouteTable[].RouteEntrys.RouteEntry[]" + EXECUTING='{ gsub (" ", "", $0); print $1 }' + IFS_="|" + ENDPOINT="--endpoint $OCF_RESKEY_endpoint" +fi ############################################################################### ############################################################################### # # Functions # ############################################################################### +request_create_route_entry() { + cmd="${OCF_RESKEY_aliyuncli} vpc CreateRouteEntry --RouteTableId $OCF_RESKEY_routing_table --DestinationCidrBlock ${OCF_RESKEY_address}/32 --NextHopId $ECS_INSTANCE_ID --NextHopType Instance ${ENDPOINT}" + ocf_log debug "executing command: $cmd" + $cmd +} + +request_delete_route_entry() { + cmd="${OCF_RESKEY_aliyuncli} vpc DeleteRouteEntry --RouteTableId $OCF_RESKEY_routing_table --DestinationCidrBlock ${OCF_RESKEY_address}/32 --NextHopId $ROUTE_TO_INSTANCE ${ENDPOINT}" + ocf_log debug "executing command: $cmd" + $cmd +} +request_describe_route_tables() { + cmd="${OCF_RESKEY_aliyuncli} vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output ${OUTPUT} ${ENDPOINT}" + ocf_log debug "executing command: $cmd" + ROUTE_TO_INSTANCE=$($cmd |grep $OCF_RESKEY_address | awk -F "${IFS_}" "${EXECUTING}") +} ip_get_and_configure() { ocf_log debug "function: ip_get_and_configure" - ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" - + request_describe_route_tables if [ "$ECS_INSTANCE_ID" != "$ROUTE_TO_INSTANCE" ]; then if [ -n "$ROUTE_TO_INSTANCE" ]; then ip_drop fi - - cmd="aliyuncli vpc CreateRouteEntry --RouteTableId $OCF_RESKEY_routing_table --DestinationCidrBlock ${OCF_RESKEY_address}/32 --NextHopId $ECS_INSTANCE_ID --NextHopType Instance --output text" - ocf_log debug "executing command: $cmd" - $cmd + request_create_route_entry rc=$? while [ $rc -ne 0 ]; do sleep 1 - cmd="aliyuncli vpc CreateRouteEntry --RouteTableId $OCF_RESKEY_routing_table --DestinationCidrBlock ${OCF_RESKEY_address}/32 --NextHopId $ECS_INSTANCE_ID --NextHopType Instance --output text" - ocf_log debug "executing command: $cmd" - $cmd + request_create_route_entry rc=$? done wait_for_started fi # Reconfigure the local ip address ip addr add "${OCF_RESKEY_address}/32" dev $OCF_RESKEY_interface rc=$? if [ $rc -ne 0 ]; then ocf_log err "command failed, rc: $rc" return $OCF_ERR_GENERIC fi ocf_log debug "IP added" return $OCF_SUCCESS } ip_drop() { ocf_log debug "function: ip_drop" cmd="ip addr delete ${OCF_RESKEY_address}/32 dev $OCF_RESKEY_interface" ocf_log debug "executing command: $cmd" $cmd rc=$? if [ $rc -ne 0 ] && [ $rc -ne 2 ]; then ocf_log err "command failed, rc $rc" return $OCF_ERR_GENERIC fi - - cmd="aliyuncli vpc DeleteRouteEntry --RouteTableId $OCF_RESKEY_routing_table --DestinationCidrBlock ${OCF_RESKEY_address}/32 --NextHopId $ROUTE_TO_INSTANCE --output text" - ocf_log debug "executing command: $cmd" - $cmd + request_delete_route_entry if [ $? -ne 0 ]; then ocf_log err "command failed, rc: $rc" return $OCF_ERR_GENERIC fi wait_for_deleted ocf_log debug "IP dropped" return $OCF_SUCCESS } wait_for_started() { - cmd="aliyuncli vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output text" - ocf_log debug "executing command: $cmd" - ROUTE_TO_INSTANCE="$($cmd | grep $OCF_RESKEY_address | awk '{ print $3 }')" - + request_describe_route_tables while [ "$ECS_INSTANCE_ID" != "$ROUTE_TO_INSTANCE" ]; do sleep 3 - cmd="aliyuncli vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output text" - ocf_log debug "executing command: $cmd" - ROUTE_TO_INSTANCE="$($cmd | grep $OCF_RESKEY_address | awk '{ print $3 }')" + request_describe_route_tables done } wait_for_deleted() { - ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" - + request_describe_route_tables while [ ! -z "$ROUTE_TO_INSTANCE" ]; do sleep 1 - cmd="aliyuncli vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output text" - ocf_log debug "executing command: $cmd" - ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" + request_describe_route_tables done } ecs_ip_metadata() { cat < 2.0 Resource Agent to move IP addresses within a VPC of the Aliyun Webservices ECS by changing an entry in an specific routing table Move IP within a VPC of the Aliyun ECS + + + +Path to command line tools for Aliyun + +Path to Aliyun CLI tools + + + VPC private IP address vpc ip + Name of the routing table, where the route for the IP address should be changed, i.e. vtb-... routing table name + Name of the network interface, i.e. eth0 network interface name - + + -Valid Aliyun CLI profile name (see 'aliyuncli configure'). +An endpoint is the service entry of an Alibaba Cloud service, i.e. vpc.cn-beijing.aliyuncs.com + +service endpoint + + -See https://www.alibabacloud.com/help/doc-detail/43039.htm?spm=a2c63.p38356.b99.16.38a914abRZtOU3 for more information about aliyuncli. + + +Valid Aliyun CLI profile name (see 'aliyun cli configure'). +See https://www.alibabacloud.com/help/zh/product/29991.htm for more information about aliyun cli. profile name + END } ecs_ip_validate() { ocf_log debug "function: validate" # IP address if [ -z "$OCF_RESKEY_address" ]; then ocf_log err "IP address parameter not set $OCF_RESKEY_ADDRESS!" exit $OCF_ERR_CONFIGURED fi # Network Interface if [ -z "$OCF_RESKEY_interface" ]; then ocf_log err "Network interface parameter not set $OCF_RESKEY_INTERFACE!" exit $OCF_ERR_CONFIGURED fi # Routing Table if [ -z "$OCF_RESKEY_routing_table" ]; then ocf_log err "Routing table parameter not set $OCF_RESKEY_ROUTING_TABLE!" exit $OCF_ERR_CONFIGURED fi if [ -z "${ECS_INSTANCE_ID}" ]; then ocf_exit_reason "Instance ID not found. Is this a ECS instance?" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } ecs_ip_start() { ocf_log info "ECS: Moving IP address $OCF_RESKEY_address to this host by adjusting routing table $OCF_RESKEY_routing_table" ecs_ip_monitor if [ $? = $OCF_SUCCESS ]; then ocf_log info "ECS: $OCF_RESKEY_address already started" return $OCF_SUCCESS fi ocf_log info "ECS: Adjusting routing table and locally configuring IP address" ip_get_and_configure rc=$? if [ $rc -ne 0 ]; then ocf_log err "Received $rc from 'aliyun cli'" return $OCF_ERR_GENERIC fi ecs_ip_monitor rc=$? if [ $rc -ne $OCF_SUCCESS ]; then ocf_log err "IP address couldn't be configured on this host (IP: $OCF_RESKEY_address, Interface: $OCF_RESKEY_interface)" return $rc fi return $OCF_SUCCESS } ecs_ip_stop() { ocf_log info "ECS: Bringing down IP address $OCF_RESKEY_address" ecs_ip_monitor if [ $? = $OCF_NOT_RUNNING ]; then ocf_log info "ECS: Address $OCF_RESKEY_address already down" return $OCF_SUCCESS fi ip_drop if [ $? -ne $OCF_SUCCESS ]; then ocf_log err "ECS: Couldn't drop IP address $OCF_RESKEY_address on interface $OCF_RESKEY_interface." return $OCF_ERR_GENERIC fi ecs_ip_monitor if [ $? = $OCF_NOT_RUNNING ]; then ocf_log info "ECS: Successfully brought down $OCF_RESKEY_address" return $OCF_SUCCESS fi ocf_log err "ECS: Couldn't bring down IP address $OCF_RESKEY_address on interface $OCF_RESKEY_interface." return $OCF_ERR_GENERIC } ecs_ip_monitor() { ocf_log debug "function: ecsip_monitor: check routing table" - cmd="aliyuncli vpc DescribeRouteTables --RouteTableId $OCF_RESKEY_routing_table --output text" - ocf_log debug "executing command: $cmd" - - ROUTE_TO_INSTANCE="$($cmd |grep $OCF_RESKEY_address | awk '{ print $3 }')" + request_describe_route_tables if [ "$ECS_INSTANCE_ID" != "$ROUTE_TO_INSTANCE" ]; then ocf_log debug "not routed to this instance ($ECS_INSTANCE_ID) but to instance $ROUTE_TO_INSTANCE" return $OCF_NOT_RUNNING fi cmd="ping -W 1 -c 1 $OCF_RESKEY_address" ocf_log debug "executing command: $cmd" $cmd > /dev/null if [ $? -ne 0 ]; then ocf_log debug "IP $OCF_RESKEY_address not locally reachable via ping on this system" return $OCF_NOT_RUNNING fi ocf_log debug "routed in VPC and locally reachable" return $OCF_SUCCESS } ############################################################################### # # MAIN # ############################################################################### case $__OCF_ACTION in meta-data) ecs_ip_metadata exit $OCF_SUCCESS;; validate-all) ecs_ip_validate;; esac ECS_INSTANCE_ID="$(curl -s http://100.100.100.200/latest/meta-data/instance-id)" case $__OCF_ACTION in start) ecs_ip_validate ecs_ip_start;; stop) ecs_ip_stop;; monitor) ecs_ip_monitor;; *) exit $OCF_ERR_UNIMPLEMENTED;; esac