You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2019/05/31 07:05:49 UTC

[cloudstack] branch 4.11 updated: systemvm: fix VR issues with Multiple Public Subnets (#3361)

This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch 4.11
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.11 by this push:
     new 2f268fb  systemvm: fix VR issues with Multiple Public Subnets (#3361)
2f268fb is described below

commit 2f268fbb52203cae96d0cff57c189600abab1390
Author: Richard Lawley <ri...@richardlawley.com>
AuthorDate: Fri May 31 08:05:42 2019 +0100

    systemvm: fix VR issues with Multiple Public Subnets (#3361)
    
    This PR resolves 2 issues related to Virtual Routers with multiple public interfaces, and works around a third.
    
    - Fixes #3353 - Adds missing throw routes for eth0/eth1 to eth3+ when there are >1 public IPs
    - Fixes #3168 - Incorrect marks set on some static NAT rules (some code references were changed from hex(int(interfacenum)) to hex(100 + int(interfacenum)) - this change just adds the remaining ones
    - Fixes #3352 - Work around that sends Gratuitous ARP messages when a HA VR becomes master to work around the problem of the MAC address being different between HA VRs. If that issue is fixed properly (i.e. a database entry for the subsequent interfaces so they can be static) then this is unnecessary, though should not cause any problems.
---
 systemvm/debian/opt/cloud/bin/configure.py      |  4 ++--
 systemvm/debian/opt/cloud/bin/cs/CsAddress.py   | 11 +++++-----
 systemvm/debian/opt/cloud/bin/cs/CsRedundant.py | 27 +++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py
index 253eb7c..4df9911 100755
--- a/systemvm/debian/opt/cloud/bin/configure.py
+++ b/systemvm/debian/opt/cloud/bin/configure.py
@@ -858,7 +858,7 @@ class CsForwardingRules(CsDataBag):
                 rule['protocol'],
                 rule['protocol'],
                 public_fwports,
-                hex(int(public_fwinterface[3:]))
+                hex(100 + int(public_fwinterface[3:]))
               )
         fw6 = "-A PREROUTING -d %s/32 -i %s -p %s -m %s --dport %s -m state --state NEW -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff" % \
               (
@@ -927,7 +927,7 @@ class CsForwardingRules(CsDataBag):
                         rule["internal_ip"]])
         self.fw.append(["mangle", "",
                         "-I PREROUTING -s %s/32 -m state --state NEW -j MARK --set-xmark %s/0xffffffff" %
-                        (rule["internal_ip"], hex(int(device[len("eth"):])))])
+                        (rule["internal_ip"], hex(100 + int(device[len("eth"):])))])
         self.fw.append(["nat", "front",
                         "-A PREROUTING -d %s/32 -j DNAT --to-destination %s" % (rule["public_ip"], rule["internal_ip"])])
         self.fw.append(["nat", "front",
diff --git a/systemvm/debian/opt/cloud/bin/cs/CsAddress.py b/systemvm/debian/opt/cloud/bin/cs/CsAddress.py
index ab0cee6..8e67825 100755
--- a/systemvm/debian/opt/cloud/bin/cs/CsAddress.py
+++ b/systemvm/debian/opt/cloud/bin/cs/CsAddress.py
@@ -258,7 +258,7 @@ class CsIP:
 
     def __init__(self, dev, config):
         self.dev = dev
-        self.dnum = hex(int(dev[3:]))
+        self.dnum = hex(100 + int(dev[3:]))
         self.iplist = {}
         self.address = {}
         self.list()
@@ -518,12 +518,11 @@ class CsIP:
 
         if method == "add":
             if not self.config.is_vpc():
-                # treat the first IP on a interface as special case to set up the routing rules
-                if self.get_type() in ["public"] and (len(self.iplist) == 1):
-                    CsHelper.execute("sudo ip route add throw " + self.config.address().dbag['eth0'][0]['network'] + " table " + tableName + " proto static")
-                    CsHelper.execute("sudo ip route add throw " + self.config.address().dbag['eth1'][0]['network'] + " table " + tableName + " proto static")
+                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 'defaul via gateway' rule in the device specific routing table
+                # 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"]:
diff --git a/systemvm/debian/opt/cloud/bin/cs/CsRedundant.py b/systemvm/debian/opt/cloud/bin/cs/CsRedundant.py
index 3ade4a2..25a4a1a 100755
--- a/systemvm/debian/opt/cloud/bin/cs/CsRedundant.py
+++ b/systemvm/debian/opt/cloud/bin/cs/CsRedundant.py
@@ -351,6 +351,33 @@ class CsRedundant(object):
 
         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 he 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 master mode")
 
     def _collect_ignore_ips(self):