b036eea91b
- Remove host interface creation from ns_ntp ocf - Create new crm resource vrouter that handles other_networks - Update direct_networks.rb to parse custom routes Change-Id: Iea26e1755e7e6d6310ad7cdb77ef1b21d850ff36 Closes-Bug: 1436868
349 lines
10 KiB
Bash
349 lines
10 KiB
Bash
#!/bin/bash
|
|
#
|
|
# Resource script for vrouter namespace support
|
|
#
|
|
# Description: Manages vrouter namespace as an OCF resource in
|
|
# an High Availability setup
|
|
#
|
|
# Vrouter OCF script's Author: Mirantis
|
|
# License: GNU General Public License (GPL)
|
|
#
|
|
# usage: $0 {start|stop|restart|status|monitor|validate-all|meta-data}
|
|
#
|
|
# The "start" arg starts vrouter.
|
|
#
|
|
# The "stop" arg stops it.
|
|
#
|
|
# OCF parameters:
|
|
# OCF_RESKEY_ns
|
|
# OCF_RESKEY_other_networks
|
|
#
|
|
# OCF_RESKEY_host_interface
|
|
# OCF_RESKEY_namespace_interface
|
|
# OCF_RESKEY_host_ip
|
|
# OCF_RESKEY_namespace_ip
|
|
# OCF_RESKEY_network_mask
|
|
# OCF_RESKEY_route_metric
|
|
#
|
|
##########################################################################
|
|
# Initialization:
|
|
|
|
OCF_ROOT_default="/usr/lib/ocf"
|
|
|
|
OCF_RESKEY_ns_default="vrouter"
|
|
OCF_RESKEY_other_networks_default=false
|
|
OCF_RESKEY_host_interface_default="vrouter-host"
|
|
OCF_RESKEY_namespace_interface_default="vr-ns"
|
|
OCF_RESKEY_host_ip_default="240.0.0.5"
|
|
OCF_RESKEY_namespace_ip_default="240.0.0.6"
|
|
OCF_RESKEY_network_mask_default="30"
|
|
OCF_RESKEY_route_metric_default="10000"
|
|
|
|
: ${OCF_ROOT=${OCF_ROOT_default}}
|
|
|
|
: ${OCF_RESKEY_ns=${OCF_RESKEY_ns_default}}
|
|
: ${OCF_RESKEY_other_networks=${OCF_RESKEY_other_networks_default}}
|
|
: ${OCF_RESKEY_host_interface=${OCF_RESKEY_host_interface_default}}
|
|
: ${OCF_RESKEY_namespace_interface=${OCF_RESKEY_namespace_interface_default}}
|
|
: ${OCF_RESKEY_host_ip=${OCF_RESKEY_host_ip_default}}
|
|
: ${OCF_RESKEY_namespace_ip=${OCF_RESKEY_namespace_ip_default}}
|
|
: ${OCF_RESKEY_network_mask=${OCF_RESKEY_network_mask_default}}
|
|
: ${OCF_RESKEY_route_metric=${OCF_RESKEY_route_metric_default}}
|
|
|
|
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
|
|
. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs
|
|
|
|
USAGE="Usage: $0 {start|stop|restart|status|monitor|validate-all|meta-data}";
|
|
|
|
RUN_IN_NS="ip netns exec $OCF_RESKEY_ns "
|
|
if [[ -z $OCF_RESKEY_ns ]] ; then
|
|
RUN=''
|
|
else
|
|
RUN="$RUN_IN_NS "
|
|
fi
|
|
|
|
##########################################################################
|
|
|
|
usage()
|
|
{
|
|
echo $USAGE >&2
|
|
}
|
|
|
|
meta_data()
|
|
{
|
|
cat <<END
|
|
<?xml version="1.0"?>
|
|
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
|
<resource-agent name="vrouter">
|
|
<version>1.0</version>
|
|
<longdesc lang="en">
|
|
This script manages vrouter daemon with namespace support
|
|
</longdesc>
|
|
<shortdesc lang="en">Manages an vrouter daemon inside an namespace</shortdesc>
|
|
|
|
<parameters>
|
|
|
|
<parameter name="ns">
|
|
<longdesc lang="en">
|
|
Name of network namespace.
|
|
Should be present.
|
|
</longdesc>
|
|
<shortdesc lang="en">Name of network namespace.</shortdesc>
|
|
<content type="string" default="${OCF_RESKEY_ns_default}"/>
|
|
</parameter>
|
|
|
|
<parameter name="other_networks">
|
|
<longdesc lang="en">
|
|
Additional routes that should be added to this resource. Routes will be added via value namespace_interface.
|
|
</longdesc>
|
|
<shortdesc lang="en">List of addtional routes to add routes for.</shortdesc>
|
|
<content type="string" default="$OCF_RESKEY_other_networks_default"/>
|
|
</parameter>
|
|
|
|
<parameter name="host_interface">
|
|
<longdesc lang="en">
|
|
The host part of the interface pair used to connect the namespace to the network
|
|
For example, "vrouter-host"
|
|
</longdesc>
|
|
<shortdesc lang="en">The name of the host interface used for namespace</shortdesc>
|
|
<content type="string" default="${OCF_RESKEY_host_interface_default}" />
|
|
</parameter>
|
|
|
|
<parameter name="namespace_interface">
|
|
<longdesc lang="en">
|
|
The namespace part of the interface pair used to connect the namespace to the network
|
|
For example, "vr-ns"
|
|
</longdesc>
|
|
<shortdesc lang="en">The name of the namespace interface used for namespace</shortdesc>
|
|
<content type="string" default="${OCF_RESKEY_namespace_interface_default}" />
|
|
</parameter>
|
|
|
|
<parameter name="host_ip">
|
|
<longdesc lang="en">
|
|
The IP address used by the host interface. Must be from the same subnet as namesapce IP
|
|
and uses network_mask to determine subnet.
|
|
Should not collide with any IP addresses already used in your network.
|
|
For example, "240.0.0.5"
|
|
</longdesc>
|
|
<shortdesc lang="en">Host interface IP address</shortdesc>
|
|
<content type="string" default="${OCF_RESKEY_host_ip_default}" />
|
|
</parameter>
|
|
|
|
<parameter name="namespace_ip">
|
|
<longdesc lang="en">
|
|
The IP address used by the namespace interface. Must be from the same subnet as host IP
|
|
and uses network_mask to determine subnet.
|
|
Should not collide with any IP addresses already used in your network.
|
|
For example, "240.0.0.6"
|
|
</longdesc>
|
|
<shortdesc lang="en">Namespace interface IP address</shortdesc>
|
|
<content type="string" default="${OCF_RESKEY_namespace_ip_default}" />
|
|
</parameter>
|
|
|
|
<parameter name="network_mask">
|
|
<longdesc lang="en">
|
|
The network mask length used to determine subnet of the host
|
|
and the namspace interfaces.
|
|
For example, "30"
|
|
</longdesc>
|
|
<shortdesc lang="en">Network mask length</shortdesc>
|
|
<content type="string" default="${OCF_RESKEY_network_mask_default}" />
|
|
</parameter>
|
|
|
|
<parameter name="route_metric">
|
|
<longdesc lang="en">
|
|
The metric value of the default route set for the pipe
|
|
link connecting namespace and host. It should be set to
|
|
a large number to be higher then other default route metrics
|
|
that could be set to override this default route.
|
|
If other routes are set eithin the namespace thir metric should
|
|
be smaller then this number if you want them to be used istead of
|
|
this route.
|
|
For example, "1000"
|
|
</longdesc>
|
|
<shortdesc lang="en">Namespace default route metric</shortdesc>
|
|
<content type="string" default="${OCF_RESKEY_route_metric_default}" />
|
|
</parameter>
|
|
|
|
</parameters>
|
|
|
|
<actions>
|
|
<action name="start" timeout="20s"/>
|
|
<action name="stop" timeout="20s"/>
|
|
<action name="reload" timeout="20s"/>
|
|
<action name="monitor" depth="0" timeout="20s" interval="60s" />
|
|
<action name="validate-all" timeout="20s"/>
|
|
<action name="meta-data" timeout="5s"/>
|
|
</actions>
|
|
</resource-agent>
|
|
END
|
|
exit $OCF_SUCCESS
|
|
}
|
|
|
|
check_ns() {
|
|
local LH="${LL} check_ns():"
|
|
local ns=`ip netns list | grep "$OCF_RESKEY_ns"`
|
|
ocf_log debug "${LH} recieved netns list: ${ns}"
|
|
[[ $ns != $OCF_RESKEY_ns ]] && return $OCF_ERR_GENERIC
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
get_ns() {
|
|
local rc
|
|
local LH="${LL} get_ns():"
|
|
check_ns && return $OCF_SUCCESS
|
|
|
|
ocf_run ip netns add $OCF_RESKEY_ns
|
|
rc=$?
|
|
ocf_run $RUN_IN_NS ip link set up dev lo
|
|
ocf_log debug "${LH} added netns ${OCF_RESKEY_ns} and set up lo"
|
|
|
|
return $rc
|
|
}
|
|
|
|
set_ns_routing() {
|
|
nsip() {
|
|
ip netns exec "${OCF_RESKEY_ns}" ip ${@}
|
|
}
|
|
|
|
# create host-ns veth pair unless it's present
|
|
ip link | grep -q "${OCF_RESKEY_host_interface}:"
|
|
if [ $? -gt 0 ]; then
|
|
ocf_log debug "Creating host interface: ${OCF_RESKEY_host_interface} and namespace interface: ${OCF_RESKEY_namespace_interface}"
|
|
ocf_run ip link add "${OCF_RESKEY_host_interface}" type veth peer name "${OCF_RESKEY_namespace_interface}"
|
|
else
|
|
return $OCF_SUCCESS
|
|
fi
|
|
|
|
# move the ns part to the namespace
|
|
ip link | grep -q "${OCF_RESKEY_namespace_interface}:"
|
|
if [ $? -eq 0 ]; then
|
|
ocf_log debug "Moving interface: ${OCF_RESKEY_namespace_interface} to namespace: ${OCF_RESKEY_ns}"
|
|
ocf_run ip link set dev "${OCF_RESKEY_namespace_interface}" netns "${OCF_RESKEY_ns}"
|
|
fi
|
|
|
|
# up the host part
|
|
ocf_log debug "Bringing up host interface: ${OCF_RESKEY_host_interface}"
|
|
ocf_run ip link set "${OCF_RESKEY_host_interface}" up
|
|
|
|
# set host part's ip
|
|
ip addr show dev "${OCF_RESKEY_host_interface}" | grep -q "inet ${OCF_RESKEY_host_ip}/${OCF_RESKEY_network_mask}"
|
|
if [ $? -gt 0 ]; then
|
|
ocf_log debug "Setting host interface: ${OCF_RESKEY_host_interface} IP to: ${OCF_RESKEY_host_ip}/${OCF_RESKEY_network_mask}"
|
|
ocf_run ip addr add "${OCF_RESKEY_host_ip}/${OCF_RESKEY_network_mask}" dev "${OCF_RESKEY_host_interface}"
|
|
fi
|
|
|
|
# up the ns part
|
|
ocf_log debug "Bringing up the namespace interface: ${OCF_RESKEY_namespace_interface}"
|
|
ocf_run nsip link set "${OCF_RESKEY_namespace_interface}" up
|
|
|
|
# set ns part's ip
|
|
nsip addr show dev "${OCF_RESKEY_namespace_interface}" | grep -q "inet ${OCF_RESKEY_namespace_ip}/${OCF_RESKEY_network_mask}"
|
|
if [ $? -gt 0 ]; then
|
|
ocf_log debug "Setting namespace interface: ${OCF_RESKEY_namespace_interface} IP to: ${OCF_RESKEY_namespace_ip}/${OCF_RESKEY_network_mask}"
|
|
ocf_run nsip addr add "${OCF_RESKEY_namespace_ip}/${OCF_RESKEY_network_mask}" dev "${OCF_RESKEY_namespace_interface}"
|
|
fi
|
|
|
|
# set default gateway inside ns
|
|
nsip route list | grep -q "default via ${OCF_RESKEY_host_ip}"
|
|
if [ $? -gt 0 ]; then
|
|
ocf_log debug "Creating default route inside the namespace to ${OCF_RESKEY_host_ip} with metric ${OCF_RESKEY_route_metric}"
|
|
ocf_run nsip route add default via "${OCF_RESKEY_host_ip}" metric "${OCF_RESKEY_route_metric}"
|
|
fi
|
|
|
|
# set masquerade on host node
|
|
iptables -t nat -L | grep -q masquerade-for-vrouter-namespace
|
|
if [ $? -gt 0 ]; then
|
|
ocf_log debug "Creating NAT rule on the host system for traffic from IP: ${OCF_RESKEY_namespace_ip}"
|
|
ocf_run iptables -t nat -A POSTROUTING -s "${OCF_RESKEY_namespace_ip}" -j MASQUERADE -m comment --comment "masquerade-for-vrouter-namespace"
|
|
fi
|
|
|
|
### Needed for ML2 routing ###
|
|
ocf_run sysctl -w net.ipv4.conf.${OCF_RESKEY_host_interface}.rp_filter=2
|
|
ocf_run $RUN_IN_NS sysctl -w net.ipv4.conf.all.rp_filter=2
|
|
##############################
|
|
|
|
if [[ "${OCF_RESKEY_other_networks}" != "false" ]] ; then
|
|
for network in ${OCF_RESKEY_other_networks}
|
|
do
|
|
ocf_log debug "Adding route on the host system to ${network}: ${OCF_RESKEY_namespace_ip}"
|
|
ocf_run $RUN_IN_NS ip route replace ${network} via ${OCF_RESKEY_host_ip} metric 10000
|
|
done
|
|
fi
|
|
}
|
|
|
|
vrouter_status() {
|
|
get_ns || return $OCF_NOT_RUNNING
|
|
set_ns_routing
|
|
}
|
|
|
|
vrouter_start()
|
|
{
|
|
get_ns
|
|
set_ns_routing
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
vrouter_stop()
|
|
{
|
|
ocf_log debug "Vrouter was stopped, namespaces still exist"
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
vrouter_monitor()
|
|
{
|
|
vrouter_status
|
|
}
|
|
|
|
vrouter_validate_all()
|
|
{
|
|
get_ns
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
vrouter_restart()
|
|
{
|
|
vrouter_stop
|
|
vrouter_start
|
|
}
|
|
|
|
#
|
|
# Main
|
|
#
|
|
|
|
if [ $# -ne 1 ]; then
|
|
usage
|
|
exit $OCF_ERR_ARGS
|
|
fi
|
|
umask 0022
|
|
export LL="${OCF_RESOURCE_INSTANCE}:"
|
|
|
|
case $1 in
|
|
start) vrouter_start
|
|
;;
|
|
|
|
stop) vrouter_stop
|
|
;;
|
|
|
|
restart) vrouter_restart
|
|
;;
|
|
|
|
status) vrouter_status
|
|
;;
|
|
|
|
monitor) vrouter_monitor
|
|
;;
|
|
|
|
validate-all) vrouter_validate_all
|
|
;;
|
|
|
|
meta-data) meta_data
|
|
;;
|
|
|
|
usage) usage; exit $OCF_SUCCESS
|
|
;;
|
|
|
|
*) usage; exit $OCF_ERR_UNIMPLEMENTED
|
|
;;
|
|
esac
|