#!/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 < 1.0 This resource manages MACVLAN network interfaces. It can add, remove, configure MACVLANs. Manages MACVLAN network interfaces. Define the interface where MACVLAN should be attached. Network interface. Define the MACVLAN NAME. It has to be a valid interface name (max 15 characters). Define the MACVLAN NAME. Define the name of the MACVLAN mode (currently only bridge is supported). Mode of the macvlan. Set the interface MAC address explicitly. MAC address of the macvlan 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: