summaryrefslogtreecommitdiffstats
path: root/heartbeat/iface-macvlan
diff options
context:
space:
mode:
Diffstat (limited to 'heartbeat/iface-macvlan')
-rwxr-xr-xheartbeat/iface-macvlan363
1 files changed, 363 insertions, 0 deletions
diff --git a/heartbeat/iface-macvlan b/heartbeat/iface-macvlan
new file mode 100755
index 0000000..685f886
--- /dev/null
+++ b/heartbeat/iface-macvlan
@@ -0,0 +1,363 @@
+#!/bin/sh
+#
+# OCF Resource Agent compliant iface-macvlan script.
+#
+# Implements network MACVLAN interface management
+#
+# Resource script for MACVLAN dervice from Fabio M. Di Nitto iface-vlan
+# script.
+#
+# Author: Ulrich Goettlich
+#
+# 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.
+#
+#
+
+# TODO:
+#
+# OCF parameters are as below
+# OCF_RESKEY_device
+# OCF_RESKEY_name
+# OCF_RESKEY_mode
+# OCF_RESKEY_mac
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_mode_default="bridge"
+
+: ${OCF_RESKEY_mode=${OCF_RESKEY_mode_default}}
+
+#######################################################################
+
+macvlan_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
+}
+
+macvlan_meta_data() {
+ cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="iface-macvlan" version="1.0">
+ <version>1.0</version>
+
+ <longdesc lang="en">
+ This resource manages MACVLAN network interfaces.
+ It can add, remove, configure MACVLANs.
+ </longdesc>
+
+ <shortdesc lang="en">
+ Manages MACVLAN network interfaces.
+ </shortdesc>
+
+ <parameters>
+ <parameter name="device" unique="0" required="1">
+ <longdesc lang="en">
+ Define the interface where MACVLAN should be attached.
+ </longdesc>
+ <shortdesc lang="en">
+ Network interface.
+ </shortdesc>
+ <content type="string"/>
+ </parameter>
+
+ <parameter name="name" unique="1" required="1">
+ <longdesc lang="en">
+ Define the MACVLAN NAME. It has to be a valid interface name (max 15 characters).
+ </longdesc>
+ <shortdesc lang="en">
+ Define the MACVLAN NAME.
+ </shortdesc>
+ <content type="string"/>
+ </parameter>
+
+ <parameter name="mode" unique="0">
+ <longdesc lang="en">
+ Define the name of the MACVLAN mode (currently only bridge is supported).
+ </longdesc>
+ <shortdesc lang="en">
+ Mode of the macvlan.
+ </shortdesc>
+ <content type="string" default="${OCF_RESKEY_mode_default}" />
+ </parameter>
+
+ <parameter name="mac" unique="1">
+ <longdesc lang="en">
+ Set the interface MAC address explicitly.
+ </longdesc>
+ <shortdesc lang="en">MAC address of the macvlan</shortdesc>
+ <content type="string" />
+</parameter>
+ </parameters>
+
+ <actions>
+ <action name="start" timeout="30s" />
+ <action name="stop" timeout="20s" />
+ <action name="status" timeout="20s" depth="0" interval="10s" />
+ <action name="monitor" timeout="20s" depth="0" interval="10s" />
+ <action name="meta-data" timeout="5s" />
+ <action name="validate-all" timeout="20s" />
+ </actions>
+</resource-agent>
+END
+}
+
+# check if the interface is admin up/down
+
+iface_is_up() {
+ if ! $IP2UTIL -o link show $1 | \
+ sed -e 's#.*<##g' -e 's#>.*##' -e 's#LOWER_UP##g' | \
+ grep -q UP; then
+ return 1
+ fi
+ return 0
+}
+
+# check if the slaves have link layer up/down
+# see kernel network documentation on meaning of LOWER_UP flag
+# for more in depth explanation on how it works
+# NOTE: this check is not reliable in virt environment
+# since interfaces are always LOWER_UP. There is no way
+# from the guest to know if the host has disconnected somehow
+
+iface_lower_is_up() {
+ if ! $IP2UTIL -o link show $1 | \
+ grep -q LOWER_UP; then
+ return 1
+ fi
+ return 0
+}
+
+macvlan_validate() {
+ check_binary $IP2UTIL
+
+ if [ -z "$OCF_RESKEY_device" ]; then
+ ocf_log err "Invalid device: value cannot be empty"
+ return $OCF_ERR_CONFIGURED
+ fi
+
+ if [ -z "$OCF_RESKEY_name" ]; then
+ ocf_log err "Invalid name: value cannot be empty"
+ return $OCF_ERR_CONFIGURED
+ fi
+
+ # the echo .. is the equivalent of strlen in bash
+ #
+ # /usr/include/linux/if.h:#define IFNAMSIZ 16
+ # needs to include 0 byte end string
+
+ if [ "${#OCF_RESKEY_name}" -gt 15 ]; then
+ ocf_log err "Invalid name: name is too long"
+ return $OCF_ERR_CONFIGURED
+ fi
+
+ if [ ! -d "/sys/class/net" ]; then
+ ocf_log err "Unable to find sysfs network class in /sys"
+ return $OCF_ERR_GENERIC
+ fi
+
+ if [ ! -e "/sys/class/net/$OCF_RESKEY_device" ]; then
+ ocf_log err "Invalid device: $OCF_RESKEY_device does not exists"
+ return $OCF_ERR_ARGS
+ fi
+
+ if [ "${OCF_RESKEY_mode}" != "bridge" ]; then
+ ocf_log err "Invalid mode: only bridge mode is currently supported (because other modes are not tested)"
+ return $OCF_ERR_CONFIGURED
+ fi
+
+ return 0
+}
+
+macvlan_check() {
+ if [ -e "/sys/class/net/$OCF_RESKEY_name" ]; then
+ if [ ! -e "$HA_RSCTMP/iface-macvlan.$OCF_RESKEY_name" ]; then
+ return $OCF_ERR_GENERIC
+ fi
+ else
+ if [ -e "$HA_RSCTMP/iface-macvlan.$OCF_RESKEY_name" ]; then
+ error="$(rm -f "$HA_RSCTMP/iface-macvlan.$OCF_RESKEY_name" 2>&1)"
+ if [ "$?" != "0" ]; then
+ ocf_log err "Unable to remove stale lock file for macvlan $OCF_RESKEY_name: $error"
+ return $OCF_ERR_INSTALLED
+ fi
+ fi
+ return $OCF_NOT_RUNNING
+ fi
+
+ if ! iface_is_up $OCF_RESKEY_name; then
+ ocf_log err "MACVLAN $OCF_RESKEY_name is administratively down"
+ return $OCF_ERR_GENERIC
+ fi
+
+ if ! iface_lower_is_up $OCF_RESKEY_name; then
+ ocf_log err "MACVLAN $OCF_RESKEY_name has no active link-layer"
+ return $OCF_ERR_GENERIC
+ fi
+
+ return $OCF_SUCCESS
+}
+
+# we need a simpler stop version to clean after us if start fails
+# without involving any error checking
+# rolling back in case of failure is otherwise complex
+
+macvlan_force_stop() {
+ $IP2UTIL link delete "$OCF_RESKEY_name" >/dev/null 2>&1
+ rm -f "$HA_RSCTMP/iface-macvlan.$OCF_RESKEY_name" 2>&1
+}
+
+macvlan_start() {
+ # check if the macvlan already exists
+ macvlan_check
+ ret=$?
+ if [ "$ret" != "$OCF_NOT_RUNNING" ]; then
+ return $ret
+ fi
+
+ # create the MACVLAN
+ set_specific_mac=""
+ [ -n "${OCF_RESKEY_mac}" ] && set_specific_mac="address ${OCF_RESKEY_mac}"
+ error="$($IP2UTIL link add link "$OCF_RESKEY_device" ${set_specific_mac} name "$OCF_RESKEY_name" type macvlan mode "$OCF_RESKEY_mode" 2>&1)"
+ if [ "$?" != "0" ]; then
+ ocf_log err "Unable to create MACVLAN $OCF_RESKEY_name: $error"
+ return $OCF_ERR_GENERIC
+ fi
+
+ # set the interface up
+ error="$($IP2UTIL link set dev "$OCF_RESKEY_device" up 2>&1)"
+ if [ "$?" != "0" ]; then
+ ocf_log err "Unable to set MACVLAN $OCF_RESKEY_device up: $error"
+ return $OCF_ERR_GENERIC
+ fi
+
+ # set the macvlan up
+ error="$($IP2UTIL link set dev "$OCF_RESKEY_name" up 2>&1)"
+ if [ "$?" != "0" ]; then
+ ocf_log err "Unable to set MACVLAN $OCF_RESKEY_name up: $error"
+ return $OCF_ERR_GENERIC
+ fi
+
+ error="$(touch "$HA_RSCTMP/iface-macvlan.$OCF_RESKEY_name" 2>&1)"
+ if [ "$?" != "0" ]; then
+ ocf_log err "Unable to create lock file for MACVLAN $OCF_RESKEY_name: $error"
+ return $OCF_ERR_GENERIC
+ fi
+
+ return $OCF_SUCCESS
+}
+
+macvlan_stop() {
+ macvlan_check
+ ret=$?
+ if [ "$ret" = "$OCF_NOT_RUNNING" ]; then
+ return $OCF_SUCCESS
+ fi
+ if [ "$ret" != "$OCF_SUCCESS" ]; then
+ return $ret
+ fi
+
+ # set macvlan down
+ error="$($IP2UTIL link set dev "$OCF_RESKEY_name" down 2>&1)"
+ if [ "$?" != "0" ]; then
+ ocf_log err "Unable to set MACVLAN $OCF_RESKEY_name down: $error"
+ return $OCF_ERR_GENERIC
+ fi
+
+ # delete macvlan
+ error="$($IP2UTIL link delete "$OCF_RESKEY_name" 2>&1)"
+ if [ "$?" != "0" ]; then
+ ocf_log err "Unable to delete MACVLAN $OCF_RESKEY_name: $error"
+ return $OCF_ERR_GENERIC
+ fi
+
+ error="$(rm -f "$HA_RSCTMP/iface-macvlan.$OCF_RESKEY_name" 2>&1)"
+ if [ "$?" != "0" ]; then
+ ocf_log err "Unable to remove lock file for MACVLAN $OCF_RESKEY_name: $error"
+ return $OCF_ERR_GENERIC
+ fi
+
+ return $OCF_SUCCESS
+}
+
+case $__OCF_ACTION in
+ meta-data)
+ macvlan_meta_data
+ exit $OCF_SUCCESS
+ ;;
+ usage|help)
+ macvlan_usage
+ exit $OCF_SUCCESS
+ ;;
+esac
+
+if [ ! -d "$HA_RSCTMP" ]; then
+ ocf_log debug "$HA_RSCTMP not found, we are probably being executed manually"
+ mkdir -p "$HA_RSCTMP"
+fi
+
+if [ -n "$__OCF_ACTION" ] && ! macvlan_validate; then
+ exit $OCF_ERR_CONFIGURED
+fi
+
+case $__OCF_ACTION in
+ start|stop)
+ if ! ocf_is_root; then
+ ocf_log err "You must be root for $__OCF_ACTION operation."
+ exit $OCF_ERR_PERM
+ fi
+ ;;
+esac
+
+case $__OCF_ACTION in
+ start)
+ macvlan_start
+ ret=$?
+ if [ "$ret" != "$OCF_SUCCESS" ]; then
+ macvlan_force_stop
+ fi
+ exit $ret
+ ;;
+ stop)
+ macvlan_stop
+ exit $?
+ ;;
+ status|monitor)
+ macvlan_check
+ exit $?
+ ;;
+ validate-all)
+ # macvlan_validate above does the trick
+ ;;
+ *)
+ macvlan_usage
+ exit $OCF_ERR_UNIMPLEMENTED
+ ;;
+esac
+# vi:sw=4:ts=8: