fixed a corner case; also changed the commands to be async and changed the method signatures to conform with the master refactor

This commit is contained in:
abhishek 2010-11-11 12:48:06 -08:00
parent 239942bbe1
commit 1faaba8fb0
6 changed files with 132 additions and 61 deletions

View File

@ -77,7 +77,16 @@ add_one_to_one_nat_entry() {
local publicIp=$2
local dIp=$3
local op=$4
iptables -t nat $op PREROUTING -i eth2 -d $publicIp -j DNAT --to-destination $guestIp
if [ "$op" == "-D" ]
then
iptables -t nat $op PREROUTING -i eth2 -d $publicIp -j DNAT --to-destination $guestIp
if [ $? -gt 0 ]
then
return 0
fi
else
iptables -t nat $op PREROUTING -i eth2 -d $publicIp -j DNAT --to-destination $guestIp
fi
iptables -t nat $op POSTROUTING -o eth2 -s $guestIp -j SNAT --to-source $publicIp
if [ "$op" == "-A" ]
then

View File

@ -6,6 +6,7 @@ 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.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;

View File

@ -22,21 +22,24 @@ import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.ApiResponseHelper;
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseAsyncCreateCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.FirewallRuleResponse;
import com.cloud.event.EventTypes;
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.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.FirewallRuleVO;
import com.cloud.user.Account;
@Implementation(description="Creates an ip forwarding rule")
public class CreateIpForwardingRuleCmd extends BaseCmd {
public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd {
public static final Logger s_logger = Logger.getLogger(CreateIpForwardingRuleCmd.class.getName());
private static final String s_name = "createipforwardingruleresponse";
@ -75,19 +78,37 @@ public class CreateIpForwardingRuleCmd extends BaseCmd {
}
@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());
public void execute() throws ServerApiException, InvalidParameterValueException, PermissionDeniedException, InsufficientAddressCapacityException, InsufficientCapacityException, ConcurrentOperationException{
FirewallRuleVO result = _networkMgr.createIpForwardingRuleOnDomr(this.getId());
if (result != null) {
FirewallRuleResponse fwResponse = ApiResponseHelper.createFirewallRuleResponse(result);
fwResponse.setResponseName(getName());
this.setResponseObject(fwResponse);
} else {
throw new ServerApiException(NET_CREATE_IPFW_RULE_ERROR, "Error in creating ip forwarding rule on the domr");
}
}
@Override
public void callCreate() throws ServerApiException,InvalidParameterValueException, PermissionDeniedException,InsufficientAddressCapacityException,InsufficientCapacityException, ResourceUnavailableException,ConcurrentOperationException, ResourceAllocationException{
FirewallRuleVO rule = _networkMgr.createIpForwardingRuleInDb(ipAddress,virtualMachineId);
this.setId(rule.getId());
}
@Override
public long getAccountId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public String getEventType() {
return EventTypes.EVENT_NET_RULE_ADD;
}
@Override
public String getEventDescription() {
return ("Creating an ipforwarding 1:1 NAT rule for "+ipAddress+" with virtual machine:"+virtualMachineId);
}
}

View File

@ -21,23 +21,22 @@ package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.ApiResponseHelper;
import com.cloud.api.BaseAsyncCmd;
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.event.EventTypes;
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;
import com.cloud.user.Account;
@Implementation(description="Deletes an ip forwarding rule")
public class DeleteIpForwardingRuleCmd extends BaseCmd {
public class DeleteIpForwardingRuleCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeleteIpForwardingRuleCmd.class.getName());
private static final String s_name = "deleteipforwardingruleresponse";
@ -70,7 +69,7 @@ public class DeleteIpForwardingRuleCmd extends BaseCmd {
public void execute() throws ServerApiException, InvalidParameterValueException, PermissionDeniedException, InsufficientAddressCapacityException, InsufficientCapacityException, ConcurrentOperationException{
try {
boolean result = false;
result = _networkMgr.deleteIpForwardingRule(this);
result = _networkMgr.deleteIpForwardingRule(id);
if (result) {
SuccessResponse response = new SuccessResponse(getName());
this.setResponseObject(response);
@ -82,4 +81,19 @@ public class DeleteIpForwardingRuleCmd extends BaseCmd {
}
}
@Override
public long getAccountId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public String getEventType() {
return EventTypes.EVENT_NET_RULE_ADD;
}
@Override
public String getEventDescription() {
return ("Deleting an ipforwarding 1:1 NAT rule id:"+id);
}
}

View File

@ -20,6 +20,7 @@ package com.cloud.network;
import java.util.List;
import java.util.Map;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AddVpnUserCmd;
import com.cloud.api.commands.AssignToLoadBalancerRuleCmd;
import com.cloud.api.commands.AssociateIPAddrCmd;
@ -362,9 +363,11 @@ public interface NetworkManager {
String getNextAvailableMacAddressInNetwork(long networkConfigurationId) throws InsufficientAddressCapacityException;
String getNextAvailableMacAddressInNetwork(long networkConfigurationId);
FirewallRuleVO createIpForwardingRule(CreateIpForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException;
FirewallRuleVO createIpForwardingRuleInDb(String ipAddr, Long virtualMachineId) throws ServerApiException;
public boolean deletePortForwardingRule(DeletePortForwardingRuleCmd cmd);
public boolean deleteIpForwardingRule(DeleteIpForwardingRuleCmd cmd);
FirewallRuleVO createIpForwardingRuleOnDomr(Long ruleId);
boolean deleteIpForwardingRule(Long id);
}

View File

@ -167,6 +167,7 @@ import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@ -2938,26 +2939,69 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return _networkConfigDao.findById(id);
}
@Override
public FirewallRuleVO createIpForwardingRuleOnDomr(Long ruleId) throws ServerApiException{
boolean success = false;
//get the rule
FirewallRuleVO rule = _rulesDao.findById(ruleId);
if(rule == null){
throw new PermissionDeniedException("Cannot create ip forwarding rule in db");
}
//get ip address
IPAddressVO ipAddress = _ipAddressDao.findById(rule.getPublicIpAddress());
if (ipAddress == null) {
throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid IP address specified.");
}
//get the domain router object
DomainRouterVO router = _routerMgr.getRouter(ipAddress.getAccountId(), ipAddress.getDataCenterId());
success = createOrDeleteIpForwardingRuleOnDomr(rule,router,rule.getPrivateIpAddress(),true); //true +> create
if(!success){
//corner case; delete record from db as domR rule creation failed
try {
_rulesDao.remove(ruleId);
throw new PermissionDeniedException("Cannot create ip forwarding rule on domr, hence deleting created record in db");
} catch (Exception e) {
throw new ServerApiException(BaseCmd.NET_CREATE_IPFW_RULE_ERROR, e.getMessage());
}
}
// Save and create the event
String description;
String ruleName = "ip forwarding";
String level = EventVO.LEVEL_INFO;
description = "created new " + ruleName + " rule [" + rule.getPublicIpAddress() + "]->["
+ rule.getPrivateIpAddress() + "]" + ":" + rule.getProtocol();
EventUtils.saveEvent(UserContext.current().getUserId(), ipAddress.getAccountId(), level, EventTypes.EVENT_NET_RULE_ADD, description);
return rule;
}
@Override @DB
public FirewallRuleVO createIpForwardingRule(CreateIpForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException {
public FirewallRuleVO createIpForwardingRuleInDb(String ipAddr, Long virtualMachineId) throws ServerApiException {
Transaction txn = Transaction.currentTxn();
txn.start();
UserVmVO userVM = null;
FirewallRuleVO newFwRule = null;
boolean locked = false;
boolean success = false;
try {
// validate IP Address exists
IPAddressVO ipAddress = _ipAddressDao.findById(cmd.getIpAddress());
IPAddressVO ipAddress = _ipAddressDao.findById(ipAddr);
if (ipAddress == null) {
throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid IP address specified.");
}
// validate user VM exists
userVM = _vmDao.findById(cmd.getVirtualMachineId());
userVM = _vmDao.findById(virtualMachineId);
if (userVM == null) {
throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid virtual machine id specified (" + cmd.getVirtualMachineId() + ").");
throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid virtual machine id specified (" + virtualMachineId + ").");
}
//sync point; cannot lock on rule ; hence sync on vm
@ -2985,18 +3029,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
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.");
throw new PermissionDeniedException("Unable to create ip forwarding rule, IP address " + ipAddress + " to virtual machine " + virtualMachineId + ", 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.");
throw new PermissionDeniedException("Unable to create ip forwarding rule, IP address " + ipAddress + " to virtual machine " + virtualMachineId + ", permission denied.");
}
}
// check for ip address/port conflicts by checking existing forwarding and load balancing rules
List<FirewallRuleVO> existingNatRules = _rulesDao.findByPublicIpPrivateIpForNatRule(cmd.getIpAddress(), userVM.getGuestIpAddress());
List<FirewallRuleVO> existingNatRules = _rulesDao.findByPublicIpPrivateIpForNatRule(ipAddr, userVM.getGuestIpAddress());
if(existingNatRules.size() > 0){
throw new NetworkRuleConflictException("The specified rule for public ip:"+cmd.getIpAddress()+" vm id:"+cmd.getVirtualMachineId()+" already exists");
throw new NetworkRuleConflictException("The specified rule for public ip:"+ipAddr+" vm id:"+virtualMachineId+" already exists");
}
newFwRule = new FirewallRuleVO();
@ -3009,26 +3053,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
newFwRule.setPrivateIpAddress(userVM.getGuestIpAddress());
newFwRule.setGroupId(null);
//get the domain router object
final DomainRouterVO router = _routerMgr.getRouter(ipAddress.getAccountId(), ipAddress.getDataCenterId());
success = createOrDeleteIpForwardingRuleOnDomr(newFwRule,router,userVM.getGuestIpAddress(),true); //true +> create
if(!success){
throw new PermissionDeniedException("Cannot create ip forwarding rule on domr");
}
_rulesDao.persist(newFwRule);
// Save and create the event
String description;
String ruleName = "ip forwarding";
String level = EventVO.LEVEL_INFO;
description = "created 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);
_rulesDao.persist(newFwRule);
txn.commit();
} catch (Exception e) {
s_logger.warn("Unable to create new firewall rule for 1:1 NAT");
@ -3043,8 +3068,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override @DB
public boolean deleteIpForwardingRule(DeleteIpForwardingRuleCmd cmd) {
Long ruleId = cmd.getId();
public boolean deleteIpForwardingRule(Long id) {
Long ruleId = id;
Long userId = UserContext.current().getUserId();
Account account = UserContext.current().getAccount();
@ -3087,8 +3112,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
boolean success = false;
try {
rule = _firewallRulesDao.acquireInLockTable(ruleId);
if (rule == null) {
ipAddress = _ipAddressDao.acquireInLockTable(publicIp);
if (ipAddress == null) {
throw new PermissionDeniedException("Unable to obtain lock on record for deletion");
}
@ -3105,12 +3130,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
String ruleName = rule.isForwarding() ? "ip forwarding" : "load balancer";
if (success) {
description = "deleted " + ruleName + " rule [" + publicIp + ":" + rule.getPublicPort() + "]->[" + rule.getPrivateIpAddress() + ":"
+ rule.getPrivatePort() + "] " + rule.getProtocol();
description = "deleted " + ruleName + " rule [" + publicIp +"]->[" + rule.getPrivateIpAddress() + "] " + rule.getProtocol();
} else {
level = EventVO.LEVEL_ERROR;
description = "Error while deleting " + ruleName + " rule [" + publicIp + ":" + rule.getPublicPort() + "]->[" + rule.getPrivateIpAddress() + ":"
+ rule.getPrivatePort() + "] " + rule.getProtocol();
description = "Error while deleting " + ruleName + " rule [" + publicIp + "]->[" + rule.getPrivateIpAddress() +"] " + rule.getProtocol();
}
EventUtils.saveEvent(userId, ipAddress.getAccountId(), level, type, description);
txn.commit();