I wanted to try Ucarp, the userland daemon to use the CARP protocol, to manage a virtual address for automatic failover between two MySQL hosts.
The only problem was, I wanted to do that with Solaris shared-IP zones. They don’t really have complete (promiscuous mode) access to their IP interfaces. The interfaces are rather virtual interfaces for the global zone which are forwarded to a particular zone. So that means, ucarp has to run on the global zone as well. But how would it know which zone/interface to manage?
So I modified the ucarp sources a bit to run a little /usr/sbin/zoneadm -z <zonename> list -p before sending the `I’m alive package’. Afterwards I was thinking about making this a bit more generic to simply allow the user to provide a special check-script to ucarp, which would influence the alive state. But that’s not done yet.
So ucarp would only send it’s broadcasts when the physical interface is up AND the zone in question is alive. The configuration of the additional virtual interface for the zone is easily done with the default arguments. Just add the <zonename> as an extra parameter for the up-/down- scripts.
The if-up.sh script I use:
#!/bin/bash # <interface name> <virtual address> <optional extra parameter> if [ $# -gt 2 ] then z_zone="zone" fi interface=$1 vaddr=$2 shift 2 /usr/sbin/ifconfig $interface addif $vaddr netmask + broadcast + up if [ ! -z "$z_zone" ] then # we need the virtual interface!! vinterface=`/usr/sbin/ifconfig -a | \ awk '$1 !~ /^(ether|inet|lo|zone)/ { interface=$1; } $1 == "inet" && $2 == "'$vaddr'" { print substr(interface, 0, length(interface) - 1); exit; }'` if [ ! -z "$vinterface" ] then fgrep -s ':' <<<$vinterface if [ $? -eq 0 ] then /usr/sbin/ifconfig $vinterface $z_zone "$@" fi fi fi
And the if-down.sh as well;-)
#!/bin/bash # <interface name> <virtual address> <optional extra parameter> interface=$1 vaddr=$2 shift 2 # we need the virtual interface!! vinterface=`/usr/sbin/ifconfig -a | awk '$1 !~ /^(ether|inet|lo|zone)/ { interface=$1; } $1 == "inet" && $2 == "'$vaddr'" { print substr(interface, 0, length(interface) - 1); exit; }'` if [ ! -z "$vinterface" ] then fgrep -s ':' <<<$vinterface if [ $? -eq 0 ] then /usr/sbin/ifconfig $vinterface down unplumb fi fi
I played with that and it seems to work as expected. My little patch for the curious ones is hier;-)
Have fun;-)
— Marco
Hi Marco,
thank you very much for this patch! That’s exactly what I was looking for. Just a small question about it: in my test infrastructure, I only have one server running multiple zones and I would like to test Ucarp with two zones running on this same host. So I tried to start two instances of Ucarp as follow (my host is 192.168.12.11, the virtual floating address is 192.168.12.10 and my zones are my-zone-1 and my-zone-2):
======================
./ucarp –nomcast –interface=nge0 –srcip=192.168.12.11 \
–vhid=1 –pass=mypassword –addr=192.168.12.10 \
–upscript=/etc/ucarp/vip-up.sh \
–downscript=/etc/ucarp/vip-down.sh \
–zone=my-zone-1 –xparam=my-zone-1
./ucarp –nomcast –interface=nge0 –srcip=192.168.12.11 \
–vhid=1 –pass=mypassword –addr=192.168.12.10 \
–upscript=/etc/ucarp/vip-up.sh \
–downscript=/etc/ucarp/vip-down.sh \
–zone=my-zone-2 –xparam=my-zone-2
======================
… but unfortunately they don’t see each other’s advertisement. In your opinion, is that a limitation of the multicast/broadcast or would it be possible to handle this particular case with your patch?
Thank you in advance for a short feedback and Best Regards,
FooFoo_2
I don’t think two zones on the same host could be handled that way. the global zone would not know what to do because all packets would go out/come in through the same interface.