port forwarding is now in

This commit is contained in:
Alex Huang 2010-12-03 08:47:29 -08:00
parent 3aa19666cf
commit a8b617c596
7 changed files with 215 additions and 112 deletions

View File

@ -47,26 +47,26 @@ public interface NetworkService {
* @throws ResourceAllocationException, InsufficientCapacityException
*/
IpAddress associateIP(AssociateIPAddrCmd cmd) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException;
public boolean disassociateIpAddress(DisassociateIPAddrCmd cmd);
boolean disassociateIpAddress(DisassociateIPAddrCmd cmd);
/**
* Create a remote access vpn from the given public ip address and client ip range
* Create a remote access vpn from the given ip address and client ip range
* @param cmd the command specifying the ip address, ip range
* @return the newly created RemoteAccessVpnVO if successful, null otherwise
* @throws InvalidParameterValueException
* @throws PermissionDeniedException
* @throws ConcurrentOperationException
*/
public RemoteAccessVpn createRemoteAccessVpn(CreateRemoteAccessVpnCmd cmd) throws ConcurrentOperationException, InvalidParameterValueException, PermissionDeniedException;
RemoteAccessVpn createRemoteAccessVpn(CreateRemoteAccessVpnCmd cmd) throws ConcurrentOperationException, InvalidParameterValueException, PermissionDeniedException;
/**
* Start a remote access vpn for the given public ip address and client ip range
* Start a remote access vpn for the given ip address and client ip range
* @param cmd the command specifying the ip address, ip range
* @return the RemoteAccessVpnVO if successful, null otherwise
* @throws ConcurrentOperationException
* @throws ResourceUnavailableException
*/
public RemoteAccessVpn startRemoteAccessVpn(CreateRemoteAccessVpnCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException;
RemoteAccessVpn startRemoteAccessVpn(CreateRemoteAccessVpnCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException;
/**
* Destroy a previously created remote access VPN
@ -74,7 +74,7 @@ public interface NetworkService {
* @return success if successful, false otherwise
* @throws ConcurrentOperationException
*/
public boolean destroyRemoteAccessVpn(DeleteRemoteAccessVpnCmd cmd) throws ConcurrentOperationException;
boolean destroyRemoteAccessVpn(DeleteRemoteAccessVpnCmd cmd) throws ConcurrentOperationException;
VpnUser addVpnUser(AddVpnUserCmd cmd) throws ConcurrentOperationException, AccountLimitException;

View File

@ -14,6 +14,7 @@ import com.cloud.network.Network;
import com.cloud.network.rules.FirewallRule;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.Adapter;
import com.cloud.utils.net.Ip;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
@ -31,11 +32,66 @@ public interface NetworkElement extends Adapter {
*/
boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException;
/**
* Prepare for a nic to be added into this network.
* @param network
* @param nic
* @param vm
* @param dest
* @param context
* @return
* @throws ConcurrentOperationException
* @throws ResourceUnavailableException
* @throws InsufficientNetworkCapacityException
*/
boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientNetworkCapacityException;
/**
* A nic is released from this network.
* @param network
* @param nic
* @param vm
* @param context
* @return
* @throws ConcurrentOperationException
* @throws ResourceUnavailableException
*/
boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException;
/**
* The network is being shutdown.
* @param network
* @param context
* @return
* @throws ConcurrentOperationException
* @throws ResourceUnavailableException
*/
boolean shutdown(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException;
/**
* Associate a new ip address to this network
* @param network
* @param ipAddress
* @return
* @throws ResourceUnavailableException
*/
boolean associate(Network network, Ip ipAddress) throws ResourceUnavailableException;
/**
* Disassociate the ip address from this network
* @param network
* @param ipAddress
* @return
* @throws ResourceUnavailableException
*/
boolean disassociate(Network network, Ip ipAddress) throws ResourceUnavailableException;
/**
* Apply rules
* @param network
* @param rules
* @return
* @throws ResourceUnavailableException
*/
boolean applyRules(Network network, List<? extends FirewallRule> rules) throws ResourceUnavailableException;
}

View File

@ -101,9 +101,11 @@ import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.router.DomainRouterManager;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.RulesManager;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.offerings.NetworkOfferingVO;
@ -202,6 +204,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
@Inject RemoteAccessVpnDao _remoteAccessVpnDao = null;
@Inject VpnUserDao _vpnUsersDao = null;
@Inject DomainRouterManager _routerMgr;
@Inject RulesManager _rulesMgr;
@Inject LoadBalancingRulesManager _lbMgr;
@Inject(adapter=NetworkGuru.class)
Adapters<NetworkGuru> _networkGurus;
@ -215,6 +219,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
SearchBuilder<AccountVO> AccountsUsingNetworkConfigurationSearch;
private Map<String, String> _configs;
@Override
public boolean sendSshKeysToHost(Long hostId, String pubKey, String prvKey) {
@ -805,78 +810,81 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return answers[0].getResult();
}
@Override @DB
@DB
protected IPAddressVO releaseOwnershipOfIpAddress(String ipAddress) {
Transaction txn = Transaction.currentTxn();
txn.start();
IPAddressVO ip = _ipAddressDao.lockRow(ipAddress, true);
if (ip == null) {
s_logger.warn("Unable to find allocated ip: " + ipAddress);
return null;
}
if (ip.getAllocated() == null) {
s_logger.debug("Ip Address is already rleeased: " + ipAddress);
return null;
}
ip.setAccountId(null);
ip.setDomainId(null);
_ipAddressDao.update(ip.getAddress(), ip);
txn.commit();
return ip;
}
@Override
public boolean releasePublicIpAddress(long userId, final String ipAddress) {
return false; // FIXME
// IPAddressVO ip = null;
// try {
// ip = _ipAddressDao.acquireInLockTable(ipAddress);
//
// if (ip == null) {
// s_logger.warn("Unable to find allocated ip: " + ipAddress);
// return false;
// }
//
// if(s_logger.isDebugEnabled()) {
// s_logger.debug("lock on ip " + ipAddress + " is acquired");
// }
//
// if (ip.getAllocated() == null) {
// s_logger.warn("ip: " + ipAddress + " is already released");
// return false;
// }
//
// if (s_logger.isDebugEnabled()) {
// s_logger.debug("Releasing ip " + ipAddress + "; sourceNat = " + ip.isSourceNat());
// }
//
//
// final List<String> ipAddrs = new ArrayList<String>();
// ipAddrs.add(ip.getAddress());
// final List<PortForwardingRuleVO> firewallRules = _rulesDao.listIPForwardingForUpdate(ipAddress);
//
// if (s_logger.isDebugEnabled()) {
// s_logger.debug("Found firewall rules: " + firewallRules.size());
// }
//
// for (final PortForwardingRuleVO fw: firewallRules) {
// fw.setEnabled(false);
// }
//
// DomainRouterVO router = null;
// if (ip.isSourceNat()) {
// router = _routerMgr.getRouter(ipAddress);
// if (router != null) {
// if (router.getPublicIpAddress() != null) {
// return false;
// }
// }
// } else {
// router = _routerMgr.getRouter(ip.getAccountId(), ip.getDataCenterId());
// }
//
// // Now send the updates down to the domR (note: we still hold locks on address and firewall)
// updateFirewallRules(ipAddress, firewallRules, router);
//
// for (final PortForwardingRuleVO rule: firewallRules) {
// _rulesDao.remove(rule.getId());
//
// // Save and create the event
// String ruleName = (rule.isForwarding() ? "ip forwarding" : "load balancer");
// String description = "deleted " + ruleName + " rule [" + rule.getSourceIpAddress() + ":" + rule.getSourcePort()
// + "]->[" + rule.getDestinationIpAddress() + ":" + rule.getDestinationPort() + "]" + " "
// + rule.getProtocol();
//
// // save off an event for removing the network rule
// EventVO event = new EventVO();
// event.setUserId(userId);
// event.setAccountId(ip.getAccountId());
// event.setType(EventTypes.EVENT_NET_RULE_DELETE);
// event.setDescription(description);
// event.setLevel(EventVO.LEVEL_INFO);
// _eventDao.persist(event);
// }
//
IPAddressVO ip = releaseOwnershipOfIpAddress(ipAddress);
if (ip == null) {
return true;
}
Ip addr = new Ip(ipAddress);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Releasing ip " + ipAddress + "; sourceNat = " + ip.isSourceNat());
}
boolean success = true;
try {
if (!_rulesMgr.revokeAllRules(addr, userId)) {
s_logger.warn("Unable to revoke all the port forwarding rules for ip " + ip);
success = false;
}
} catch (ResourceUnavailableException e) {
s_logger.warn("Unable to revoke all the port forwarding rules for ip " + ip, e);
success = false;
}
if (!_lbMgr.removeAllLoadBalanacers(addr)) {
s_logger.warn("Unable to revoke all the load balancer rules for ip " + ip);
success = false;
}
for (NetworkElement ne : _networkElements) {
try {
ne.disassociate(null, new Ip(ipAddress));
} catch (ResourceUnavailableException e) {
s_logger.warn("Unable to release the ip address " + ip, e);
success = false;
}
}
if (success) {
_ipAddressDao.unassignIpAddress(ipAddress);
s_logger.debug("released a public ip: " + ipAddress);
}
final EventVO event = new EventVO();
event.setUserId(userId);
event.setAccountId(ip.getAccountId());
event.setType(EventTypes.EVENT_NET_IP_RELEASE);
event.setParameters("address=" + ipAddress + "\nsourceNat="+ip.isSourceNat());
event.setDescription("released a public ip: " + ipAddress);
_eventDao.persist(event);
return success;
// List<LoadBalancerVO> loadBalancers = _loadBalancerDao.listByIpAddress(ipAddress);
// for (LoadBalancerVO loadBalancer : loadBalancers) {
// _loadBalancerDao.remove(loadBalancer.getId());
@ -892,7 +900,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
// event.setLevel(EventVO.LEVEL_INFO);
// _eventDao.persist(event);
// }
//
// if ((router != null) && (router.getState() == State.Running)) {
// if (s_logger.isDebugEnabled()) {
// s_logger.debug("Disassociate ip " + router.getHostName());
@ -917,29 +925,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
// return false;
// }
// } else {
// _ipAddressDao.unassignIpAddress(ipAddress);
// }
// s_logger.debug("released a public ip: " + ipAddress);
// final EventVO event = new EventVO();
// event.setUserId(userId);
// event.setAccountId(ip.getAccountId());
// event.setType(EventTypes.EVENT_NET_IP_RELEASE);
// event.setParameters("address=" + ipAddress + "\nsourceNat="+ip.isSourceNat());
// event.setDescription("released a public ip: " + ipAddress);
// _eventDao.persist(event);
//
// return true;
// } catch (final Throwable e) {
// s_logger.warn("ManagementServer error", e);
// return false;
// } finally {
// if(ip != null) {
// if(s_logger.isDebugEnabled()) {
// s_logger.debug("Releasing lock on ip " + ipAddress);
// }
// _ipAddressDao.releaseFromLockTable(ipAddress);
// }
// }
}
@Override

View File

@ -61,6 +61,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, String> implem
AccountSearch.done();
}
@Override
public boolean mark(long dcId, String ip) {
SearchCriteria<IPAddressVO> sc = DcIpSearch.create();
sc.setParameters("dataCenterId", dcId);
@ -72,6 +73,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, String> implem
return update(vo, sc) >= 1;
}
@Override
@DB
public List<String> assignAcccountSpecificIps(long accountId, long domainId, Long vlanDbId, boolean sourceNat) {
@ -110,6 +112,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, String> implem
return null;
}
@Override
public void setIpAsSourceNat(String ipAddr){
IPAddressVO ip = createForUpdate(ipAddr);
@ -158,7 +161,8 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, String> implem
address.setAccountId(null);
address.setDomainId(null);
address.setAllocated(null);
address.setSourceNat(false);
address.setSourceNat(false);
address.setOneToOneNat(false);
update(ipAddress, address);
}
@ -176,7 +180,8 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, String> implem
return listIncludingRemovedBy(sc);
}
public List<IPAddressVO> listByDcIdIpAddress(long dcId, String ipAddress) {
@Override
public List<IPAddressVO> listByDcIdIpAddress(long dcId, String ipAddress) {
SearchCriteria<IPAddressVO> sc = DcIpSearch.create();
sc.setParameters("dataCenterId", dcId);
sc.setParameters("ipAddress", ipAddress);

View File

@ -39,6 +39,7 @@ import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.utils.net.Ip;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
@ -123,6 +124,19 @@ public class DomainRouterElement extends AdapterBase implements NetworkElement {
@Override
public boolean applyRules(Network config, List<? extends FirewallRule> rules) throws ResourceUnavailableException {
return false;
}
@Override
public boolean associate(Network network, Ip ipAddress) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean disassociate(Network network, Ip ipAddress) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -20,6 +20,7 @@ package com.cloud.network.rules;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
@ -54,4 +55,6 @@ public interface RulesManager extends RulesService {
void detectRulesConflict(FirewallRule newRule, IpAddress ipAddress) throws NetworkRuleConflictException;
void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) throws InvalidParameterValueException, PermissionDeniedException;
boolean revokeAllRules(Ip ip, long userId) throws ResourceUnavailableException;
}

View File

@ -29,6 +29,7 @@ import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
@ -39,6 +40,7 @@ import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRule.State;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offering.NetworkOffering.GuestIpType;
@ -69,6 +71,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
@Inject UserVmDao _vmDao;
@Inject AccountManager _accountMgr;
@Inject NetworkManager _networkMgr;
@Inject EventDao _eventDao;
@Override
public void detectRulesConflict(FirewallRule newRule, IpAddress ipAddress) throws NetworkRuleConflictException {
@ -264,8 +267,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@DB
protected void revokeRule(FirewallRuleVO rule, Account caller) {
_accountMgr.checkAccess(caller, rule);
protected void revokeRule(FirewallRuleVO rule, Account caller, long userId) {
if (caller != null) {
_accountMgr.checkAccess(caller, rule);
}
Transaction txn = Transaction.currentTxn();
txn.start();
@ -286,6 +291,24 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
ipAddress.setOneToOneNat(false);
_ipAddressDao.update(ipAddress.getAddress(), ipAddress);
}
// Save and create the event
String ruleName = rule.getPurpose() == Purpose.Firewall ? "Firewall" : (rule.getProtocol().equals(NetUtils.NAT_PROTO) ? "ip forwarding" : "port forwarding");
StringBuilder description = new StringBuilder("deleted ").append(ruleName).append(" rule [").append(rule.getSourceIpAddress()).append(":").append(rule.getSourcePortStart()).append("-").append(rule.getSourcePortEnd()).append("]");
if (rule.getPurpose() == Purpose.PortForwarding) {
PortForwardingRuleVO pfRule = (PortForwardingRuleVO)rule;
description.append("->[").append(pfRule.getDestinationIpAddress()).append(":").append(pfRule.getDestinationPortStart()).append("-").append(pfRule.getDestinationPortEnd()).append("]");
}
description.append(" ").append(rule.getProtocol());
// save off an event for removing the network rule
EventVO event = new EventVO();
event.setUserId(userId);
event.setAccountId(rule.getAccountId());
event.setType(EventTypes.EVENT_NET_RULE_DELETE);
event.setDescription(description.toString());
event.setLevel(EventVO.LEVEL_INFO);
_eventDao.persist(event);
}
@Override
@ -299,13 +322,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
_accountMgr.checkAccess(caller, rule);
revokeRule(rule, caller);
String description;
String type = EventTypes.EVENT_NET_RULE_DELETE;
String level = EventVO.LEVEL_INFO;
description = "deleted ip forwarding rule [" + rule.getSourceIpAddress() + ":" + rule.getSourcePortStart() + "]->[" + rule.getDestinationIpAddress() + ":" + rule.getDestinationPortStart() + "] " + rule.getProtocol();
EventUtils.saveEvent(ctx.getUserId(), rule.getAccountId(), level, type, description);
revokeRule(rule, caller, ctx.getUserId());
if (apply) {
applyPortForwardingRules(rule.getSourceIpAddress(), true);
@ -379,6 +396,29 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
public boolean applyPortForwardingRules(Ip ip, Account caller) throws ResourceUnavailableException {
return applyPortForwardingRules(ip, false, caller);
}
@Override @DB
public boolean revokeAllRules(Ip ip, long userId) throws ResourceUnavailableException {
List<PortForwardingRuleVO> rules = _forwardingDao.listByIpAndNotRevoked(ip);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Releasing " + rules.size() + " rules for " + ip);
}
for (PortForwardingRuleVO rule : rules) {
revokeRule(rule, null, userId);
}
applyPortForwardingRules(ip, true, null);
// Now we check again in case more rules have been inserted.
rules = _forwardingDao.listByIpAndNotRevoked(ip);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully released rules for " + ip + " and # of rules now = " + rules.size());
}
return rules.size() == 0;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {