diff --git a/api/src/com/cloud/agent/api/routing/SetStaticNatRulesAnswer.java b/api/src/com/cloud/agent/api/routing/SetStaticNatRulesAnswer.java
index d7942e0cf7a..f393e8d31de 100644
--- a/api/src/com/cloud/agent/api/routing/SetStaticNatRulesAnswer.java
+++ b/api/src/com/cloud/agent/api/routing/SetStaticNatRulesAnswer.java
@@ -25,8 +25,8 @@ public class SetStaticNatRulesAnswer extends Answer {
super();
}
- public SetStaticNatRulesAnswer(SetStaticNatRulesCommand cmd, String[] results) {
- super(cmd, true, null);
+ public SetStaticNatRulesAnswer(SetStaticNatRulesCommand cmd, String[] results, Boolean success) {
+ super(cmd, success, null);
assert(cmd.getRules().length == results.length) : "Shouldn't the results match the commands?";
this.results = results;
diff --git a/api/src/com/cloud/agent/api/to/StaticNatRuleTO.java b/api/src/com/cloud/agent/api/to/StaticNatRuleTO.java
index c0359dbb0d7..a4845989d7f 100644
--- a/api/src/com/cloud/agent/api/to/StaticNatRuleTO.java
+++ b/api/src/com/cloud/agent/api/to/StaticNatRuleTO.java
@@ -41,8 +41,8 @@ public class StaticNatRuleTO extends FirewallRuleTO{
}
- protected StaticNatRuleTO(long id, String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked, boolean brandNew) {
- super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, FirewallRule.Purpose.StaticNat, null,0,0);
+ public StaticNatRuleTO(long id, String srcIp, Integer srcPortStart, Integer srcPortEnd, String dstIp, Integer dstPortStart, Integer dstPortEnd, String protocol, boolean revoked, boolean alreadyAdded) {
+ super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, alreadyAdded, FirewallRule.Purpose.StaticNat, null,0,0);
this.dstIp = dstIp;
}
diff --git a/api/src/com/cloud/api/commands/DisableStaticNatCmd.java b/api/src/com/cloud/api/commands/DisableStaticNatCmd.java
index 258cbd6b021..afc68cd7d66 100644
--- a/api/src/com/cloud/api/commands/DisableStaticNatCmd.java
+++ b/api/src/com/cloud/api/commands/DisableStaticNatCmd.java
@@ -76,7 +76,7 @@ public class DisableStaticNatCmd extends BaseAsyncCmd {
@Override
public void execute() throws ResourceUnavailableException {
- boolean result = _rulesService.disableOneToOneNat(ipAddressId);
+ boolean result = _rulesService.disableStaticNat(ipAddressId);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
diff --git a/api/src/com/cloud/api/commands/EnableStaticNatCmd.java b/api/src/com/cloud/api/commands/EnableStaticNatCmd.java
index 3b6262b8259..e8f1879e7ab 100644
--- a/api/src/com/cloud/api/commands/EnableStaticNatCmd.java
+++ b/api/src/com/cloud/api/commands/EnableStaticNatCmd.java
@@ -80,7 +80,7 @@ public class EnableStaticNatCmd extends BaseCmd{
@Override
public void execute(){
try {
- boolean result = _rulesService.enableOneToOneNat(ipAddressId, virtualMachineId);
+ boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);
diff --git a/api/src/com/cloud/network/element/NetworkElement.java b/api/src/com/cloud/network/element/NetworkElement.java
index c14b06db9b6..a4f42dffd9d 100644
--- a/api/src/com/cloud/network/element/NetworkElement.java
+++ b/api/src/com/cloud/network/element/NetworkElement.java
@@ -35,6 +35,7 @@ import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.PublicIpAddress;
import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.StaticNat;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.NicProfile;
@@ -132,5 +133,14 @@ public interface NetworkElement extends Adapter {
* @throws ResourceUnavailableException
*/
boolean applyRules(Network network, List extends FirewallRule> rules) throws ResourceUnavailableException;
+
+ /**
+ * Creates static nat rule (public IP to private IP mapping) on the network element
+ * @param config
+ * @param rules
+ * @return
+ * @throws ResourceUnavailableException
+ */
+ boolean applyStaticNats(Network config, List extends StaticNat> rules) throws ResourceUnavailableException;
}
diff --git a/api/src/com/cloud/network/rules/RulesService.java b/api/src/com/cloud/network/rules/RulesService.java
index 7af02a291fd..61e912ae5e0 100644
--- a/api/src/com/cloud/network/rules/RulesService.java
+++ b/api/src/com/cloud/network/rules/RulesService.java
@@ -54,9 +54,9 @@ public interface RulesService {
boolean applyPortForwardingRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;
- boolean enableOneToOneNat(long ipAddressId, long vmId) throws NetworkRuleConflictException;
+ boolean enableStaticNat(long ipAddressId, long vmId) throws NetworkRuleConflictException;
- boolean disableOneToOneNat(long ipAddressId) throws ResourceUnavailableException;
+ boolean disableStaticNat(long ipAddressId) throws ResourceUnavailableException;
PortForwardingRule getPortForwardigRule(long ruleId);
FirewallRule getFirewallRule(long ruleId);
diff --git a/api/src/com/cloud/network/rules/StaticNat.java b/api/src/com/cloud/network/rules/StaticNat.java
new file mode 100644
index 00000000000..430eaf42094
--- /dev/null
+++ b/api/src/com/cloud/network/rules/StaticNat.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.cloud.network.rules;
+
+
+public interface StaticNat{
+
+ long getAccountId();
+
+ long getDomainId();
+
+ long getNetworkId();
+
+ long getSourceIpAddressId();
+
+ String getDestIpAddress();
+
+ boolean isForRevoke();
+}
diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
index f8ff6766ecb..d51ca001c1e 100755
--- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
+++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
@@ -193,6 +193,7 @@ public class VirtualRoutingResource implements Manager {
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
String[] results = new String[cmd.getRules().length];
int i = 0;
+ boolean endResult = true;
for (StaticNatRuleTO rule : cmd.getRules()) {
String result = null;
final Script command = new Script(_firewallPath, _timeout, s_logger);
@@ -207,10 +208,15 @@ public class VirtualRoutingResource implements Manager {
command.add(" -G ") ;
result = command.execute();
- results[i++] = (!(result == null || result.isEmpty())) ? "Failed" : null;
+ if (result == null || result.isEmpty()) {
+ results[i++] = "Failed";
+ endResult = false;
+ } else {
+ results[i++] = null;
+ }
}
- return new SetStaticNatRulesAnswer(cmd, results);
+ return new SetStaticNatRulesAnswer(cmd, results, endResult);
}
diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index 0a720014021..a5fcc203484 100644
--- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -1269,6 +1269,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
//String args = routerIp;
String[] results = new String[cmd.getRules().length];
int i = 0;
+ boolean endResult = true;
for (StaticNatRuleTO rule : cmd.getRules()) {
//1:1 NAT needs instanceip;publicip;domrip;op
StringBuilder args = new StringBuilder();
@@ -1276,15 +1277,23 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
args.append(rule.revoked() ? " -D " : " -A ");
args.append(" -l ").append(rule.getSrcIp());
args.append(" -r ").append(rule.getDstIp());
- args.append(" -P ").append(rule.getProtocol().toLowerCase());
+ if (rule.getProtocol() != null) {
+ args.append(" -P ").append(rule.getProtocol().toLowerCase());
+ }
+
args.append(" -d ").append(rule.getStringSrcPortRange());
args.append(" -G ");
String result = callHostPlugin(conn, "vmops", "setFirewallRule", "args", args.toString());
- results[i++] = (result == null || result.isEmpty()) ? "Failed" : null;
+ if (result == null || result.isEmpty()) {
+ results[i++] = "Failed";
+ endResult = false;
+ } else {
+ results[i++] = null;
+ }
}
- return new SetStaticNatRulesAnswer(cmd, results);
+ return new SetStaticNatRulesAnswer(cmd, results, endResult);
}
protected Answer execute(final LoadBalancerConfigCommand cmd) {
diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java
index c46f2b6728e..163c428cc10 100644
--- a/server/src/com/cloud/network/NetworkManager.java
+++ b/server/src/com/cloud/network/NetworkManager.java
@@ -35,6 +35,7 @@ import com.cloud.network.Networks.TrafficType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpn.PasswordResetElement;
import com.cloud.network.vpn.RemoteAccessVpnElement;
import com.cloud.offerings.NetworkOfferingVO;
@@ -210,4 +211,6 @@ public interface NetworkManager extends NetworkService {
String getGlobalGuestDomainSuffix();
String getStartIpAddress(long networkId);
+
+ boolean applyStaticNats(List extends StaticNat> staticNats, boolean continueOnError) throws ResourceUnavailableException;
}
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index e30225f3a69..3cb30dea9af 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -102,6 +102,7 @@ import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.StaticNat;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.RulesManager;
@@ -3190,4 +3191,29 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return startIP;
}
+
+ @Override
+ public boolean applyStaticNats(List extends StaticNat> staticNats, boolean continueOnError) throws ResourceUnavailableException {
+ if (staticNats == null || staticNats.size() == 0) {
+ s_logger.debug("There are no static nat rules for the network elements");
+ return true;
+ }
+
+ boolean success = true;
+ Network network = _networksDao.findById(staticNats.get(0).getNetworkId());
+ for (NetworkElement ne : _networkElements) {
+ try {
+ boolean handled = ne.applyStaticNats(network, staticNats);
+ s_logger.debug("Static Nat for network " + network.getId() + " were " + (handled ? "" : " not") + " handled by " + ne.getName());
+ } catch (ResourceUnavailableException e) {
+ if (!continueOnError) {
+ throw e;
+ }
+ s_logger.warn("Problems with " + ne.getName() + " but pushing on", e);
+ success = false;
+ }
+ }
+
+ return success;
+ }
}
diff --git a/server/src/com/cloud/network/element/DhcpElement.java b/server/src/com/cloud/network/element/DhcpElement.java
index 97dff205318..42efc838cad 100644
--- a/server/src/com/cloud/network/element/DhcpElement.java
+++ b/server/src/com/cloud/network/element/DhcpElement.java
@@ -45,6 +45,7 @@ import com.cloud.network.dao.NetworkDao;
import com.cloud.network.router.VirtualNetworkApplianceManager;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpn.PasswordResetElement;
import com.cloud.offering.NetworkOffering;
import com.cloud.user.AccountManager;
@@ -245,4 +246,9 @@ public class DhcpElement extends AdapterBase implements NetworkElement, Password
return _routerMgr.savePasswordToRouter(network, nic, uservm);
}
+
+ @Override
+ public boolean applyStaticNats(Network config, List extends StaticNat> rules) throws ResourceUnavailableException {
+ return false;
+ }
}
diff --git a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java
index 63824448330..c096325814d 100644
--- a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java
+++ b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java
@@ -42,6 +42,7 @@ import com.cloud.network.PublicIpAddress;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.lb.ElasticLoadBalancerManager;
import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.StaticNat;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.utils.component.AdapterBase;
@@ -166,4 +167,9 @@ public class ElasticLoadBalancerElement extends AdapterBase implements NetworkEl
}
return true;
}
+
+ @Override
+ public boolean applyStaticNats(Network config, List extends StaticNat> rules) throws ResourceUnavailableException {
+ return false;
+ }
}
diff --git a/server/src/com/cloud/network/element/OvsElement.java b/server/src/com/cloud/network/element/OvsElement.java
index ed51c0291bc..4cfe1ef50e2 100644
--- a/server/src/com/cloud/network/element/OvsElement.java
+++ b/server/src/com/cloud/network/element/OvsElement.java
@@ -38,6 +38,7 @@ import com.cloud.network.element.NetworkElement;
import com.cloud.network.ovs.OvsNetworkManager;
import com.cloud.network.ovs.OvsTunnelManager;
import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.StaticNat;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
@@ -142,5 +143,10 @@ public class OvsElement extends AdapterBase implements NetworkElement {
throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
+
+ @Override
+ public boolean applyStaticNats(Network config, List extends StaticNat> rules) throws ResourceUnavailableException {
+ return false;
+ }
}
diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java
index d4bfa290c99..f7fe4354b53 100644
--- a/server/src/com/cloud/network/element/VirtualRouterElement.java
+++ b/server/src/com/cloud/network/element/VirtualRouterElement.java
@@ -49,6 +49,7 @@ import com.cloud.network.router.VirtualNetworkApplianceManager;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.RulesManager;
+import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpn.RemoteAccessVpnElement;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingDao;
@@ -284,4 +285,21 @@ public class VirtualRouterElement extends DhcpElement implements NetworkElement,
return capabilities;
}
+
+ @Override
+ public boolean applyStaticNats(Network config, List extends StaticNat> rules) throws ResourceUnavailableException {
+ DataCenter dc = _configMgr.getZone(config.getDataCenterId());
+ if (canHandle(config.getGuestType(),dc)) {
+ long networkId = config.getId();
+ List routers = _routerDao.findByNetwork(networkId);
+ if (routers == null || routers.isEmpty()) {
+ s_logger.debug("Virtual router elemnt doesn't need to apply static nat on the backend; virtual router doesn't exist in the network " + config.getId());
+ return true;
+ }
+
+ return _routerMgr.applyStaticNats(config, rules);
+ } else {
+ return true;
+ }
+ }
}
diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
index ea9712e33cb..d6105b65d79 100644
--- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
+++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
@@ -317,7 +317,6 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
throw new InvalidParameterValueException("Protocol " + proto + " is currently supported only for rules with purpose " + Purpose.Firewall);
}
}
-
}
@Override
@@ -516,4 +515,5 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
return rules.size() == 0;
}
+
}
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
index 2fc0902d21f..dbae1f1e4a3 100644
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
@@ -30,6 +30,7 @@ import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.VirtualNetworkApplianceService;
import com.cloud.network.VpnUser;
import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.StaticNat;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.uservm.UserVm;
@@ -89,4 +90,7 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
VirtualRouter stop(VirtualRouter router, boolean forced, User callingUser, Account callingAccount) throws ConcurrentOperationException, ResourceUnavailableException;
String getDnsBasicZoneUpdate();
+
+ boolean applyStaticNats(Network network, List extends StaticNat> rules) throws ResourceUnavailableException;
+
}
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index bf60675a1ee..90a40472733 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -135,6 +135,7 @@ import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.RulesManager;
+import com.cloud.network.rules.StaticNat;
import com.cloud.network.rules.StaticNatRule;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offering.NetworkOffering;
@@ -2087,8 +2088,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
public boolean applyFirewallRules(Network network, List extends FirewallRule> rules) throws ResourceUnavailableException {
List routers = _routerDao.findByNetwork(network.getId());
if (routers == null || routers.isEmpty()) {
- s_logger.warn("Unable to apply lb rules, virtual router doesn't exist in the network " + network.getId());
- throw new ResourceUnavailableException("Unable to apply lb rules", DataCenter.class, network.getDataCenterId());
+ s_logger.warn("Unable to apply firewall rules, virtual router doesn't exist in the network " + network.getId());
+ throw new ResourceUnavailableException("Unable to apply firewall rules", DataCenter.class, network.getDataCenterId());
}
boolean result = true;
@@ -2197,4 +2198,62 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
return _dnsBasicZoneUpdates;
}
+
+ @Override
+ public boolean applyStaticNats(Network network, List extends StaticNat> rules) throws ResourceUnavailableException {
+ List routers = _routerDao.findByNetwork(network.getId());
+ if (routers == null || routers.isEmpty()) {
+ s_logger.warn("Unable to create static nat, virtual router doesn't exist in the network " + network.getId());
+ throw new ResourceUnavailableException("Unable to create static nat", DataCenter.class, network.getDataCenterId());
+ }
+
+ boolean result = true;
+ for (DomainRouterVO router : routers) {
+ if (router.getState() == State.Running) {
+ s_logger.debug("Applying " + rules.size() + " static nat in network " + network);
+ result = applyStaticNat(router, rules);
+
+ //If rules fail to apply on one domR, no need to proceed with the rest
+ if (!result) {
+ throw new ResourceUnavailableException("Unable to apply static nat on router ", VirtualRouter.class, router.getId());
+ }
+
+ } else if (router.getState() == State.Stopped || router.getState() == State.Stopping) {
+ s_logger.debug("Router is in " + router.getState() + ", so not sending apply firewall rules commands to the backend");
+ } else {
+ s_logger.warn("Unable to apply static nat, virtual router is not in the right state " + router.getState());
+ throw new ResourceUnavailableException("Unable to apply static nat, virtual router is not in the right state", VirtualRouter.class, router.getId());
+ }
+ }
+
+ return result;
+ }
+
+
+ protected boolean applyStaticNat(DomainRouterVO router, List extends StaticNat> rules) throws ResourceUnavailableException {
+ Commands cmds = new Commands(OnError.Continue);
+ createApplyStaticNatCommands(rules, router, cmds);
+ // Send commands to router
+ return sendCommandsToRouter(router, cmds);
+ }
+
+ private void createApplyStaticNatCommands(List extends StaticNat> rules, DomainRouterVO router, Commands cmds) {
+ List rulesTO = null;
+ if (rules != null) {
+ rulesTO = new ArrayList();
+ for (StaticNat rule : rules) {
+ IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
+ StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
+ rulesTO.add(ruleTO);
+ }
+ }
+
+ SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rulesTO);
+ cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress());
+ cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, router.getGuestIpAddress());
+ cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
+ DataCenterVO dcVo = _dcDao.findById(router.getDataCenterIdToDeployIn());
+ cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString());
+ cmds.addCommand(cmd);
+ }
}
diff --git a/server/src/com/cloud/network/rules/RulesManager.java b/server/src/com/cloud/network/rules/RulesManager.java
index 8872d2c1b95..1f83b1ca320 100644
--- a/server/src/com/cloud/network/rules/RulesManager.java
+++ b/server/src/com/cloud/network/rules/RulesManager.java
@@ -66,6 +66,8 @@ public interface RulesManager extends RulesService {
boolean releasePorts(long ipId, String protocol, FirewallRule.Purpose purpose, int... ports);
List listByNetworkId(long networkId);
+
+ boolean applyStaticNat(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke);
}
diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java
index 972d7816e51..d1130dad42b 100755
--- a/server/src/com/cloud/network/rules/RulesManagerImpl.java
+++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java
@@ -291,7 +291,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@Override
- public boolean enableOneToOneNat(long ipId, long vmId) throws NetworkRuleConflictException {
+ public boolean enableStaticNat(long ipId, long vmId) throws NetworkRuleConflictException {
Account caller = UserContext.current().getCaller();
@@ -351,7 +351,22 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
ipAddress.setOneToOneNat(true);
ipAddress.setAssociatedWithVmId(vmId);
- return _ipAddressDao.update(ipAddress.getId(), ipAddress);
+ if (_ipAddressDao.update(ipAddress.getId(), ipAddress)) {
+ //enable static nat on the backend
+ s_logger.trace("Enabling static nat for ip address " + ipAddress + " and vm id=" + vmId + " on the backend");
+ if (applyStaticNat(ipId, false, caller, false)) {
+ return true;
+ } else {
+ ipAddress.setOneToOneNat(false);
+ ipAddress.setAssociatedWithVmId(null);
+ _ipAddressDao.update(ipAddress.getId(), ipAddress);
+ s_logger.warn("Failed to enable static nat rule for ip address " + ipId + " on the backend");
+ return false;
+ }
+ } else {
+ s_logger.warn("Failed to update ip address " + ipAddress + " in the DB as a part of enableStaticNat");
+ return false;
+ }
}
@@ -797,10 +812,14 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
s_logger.debug("Releasing " + staticNatRules.size() + " static nat rules for ip id=" + ipId);
}
+
for (FirewallRuleVO rule : staticNatRules) {
// Mark all static nat rules as Revoke, but don't revoke them yet
revokeStaticNatRuleInternal(rule.getId(), caller, userId, false);
}
+
+ //revoke static nat for the ip address
+ boolean staticNatRevoked = applyStaticNat(ipId, false, caller, true);
// revoke all port forwarding rules
applyPortForwardingRules(ipId, true, caller);
@@ -816,7 +835,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
s_logger.debug("Successfully released rules for ip id=" + ipId + " and # of rules now = " + rules.size());
}
- return rules.size() == 0;
+ return (rules.size() == 0 && staticNatRevoked);
}
@Override
@@ -955,7 +974,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@Override
- public boolean disableOneToOneNat(long ipId) throws ResourceUnavailableException {
+ public boolean disableStaticNat(long ipId) throws ResourceUnavailableException {
boolean success = true;
Account caller = UserContext.current().getCaller();
@@ -1007,4 +1026,50 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return new StaticNatRuleImpl(ruleVO, guestNic.getIp4Address());
}
+ @Override
+ public boolean applyStaticNat(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke) {
+
+ List staticNats = new ArrayList();
+ IpAddress sourceIp = _ipAddressDao.findById(sourceIpId);
+
+ Long networkId = sourceIp.getAssociatedWithNetworkId();
+ if (networkId == null) {
+ throw new CloudRuntimeException("Ip address is not associated with any network");
+ }
+
+ UserVmVO vm = _vmDao.findById(sourceIp.getAssociatedWithVmId());
+ Network network = _networkMgr.getNetwork(networkId);
+ if (network == null) {
+ throw new CloudRuntimeException("Unable to find ip address to map to in vm id=" + vm.getId());
+ }
+
+ if (!sourceIp.isOneToOneNat()) {
+ s_logger.debug("Source ip id=" + sourceIpId + " is not one to one nat");
+ return true;
+ }
+
+ if (caller != null) {
+ _accountMgr.checkAccess(caller, sourceIp);
+ }
+
+ //create new static nat rule
+ // Get nic IP4 address
+ Nic guestNic = _networkMgr.getNicInNetwork(sourceIp.getAssociatedWithVmId(), networkId);
+ assert (guestNic != null && guestNic.getIp4Address() != null) : "Vm doesn't belong to network associated with ipAddress or ip4 address is null...how is it possible?";
+ String dstIp = guestNic.getIp4Address();
+ StaticNatImpl staticNat = new StaticNatImpl(sourceIp.getAccountId(), sourceIp.getDomainId(), networkId, sourceIpId, dstIp, forRevoke);
+ staticNats.add(staticNat);
+
+ try {
+ if (!_networkMgr.applyStaticNats(staticNats, continueOnError)) {
+ return false;
+ }
+ } catch (ResourceUnavailableException ex) {
+ s_logger.warn("Failed to create static nat rule due to ", ex);
+ return false;
+ }
+
+ return true;
+ }
+
}
diff --git a/server/src/com/cloud/network/rules/StaticNatImpl.java b/server/src/com/cloud/network/rules/StaticNatImpl.java
new file mode 100644
index 00000000000..b8ebf2a002e
--- /dev/null
+++ b/server/src/com/cloud/network/rules/StaticNatImpl.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.cloud.network.rules;
+
+public class StaticNatImpl implements StaticNat{
+ long accountId;
+ long domainId;
+ long networkId;
+ long sourceIpAddressId;
+ String destIpAddress;
+ boolean forRevoke;
+
+
+
+ public StaticNatImpl(long accountId, long domainId, long networkId, long sourceIpAddressId, String destIpAddress, boolean forRevoke) {
+ super();
+ this.accountId = accountId;
+ this.domainId = domainId;
+ this.networkId = networkId;
+ this.sourceIpAddressId = sourceIpAddressId;
+ this.destIpAddress = destIpAddress;
+ this.forRevoke = forRevoke;
+ }
+
+ @Override
+ public long getAccountId() {
+ return accountId;
+ }
+
+ @Override
+ public long getDomainId() {
+ return domainId;
+ }
+
+ @Override
+ public long getNetworkId() {
+ return networkId;
+ }
+
+ @Override
+ public long getSourceIpAddressId() {
+ return sourceIpAddressId;
+ }
+
+ @Override
+ public String getDestIpAddress() {
+ return destIpAddress;
+ }
+
+ @Override
+ public boolean isForRevoke() {
+ return forRevoke;
+ }
+
+}
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index a9cd7c16841..9866e252e80 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -1254,7 +1254,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(vmId);
try {
if (ip != null) {
- if (_rulesMgr.disableOneToOneNat(ip.getId())) {
+ if (_rulesMgr.disableStaticNat(ip.getId())) {
s_logger.debug("Disabled 1-1 nat for ip address " + ip + " as a part of vm id=" + vmId + " expunge");
} else {
s_logger.warn("Failed to disable static nat for ip address " + ip + " as a part of vm id=" + vmId + " expunge");