ip nat rule forwarding done

This commit is contained in:
Alex Huang 2010-12-03 04:07:18 -08:00
parent 9a70ee54f0
commit b859e103d8
15 changed files with 190 additions and 68 deletions

View File

@ -8,11 +8,11 @@ public abstract class BaseAsyncCreateCmd extends BaseAsyncCmd {
public abstract void callCreate();
public Long getId() {
public Long getEntityId() {
return id;
}
public void setId(Long id) {
public void setEntityId(Long id) {
this.id = id;
}

View File

@ -28,11 +28,15 @@ 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.NetworkRuleConflictException;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
@Implementation(description="Creates an ip forwarding rule", responseObject=FirewallRuleResponse.class)
public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd {
public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements PortForwardingRule {
public static final Logger s_logger = Logger.getLogger(CreateIpForwardingRuleCmd.class.getName());
private static final String s_name = "createipforwardingruleresponse";
@ -72,9 +76,17 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd {
@Override
public void execute(){
PortForwardingRule result = _rulesService.createIpForwardingRuleInDb(ipAddress, virtualMachineId);
if (result != null) {
FirewallRuleResponse fwResponse = _responseGenerator.createFirewallRuleResponse(result);
boolean result;
try {
result = _rulesService.applyPortForwardingRules(new Ip(ipAddress), UserContext.current().getAccount());
} catch (Exception e) {
s_logger.error("Unable to apply port forwarding rules", e);
_rulesService.revokePortForwardingRule(getEntityId(), true);
result = false;
}
if (result) {
PortForwardingRule rule = _entityMgr.findById(PortForwardingRule.class, getEntityId());
FirewallRuleResponse fwResponse = _responseGenerator.createFirewallRuleResponse(rule);
fwResponse.setResponseName(getName());
this.setResponseObject(fwResponse);
} else {
@ -84,13 +96,16 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd {
}
@Override
public void callCreate(){
PortForwardingRule rule = _rulesService.createIpForwardingRuleInDb(ipAddress,virtualMachineId);
if (rule != null){
this.setId(rule.getId());
} else {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create ip forwarding rule");
public void callCreate() {
PortForwardingRule rule;
try {
rule = _rulesService.createPortForwardingRule(this, virtualMachineId);
} catch (NetworkRuleConflictException e) {
s_logger.info("Unable to create Port Forwarding Rule due to " + e.getMessage());
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage());
}
this.setEntityId(rule.getId());
}
@Override
@ -108,4 +123,69 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd {
return ("Creating an ipforwarding 1:1 NAT rule for "+ipAddress+" with virtual machine:"+virtualMachineId);
}
@Override
public long getId() {
throw new UnsupportedOperationException("Don't call me");
}
@Override
public String getXid() {
return null;
}
@Override
public Ip getSourceIpAddress() {
return new Ip(ipAddress);
}
@Override
public int getSourcePortStart() {
return -1;
}
@Override
public int getSourcePortEnd() {
return -1;
}
@Override
public String getProtocol() {
return NetUtils.NAT_PROTO;
}
@Override
public Purpose getPurpose() {
return Purpose.PortForwarding;
}
@Override
public State getState() {
throw new UnsupportedOperationException("Don't call me");
}
@Override
public long getNetworkId() {
return -1;
}
@Override
public long getDomainId() {
throw new UnsupportedOperationException("Don't call me");
}
@Override
public Ip getDestinationIpAddress() {
return null;
}
@Override
public int getDestinationPortStart() {
return -1;
}
@Override
public int getDestinationPortEnd() {
return -1;
}
}

View File

@ -21,11 +21,13 @@ package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseAsyncCreateCmd;
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.event.EventTypes;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.rules.PortForwardingRule;
@ -33,7 +35,7 @@ import com.cloud.user.UserContext;
import com.cloud.utils.net.Ip;
@Implementation(description="Creates a port forwarding rule", responseObject=FirewallRuleResponse.class)
public class CreatePortForwardingRuleCmd extends BaseCmd implements PortForwardingRule {
public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements PortForwardingRule {
public static final Logger s_logger = Logger.getLogger(CreatePortForwardingRuleCmd.class.getName());
private static final String s_name = "createportforwardingruleresponse";
@ -98,7 +100,7 @@ public class CreatePortForwardingRuleCmd extends BaseCmd implements PortForwardi
try {
UserContext callerContext = UserContext.current();
PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId, callerContext.getAccount());
PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId);
if (result == null) {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "An existing rule for ipAddress / port / protocol of " + ipAddress + " / " + publicPort + " / " + protocol + " exits.");
}
@ -183,4 +185,26 @@ public class CreatePortForwardingRuleCmd extends BaseCmd implements PortForwardi
public int getDestinationPortEnd() {
return Integer.parseInt(privatePort);
}
@Override
public void callCreate() {
try {
PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId);
setEntityId(result.getId());
} catch (NetworkRuleConflictException ex) {
s_logger.info("Network rule conflict: " + ex.getMessage());
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage());
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_NET_RULE_ADD;
}
@Override
public String getEventDescription() {
return ("Creating an port forwarding rule for "+ipAddress+" with virtual machine:"+virtualMachineId);
}
}

View File

@ -138,7 +138,7 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
try {
RemoteAccessVpn vpn = _networkService.createRemoteAccessVpn(this);
if (vpn != null) {
this.setId(vpn.getId());
this.setEntityId(vpn.getId());
} else {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create remote access vpn");
}

View File

@ -171,7 +171,7 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd {
public void callCreate(){
VirtualMachineTemplate template = _userVmService.createPrivateTemplateRecord(this);
if (template != null){
this.setId(template.getId());
this.setEntityId(template.getId());
} else {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create a template");
}

View File

@ -148,7 +148,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd {
try {
Volume volume = _storageMgr.allocVolume(this);
if (volume != null) {
this.setId(volume.getId());
this.setEntityId(volume.getId());
} else {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create volume");
}

View File

@ -28,6 +28,7 @@ import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.SuccessResponse;
import com.cloud.event.EventTypes;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.user.Account;
@Implementation(description="Deletes an ip forwarding rule", responseObject=SuccessResponse.class)
@ -62,9 +63,8 @@ public class DeleteIpForwardingRuleCmd extends BaseAsyncCmd {
@Override
public void execute(){
boolean result = false;
result = _rulesService.deleteIpForwardingRule(id);
if (result) {
PortForwardingRule rule = _rulesService.revokePortForwardingRule(id, true);
if (rule != null) {
SuccessResponse response = new SuccessResponse(getName());
this.setResponseObject(response);
} else {

View File

@ -22,6 +22,7 @@ import com.cloud.utils.net.Ip;
public interface FirewallRule extends ControlledEntity {
enum Purpose {
Firewall,
PortForwarding,
LoadBalancing,
Vpn,

View File

@ -27,20 +27,16 @@ import com.cloud.utils.net.Ip;
public interface RulesService {
List<? extends PortForwardingRule> searchForIpForwardingRules(Ip ip, Long start, Long size);
PortForwardingRule createIpForwardingRuleInDb(String ipAddr, long virtualMachineId);
boolean deleteIpForwardingRule(Long id);
/**
* Creates a port forwarding rule between two ip addresses or between
* an ip address and a virtual machine.
* @param rule rule to be created.
* @param vmId vm to be linked to. If specified the destination ip address is ignored.
* @param caller caller
* @return PortForwardingRule if created.
* @throws NetworkRuleConflictException if conflicts in the network rules are detected.
*/
PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, Account caller) throws NetworkRuleConflictException;
PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId) throws NetworkRuleConflictException;
/**
* Revokes a port forwarding rule
@ -56,7 +52,5 @@ public interface RulesService {
*/
public List<? extends PortForwardingRule> listPortForwardingRules(ListPortForwardingRulesCmd cmd);
boolean applyFirewallRules(Ip ip, Account caller) throws ResourceUnavailableException;
boolean applyNatRules(Ip ip) throws ResourceUnavailableException;
boolean applyPortForwardingRules(Ip ip, Account caller) throws ResourceUnavailableException;
}

View File

@ -373,7 +373,7 @@ public class ApiServer implements HttpRequestHandler {
if (cmdObj instanceof BaseAsyncCreateCmd) {
BaseAsyncCreateCmd createCmd = (BaseAsyncCreateCmd)cmdObj;
_dispatcher.dispatchCreateCmd(createCmd, params);
objectId = createCmd.getId();
objectId = createCmd.getEntityId();
params.put("id", objectId.toString());
} else {
ApiDispatcher.setupParameters(cmdObj, params);

View File

@ -1687,7 +1687,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
Long userId = UserContext.current().getUserId();
Account account = getAccountForApiCommand(cmd.getAccountName(), cmd.getDomainId());
EventUtils.saveStartedEvent(userId, account.getId(), EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE, "Creating a Remote Access VPN for account: " + account.getAccountName() + " in zone " + cmd.getZoneId(), cmd.getStartEventId());
RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findById(cmd.getId());
RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findById(cmd.getEntityId());
String publicIp = vpnVO.getVpnServerAddress();
Long vpnId = vpnVO.getId();
Transaction txn = Transaction.currentTxn();

View File

@ -46,8 +46,11 @@ import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
@ -66,7 +69,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
@Inject UserVmDao _vmDao;
@Inject AccountManager _accountMgr;
@Inject NetworkManager _networkMgr;
@Override
public void detectRulesConflict(FirewallRule newRule, IpAddress ipAddress) throws NetworkRuleConflictException {
@ -113,6 +115,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return;
}
if (userVm.getState() == com.cloud.vm.State.Destroyed || userVm.getState() == com.cloud.vm.State.Expunging) {
throw new InvalidParameterValueException("Invalid user vm: " + userVm.getId());
}
_accountMgr.checkAccess(caller, userVm);
// validate that IP address and userVM belong to the same account
@ -124,10 +130,14 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
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());
}
}
@Override
public PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, Account caller) throws NetworkRuleConflictException {
@Override @DB
public PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId) throws NetworkRuleConflictException {
UserContext ctx = UserContext.current();
Account caller = ctx.getAccount();
String ipAddr = rule.getSourceIpAddress().addr();
IPAddressVO ipAddress = _ipAddressDao.findById(ipAddr);
@ -171,7 +181,13 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
long domainId = network.getDomainId();
checkIpAndUserVm(ipAddress, vm, caller);
boolean isNat = NetUtils.NAT_PROTO.equals(rule.getProtocol());
if (isNat && (ipAddress.isSourceNat() || ipAddress.isOneToOneNat())) {
throw new NetworkRuleConflictException("Can't do one to one NAT on ip address: " + ipAddress.getAddress());
}
Transaction txn = Transaction.currentTxn();
txn.start();
PortForwardingRuleVO newRule =
new PortForwardingRuleVO(rule.getXid(),
rule.getSourceIpAddress(),
@ -185,6 +201,12 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
accountId,
domainId);
newRule = _forwardingDao.persist(newRule);
if (isNat) {
ipAddress.setOneToOneNat(true);
_ipAddressDao.update(ipAddress.getAddress(), ipAddress);
}
txn.commit();
boolean success = false;
try {
@ -196,7 +218,13 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
success = true;
return newRule;
} catch (Exception e) {
txn.start();
_forwardingDao.remove(newRule.getId());
if (isNat) {
ipAddress.setOneToOneNat(false);
_ipAddressDao.update(ipAddress.getAddress(), ipAddress);
}
txn.commit();
if (e instanceof NetworkRuleConflictException) {
throw (NetworkRuleConflictException)e;
}
@ -221,19 +249,43 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
}
protected Pair<Network, Ip> getUserVmGuestIpAddress(UserVm vm) {
Ip dstIp = null;
List<? extends Nic> nics = _networkMgr.getNics(vm);
for (Nic nic : nics) {
Network ntwk = _networkMgr.getNetwork(nic.getNetworkId());
if (ntwk.getGuestType() == GuestIpType.Virtualized) {
dstIp = new Ip(nic.getIp4Address());
return new Pair<Network, Ip>(ntwk, dstIp);
}
}
throw new CloudRuntimeException("Unable to find ip address to map to in " + vm.getId());
}
@DB
protected void revokeRule(FirewallRuleVO rule, Account caller) {
_accountMgr.checkAccess(caller, rule);
Transaction txn = Transaction.currentTxn();
txn.start();
if (rule.getState() == State.Staged) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found a rule that is still in stage state so just removing it: " + rule);
}
_firewallDao.remove(rule.getId());
return;
} else if (rule.getState() == State.Add) {
rule.setState(State.Revoke);
_firewallDao.update(rule.getId(), rule);
}
if (NetUtils.NAT_PROTO.equals(rule.protocol) && rule.getSourcePortStart() == -1) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Removing one to one nat so setting the ip back to one to one nat is false: " + rule.getSourceIpAddress());
}
IPAddressVO ipAddress = _ipAddressDao.findById(rule.getSourceIpAddress().addr());
ipAddress.setOneToOneNat(false);
_ipAddressDao.update(ipAddress.getAddress(), ipAddress);
}
}
@Override
@ -283,18 +335,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return rules;
}
@Override
public PortForwardingRule createIpForwardingRuleInDb(String ipAddr, long virtualMachineId) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean deleteIpForwardingRule(Long id) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean applyPortForwardingRules(Ip ip, boolean continueOnError) {
try {
@ -335,25 +375,11 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return _forwardingDao.searchNatRules(ip, start, size);
}
@Override
public boolean applyPortForwardingRules(Ip ip, Account caller) throws ResourceUnavailableException {
return applyPortForwardingRules(ip, false, caller);
}
@Override
public boolean applyNatRules(Ip ip) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean applyFirewallRules(Ip ip, Account caller) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
@ -675,9 +701,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
// return newFwRule;
// }
//
// @Override @DB
// public boolean deletePortForwardingRule(Long id, boolean sysContext) {
// }
// @Override @DB
// public PortForwardingRule createIpForwardingRuleOnDomr(long ruleId) {
// Transaction txn = Transaction.currentTxn();

View File

@ -1094,7 +1094,7 @@ public class ManagementServerImpl implements ManagementServer {
}
DeployVm2Cmd cmd2 = new DeployVm2Cmd();
cmd2.setId(vm.getId());
cmd2.setEntityId(vm.getId());
vm = _userVmService.startVirtualMachine(cmd2);
return vm;
}

View File

@ -1831,7 +1831,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
@Override @DB
public VolumeVO createVolume(CreateVolumeCmd cmd) {
VolumeVO volume = _volsDao.findById(cmd.getId());
VolumeVO volume = _volsDao.findById(cmd.getEntityId());
// VolumeVO createdVolume = null;
Long userId = UserContext.current().getUserId();

View File

@ -2567,13 +2567,13 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM
if (s_logger.isInfoEnabled()) {
s_logger.info(msg);
}
_templateDao.remove(command.getId()); // Mark it removed so that templates with the same name can be created subsequently. Bug 7366
_templateDao.remove(command.getEntityId()); // Mark it removed so that templates with the same name can be created subsequently. Bug 7366
throw new CloudRuntimeException(msg);
}
SnapshotCommand cmd = null;
VMTemplateVO privateTemplate = null;
long templateId = command.getId();
long templateId = command.getEntityId();
long zoneId = volume.getDataCenterId();
String uniqueName = getRandomPrivateTemplateName();
@ -3722,7 +3722,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM
@Override
public UserVm startVirtualMachine(DeployVm2Cmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
long vmId = cmd.getId();
long vmId = cmd.getEntityId();
UserVmVO vm = _vmDao.findById(vmId);
// Check that the password was passed in and is valid