this is a good point to check the code in; have completed a part of the enhancement's code; with create and delete ip forwarding rule commands and the skeleton for port to rule map with associated table

This commit is contained in:
abhishek 2010-11-10 11:03:04 -08:00
parent e5ca5dddf9
commit 26b75fc05d
14 changed files with 569 additions and 92 deletions

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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;
}
}

View File

@ -44,5 +44,6 @@ public interface FirewallRulesDao extends GenericDao<FirewallRuleVO, Long> {
public List<FirewallRuleVO> listBySecurityGroupId(long securityGroupId);
public List<FirewallRuleVO> listByLoadBalancerId(long loadBalancerId);
public List<FirewallRuleVO> 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<FirewallRuleVO> findByPublicIpPrivateIpForNatRule(String publicIp,String privateIp);
}

View File

@ -55,7 +55,8 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
protected SearchBuilder<FirewallRuleVO> FWByPrivateIPSearch;
protected SearchBuilder<FirewallRuleVO> RulesExcludingPubIpPort;
protected SearchBuilder<FirewallRuleVO> FWByGroupId;
protected SearchBuilder<FirewallRuleVO> FWByGroupAndPrivateIp;
protected SearchBuilder<FirewallRuleVO> FWByGroupAndPrivateIp;
protected SearchBuilder<FirewallRuleVO> FWByPrivateIpPrivatePortPublicIpPublicPortSearch;
protected FirewallRulesDaoImpl() {
}
@ -124,6 +125,13 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> 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<FirewallRuleVO, Long> i
sc.setParameters("forwarding", forwarding);
return findOneBy(sc);
}
@Override
public List<FirewallRuleVO> findByPublicIpPrivateIpForNatRule(String publicIp, String privateIp){
SearchCriteria<FirewallRuleVO> sc = FWByPrivateIpPrivatePortPublicIpPublicPortSearch.create();
sc.setParameters("publicIpAddress", publicIp);
sc.setParameters("privateIpAddress", privateIp);
return listBy(sc);
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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<IprulePortrangeMapVO, Long> {
List<IprulePortrangeMapVO> listPortRecordsForRule(Long ruleId);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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<IprulePortrangeMapVO, Long> implements IprulePortrangeMapDao {
private static final Logger s_logger = Logger.getLogger(IprulePortrangeMapDaoImpl.class);
private final SearchBuilder<IprulePortrangeMapVO> ListByForwardingRule;
protected IprulePortrangeMapDaoImpl() {
ListByForwardingRule = createSearchBuilder();
ListByForwardingRule.and("ruleId", ListByForwardingRule.entity().getFwruleId(), SearchCriteria.Op.EQ);
ListByForwardingRule.done();
}
@Override
public List<IprulePortrangeMapVO> listPortRecordsForRule(Long ruleId) {
SearchCriteria<IprulePortrangeMapVO> sc = ListByForwardingRule.create();
sc.setParameters("ruleId", ruleId);
return listBy(sc);
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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());
}
}
}

View File

@ -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";

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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());
}
}
}

View File

@ -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);

View File

@ -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";
/////////////////////////////////////////////////////

View File

@ -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<IPAddressVO> listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat);
public boolean disassociateIpAddress(DisassociateIPAddrCmd cmd);
public boolean deleteIpForwardingRule(DeletePortForwardingRuleCmd cmd);
List<NetworkConfigurationVO> setupNetworkConfiguration(Account owner, NetworkOfferingVO offering, DeploymentPlan plan);
List<NetworkConfigurationVO> 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);
}

View File

@ -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<NetworkGuru> _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<FirewallRuleVO> existingRulesOnPubIp = _rulesDao.listIPForwarding(ipAddress.getAddress());
// check for ip address/port conflicts by checking existing forwarding and load balancing rules
List<FirewallRuleVO> 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<String> since more than one proto can be mapped...
Map<String, Ternary<String, String, List<String>>> mappedPublicPorts = new HashMap<String, Ternary<String, String, List<String>>>();
// Save and create the event
String description;
String ruleName = "ip forwarding";
String level = EventVO.LEVEL_INFO;
if (existingRulesOnPubIp != null) {
for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
Ternary<String, String, List<String>> portMappings = mappedPublicPorts.get(fwRule.getPublicPort());
List<String> protocolList = null;
if (portMappings == null) {
protocolList = new ArrayList<String>();
} else {
protocolList = portMappings.third();
}
protocolList.add(fwRule.getProtocol());
mappedPublicPorts.put(fwRule.getPublicPort(), new Ternary<String, String, List<String>>(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<IprulePortrangeMapVO> 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;
}
}

View File

@ -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,