Ian Southam 093749eaae A start on the redundancy code
This will not break anything but also will not work
2015-03-16 11:35:29 +01:00

138 lines
5.5 KiB
Python

# -- 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