You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by pe...@apache.org on 2024/03/05 02:09:48 UTC

(cloudstack) 04/06: NSX: Fix DNS resolver for guest NSX networks (#23)

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

pearl11594 pushed a commit to branch nsx-additional-fixes
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 059d20f573be9f28aa6163f6c844e71d971636df
Author: Pearl Dsilva <pe...@gmail.com>
AuthorDate: Mon Feb 26 10:25:43 2024 -0500

    NSX: Fix DNS resolver for guest NSX networks (#23)
    
    * vpc: create vpc tiers with dns server of vpc instead of zone
    
    with this change
    ```
    root@r-575-VM:~# cat /etc/dnsmasq.d/cloud.conf
    dhcp-hostsfile=/etc/dhcphosts.txt
    listen-address=127.0.0.1,172.17.1.1,172.17.2.1,172.17.3.1
    dhcp-range=set:interface-eth2-0,172.17.1.1,static
    dhcp-option=tag:interface-eth2-0,15,cs2cloud.internal
    dhcp-option=tag:interface-eth2-0,6,172.17.1.1,10.0.32.1,8.8.8.8
    dhcp-option=tag:interface-eth2-0,3,172.17.1.1
    dhcp-option=eth2,26,1500
    dhcp-option=tag:interface-eth2-0,1,255.255.255.0
    dhcp-range=set:interface-eth3-1,172.17.2.1,static
    dhcp-option=tag:interface-eth3-1,15,cs2cloud.internal
    dhcp-option=tag:interface-eth3-1,6,172.17.2.1,8.8.8.8,1.1.1.1
    dhcp-option=tag:interface-eth3-1,3,172.17.2.1
    dhcp-option=eth3,26,1500
    dhcp-option=tag:interface-eth3-1,1,255.255.255.0
    dhcp-range=set:interface-eth4-2,172.17.3.1,static
    dhcp-option=tag:interface-eth4-2,15,cs2cloud.internal
    dhcp-option=tag:interface-eth4-2,6,172.17.3.1,8.8.8.8,1.1.1.1
    dhcp-option=tag:interface-eth4-2,3,172.17.3.1
    dhcp-option=eth4,26,1500
    dhcp-option=tag:interface-eth4-2,1,255.255.255.0
    root@r-575-VM:~#
    ```
    
    * NSX: Fix DNS resolver for guest NSX networks
    
    * rename variable
    
    ---------
    
    Co-authored-by: Wei Zhou <we...@apache.org>
---
 .../cloud/agent/api/SetupGuestNetworkCommand.java  |  9 +++
 .../facade/SetGuestNetworkConfigItem.java          |  1 +
 .../virtualnetwork/model/GuestNetwork.java         |  9 +++
 .../java/com/cloud/network/NetworkModelImpl.java   | 16 +++++
 .../cloud/network/router/CommandSetupHelper.java   |  3 +-
 .../com/cloud/network/NetworkModelImplTest.java    | 84 +++++++++++++++-------
 systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py |  2 +-
 7 files changed, 96 insertions(+), 28 deletions(-)

diff --git a/core/src/main/java/com/cloud/agent/api/SetupGuestNetworkCommand.java b/core/src/main/java/com/cloud/agent/api/SetupGuestNetworkCommand.java
index e9781993239..06583f2d0d3 100644
--- a/core/src/main/java/com/cloud/agent/api/SetupGuestNetworkCommand.java
+++ b/core/src/main/java/com/cloud/agent/api/SetupGuestNetworkCommand.java
@@ -35,6 +35,7 @@ public class SetupGuestNetworkCommand extends NetworkElementCommand {
     String routerIpv6 = null;
     String routerIpv6Gateway = null;
     String routerIpv6Cidr = null;
+    boolean isVrGuestGateway = false;
 
     public NicTO getNic() {
         return nic;
@@ -114,4 +115,12 @@ public class SetupGuestNetworkCommand extends NetworkElementCommand {
     public void setDefaultIp6Dns2(String defaultIp6Dns2) {
         this.defaultIp6Dns2 = defaultIp6Dns2;
     }
+
+    public boolean isVrGuestGateway() {
+        return isVrGuestGateway;
+    }
+
+    public void setVrGuestGateway(boolean vrGuestGateway) {
+        isVrGuestGateway = vrGuestGateway;
+    }
 }
diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetGuestNetworkConfigItem.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetGuestNetworkConfigItem.java
index aee1e779571..1a6824ceb7f 100644
--- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetGuestNetworkConfigItem.java
+++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetGuestNetworkConfigItem.java
@@ -75,6 +75,7 @@ public class SetGuestNetworkConfigItem extends AbstractConfigItemFacade {
         guestNetwork.setRouterIp6(command.getRouterIpv6());
         guestNetwork.setRouterIp6Gateway(command.getRouterIpv6Gateway());
         guestNetwork.setRouterIp6Cidr(command.getRouterIpv6Cidr());
+        guestNetwork.setVrGuestGateway(command.isVrGuestGateway());
 
         return generateConfigItems(guestNetwork);
     }
diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/GuestNetwork.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/GuestNetwork.java
index bb5e443c2e8..a416b4bc5e4 100644
--- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/GuestNetwork.java
+++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/GuestNetwork.java
@@ -37,6 +37,7 @@ public class GuestNetwork extends ConfigBase {
     private String routerIp6;
     private String routerIp6Gateway;
     private String routerIp6Cidr;
+    private boolean isVrGuestGateway;
 
     private Integer mtu;
 
@@ -202,4 +203,12 @@ public class GuestNetwork extends ConfigBase {
     public Integer getMtu() {
         return mtu;
     }
+
+    public boolean isVrGuestGateway() {
+        return isVrGuestGateway;
+    }
+
+    public void setVrGuestGateway(boolean vrGuestGateway) {
+        isVrGuestGateway = vrGuestGateway;
+    }
 }
diff --git a/server/src/main/java/com/cloud/network/NetworkModelImpl.java b/server/src/main/java/com/cloud/network/NetworkModelImpl.java
index 407264e86aa..07e471c377f 100644
--- a/server/src/main/java/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkModelImpl.java
@@ -101,8 +101,10 @@ import com.cloud.network.router.VirtualRouter;
 import com.cloud.network.rules.FirewallRule.Purpose;
 import com.cloud.network.rules.FirewallRuleVO;
 import com.cloud.network.rules.dao.PortForwardingRulesDao;
+import com.cloud.network.vpc.Vpc;
 import com.cloud.network.vpc.VpcGatewayVO;
 import com.cloud.network.vpc.dao.PrivateIpDao;
+import com.cloud.network.vpc.dao.VpcDao;
 import com.cloud.network.vpc.dao.VpcGatewayDao;
 import com.cloud.offering.NetworkOffering;
 import com.cloud.offering.NetworkOffering.Detail;
@@ -178,6 +180,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
     ProjectDao projectDao;
     @Inject
     NetworkPermissionDao _networkPermissionDao;
+    @Inject
+    VpcDao vpcDao;
 
     private List<NetworkElement> networkElements;
 
@@ -2713,6 +2717,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
         if (StringUtils.isNotBlank(network.getDns1())) {
             return new Pair<>(network.getDns1(), network.getDns2());
         }
+        if (network.getVpcId() != null) {
+            Vpc vpc = vpcDao.findById(network.getVpcId());
+            if (vpc != null && StringUtils.isNotBlank(vpc.getIp4Dns1())) {
+                return new Pair<>(vpc.getIp4Dns1(), vpc.getIp4Dns2());
+            }
+        }
         return new Pair<>(zone.getDns1(), zone.getDns2());
     }
 
@@ -2721,6 +2731,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
         if (StringUtils.isNotBlank(network.getIp6Dns1())) {
             return new Pair<>(network.getIp6Dns1(), network.getIp6Dns2());
         }
+        if (network.getVpcId() != null) {
+            Vpc vpc = vpcDao.findById(network.getVpcId());
+            if (vpc != null && StringUtils.isNotBlank(vpc.getIp6Dns1())) {
+                return new Pair<>(vpc.getIp6Dns1(), vpc.getIp6Dns2());
+            }
+        }
         return new Pair<>(zone.getIp6Dns1(), zone.getIp6Dns2());
     }
 
diff --git a/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java b/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java
index 677707ea729..ce5024a5e1b 100644
--- a/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java
+++ b/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java
@@ -1160,7 +1160,7 @@ public class CommandSetupHelper {
 
     public SetupGuestNetworkCommand createSetupGuestNetworkCommand(final DomainRouterVO router, final boolean add, final NicProfile guestNic) {
         final Network network = _networkModel.getNetwork(guestNic.getNetworkId());
-
+        final NetworkOfferingVO networkOfferingVO = _networkOfferingDao.findById(network.getNetworkOfferingId());
         String defaultDns1 = null;
         String defaultDns2 = null;
         String defaultIp6Dns1 = null;
@@ -1197,6 +1197,7 @@ public class CommandSetupHelper {
         final SetupGuestNetworkCommand setupCmd = new SetupGuestNetworkCommand(dhcpRange, networkDomain, router.getIsRedundantRouter(), defaultDns1, defaultDns2, add, _itMgr.toNicTO(nicProfile,
                 router.getHypervisorType()));
 
+        setupCmd.setVrGuestGateway(networkOfferingVO.isForNsx());
         NicVO publicNic = _nicDao.findDefaultNicForVM(router.getId());
         if (publicNic != null) {
             updateSetupGuestNetworkCommandIpv6(setupCmd, network, publicNic, defaultIp6Dns1, defaultIp6Dns2);
diff --git a/server/src/test/java/com/cloud/network/NetworkModelImplTest.java b/server/src/test/java/com/cloud/network/NetworkModelImplTest.java
index 0f15abcae77..41adb65fb80 100644
--- a/server/src/test/java/com/cloud/network/NetworkModelImplTest.java
+++ b/server/src/test/java/com/cloud/network/NetworkModelImplTest.java
@@ -28,13 +28,19 @@ import com.cloud.network.element.NetworkElement;
 import com.cloud.network.element.VpcVirtualRouterElement;
 import com.cloud.offerings.NetworkOfferingVO;
 import com.cloud.offerings.dao.NetworkOfferingDao;
+import com.cloud.network.vpc.VpcVO;
+import com.cloud.network.vpc.dao.VpcDao;
 import com.cloud.utils.Pair;
 import com.cloud.utils.net.Ip;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+
 import org.mockito.ArgumentMatchers;
+import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
+import org.mockito.Matchers;
+import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.springframework.test.util.ReflectionTestUtils;
 
@@ -44,12 +50,17 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import org.mockito.junit.MockitoJUnitRunner;
 
+@RunWith(MockitoJUnitRunner.class)
 public class NetworkModelImplTest {
-    final String[] ip4Dns1 = {"5.5.5.5", "6.6.6.6"};
-    final String[] ip4Dns2 = {"7.7.7.7", "8.8.8.8"};
-    final String[] ip6Dns1 = {"2001:4860:4860::5555", "2001:4860:4860::6666"};
-    final String[] ip6Dns2 = {"2001:4860:4860::7777", "2001:4860:4860::8888"};
+    final String[] ip4Dns1 = {"5.5.5.5", "6.6.6.6", "9.9.9.9"};
+    final String[] ip4Dns2 = {"7.7.7.7", "8.8.8.8", "10.10.10.10"};
+    final String[] ip6Dns1 = {"2001:4860:4860::5555", "2001:4860:4860::6666", "2001:4860:4860::9999"};
+    final String[] ip6Dns2 = {"2001:4860:4860::7777", "2001:4860:4860::8888", "2001:4860:4860::AAAA"};
+
+    @Mock
+    private VpcDao vpcDao;
 
     @InjectMocks
     private NetworkModelImpl networkModel = new NetworkModelImpl();
@@ -63,18 +74,24 @@ public class NetworkModelImplTest {
         networkModel._networkOfferingDao = networkOfferingDao;
         networkModel._ntwkSrvcDao = networkServiceMapDao;
     }
-    private void prepareMocks(boolean isIp6, Network network, DataCenter zone,
-                              String dns1, String dns2, String dns3, String dns4) {
+
+    private void prepareMocks(boolean isIp6, Network network, DataCenter zone, VpcVO vpc,
+                              String networkDns1, String zoneDns1, String networkDns2, String zoneDns2,
+                              String vpcDns1, String vpcDns2) {
         if (isIp6) {
-            Mockito.when(network.getIp6Dns1()).thenReturn(dns1);
-            Mockito.when(zone.getIp6Dns1()).thenReturn(dns2);
-            Mockito.when(network.getIp6Dns2()).thenReturn(dns3);
-            Mockito.when(zone.getIp6Dns2()).thenReturn(dns4);
+            Mockito.when(network.getIp6Dns1()).thenReturn(networkDns1);
+            Mockito.when(zone.getIp6Dns1()).thenReturn(zoneDns1);
+            Mockito.when(network.getIp6Dns2()).thenReturn(networkDns2);
+            Mockito.when(zone.getIp6Dns2()).thenReturn(zoneDns2);
+            Mockito.when(vpc.getIp6Dns1()).thenReturn(vpcDns1);
+            Mockito.when(vpc.getIp6Dns2()).thenReturn(vpcDns2);
         } else {
-            Mockito.when(network.getDns1()).thenReturn(dns1);
-            Mockito.when(zone.getDns1()).thenReturn(dns2);
-            Mockito.when(network.getDns2()).thenReturn(dns3);
-            Mockito.when(zone.getDns2()).thenReturn(dns4);
+            Mockito.when(network.getDns1()).thenReturn(networkDns1);
+            Mockito.when(zone.getDns1()).thenReturn(zoneDns1);
+            Mockito.when(network.getDns2()).thenReturn(networkDns2);
+            Mockito.when(zone.getDns2()).thenReturn(zoneDns2);
+            Mockito.when(vpc.getIp4Dns1()).thenReturn(vpcDns1);
+            Mockito.when(vpc.getIp4Dns2()).thenReturn(vpcDns2);
         }
     }
 
@@ -83,38 +100,53 @@ public class NetworkModelImplTest {
         String[] dns2 = isIp6 ? ip6Dns2 : ip4Dns2;
         Network network = Mockito.mock(Network.class);
         DataCenter zone = Mockito.mock(DataCenter.class);
-        // Both network and zone have valid dns
-        prepareMocks(isIp6, network, zone, dns1[0], dns1[1], dns2[0], dns1[1]);
+        VpcVO vpc = Mockito.mock(VpcVO.class);
+        Mockito.when(network.getVpcId()).thenReturn(1L);
+        Mockito.doReturn(vpc).when(vpcDao).findById(Matchers.anyLong());
+        // network, vpc and zone have valid dns
+        prepareMocks(isIp6, network, zone, vpc, dns1[0], dns1[1], dns2[0], dns2[1], dns1[2], dns2[2]);
         Pair<String, String> result = isIp6 ? networkModel.getNetworkIp6Dns(network, zone) :
                 networkModel.getNetworkIp4Dns(network, zone);
         Assert.assertEquals(dns1[0], result.first());
         Assert.assertEquals(dns2[0], result.second());
-        // Network has valid dns and zone don't
-        prepareMocks(isIp6, network, zone, dns1[0], null, dns2[0], null);
+        // Network has valid dns and vpc/zone don't
+        prepareMocks(isIp6, network, zone, vpc, dns1[0], null, dns2[0], null, null, null);
         result = isIp6 ? networkModel.getNetworkIp6Dns(network, zone) :
                 networkModel.getNetworkIp4Dns(network, zone);
         Assert.assertEquals(dns1[0], result.first());
         Assert.assertEquals(dns2[0], result.second());
-        // Zone has a valid dns and network don't
-        prepareMocks(isIp6, network, zone, null, dns1[1],  null, dns2[1]);
+        // Vpc has valid dns and network/zone don't
+        prepareMocks(isIp6, network, zone, vpc, null, null, null, null, dns1[2], dns2[2]);
+        result = isIp6 ? networkModel.getNetworkIp6Dns(network, zone) :
+                networkModel.getNetworkIp4Dns(network, zone);
+        Assert.assertEquals(dns1[2], result.first());
+        Assert.assertEquals(dns2[2], result.second());
+        // Zone has a valid dns and network/vpc don't
+        prepareMocks(isIp6, network, zone, vpc, null, dns1[1],  null, dns2[1], null, null);
         result = isIp6 ? networkModel.getNetworkIp6Dns(network, zone) :
                 networkModel.getNetworkIp4Dns(network, zone);
         Assert.assertEquals(dns1[1], result.first());
         Assert.assertEquals(dns2[1], result.second());
-        // Zone has a valid dns and network has only first dns
-        prepareMocks(isIp6, network, zone, dns1[0], dns1[1],  null, dns2[1]);
+        // Zone/vpc has a valid dns and network has only first dns
+        prepareMocks(isIp6, network, zone, vpc, dns1[0], dns1[1],  null, dns2[1], dns1[2], dns2[2]);
         result = isIp6 ? networkModel.getNetworkIp6Dns(network, zone) :
                 networkModel.getNetworkIp4Dns(network, zone);
         Assert.assertEquals(dns1[0], result.first());
         Assert.assertNull(result.second());
-        // Both network and zone only have the first dns
-        prepareMocks(isIp6, network, zone, dns1[0], dns1[1],  null, null);
+        // network don't have a valid dns, vpc has only first dns, Zone has a valid dns
+        prepareMocks(isIp6, network, zone, vpc, null, dns1[1], null, dns2[1], dns1[2], null);
+        result = isIp6 ? networkModel.getNetworkIp6Dns(network, zone) :
+                networkModel.getNetworkIp4Dns(network, zone);
+        Assert.assertEquals(dns1[2], result.first());
+        Assert.assertNull(result.second());
+        // network/vpc/zone only have the first dns
+        prepareMocks(isIp6, network, zone, vpc, dns1[0], dns1[1],  null, null, dns1[2], null);
         result = isIp6 ? networkModel.getNetworkIp6Dns(network, zone) :
                 networkModel.getNetworkIp4Dns(network, zone);
         Assert.assertEquals(dns1[0], result.first());
         Assert.assertNull(result.second());
-        // Both network and zone dns are null
-        prepareMocks(isIp6, network, zone, null, null,  null, null);
+        // network/vpc and zone dns are null
+        prepareMocks(isIp6, network, zone, vpc, null, null,  null, null, null, null);
         result = isIp6 ? networkModel.getNetworkIp6Dns(network, zone) :
                 networkModel.getNetworkIp4Dns(network, zone);
         Assert.assertNull(result.first());
diff --git a/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py b/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py
index a934862c224..41b8b644186 100755
--- a/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py
+++ b/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py
@@ -40,7 +40,7 @@ class CsGuestNetwork:
             return self.config.get_dns()
 
         dns = []
-        if 'router_guest_gateway' in self.data and not self.config.use_extdns():
+        if 'router_guest_gateway' in self.data and not self.config.use_extdns() and 'is_vr_guest_gateway' not in self.data:
             dns.append(self.data['router_guest_gateway'])
 
         if 'dns' in self.data: