Merge branch '4.14'
diff --git a/api/src/main/java/com/cloud/agent/api/to/IpAddressTO.java b/api/src/main/java/com/cloud/agent/api/to/IpAddressTO.java
index 1169820..5be71ba 100644
--- a/api/src/main/java/com/cloud/agent/api/to/IpAddressTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/IpAddressTO.java
@@ -35,6 +35,7 @@
     private String networkName;
     private Integer nicDevId;
     private boolean newNic;
+    private boolean isPrivateGateway;
 
     public IpAddressTO(long accountId, String ipAddress, boolean add, boolean firstIP, boolean sourceNat, String broadcastUri, String vlanGateway, String vlanNetmask,
             String vifMacAddress, Integer networkRate, boolean isOneToOneNat) {
@@ -133,4 +134,12 @@
     public void setNewNic(boolean newNic) {
         this.newNic = newNic;
     }
+
+    public boolean isPrivateGateway() {
+        return isPrivateGateway;
+    }
+
+    public void setPrivateGateway(boolean isPrivateGateway) {
+        this.isPrivateGateway = isPrivateGateway;
+    }
 }
diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/IpAssociationConfigItem.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/IpAssociationConfigItem.java
index 64f953d..3690853 100644
--- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/IpAssociationConfigItem.java
+++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/IpAssociationConfigItem.java
@@ -42,6 +42,7 @@
         for (final IpAddressTO ip : command.getIpAddresses()) {
             final IpAddress ipAddress = new IpAddress(ip.getPublicIp(), ip.isSourceNat(), ip.isAdd(), ip.isOneToOneNat(), ip.isFirstIP(), ip.getVlanGateway(), ip.getVlanNetmask(),
                     ip.getVifMacAddress(), ip.getNicDevId(), ip.isNewNic(), ip.getTrafficType().toString());
+            ipAddress.setPrivateGateway(ip.isPrivateGateway());
             ips.add(ipAddress);
         }
 
diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/IpAddress.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/IpAddress.java
index 70aeb4c..627bcf0 100644
--- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/IpAddress.java
+++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/IpAddress.java
@@ -32,6 +32,7 @@
     private Integer nicDevId;
     private boolean newNic;
     private String nwType;
+    private boolean isPrivateGateway;
 
     public IpAddress() {
         // Empty constructor for (de)serialization
@@ -133,4 +134,12 @@
         this.newNic = newNic;
     }
 
+    public boolean isPrivateGateway() {
+        return isPrivateGateway;
+    }
+
+    public void setPrivateGateway(boolean isPrivateGateway) {
+        this.isPrivateGateway = isPrivateGateway;
+    }
+
 }
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 4adf140..262fa4b 100644
--- a/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java
+++ b/server/src/main/java/com/cloud/network/router/CommandSetupHelper.java
@@ -106,9 +106,7 @@
 import com.cloud.network.vpc.StaticRouteProfile;
 import com.cloud.network.vpc.Vpc;
 import com.cloud.network.vpc.VpcGateway;
-import com.cloud.network.vpc.VpcGatewayVO;
 import com.cloud.network.vpc.dao.VpcDao;
-import com.cloud.network.vpc.dao.VpcGatewayDao;
 import com.cloud.offering.NetworkOffering;
 import com.cloud.offerings.NetworkOfferingVO;
 import com.cloud.offerings.dao.NetworkOfferingDao;
@@ -174,8 +172,6 @@
     @Inject
     private VpcDao _vpcDao;
     @Inject
-    private VpcGatewayDao _vpcGatewayDao;
-    @Inject
     private VlanDao _vlanDao;
     @Inject
     private IPAddressDao _ipAddressDao;
@@ -734,8 +730,7 @@
                 final IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, firstIP, sourceNat, BroadcastDomainType.fromString(ipAddr.getVlanTag()).toString(), ipAddr.getGateway(),
                         ipAddr.getNetmask(), macAddress, networkRate, ipAddr.isOneToOneNat());
 
-                ip.setTrafficType(getNetworkTrafficType(network));
-                ip.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network));
+                setIpAddressNetworkParams(ip, network, router);
                 ipsToSend[i++] = ip;
                 if (ipAddr.isSourceNat()) {
                     sourceNatIpAdd = new Pair<IpAddressTO, Long>(ip, ipAddr.getNetworkId());
@@ -859,8 +854,7 @@
                 final IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask,
                         vifMacAddress, networkRate, ipAddr.isOneToOneNat());
 
-                ip.setTrafficType(getNetworkTrafficType(network));
-                ip.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network));
+                setIpAddressNetworkParams(ip, network, router);
                 ipsToSend[i++] = ip;
                 /*
                  * send the firstIP = true for the first Add, this is to create
@@ -987,8 +981,7 @@
                 final IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, ipAddr.getIpAddress(), add, false, ipAddr.getSourceNat(), ipAddr.getBroadcastUri(),
                         ipAddr.getGateway(), ipAddr.getNetmask(), ipAddr.getMacAddress(), null, false);
 
-                ip.setTrafficType(getNetworkTrafficType(network));
-                ip.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network));
+                setIpAddressNetworkParams(ip, network, router);
                 ipsToSend[i++] = ip;
 
             }
@@ -1145,13 +1138,16 @@
         return dhcpRange;
     }
 
-    private TrafficType getNetworkTrafficType(Network network) {
-        final VpcGatewayVO gateway = _vpcGatewayDao.getVpcGatewayByNetworkId(network.getId());
-        if (gateway != null) {
+    private void setIpAddressNetworkParams(IpAddressTO ipAddress, final Network network, final VirtualRouter router) {
+        if (_networkModel.isPrivateGateway(network.getId())) {
             s_logger.debug("network " + network.getId() + " (name: " + network.getName() + " ) is a vpc private gateway, set traffic type to Public");
-            return TrafficType.Public;
+            ipAddress.setTrafficType(TrafficType.Public);
+            ipAddress.setPrivateGateway(true);
         } else {
-            return network.getTrafficType();
+            ipAddress.setTrafficType(network.getTrafficType());
+            ipAddress.setPrivateGateway(false);
         }
+        ipAddress.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network));
     }
+
 }
diff --git a/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java
index 556fe18..7c95761 100644
--- a/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java
@@ -77,7 +77,6 @@
 import com.cloud.network.vpc.StaticRouteProfile;
 import com.cloud.network.vpc.Vpc;
 import com.cloud.network.vpc.VpcGateway;
-import com.cloud.network.vpc.VpcGatewayVO;
 import com.cloud.network.vpc.VpcManager;
 import com.cloud.network.vpc.VpcVO;
 import com.cloud.network.vpc.dao.PrivateIpDao;
@@ -277,15 +276,6 @@
                 if (defaultDns2 != null) {
                     buf.append(" dns2=").append(defaultDns2);
                 }
-
-                VpcGatewayVO privateGatewayForVpc = _vpcGatewayDao.getPrivateGatewayForVpc(domainRouterVO.getVpcId());
-                if (privateGatewayForVpc != null) {
-                    String ip4Address = privateGatewayForVpc.getIp4Address();
-                    buf.append(" privategateway=").append(ip4Address);
-                    s_logger.debug("Set privategateway field in cmd_line.json to " + ip4Address);
-                } else {
-                    buf.append(" privategateway=None");
-                }
             }
         }
 
diff --git a/server/src/main/java/com/cloud/network/rules/NicPlugInOutRules.java b/server/src/main/java/com/cloud/network/rules/NicPlugInOutRules.java
index 40cf72c..6ee5e85 100644
--- a/server/src/main/java/com/cloud/network/rules/NicPlugInOutRules.java
+++ b/server/src/main/java/com/cloud/network/rules/NicPlugInOutRules.java
@@ -29,6 +29,8 @@
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.NetworkUsageCommand;
 import com.cloud.agent.manager.Commands;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.ResourceUnavailableException;
@@ -38,6 +40,9 @@
 import com.cloud.network.Networks.BroadcastDomainType;
 import com.cloud.network.Networks.IsolationType;
 import com.cloud.network.PublicIpAddress;
+import com.cloud.network.dao.FirewallRulesDao;
+import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.IPAddressVO;
 import com.cloud.network.router.VirtualRouter;
 import com.cloud.network.vpc.VpcManager;
 import com.cloud.network.vpc.VpcVO;
@@ -51,6 +56,9 @@
 import com.cloud.vm.VirtualMachineManager;
 import com.cloud.vm.dao.NicDao;
 
+import org.apache.cloudstack.network.topology.NetworkTopology;
+import org.apache.cloudstack.network.topology.NetworkTopologyContext;
+
 public class NicPlugInOutRules extends RuleApplier {
 
     private static final Logger s_logger = Logger.getLogger(NicPlugInOutRules.class);
@@ -75,6 +83,28 @@
 
         NetworkModel networkModel = visitor.getVirtualNetworkApplianceFactory().getNetworkModel();
         VirtualMachineManager itMgr = visitor.getVirtualNetworkApplianceFactory().getItMgr();
+        NicDao nicDao = visitor.getVirtualNetworkApplianceFactory().getNicDao();
+
+        // de-associate IPs before unplugging nics
+        if (!nicsToUnplug.isEmpty()) {
+            NetworkTopologyContext networkTopologyContext = visitor.getVirtualNetworkApplianceFactory().getNetworkTopologyContext();
+            final DataCenterDao dcDao = visitor.getVirtualNetworkApplianceFactory().getDcDao();
+            final DataCenterVO dcVO = dcDao.findById(router.getDataCenterId());
+            final NetworkTopology networkTopology = networkTopologyContext.retrieveNetworkTopology(dcVO);
+
+            final String typeString = "vpc ip association before unplugging nics";
+            final boolean isPodLevelException = false;
+            final boolean failWhenDisconnect = false;
+            final Long podId = null;
+            final VpcIpAssociationRules ipAssociationRules = new VpcIpAssociationRules(_network, _ipAddresses);
+            final boolean result = networkTopology.applyRules(_network, router, typeString, isPodLevelException, podId, failWhenDisconnect,
+                    new RuleApplierWrapper<RuleApplier>(ipAssociationRules));
+            if (!result) {
+                s_logger.warn("Failed to de-associate IPs before unplugging nics");
+                return false;
+            }
+        }
+
         // 1) Unplug the nics
         for (Entry<String, PublicIpAddress> entry : nicsToUnplug.entrySet()) {
             Network publicNtwk = null;
@@ -159,6 +189,9 @@
 
         VpcManager vpcMgr = visitor.getVirtualNetworkApplianceFactory().getVpcMgr();
         NicDao nicDao = visitor.getVirtualNetworkApplianceFactory().getNicDao();
+        IPAddressDao ipAddressDao = visitor.getVirtualNetworkApplianceFactory().getIpAddressDao();
+        FirewallRulesDao rulesDao = visitor.getVirtualNetworkApplianceFactory().getFirewallRulesDao();
+
         // find out nics to unplug
         for (PublicIpAddress ip : _ipAddresses) {
             long publicNtwkId = ip.getNetworkId();
@@ -170,10 +203,26 @@
             }
 
             if (ip.getState() == IpAddress.State.Releasing) {
-                Nic nic = nicDao.findByIp4AddressAndNetworkIdAndInstanceId(publicNtwkId, _router.getId(), ip.getAddress().addr());
+                NicVO nic = nicDao.findByIp4AddressAndNetworkIdAndInstanceId(publicNtwkId, _router.getId(), ip.getAddress().addr());
                 if (nic != null) {
-                    nicsToUnplug.put(ip.getVlanTag(), ip);
-                    s_logger.debug("Need to unplug the nic for ip=" + ip + "; vlan=" + ip.getVlanTag() + " in public network id =" + publicNtwkId);
+                    final List<IPAddressVO> allIps = ipAddressDao.listByAssociatedVpc(ip.getVpcId(), null);
+                    boolean ipUpdated = false;
+                    for (IPAddressVO allIp : allIps) {
+                        if (allIp.getId() != ip.getId() && allIp.getVlanId() == ip.getVlanId()
+                                && (allIp.isSourceNat()
+                                || rulesDao.countRulesByIpIdAndState(allIp.getId(), FirewallRule.State.Active) > 0
+                                || (allIp.isOneToOneNat() && allIp.getRuleState() == null))) {
+                            s_logger.debug("Updating the nic " + nic + " with new ip address " + allIp.getAddress().addr());
+                            nic.setIPv4Address(allIp.getAddress().addr());
+                            nicDao.update(nic.getId(), nic);
+                            ipUpdated = true;
+                            break;
+                        }
+                    }
+                    if (!ipUpdated) {
+                        nicsToUnplug.put(ip.getVlanTag(), ip);
+                        s_logger.debug("Need to unplug the nic for ip=" + ip + "; vlan=" + ip.getVlanTag() + " in public network id =" + publicNtwkId);
+                    }
                 }
             }
         }
@@ -215,4 +264,4 @@
 
         return nicsToChange;
     }
-}
\ No newline at end of file
+}
diff --git a/server/src/main/java/com/cloud/network/rules/VirtualNetworkApplianceFactory.java b/server/src/main/java/com/cloud/network/rules/VirtualNetworkApplianceFactory.java
index 34400ea..9d4660d 100644
--- a/server/src/main/java/com/cloud/network/rules/VirtualNetworkApplianceFactory.java
+++ b/server/src/main/java/com/cloud/network/rules/VirtualNetworkApplianceFactory.java
@@ -26,6 +26,7 @@
 import com.cloud.dc.dao.VlanDao;
 import com.cloud.network.IpAddressManager;
 import com.cloud.network.NetworkModel;
+import com.cloud.network.dao.FirewallRulesDao;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.network.dao.LoadBalancerDao;
 import com.cloud.network.dao.NetworkDao;
@@ -43,6 +44,8 @@
 import com.cloud.vm.dao.NicIpAliasDao;
 import com.cloud.vm.dao.UserVmDao;
 
+import org.apache.cloudstack.network.topology.NetworkTopologyContext;
+
 public class VirtualNetworkApplianceFactory {
 
     @Inject
@@ -83,6 +86,8 @@
     private IpAddressManager _ipAddrMgr;
     @Inject
     private NetworkACLManager _networkACLMgr;
+    @Inject
+    private FirewallRulesDao _rulesDao;
 
     @Autowired
     @Qualifier("networkHelper")
@@ -91,6 +96,9 @@
     @Inject
     private NicProfileHelper _nicProfileHelper;
 
+    @Inject
+    private NetworkTopologyContext _networkTopologyContext;
+
     public NetworkModel getNetworkModel() {
         return _networkModel;
     }
@@ -174,4 +182,12 @@
     public NicProfileHelper getNicProfileHelper() {
         return _nicProfileHelper;
     }
-}
\ No newline at end of file
+
+    public NetworkTopologyContext getNetworkTopologyContext() {
+        return _networkTopologyContext;
+    }
+
+    public FirewallRulesDao getFirewallRulesDao() {
+        return _rulesDao;
+    }
+}
diff --git a/server/src/main/java/org/apache/cloudstack/network/topology/AdvancedNetworkTopology.java b/server/src/main/java/org/apache/cloudstack/network/topology/AdvancedNetworkTopology.java
index f35f142..fc29fcc 100644
--- a/server/src/main/java/org/apache/cloudstack/network/topology/AdvancedNetworkTopology.java
+++ b/server/src/main/java/org/apache/cloudstack/network/topology/AdvancedNetworkTopology.java
@@ -214,7 +214,11 @@
         final boolean result = applyRules(network, router, typeString, isPodLevelException, podId, failWhenDisconnect, new RuleApplierWrapper<RuleApplier>(ipAssociationRules));
 
         if (result) {
-            _advancedVisitor.visit(nicPlugInOutRules);
+            if (router.getState() == State.Stopped || router.getState() == State.Stopping) {
+                s_logger.debug("Router " + router.getInstanceName() + " is in " + router.getState() + ", so not sending NicPlugInOutRules command to the backend");
+            } else {
+                _advancedVisitor.visit(nicPlugInOutRules);
+            }
         }
 
         return result;
@@ -241,4 +245,4 @@
         final boolean result = applyRules(network, router, typeString, isPodLevelException, podId, failWhenDisconnect, new RuleApplierWrapper<RuleApplier>(aclsRules));
         return result;
     }
-}
\ No newline at end of file
+}
diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py
index 01e580f..be67f40 100755
--- a/systemvm/debian/opt/cloud/bin/configure.py
+++ b/systemvm/debian/opt/cloud/bin/configure.py
@@ -817,6 +817,13 @@
                 return interface.get_gateway()
         return None
 
+    def getPrivateGatewayNetworks(self):
+        interfaces = []
+        for interface in self.config.address().get_interfaces():
+            if interface.is_private_gateway():
+                interfaces.append(interface)
+        return interfaces
+
     def portsToString(self, ports, delimiter):
         ports_parts = ports.split(":", 2)
         if ports_parts[0] == ports_parts[1]:
@@ -948,12 +955,21 @@
         if device is None:
             raise Exception("Ip address %s has no device in the ips databag" % rule["public_ip"])
 
+        chain_name = "PREROUTING-%s-def" % device
         self.fw.append(["mangle", "front",
-                        "-A PREROUTING -d %s/32 -m state --state NEW -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff" %
-                        rule["public_ip"]])
-        self.fw.append(["mangle", "front",
-                        "-A PREROUTING -d %s/32 -m state --state NEW -j MARK --set-xmark %s/0xffffffff" %
-                        (rule["public_ip"], hex(100 + int(device[len("eth"):])))])
+                        "-A PREROUTING -s %s/32 -m state --state NEW -j %s" %
+                        (rule["internal_ip"], chain_name)])
+        self.fw.append(["mangle", "",
+                        "-A %s -j MARK --set-xmark %s/0xffffffff" %
+                        (chain_name, hex(100 + int(device[len("eth"):])))])
+        self.fw.append(["mangle", "",
+                        "-A %s -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff" %
+                        chain_name])
+        private_gateways = self.getPrivateGatewayNetworks()
+        for private_gw in private_gateways:
+            self.fw.append(["mangle", "front", "-A %s -d %s -j RETURN" %
+                            (chain_name, private_gw.get_network())])
+
         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 3340a55..44b6950 100755
--- a/systemvm/debian/opt/cloud/bin/cs/CsAddress.py
+++ b/systemvm/debian/opt/cloud/bin/cs/CsAddress.py
@@ -197,6 +197,11 @@
             return True
         return False
 
+    def is_private_gateway(self):
+        if "is_private_gateway" in self.address:
+            return self.address['is_private_gateway']
+        return False
+
     def is_added(self):
         return self.get_attr("add")
 
@@ -476,10 +481,33 @@
             self.fw.append(["", "front", "-A NETWORK_STATS_%s -o %s -s %s" %
                             ("eth1", "eth1", guestNetworkCidr)])
 
+        if self.is_private_gateway():
+            self.fw.append(["filter", "", "-A FORWARD -d %s -o %s -j ACL_INBOUND_%s" %
+                            (self.address['network'], self.dev, self.dev)])
+            self.fw.append(["filter", "", "-A ACL_INBOUND_%s -j DROP" % self.dev])
+            self.fw.append(["mangle", "",
+                            "-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s/32 -j ACL_OUTBOUND_%s" %
+                            (self.dev, self.address['network'], self.address['gateway'], self.dev)])
+            self.fw.append(["mangle", "front",
+                            "-A PREROUTING -s %s -d %s -m state --state NEW -j MARK --set-xmark %s/0xffffffff" %
+                            (self.cl.get_vpccidr(), self.address['network'], hex(100 + int(self.dev[3:])))])
             if self.address["source_nat"]:
                 self.fw.append(["nat", "front",
                                 "-A POSTROUTING -o %s -j SNAT --to-source %s" %
                                 (self.dev, self.address['public_ip'])])
+            if self.get_gateway() == self.get_ip_address():
+                for inf, addresses in self.config.address().dbag.iteritems():
+                    if not inf.startswith("eth"):
+                        continue
+                    for address in addresses:
+                        if "nw_type" in address and address["nw_type"] == "guest":
+                            self.fw.append(["filter", "front", "-A FORWARD -s %s -d %s -j ACL_INBOUND_%s" %
+                                            (address["network"], self.address["network"], self.dev)])
+                            self.fw.append(["filter", "front", "-A FORWARD -s %s -d %s -j ACL_INBOUND_%s" %
+                                            (self.address["network"], address["network"], address["device"])])
+                # Accept packet from private gateway if VPC VR is used as gateway
+                self.fw.append(["filter", "", "-A FORWARD -s %s ! -d %s -j ACCEPT" %
+                                (self.address['network'], self.address['network'])])
 
         if self.get_type() in ["public"]:
             self.fw.append(
@@ -625,6 +653,11 @@
             return True
         return False
 
+    def is_private_gateway(self):
+        if "is_private_gateway" in self.address:
+            return self.address['is_private_gateway']
+        return False
+
     def ip(self):
         return str(self.address['cidr'])
 
diff --git a/systemvm/debian/opt/cloud/bin/merge.py b/systemvm/debian/opt/cloud/bin/merge.py
index b988b7a..4ab9911 100755
--- a/systemvm/debian/opt/cloud/bin/merge.py
+++ b/systemvm/debian/opt/cloud/bin/merge.py
@@ -153,13 +153,10 @@
         dp['gateway'] = d['router_guest_gateway']
         dp['nic_dev_id'] = d['device'][3:]
         dp['nw_type'] = 'guest'
-        dp = PrivateGatewayHack.update_network_type_for_privategateway(dbag, dp)
         qf = QueueFile()
         qf.load({'ip_address': [dp], 'type': 'ips'})
         if 'domain_name' not in d.keys() or d['domain_name'] == '':
             d['domain_name'] = "cloudnine.internal"
-
-        d = PrivateGatewayHack.update_network_type_for_privategateway(dbag, d)
         return cs_guestnetwork.merge(dbag, d)
 
     def process_dhcp_entry(self, dbag):
@@ -329,42 +326,3 @@
         os.remove(origPath)
 
         logging.debug("Processed file written to %s", zipped_file_name)
-
-
-class PrivateGatewayHack:
-
-    @classmethod
-    def update_network_type_for_privategateway(cls, dbag, data):
-        ip = data['router_guest_ip'] if 'router_guest_ip' in data.keys() else data['public_ip']
-
-        initial_data = cls.load_inital_data()
-        has_private_gw_ip = cls.if_config_has_privategateway(initial_data)
-        private_gw_matches = 'privategateway' in initial_data['config'] and cls.ip_matches_private_gateway_ip(ip, initial_data['config']['privategateway'])
-
-        if has_private_gw_ip and private_gw_matches:
-            data['nw_type'] = "public"
-            logging.debug("Updating nw_type for ip %s" % ip)
-        else:
-            logging.debug("Not updating nw_type for ip %s because has_private_gw_ip = %s and private_gw_matches = %s " % (ip, has_private_gw_ip, private_gw_matches))
-        return data
-
-    @classmethod
-    def if_config_has_privategateway(cls, dbag):
-        return 'privategateway' in dbag['config'].keys() and dbag['config']['privategateway'] != "None"
-
-    @classmethod
-    def ip_matches_private_gateway_ip(cls, ip, private_gateway_ip):
-        new_ip_matches_private_gateway_ip = False
-        if ip == private_gateway_ip:
-            new_ip_matches_private_gateway_ip = True
-        return new_ip_matches_private_gateway_ip
-
-    @classmethod
-    def load_inital_data(cls):
-        initial_data_bag = DataBag()
-        initial_data_bag.setKey('cmdline')
-        initial_data_bag.load()
-        initial_data = initial_data_bag.getDataBag()
-        logging.debug("Initial data = %s" % initial_data)
-
-        return initial_data
diff --git a/test/integration/component/test_multiple_subnets_in_isolated_network.py b/test/integration/component/test_multiple_subnets_in_isolated_network.py
index 9892a3b..9cbd3bb 100644
--- a/test/integration/component/test_multiple_subnets_in_isolated_network.py
+++ b/test/integration/component/test_multiple_subnets_in_isolated_network.py
@@ -35,6 +35,7 @@
                              NetworkOffering,
                              VPC,
                              VpcOffering,
+                             StaticNATRule,
                              NATRule,
                              PublicIPAddress,
                              PublicIpRange)
@@ -191,6 +192,35 @@
                 sourcenatIp = nic.ipaddress
         return guestIp, controlIp, sourcenatIp
 
+    def verify_router_publicnic_state(self, router, host, publicNics):
+        command = '/opt/cloud/bin/checkrouter.sh | cut -d ":" -f2 |tr -d " "'
+        self.logger.debug("Executing command '%s'" % command)
+        result = get_process_status(
+            host.ipaddress,
+            host.port,
+            host.user,
+            host.password,
+            router.linklocalip,
+            command)
+        self.assertTrue(len(result) > 0, "Cannot get router %s redundant state" % router.name)
+        redundant_state = result[0]
+        self.logger.debug("router %s redudnant state is %s" % (router.name, redundant_state))
+        if redundant_state == "FAULT":
+            self.logger.debug("Skip as redundant_state is %s" % redundant_state)
+            return
+        elif redundant_state == "MASTER":
+            command = 'ip link show |grep BROADCAST | egrep "%s" |grep "state DOWN" |wc -l' % publicNics
+        elif redundant_state == "BACKUP":
+            command = 'ip link show |grep BROADCAST | egrep "%s" |grep "state UP" |wc -l' % publicNics
+        result = get_process_status(
+            host.ipaddress,
+            host.port,
+            host.user,
+            host.password,
+            router.linklocalip,
+            command)
+        self.assertTrue(len(result) > 0 and result[0] == "0", "Expected result is 0 but actual result is %s" % result[0])
+
     def verify_network_interfaces_in_router(self, router, host, expectedNics):
         command = 'ip link show |grep BROADCAST | cut -d ":" -f2 |tr -d " "|tr "\n" ","'
         self.logger.debug("Executing command '%s'" % command)
@@ -247,7 +277,7 @@
         #   verify the IPs in VR. eth0 -> guest nic IP, eth2 -> source nat IP
 
         # 6. create new public ip range 1
-        # 7. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
+        # 7. get a free ip 4 in new ip range 2, assign to network, and enable static nat to vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
         #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 1
         # 8. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
@@ -278,6 +308,21 @@
         # 17. release new ip 4
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
         #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 3, eth4 -> new ip 6
+        # 18. release new ip 3
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth4 -> new ip 6
+        # 19. restart network
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth4 -> new ip 6
+        # 20. reboot router
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
+        # 21. restart network with cleanup
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
+        # 22. restart network with cleanup, makeredundant=true
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
         """
 
         # Create new domain1
@@ -337,6 +382,7 @@
             self.verify_ip_address_in_router(router, host, guestIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
+            self.verify_router_publicnic_state(router, host, "eth2")
 
         # 4. get a free public ip, assign to network, and create port forwarding rules (ssh) to the vm
         ipaddress = PublicIPAddress.create(
@@ -362,6 +408,7 @@
             self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress.ipaddress.ipaddress, "eth2", True)
+            self.verify_router_publicnic_state(router, host, "eth2")
 
         # 5. release the new ip
         ipaddress.delete(self.apiclient)
@@ -377,6 +424,7 @@
             self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress.ipaddress.ipaddress, "eth2", False)
+            self.verify_router_publicnic_state(router, host, "eth2")
 
         # 6. create new public ip range 1
         self.services["publiciprange"]["zoneid"] = self.zone.id
@@ -395,7 +443,7 @@
         )
         self.cleanup.append(self.public_ip_range1)
 
-        # 7. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
+        # 7. get a free ip 4 in new ip range 2, assign to network, and enable static nat to vm
         ip_address_1 = self.get_free_ipaddress(self.public_ip_range1.vlan.id)
         ipaddress_1 = PublicIPAddress.create(
             self.apiclient,
@@ -404,12 +452,11 @@
             ipaddress=ip_address_1
         )
 
-        nat_rule = NATRule.create(
+        StaticNATRule.enable(
             self.apiclient,
-            self.virtual_machine1,
-            self.services["natrule"],
+            virtualmachineid=self.virtual_machine1.id,
             ipaddressid=ipaddress_1.ipaddress.id,
-            openfirewall=True
+            networkid=self.network1.id
         )
 
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -423,6 +470,7 @@
             self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 8. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -452,6 +500,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 9. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -482,6 +531,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 10. release new ip 2
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -499,6 +549,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 11. release new ip 1
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -515,6 +566,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 12. create new public ip range 2
         self.services["publiciprange"]["zoneid"] = self.zone.id
@@ -544,12 +596,11 @@
             ipaddress=ip_address_4
         )
 
-        nat_rule = NATRule.create(
+        StaticNATRule.enable(
             self.apiclient,
-            self.virtual_machine1,
-            self.services["natrule"],
+            virtualmachineid=self.virtual_machine1.id,
             ipaddressid=ipaddress_4.ipaddress.id,
-            openfirewall=True
+            networkid=self.network1.id
         )
 
 
@@ -563,6 +614,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 14. get a free ip 5 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -593,6 +645,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 15. get a free ip 6 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -624,6 +677,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 16. release new ip 5
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -642,6 +696,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 17. release new ip 4
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -659,6 +714,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 18. release new ip 3
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,"
@@ -675,8 +731,11 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth4")
 
         # 19. restart network
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth4 -> new ip 6
         self.network1.restart(self.apiclient)
         routers = self.get_routers(self.network1.id)
         for router in routers:
@@ -689,8 +748,11 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth4")
 
-        # reboot router
+        # 20. reboot router
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
         for router in routers:
             cmd = rebootRouter.rebootRouterCmd()
             cmd.id = router.id
@@ -705,8 +767,11 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
-        # 20. restart network with cleanup
+        # 21. restart network with cleanup
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
         self.network1.restart(self.apiclient, cleanup=True)
         routers = self.get_routers(self.network1.id)
         for router in routers:
@@ -720,7 +785,9 @@
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth3", True)
 
-        # 21. restart network with cleanup, makeredundant=true
+        # 22. restart network with cleanup, makeredundant=true
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
         self.network1.restart(self.apiclient, cleanup=True, makeredundant=True)
         routers = self.get_routers(self.network1.id)
         for router in routers:
@@ -733,3 +800,4 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
diff --git a/test/integration/component/test_multiple_subnets_in_isolated_network_rvr.py b/test/integration/component/test_multiple_subnets_in_isolated_network_rvr.py
index 2abd076..7b58e00 100644
--- a/test/integration/component/test_multiple_subnets_in_isolated_network_rvr.py
+++ b/test/integration/component/test_multiple_subnets_in_isolated_network_rvr.py
@@ -35,6 +35,7 @@
                              NetworkOffering,
                              VPC,
                              VpcOffering,
+                             StaticNATRule,
                              NATRule,
                              PublicIPAddress,
                              PublicIpRange)
@@ -191,6 +192,35 @@
                 sourcenatIp = nic.ipaddress
         return guestIp, controlIp, sourcenatIp
 
+    def verify_router_publicnic_state(self, router, host, publicNics):
+        command = '/opt/cloud/bin/checkrouter.sh | cut -d ":" -f2 |tr -d " "'
+        self.logger.debug("Executing command '%s'" % command)
+        result = get_process_status(
+            host.ipaddress,
+            host.port,
+            host.user,
+            host.password,
+            router.linklocalip,
+            command)
+        self.assertTrue(len(result) > 0, "Cannot get router %s redundant state" % router.name)
+        redundant_state = result[0]
+        self.logger.debug("router %s redudnant state is %s" % (router.name, redundant_state))
+        if redundant_state == "FAULT":
+            self.logger.debug("Skip as redundant_state is %s" % redundant_state)
+            return
+        elif redundant_state == "MASTER":
+            command = 'ip link show |grep BROADCAST | egrep "%s" |grep "state DOWN" |wc -l' % publicNics
+        elif redundant_state == "BACKUP":
+            command = 'ip link show |grep BROADCAST | egrep "%s" |grep "state UP" |wc -l' % publicNics
+        result = get_process_status(
+            host.ipaddress,
+            host.port,
+            host.user,
+            host.password,
+            router.linklocalip,
+            command)
+        self.assertTrue(len(result) > 0 and result[0] == "0", "Expected result is 0 but actual result is %s" % result[0])
+
     def verify_network_interfaces_in_router(self, router, host, expectedNics):
         command = 'ip link show |grep BROADCAST | cut -d ":" -f2 |tr -d " "|tr "\n" ","'
         self.logger.debug("Executing command '%s'" % command)
@@ -247,7 +277,7 @@
         #   verify the IPs in VR. eth0 -> guest nic IP, eth2 -> source nat IP
 
         # 6. create new public ip range 1
-        # 7. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
+        # 7. get a free ip 4 in new ip range 2, assign to network, and enable static nat to vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
         #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 1
         # 8. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
@@ -278,6 +308,21 @@
         # 17. release new ip 4
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
         #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 3, eth4 -> new ip 6
+        # 18. release new ip 3
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth4 -> new ip 6
+        # 19. restart network
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth4 -> new ip 6
+        # 20. reboot router
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
+        # 21. restart network with cleanup
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
+        # 22. restart network with cleanup, makeredundant=true
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
         """
 
         # Create new domain1
@@ -337,6 +382,7 @@
             self.verify_ip_address_in_router(router, host, guestIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
+            self.verify_router_publicnic_state(router, host, "eth2")
 
         # 4. get a free public ip, assign to network, and create port forwarding rules (ssh) to the vm
         ipaddress = PublicIPAddress.create(
@@ -362,6 +408,7 @@
             self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress.ipaddress.ipaddress, "eth2", True)
+            self.verify_router_publicnic_state(router, host, "eth2")
 
         # 5. release the new ip
         ipaddress.delete(self.apiclient)
@@ -377,6 +424,7 @@
             self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress.ipaddress.ipaddress, "eth2", False)
+            self.verify_router_publicnic_state(router, host, "eth2")
 
         # 6. create new public ip range 1
         self.services["publiciprange"]["zoneid"] = self.zone.id
@@ -395,7 +443,7 @@
         )
         self.cleanup.append(self.public_ip_range1)
 
-        # 7. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
+        # 7. get a free ip 4 in new ip range 2, assign to network, and enable static nat to vm
         ip_address_1 = self.get_free_ipaddress(self.public_ip_range1.vlan.id)
         ipaddress_1 = PublicIPAddress.create(
             self.apiclient,
@@ -404,12 +452,11 @@
             ipaddress=ip_address_1
         )
 
-        nat_rule = NATRule.create(
+        StaticNATRule.enable(
             self.apiclient,
-            self.virtual_machine1,
-            self.services["natrule"],
+            virtualmachineid=self.virtual_machine1.id,
             ipaddressid=ipaddress_1.ipaddress.id,
-            openfirewall=True
+            networkid=self.network1.id
         )
 
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -423,6 +470,7 @@
             self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 8. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -452,6 +500,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 9. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -482,6 +531,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 10. release new ip 2
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -499,6 +549,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 11. release new ip 1
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -515,6 +566,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
         # 12. create new public ip range 2
         self.services["publiciprange"]["zoneid"] = self.zone.id
@@ -544,12 +596,11 @@
             ipaddress=ip_address_4
         )
 
-        nat_rule = NATRule.create(
+        StaticNATRule.enable(
             self.apiclient,
-            self.virtual_machine1,
-            self.services["natrule"],
+            virtualmachineid=self.virtual_machine1.id,
             ipaddressid=ipaddress_4.ipaddress.id,
-            openfirewall=True
+            networkid=self.network1.id
         )
 
 
@@ -563,6 +614,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 14. get a free ip 5 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -593,6 +645,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 15. get a free ip 6 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -624,6 +677,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 16. release new ip 5
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -642,6 +696,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 17. release new ip 4
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -659,6 +714,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3|eth4")
 
         # 18. release new ip 3
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,"
@@ -675,8 +731,11 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth4")
 
         # 19. restart network
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth4 -> new ip 6
         self.network1.restart(self.apiclient)
         routers = self.get_routers(self.network1.id)
         for router in routers:
@@ -689,8 +748,11 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth4", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth4")
 
-        # reboot router
+        # 20. reboot router
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
         for router in routers:
             cmd = rebootRouter.rebootRouterCmd()
             cmd.id = router.id
@@ -705,8 +767,11 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
 
-        # 20. restart network with cleanup
+        # 21. restart network with cleanup
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
         self.network1.restart(self.apiclient, cleanup=True)
         routers = self.get_routers(self.network1.id)
         for router in routers:
@@ -719,3 +784,21 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
+
+        # 22. restart network with cleanup, makeredundant=true
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,"
+        #   verify the IPs in VR. eth0 -> guest nic, eth2 -> source nat IP, eth3 -> new ip 6
+        self.network1.restart(self.apiclient, cleanup=True, makeredundant=True)
+        routers = self.get_routers(self.network1.id)
+        for router in routers:
+            host = self.get_router_host(router)
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,")
+            guestIp, controlIp, sourcenatIp = self.get_router_ips(router)
+            self.verify_ip_address_in_router(router, host, guestIp, "eth0", True)
+            self.verify_ip_address_in_router(router, host, controlIp, "eth1", True)
+            self.verify_ip_address_in_router(router, host, sourcenatIp, "eth2", True)
+            self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth3", False)
+            self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth3", False)
+            self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth2|eth3")
diff --git a/test/integration/component/test_multiple_subnets_in_vpc.py b/test/integration/component/test_multiple_subnets_in_vpc.py
index a9e3696..eaa4216 100644
--- a/test/integration/component/test_multiple_subnets_in_vpc.py
+++ b/test/integration/component/test_multiple_subnets_in_vpc.py
@@ -35,6 +35,8 @@
                              NetworkOffering,
                              VPC,
                              VpcOffering,
+                             PrivateGateway,
+                             StaticNATRule,
                              NATRule,
                              PublicIPAddress,
                              PublicIpRange)
@@ -194,6 +196,35 @@
                 sourcenatIp = nic.ipaddress
         return controlIp, sourcenatIp, tier1_Ip, tier2_Ip
 
+    def verify_router_publicnic_state(self, router, host, publicNics):
+        command = '/opt/cloud/bin/checkrouter.sh | cut -d ":" -f2 |tr -d " "'
+        self.logger.debug("Executing command '%s'" % command)
+        result = get_process_status(
+            host.ipaddress,
+            host.port,
+            host.user,
+            host.password,
+            router.linklocalip,
+            command)
+        self.assertTrue(len(result) > 0, "Cannot get router %s redundant state" % router.name)
+        redundant_state = result[0]
+        self.logger.debug("router %s redudnant state is %s" % (router.name, redundant_state))
+        if redundant_state == "FAULT":
+            self.logger.debug("Skip as redundant_state is %s" % redundant_state)
+            return
+        elif redundant_state == "MASTER":
+            command = 'ip link show |grep BROADCAST | egrep "%s" |grep "state DOWN" |wc -l' % publicNics
+        elif redundant_state == "BACKUP":
+            command = 'ip link show |grep BROADCAST | egrep "%s" |grep "state UP" |wc -l' % publicNics
+        result = get_process_status(
+            host.ipaddress,
+            host.port,
+            host.user,
+            host.password,
+            router.linklocalip,
+            command)
+        self.assertTrue(len(result) > 0 and result[0] == "0", "Expected result is 0 but actual result is %s" % result[0])
+
     def verify_network_interfaces_in_router(self, router, host, expectedNics):
         command = 'ip link show |grep BROADCAST | cut -d ":" -f2 |tr -d " "|tr "\n" ","'
         self.logger.debug("Executing command '%s'" % command)
@@ -272,7 +303,7 @@
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth3 -> new ip 3, eth4 -> tier 2
 
         # 13. create new public ip range 2
-        # 14. get a free ip 4 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
+        # 14. get a free ip 4 in new ip range 2, assign to network, and enable static nat to vm 2 in tier 2
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth3 -> new ip 3, eth4 -> tier 2, eth5 -> new ip 4
         # 15. get a free ip 5 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
@@ -287,6 +318,23 @@
         # 18. release new ip 4
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth3 -> new ip 3, eth4 -> tier 2, eth5 -> new ip 6
+        # 19. release new ip 3
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth4 -> tier 2, eth5 -> new ip 6
+        # 20. restart tier1
+        # 22. restart VPC
+        # 23. Add private gateway
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth4 -> tier 2, eth5 -> new ip 6, eth3-> private gateway
+        # 24. reboot router
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
+        # 25. restart VPC with cleanup
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
+        # 26. restart VPC with cleanup, makeredundant=true
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
         """
 
         # Create new domain1
@@ -384,6 +432,7 @@
             self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
+            self.verify_router_publicnic_state(router, host, "eth1")
 
         # 4. get a free public ip, assign to network, and create port forwarding rules (ssh) to the vm
         ipaddress = PublicIPAddress.create(
@@ -409,6 +458,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress.ipaddress.ipaddress, "eth1", True)
+            self.verify_router_publicnic_state(router, host, "eth1")
 
         # 5. release the new ip
         ipaddress.delete(self.apiclient)
@@ -424,6 +474,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress.ipaddress.ipaddress, "eth1", False)
+            self.verify_router_publicnic_state(router, host, "eth1")
 
         # 6. create new public ip range 1
         self.services["publiciprange"]["zoneid"] = self.zone.id
@@ -451,10 +502,9 @@
             ipaddress=ip_address_1
         )
 
-        nat_rule = NATRule.create(
+        StaticNATRule.enable(
             self.apiclient,
-            self.virtual_machine1,
-            self.services["natrule"],
+            virtualmachineid=self.virtual_machine1.id,
             ipaddressid=ipaddress_1.ipaddress.id,
             networkid=vpc_tier_1.id
         )
@@ -470,6 +520,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 8. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -499,6 +550,7 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 9. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -529,6 +581,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 10. release new ip 2
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -546,6 +599,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 11. release new ip 1
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -562,6 +616,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 12. create a tier in the vpc, and create a vm in the tier.
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -581,7 +636,7 @@
         )
 
         try:
-            self.virtual_machine1 = VirtualMachine.create(
+            self.virtual_machine2 = VirtualMachine.create(
                 self.apiclient,
                 self.services["virtual_machine"],
                 accountid=self.account1.name,
@@ -604,6 +659,7 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 13. create new public ip range 2
         self.services["publiciprange"]["zoneid"] = self.zone.id
@@ -621,7 +677,7 @@
         )
         self.cleanup.append(self.public_ip_range2)
 
-        # 14. get a free ip 4 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
+        # 14. get a free ip 4 in new ip range 2, assign to network, and enable static nat to vm 2 in tier 2
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth3 -> new ip 3, eth4 -> tier 2, eth5 -> new ip 4
         ip_address_4 = self.get_free_ipaddress(self.public_ip_range2.vlan.id)
@@ -632,10 +688,9 @@
             ipaddress=ip_address_4
         )
 
-        nat_rule = NATRule.create(
+        StaticNATRule.enable(
             self.apiclient,
-            self.virtual_machine1,
-            self.services["natrule"],
+            virtualmachineid=self.virtual_machine2.id,
             ipaddressid=ipaddress_4.ipaddress.id,
             networkid=vpc_tier_2.id
         )
@@ -651,6 +706,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 15. get a free ip 5 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
@@ -665,7 +721,7 @@
 
         nat_rule = NATRule.create(
             self.apiclient,
-            self.virtual_machine1,
+            self.virtual_machine2,
             self.services["natrule"],
             ipaddressid=ipaddress_5.ipaddress.id,
             networkid=vpc_tier_2.id
@@ -682,6 +738,7 @@
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 16. get a free ip 6 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
@@ -696,7 +753,7 @@
 
         nat_rule = NATRule.create(
             self.apiclient,
-            self.virtual_machine1,
+            self.virtual_machine2,
             self.services["natrule"],
             ipaddressid=ipaddress_6.ipaddress.id,
             networkid=vpc_tier_2.id
@@ -714,6 +771,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 17. release new ip 5
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
@@ -733,6 +791,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 18. release new ip 4
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
@@ -751,9 +810,10 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 19. release new ip 3
-        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,eth5,"
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth4 -> tier 2, eth5 -> new ip 6
         ipaddress_3.delete(self.apiclient)
         routers = self.get_vpc_routers(self.vpc1.id)
@@ -768,6 +828,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth5")
 
         # 20. restart tier1
         vpc_tier_1.restart(self.apiclient)
@@ -781,6 +842,7 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth5")
 
         #21. restart tier2
         vpc_tier_2.restart(self.apiclient)
@@ -794,6 +856,7 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth5")
 
         # 22. restart VPC
         self.vpc1.restart(self.apiclient)
@@ -807,44 +870,84 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth5")
 
-        # reboot router
+        # 23. Add private gateway
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth4 -> tier 2, eth5 -> new ip 6, eth3-> private gateway
+        private_gateway_ip = "172.16." + str(random_subnet_number + 2) + ".1"
+        private_gateway = PrivateGateway.create(
+            self.apiclient,
+            gateway=private_gateway_ip,
+            ipaddress=private_gateway_ip,
+            netmask='255.255.255.0',
+            vlan=get_free_vlan(self.apiclient, self.zone.id)[1],
+            vpcid=self.vpc1.id
+        )
+        routers = self.get_vpc_routers(self.vpc1.id)
+        for router in routers:
+            host = self.get_router_host(router)
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth4,eth5,eth3,")
+            controlIp, sourcenatIp, tier1_Ip, tier2_Ip = self.get_vpc_router_ips(router)
+            self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
+            self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
+            self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
+            self.verify_ip_address_in_router(router, host, private_gateway_ip, "eth3", True)
+            self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", False)
+            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
+
+        # 24. reboot router
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
+        routers = self.get_vpc_routers(self.vpc1.id)
         for router in routers:
             cmd = rebootRouter.rebootRouterCmd()
             cmd.id = router.id
             self.apiclient.rebootRouter(cmd)
             router = self.get_router(router.id)
             host = self.get_router_host(router)
-            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,")
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,eth5,")
             controlIp, sourcenatIp, tier1_Ip, tier2_Ip = self.get_vpc_router_ips(router)
             self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth3", True)
-            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, private_gateway_ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth2|eth4")
 
-        # 23. restart VPC with cleanup
+        # 25. restart VPC with cleanup
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
         self.vpc1.restart(self.apiclient, cleanup=True)
         routers = self.get_vpc_routers(self.vpc1.id)
         for router in routers:
             host = self.get_router_host(router)
-            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,")
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,eth5,")
             controlIp, sourcenatIp, tier1_Ip, tier2_Ip = self.get_vpc_router_ips(router)
             self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth3", True)
-            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, private_gateway_ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth2|eth4")
 
-        # 24. restart VPC with cleanup, makeredundant=true
+        # 26. restart VPC with cleanup, makeredundant=true
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
         self.vpc1.restart(self.apiclient, cleanup=True, makeredundant=True)
         routers = self.get_vpc_routers(self.vpc1.id)
         for router in routers:
             host = self.get_router_host(router)
-            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,")
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,eth5,")
             controlIp, sourcenatIp, tier1_Ip, tier2_Ip = self.get_vpc_router_ips(router)
             self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth3", True)
-            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, private_gateway_ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth2|eth4")
diff --git a/test/integration/component/test_multiple_subnets_in_vpc_rvr.py b/test/integration/component/test_multiple_subnets_in_vpc_rvr.py
index 392620f..f6c0f52 100644
--- a/test/integration/component/test_multiple_subnets_in_vpc_rvr.py
+++ b/test/integration/component/test_multiple_subnets_in_vpc_rvr.py
@@ -35,6 +35,8 @@
                              NetworkOffering,
                              VPC,
                              VpcOffering,
+                             PrivateGateway,
+                             StaticNATRule,
                              NATRule,
                              PublicIPAddress,
                              PublicIpRange)
@@ -194,6 +196,35 @@
                 sourcenatIp = nic.ipaddress
         return controlIp, sourcenatIp, tier1_Ip, tier2_Ip
 
+    def verify_router_publicnic_state(self, router, host, publicNics):
+        command = '/opt/cloud/bin/checkrouter.sh | cut -d ":" -f2 |tr -d " "'
+        self.logger.debug("Executing command '%s'" % command)
+        result = get_process_status(
+            host.ipaddress,
+            host.port,
+            host.user,
+            host.password,
+            router.linklocalip,
+            command)
+        self.assertTrue(len(result) > 0, "Cannot get router %s redundant state" % router.name)
+        redundant_state = result[0]
+        self.logger.debug("router %s redudnant state is %s" % (router.name, redundant_state))
+        if redundant_state == "FAULT":
+            self.logger.debug("Skip as redundant_state is %s" % redundant_state)
+            return
+        elif redundant_state == "MASTER":
+            command = 'ip link show |grep BROADCAST | egrep "%s" |grep "state DOWN" |wc -l' % publicNics
+        elif redundant_state == "BACKUP":
+            command = 'ip link show |grep BROADCAST | egrep "%s" |grep "state UP" |wc -l' % publicNics
+        result = get_process_status(
+            host.ipaddress,
+            host.port,
+            host.user,
+            host.password,
+            router.linklocalip,
+            command)
+        self.assertTrue(len(result) > 0 and result[0] == "0", "Expected result is 0 but actual result is %s" % result[0])
+
     def verify_network_interfaces_in_router(self, router, host, expectedNics):
         command = 'ip link show |grep BROADCAST | cut -d ":" -f2 |tr -d " "|tr "\n" ","'
         self.logger.debug("Executing command '%s'" % command)
@@ -272,7 +303,7 @@
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth3 -> new ip 3, eth4 -> tier 2
 
         # 13. create new public ip range 2
-        # 14. get a free ip 4 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
+        # 14. get a free ip 4 in new ip range 2, assign to network, and enable static nat to vm 2 in tier 2
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth3 -> new ip 3, eth4 -> tier 2, eth5 -> new ip 4
         # 15. get a free ip 5 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
@@ -287,6 +318,23 @@
         # 18. release new ip 4
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth3 -> new ip 3, eth4 -> tier 2, eth5 -> new ip 6
+        # 19. release new ip 3
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth4 -> tier 2, eth5 -> new ip 6
+        # 20. restart tier1
+        # 22. restart VPC
+        # 23. Add private gateway
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth4 -> tier 2, eth5 -> new ip 6, eth3-> private gateway
+        # 24. reboot router
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
+        # 25. restart VPC with cleanup
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
+        # 26. restart VPC with cleanup, makeredundant=true
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
         """
 
         # Create new domain1
@@ -384,6 +432,7 @@
             self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
+            self.verify_router_publicnic_state(router, host, "eth1")
 
         # 4. get a free public ip, assign to network, and create port forwarding rules (ssh) to the vm
         ipaddress = PublicIPAddress.create(
@@ -409,6 +458,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress.ipaddress.ipaddress, "eth1", True)
+            self.verify_router_publicnic_state(router, host, "eth1")
 
         # 5. release the new ip
         ipaddress.delete(self.apiclient)
@@ -424,6 +474,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress.ipaddress.ipaddress, "eth1", False)
+            self.verify_router_publicnic_state(router, host, "eth1")
 
         # 6. create new public ip range 1
         self.services["publiciprange"]["zoneid"] = self.zone.id
@@ -451,10 +502,9 @@
             ipaddress=ip_address_1
         )
 
-        nat_rule = NATRule.create(
+        StaticNATRule.enable(
             self.apiclient,
-            self.virtual_machine1,
-            self.services["natrule"],
+            virtualmachineid=self.virtual_machine1.id,
             ipaddressid=ipaddress_1.ipaddress.id,
             networkid=vpc_tier_1.id
         )
@@ -470,6 +520,7 @@
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 8. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -499,6 +550,7 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 9. get a free ip in new ip range, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -529,6 +581,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 10. release new ip 2
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -546,6 +599,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 11. release new ip 1
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3"
@@ -562,6 +616,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_1.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_2.ipaddress.ipaddress, "eth3", False)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 12. create a tier in the vpc, and create a vm in the tier.
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,"
@@ -581,7 +636,7 @@
         )
 
         try:
-            self.virtual_machine1 = VirtualMachine.create(
+            self.virtual_machine2 = VirtualMachine.create(
                 self.apiclient,
                 self.services["virtual_machine"],
                 accountid=self.account1.name,
@@ -604,6 +659,7 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3")
 
         # 13. create new public ip range 2
         self.services["publiciprange"]["zoneid"] = self.zone.id
@@ -621,7 +677,7 @@
         )
         self.cleanup.append(self.public_ip_range2)
 
-        # 14. get a free ip 4 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
+        # 14. get a free ip 4 in new ip range 2, assign to network, and enable static nat to vm 2 in tier 2
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth3 -> new ip 3, eth4 -> tier 2, eth5 -> new ip 4
         ip_address_4 = self.get_free_ipaddress(self.public_ip_range2.vlan.id)
@@ -632,10 +688,9 @@
             ipaddress=ip_address_4
         )
 
-        nat_rule = NATRule.create(
+        StaticNATRule.enable(
             self.apiclient,
-            self.virtual_machine1,
-            self.services["natrule"],
+            virtualmachineid=self.virtual_machine2.id,
             ipaddressid=ipaddress_4.ipaddress.id,
             networkid=vpc_tier_2.id
         )
@@ -651,6 +706,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 15. get a free ip 5 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
@@ -665,7 +721,7 @@
 
         nat_rule = NATRule.create(
             self.apiclient,
-            self.virtual_machine1,
+            self.virtual_machine2,
             self.services["natrule"],
             ipaddressid=ipaddress_5.ipaddress.id,
             networkid=vpc_tier_2.id
@@ -682,6 +738,7 @@
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 16. get a free ip 6 in new ip range 2, assign to network, and create port forwarding rules (ssh) to the vm
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
@@ -696,7 +753,7 @@
 
         nat_rule = NATRule.create(
             self.apiclient,
-            self.virtual_machine1,
+            self.virtual_machine2,
             self.services["natrule"],
             ipaddressid=ipaddress_6.ipaddress.id,
             networkid=vpc_tier_2.id
@@ -714,6 +771,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 17. release new ip 5
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
@@ -733,6 +791,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", True)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 18. release new ip 4
         #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
@@ -751,9 +810,10 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
 
         # 19. release new ip 3
-        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,eth5,"
         #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth4 -> tier 2, eth5 -> new ip 6
         ipaddress_3.delete(self.apiclient)
         routers = self.get_vpc_routers(self.vpc1.id)
@@ -768,6 +828,7 @@
             self.verify_ip_address_in_router(router, host, ipaddress_4.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_5.ipaddress.ipaddress, "eth5", False)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth5")
 
         # 20. restart tier1
         vpc_tier_1.restart(self.apiclient)
@@ -781,6 +842,7 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth5")
 
         #21. restart tier2
         vpc_tier_2.restart(self.apiclient)
@@ -794,6 +856,7 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth5")
 
         # 22. restart VPC
         self.vpc1.restart(self.apiclient)
@@ -807,44 +870,84 @@
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth5")
 
-        # reboot router
+        # 23. Add private gateway
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> tier 1, eth4 -> tier 2, eth5 -> new ip 6, eth3-> private gateway
+        private_gateway_ip = "172.16." + str(random_subnet_number + 2) + ".1"
+        private_gateway = PrivateGateway.create(
+            self.apiclient,
+            gateway=private_gateway_ip,
+            ipaddress=private_gateway_ip,
+            netmask='255.255.255.0',
+            vlan=get_free_vlan(self.apiclient, self.zone.id)[1],
+            vpcid=self.vpc1.id
+        )
+        routers = self.get_vpc_routers(self.vpc1.id)
+        for router in routers:
+            host = self.get_router_host(router)
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth4,eth5,eth3,")
+            controlIp, sourcenatIp, tier1_Ip, tier2_Ip = self.get_vpc_router_ips(router)
+            self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
+            self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
+            self.verify_ip_address_in_router(router, host, tier1_Ip, "eth2", True)
+            self.verify_ip_address_in_router(router, host, private_gateway_ip, "eth3", True)
+            self.verify_ip_address_in_router(router, host, ipaddress_3.ipaddress.ipaddress, "eth3", False)
+            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth3|eth5")
+
+        # 24. reboot router
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
+        routers = self.get_vpc_routers(self.vpc1.id)
         for router in routers:
             cmd = rebootRouter.rebootRouterCmd()
             cmd.id = router.id
             self.apiclient.rebootRouter(cmd)
             router = self.get_router(router.id)
             host = self.get_router_host(router)
-            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,")
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,eth5,")
             controlIp, sourcenatIp, tier1_Ip, tier2_Ip = self.get_vpc_router_ips(router)
             self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth3", True)
-            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, private_gateway_ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth2|eth4")
 
-        # 23. restart VPC with cleanup
+        # 25. restart VPC with cleanup
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
         self.vpc1.restart(self.apiclient, cleanup=True)
         routers = self.get_vpc_routers(self.vpc1.id)
         for router in routers:
             host = self.get_router_host(router)
-            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,")
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,eth5,")
             controlIp, sourcenatIp, tier1_Ip, tier2_Ip = self.get_vpc_router_ips(router)
             self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth3", True)
-            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, private_gateway_ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth2|eth4")
 
-        # 24. restart VPC with cleanup, makeredundant=true
+        # 26. restart VPC with cleanup, makeredundant=true
+        #   verify the available nics in VR should be "eth0,eth1,eth2,eth3,eth4,eth5,"
+        #   verify the IPs in VR. eth1 -> source nat IP, eth2 -> new ip 6, eth3 -> tier 1, eth4 -> private gateway, eth5 -> tier 2
         self.vpc1.restart(self.apiclient, cleanup=True, makeredundant=True)
         routers = self.get_vpc_routers(self.vpc1.id)
         for router in routers:
             host = self.get_router_host(router)
-            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,")
+            self.verify_network_interfaces_in_router(router, host, "eth0,eth1,eth2,eth3,eth4,eth5,")
             controlIp, sourcenatIp, tier1_Ip, tier2_Ip = self.get_vpc_router_ips(router)
             self.verify_ip_address_in_router(router, host, controlIp, "eth0", True)
             self.verify_ip_address_in_router(router, host, sourcenatIp, "eth1", True)
             self.verify_ip_address_in_router(router, host, ipaddress_6.ipaddress.ipaddress, "eth2", True)
             self.verify_ip_address_in_router(router, host, tier1_Ip, "eth3", True)
-            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, private_gateway_ip, "eth4", True)
+            self.verify_ip_address_in_router(router, host, tier2_Ip, "eth5", True)
+            self.verify_router_publicnic_state(router, host, "eth1|eth2|eth4")