diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index c347dc11073..8a106fffc42 100755
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -107,6 +107,9 @@ createPortForwardingRule=com.cloud.api.commands.CreatePortForwardingRuleCmd;15
deletePortForwardingRule=com.cloud.api.commands.DeletePortForwardingRuleCmd;15
updatePortForwardingRule=com.cloud.api.commands.UpdatePortForwardingRuleCmd;15
+#### NAT commands
+createIpForwardingRule=com.cloud.api.commands.CreateIpForwardingRuleCmd;15
+
#### load balancer commands
createLoadBalancerRule=com.cloud.api.commands.CreateLoadBalancerRuleCmd;15
deleteLoadBalancerRule=com.cloud.api.commands.DeleteLoadBalancerRuleCmd;15
diff --git a/core/src/com/cloud/network/IprulePortrangeMapVO.java b/core/src/com/cloud/network/IprulePortrangeMapVO.java
new file mode 100644
index 00000000000..2304a7d854a
--- /dev/null
+++ b/core/src/com/cloud/network/IprulePortrangeMapVO.java
@@ -0,0 +1,88 @@
+/**
+ * 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;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name=("iprule_portrange_map"))
+public class IprulePortrangeMapVO {
+ @Id
+ @GeneratedValue(strategy=GenerationType.IDENTITY)
+ @Column(name="id")
+ private Long id;
+
+ @Column(name="fwrule_id")
+ private Long fwruleId;
+
+ @Column(name="start_port")
+ private String startPort = null;
+
+ @Column(name="end_port")
+ private String endPort = null;
+
+ public IprulePortrangeMapVO() {
+ }
+
+ public IprulePortrangeMapVO(Long id, Long ruleId, String startPort, String endPort) {
+ this.id = id;
+ this.fwruleId = ruleId;
+ this.startPort = startPort;
+ this.endPort = endPort;
+
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Long getFwruleId() {
+ return fwruleId;
+ }
+
+ public void setFwruleId(Long fwruleId) {
+ this.fwruleId = fwruleId;
+ }
+
+ public String getStartPort() {
+ return startPort;
+ }
+
+ public void setStartPort(String startPort) {
+ this.startPort = startPort;
+ }
+
+ public String getEndPort() {
+ return endPort;
+ }
+
+ public void setEndPort(String endPort) {
+ this.endPort = endPort;
+ }
+}
+
diff --git a/core/src/com/cloud/network/dao/FirewallRulesDao.java b/core/src/com/cloud/network/dao/FirewallRulesDao.java
index 7db42df3bf6..ef2bd4f0ed4 100644
--- a/core/src/com/cloud/network/dao/FirewallRulesDao.java
+++ b/core/src/com/cloud/network/dao/FirewallRulesDao.java
@@ -44,5 +44,6 @@ public interface FirewallRulesDao extends GenericDao {
public List listBySecurityGroupId(long securityGroupId);
public List listByLoadBalancerId(long loadBalancerId);
public List listForwardingByPubAndPrivIp(boolean forwarding, String publicIPAddress, String privateIp);
- public FirewallRuleVO findByGroupAndPrivateIp(long groupId, String privateIp, boolean forwarding);
+ public FirewallRuleVO findByGroupAndPrivateIp(long groupId, String privateIp, boolean forwarding);
+ List findByPublicIpPrivateIpForNatRule(String publicIp,String privateIp);
}
diff --git a/core/src/com/cloud/network/dao/FirewallRulesDaoImpl.java b/core/src/com/cloud/network/dao/FirewallRulesDaoImpl.java
index 55bce08b553..be3dee36020 100644
--- a/core/src/com/cloud/network/dao/FirewallRulesDaoImpl.java
+++ b/core/src/com/cloud/network/dao/FirewallRulesDaoImpl.java
@@ -55,7 +55,8 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i
protected SearchBuilder FWByPrivateIPSearch;
protected SearchBuilder RulesExcludingPubIpPort;
protected SearchBuilder FWByGroupId;
- protected SearchBuilder FWByGroupAndPrivateIp;
+ protected SearchBuilder FWByGroupAndPrivateIp;
+ protected SearchBuilder FWByPrivateIpPrivatePortPublicIpPublicPortSearch;
protected FirewallRulesDaoImpl() {
}
@@ -124,6 +125,13 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i
FWByGroupAndPrivateIp.and("forwarding", FWByGroupAndPrivateIp.entity().isForwarding(), SearchCriteria.Op.EQ);
FWByGroupAndPrivateIp.done();
+ FWByPrivateIpPrivatePortPublicIpPublicPortSearch = createSearchBuilder();
+ FWByPrivateIpPrivatePortPublicIpPublicPortSearch.and("publicIpAddress", FWByPrivateIpPrivatePortPublicIpPublicPortSearch.entity().getPublicIpAddress(), SearchCriteria.Op.EQ);
+ FWByPrivateIpPrivatePortPublicIpPublicPortSearch.and("privateIpAddress", FWByPrivateIpPrivatePortPublicIpPublicPortSearch.entity().getPrivateIpAddress(), SearchCriteria.Op.EQ);
+ FWByPrivateIpPrivatePortPublicIpPublicPortSearch.and("privatePort", FWByPrivateIpPrivatePortPublicIpPublicPortSearch.entity().getPrivatePort(), SearchCriteria.Op.NULL);
+ FWByPrivateIpPrivatePortPublicIpPublicPortSearch.and("publicPort", FWByPrivateIpPrivatePortPublicIpPublicPortSearch.entity().getPublicPort(), SearchCriteria.Op.NULL);
+ FWByPrivateIpPrivatePortPublicIpPublicPortSearch.done();
+
return true;
}
@@ -306,5 +314,13 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i
sc.setParameters("forwarding", forwarding);
return findOneBy(sc);
+ }
+
+ @Override
+ public List findByPublicIpPrivateIpForNatRule(String publicIp, String privateIp){
+ SearchCriteria sc = FWByPrivateIpPrivatePortPublicIpPublicPortSearch.create();
+ sc.setParameters("publicIpAddress", publicIp);
+ sc.setParameters("privateIpAddress", privateIp);
+ return listBy(sc);
}
}
diff --git a/core/src/com/cloud/network/dao/IprulePortrangeMapDao.java b/core/src/com/cloud/network/dao/IprulePortrangeMapDao.java
new file mode 100644
index 00000000000..00da1107718
--- /dev/null
+++ b/core/src/com/cloud/network/dao/IprulePortrangeMapDao.java
@@ -0,0 +1,30 @@
+/**
+ * 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.dao;
+
+import java.util.List;
+
+import com.cloud.network.IprulePortrangeMapVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface IprulePortrangeMapDao extends GenericDao {
+
+ List listPortRecordsForRule(Long ruleId);
+
+}
diff --git a/core/src/com/cloud/network/dao/IprulePortrangeMapDaoImpl.java b/core/src/com/cloud/network/dao/IprulePortrangeMapDaoImpl.java
new file mode 100644
index 00000000000..bbd5e1eec86
--- /dev/null
+++ b/core/src/com/cloud/network/dao/IprulePortrangeMapDaoImpl.java
@@ -0,0 +1,57 @@
+/**
+ * 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.dao;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.network.FirewallRuleVO;
+import com.cloud.network.IprulePortrangeMapVO;
+import com.cloud.network.LoadBalancerVO;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+
+@Local(value={IprulePortrangeMapDao.class})
+public class IprulePortrangeMapDaoImpl extends GenericDaoBase implements IprulePortrangeMapDao {
+ private static final Logger s_logger = Logger.getLogger(IprulePortrangeMapDaoImpl.class);
+
+ private final SearchBuilder ListByForwardingRule;
+
+ protected IprulePortrangeMapDaoImpl() {
+ ListByForwardingRule = createSearchBuilder();
+ ListByForwardingRule.and("ruleId", ListByForwardingRule.entity().getFwruleId(), SearchCriteria.Op.EQ);
+ ListByForwardingRule.done();
+
+ }
+
+ @Override
+ public List listPortRecordsForRule(Long ruleId) {
+ SearchCriteria sc = ListByForwardingRule.create();
+ sc.setParameters("ruleId", ruleId);
+ return listBy(sc);
+ }
+}
diff --git a/server/src/com/cloud/api/commands/CreateIpForwardingRuleCmd.java b/server/src/com/cloud/api/commands/CreateIpForwardingRuleCmd.java
new file mode 100644
index 00000000000..51439062aab
--- /dev/null
+++ b/server/src/com/cloud/api/commands/CreateIpForwardingRuleCmd.java
@@ -0,0 +1,93 @@
+/**
+ * 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.api.commands;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.api.ApiConstants;
+import com.cloud.api.ApiResponseHelper;
+import com.cloud.api.BaseCmd;
+import com.cloud.api.Implementation;
+import com.cloud.api.Parameter;
+import com.cloud.api.ServerApiException;
+import com.cloud.api.response.FirewallRuleResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.network.FirewallRuleVO;
+
+@Implementation(description="Creates an ip forwarding rule")
+public class CreateIpForwardingRuleCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(CreateIpForwardingRuleCmd.class.getName());
+
+ private static final String s_name = "createipforwardingruleresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, required=true, description="the public IP address of the forwarding rule, already associated via associateIp")
+ private String ipAddress;
+
+ @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, required=true, description="the ID of the virtual machine for the forwarding rule")
+ private Long virtualMachineId;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public Long getVirtualMachineId() {
+ return virtualMachineId;
+ }
+
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute() throws ServerApiException, InvalidParameterValueException, PermissionDeniedException, InsufficientAddressCapacityException, InsufficientCapacityException, ConcurrentOperationException{
+ try {
+ FirewallRuleVO result = _networkMgr.createIpForwardingRule(this);
+ if (result != null) {
+ FirewallRuleResponse fwResponse = ApiResponseHelper.createFirewallRuleResponse(result);
+ fwResponse.setResponseName(getName());
+ this.setResponseObject(fwResponse);
+ } else {
+ //throw new ServerApiException(NET_CREATE_IPFW_RULE_ERROR, "An existing rule for ipAddress / port / protocol of " + ipAddress + " / " + publicPort + " / " + protocol + " exits.");
+ }
+ } catch (NetworkRuleConflictException ex) {
+ throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
+ }
+ }
+
+}
diff --git a/server/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java b/server/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java
index 67c3dd603b5..cd988eef39d 100644
--- a/server/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java
+++ b/server/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java
@@ -36,8 +36,8 @@ import com.cloud.exception.PermissionDeniedException;
import com.cloud.network.FirewallRuleVO;
@Implementation(description="Creates a port forwarding rule")
-public class CreateIPForwardingRuleCmd extends BaseCmd {
- public static final Logger s_logger = Logger.getLogger(CreateIPForwardingRuleCmd.class.getName());
+public class CreatePortForwardingRuleCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(CreatePortForwardingRuleCmd.class.getName());
private static final String s_name = "createportforwardingruleresponse";
diff --git a/server/src/com/cloud/api/commands/DeleteIpForwardingRuleCmd.java b/server/src/com/cloud/api/commands/DeleteIpForwardingRuleCmd.java
new file mode 100644
index 00000000000..8f77eb1b57b
--- /dev/null
+++ b/server/src/com/cloud/api/commands/DeleteIpForwardingRuleCmd.java
@@ -0,0 +1,85 @@
+/**
+ * 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.api.commands;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.api.ApiConstants;
+import com.cloud.api.ApiResponseHelper;
+import com.cloud.api.BaseCmd;
+import com.cloud.api.Implementation;
+import com.cloud.api.Parameter;
+import com.cloud.api.ServerApiException;
+import com.cloud.api.response.FirewallRuleResponse;
+import com.cloud.api.response.SuccessResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.network.FirewallRuleVO;
+
+@Implementation(description="Deletes an ip forwarding rule")
+public class DeleteIpForwardingRuleCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(DeleteIpForwardingRuleCmd.class.getName());
+
+ private static final String s_name = "deleteipforwardingruleresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the id of the forwarding rule")
+ private Long id;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute() throws ServerApiException, InvalidParameterValueException, PermissionDeniedException, InsufficientAddressCapacityException, InsufficientCapacityException, ConcurrentOperationException{
+ try {
+ boolean result = false;
+ result = _networkMgr.deleteIpForwardingRule(this);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete ip forwarding rule");
+ }
+ } catch (Exception ex) {
+ throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
+ }
+ }
+
+}
diff --git a/server/src/com/cloud/api/commands/DeletePortForwardingRuleCmd.java b/server/src/com/cloud/api/commands/DeletePortForwardingRuleCmd.java
index ddfb872db95..e93cb77eb31 100644
--- a/server/src/com/cloud/api/commands/DeletePortForwardingRuleCmd.java
+++ b/server/src/com/cloud/api/commands/DeletePortForwardingRuleCmd.java
@@ -32,8 +32,8 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
@Implementation(description="Deletes a port forwarding rule")
-public class DeleteIPForwardingRuleCmd extends BaseCmd {
- public static final Logger s_logger = Logger.getLogger(DeleteIPForwardingRuleCmd.class.getName());
+public class DeletePortForwardingRuleCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(DeletePortForwardingRuleCmd.class.getName());
private static final String s_name = "deleteportforwardingruleresponse";
/////////////////////////////////////////////////////
@@ -63,7 +63,7 @@ public class DeleteIPForwardingRuleCmd extends BaseCmd {
@Override
public void execute() throws ServerApiException, InvalidParameterValueException, PermissionDeniedException, InsufficientAddressCapacityException, InsufficientCapacityException, ConcurrentOperationException{
- boolean result = _networkMgr.deleteIpForwardingRule(this);
+ boolean result = _networkMgr.deletePortForwardingRule(this);
if (result) {
SuccessResponse response = new SuccessResponse(getName());
this.setResponseObject(response);
diff --git a/server/src/com/cloud/api/commands/UpdatePortForwardingRuleCmd.java b/server/src/com/cloud/api/commands/UpdatePortForwardingRuleCmd.java
index 35dea1922fe..3674c320107 100644
--- a/server/src/com/cloud/api/commands/UpdatePortForwardingRuleCmd.java
+++ b/server/src/com/cloud/api/commands/UpdatePortForwardingRuleCmd.java
@@ -21,8 +21,8 @@ import com.cloud.network.IPAddressVO;
import com.cloud.user.Account;
@Implementation(description="Updates a port forwarding rule. Only the private port and the virtual machine can be updated.")
-public class UpdateIPForwardingRuleCmd extends BaseAsyncCmd {
- public static final Logger s_logger = Logger.getLogger(UpdateIPForwardingRuleCmd.class.getName());
+public class UpdatePortForwardingRuleCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(UpdatePortForwardingRuleCmd.class.getName());
private static final String s_name = "updateportforwardingruleresponse";
/////////////////////////////////////////////////////
diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java
index dce23943464..b01de8ba1dc 100644
--- a/server/src/com/cloud/network/NetworkManager.java
+++ b/server/src/com/cloud/network/NetworkManager.java
@@ -27,6 +27,7 @@ import com.cloud.api.commands.CreateIpForwardingRuleCmd;
import com.cloud.api.commands.CreatePortForwardingRuleCmd;
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
import com.cloud.api.commands.CreateRemoteAccessVpnCmd;
+import com.cloud.api.commands.DeleteIpForwardingRuleCmd;
import com.cloud.api.commands.DeletePortForwardingRuleCmd;
import com.cloud.api.commands.DeleteLoadBalancerRuleCmd;
import com.cloud.api.commands.DeleteRemoteAccessVpnCmd;
@@ -304,8 +305,6 @@ public interface NetworkManager {
List listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat);
public boolean disassociateIpAddress(DisassociateIPAddrCmd cmd);
-
- public boolean deleteIpForwardingRule(DeletePortForwardingRuleCmd cmd);
List setupNetworkConfiguration(Account owner, NetworkOfferingVO offering, DeploymentPlan plan);
List setupNetworkConfiguration(Account owner, NetworkOfferingVO offering, NetworkConfiguration predefined, DeploymentPlan plan);
@@ -364,4 +363,8 @@ public interface NetworkManager {
String getNextAvailableMacAddressInNetwork(long networkConfigurationId);
FirewallRuleVO createIpForwardingRule(CreateIpForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException;
+
+ public boolean deletePortForwardingRule(DeletePortForwardingRuleCmd cmd);
+
+ public boolean deleteIpForwardingRule(DeleteIpForwardingRuleCmd cmd);
}
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index d6517012391..03cd2310d4b 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -53,6 +53,7 @@ import com.cloud.api.commands.CreateIpForwardingRuleCmd;
import com.cloud.api.commands.CreatePortForwardingRuleCmd;
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
import com.cloud.api.commands.CreateRemoteAccessVpnCmd;
+import com.cloud.api.commands.DeleteIpForwardingRuleCmd;
import com.cloud.api.commands.DeletePortForwardingRuleCmd;
import com.cloud.api.commands.DeleteLoadBalancerRuleCmd;
import com.cloud.api.commands.DeleteRemoteAccessVpnCmd;
@@ -107,6 +108,7 @@ import com.cloud.network.Network.TrafficType;
import com.cloud.network.configuration.NetworkGuru;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.IprulePortrangeMapDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkConfigurationDao;
@@ -218,6 +220,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
@Inject RemoteAccessVpnDao _remoteAccessVpnDao = null;
@Inject VpnUserDao _vpnUsersDao = null;
@Inject DomainRouterManager _routerMgr;
+ @Inject IprulePortrangeMapDao _iprulePortrangeMapDao = null;
@Inject(adapter=NetworkGuru.class)
Adapters _networkGurus;
@@ -2510,7 +2513,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override @DB
- public boolean deleteIpForwardingRule(DeletePortForwardingRuleCmd cmd) {
+ public boolean deletePortForwardingRule(DeletePortForwardingRuleCmd cmd) {
Long ruleId = cmd.getId();
Long userId = UserContext.current().getUserId();
Account account = UserContext.current().getAccount();
@@ -2937,96 +2940,185 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return _networkConfigDao.findById(id);
}
- @Override
+ @Override @DB
public FirewallRuleVO createIpForwardingRule(CreateIpForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException {
- // validate IP Address exists
- IPAddressVO ipAddress = _ipAddressDao.findById(cmd.getIpAddress());
- if (ipAddress == null) {
- throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid IP address specified.");
- }
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ UserVmVO userVM = null;
+ FirewallRuleVO newFwRule = null;
+ boolean locked = false;
+ try {
+ // validate IP Address exists
+ IPAddressVO ipAddress = _ipAddressDao.findById(cmd.getIpAddress());
+ if (ipAddress == null) {
+ throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid IP address specified.");
+ }
- // validate user VM exists
- UserVmVO userVM = _vmDao.findById(cmd.getVirtualMachineId());
- if (userVM == null) {
- throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid virtual machine id specified (" + cmd.getVirtualMachineId() + ").");
- }
+ // validate user VM exists
+ userVM = _vmDao.findById(cmd.getVirtualMachineId());
+ if (userVM == null) {
+ throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid virtual machine id specified (" + cmd.getVirtualMachineId() + ").");
+ }
+
+ //sync point; cannot lock on rule ; hence sync on vm
+ userVM = _vmDao.acquireInLockTable(userVM.getId());
+
+ if(userVM == null){
+ s_logger.warn("Unable to acquire lock on user vm for creating 1-1 NAT rule");
+ return newFwRule;
+ }else{
+ locked = true;
+ }
- // validate that IP address and userVM belong to the same account
- if ((ipAddress.getAccountId() == null) || (ipAddress.getAccountId().longValue() != userVM.getAccountId())) {
- throw new InvalidParameterValueException("Unable to create ip forwarding rule, IP address " + ipAddress + " owner is not the same as owner of virtual machine " + userVM.toString());
- }
+ // validate that IP address and userVM belong to the same account
+ if ((ipAddress.getAccountId() == null) || (ipAddress.getAccountId().longValue() != userVM.getAccountId())) {
+ throw new InvalidParameterValueException("Unable to create ip forwarding rule, IP address " + ipAddress + " owner is not the same as owner of virtual machine " + userVM.toString());
+ }
- // validate that userVM is in the same availability zone as the IP address
- if (ipAddress.getDataCenterId() != userVM.getDataCenterId()) {
- throw new InvalidParameterValueException("Unable to create ip forwarding rule, IP address " + ipAddress + " is not in the same availability zone as virtual machine " + userVM.toString());
- }
+ // validate that userVM is in the same availability zone as the IP address
+ if (ipAddress.getDataCenterId() != userVM.getDataCenterId()) {
+ throw new InvalidParameterValueException("Unable to create ip forwarding rule, IP address " + ipAddress + " is not in the same availability zone as virtual machine " + userVM.toString());
+ }
- // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
- Account account = UserContext.current().getAccount();
- if (account != null) {
- if ((account.getType() == Account.ACCOUNT_TYPE_ADMIN) || (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)) {
- if (!_domainDao.isChildDomain(account.getDomainId(), userVM.getDomainId())) {
- throw new PermissionDeniedException("Unable to create ip forwarding rule, IP address " + ipAddress + " to virtual machine " + cmd.getVirtualMachineId() + ", permission denied.");
- }
- } else if (account.getId() != userVM.getAccountId()) {
- throw new PermissionDeniedException("Unable to create ip forwarding rule, IP address " + ipAddress + " to virtual machine " + cmd.getVirtualMachineId() + ", permission denied.");
- }
- }
+ // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
+ Account account = UserContext.current().getAccount();
+ if (account != null) {
+ if ((account.getType() == Account.ACCOUNT_TYPE_ADMIN) || (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)) {
+ if (!_domainDao.isChildDomain(account.getDomainId(), userVM.getDomainId())) {
+ throw new PermissionDeniedException("Unable to create ip forwarding rule, IP address " + ipAddress + " to virtual machine " + cmd.getVirtualMachineId() + ", permission denied.");
+ }
+ } else if (account.getId() != userVM.getAccountId()) {
+ throw new PermissionDeniedException("Unable to create ip forwarding rule, IP address " + ipAddress + " to virtual machine " + cmd.getVirtualMachineId() + ", permission denied.");
+ }
+ }
- // check for ip address/port conflicts by checking existing forwarding and load balancing rules
- List existingRulesOnPubIp = _rulesDao.listIPForwarding(ipAddress.getAddress());
+ // check for ip address/port conflicts by checking existing forwarding and load balancing rules
+ List existingNatRules = _rulesDao.findByPublicIpPrivateIpForNatRule(cmd.getIpAddress(), userVM.getGuestIpAddress());
+
+ if(existingNatRules.size() > 0){
+ throw new NetworkRuleConflictException("The specified rule for public ip:"+cmd.getIpAddress()+" vm id:"+cmd.getVirtualMachineId()+" already exists");
+ }
+
+ newFwRule = new FirewallRuleVO();
+ newFwRule.setEnabled(true);
+ newFwRule.setForwarding(true);
+ newFwRule.setPrivatePort(null);
+ newFwRule.setProtocol("NAT");//protocol cannot be null; adding this as a NAT
+ newFwRule.setPublicPort(null);
+ newFwRule.setPublicIpAddress(ipAddress.getAddress());
+ newFwRule.setPrivateIpAddress(userVM.getGuestIpAddress());
+ newFwRule.setGroupId(null);
+ _rulesDao.persist(newFwRule);
- // FIXME: The mapped ports should be String, String, List since more than one proto can be mapped...
- Map>> mappedPublicPorts = new HashMap>>();
+ // Save and create the event
+ String description;
+ String ruleName = "ip forwarding";
+ String level = EventVO.LEVEL_INFO;
- if (existingRulesOnPubIp != null) {
- for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
- Ternary> portMappings = mappedPublicPorts.get(fwRule.getPublicPort());
- List protocolList = null;
- if (portMappings == null) {
- protocolList = new ArrayList();
- } else {
- protocolList = portMappings.third();
- }
- protocolList.add(fwRule.getProtocol());
- mappedPublicPorts.put(fwRule.getPublicPort(), new Ternary>(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort(), protocolList));
- }
- }
+ description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
+ + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
- FirewallRuleVO newFwRule = new FirewallRuleVO();
- newFwRule.setEnabled(true);
- newFwRule.setForwarding(true);
-// newFwRule.setPrivatePort(privatePort);
-// newFwRule.setProtocol(protocol);
-// newFwRule.setPublicPort(publicPort);
- newFwRule.setPublicIpAddress(ipAddress.getAddress());
- newFwRule.setPrivateIpAddress(userVM.getGuestIpAddress());
-// newFwRule.setGroupId(securityGroupId);
- newFwRule.setGroupId(null);
-
- // In 1.0 the rules were always persisted when a user created a rule. When the rules get sent down
- // the stopOnError parameter is set to false, so the agent will apply all rules that it can. That
- // behavior is preserved here by persisting the rule before sending it to the agent.
- _rulesDao.persist(newFwRule);
-
- boolean success = updateFirewallRule(newFwRule, null, null);
-
- // Save and create the event
- String description;
- String ruleName = "ip forwarding";
- String level = EventVO.LEVEL_INFO;
-
- if (success == true) {
- description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
- + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
- } else {
- level = EventVO.LEVEL_ERROR;
- description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
- + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
- }
-
- EventUtils.saveEvent(UserContext.current().getUserId(), userVM.getAccountId(), level, EventTypes.EVENT_NET_RULE_ADD, description);
+ EventUtils.saveEvent(UserContext.current().getUserId(), userVM.getAccountId(), level, EventTypes.EVENT_NET_RULE_ADD, description);
+
+ txn.commit();
+ } catch (Exception e) {
+ s_logger.warn("Unable to create new firewall rule for 1:1 NAT");
+ txn.rollback();
+ }finally{
+ if(locked)
+ _vmDao.releaseFromLockTable(userVM.getId());
+ }
return newFwRule;
}
+
+ @Override @DB
+ public boolean deleteIpForwardingRule(DeleteIpForwardingRuleCmd cmd) {
+ Long ruleId = cmd.getId();
+ Long userId = UserContext.current().getUserId();
+ Account account = UserContext.current().getAccount();
+
+ //verify input parameters here
+ FirewallRuleVO rule = _firewallRulesDao.findById(ruleId);
+ if (rule == null) {
+ throw new InvalidParameterValueException("Unable to find port forwarding rule " + ruleId);
+ }
+
+ String publicIp = rule.getPublicIpAddress();
+
+
+ IPAddressVO ipAddress = _ipAddressDao.findById(publicIp);
+ if (ipAddress == null) {
+ throw new InvalidParameterValueException("Unable to find IP address for ip forwarding rule " + ruleId);
+ }
+
+ // although we are not writing these values to the DB, we will check
+ // them out of an abundance
+ // of caution (may not be warranted)
+
+ Account ruleOwner = _accountDao.findById(ipAddress.getAccountId());
+ if (ruleOwner == null) {
+ throw new InvalidParameterValueException("Unable to find owning account for ip forwarding rule " + ruleId);
+ }
+
+ // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
+ if (account != null) {
+ if (isAdmin(account.getType())) {
+ if (!_domainDao.isChildDomain(account.getDomainId(), ruleOwner.getDomainId())) {
+ throw new PermissionDeniedException("Unable to delete ip forwarding rule " + ruleId + ", permission denied.");
+ }
+ } else if (account.getId() != ruleOwner.getId()) {
+ throw new PermissionDeniedException("Unable to delete ip forwarding rule " + ruleId + ", permission denied.");
+ }
+ }
+
+ Transaction txn = Transaction.currentTxn();
+ boolean locked = false;
+ boolean success = false;
+ try {
+
+ rule = _firewallRulesDao.acquireInLockTable(ruleId);
+ if (rule == null) {
+ throw new PermissionDeniedException("Unable to obtain lock on record for deletion");
+ }
+
+ locked = true;
+ txn.start();
+ //if there is an open port range associated with the rule, don't allow deletion
+ List portRecordsForRule = _iprulePortrangeMapDao.listPortRecordsForRule(ruleId);
+
+ if (portRecordsForRule != null && portRecordsForRule.size() > 0) {
+ throw new InvalidParameterValueException("Cannot delete rule as port mappings for this rule exist; please delete those mappings first");
+ }
+
+ success = _firewallRulesDao.remove(ruleId);
+
+ String description;
+ String type = EventTypes.EVENT_NET_RULE_DELETE;
+ String level = EventVO.LEVEL_INFO;
+ String ruleName = rule.isForwarding() ? "ip forwarding" : "load balancer";
+
+ if (success) {
+ description = "deleted " + ruleName + " rule [" + publicIp + ":" + rule.getPublicPort() + "]->[" + rule.getPrivateIpAddress() + ":"
+ + rule.getPrivatePort() + "] " + rule.getProtocol();
+ } else {
+ level = EventVO.LEVEL_ERROR;
+ description = "Error while deleting " + ruleName + " rule [" + publicIp + ":" + rule.getPublicPort() + "]->[" + rule.getPrivateIpAddress() + ":"
+ + rule.getPrivatePort() + "] " + rule.getProtocol();
+ }
+ EventUtils.saveEvent(userId, ipAddress.getAccountId(), level, type, description);
+ txn.commit();
+ }catch (Exception ex) {
+ txn.rollback();
+ s_logger.error("Unexpected exception deleting port forwarding rule " + ruleId, ex);
+ return false;
+ }finally {
+ if (locked) {
+ _ipAddressDao.releaseFromLockTable(publicIp);
+ }
+ txn.close();
+ }
+ return success;
+ }
}
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index 91c0e1276e0..b73d95cf875 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -445,6 +445,15 @@ CREATE TABLE `cloud`.`ip_forwarding` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
+CREATE TABLE `cloud`.`iprule_portrange_map`(
+ `id` bigint unsigned NOT NULL auto_increment,
+ `fwrule_id` bigint unsigned NOT NULL,
+ `start_port` varchar(10) default NULL,
+ `end_port` varchar(10) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
+
+
CREATE TABLE `cloud`.`host` (
`id` bigint unsigned NOT NULL auto_increment,
`name` varchar(255) NOT NULL,