CLOUDSTACK-9287 - Refactor the interface state configuration

- This also refactors the CsAddress in order to offer better readability in a couple of methods.
This commit is contained in:
Wilder Rodrigues 2016-02-17 07:31:39 +01:00 committed by Remi Bergsma
parent 850fb1a557
commit c41edc1fe6
4 changed files with 99 additions and 98 deletions

View File

@ -731,34 +731,34 @@ class CsForwardingRules(CsDataBag):
#return the VR guest interface ip
def getGuestIp(self):
ipr = []
interfaces = []
ipAddr = None
for ip in self.config.address().get_ips():
if ip.is_guest():
ipr.append(ip)
if len(ipr) > 0:
ipAddr = sorted(ipr)[-1]
for interface in self.config.address().get_interfaces():
if interface.is_guest():
interfaces.append(interface)
if len(interfaces) > 0:
ipAddr = sorted(interfaces)[-1]
if ipAddr:
return ipAddr.get_ip()
return None
def getDeviceByIp(self, ipa):
for ip in self.config.address().get_ips():
if ip.ip_in_subnet(ipa):
return ip.get_device()
for interface in self.config.address().get_interfaces():
if interface.ip_in_subnet(ipa):
return interface.get_device()
return None
def getNetworkByIp(self, ipa):
for ip in self.config.address().get_ips():
if ip.ip_in_subnet(ipa):
return ip.get_network()
for interface in self.config.address().get_interfaces():
if interface.ip_in_subnet(ipa):
return interface.get_network()
return None
def getGatewayByIp(self, ipa):
for ip in self.config.address().get_ips():
if ip.ip_in_subnet(ipa):
return ip.get_gateway()
for interface in self.config.address().get_interfaces():
if interface.ip_in_subnet(ipa):
return interface.get_gateway()
return None
def portsToString(self, ports, delimiter):

View File

@ -28,7 +28,6 @@ from CsRoute import CsRoute
from CsRule import CsRule
VRRP_TYPES = ['guest']
PUBLIC_INTERFACE = ['eth1']
class CsAddress(CsDataBag):
@ -37,14 +36,14 @@ class CsAddress(CsDataBag):
ip = CsIP(dev, self.config)
ip.compare(self.dbag)
def get_ips(self):
ret = []
def get_interfaces(self):
interfaces = []
for dev in self.dbag:
if dev == "id":
continue
for ip in self.dbag[dev]:
ret.append(CsInterface(ip, self.config))
return ret
interfaces.append(CsInterface(ip, self.config))
return interfaces
def get_guest_if(self):
"""
@ -52,13 +51,13 @@ class CsAddress(CsDataBag):
"""
guest_interface = None
lowest_device = 1000
for ip in self.get_ips():
if ip.is_guest() and ip.is_added():
device = ip.get_device()
for interface in self.get_interfaces():
if interface.is_guest() and interface.is_added():
device = interface.get_device()
device_suffix = int(''.join([digit for digit in device if digit.isdigit()]))
if device_suffix < lowest_device:
lowest_device = device_suffix
guest_interface = ip
guest_interface = interface
logging.debug("Guest interface will be set on device '%s' and IP '%s'" % (guest_interface.get_device(), guest_interface.get_ip()))
return guest_interface
@ -94,9 +93,9 @@ class CsAddress(CsDataBag):
"""
Return the address object that has the control interface
"""
for ip in self.get_ips():
if ip.is_control():
return ip
for interface in self.get_interfaces():
if interface.is_control():
return interface
return None
def process(self):
@ -290,24 +289,27 @@ class CsIP:
route = CsRoute()
if not self.get_type() in ["control"]:
route.add_table(self.dev)
CsRule(self.dev).addMark()
self.check_is_up()
interfaces = [CsInterface(address, self.config)]
CsHelper.reconfigure_interfaces(self.cl, interfaces)
self.set_mark()
self.arpPing()
CsRpsrfs(self.dev).enable()
self.post_config_change("add")
'''For isolated/redundant and dhcpsrvr routers, call this method after the post_config is complete '''
if not self.config.is_vpc():
self.setup_router_control()
if self.config.is_vpc() or self.cl.is_redundant():
# 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 self.get_type() in ["public"] and address["device"] in PUBLIC_INTERFACE:
if self.get_type() in ["public"] and address["device"] == CsHelper.PUBLIC_INTERFACES[self.cl.get_type()]:
gateway = str(address["gateway"])
route.add_defaultroute(gateway)
else:
@ -316,29 +318,6 @@ class CsIP:
if(self.cl.get_gateway()):
route.add_defaultroute(self.cl.get_gateway())
def check_is_up(self):
""" Ensure device is up """
state_commands = {"router" : "ip addr | grep eth0 | grep inet | wc -l | xargs bash -c 'if [ $0 == 2 ]; then echo \"MASTER\"; else echo \"BACKUP\"; fi'",
"vpcrouter" : "ip addr | grep eth1 | grep state | awk '{print $9;}' | xargs bash -c 'if [ $0 == \"UP\" ]; then echo \"MASTER\"; else echo \"BACKUP\"; fi'"}
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 self.is_public():
state_cmd = state_commands[self.cl.get_type()]
logging.info("Check state command => %s" % state_cmd)
state = CsHelper.execute(state_cmd)[0]
logging.info("Route state => %s" % state)
if self.getDevice() not in PUBLIC_INTERFACE and state == "MASTER":
CsHelper.execute(cmd2)
else:
CsHelper.execute(cmd2)
def set_mark(self):
cmd = "-A PREROUTING -i %s -m state --state NEW -j CONNMARK --set-xmark %s/0xffffffff" % \
(self.getDevice(), self.dnum)
@ -365,12 +344,12 @@ class CsIP:
def setup_router_control(self):
if self.config.is_vpc():
return
self.fw.append(
["filter", "", "-A FW_OUTBOUND -m state --state RELATED,ESTABLISHED -j ACCEPT"])
self.fw.append(
["filter", "", "-A INPUT -i eth1 -p tcp -m tcp --dport 3922 -m state --state NEW,ESTABLISHED -j ACCEPT"])
self.fw.append(["filter", "", "-P INPUT DROP"])
self.fw.append(["filter", "", "-P FORWARD DROP"])

View File

@ -27,6 +27,30 @@ import shutil
from netaddr import *
from pprint import pprint
PUBLIC_INTERFACES = {"router" : "eth0", "vpcrouter" : "eth1"}
STATE_COMMANDS = {"router" : "ip addr | grep eth0 | grep inet | wc -l | xargs bash -c 'if [ $0 == 2 ]; then echo \"MASTER\"; else echo \"BACKUP\"; fi'",
"vpcrouter" : "ip addr | grep eth1 | grep state | awk '{print $9;}' | xargs bash -c 'if [ $0 == \"UP\" ]; then echo \"MASTER\"; else echo \"BACKUP\"; fi'"}
def reconfigure_interfaces(router_config, interfaces):
for interface in interfaces:
cmd = "ip link show %s | grep 'state DOWN'" % interface.get_device()
for device in execute(cmd):
if " DOWN " in device:
cmd = "ip link set %s up" % interface.get_device()
# 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 router_config.is_redundant() and interface.is_public():
state_cmd = STATE_COMMANDS[router_config.get_type()]
logging.info("Check state command => %s" % state_cmd)
state = execute(state_cmd)[0]
logging.info("Route state => %s" % state)
if interface.get_device() != PUBLIC_INTERFACES[router_config.get_type()] and state == "MASTER":
execute(cmd)
else:
execute(cmd)
def is_mounted(name):
for i in execute("mount"):

View File

@ -41,8 +41,6 @@ from CsRoute import CsRoute
import socket
from time import sleep
PUBLIC_INTERFACE = ['eth0', 'eth1']
class CsRedundant(object):
CS_RAMDISK_DIR = "/ramdisk"
@ -89,7 +87,7 @@ class CsRedundant(object):
self._redundant_off()
return
interfaces = [interface for interface in self.address.get_ips() if interface.is_guest()]
interfaces = [interface for interface in self.address.get_interfaces() if interface.is_guest()]
isDeviceReady = False
dev = ''
for interface in interfaces:
@ -229,9 +227,9 @@ class CsRedundant(object):
self.set_lock()
logging.info("Router switched to fault mode")
ips = [ip for ip in self.address.get_ips() if ip.is_public() and ip.get_device() in PUBLIC_INTERFACE]
for ip in ips:
CsHelper.execute("ifconfig %s down" % ip.get_device())
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)
@ -239,15 +237,18 @@ class CsRedundant(object):
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()
interfaces = [interface for interface in self.address.get_interfaces() if interface.needs_vrrp()]
for interface in interfaces:
CsPasswdSvc(interface.get_gateway()).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_backup(self):
""" Set the current router to backup """
if not self.cl.is_redundant():
@ -258,28 +259,31 @@ class CsRedundant(object):
logging.debug("Setting router to backup")
dev = ''
ips = [ip for ip in self.address.get_ips() if ip.is_public() and ip.get_device() in PUBLIC_INTERFACE]
for ip in ips:
if dev == ip.get_device():
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" % ip.get_device())
cmd2 = "ip link set %s down" % ip.get_device()
logging.info("Bringing public interface %s down" % interface.get_device())
cmd2 = "ip link set %s down" % interface.get_device()
CsHelper.execute(cmd2)
dev = ip.get_device()
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")
ips = [ip for ip in self.address.get_ips() if ip.needs_vrrp()]
for ip in ips:
CsPasswdSvc(ip.get_gateway()).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 set_master(self):
@ -292,12 +296,12 @@ class CsRedundant(object):
logging.debug("Setting router to master")
dev = ''
ips = [ip for ip in self.address.get_ips() if ip.is_public()]
interfaces = [interface for interface in self.address.get_interfaces() if interface.is_public()]
route = CsRoute()
for ip in ips:
if dev == ip.get_device():
for interface in interfaces:
if dev == interface.get_device():
continue
dev = ip.get_device()
dev = interface.get_device()
logging.info("Will proceed configuring device ==> %s" % dev)
cmd2 = "ip link set %s up" % dev
if CsDevice(dev, self.config).waitfordevice():
@ -305,9 +309,9 @@ class CsRedundant(object):
logging.info("Bringing public interface %s up" % dev)
try:
gateway = ip.get_gateway()
gateway = interface.get_gateway()
logging.info("Adding gateway ==> %s to device ==> %s" % (gateway, dev))
if ip.get_device() in PUBLIC_INTERFACE:
if dev == CsHelper.PUBLIC_INTERFACES[self.cl.get_type()]:
route.add_defaultroute(gateway)
except:
logging.error("ERROR getting gateway from device %s" % dev)
@ -322,14 +326,17 @@ class CsRedundant(object):
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()
interfaces = [interface for interface in self.address.get_interfaces() if interface.needs_vrrp()]
for interface in interfaces:
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 _collect_ignore_ips(self):
@ -355,23 +362,14 @@ class CsRedundant(object):
that could function as a router and VPC router at the same time
"""
lines = []
for ip in self.address.get_ips():
if ip.needs_vrrp():
for interface in self.address.get_interfaces():
if interface.needs_vrrp():
cmdline=self.config.get_cmdline_instance()
if not ip.is_added():
if not interface.is_added():
continue
if(cmdline.get_type()=='router'):
str = " %s brd %s dev %s\n" % (cmdline.get_guest_gw(), ip.get_broadcast(), ip.get_device())
str = " %s brd %s dev %s\n" % (cmdline.get_guest_gw(), interface.get_broadcast(), interface.get_device())
else:
str = " %s brd %s dev %s\n" % (ip.get_gateway_cidr(), ip.get_broadcast(), ip.get_device())
str = " %s brd %s dev %s\n" % (interface.get_gateway_cidr(), interface.get_broadcast(), interface.get_device())
lines.append(str)
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)