diff options
Diffstat (limited to '')
-rwxr-xr-x | heartbeat/Route | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/heartbeat/Route b/heartbeat/Route new file mode 100755 index 0000000..7db41d0 --- /dev/null +++ b/heartbeat/Route @@ -0,0 +1,348 @@ +#!/bin/sh +# +# Route OCF RA. Enables and disables network routes. +# +# (c) 2008-2010 Florian Haas, Dejan Muhamedagic, +# and Linux-HA contributors +# +# 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 + +# Default values +OCF_RESKEY_device_default="" +OCF_RESKEY_gateway_default="" +OCF_RESKEY_source_default="" +OCF_RESKEY_table_default="" +OCF_RESKEY_family_default="detect" + +: ${OCF_RESKEY_device=${OCF_RESKEY_device_default}} +: ${OCF_RESKEY_gateway=${OCF_RESKEY_gateway_default}} +: ${OCF_RESKEY_source=${OCF_RESKEY_source_default}} +: ${OCF_RESKEY_table=${OCF_RESKEY_table_default}} +: ${OCF_RESKEY_family=${OCF_RESKEY_family_default}} + +####################################################################### + +meta_data() { + cat <<END +<?xml version="1.0"?> +<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> +<resource-agent name="Route" version="1.0"> +<version>1.0</version> + +<longdesc lang="en"> +Enables and disables network routes. + +Supports host and net routes, routes via a gateway address, +and routes using specific source addresses. + +This resource agent is useful if a node's routing table +needs to be manipulated based on node role assignment. + +Consider the following example use case: + + - One cluster node serves as an IPsec tunnel endpoint. + + - All other nodes use the IPsec tunnel to reach hosts + in a specific remote network. + +Then, here is how you would implement this scheme making use +of the Route resource agent: + + - Configure an ipsec LSB resource. + + - Configure a cloned Route OCF resource. + + - Create an order constraint to ensure + that ipsec is started before Route. + + - Create a colocation constraint between the + ipsec and Route resources, to make sure no instance + of your cloned Route resource is started on the + tunnel endpoint itself. +</longdesc> +<shortdesc lang="en">Manages network routes</shortdesc> + +<parameters> + +<parameter name="destination" unique="1" required="1"> +<longdesc lang="en"> +The destination network (or host) to be configured for the route. +Specify the netmask suffix in CIDR notation (e.g. "/24"). +If no suffix is given, a host route will be created. +Specify "0.0.0.0/0" or "default" if you want this resource to set +the system default route. +</longdesc> +<shortdesc lang="en">Destination network</shortdesc> +<content type="string" /> +</parameter> + +<parameter name="device" unique="0"> +<longdesc lang="en"> +The outgoing network device to use for this route. +</longdesc> +<shortdesc lang="en">Outgoing network device</shortdesc> +<content type="string" default="${OCF_RESKEY_device_default}" /> +</parameter> + +<parameter name="gateway" unique="0"> +<longdesc lang="en"> +The gateway IP address to use for this route. +</longdesc> +<shortdesc lang="en">Gateway IP address</shortdesc> +<content type="string" default="${OCF_RESKEY_gateway_default}" /> +</parameter> + +<parameter name="source" unique="0"> +<longdesc lang="en"> +The source IP address to be configured for the route. +</longdesc> +<shortdesc lang="en">Source IP address</shortdesc> +<content type="string" default="${OCF_RESKEY_source_default}" /> +</parameter> + +<parameter name="table" unique="0"> +<longdesc lang="en"> +The routing table to be configured for the route. +</longdesc> +<shortdesc lang="en">Routing table</shortdesc> +<content type="string" default="${OCF_RESKEY_table_default}" /> +</parameter> + +<parameter name="family" unique="0"> +<longdesc lang="en"> +The address family to be used for the route +ip4 IP version 4 +ip6 IP version 6 +detect Detect from 'destination' address. +</longdesc> +<shortdesc lang="en">Address Family</shortdesc> +<content type="string" default="${OCF_RESKEY_family_default}" /> +</parameter> + +</parameters> + +<actions> +<action name="start" timeout="20s" /> +<action name="stop" timeout="20s" /> +<action name="monitor" timeout="20s" interval="10s" + depth="0"/> +<action name="reload" timeout="20s" /> +<action name="meta-data" timeout="5s" /> +<action name="validate-all" timeout="20s" /> +</actions> +</resource-agent> +END +} + +####################################################################### + +create_route_spec() { + # Creates a route specification for use by "ip route (add|del|show)" + route_spec="to ${OCF_RESKEY_destination}" + if [ -n "${OCF_RESKEY_device}" ]; then + route_spec="${route_spec} dev ${OCF_RESKEY_device}" + fi + if [ -n "${OCF_RESKEY_gateway}" ]; then + route_spec="${route_spec} via ${OCF_RESKEY_gateway}" + fi + if [ -n "${OCF_RESKEY_source}" ]; then + route_spec="${route_spec} src ${OCF_RESKEY_source}" + fi + if [ -n "${OCF_RESKEY_table}" ]; then + route_spec="${route_spec} table ${OCF_RESKEY_table}" + fi + echo "$route_spec" +} + +route_usage() { + cat <<END +usage: $0 {start|stop|status|monitor|validate-all|meta-data} + +Expects to have a fully populated OCF RA-compliant environment set. +END +} + +route_start() { + route_validate || exit $? + + route_status + status=$? + if [ $status -eq $OCF_SUCCESS ]; then + ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : already started." + return $OCF_SUCCESS + fi + route_spec="$(create_route_spec)" + if ip route add $route_spec; then + ocf_log info "${OCF_RESOURCE_INSTANCE} Added network route: $route_spec" + return $OCF_SUCCESS + else + ocf_exit_reason "${OCF_RESOURCE_INSTANCE} Failed to add network route: $route_spec" + fi + return $OCF_ERR_GENERIC +} + +route_stop() { + route_status + status=$? + case $status in + $OCF_SUCCESS) + route_spec="$(create_route_spec)" + if ip route del $route_spec; then + ocf_log info "${OCF_RESOURCE_INSTANCE} Removed network route: $route_spec" + return $OCF_SUCCESS + else + ocf_exit_reason "${OCF_RESOURCE_INSTANCE} Failed to remove network route: $route_spec" + fi + ;; + $OCF_NOT_RUNNING) + ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : already stopped." + return $OCF_SUCCESS + ;; + esac + return $OCF_ERR_GENERIC +} + +route_status() { + show_output="$(ip $addr_family route show $(create_route_spec) 2>/dev/null)" + if [ $? -eq 0 ]; then + if [ -n "$show_output" ]; then + # "ip route show" returned zero, and produced output on + # stdout. That is what we expect. + return $OCF_SUCCESS + else + # "ip route show" returned zero, but produced no + # output on stdout. Assume the route was cleanly + # unconfigured. + return $OCF_NOT_RUNNING + fi + else + # "ip route show" returned an error code. Assume something + # went wrong. + if ocf_is_probe; then + return $OCF_NOT_RUNNING + else + return $OCF_ERR_GENERIC + fi + fi +} + +route_validate() { + # If we're running as a clone, are the clone meta attrs OK? + if [ "${OCF_RESKEY_CRM_meta_clone}" ]; then + if [ "${OCF_RESKEY_CRM_meta_clone_node_max}" != 1 ]; then + ocf_exit_reason "Misconfigured clone parameters. Must set meta attribute \"clone_node_max\" to 1, got ${OCF_RESKEY_CRM_meta_clone_node_max}." + return $OCF_ERR_CONFIGURED + fi + fi + # Did we get a destination? + if [ -z "${OCF_RESKEY_destination}" ]; then + ocf_exit_reason "Missing required parameter \"destination\"." + return $OCF_ERR_CONFIGURED + fi + # Did we get either a device or a gateway address? + if [ -z "${OCF_RESKEY_device}" -a -z "${OCF_RESKEY_gateway}" ]; then + ocf_exit_reason "Must specify either \"device\", or \"gateway\", or both." + return $OCF_ERR_CONFIGURED + fi + # If a device has been configured, is it available on this system? + if [ -n "${OCF_RESKEY_device}" ]; then + if ! ip link show ${OCF_RESKEY_device} >/dev/null 2>&1; then + ocf_exit_reason "Network device ${OCF_RESKEY_device} appears not to be available on this system." + # OCF_ERR_ARGS prevents the resource from running anywhere at all, + # maybe another node has the interface? + # OCF_ERR_INSTALLED just prevents starting on this particular node. + return $OCF_ERR_INSTALLED + fi + fi + + # The following tests must return $OCF_ERR_INSTALLED, but only if + # the resource is actually running (i.e., not during probes) + if ! ocf_is_probe; then + # If a source address has been configured, is it available on + # this system? + if [ -n "${OCF_RESKEY_source}" ]; then + if ! ip address show | grep -w ${OCF_RESKEY_source} >/dev/null 2>&1; then + ocf_exit_reason "Source address ${OCF_RESKEY_source} appears not to be available on this system." + # same reason as with _device: + return $OCF_ERR_INSTALLED + fi + fi + # If a gateway address has been configured, is it reachable? + if [ -n "${OCF_RESKEY_gateway}" ]; then + if ! ip route get ${OCF_RESKEY_gateway} >/dev/null 2>&1; then + ocf_exit_reason "Gateway address ${OCF_RESKEY_gateway} is unreachable." + # same reason as with _device: + return $OCF_ERR_INSTALLED + fi + fi + fi + return $OCF_SUCCESS +} + +# These two actions must always succeed +case $__OCF_ACTION in +meta-data) meta_data + # OCF variables are not set when querying meta-data + exit 0 + ;; +usage|help) route_usage + exit $OCF_SUCCESS + ;; +esac + +# Don't do anything if the necessary utilities aren't present +for binary in ip grep; do + check_binary $binary +done + +case $OCF_RESKEY_family in + ip4) addr_family="-4" ;; + ip6) addr_family="-6" ;; + detect) + case $OCF_RESKEY_destination in + *:*) addr_family="-6" ;; + *.*) addr_family="-4" ;; + *) ocf_exit_reason "Address family detection requires a numeric destination address." ;; + esac ;; + *) ocf_exit_reason "Address family '${OCF_RESKEY_family}' not recognized." ;; +esac + +case $__OCF_ACTION in +start) route_start;; +stop) route_stop;; +status|monitor) route_status;; +reload) ocf_log info "Reloading..." + route_start + ;; +validate-all) route_validate;; +*) route_usage + exit $OCF_ERR_UNIMPLEMENTED + ;; +esac +rc=$? +ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION returned $rc" +exit $rc |