mirror of https://github.com/apache/cloudstack.git
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:
parent
850fb1a557
commit
c41edc1fe6
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
|
||||
|
|
|
|||
|
|
@ -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"):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue