A start on the redundancy code

This will not break anything but also will not work
This commit is contained in:
Ian Southam 2014-09-18 17:03:28 +02:00 committed by wilderrodrigues
parent a01e9082cd
commit 093749eaae
24 changed files with 1477 additions and 81 deletions

View File

@ -869,6 +869,7 @@ setup_redundant_router() {
sed -i "s/\[ETH2MASK\]/$ETH2_MASK/g" $rrouter_bin_path/enable_pubip.sh sed -i "s/\[ETH2MASK\]/$ETH2_MASK/g" $rrouter_bin_path/enable_pubip.sh
sed -i "s/\[GATEWAY\]/$GW/g" $rrouter_bin_path/enable_pubip.sh sed -i "s/\[GATEWAY\]/$GW/g" $rrouter_bin_path/enable_pubip.sh
sed -i "s/\[GATEWAY\]/$GW/g" $rrouter_bin_path/master.sh sed -i "s/\[GATEWAY\]/$GW/g" $rrouter_bin_path/master.sh
sed -i "s/\[RROUTER_BIN_PATH\]/$rrouter_bin_path_str/g" $rrouter_bin_path/master.sh sed -i "s/\[RROUTER_BIN_PATH\]/$rrouter_bin_path_str/g" $rrouter_bin_path/master.sh
sed -i "s/\[RROUTER_BIN_PATH\]/$rrouter_bin_path_str/g" $rrouter_bin_path/backup.sh sed -i "s/\[RROUTER_BIN_PATH\]/$rrouter_bin_path_str/g" $rrouter_bin_path/backup.sh
sed -i "s/\[RROUTER_BIN_PATH\]/$rrouter_bin_path_str/g" $rrouter_bin_path/fault.sh sed -i "s/\[RROUTER_BIN_PATH\]/$rrouter_bin_path_str/g" $rrouter_bin_path/fault.sh

View File

@ -0,0 +1,105 @@
# -- coding: utf-8 --
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import logging
import re
import copy
class CsFile:
""" File editors """
def __init__(self, filename):
self.filename = filename
self.load()
def load(self):
self.new_config = []
self.config = []
try:
for line in open(self.filename):
self.new_config.append(line)
except IOError:
logging.debug("File %s does not exist" % self.filename)
return
else:
logging.debug("Reading file %s" % self.filename)
self.config = copy.deepcopy(self.new_config)
def is_changed(self):
if set(self.config) != set(self.new_config):
return True
else:
return False
def commit(self):
if not self.is_changed():
return
handle = open(self.filename, "w+")
for line in self.new_config:
handle.write(line)
handle.close()
logging.info("Wrote edited file %s" % self.filename)
def dump(self):
for line in self.new_config:
print line
def addeq(self, string):
""" Update a line in a file of the form token=something
match on token= and replace something if needed
Add line if token is not present
"""
token = string.split('=')[0] + '='
self.search(token, string)
def add(self, string, where = -1):
for index, line in enumerate(self.new_config):
if line.strip() == string:
return
if where == -1:
self.new_config.append("%s\n" % string)
else:
self.new_config.insert(where, "%s\n" % string)
def section(self, start, end, content):
sind = -1
eind = -1
found = False
for index, line in enumerate(self.new_config):
if found and line.strip() == end:
eind = index
found = False
if line.strip() == start:
sind = index + 1
found = True
self.new_config[sind:eind] = content
def greplace(self, search, replace):
self.new_config = [w.replace(search, replace) for w in self.new_config]
def search(self, search, replace):
found = False
logging.debug("Searching for %s and replacing with %s" % (search, replace))
for index, line in enumerate(self.new_config):
if line.lstrip().startswith("#"):
continue
if re.search(search, line):
found = True
if not replace in line:
self.new_config[index] = replace + "\n"
if not found:
self.new_config.append(replace + "\n")

View File

@ -10,6 +10,38 @@ import shutil
from netaddr import * from netaddr import *
from pprint import pprint from pprint import pprint
def is_mounted(name):
for i in execute("mount"):
vals = i.lstrip().split()
if vals[0] == "tmpfs" and vals[2] == name:
return True
return False
def mount_tmpfs(name):
if not is_mounted(name):
print "Mounting it"
execute("mount tmpfs %s -t tmpfs" % name)
def umount_tmpfs(name):
if is_mounted(name):
execute("umount %s" % name)
def rm(name):
os.remove(name) if os.path.isfile(name) else None
def rmdir(name):
if name:
shutil.rmtree(name, True)
def mkdir(name, mode, fatal):
try:
os.makedirs(name, mode)
except OSError as e:
if e.errno != 17:
print "failed to make directories " + name + " due to :" +e.strerror
if(fatal):
sys.exit(1)
def updatefile(filename, val, mode): def updatefile(filename, val, mode):
""" add val to file """ """ add val to file """
handle = open(filename, 'r') handle = open(filename, 'r')
@ -102,6 +134,7 @@ def execute2(command):
""" Execute command """ """ Execute command """
logging.debug("Executing %s" % command) logging.debug("Executing %s" % command)
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
p.wait()
return p return p
def service(name, op): def service(name, op):

View File

@ -1,4 +1,20 @@
# -- coding: utf-8 -- # -- coding: utf-8 --
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import CsHelper import CsHelper
from pprint import pprint from pprint import pprint
from cs_databag import CsDataBag, CsCmdLine from cs_databag import CsDataBag, CsCmdLine

View File

@ -0,0 +1,137 @@
# -- coding: utf-8 --
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# -------------------------------------------------------------------- #
# Notes
# -------------------------------------------------------------------- #
# Vrouter
#
# eth0 router gateway IP for isolated network
# eth1 Control IP for hypervisor
# eth2 public ip(s)
#
# VPC Router
#
# eth0 control interface
# eth1 public ip
# eth2+ Guest networks
# -------------------------------------------------------------------- #
import sys
import os
from pprint import pprint
from cs_databag import CsDataBag, CsCmdLine
import logging
import CsHelper
from CsFile import CsFile
class CsRedundant(object):
CS_RAMDISK_DIR = "/ramdisk"
CS_ROUTER_DIR = "%s/rrouter" % CS_RAMDISK_DIR
CS_TEMPLATES = [
"enable_pubip.sh.templ",
"master.sh.templ", "backup.sh.templ", "fault.sh.templ",
"primary-backup.sh.templ", "heartbeat.sh.templ", "check_heartbeat.sh.templ",
"arping_gateways.sh.templ", "check_bumpup.sh", "disable_pubip.sh",
"services.sh",
]
CS_TEMPLATES_DIR = "/opt/cloud/templates"
def __init__(self):
pass
def set(self, cl, address):
logging.debug("Router redundancy status is %s", cl.is_redundant())
self.cl = cl
self.address = address
if cl.is_redundant():
self._redundant_on()
else:
self._redundant_off()
def _redundant_off(self):
CsHelper.umount_tmpfs(self.CS_RAMDISK_DIR)
CsHelper.rmdir(self.CS_RAMDISK_DIR)
CsHelper.rm("/etc/cron.d/heartbeat")
def _redundant_on(self):
CsHelper.mkdir(self.CS_RAMDISK_DIR, 0755, False)
CsHelper.mount_tmpfs(self.CS_RAMDISK_DIR)
CsHelper.mkdir(self.CS_ROUTER_DIR, 0755, False)
for s in self.CS_TEMPLATES:
d = s
if s.endswith(".templ"):
d = s.replace(".templ", "")
CsHelper.copy_if_needed("%s/%s" % (self.CS_TEMPLATES_DIR, s), "%s/%s" % (self.CS_ROUTER_DIR, d))
CsHelper.copy_if_needed("%s/%s" % (self.CS_TEMPLATES_DIR, "keepalived.conf.templ"), "/etc/keepalived/keepalived.conf")
CsHelper.copy_if_needed("%s/%s" % (self.CS_TEMPLATES_DIR, "conntrackd.conf.templ"), "/etc/conntrackd/conntrackd.conf")
CsHelper.copy_if_needed("%s/%s" % (self.CS_TEMPLATES_DIR, "checkrouter.sh.templ"), "/opt/cloud/bin/checkrouter.sh")
# keepalived configuration
file = CsFile("/etc/keepalived/keepalived.conf")
file.search(" router_id ", " router_id %s" % self.cl.get_name())
file.search(" priority ", " priority %s" % 20)
file.search(" weight ", " weight %s" % 2)
file.greplace("[RROUTER_BIN_PATH]", self.CS_ROUTER_DIR)
file.section("virtual_ipaddress {", "}", self._collect_ips())
file.commit()
# conntrackd configuration
control = self.address.get_control_if()
connt = CsFile("/etc/conntrackd/conntrackd.conf")
connt.search("[\s\t]IPv4_interface ", "\t\tIPv4_interface %s" % control.get_ip())
connt.search("[\s\t]Interface ", "\t\tInterface %s" % control.get_device())
connt.section("Address Ignore {", "}", self._collect_ignore_ips())
connt.commit()
# FIXME
# enable/disable_pubip/master/slave etc. will need rewriting to use the new python config
# Configure heartbeat cron job
cron = CsFile("/etc/cron.d/heartbeat")
cron.add("SHELL=/bin/bash", 0)
cron.add("PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin", 1)
cron.add("*/1 * * * * root $SHELL %s/check_heartbeat.sh 2>&1 > /dev/null" % self.CS_ROUTER_DIR, -1)
cron.commit()
def _collect_ignore_ips(self):
"""
This returns a list of ip objects that should be ignored
by conntrackd
"""
lines = []
lines.append("\t\t\tIPv4_address %s\n" % "127.0.0.1")
lines.append("\t\t\tIPv4_address %s\n" % self.address.get_control_if().get_ip())
# FIXME - Do we need to also add any internal network gateways?
return lines
def _collect_ips(self):
"""
Construct a list containing all the ips that need to be looked afer by vrrp
This is based upon the address_needs_vrrp method in CsAddress which looks at
the network type and decides if it is an internal address or an external one
In a DomR there will only ever be one address in a VPC there can be many
The new code also gives the possibility to cloudstack to have a hybrid device
thet could function as a router and VPC router at the same time
"""
lines = []
for o in self.address.get_ips():
if o.needs_vrrp():
str = " %s brd %s dev %s\n" % (o.get_cidr(), o.get_broadcast(), o.get_ip())
lines.append(str)
return lines

View File

@ -31,58 +31,11 @@ import CsHelper
from CsNetfilter import CsNetfilters from CsNetfilter import CsNetfilters
from fcntl import flock, LOCK_EX, LOCK_UN from fcntl import flock, LOCK_EX, LOCK_UN
from CsDhcp import CsDhcp from CsDhcp import CsDhcp
from CsRedundant import *
from CsFile import CsFile
fw = [] fw = []
class CsFile:
""" File editors """
def __init__(self, filename):
self.filename = filename
self.changed = False
self.load()
def load(self):
self.new_config = []
try:
for line in open(self.filename):
self.new_config.append(line)
except IOError:
logging.debug("File %s does not exist" % self.filename)
return
else:
logging.debug("Reading file %s" % self.filename)
def is_changed(self):
return self.changed
def commit(self):
if not self.changed:
return
handle = open(self.filename, "w+")
for line in self.new_config:
handle.write(line)
handle.close()
logging.info("Wrote edited file %s" % self.filename)
def add(self, string):
self.search(string, string)
def search(self, search, replace):
found = False
logging.debug("Searching for %s and replacing with %s" % (search, replace))
for index, line in enumerate(self.new_config):
if line.lstrip().startswith("#"):
continue
if re.search(search, line):
found = True
if not replace in line:
self.changed = True
self.new_config[index] = replace + "\n"
if not found:
self.new_config.append(replace + "\n")
self.changed = True
class CsRule: class CsRule:
""" Manage iprules """ Manage iprules
Supported Types: Supported Types:
@ -675,13 +628,7 @@ class CsVmMetadata(CsDataBag):
htaccessFolder = "/var/www/html/latest" htaccessFolder = "/var/www/html/latest"
htaccessFile = htaccessFolder + "/.htaccess" htaccessFile = htaccessFolder + "/.htaccess"
try: CsHelper.mkdir(htaccessFolder, 0755, True)
os.mkdir(htaccessFolder,0755)
except OSError as e:
# error 17 is already exists, we do it this way for concurrency
if e.errno != 17:
print "failed to make directories " + htaccessFolder + " due to :" +e.strerror
sys.exit(1)
if os.path.exists(htaccessFile): if os.path.exists(htaccessFile):
fh = open(htaccessFile, "r+a") fh = open(htaccessFile, "r+a")
@ -757,6 +704,32 @@ class CsAddress(CsDataBag):
ip = CsIP(dev) ip = CsIP(dev)
ip.compare(self.dbag) ip.compare(self.dbag)
def get_ips(self):
ret = []
for dev in self.dbag:
if dev == "id":
continue
for ip in self.dbag[dev]:
ret.append(CsInterface(ip))
return ret
def needs_vrrp(self,o):
"""
Returns if the ip needs to be managed by keepalived or not
"""
if "nw_type" in o and o['nw_type'] in [ 'guest' ]:
return True
return False
def get_control_if(self):
"""
Return the address object that has the control interface
"""
for ip in self.get_ips():
if ip.is_control():
return ip
return None
def process(self): def process(self):
for dev in self.dbag: for dev in self.dbag:
if dev == "id": if dev == "id":
@ -805,6 +778,45 @@ class CsAddress(CsDataBag):
fw.append(["mangle", "", "-A VPN_STATS_%s -o %s -m mark --set-xmark 0x525/0xffffffff" % (dev, dev)]) fw.append(["mangle", "", "-A VPN_STATS_%s -o %s -m mark --set-xmark 0x525/0xffffffff" % (dev, dev)])
fw.append(["mangle", "", "-A VPN_STATS_%s -i %s -m mark --set-xmark 0x524/0xffffffff" % (dev, dev)]) fw.append(["mangle", "", "-A VPN_STATS_%s -i %s -m mark --set-xmark 0x524/0xffffffff" % (dev, dev)])
class CsInterface:
""" Hold one single ip """
def __init__(self, o):
self.address = o
def get_ip(self):
return self.get_attr("public_ip")
def get_device(self):
return self.get_attr("device")
def get_cidr(self):
return self.get_attr("cidr")
def get_broadcast(self):
return self.get_attr("broadcast")
def get_attr(self, attr):
if attr in self.address:
return self.address[attr]
else:
return "ERROR"
def needs_vrrp(self):
"""
Returns if the ip needs to be managed by keepalived or not
"""
if "nw_type" in self.address and self.address['nw_type'] in [ 'guest' ]:
return True
return False
def is_control(self):
if "nw_type" in self.address and self.address['nw_type'] in [ 'control' ]:
return True
return False
def to_str(self):
pprint(self.address)
class CsSite2SiteVpn(CsDataBag): class CsSite2SiteVpn(CsDataBag):
""" """
Setup any configured vpns (using swan) Setup any configured vpns (using swan)
@ -818,7 +830,7 @@ class CsSite2SiteVpn(CsDataBag):
self.confips = [] self.confips = []
# collect a list of configured vpns # collect a list of configured vpns
for file in os.listdir(self.VPNCONFDIR): for file in os.listdir(self.VPNCONFDIR):
m = re.search("ipsec.vpn-(.*).conf", file) m = re.search("^ipsec.vpn-(.*).conf", file)
if m: if m:
self.confips.append(m.group(1)) self.confips.append(m.group(1))
@ -867,36 +879,42 @@ class CsSite2SiteVpn(CsDataBag):
if rightpeer in self.confips: if rightpeer in self.confips:
self.confips.remove(rightpeer) self.confips.remove(rightpeer)
file = CsFile(vpnconffile) file = CsFile(vpnconffile)
file.add("conn vpn-%s" % rightpeer) file.search("conn ", "conn vpn-%s" % rightpeer)
file.add(" left=%s" % leftpeer) file.addeq(" left=%s" % leftpeer)
file.add(" leftsubnet=%s" % obj['local_guest_cidr']) file.addeq(" leftsubnet=%s" % obj['local_guest_cidr'])
file.add(" leftnexthop=%s" % obj['local_public_gateway']) file.addeq(" leftnexthop=%s" % obj['local_public_gateway'])
file.add(" right=%s" % rightpeer) file.addeq(" right=%s" % rightpeer)
file.add(" rightsubnets=%s" % peerlist) file.addeq(" rightsubnets=%s" % peerlist)
file.add(" type=tunnel") file.addeq(" type=tunnel")
file.add(" authby=secret") file.addeq(" authby=secret")
file.add(" keyexchange=ike") file.addeq(" keyexchange=ike")
file.add(" ike=%s" % obj['ike_policy']) file.addeq(" ike=%s" % obj['ike_policy'])
file.add(" ikelifetime=%s" % obj['ike_lifetime']) file.addeq(" ikelifetime=%s" % self.convert_sec_to_h(obj['ike_lifetime']))
file.add(" esp=%s" % obj['esp_lifetime']) file.addeq(" esp=%s" % self.convert_sec_to_h(obj['esp_lifetime']))
file.add(" salifetime=%s" % obj['esp_lifetime']) file.addeq(" salifetime=%s" % self.convert_sec_to_h(obj['esp_lifetime']))
file.add(" pfs=%s" % CsHelper.bool_to_yn(obj['dpd'])) file.addeq(" pfs=%s" % CsHelper.bool_to_yn(obj['dpd']))
file.add(" keyingtries=2") file.addeq(" keyingtries=2")
file.add(" auto=add") file.addeq(" auto=add")
if obj['dpd']: if obj['dpd']:
file.add(" dpddelay=30") file.addeq(" dpddelay=30")
file.add(" dpdtimeout=120") file.addeq(" dpdtimeout=120")
file.add(" dpdaction=restart") file.addeq(" dpdaction=restart")
file.commit() file.commit()
secret = CsFile(vpnsecretsfile) secret = CsFile(vpnsecretsfile)
secret.add("%s %s: PSK \"%s\"" % (leftpeer, rightpeer, obj['ipsec_psk'])) secret.search("%s " % leftpeer, "%s %s: PSK \"%s\"" % (leftpeer, rightpeer, obj['ipsec_psk']))
secret.commit() secret.commit()
if secret.is_changed() or file.is_changed(): if secret.is_changed() or file.is_changed():
logging.info("Configured vpn %s %s", leftpeer, rightpeeer) logging.info("Configured vpn %s %s", leftpeer, rightpeer)
CsHelper.execute("ipsec auto --rereadall") CsHelper.execute("ipsec auto --rereadall")
CsHelper.execute("ipsec --add vpn-%s" % rightpeer) CsHelper.execute("ipsec --add vpn-%s" % rightpeer)
if not obj['passive']: if not obj['passive']:
CsHelper.execute("ipsec --up vpn-%s" % rightpeer) CsHelper.execute("ipsec --up vpn-%s" % rightpeer)
os.chmod(vpnsecretsfile, 0o400)
def convert_sec_to_h(self, val):
hrs = int(val) / 3600
return "%sh" % hrs
class CsForwardingRules(CsDataBag): class CsForwardingRules(CsDataBag):
def __init__(self, key): def __init__(self, key):
@ -980,6 +998,10 @@ def main(argv):
vpns = CsSite2SiteVpn("site2sitevpn") vpns = CsSite2SiteVpn("site2sitevpn")
vpns.process() vpns.process()
red = CsRedundant()
# Move to init and make a single call?
red.set(cl, address)
nf = CsNetfilters() nf = CsNetfilters()
nf.compare(fw) nf.compare(fw)

View File

@ -40,6 +40,12 @@ class CsCmdLine(CsDataBag):
return self.dbag['config']['redundant'] == "true" return self.dbag['config']['redundant'] == "true"
return False return False
def get_name(self):
if "name" in self.dbag['config']:
return self.dbag['config']['name']
else:
return "unloved-router"
def get_type(self): def get_type(self):
if "type" in self.dbag['config']: if "type" in self.dbag['config']:
return self.dbag['config']['type'] return self.dbag['config']['type']

View File

@ -29,6 +29,7 @@ def merge(dbag, ip):
if ip['add']: if ip['add']:
ipo = IPNetwork(ip['public_ip'] + '/' + ip['netmask']) ipo = IPNetwork(ip['public_ip'] + '/' + ip['netmask'])
ip['device'] = 'eth' + str(ip['nic_dev_id']) ip['device'] = 'eth' + str(ip['nic_dev_id'])
ip['broadcast'] = str(ipo.broadcast)
ip['cidr'] = str(ipo.ip) + '/' + str(ipo.prefixlen) ip['cidr'] = str(ipo.ip) + '/' + str(ipo.prefixlen)
ip['network'] = str(ipo.network) + '/' + str(ipo.prefixlen) ip['network'] = str(ipo.network) + '/' + str(ipo.prefixlen)
if 'nw_type' not in ip.keys(): if 'nw_type' not in ip.keys():

View File

@ -0,0 +1,2 @@
These are the templates for the redundant router
and redundant vpc_router

View File

@ -0,0 +1,29 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
ip link|grep BROADCAST|grep -v eth0|grep -v eth1|cut -d ":" -f 2 > /tmp/iflist
while read i
do
ip addr show $i|grep "inet " > /tmp/iplist_$i
while read line
do
ip=`echo $line|cut -d " " -f 2|cut -d "/" -f 1`
arping -I $i -A $ip -c 1 >> [RROUTER_LOG] 2>&1
arping -I $i -A $ip -c 1 >> [RROUTER_LOG] 2>&1
done < /tmp/iplist_$i
done < /tmp/iflist
sleep 1

View File

@ -0,0 +1,39 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
sleep 1
source /root/func.sh
lock="biglock"
locked=$(getLockFile $lock)
if [ "$locked" != "1" ]
then
exit 1
fi
echo To backup called >> [RROUTER_LOG]
[RROUTER_BIN_PATH]/disable_pubip.sh >> [RROUTER_LOG] 2>&1
echo Disable public ip $? >> [RROUTER_LOG]
[RROUTER_BIN_PATH]/services.sh stop >> [RROUTER_LOG] 2>&1
[RROUTER_BIN_PATH]/primary-backup.sh backup >> [RROUTER_LOG] 2>&1
echo Switch conntrackd mode backup $? >> [RROUTER_LOG]
echo Status: BACKUP >> [RROUTER_LOG]
releaseLockFile $lock $locked
exit 0

View File

@ -0,0 +1,19 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
cat /tmp/rrouter_bumped

View File

@ -0,0 +1,56 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
ROUTER_BIN_PATH=/ramdisk/rrouter
ROUTER_LOG=${ROUTER_BIN_PATH}/keepalived.log
STRIKE_FILE="$ROUTER_BIN_PATH/keepalived.strikes"
if [ -e $ROUTER_BIN_PATH/keepalived.ts2 ]
then
lasttime=$(cat $ROUTER_BIN_PATH/keepalived.ts2)
thistime=$(cat $ROUTER_BIN_PATH/keepalived.ts)
diff=$(($thistime - $lasttime))
s=0
if [ $diff -lt 30 ]
then
if [ -e $STRIKE_FILE ]
then
s=`cat $STRIKE_FILE 2>/dev/null`
fi
s=$(($s+1))
echo $s > $STRIKE_FILE
else
rm $STRIKE_FILE
fi
#3 strikes rule
if [ $s -gt 2 ]
then
echo Keepalived process is dead! >> $ROUTER_LOG
$ROUTER_BIN_PATH/services.sh stop >> $ROUTER_LOG 2>&1
$ROUTER_BIN_PATH/disable_pubip.sh >> $ROUTER_LOG 2>&1
$ROUTER_BIN_PATH/primary-backup.sh fault >> $ROUTER_LOG 2>&1
service keepalived stop >> $ROUTER_LOG 2>&1
service conntrackd stop >> $ROUTER_LOG 2>&1
pkill -9 keepalived >> $ROUTER_LOG 2>&1
pkill -9 conntrackd >> $ROUTER_LOG 2>&1
echo Status: FAULT \(keepalived process is dead\) >> $ROUTER_LOG
exit
fi
fi
cp $ROUTER_BIN_PATH/keepalived.ts $ROUTER_BIN_PATH/keepalived.ts2

View File

@ -0,0 +1,56 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
source /root/func.sh
nolock=0
if [ $# -eq 1 ]
then
if [ $1 == "--no-lock" ]
then
nolock=1
fi
fi
if [ $nolock -eq 0 ]
then
lock="biglock"
locked=$(getLockFile $lock)
if [ "$locked" != "1" ]
then
exit 1
fi
fi
bumped="Bumped: NO"
if [ -e /tmp/rrouter_bumped ]
then
bumped="Bumped: YES"
fi
stat=`tail -n 1 [RROUTER_LOG] | grep "Status"`
if [ $? -eq 0 ]
then
echo "$stat&$bumped"
fi
if [ $nolock -eq 0 ]
then
unlock_exit $? $lock $locked
fi

View File

@ -0,0 +1,401 @@
#
# Synchronizer settings
#
Sync {
Mode FTFW {
#
# Size of the resend queue (in objects). This is the maximum
# number of objects that can be stored waiting to be confirmed
# via acknoledgment. If you keep this value low, the daemon
# will have less chances to recover state-changes under message
# omission. On the other hand, if you keep this value high,
# the daemon will consume more memory to store dead objects.
# Default is 131072 objects.
#
# ResendQueueSize 131072
#
# This parameter allows you to set an initial fixed timeout
# for the committed entries when this node goes from backup
# to primary. This mechanism provides a way to purge entries
# that were not recovered appropriately after the specified
# fixed timeout. If you set a low value, TCP entries in
# Established states with no traffic may hang. For example,
# an SSH connection without KeepAlive enabled. If not set,
# the daemon uses an approximate timeout value calculation
# mechanism. By default, this option is not set.
#
# CommitTimeout 180
#
# If the firewall replica goes from primary to backup,
# the conntrackd -t command is invoked in the script.
# This command schedules a flush of the table in N seconds.
# This is useful to purge the connection tracking table of
# zombie entries and avoid clashes with old entries if you
# trigger several consecutive hand-overs. Default is 60 seconds.
#
# PurgeTimeout 60
# Set the acknowledgement window size. If you decrease this
# value, the number of acknowlegdments increases. More
# acknowledgments means more overhead as conntrackd has to
# handle more control messages. On the other hand, if you
# increase this value, the resend queue gets more populated.
# This results in more overhead in the queue releasing.
# The following value is based on some practical experiments
# measuring the cycles spent by the acknowledgment handling
# with oprofile. If not set, default window size is 300.
#
# ACKWindowSize 300
#
# This clause allows you to disable the external cache. Thus,
# the state entries are directly injected into the kernel
# conntrack table. As a result, you save memory in user-space
# but you consume slots in the kernel conntrack table for
# backup state entries. Moreover, disabling the external cache
# means more CPU consumption. You need a Linux kernel
# >= 2.6.29 to use this feature. By default, this clause is
# set off. If you are installing conntrackd for first time,
# please read the user manual and I encourage you to consider
# using the fail-over scripts instead of enabling this option!
#
# DisableExternalCache Off
}
#
# Multicast IP and interface where messages are
# broadcasted (dedicated link). IMPORTANT: Make sure
# that iptables accepts traffic for destination
# 225.0.0.50, eg:
#
# iptables -I INPUT -d 225.0.0.50 -j ACCEPT
# iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT
#
Multicast {
#
# Multicast address: The address that you use as destination
# in the synchronization messages. You do not have to add
# this IP to any of your existing interfaces. If any doubt,
# do not modify this value.
#
IPv4_address 225.0.0.50
#
# The multicast group that identifies the cluster. If any
# doubt, do not modify this value.
#
Group 3780
#
# IP address of the interface that you are going to use to
# send the synchronization messages. Remember that you must
# use a dedicated link for the synchronization messages.
#
IPv4_interface [LINK_IP]
#
# The name of the interface that you are going to use to
# send the synchronization messages.
#
Interface [LINK_IF]
# The multicast sender uses a buffer to enqueue the packets
# that are going to be transmitted. The default size of this
# socket buffer is available at /proc/sys/net/core/wmem_default.
# This value determines the chances to have an overrun in the
# sender queue. The overrun results packet loss, thus, losing
# state information that would have to be retransmitted. If you
# notice some packet loss, you may want to increase the size
# of the sender buffer. The default size is usually around
# ~100 KBytes which is fairly small for busy firewalls.
#
SndSocketBuffer 1249280
# The multicast receiver uses a buffer to enqueue the packets
# that the socket is pending to handle. The default size of this
# socket buffer is available at /proc/sys/net/core/rmem_default.
# This value determines the chances to have an overrun in the
# receiver queue. The overrun results packet loss, thus, losing
# state information that would have to be retransmitted. If you
# notice some packet loss, you may want to increase the size of
# the receiver buffer. The default size is usually around
# ~100 KBytes which is fairly small for busy firewalls.
#
RcvSocketBuffer 1249280
#
# Enable/Disable message checksumming. This is a good
# property to achieve fault-tolerance. In case of doubt, do
# not modify this value.
#
Checksum on
}
#
# You can specify more than one dedicated link. Thus, if one dedicated
# link fails, conntrackd can fail-over to another. Note that adding
# more than one dedicated link does not mean that state-updates will
# be sent to all of them. There is only one active dedicated link at
# a given moment. The `Default' keyword indicates that this interface
# will be selected as the initial dedicated link. You can have
# up to 4 redundant dedicated links. Note: Use different multicast
# groups for every redundant link.
#
# Multicast Default {
# IPv4_address 225.0.0.51
# Group 3781
# IPv4_interface 192.168.100.101
# Interface eth3
# # SndSocketBuffer 1249280
# # RcvSocketBuffer 1249280
# Checksum on
# }
#
# You can use Unicast UDP instead of Multicast to propagate events.
# Note that you cannot use unicast UDP and Multicast at the same
# time, you can only select one.
#
# UDP {
#
# UDP address that this firewall uses to listen to events.
#
# IPv4_address 192.168.2.100
#
# or you may want to use an IPv6 address:
#
# IPv6_address fe80::215:58ff:fe28:5a27
#
# Destination UDP address that receives events, ie. the other
# firewall's dedicated link address.
#
# IPv4_Destination_Address 192.168.2.101
#
# or you may want to use an IPv6 address:
#
# IPv6_Destination_Address fe80::2d0:59ff:fe2a:775c
#
# UDP port used
#
# Port 3780
#
# The name of the interface that you are going to use to
# send the synchronization messages.
#
# Interface eth2
#
# The sender socket buffer size
#
# SndSocketBuffer 1249280
#
# The receiver socket buffer size
#
# RcvSocketBuffer 1249280
#
# Enable/Disable message checksumming.
#
# Checksum on
# }
}
#
# General settings
#
General {
#
# Set the nice value of the daemon, this value goes from -20
# (most favorable scheduling) to 19 (least favorable). Using a
# very low value reduces the chances to lose state-change events.
# Default is 0 but this example file sets it to most favourable
# scheduling as this is generally a good idea. See man nice(1) for
# more information.
#
Nice -20
#
# Select a different scheduler for the daemon, you can select between
# RR and FIFO and the process priority (minimum is 0, maximum is 99).
# See man sched_setscheduler(2) for more information. Using a RT
# scheduler reduces the chances to overrun the Netlink buffer.
#
# Scheduler {
# Type FIFO
# Priority 99
# }
#
# Number of buckets in the cache hashtable. The bigger it is,
# the closer it gets to O(1) at the cost of consuming more memory.
# Read some documents about tuning hashtables for further reference.
#
HashSize 32768
#
# Maximum number of conntracks, it should be double of:
# $ cat /proc/sys/net/netfilter/nf_conntrack_max
# since the daemon may keep some dead entries cached for possible
# retransmission during state synchronization.
#
HashLimit 131072
#
# Logfile: on (/var/log/conntrackd.log), off, or a filename
# Default: off
#
LogFile on
#
# Syslog: on, off or a facility name (daemon (default) or local0..7)
# Default: off
#
#Syslog on
#
# Lockfile
#
LockFile /var/lock/conntrack.lock
#
# Unix socket configuration
#
UNIX {
Path /var/run/conntrackd.ctl
Backlog 20
}
#
# Netlink event socket buffer size. If you do not specify this clause,
# the default buffer size value in /proc/net/core/rmem_default is
# used. This default value is usually around 100 Kbytes which is
# fairly small for busy firewalls. This leads to event message dropping
# and high CPU consumption. This example configuration file sets the
# size to 2 MBytes to avoid this sort of problems.
#
NetlinkBufferSize 2097152
#
# The daemon doubles the size of the netlink event socket buffer size
# if it detects netlink event message dropping. This clause sets the
# maximum buffer size growth that can be reached. This example file
# sets the size to 8 MBytes.
#
NetlinkBufferSizeMaxGrowth 8388608
#
# If the daemon detects that Netlink is dropping state-change events,
# it automatically schedules a resynchronization against the Kernel
# after 30 seconds (default value). Resynchronizations are expensive
# in terms of CPU consumption since the daemon has to get the full
# kernel state-table and purge state-entries that do not exist anymore.
# Be careful of setting a very small value here. You have the following
# choices: On (enabled, use default 30 seconds value), Off (disabled)
# or Value (in seconds, to set a specific amount of time). If not
# specified, the daemon assumes that this option is enabled.
#
# NetlinkOverrunResync On
#
# If you want reliable event reporting over Netlink, set on this
# option. If you set on this clause, it is a good idea to set off
# NetlinkOverrunResync. This option is off by default and you need
# a Linux kernel >= 2.6.31.
#
# NetlinkEventsReliable Off
#
# By default, the daemon receives state updates following an
# event-driven model. You can modify this behaviour by switching to
# polling mode with the PollSecs clause. This clause tells conntrackd
# to dump the states in the kernel every N seconds. With regards to
# synchronization mode, the polling mode can only guarantee that
# long-lifetime states are recovered. The main advantage of this method
# is the reduction in the state replication at the cost of reducing the
# chances of recovering connections.
#
# PollSecs 15
#
# The daemon prioritizes the handling of state-change events coming
# from the core. With this clause, you can set the maximum number of
# state-change events (those coming from kernel-space) that the daemon
# will handle after which it will handle other events coming from the
# network or userspace. A low value improves interactivity (in terms of
# real-time behaviour) at the cost of extra CPU consumption.
# Default (if not set) is 100.
#
# EventIterationLimit 100
#
# Event filtering: This clause allows you to filter certain traffic,
# There are currently three filter-sets: Protocol, Address and
# State. The filter is attached to an action that can be: Accept or
# Ignore. Thus, you can define the event filtering policy of the
# filter-sets in positive or negative logic depending on your needs.
# You can select if conntrackd filters the event messages from
# user-space or kernel-space. The kernel-space event filtering
# saves some CPU cycles by avoiding the copy of the event message
# from kernel-space to user-space. The kernel-space event filtering
# is prefered, however, you require a Linux kernel >= 2.6.29 to
# filter from kernel-space. If you want to select kernel-space
# event filtering, use the keyword 'Kernelspace' instead of
# 'Userspace'.
#
Filter From Userspace {
#
# Accept only certain protocols: You may want to replicate
# the state of flows depending on their layer 4 protocol.
#
Protocol Accept {
TCP
SCTP
DCCP
# UDP
# ICMP # This requires a Linux kernel >= 2.6.31
}
#
# Ignore traffic for a certain set of IP's: Usually all the
# IP assigned to the firewall since local traffic must be
# ignored, only forwarded connections are worth to replicate.
# Note that these values depends on the local IPs that are
# assigned to the firewall.
#
Address Ignore {
IPv4_address 127.0.0.1 # loopback
IPv4_address [IGNORE_IP1]
IPv4_address [IGNORE_IP2]
IPv4_address [IGNORE_IP3]
#IPv4_address 192.168.0.100 # virtual IP 1
#IPv4_address 192.168.1.100 # virtual IP 2
#IPv4_address 192.168.0.1
#IPv4_address 192.168.1.1
#IPv4_address 192.168.100.100 # dedicated link ip
#
# You can also specify networks in format IP/cidr.
# IPv4_address 192.168.0.0/24
#
# You can also specify an IPv6 address
# IPv6_address ::1
}
#
# Uncomment this line below if you want to filter by flow state.
# This option introduces a trade-off in the replication: it
# reduces CPU consumption at the cost of having lazy backup
# firewall replicas. The existing TCP states are: SYN_SENT,
# SYN_RECV, ESTABLISHED, FIN_WAIT, CLOSE_WAIT, LAST_ACK,
# TIME_WAIT, CLOSED, LISTEN.
#
# State Accept {
# ESTABLISHED CLOSED TIME_WAIT CLOSE_WAIT for TCP
# }
}
}

View File

@ -0,0 +1,23 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
ip link|grep BROADCAST|grep -v eth0|grep -v eth1|cut -d ":" -f 2 > /tmp/iflist
while read i
do
ifconfig $i down
done < /tmp/iflist

View File

@ -0,0 +1,50 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
ip link|grep BROADCAST|grep -v eth0|grep -v eth1|cut -d ":" -f 2 > /tmp/iflist
ip addr show eth2 | grep "inet" 2>&1 > /dev/null
is_init=$?
set -e
while read i
do
# if eth2'ip has already been configured, we would use ifconfig rather than ifdown/ifup
if [ "$i" == "eth2" -a "$is_init" != "0" ]
then
ifdown $i
ifup $i
else
ifconfig $i down
ifconfig $i up
fi
done < /tmp/iflist
ip route add default via [GATEWAY] dev eth2
while read line
do
dev=$(echo $line | awk '{print $1'})
gw=$(echo $line | awk '{print $2'})
if [ "$dev" == "eth2" ]
then
continue;
fi
ip route add default via $gw table Table_$dev proto static
done < /var/cache/cloud/ifaceGwIp

View File

@ -0,0 +1,37 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
source /root/func.sh
lock="biglock"
locked=$(getLockFile $lock)
if [ "$locked" != "1" ]
then
exit 1
fi
echo To fault called >> [RROUTER_LOG]
[RROUTER_BIN_PATH]/disable_pubip.sh >> [RROUTER_LOG] 2>&1
echo Disable public ip >> [RROUTER_LOG]
[RROUTER_BIN_PATH]/services.sh stop >> [RROUTER_LOG] 2>&1
echo Stop services $? >> [RROUTER_LOG]
[RROUTER_BIN_PATH]/primary-backup.sh fault >> [RROUTER_LOG] 2>&1
echo Switch conntrackd mode fault $? >> [RROUTER_LOG]
echo Status: FAULT >> [RROUTER_LOG]
releaseLockFile $lock $locked

View File

@ -0,0 +1,20 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
t=$(date +%s)
echo $t > /ramdisk/rrouter/keepalived.ts

View File

@ -0,0 +1,57 @@
! Licensed to the Apache Software Foundation (ASF) under one
! or more contributor license agreements. See the NOTICE file
! distributed with this work for additional information
! regarding copyright ownership. The ASF licenses this file
! to you under the Apache License, Version 2.0 (the
! "License"); you may not use this file except in compliance
! with the License. You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing,
! software distributed under the License is distributed on an
! "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
! KIND, either express or implied. See the License for the
! specific language governing permissions and limitations
! under the License.
global_defs {
router_id [ROUTER_ID]
}
vrrp_script check_bumpup {
script "[RROUTER_BIN_PATH]/check_bumpup.sh"
interval 5
weight [DELTA]
}
vrrp_script heartbeat {
script "[RROUTER_BIN_PATH]/heartbeat.sh"
interval 10
}
vrrp_instance inside_network {
state BACKUP
interface eth0
virtual_router_id 51
priority [PRIORITY]
advert_int 1
authentication {
auth_type PASS
auth_pass WORD
}
virtual_ipaddress {
[ROUTER_IP] brd [BOARDCAST] dev eth0
}
track_script {
check_bumpup
heartbeat
}
notify_master "[RROUTER_BIN_PATH]/master.sh"
notify_backup "[RROUTER_BIN_PATH]/backup.sh"
notify_fault "[RROUTER_BIN_PATH]/fault.sh"
}

View File

@ -0,0 +1,60 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
source /root/func.sh
lock="biglock"
locked=$(getLockFile $lock)
if [ "$locked" != "1" ]
then
exit 1
fi
echo To master called >> [RROUTER_LOG]
[RROUTER_BIN_PATH]/enable_pubip.sh >> [RROUTER_LOG] 2>&1
ret=$?
if [ $ret -eq 0 ]
then
[RROUTER_BIN_PATH]/services.sh restart >> [RROUTER_LOG] 2>&1
ret=$?
fi
last_msg=`tail -n 1 [RROUTER_LOG]`
echo Enable public ip returned $ret >> [RROUTER_LOG]
if [ $ret -ne 0 ]
then
echo Fail to enable public ip! >> [RROUTER_LOG]
[RROUTER_BIN_PATH]/disable_pubip.sh >> [RROUTER_LOG] 2>&1
[RROUTER_BIN_PATH]/services.sh stop >> [RROUTER_LOG] 2>&1
service keepalived stop >> [RROUTER_LOG] 2>&1
service conntrackd stop >> [RROUTER_LOG] 2>&1
echo Status: FAULT \($last_msg\) >> [RROUTER_LOG]
releaseLockFile $lock $locked
exit
fi
[RROUTER_BIN_PATH]/primary-backup.sh primary >> [RROUTER_LOG] 2>&1
ret=$?
echo Switch conntrackd mode primary returned $ret >> [RROUTER_LOG]
if [ $ret -ne 0 ]
then
echo Fail to switch conntrackd mode, but try to continue working >> [RROUTER_LOG]
fi
[RROUTER_BIN_PATH]/arping_gateways.sh
echo Status: MASTER >> [RROUTER_LOG]
releaseLockFile $lock $locked
exit 0

View File

@ -0,0 +1,126 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
CONNTRACKD_BIN=/usr/sbin/conntrackd
CONNTRACKD_LOCK=/var/lock/conntrack.lock
CONNTRACKD_CONFIG=/etc/conntrackd/conntrackd.conf
CONNTRACKD_LOG=[RROUTER_LOG]
case "$1" in
primary)
#
# commit the external cache into the kernel table
#
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -c
if [ $? -eq 1 ]
then
logger "ERROR: failed to invoke conntrackd -c"
fi
#
# flush the internal and the external caches
#
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -f
if [ $? -eq 1 ]
then
logger "ERROR: failed to invoke conntrackd -f"
fi
#
# resynchronize my internal cache to the kernel table
#
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -R
if [ $? -eq 1 ]
then
logger "ERROR: failed to invoke conntrackd -R"
fi
#
# send a bulk update to backups
#
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -B
if [ $? -eq 1 ]
then
logger "ERROR: failed to invoke conntrackd -B"
fi
echo Conntrackd switch to primary done >> $CONNTRACKD_LOG
;;
backup)
#
# is conntrackd running? request some statistics to check it
#
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -s
if [ $? -eq 1 ]
then
#
# something's wrong, do we have a lock file?
#
if [ -f $CONNTRACKD_LOCK ]
then
logger "WARNING: conntrackd was not cleanly stopped."
logger "If you suspect that it has crashed:"
logger "1) Enable coredumps"
logger "2) Try to reproduce the problem"
logger "3) Post the coredump to netfilter-devel@vger.kernel.org"
rm -f $CONNTRACKD_LOCK
fi
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -d
if [ $? -eq 1 ]
then
logger "ERROR: cannot launch conntrackd"
exit 1
fi
fi
#
# shorten kernel conntrack timers to remove the zombie entries.
#
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -t
if [ $? -eq 1 ]
then
logger "ERROR: failed to invoke conntrackd -t"
fi
#
# request resynchronization with master firewall replica (if any)
# Note: this does nothing in the alarm approach.
#
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -n
if [ $? -eq 1 ]
then
logger "ERROR: failed to invoke conntrackd -n"
fi
echo Conntrackd switch to backup done >> $CONNTRACKD_LOG
;;
fault)
#
# shorten kernel conntrack timers to remove the zombie entries.
#
$CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -t
if [ $? -eq 1 ]
then
logger "ERROR: failed to invoke conntrackd -t"
fi
echo Conntrackd switch to fault done >> $CONNTRACKD_LOG
;;
*)
logger "conntrackd: ERROR: unknown state transition: " $1
echo "Usage: primary-backup.sh {primary|backup|fault}"
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,68 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
vpn_service() {
ps aux|grep ipsec | grep -v grep > /dev/null
no_vpn=$?
if [ $no_vpn -eq 1 ]
then
return 0
fi
r=0
case "$1" in
stop)
service ipsec stop && \
service xl2tpd stop
r=$?
;;
restart)
service ipsec restart && \
service xl2tpd restart
r=$?
;;
esac
return $r
}
ret=0
case "$1" in
start)
vpn_service restart && \
service cloud-passwd-srvr start && \
service dnsmasq start
ret=$?
;;
stop)
vpn_service stop && \
service cloud-passwd-srvr stop && \
service dnsmasq stop
ret=$?
;;
restart)
vpn_service restart && \
service cloud-passwd-srvr restart && \
service dnsmasq restart
ret=$?
;;
*)
echo "Usage: services {start|stop|restart}"
exit 1
;;
esac
exit $ret

View File

@ -227,13 +227,16 @@ class UpdateConfigTestCase(SystemVMTestCase):
"domain_name":"devcloud.local", "domain_name":"devcloud.local",
"type":"guestnetwork" "type":"guestnetwork"
} }
config['add'] = False
# Clear up from any failed test runs
self.update_config(config)
config['add'] = True
self.guest_network(config) self.guest_network(config)
passw = { "172.16.1.20" : "20", passw = { "172.16.1.20" : "20",
"172.16.1.21" : "21", "172.16.1.21" : "21",
"172.16.1.22" : "22" "172.16.1.22" : "22"
} }
self.check_password(passw) self.check_password(passw)
#self.check_acl(self.basic_acl)
passw = { "172.16.1.20" : "120", passw = { "172.16.1.20" : "120",
"172.16.1.21" : "121", "172.16.1.21" : "121",
@ -318,14 +321,41 @@ class UpdateConfigTestCase(SystemVMTestCase):
assert file.has_line("/var/cache/cloud/passwords", "%s=%s" % (ip, password)) assert file.has_line("/var/cache/cloud/passwords", "%s=%s" % (ip, password))
def guest_network(self,config): def guest_network(self,config):
vpn_config = {
"local_public_ip": config['router_guest_ip'],
"local_guest_cidr":"%s/%s" % (config['router_guest_gateway'], config['cidr']),
"local_public_gateway":"172.16.1.1",
"peer_gateway_ip":"10.200.200.1",
"peer_guest_cidr_list":"10.0.0.0/24",
"esp_policy":"3des-md5",
"ike_policy":"3des-md5",
"ipsec_psk":"vpnblabla",
"ike_lifetime":86400,
"esp_lifetime":3600,
"create":True,
"dpd":False,
"passive":False,
"type":"site2sitevpn"
}
octets = config['router_guest_ip'].split('.')
configs = []
# This should fail because the network does not yet exist
self.update_config(vpn_config)
assert not file.exists("/etc/ipsec.d/ipsec.vpn-%s.conf" % vpn_config['peer_gateway_ip'])
self.update_config(config) self.update_config(config)
self.update_config(vpn_config)
assert ip.has_ip("%s/%s" % (config['router_guest_ip'], config['cidr']), config['device']) assert ip.has_ip("%s/%s" % (config['router_guest_ip'], config['cidr']), config['device'])
assert process.is_up("apache2"), "Apache2 should be running after adding a guest network" assert process.is_up("apache2"), "Apache2 should be running after adding a guest network"
assert process.is_up("dnsmasq"), "Dnsmasq should be running after adding a guest network" assert process.is_up("dnsmasq"), "Dnsmasq should be running after adding a guest network"
assert file.exists("/etc/ipsec.d/ipsec.vpn-%s.conf" % vpn_config['peer_gateway_ip'])
assert file.mode_is("/etc/ipsec.d/ipsec.vpn-%s.secrets" % vpn_config['peer_gateway_ip'], "400")
result = run("/usr/sbin/ipsec setup status", timeout=600, warn_only=True)
assert result.succeeded, 'ipsec returned non zero status %s' % config['router_guest_ip']
# Add a host to the dhcp server # Add a host to the dhcp server
# This must happen in order for dnsmasq to be listening # This must happen in order for dnsmasq to be listening
octets = config['router_guest_ip'].split('.')
configs = []
for n in range(3,13): for n in range(3,13):
ipb = ".".join(octets[0:3]) ipb = ".".join(octets[0:3])
ipa = "%s.%s" % (ipb, n) ipa = "%s.%s" % (ipb, n)
@ -351,6 +381,8 @@ class UpdateConfigTestCase(SystemVMTestCase):
for o in configs: for o in configs:
line = "%s,%s,%s,infinite" % (o['mac_address'], o['ipv4_adress'], o['host_name']) line = "%s,%s,%s,infinite" % (o['mac_address'], o['ipv4_adress'], o['host_name'])
assert file.has_line("/etc/dhcphosts.txt", line) is False assert file.has_line("/etc/dhcphosts.txt", line) is False
# If the network gets deleted so should the vpn
assert not file.exists("/etc/ipsec.d/ipsec.vpn-%s.conf" % vpn_config['peer_gateway_ip'])
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()