NSX: Last Fixes
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 e978199..06583f2 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 @@
     String routerIpv6 = null;
     String routerIpv6Gateway = null;
     String routerIpv6Cidr = null;
+    boolean isVrGuestGateway = false;
 
     public NicTO getNic() {
         return nic;
@@ -114,4 +115,12 @@
     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 aee1e77..1a6824c 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 @@
         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 bb5e443..a416b4b 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 @@
     private String routerIp6;
     private String routerIp6Gateway;
     private String routerIp6Cidr;
+    private boolean isVrGuestGateway;
 
     private Integer mtu;
 
@@ -202,4 +203,12 @@
     public Integer getMtu() {
         return mtu;
     }
+
+    public boolean isVrGuestGateway() {
+        return isVrGuestGateway;
+    }
+
+    public void setVrGuestGateway(boolean vrGuestGateway) {
+        isVrGuestGateway = vrGuestGateway;
+    }
 }
diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java
index 453a260..6fbf417 100644
--- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java
+++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java
@@ -387,7 +387,10 @@
             String privatePort = cmd.getPrivatePort();
             String service = privatePort.contains("-") ? nsxApiClient.getServicePath(ruleName, privatePort, cmd.getProtocol(), null, null) :
                     nsxApiClient.getNsxInfraServices(ruleName, privatePort, cmd.getProtocol(), null, null);
-
+            if (nsxApiClient.doesPfRuleExist(ruleName, tier1GatewayName)) {
+                LOGGER.debug(String.format("Port forward rule for port: %s exits on NSX, not adding it again", privatePort));
+                return new NsxAnswer(cmd, true, null);
+            }
             nsxApiClient.createPortForwardingRule(ruleName, tier1GatewayName, cmd.getNetworkResourceName(), cmd.getPublicIp(),
                     cmd.getVmIp(), cmd.getPublicPort(), service);
         } catch (Exception e) {
diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
index fe02948..d443b0e 100644
--- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
+++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
@@ -124,6 +124,7 @@
     protected static final String NSX_LB_PASSIVE_MONITOR = "/infra/lb-monitor-profiles/default-passive-lb-monitor";
     protected static final String TCP_MONITOR_PROFILE = "LBTcpMonitorProfile";
     protected static final String UDP_MONITOR_PROFILE = "LBUdpMonitorProfile";
+    protected static final String NAT_ID = "USER";
 
     private enum PoolAllocation { ROUTING, LB_SMALL, LB_MEDIUM, LB_LARGE, LB_XLARGE }
 
@@ -342,15 +343,14 @@
 
     private void removeTier1GatewayNatRules(String tier1Id) {
         NatRules natRulesService = (NatRules) nsxService.apply(NatRules.class);
-        String natId = "USER";
-        PolicyNatRuleListResult result = natRulesService.list(tier1Id, natId, null, false, null, null, null, null);
+        PolicyNatRuleListResult result = natRulesService.list(tier1Id, NAT_ID, null, false, null, null, null, null);
         List<PolicyNatRule> natRules = result.getResults();
         if (CollectionUtils.isEmpty(natRules)) {
             logger.debug(String.format("Didn't find any NAT rule to remove on the Tier 1 Gateway %s", tier1Id));
         } else {
             for (PolicyNatRule natRule : natRules) {
                 logger.debug(String.format("Removing NAT rule %s from Tier 1 Gateway %s", natRule.getId(), tier1Id));
-                natRulesService.delete(tier1Id, natId, natRule.getId());
+                natRulesService.delete(tier1Id, NAT_ID, natRule.getId());
             }
         }
 
@@ -566,13 +566,24 @@
             natService.patch(tier1GatewayName, NatId.USER.name(), ruleName, rule);
         } catch (Error error) {
             ApiError ae = error.getData()._convertTo(ApiError.class);
-            String msg = String.format("Failed to delete NSX Port-forward rule %s for network: %s, due to %s",
+            String msg = String.format("Failed to add NSX Port-forward rule %s for network: %s, due to %s",
                     ruleName, networkName, ae.getErrorMessage());
             logger.error(msg);
             throw new CloudRuntimeException(msg);
         }
     }
 
+    public boolean doesPfRuleExist(String ruleName, String tier1GatewayName) {
+        try {
+            NatRules natService = (NatRules) nsxService.apply(NatRules.class);
+            PolicyNatRule rule = natService.get(tier1GatewayName, NAT_ID, ruleName);
+            return !Objects.isNull(rule);
+        } catch (Error error) {
+            logger.debug(String.format("Found a port forward rule named: %s on NSX", ruleName));
+            return false;
+        }
+    }
+
     List<LBPoolMember> getLbPoolMembers(List<NsxLoadBalancerMember> memberList, String tier1GatewayName) {
         List<LBPoolMember> members = new ArrayList<>();
         for (NsxLoadBalancerMember member : memberList) {
@@ -629,6 +640,8 @@
             LBUdpMonitorProfile lbUdpMonitorProfile = new LBUdpMonitorProfile.Builder(UDP_MONITOR_PROFILE)
                     .setDisplayName(lbMonitorProfileId)
                     .setMonitorPort(Long.parseLong(port))
+                    .setSend("")
+                    .setReceive("")
                     .build();
             lbActiveMonitor.patch(lbMonitorProfileId, lbUdpMonitorProfile);
         }
@@ -676,6 +689,9 @@
             String lbVirtualServerName = getVirtualServerName(tier1GatewayName, lbId);
             String lbServiceName = getLoadBalancerName(tier1GatewayName);
             LbVirtualServers lbVirtualServers = (LbVirtualServers) nsxService.apply(LbVirtualServers.class);
+            if (Objects.nonNull(getLbVirtualServerService(lbVirtualServers, lbServiceName))) {
+                return;
+            }
             LBVirtualServer lbVirtualServer = new LBVirtualServer.Builder()
                     .setId(lbVirtualServerName)
                     .setDisplayName(lbVirtualServerName)
@@ -694,6 +710,19 @@
         }
     }
 
+    private LBVirtualServer getLbVirtualServerService(LbVirtualServers lbVirtualServers, String lbVSName) {
+        try {
+            LBVirtualServer lbVirtualServer = lbVirtualServers.get(lbVSName);
+            if (Objects.nonNull(lbVirtualServer)) {
+                return lbVirtualServer;
+            }
+        } catch (Exception e) {
+            logger.debug(String.format("Found an LB virtual server named: %s on NSX", lbVSName));
+            return null;
+        }
+        return null;
+    }
+
     public void deleteNsxLbResources(String tier1GatewayName, long lbId) {
         try {
             // Delete associated Virtual servers
diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java
index ce27a7d..1fb546e 100644
--- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java
+++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java
@@ -535,8 +535,7 @@
         for (PortForwardingRule rule : rules) {
             IPAddressVO publicIp = ApiDBUtils.findIpAddressById(rule.getSourceIpAddressId());
             UserVm vm = ApiDBUtils.findUserVmById(rule.getVirtualMachineId());
-            if ((vm == null && (rule.getState() != FirewallRule.State.Revoke)) ||
-                    (vm != null && networkModel.getNicInNetwork(vm.getId(), network.getId()) == null)) {
+            if (vm == null && rule.getState() != FirewallRule.State.Revoke) {
                 continue;
             }
             NsxOpObject nsxObject = getNsxOpObject(network);
@@ -559,7 +558,7 @@
                     .setRuleId(rule.getId())
                     .setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT))
                     .build();
-            if (rule.getState() == FirewallRule.State.Add) {
+            if (Arrays.asList(FirewallRule.State.Add, FirewallRule.State.Active).contains(rule.getState())) {
                 result &= nsxService.createPortForwardRule(networkRule);
             } else if (rule.getState() == FirewallRule.State.Revoke) {
                 result &= nsxService.deletePortForwardRule(networkRule);
@@ -643,9 +642,6 @@
     public boolean applyLBRules(Network network, List<LoadBalancingRule> rules) throws ResourceUnavailableException {
         boolean result = true;
         for (LoadBalancingRule loadBalancingRule : rules) {
-            if (loadBalancingRule.getState() == FirewallRule.State.Active) {
-                continue;
-            }
             IPAddressVO publicIp = ipAddressDao.findByIpAndDcId(network.getDataCenterId(),
                     loadBalancingRule.getSourceIp().addr());
             NsxOpObject nsxObject = getNsxOpObject(network);
@@ -664,10 +660,10 @@
                     .setPublicPort(String.valueOf(loadBalancingRule.getSourcePortStart()))
                     .setPrivatePort(String.valueOf(loadBalancingRule.getDefaultPortStart()))
                     .setRuleId(loadBalancingRule.getId())
-                    .setProtocol(loadBalancingRule.getProtocol().toUpperCase(Locale.ROOT))
+                    .setProtocol(loadBalancingRule.getLbProtocol().toUpperCase(Locale.ROOT))
                     .setAlgorithm(loadBalancingRule.getAlgorithm())
                     .build();
-            if (loadBalancingRule.getState() == FirewallRule.State.Add) {
+            if (Arrays.asList(FirewallRule.State.Add, FirewallRule.State.Active).contains(loadBalancingRule.getState())) {
                 result &= nsxService.createLbRule(networkRule);
             } else if (loadBalancingRule.getState() == FirewallRule.State.Revoke) {
                 result &= nsxService.deleteLbRule(networkRule);
diff --git a/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxElementTest.java b/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxElementTest.java
index 318542c..ff7fa54 100644
--- a/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxElementTest.java
+++ b/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxElementTest.java
@@ -392,7 +392,7 @@
         LoadBalancerVO lb = new LoadBalancerVO(null, null, null, 0L, 8080, 8081, null, 0L, 0L, 1L, null, null);
         lb.setState(FirewallRule.State.Add);
         LoadBalancingRule.LbDestination destination = new LoadBalancingRule.LbDestination(6443, 6443, "172.30.110.11", false);
-        LoadBalancingRule rule = new LoadBalancingRule(lb, List.of(destination), null, null, new Ip("10.1.13.10"));
+        LoadBalancingRule rule = new LoadBalancingRule(lb, List.of(destination), null, null, new Ip("10.1.13.10"), null, "TCP");
 
         VpcVO vpc = Mockito.mock(VpcVO.class);
 
@@ -415,7 +415,7 @@
         LoadBalancerVO lb = new LoadBalancerVO(null, null, null, 0L, 8080, 8081, null, 0L, 0L, 1L, null, null);
         lb.setState(FirewallRule.State.Revoke);
         LoadBalancingRule.LbDestination destination = new LoadBalancingRule.LbDestination(6443, 6443, "172.30.110.11", false);
-        LoadBalancingRule rule = new LoadBalancingRule(lb, List.of(destination), null, null, new Ip("10.1.13.10"));
+        LoadBalancingRule rule = new LoadBalancingRule(lb, List.of(destination), null, null, new Ip("10.1.13.10"), null, "TCP");
 
         VpcVO vpc = Mockito.mock(VpcVO.class);
 
diff --git a/server/src/main/java/com/cloud/network/NetworkModelImpl.java b/server/src/main/java/com/cloud/network/NetworkModelImpl.java
index 407264e..07e471c 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.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 @@
     ProjectDao projectDao;
     @Inject
     NetworkPermissionDao _networkPermissionDao;
+    @Inject
+    VpcDao vpcDao;
 
     private List<NetworkElement> networkElements;
 
@@ -2713,6 +2717,12 @@
         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 @@
         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 677707e..ce5024a 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 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 @@
         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 0f15abc..41adb65 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.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.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 @@
         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 @@
         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 a934862..41b8b64 100755
--- a/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py
+++ b/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py
@@ -40,7 +40,7 @@
             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: