def set_master(self): """ Set the current router to master """ if not self.cl.is_redundant(): logging.error("Set master called on non-redundant router") return self.set_lock() logging.debug("Setting router to master") dev = '' interfaces = [interface for interface in self.address.get_interfaces() if interface.is_public()] route = CsRoute() for interface in interfaces: if dev == interface.get_device(): continue dev = interface.get_device() logging.info("Will proceed configuring device ==> %s" % dev) cmd = "ip link set %s up" % dev if CsDevice(dev, self.config).waitfordevice(): CsHelper.execute(cmd) logging.info("Bringing public interface %s up" % dev) try: gateway = interface.get_gateway() logging.info("Adding gateway ==> %s to device ==> %s" % (gateway, dev)) if dev == CsHelper.PUBLIC_INTERFACES[self.cl.get_type()]: route.add_defaultroute(gateway) except: logging.error("ERROR getting gateway from device %s" % dev) else: logging.error("Device %s was not ready could not bring it up" % dev) logging.debug("Configuring static routes") static_routes = CsStaticRoutes("staticroutes", self.config) static_routes.process() 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) CsHelper.execute("%s -B" % cmd) CsHelper.service("ipsec", "restart") CsHelper.service("xl2tpd", "restart") interfaces = [interface for interface in self.address.get_interfaces() if interface.needs_vrrp()] for interface in interfaces: # Listen on local ip address, as cloud-init uses the 'dhcp-server-identifier' address, # which unfortunately is not the gateway address. CsPasswdSvc(interface.get_ip()).start() CsHelper.service("dnsmasq", "restart") self.cl.set_master_state(True) self.cl.save() self.release_lock() interfaces = [interface for interface in self.address.get_interfaces() if interface.is_public()] CsHelper.reconfigure_interfaces(self.cl, interfaces) logging.info("Router switched to master mode")
def set_master(self): """ Set the current router to master """ if not self.cl.is_redundant(): logging.error("Set master called on non-redundant router") return self.set_lock() logging.debug("Setting router to master") ads = [o for o in self.address.get_ips() if o.is_public()] dev = '' route = CsRoute() for o in ads: if dev == o.get_device(): continue dev = o.get_device() logging.info("Will proceed configuring device ==> %s" % dev) cmd2 = "ip link set %s up" % dev if CsDevice(dev, self.config).waitfordevice(): CsHelper.execute(cmd2) logging.info("Bringing public interface %s up" % dev) try: gateway = o.get_gateway() logging.info("Adding gateway ==> %s to device ==> %s" % (gateway, dev)) route.add_defaultroute(gateway) except: logging.error("ERROR getting gateway from device %s" % dev) else: logging.error("Device %s was not ready could not bring it up" % dev) # ip route add default via $gw table Table_$dev proto static 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) CsHelper.execute("%s -B" % cmd) CsHelper.service("ipsec", "restart") CsHelper.service("xl2tpd", "restart") ads = [o for o in self.address.get_ips() if o.needs_vrrp()] for o in ads: CsPasswdSvc(o.get_gateway()).restart() CsHelper.service("dnsmasq", "restart") self.cl.set_master_state(True) self.cl.save() self.release_lock() logging.info("Router switched to master mode")
def _redundant_on(self): guest = self.address.get_guest_if() # No redundancy if there is no guest network if guest is None: self.set_backup() self._redundant_off() return interfaces = [ interface for interface in self.address.get_interfaces() if interface.is_guest() ] isDeviceReady = False dev = '' for interface in interfaces: if dev == interface.get_device(): continue dev = interface.get_device() logging.info( "Wait for devices to be configured so we can start keepalived") devConfigured = CsDevice(dev, self.config).waitfordevice() if devConfigured: command = "ip link show %s | grep 'state UP'" % dev devUp = CsHelper.execute(command) if devUp: logging.info( "Device %s is present, let's start keepalived now." % dev) isDeviceReady = True if not isDeviceReady: logging.info( "Guest network not configured yet, let's stop router redundancy for now." ) CsHelper.service("conntrackd", "stop") CsHelper.service("keepalived", "stop") return 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"), self.KEEPALIVED_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 check_router = CsFile("/opt/cloud/bin/checkrouter.sh") check_router.greplace("[RROUTER_LOG]", self.RROUTER_LOG) check_router.commit() # keepalived configuration keepalived_conf = CsFile(self.KEEPALIVED_CONF) keepalived_conf.search(" router_id ", " router_id %s" % self.cl.get_name()) keepalived_conf.search(" interface ", " interface %s" % guest.get_device()) keepalived_conf.search(" advert_int ", " advert_int %s" % self.cl.get_advert_int()) keepalived_conf.greplace("[RROUTER_BIN_PATH]", self.CS_ROUTER_DIR) keepalived_conf.section("authentication {", "}", [ " auth_type AH \n", " auth_pass %s\n" % self.cl.get_router_password()[:8] ]) keepalived_conf.section("virtual_ipaddress {", "}", self._collect_ips()) # conntrackd configuration conntrackd_template_conf = "%s/%s" % (self.CS_TEMPLATES_DIR, "conntrackd.conf.templ") conntrackd_temp_bkp = "%s/%s" % (self.CS_TEMPLATES_DIR, "conntrackd.conf.templ.bkp") CsHelper.copy(conntrackd_template_conf, conntrackd_temp_bkp) conntrackd_tmpl = CsFile(conntrackd_template_conf) conntrackd_tmpl.section("Multicast {", "}", [ "IPv4_address 225.0.0.50\n", "Group 3780\n", "IPv4_interface %s\n" % guest.get_ip(), "Interface %s\n" % guest.get_device(), "SndSocketBuffer 1249280\n", "RcvSocketBuffer 1249280\n", "Checksum on\n" ]) conntrackd_tmpl.section("Address Ignore {", "}", self._collect_ignore_ips()) conntrackd_tmpl.commit() conntrackd_conf = CsFile(self.CONNTRACKD_CONF) is_equals = conntrackd_tmpl.compare(conntrackd_conf) force_keepalived_restart = False proc = CsProcess(['/etc/conntrackd/conntrackd.conf']) if not proc.find() or not is_equals: CsHelper.copy(conntrackd_template_conf, self.CONNTRACKD_CONF) CsHelper.service("conntrackd", "restart") force_keepalived_restart = True # Restore the template file and remove the backup. CsHelper.copy(conntrackd_temp_bkp, conntrackd_template_conf) CsHelper.execute("rm -rf %s" % conntrackd_temp_bkp) # Configure heartbeat cron job - runs every 30 seconds heartbeat_cron = CsFile("/etc/cron.d/heartbeat") heartbeat_cron.add("SHELL=/bin/bash", 0) heartbeat_cron.add( "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin", 1) heartbeat_cron.add( "* * * * * root $SHELL %s/check_heartbeat.sh 2>&1 > /dev/null" % self.CS_ROUTER_DIR, -1) heartbeat_cron.add( "* * * * * root sleep 30; $SHELL %s/check_heartbeat.sh 2>&1 > /dev/null" % self.CS_ROUTER_DIR, -1) heartbeat_cron.commit() proc = CsProcess(['/usr/sbin/keepalived']) if not proc.find(): force_keepalived_restart = True if keepalived_conf.is_changed() or force_keepalived_restart: keepalived_conf.commit() os.chmod(self.KEEPALIVED_CONF, 0o644) if force_keepalived_restart or not self.cl.is_primary(): CsHelper.service("keepalived", "restart") else: CsHelper.service("keepalived", "reload")
def set_primary(self): """ Set the current router to primary """ if not self.cl.is_redundant(): logging.error("Set primary called on non-redundant router") return self.set_lock() logging.debug("Setting router to primary") dev = '' interfaces = [ interface for interface in self.address.get_interfaces() if interface.is_public() ] route = CsRoute() for interface in interfaces: if dev == interface.get_device(): continue dev = interface.get_device() logging.info("Will proceed configuring device ==> %s" % dev) cmd = "ip link set %s up" % dev if CsDevice(dev, self.config).waitfordevice(): CsHelper.execute(cmd) logging.info("Bringing public interface %s up" % dev) try: gateway = interface.get_gateway() logging.info("Adding gateway ==> %s to device ==> %s" % (gateway, dev)) if dev == CsHelper.PUBLIC_INTERFACES[self.cl.get_type()]: route.add_defaultroute(gateway) except Exception: logging.error("ERROR getting gateway from device %s" % dev) if dev == CsHelper.PUBLIC_INTERFACES[self.cl.get_type()]: try: self._add_ipv6_to_interface(interface, interface.get_ip6()) if interface.get_gateway6(): route.add_defaultroute_v6(interface.get_gateway6()) except Exception as e: logging.error( "ERROR adding IPv6, getting IPv6 gateway from device %s: %s" % (dev, e)) else: logging.error("Device %s was not ready could not bring it up" % dev) self._add_ipv6_guest_gateway() logging.debug("Configuring static routes") static_routes = CsStaticRoutes("staticroutes", self.config) static_routes.process() 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) CsHelper.execute("%s -B" % cmd) CsHelper.service("ipsec", "restart") CsHelper.service("xl2tpd", "restart") interfaces = [ interface for interface in self.address.get_interfaces() if interface.needs_vrrp() ] for interface in interfaces: if interface.is_added(): CsPasswdSvc(interface.get_gateway() + "," + interface.get_ip()).restart() CsHelper.service("dnsmasq", "restart") self.cl.set_primary_state(True) self.cl.save() self.release_lock() interfaces = [ interface for interface in self.address.get_interfaces() if interface.is_public() ] CsHelper.reconfigure_interfaces(self.cl, interfaces) public_devices = list( set([interface.get_device() for interface in interfaces])) if len(public_devices) > 1: # Handle specific failures when multiple public interfaces public_devices.sort() # Ensure the default route is added, or outgoing traffic from VMs with static NAT on # the subsequent interfaces will go from the wrong IP route = CsRoute() dev = '' for interface in interfaces: if dev == interface.get_device(): continue dev = interface.get_device() gateway = interface.get_gateway() if gateway: route.add_route(dev, gateway) # The first public interface has a static MAC address between VRs. Subsequent ones don't, # so an ARP announcement is needed on failover for device in public_devices[1:]: logging.info("Sending garp messages for IPs on %s" % device) for interface in interfaces: if interface.get_device() == device: CsHelper.execute("arping -I %s -U %s -c 1" % (device, interface.get_ip())) logging.info("Router switched to primary mode")