def set_backup(self): """ Set the current router to backup """ if not self.cl.is_redundant(): logging.error("Set backup called on non-redundant router") return """ if not self.cl.is_master(): logging.error("Set backup called on node that is already backup") return """ self.set_lock() logging.debug("Setting router to backup") ads = [o for o in self.address.get_ips() if o.is_public()] dev = '' for o in ads: if dev == o.get_device(): continue logging.info("Bringing public interface %s down" % o.get_device()) cmd2 = "ip link set %s up" % o.get_device() CsHelper.execute(cmd2) dev = o.get_device() cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF) CsHelper.execute("%s -d" % cmd) CsHelper.service("ipsec", "stop") CsHelper.service("xl2tpd", "stop") ads = [o for o in self.address.get_ips() if o.needs_vrrp()] for o in ads: CsPasswdSvc(o.get_gateway()).stop() CsHelper.service("dnsmasq", "stop") # self._set_priority(self.CS_PRIO_DOWN) self.cl.set_master_state(False) self.cl.save() self.release_lock() logging.info("Router switched to backup mode")
def set_fault(self): """ Set fault mode on this router """ if not self.cl.is_redundant(): logging.error("Set fault called on non-redundant router") return self.set_lock() logging.info("Router switched to fault mode") ips = [ip for ip in self.address.get_ips() if ip.is_public()] for ip in ips: CsHelper.execute("ifconfig %s down" % ip.get_device()) cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF) CsHelper.execute("%s -s" % cmd) CsHelper.service("ipsec", "stop") CsHelper.service("xl2tpd", "stop") CsHelper.service("dnsmasq", "stop") ips = [ip for ip in self.address.get_ips() if ip.needs_vrrp()] for ip in ips: CsPasswdSvc(ip.get_gateway()).stop() self.cl.set_fault_state() self.cl.save() self.release_lock() logging.info("Router switched to fault mode")
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)
def delete_leases(self): changed = [] leases = [] try: for line in open(LEASES): bits = line.strip().split(' ') to = {"device": bits[0], "mac": bits[1], "ip": bits[2], "host": bits[3:], "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 leases.append(to) for o in leases: if o['del']: cmd = "dhcp_release eth%s %s %s" % (o['device'], o['ip'], o['mac']) logging.info(cmd) CsHelper.execute(cmd) except IOError: return
def compare(self, list): """ Compare reality with what is needed """ for c in self.chain.get("filter"): # Ensure all inbound/outbound chains have a default drop rule if c.startswith("ACL_INBOUND") or c.startswith("ACL_OUTBOUND"): list.append(["filter", "", "-A %s -j DROP" % c]) # PASS 1: Ensure all chains are present for fw in list: new_rule = CsNetfilter() new_rule.parse(fw[2]) new_rule.set_table(fw[0]) self.add_chain(new_rule) # PASS 2: Create rules for fw in list: new_rule = CsNetfilter() new_rule.parse(fw[2]) new_rule.set_table(fw[0]) if isinstance(fw[1], int): new_rule.set_count(fw[1]) if self.has_rule(new_rule): logging.debug("rule %s exists in table %s", fw[2], new_rule.get_table()) else: # print "Add rule %s in table %s" % ( fw[2], new_rule.get_table()) logging.info("Add rule %s in table %s", fw[2], new_rule.get_table()) # front means insert instead of append cpy = fw[2] if fw[1] == "front": cpy = cpy.replace('-A', '-I') if isinstance(fw[1], int): cpy = cpy.replace("-A %s" % new_rule.get_chain(), '-I %s %s' % (new_rule.get_chain(), fw[1])) CsHelper.execute("iptables -t %s %s" % (new_rule.get_table(), cpy)) self.del_standard() self.get_unseen()
def get_unseen(self): del_list = [x for x in self.rules if x.unseen()] for r in del_list: cmd = "iptables -t %s %s" % (r.get_table(), r.to_str(True)) CsHelper.execute(cmd) # print "Delete rule %s from table %s" % (r.to_str(True), r.get_table()) logging.info("Delete rule %s from table %s", r.to_str(True), r.get_table())
def __update(self, vm_ip, password): token = "" try: tokenFile = open(self.TOKEN_FILE) token = tokenFile.read() except IOError: logging.debug("File %s does not exist" % self.TOKEN_FILE) logging.debug("Got VM '%s' and password '%s'" % (vm_ip, password)) get_cidrs_cmd = "ip addr show | grep inet | grep -v secondary | awk '{print $2}'" cidrs = CsHelper.execute(get_cidrs_cmd) logging.debug("Found these CIDRs: %s" % cidrs) for cidr in cidrs: logging.debug("Processing CIDR '%s'" % cidr) if IPAddress(vm_ip) in IPNetwork(cidr): ip = cidr.split('/')[0] logging.debug("Cidr %s matches vm ip address %s so adding passwd to passwd server at %s" % (cidr, vm_ip, ip)) proc = CsProcess(['/opt/cloud/bin/passwd_server_ip.py', ip]) if proc.find(): update_command = 'curl --header "DomU_Request: save_password" "http://{SERVER_IP}:8080/" -F "ip={VM_IP}" -F "password={PASSWORD}" ' \ '-F "token={TOKEN}" --interface 127.0.0.1 >/dev/null 2>/dev/null &'.format(SERVER_IP=ip, VM_IP=vm_ip, PASSWORD=password, TOKEN=token) result = CsHelper.execute(update_command) logging.debug("Update password server result ==> %s" % result) else: logging.debug("Update password server skipped because we didn't find a passwd server process for %s (makes sense on backup routers)" % ip)
def set_backup(self): """ Set the current router to backup """ if not self.cl.is_redundant(): logging.error("Set backup called on non-redundant router") return self.set_lock() logging.debug("Setting router to backup") dev = '' ips = [ip for ip in self.address.get_ips() if ip.is_public()] for ip in ips: if dev == ip.get_device(): continue logging.info("Bringing public interface %s down" % ip.get_device()) cmd2 = "ip link set %s down" % ip.get_device() CsHelper.execute(cmd2) dev = ip.get_device() cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF) CsHelper.execute("%s -d" % cmd) CsHelper.service("ipsec", "stop") CsHelper.service("xl2tpd", "stop") ips = [ip for ip in self.address.get_ips() if ip.needs_vrrp()] for ip in ips: CsPasswdSvc(ip.get_gateway()).stop() CsHelper.service("dnsmasq", "stop") self.cl.set_master_state(False) self.cl.save() self.release_lock() logging.info("Router switched to backup 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") 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) 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: CsPasswdSvc(interface.get_ip()).restart() CsPasswdSvc(interface.get_gateway()).restart() 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 __update(self, route): if route['revoke']: command = "ip route del %s via %s" % (route['network'], route['gateway']) CsHelper.execute(command) else: command = "ip route show | grep %s | awk '{print $1, $3}'" % route['network'] result = CsHelper.execute(command) if not result: route_command = "ip route add %s via %s" % (route['network'], route['gateway']) CsHelper.execute(route_command)
def add_table(self, devicename): tablenumber = 100 + int(devicename[3:]) tablename = self.get_tablename(devicename) str = "%s %s" % (tablenumber, tablename) filename = "/etc/iproute2/rt_tables" logging.info("Adding route table: " + str + " to " + filename + " if not present ") if not CsHelper.definedinfile(filename, str): CsHelper.execute("sudo echo " + str + " >> /etc/iproute2/rt_tables") # remove "from all table tablename" if exists, else it will interfer with # routing of unintended traffic if self.findRule("from all lookup " + tablename): CsHelper.execute("sudo ip rule delete from all table " + tablename)
def check_is_up(self): """ Ensure device is up """ cmd = "ip link show %s | grep 'state DOWN'" % self.getDevice() for i in CsHelper.execute(cmd): if " DOWN " in i: cmd2 = "ip link set %s up" % self.getDevice() # If redundant do not bring up public interfaces # master.py and keepalived deal with tham if self.cl.is_redundant() and not self.is_public(): CsHelper.execute(cmd2) # if not redundant bring everything up if not self.cl.is_redundant(): CsHelper.execute(cmd2)
def configure(self, address): # When "add" is false, it means that the IP has to be removed. if address["add"]: try: logging.info("Configuring address %s on device %s", self.ip(), self.dev) cmd = "ip addr add dev %s %s brd +" % (self.dev, self.ip()) CsHelper.execute(cmd) except Exception as e: logging.info("Exception occurred ==> %s" % e) else: self.delete(self.ip()) self.post_configure(address)
def check_is_up(self): """ Ensure device is up """ cmd = "ip link show %s | grep 'state DOWN'" % self.getDevice() for i in CsHelper.execute(cmd): if " DOWN " in i: cmd2 = "ip link set %s up" % self.getDevice() # If redundant only bring up public interfaces that are not eth1. # Reason: private gateways are public interfaces. # master.py and keepalived will deal with eth1 public interface. if self.cl.is_redundant() and (not self.is_public() or self.getDevice() not in PUBLIC_INTERFACE): CsHelper.execute(cmd2) # if not redundant bring everything up if not self.cl.is_redundant(): CsHelper.execute(cmd2)
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") self.address.process() logging.info("added default routes") # 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 set_route(self, cmd, method="add"): """ Add a route if it is not already defined """ found = False for i in CsHelper.execute("ip route show " + cmd): found = True if not found and method == "add": logging.info("Add " + cmd) cmd = "ip route add " + cmd elif found and method == "delete": logging.info("Delete " + cmd) cmd = "ip route delete " + cmd else: return CsHelper.execute(cmd)
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 list(self): self.iplist = {} cmd = ("ip addr show dev " + self.dev) for i in CsHelper.execute(cmd): vals = i.lstrip().split() if (vals[0] == 'inet'): self.iplist[vals[1]] = self.dev
def check_if_link_up(self,dev): cmd="ip link show dev %s | tr '\n' ' ' | cut -d ' ' -f 9"%dev result = CsHelper.execute(cmd) if(result and result[0].lower() == "up"): return True else: return False
def check_if_link_exists(self,dev): cmd="ip link show dev %s"%dev result = CsHelper.execute(cmd) if(len(result) != 0): return True else: return False
def compare(self, list): """ Compare reality with what is needed """ # PASS 1: Ensure all chains are present for fw in list: new_rule = CsNetfilter() new_rule.parse(fw[2]) new_rule.set_table(fw[0]) self.add_chain(new_rule) ruleSet = set() # PASS 2: Create rules for fw in list: tupledFw = tuple(fw) if tupledFw in ruleSet : logging.debug("Already processed : %s", tupledFw) continue new_rule = CsNetfilter() new_rule.parse(fw[2]) new_rule.set_table(fw[0]) if isinstance(fw[1], int): new_rule.set_count(fw[1]) rule_chain = new_rule.get_chain() logging.debug("Checking if the rule already exists: rule=%s table=%s chain=%s", new_rule.get_rule(), new_rule.get_table(), new_rule.get_chain()) if self.has_rule(new_rule): logging.debug("Exists: rule=%s table=%s", fw[2], new_rule.get_table()) else: # print "Add rule %s in table %s" % ( fw[2], new_rule.get_table()) logging.info("Add: rule=%s table=%s", fw[2], new_rule.get_table()) # front means insert instead of append cpy = fw[2] if fw[1] == "front": cpy = cpy.replace('-A', '-I') if isinstance(fw[1], int): # if the rule is for ACLs, we want to insert them in order, right before the DROP all if rule_chain.startswith("ACL_INBOUND"): rule_count = self.chain.get_count(rule_chain) cpy = cpy.replace("-A %s" % new_rule.get_chain(), '-I %s %s' % (new_rule.get_chain(), rule_count)) else: cpy = cpy.replace("-A %s" % new_rule.get_chain(), '-I %s %s' % (new_rule.get_chain(), fw[1])) CsHelper.execute("iptables -t %s %s" % (new_rule.get_table(), cpy)) ruleSet.add(tupledFw) self.chain.add_rule(rule_chain) self.del_standard() self.get_unseen()
def set_route(self, cmd, method="add"): """ Add a route if it is not already defined """ found = False search = cmd if "throw" in search: search = "type " + search for i in CsHelper.execute("ip route show " + search): found = True if not found and method == "add": logging.info("Add " + cmd) cmd = "ip route add " + cmd elif found and method == "delete": logging.info("Delete " + cmd) cmd = "ip route delete " + cmd else: return CsHelper.execute(cmd)
def set_backup(self): """ Set the current router to backup """ if not self.cl.is_redundant(): logging.error("Set backup called on non-redundant router") return self.set_lock() logging.debug("Setting router to backup") dev = '' interfaces = [ interface for interface in self.address.get_interfaces() if interface.is_public() ] for interface in interfaces: if dev == interface.get_device(): continue logging.info("Bringing public interface %s down" % interface.get_device()) cmd2 = "ip link set %s down" % interface.get_device() CsHelper.execute(cmd2) dev = interface.get_device() cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF) CsHelper.execute("%s -d" % cmd) CsHelper.service("ipsec", "stop") CsHelper.service("xl2tpd", "stop") interfaces = [ interface for interface in self.address.get_interfaces() if interface.needs_vrrp() ] for interface in interfaces: CsPasswdSvc(interface.get_gateway()).stop() CsHelper.service("dnsmasq", "stop") self.cl.set_master_state(False) 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 backup mode")
def process(self): route = CsRoute() found_defaultroute = False for dev in self.dbag: if dev == "id": continue ip = CsIP(dev, self.config) for address in self.dbag[dev]: # check if link is up if not self.check_if_link_up(dev): cmd = "ip link set %s up" % dev CsHelper.execute(cmd) gateway = str(address["gateway"]) network = str(address["network"]) ip.setAddress(address) if ip.configured(): logging.info("Address %s on device %s already configured", ip.ip(), dev) ip.post_configure() else: logging.info("Address %s on device %s not configured", ip.ip(), dev) if CsDevice(dev, self.config).waitfordevice(): ip.configure() route.add_route(dev, network) # The code looks redundant here, but we actually have to cater for routers and # VPC routers in a different manner. Please do not remove this block otherwise # The VPC default route will be broken. if address["nw_type"] == "public" and not found_defaultroute: if not route.defaultroute_exists(): if route.add_defaultroute(gateway): found_defaultroute = True # once we start processing public ip's we need to verify there # is a default route and add if needed if not route.defaultroute_exists(): cmdline = self.config.cmdline() if cmdline.get_gateway(): route.add_defaultroute(cmdline.get_gateway())
def list(self): self.iplist = {} cmd = ("ip addr show dev " + self.dev) for i in CsHelper.execute(cmd): vals = i.lstrip().split() if (vals[0] == 'inet'): cidr = vals[1] self.iplist[cidr] = self.dev
def __update(self, vm_ip, password): token = "" try: token_file = open(self.TOKEN_FILE) token = token_file.read() except IOError: logging.debug("File %s does not exist" % self.TOKEN_FILE) logging.debug("Got VM '%s' and password '%s'" % (vm_ip, password)) get_cidrs_cmd = "ip addr show | grep inet | grep -v secondary | awk '{print $2}'" cidrs = CsHelper.execute(get_cidrs_cmd) logging.debug("Found these CIDRs: %s" % cidrs) for cidr in cidrs: logging.debug("Processing CIDR '%s'" % cidr) if CsHelper.IPAddress(vm_ip) in CsHelper.IPNetwork(cidr): ip = cidr.split('/')[0] logging.debug( "Cidr %s matches vm ip address %s so adding passwd to passwd server at %s" % (cidr, vm_ip, ip)) proc = CsProcess( ['/opt/cosmic/router/bin/passwd_server_ip.py', ip]) max_tries = 5 test_tries = 0 while test_tries < max_tries: logging.debug("Updating passwd server on %s" % ip) if proc.find(): url = "http://{SERVER_IP}:8080/".format(SERVER_IP=ip) headers = {'DomU_Request': 'save_password'} params = { 'ip': vm_ip, 'password': password, 'token': token } req = urllib2.Request(url, urllib.urlencode(params), headers=headers) try: res = urllib2.urlopen(req).read() if res.code == 200: logging.debug( "Update password server result ==> %s" % res) return res except Exception as e: logging.debug( "Error while querying password server ==> %s" % e.message) test_tries += 1 logging.debug( "Testing password server process round %s/%s" % (test_tries, max_tries)) time.sleep(2) logging.debug( "Update password server skipped because we didn't find a passwd server process for " "%s (makes sense on backup routers)" % ip)
def __update(self, vm_ip, password): token = "" try: token_file = open(self.TOKEN_FILE) token = token_file.read() except IOError: logging.debug("File %s does not exist" % self.TOKEN_FILE) logging.debug("Got VM '%s' and password '%s'" % (vm_ip, password)) get_cidrs_cmd = "ip addr show | grep inet | grep -v secondary | awk '{print $2}'" cidrs = CsHelper.execute(get_cidrs_cmd) logging.debug("Found these CIDRs: %s" % cidrs) for cidr in cidrs: logging.debug("Processing CIDR '%s'" % cidr) if CsHelper.IPAddress(vm_ip) in CsHelper.IPNetwork(cidr): ip = cidr.split('/')[0] logging.debug( "Cidr %s matches vm ip address %s so adding passwd to passwd server at %s" % (cidr, vm_ip, ip)) proc = CsProcess( ['/opt/cosmic/router/bin/passwd_server_ip.py', ip]) max_tries = 5 test_tries = 0 while test_tries < max_tries: logging.debug("Updating passwd server on %s" % ip) if proc.find(): update_command = 'curl --header "DomU_Request: save_password" "http://{SERVER_IP}:8080/" -F "ip=' \ '{VM_IP}" -F "password={PASSWORD}" -F "token={TOKEN}" --interface 127.0.0.1 ' \ '>/dev/null 2>/dev/null &'.format(SERVER_IP=ip, VM_IP=vm_ip, PASSWORD=password, TOKEN=token) result = CsHelper.execute(update_command) logging.debug("Update password server result ==> %s" % result) return result test_tries += 1 self.logger.debug( "Testing password server process round %s/%s" % (test_tries, max_tries)) time.sleep(2) logging.debug( "Update password server skipped because we didn't find a passwd server process for " "%s (makes sense on backup routers)" % ip)
def _disable_radvd(self, dev): """ Disable radvd for non-primary VR """ if dev == '': return CsHelper.service("radvd", "stop") CsHelper.service("radvd", "disable") logging.info(CsHelper.execute("systemctl status radvd"))
def find_pid(self): self.pid = [] for i in CsHelper.execute("ps aux"): items = len(self.search) proc = re.split("\s+", i)[items*-1:] matches = len([m for m in proc if m in self.search]) if matches == items: self.pid.append(re.split("\s+", i)[1]) return self.pid
def compare(self, list): """ Compare reality with what is needed """ for c in self.chain.get("filter"): # Ensure all inbound/outbound chains have a default drop rule if c.startswith("ACL_INBOUND") or c.startswith("ACL_OUTBOUND"): list.append(["filter", "", "-A %s -j DROP" % c]) # PASS 1: Ensure all chains are present for fw in list: new_rule = CsNetfilter() new_rule.parse(fw[2]) new_rule.set_table(fw[0]) self.add_chain(new_rule) # PASS 2: Create rules for fw in list: new_rule = CsNetfilter() new_rule.parse(fw[2]) new_rule.set_table(fw[0]) if isinstance(fw[1], int): new_rule.set_count(fw[1]) logging.debug( "Checking if the rule already exists: rule=%s table=%s chain=%s", new_rule.get_rule(), new_rule.get_table(), new_rule.get_chain()) if self.has_rule(new_rule): logging.debug("Exists: rule=%s table=%s", fw[2], new_rule.get_table()) else: # print "Add rule %s in table %s" % ( fw[2], new_rule.get_table()) logging.info("Add: rule=%s table=%s", fw[2], new_rule.get_table()) # front means insert instead of append cpy = fw[2] if fw[1] == "front": cpy = cpy.replace('-A', '-I') if isinstance(fw[1], int): cpy = cpy.replace( "-A %s" % new_rule.get_chain(), '-I %s %s' % (new_rule.get_chain(), fw[1])) CsHelper.execute("iptables -t %s %s" % (new_rule.get_table(), cpy)) self.del_standard() self.get_unseen()
def process(self): route = CsRoute() for dev in self.dbag: if dev == "id": continue ip = CsIP(dev, self.config) for address in self.dbag[dev]: if(address["nw_type"]!="public"): continue #check if link is up if (not self.check_if_link_exists(dev)): logging.info("link %s does not exist, so not processing"%dev) continue if not self.check_if_link_up(dev): cmd="ip link set %s up"%dev CsHelper.execute(cmd) network = str(address["network"]) ip.setAddress(address) if ip.configured(): logging.info( "Address %s on device %s already configured", ip.ip(), dev) ip.post_configure() else: logging.info( "Address %s on device %s not configured", ip.ip(), dev) if CsDevice(dev, self.config).waitfordevice(): ip.configure() route.add_route(dev, network) # once we start processing public ip's we need to verify there # is a default route and add if needed if not route.defaultroute_exists(): cmdline=self.config.get_cmdline_instance() if(cmdline.get_gateway()): route.add_defaultroute(cmdline.get_gateway())
def find_pid(self): self.pid = [] for i in CsHelper.execute("ps aux"): items = len(self.search) proc = re.split(r"\s+", i)[items*-1:] matches = len([m for m in proc if m in self.search]) if matches == items: self.pid.append(re.split(r"\s+", i)[1]) logging.debug("CsProcess:: Searching for process ==> %s and found PIDs ==> %s", self.search, self.pid) return self.pid
def set_fault(self): """ Set fault mode on this router """ if not self.cl.is_redundant(): logging.error("Set fault called on non-redundant router") return self.set_lock() logging.info("Setting router to fault") interfaces = [ interface for interface in self.address.get_interfaces() if interface.is_public() ] for interface in interfaces: CsHelper.execute("ifconfig %s down" % interface.get_device()) cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF) CsHelper.execute("%s -s" % cmd) CsHelper.service("ipsec", "stop") CsHelper.service("xl2tpd", "stop") CsHelper.service("dnsmasq", "stop") CsHelper.service("radvd", "stop") interfaces = [ interface for interface in self.address.get_interfaces() if interface.needs_vrrp() ] for interface in interfaces: CsPasswdSvc(interface.get_gateway() + "," + interface.get_ip()).stop() self.cl.set_fault_state() self.cl.save() self.release_lock() logging.info("Router switched to fault mode") interfaces = [ interface for interface in self.address.get_interfaces() if interface.is_public() ] CsHelper.reconfigure_interfaces(self.cl, interfaces)
def set_fault(self): """ Set fault mode on this router """ if not self.cl.is_redundant(): logging.error("Set fault called on non-redundant router") return s = self.set_lock() logging.info("Router switched to fault mode") 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_CONF) CsHelper.execute("%s -s" % cmd) CsHelper.service("ipsec", "stop") CsHelper.service("xl2tpd", "stop") CsHelper.service("dnsmasq", "stop") ads = [o for o in self.address.get_ips() if o.needs_vrrp()] for o in ads: pwdsvc = CsPasswdSvc(o.get_gateway()).stop() self.cl.set_fault_state() self.cl.save() logging.info("Router switched to fault mode")
def delete_leases(self): macs_dhcphosts = [] try: logging.info("Attempting to delete entries from dnsmasq.leases file for VMs which are not on dhcphosts file") for host in open(DHCP_HOSTS): macs_dhcphosts.append(host.split(',')[0]) removed = 0 for leaseline in open(LEASES): lease = leaseline.split(' ') mac = lease[1] ip = lease[2] if mac not in macs_dhcphosts: cmd = "dhcp_release $(ip route get %s | grep eth | head -1 | awk '{print $3}') %s %s" % (ip, ip, mac) logging.info(cmd) CsHelper.execute(cmd) removed = removed + 1 self.del_host(ip) logging.info("Deleted %s entries from dnsmasq.leases file" % str(removed)) except Exception as e: logging.error("Caught error while trying to delete entries from dnsmasq.leases file: %s" % e)
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 """ if self.cl.is_master(): logging.error("Set master called on master node") return """ self.set_lock() logging.debug("Setting router to master") ads = [o for o in self.address.get_ips() if o.is_public()] dev = '' for o in ads: if dev == o.get_device(): continue cmd2 = "ip link set %s up" % o.get_device() if CsDevice(o.get_device(), self.config).waitfordevice(): CsHelper.execute(cmd2) dev = o.get_device() logging.info("Bringing public interface %s up" % o.get_device()) else: logging.error("Device %s was not ready could not bring it up" % o.get_device()) # 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 defaultroute_exists(self): """ Return True if a default route is present :return: bool """ logging.info("Checking if default ipv4 route is present") route_found = CsHelper.execute("ip -4 route list 0/0") if len(route_found) > 0: logging.info("Default route found: " + route_found[0]) return True else: logging.warn("No default route found!") return False
def defaultroute_exists(self): """ Return True if a default route is present :return: bool """ logging.info("Checking if default ipv4 route is present") route_found = CsHelper.execute("ip -4 route list 0/0") if len(route_found) > 0: logging.info("Default route found: " + route_found[0]) return True else: logging.warn("No default route found!") return False
def find_pid(self): self.pid = [] items = len(self.search) for i in CsHelper.execute("ps aux"): proc = re.split(r"\s+", i)[10:] matches = len([m for m in proc if m in self.search]) if matches == items: self.pid.append(re.split(r"\s+", i)[1]) logging.debug( "CsProcess:: Searching for process ==> %s and found PIDs ==> %s", self.search, self.pid) return self.pid
def get_all_rules(self): for i in CsHelper.execute("iptables-save"): if i.startswith('*'): # Table self.table.add(i[1:]) if i.startswith(':'): # Chain self.chain.add(self.table.last(), i[1:].split(' ')[0]) if i.startswith('-A'): # Rule self.chain.add_rule(i.split()[1]) rule = CsNetfilter() rule.parse(i) rule.set_table(self.table.last()) rule.set_chain(i.split()[1]) rule.set_count(self.chain.get_count(i.split()[1])) self.save(rule)
def get_all_rules(self): for i in CsHelper.execute("iptables-save"): if i.startswith('*'): # Table self.table.add(i[1:]) if i.startswith(':'): # Chain self.chain.add(self.table.last(), i[1:].split(' ')[0]) if i.startswith('-A'): # Rule self.chain.add_rule(i.split()[1]) rule = CsNetfilter() rule.parse(i) rule.set_table(self.table.last()) rule.set_chain(i.split()[1]) rule.set_count(self.chain.get_count(i.split()[1])) self.save(rule)
def __update(self, vm_ip, password): token = "" try: token_file = open(self.TOKEN_FILE) token = token_file.read() except IOError: logging.debug("File %s does not exist" % self.TOKEN_FILE) logging.debug("Got VM '%s' and password '%s'" % (vm_ip, password)) get_cidrs_cmd = "ip addr show | grep inet | grep -v secondary | awk '{print $2}'" cidrs = CsHelper.execute(get_cidrs_cmd) logging.debug("Found these CIDRs: %s" % cidrs) for cidr in cidrs: logging.debug("Processing CIDR '%s'" % cidr) if CsHelper.IPAddress(vm_ip) in CsHelper.IPNetwork(cidr): ip = cidr.split('/')[0] logging.debug( "Cidr %s matches vm ip address %s so adding passwd to passwd server at %s" % (cidr, vm_ip, ip)) proc = CsProcess(['/opt/cosmic/router/bin/passwd_server_ip.py', ip]) max_tries = 5 test_tries = 0 while test_tries < max_tries: logging.debug("Updating passwd server on %s" % ip) if proc.find(): url = "http://{SERVER_IP}:8080/".format(SERVER_IP=ip) headers = {'DomU_Request': 'save_password'} params = {'ip': vm_ip, 'password': password, 'token': token} req = urllib2.Request(url, urllib.urlencode(params), headers=headers) try: res = urllib2.urlopen(req) if res.getcode() == 200: logging.debug("Update password server result ==> %s" % res.read()) return 0 except Exception as e: logging.debug("Error while querying password server ==> %s" % e.message) return 1 test_tries += 1 logging.debug("Testing password server process round %s/%s" % (test_tries, max_tries)) time.sleep(2) logging.debug("Update password server skipped because we didn't find a passwd server process for " "%s (makes sense on backup routers)" % ip) return 1 # on a non-master router no passwords to set, so we finish with success return 0
def list(self): self.iplist = {} cmd = ("ip addr show dev " + self.dev) for i in CsHelper.execute(cmd): vals = i.lstrip().split() if (vals[0] == 'inet'): cidr = vals[1] for ip, device in self.iplist.iteritems(): logging.info( "Iterating over the existing IPs. CIDR to be configured ==> %s, existing IP ==> %s on device ==> %s", cidr, ip, device) if cidr[0] != ip[0] and device != self.dev: self.iplist[cidr] = self.dev
def list(self): self.iplist = {} cmd = ("ip addr show dev " + self.dev) for i in CsHelper.execute(cmd): vals = i.lstrip().split() if (vals[0] == 'inet'): cidr = vals[1] for ip, device in self.iplist.iteritems(): logging.info( "Iterating over the existing IPs. CIDR to be configured ==> %s, existing IP ==> %s on device ==> %s", cidr, ip, device) if cidr[0] != ip[0] and device != self.dev: self.iplist[cidr] = self.dev
def process(self): for dev in self.dbag: if dev == "id": continue ip = CsIP(dev, self.config) for address in self.dbag[dev]: #check if link is up if not self.check_if_link_up(dev): cmd="ip link set %s up" % dev CsHelper.execute(cmd) ip.setAddress(address) if ip.configured(): logging.info( "Address %s on device %s already configured", ip.ip(), dev) ip.post_configure(address) else: logging.info( "Address %s on device %s not configured", ip.ip(), dev) if CsDevice(dev, self.config).waitfordevice(): ip.configure(address)
def apply_rules(self): s = [] for r in self.iptablerules: r.replace(' ', ' ') # Remove duplicate spaces if r not in s: s.append(r) chains = Tables(s) chains.table_printout() # COMMIT all rules. result = CsHelper.execute("iptables-restore < /tmp/rules.save") if result: logging.info("iptables-restore result: %s", result) else: logging.info("iptables-restore result: success!")
def add_address_route(self, entry): if 'router_guest_ip6' in entry.keys() and entry['router_guest_ip6']: self.enable_ipv6(entry['device']) cidr_size = entry['router_guest_ip6_cidr'].split("/")[-1] full_addr = entry['router_guest_ip6_gateway'] + "/" + cidr_size if not CsHelper.execute("ip -6 addr show dev %s | grep -w %s" % (entry['device'], full_addr)): CsHelper.execute("ip -6 addr add %s dev %s" % (full_addr, entry['device'])) if 'router_ip6' in entry.keys() and entry['router_ip6']: self.__disable_dad(VPC_PUBLIC_INTERFACE) full_public_addr = entry['router_ip6'] + "/" + cidr_size if not CsHelper.execute( "ip -6 addr show dev %s | grep -w %s" % (VPC_PUBLIC_INTERFACE, full_public_addr)): CsHelper.execute("ip -6 addr add %s dev %s" % (full_public_addr, VPC_PUBLIC_INTERFACE)) if not CsHelper.execute("ip -6 route list default via %s" % entry['router_ip6_gateway']): CsHelper.execute("ip -6 route add default via %s" % entry['router_ip6_gateway']) else: return
def add_defaultroute_v6(self, gateway): """ Add a default route # for example, ip -6 route add default via fd80:20:20:20::1 :param str gateway :return: bool """ if not gateway: raise Exception("Gateway cannot be None.") logging.info("Checking if default ipv6 route is present") route_found = CsHelper.execute("ip -6 route list default") if len(route_found) > 0: logging.info("Default IPv6 route found: " + route_found[0]) return False else: cmd = "default via " + gateway logging.info("Adding default IPv6 route") self.set_route_v6(cmd) return True
def _redundant_on(self): guest = self.address.get_guest_if() # No redundancy if there is no guest network if self.cl.is_master() or guest is None: for obj in [o for o in self.address.get_ips() if o.is_public()]: self.check_is_up(obj.get_device()) if guest is None: self._redundant_off() 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, "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(self.KEEPALIVED_CONF) ads = [o for o in self.address.get_ips() if o.is_public()] # Add a comment for each public IP. If any change this will cause keepalived to restart # As things stand keepalived will be configured before the IP is added or deleted i = 0 for o in ads: file.addeq("! %s=%s" % (i, o.get_cidr())) i = i + 1 file.search(" router_id ", " router_id %s" % self.cl.get_name()) file.search(" priority ", " priority %s" % self.cl.get_priority()) file.search(" interface ", " interface %s" % guest.get_device()) file.search(" state ", " state %s" % "EQUAL") file.search(" virtual_router_id ", " virtual_router_id %s" % self.cl.get_router_id()) file.greplace("[RROUTER_BIN_PATH]", self.CS_ROUTER_DIR) file.section("authentication {", "}", [" auth_type AH \n", " auth_pass %s\n" % self.cl.get_router_password()]) file.section("virtual_ipaddress {", "}", self._collect_ips()) file.commit() # conntrackd configuration connt = CsFile(self.CONNTRACKD_CONF) if guest is not None: connt.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"]) connt.section("Address Ignore {", "}", self._collect_ignore_ips()) connt.commit() if connt.is_changed(): CsHelper.service("conntrackd", "restart") if file.is_changed(): CsHelper.service("keepalived", "reload") # 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() proc = CsProcess(['/usr/sbin/keepalived', '--vrrp']) if not proc.find(): CsHelper.service("keepalived", "restart")
def add_chain(self, rule): """ Add the given chain if it is not already present """ if not self.has_chain(rule.get_table(), rule.get_chain()): CsHelper.execute("iptables -t %s -N %s" % (rule.get_table(), rule.get_chain())) self.chain.add(rule.get_table(), rule.get_chain())
def flush(self): CsHelper.execute("ip route flush table %s" % (self.table)) CsHelper.execute("ip route flush cache")
def flush_table(self, tablename): CsHelper.execute("ip route flush table %s" % (tablename)) CsHelper.execute("ip route flush cache")
def findRule(self, rule): for i in CsHelper.execute("ip rule show"): if rule in i.strip(): return True return False
def arpPing(self): if not self.address['gateway'] or self.address['gateway'] == 'None': return cmd = "arping -c 1 -I %s -A -U -s %s %s" % ( self.dev, self.address['public_ip'], self.address['gateway']) CsHelper.execute(cmd, wait=False)
def arpPing(self): cmd = "arping -c 1 -I %s -A -U -s %s %s" % ( self.dev, self.address['public_ip'], self.address['gateway']) CsHelper.execute(cmd)
def post_config_change(self, method): route = CsRoute() tableName = "Table_" + self.dev if method == "add": if not self.config.is_vpc(): if self.get_type() in ["public"]: route.set_route( "table %s throw %s proto static" % (tableName, self.config.address().dbag['eth0'][0]['network'])) route.set_route( "table %s throw %s proto static" % (tableName, self.config.address().dbag['eth1'][0]['network'])) # add 'default via gateway' rule in the device specific routing table if "gateway" in self.address and self.address[ "gateway"] and self.address["gateway"] != "None": route.add_route(self.dev, self.address["gateway"]) if "network" in self.address and self.address["network"]: route.add_network_route(self.dev, str(self.address["network"])) if self.get_type() in ["public"]: CsRule(self.dev).addRule("from " + str(self.address["network"])) if self.config.is_vpc(): if self.get_type() in [ "public" ] and "gateway" in self.address and self.address[ "gateway"] and self.address["gateway"] != "None": route.add_route(self.dev, self.address["gateway"]) for inf, addresses in self.config.address().dbag.iteritems( ): if not inf.startswith("eth"): continue for address in addresses: if "nw_type" in address and address[ "nw_type"] == "guest": route.add_network_route( self.dev, str(address["network"])) route.add_network_route(self.dev, str(self.address["network"])) CsHelper.execute("sudo ip route flush cache") elif method == "delete": # treat the last IP to be dis-associated with interface as special case to clean up the routing rules if self.get_type() in [ "public" ] and (not self.config.is_vpc()) and (len(self.iplist) == 0): CsHelper.execute("sudo ip rule delete table " + tableName) CsHelper.execute("sudo ip route flush table " + tableName) CsHelper.execute("sudo ip route flush cache") CsRule(self.dev).delMark() self.fw_router() self.fw_vpcrouter() cmdline = self.config.cmdline() # On deletion nw_type will no longer be known if self.get_type() in ('guest'): if self.config.is_vpc() or self.config.is_router(): CsDevice(self.dev, self.config).configure_rp() logging.error( "Not able to setup source-nat for a regular router yet") if (self.config.has_dns() or self.config.is_dhcp()) and self.config.expose_dns(): logging.info("Making dns publicly available") dns = CsDnsmasq(self) dns.add_firewall_rules() else: logging.info("Not making dns publicly available") if self.config.has_metadata(): app = CsApache(self) app.setup() # If redundant then this is dealt with # by the primary backup functions if not cmdline.is_redundant(): if method == "add": CsPasswdSvc(self.address['public_ip']).start() elif method == "delete": CsPasswdSvc(self.address['public_ip']).stop() elif cmdline.is_primary(): if method == "add": CsPasswdSvc(self.get_gateway() + "," + self.address['public_ip']).start() elif method == "delete": CsPasswdSvc(self.get_gateway() + "," + self.address['public_ip']).stop() if self.get_type() == "public" and self.config.is_vpc( ) and method == "add": if self.address["source_nat"]: vpccidr = cmdline.get_vpccidr() self.fw.append([ "filter", 3, "-A FORWARD -s %s ! -d %s -j ACCEPT" % (vpccidr, vpccidr) ]) self.fw.append([ "nat", "", "-A POSTROUTING -j SNAT -o %s --to-source %s" % (self.dev, self.address['public_ip']) ])
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")
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")