Lots of changes to do with redundancy

This commit is contained in:
Ian Southam 2015-01-26 14:17:25 +01:00 committed by wilderrodrigues
parent 62d586e2af
commit 279f1a2741
11 changed files with 91 additions and 49 deletions

View File

@ -61,6 +61,9 @@ class CsCmdLine(CsDataBag):
return self.idata()['router_pr']
return 99
def set_priority(self, val):
self.idata()['router_pr'] = val
def is_redundant(self):
if "redundant_router" in self.idata():
return self.idata()['redundant_router'] == "true"

View File

@ -68,8 +68,8 @@ class CsDhcp(CsDataBag):
line = "dhcp-option=tag:interface-%s,15,%s" % (device, gn.get_domain())
self.conf.search(sline, line)
# DNS search order
sline = "dhcp-option=tag:interface-%s,119" % device
line = "dhcp-option=tag:interface-%s,119,%s" % (device, ','.join(gn.get_dns()))
sline = "dhcp-option=tag:interface-%s,6" % device
line = "dhcp-option=tag:interface-%s,6,%s" % (device, ','.join(gn.get_dns()))
self.conf.search(sline, line)
# Gateway
gateway = ''
@ -103,7 +103,7 @@ class CsDhcp(CsDataBag):
"del": False
}
changed.append(to)
for v in changed:
if v['mac'] == to['mac'] or v['ip'] == to['ip'] or v['host'] == to['host']:
to['del'] = True

View File

@ -37,29 +37,29 @@ class CsGuestNetwork:
def get_dns(self):
if not self.guest:
return self.config.get_dns()
# Can a router provide dhcp but not dns?
return self.config.get_dns()
# Can a router provide dhcp but not dns?
if 'dns' in self.data:
return [ self.data['router_guest_gateway'] ] + self.data['dns'].split(',')
return [self.data['router_guest_gateway']] + self.data['dns'].split(',')
elif "router_guest_gateway" in self.data:
return [ self.data['router_guest_gateway'] ]
return [self.data['router_guest_gateway']]
else:
return [""]
def set_dns(self, val):
self.data['dns'] = val
self.data['dns'] = val
def set_router(self, val):
self.data['router_guest_gateway'] = val
self.data['router_guest_gateway'] = val
def get_netmask(self):
#We need to fix it properly. I just added the if, as Ian did in some other files, to avoid the exception.
# We need to fix it properly. I just added the if, as Ian did in some other files, to avoid the exception.
if 'router_guest_netmask' in self.data:
return self.data['router_guest_netmask']
return ''
def get_gateway(self):
#We need to fix it properly. I just added the if, as Ian did in some other files, to avoid the exception.
# We need to fix it properly. I just added the if, as Ian did in some other files, to avoid the exception.
if 'router_guest_gateway' in self.data:
return self.data['router_guest_gateway']
return ''

View File

@ -50,4 +50,4 @@ class CsProcess(object):
def find(self):
has_pid = len(self.find_pid()) > 0
return has_pid
return has_pid

View File

@ -43,6 +43,8 @@ from CsConfig import CsConfig
class CsRedundant(object):
CS_RAMDISK_DIR = "/ramdisk"
CS_PRIO_UP = 1
CS_PRIO_DOWN = -1
CS_ROUTER_DIR = "%s/rrouter" % CS_RAMDISK_DIR
CS_TEMPLATES = [
"heartbeat.sh.templ", "check_heartbeat.sh.templ",
@ -50,9 +52,10 @@ class CsRedundant(object):
]
CS_TEMPLATES_DIR = "/opt/cloud/templates"
CONNTRACKD_BIN = "/usr/sbin/conntrackd"
CONNTRACKD_LOCK = "/var/lock/conntrack.lock"
CONNTRACKD_CONFIG = "/etc/conntrackd/conntrackd.conf"
CONNTRACKD_KEEPALIVED_CONFLOCK = "/var/lock/conntrack.lock"
CONNTRACKD_CONF = "/etc/conntrackd/conntrackd.conf"
RROUTER_LOG = "/var/log/cloud.log"
KEEPALIVED_CONF = "/etc/keepalived/keepalived.conf"
def __init__(self, config):
self.cl = config.cmdline()
@ -71,8 +74,8 @@ class CsRedundant(object):
CsHelper.service("keepalived", "stop")
CsHelper.umount_tmpfs(self.CS_RAMDISK_DIR)
CsHelper.rmdir(self.CS_RAMDISK_DIR)
CsHelper.rm("/etc/conntrackd/conntrackd.conf")
CsHelper.rm("/etc/keepalived/keepalived.conf")
CsHelper.rm(self.CONNTRACKD_CONF)
CsHelper.rm(self.KEEPALIVED_CONF)
def _redundant_on(self):
CsHelper.mkdir(self.CS_RAMDISK_DIR, 0755, False)
@ -83,17 +86,18 @@ class CsRedundant(object):
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, "keepalived.conf.templ"), self.KEEPALIVED_CONF)
CsHelper.copy_if_needed("%s/%s" % (self.CS_TEMPLATES_DIR, "conntrackd.conf.templ"), self.CONNTRACKD_CONF)
CsHelper.copy_if_needed("%s/%s" % (self.CS_TEMPLATES_DIR, "checkrouter.sh.templ"), "/opt/cloud/bin/checkrouter.sh")
CsHelper.execute('sed -i "s/--exec\ \$DAEMON;/--exec\ \$DAEMON\ --\ --vrrp;/g" /etc/init.d/keepalived')
# checkrouter.sh configuration
file = CsFile("/opt/cloud/bin/checkrouter.sh")
file.greplace("[RROUTER_LOG]", self.RROUTER_LOG)
file.commit()
# keepalived configuration
file = CsFile("/etc/keepalived/keepalived.conf")
file = CsFile(self.KEEPALIVED_CONF)
file.search(" router_id ", " router_id %s" % self.cl.get_name())
file.search(" priority ", " priority %s" % self.cl.get_priority())
file.search(" weight ", " weight %s" % 2)
@ -103,7 +107,7 @@ class CsRedundant(object):
# conntrackd configuration
guest = self.address.get_guest_if()
connt = CsFile("/etc/conntrackd/conntrackd.conf")
connt = CsFile(self.CONNTRACKD_CONF)
connt.section("Multicast {", "}", [
"IPv4_address 225.0.0.50\n",
"Group 3780\n",
@ -139,7 +143,7 @@ class CsRedundant(object):
ads = [o for o in self.address.get_ips() if o.needs_vrrp()]
for o in ads:
CsHelper.execute("ifconfig %s down" % o.get_device())
cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONFIG)
cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF)
CsHelper.execute("%s -s" % cmd)
CsHelper.service("ipsec", "stop")
CsHelper.service("xl2tpd", "stop")
@ -163,14 +167,15 @@ class CsRedundant(object):
ads = [o for o in self.address.get_ips() if o.is_public()]
for o in ads:
CsHelper.execute("ifconfig %s down" % o.get_device())
cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONFIG)
cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF)
CsHelper.execute("%s -d" % cmd)
CsHelper.service("ipsec", "stop")
CsHelper.service("xl2tpd", "stop")
CsHelper.service("cloud-passwd-srvr", "stop")
CsHelper.service("dnsmasq", "stop")
self._set_priority(self.CS_PRIO_DOWN)
self.cl.dbag['config']['redundant_master'] = "false"
CsHelper.service("keepalived", "restart")
#CsHelper.service("keepalived", "restart")
self.cl.save()
logging.info("Router switched to backup mode")
@ -192,7 +197,7 @@ class CsRedundant(object):
CsHelper.execute("arping -I %s -A %s -c 1" % (o.get_device(), o.get_ip()))
# FIXME Need to add in the default routes but I am unsure what the gateway is
# ip route add default via $gw table Table_$dev proto static
cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONFIG)
cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF)
CsHelper.execute("%s -c" % cmd)
CsHelper.execute("%s -f" % cmd)
CsHelper.execute("%s -R" % cmd)
@ -202,10 +207,17 @@ class CsRedundant(object):
CsHelper.service("cloud-passwd-srvr", "restart")
CsHelper.service("dnsmasq", "restart")
self.cl.dbag['config']['redundant_master'] = "true"
self._set_priority(self.CS_PRIO_UP)
self.cl.save()
CsHelper.service("keepalived", "restart")
#CsHelper.service("keepalived", "restart")
logging.info("Router switched to master mode")
def _set_priority(self, dir):
self.cl.set_priority(int(self.cl.get_priority()) + dir)
file = CsFile(self.KEEPALIVED_CONF)
file.search(" priority ", " priority %s" % self.cl.get_priority())
file.commit()
def _collect_ignore_ips(self):
"""
This returns a list of ip objects that should be ignored
@ -232,4 +244,14 @@ class CsRedundant(object):
if o.needs_vrrp():
str = " %s brd %s dev %s\n" % (o.get_gateway_cidr(), o.get_broadcast(), o.get_device())
lines.append(str)
# This is wrong set_master and set_backup need to do this
self.check_is_up(o.get_device())
return lines
def check_is_up(self, device):
""" Ensure device is up """
cmd = "ip link show %s | grep 'state DOWN'" % device
for i in CsHelper.execute(cmd):
if " DOWN " in i:
cmd2 = "ip link set %s up" % device
CsHelper.execute(cmd2)

View File

@ -19,11 +19,12 @@ from pprint import pprint
keys = ['eth1', 'eth2', 'eth3', 'eth4', 'eth5', 'eth6', 'eth7', 'eth8', 'eth9']
def merge(dbag, gn):
device = gn['device']
if not gn['add'] and device in dbag:
if dbag[device]:
device_to_die = dbag[device][0]
try:
@ -33,8 +34,8 @@ def merge(dbag, gn):
del(dbag[device])
else:
del(dbag[device])
else:
dbag.setdefault(device, []).append(gn)
return dbag
return dbag

View File

@ -0,0 +1,10 @@
from cs.CsGuestNetwork import CsGuestNetwork
import merge
merge.DataBag.DPATH = "."
csguestnetwork = CsGuestNetwork({}, {})
csguestnetwork.guest = True
csguestnetwork.set_dns("1.1.1.1,2.2.2.2")
csguestnetwork.set_router("3.3.3.3")
dns = csguestnetwork.get_dns()
print dns

View File

@ -126,7 +126,6 @@ class updateDataBag:
def processGuestNetwork(self, dbag):
d = self.qFile.data
dp = {}
dp['public_ip'] = d['router_guest_ip']
dp['netmask'] = d['router_guest_netmask']

View File

@ -38,11 +38,13 @@ jsonPath = "/var/cache/cloud/%s"
jsonCmdConfigPath = jsonPath % sys.argv[1]
currentGuestNetConfig = "/etc/cloudstack/guestnetwork.json"
def finish_config():
# Converge
returncode = configure.main([])
sys.exit(returncode)
def process_file():
print "[INFO] Processing JSON file %s" % sys.argv[1]
qf = QueueFile()
@ -51,59 +53,60 @@ def process_file():
# Converge
finish_config()
def is_guestnet_configured(guestnet_dict, keys):
existing_keys = []
new_eth_key = None
for k1, v1 in guestnet_dict.iteritems():
if k1 in keys and len(v1) > 0:
existing_keys.append(k1)
if not existing_keys:
'''
It seems all the interfaces have been removed. Let's allow a new configuration to come in.
'''
print "[WARN] update_config.py :: Reconfiguring guest network..."
return False
file = open(jsonCmdConfigPath)
new_guestnet_dict = json.load(file)
if not new_guestnet_dict['add']:
'''
Guest network has to be removed.
'''
print "[INFO] update_config.py :: Removing guest network..."
return False
'''
Check if we have a new guest network ready to be setup
'''
device = new_guestnet_dict['device']
if device in existing_keys:
'''
Device already configured, ignore.
'''
return True
exists = False
for key in existing_keys:
for interface in guestnet_dict[key]:
new_mac = new_guestnet_dict["mac_address"].encode('utf-8')
old_mac = interface["mac_address"].encode('utf-8')
new_ip = new_guestnet_dict["router_guest_ip"].encode('utf-8')
old_ip = interface["router_guest_ip"].encode('utf-8')
if (new_mac == old_mac) and (new_ip == old_ip):
exists = True
break
if exists:
break
return exists
if not (os.path.isfile(jsonCmdConfigPath) and os.access(jsonCmdConfigPath, os.R_OK)):
@ -122,7 +125,7 @@ if sys.argv[1] == "guest_network.json":
if os.path.isfile(currentGuestNetConfig):
file = open(currentGuestNetConfig)
guestnet_dict = json.load(file)
if not is_guestnet_configured(guestnet_dict, ['eth1', 'eth2', 'eth3', 'eth4', 'eth5', 'eth6', 'eth7', 'eth8', 'eth9']):
print "[INFO] update_config.py :: Processing Guest Network."
process_file()
@ -133,5 +136,5 @@ if sys.argv[1] == "guest_network.json":
print "[INFO] update_config.py :: No GuestNetwork configured yet. Configuring first one now."
process_file()
else:
print "[INFO] update_config.py :: Processing incoming file => %s" % sys.argv[1]
process_file()
print "[INFO] update_config.py :: Processing incoming file => %s" % sys.argv[1]
process_file()

View File

@ -52,7 +52,7 @@ vrrp_instance inside_network {
}
!That's the correct path of the master.py file.
!notify_master "/opt/cloud/bin/master.py --master"
!notify_backup "/opt/cloud/bin/master.py --backup"
!notify_fault "/opt/cloud/bin/master.py --fault"
notify_master "/opt/cloud/bin/master.py --master"
notify_backup "/opt/cloud/bin/master.py --backup"
notify_fault "/opt/cloud/bin/master.py --fault"
}

View File

@ -18,6 +18,10 @@ class TestCsCmdLine(unittest.TestCase):
def test_get_priority(self):
self.assertTrue(self.cscmdline.get_priority() == 99)
def test_set_priority(self):
self.cscmdline.set_priority(100)
self.assertTrue(self.cscmdline.get_priority() == 100)
def test_is_redundant(self):
self.assertTrue(self.cscmdline.is_redundant() is False)
self.cscmdline.set_redundant()