diff --git a/api/src/com/cloud/api/commands/DeleteVlanIpRangeCmd.java b/api/src/com/cloud/api/commands/DeleteVlanIpRangeCmd.java index 1224681baf7..d513ba0ed9b 100644 --- a/api/src/com/cloud/api/commands/DeleteVlanIpRangeCmd.java +++ b/api/src/com/cloud/api/commands/DeleteVlanIpRangeCmd.java @@ -12,8 +12,6 @@ // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.api.commands; -import java.util.UUID; - import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index 95bdeb26a2f..85cdf34cf24 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -137,9 +137,10 @@ public interface ConfigurationManager extends ConfigurationService, Manager { * * @param userId * @param vlanDbId + * @param caller TODO * @return success/failure */ - boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId); + boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller); /** * Converts a comma separated list of tags to a List diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index d2bbb91e8d9..d05990b4710 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -38,8 +38,8 @@ import org.apache.log4j.Logger; import com.cloud.acl.SecurityChecker; import com.cloud.alert.AlertManager; -import com.cloud.api.ApiDBUtils; import com.cloud.api.ApiConstants.LDAPParams; +import com.cloud.api.ApiDBUtils; import com.cloud.api.commands.CreateDiskOfferingCmd; import com.cloud.api.commands.CreateNetworkOfferingCmd; import com.cloud.api.commands.CreateServiceOfferingCmd; @@ -110,6 +110,7 @@ import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetworkVO; +import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.PhysicalNetworkDao; @@ -155,6 +156,7 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.NicDao; import edu.emory.mathcs.backport.java.util.Arrays; @@ -219,6 +221,10 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura SwiftManager _swiftMgr; @Inject PhysicalNetworkTrafficTypeDao _trafficTypeDao; + @Inject + NicDao _nicDao; + @Inject + FirewallRulesDao _firewallDao; // FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao? protected static final DataCenterLinkLocalIpAddressDaoImpl _LinkLocalIpAllocDao = ComponentLocator.inject(DataCenterLinkLocalIpAddressDaoImpl.class); @@ -2425,24 +2431,78 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } @Override - public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId) { + @DB + public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller) { VlanVO vlan = _vlanDao.findById(vlanDbId); if (vlan == null) { throw new InvalidParameterValueException("Please specify a valid IP range id."); } + + boolean isAccountSpecific = false; + List acctVln = _accountVlanMapDao.listAccountVlanMapsByVlan(vlan.getId()); + // Check for account wide pool. It will have an entry for account_vlan_map. + if (acctVln != null && !acctVln.isEmpty()) { + isAccountSpecific = true; + } // Check if the VLAN has any allocated public IPs - if (_publicIpAddressDao.countIPs(vlan.getDataCenterId(), vlanDbId, true) > 0) { - throw new InvalidParameterValueException("The IP range can't be deleted because it has allocated public IP addresses."); + long allocIpCount = _publicIpAddressDao.countIPs(vlan.getDataCenterId(), vlanDbId, true); + boolean success = true; + if (allocIpCount > 0) { + if (isAccountSpecific) { + try { + vlan = _vlanDao.acquireInLockTable(vlanDbId, 30); + if (vlan == null) { + throw new CloudRuntimeException("Unable to acquire vlan configuration: " + vlanDbId); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("lock vlan " + vlanDbId + " is acquired"); + } + + List ips = _publicIpAddressDao.listByVlanId(vlanDbId); + + for (IPAddressVO ip : ips) { + if (ip.isOneToOneNat()) { + throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + + " as ip " + ip + " belonging to the range is used for static nat purposes. Cleanup the rules first"); + } + + if (ip.isSourceNat() && _nicDao.findByIp4AddressAndNetworkId(ip.getAddress().addr(), ip.getSourceNetworkId()) != null) { + throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + + " as ip " + ip + " belonging to the range is a source nat ip for the network id=" + ip.getSourceNetworkId() + + ". Either delete the network, or Virtual Router instance using this ip address"); + } + + if (_firewallDao.countRulesByIpId(ip.getId()) > 0) { + throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + + " as ip " + ip + " belonging to the range has firewall rules applied. Cleanup the rules first"); + } + //release public ip address here + success = success && _networkMgr.releasePublicIpAddress(ip.getId(), userId, caller); + } + if (!success) { + s_logger.warn("Some ip addresses failed to be released as a part of vlan " + vlanDbId + " removal"); + } + } finally { + _vlanDao.releaseFromLockTable(vlanDbId); + } + } else { + throw new InvalidParameterValueException("The IP range can't be deleted because it has allocated public IP addresses."); + } } - // Delete all public IPs in the VLAN - if (!deletePublicIPRange(vlanDbId)) { + if (success) { + // Delete all public IPs in the VLAN + if (!deletePublicIPRange(vlanDbId)) { + return false; + } + + // Delete the VLAN + return _vlanDao.expunge(vlanDbId); + } else { return false; } - - // Delete the VLAN - return _vlanDao.expunge(vlanDbId); } @Override @@ -2766,8 +2826,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new InvalidParameterValueException("Please specify a valid IP range id."); } - return deleteVlanAndPublicIpRange(UserContext.current().getCallerUserId(), vlanDbId); - + return deleteVlanAndPublicIpRange(UserContext.current().getCallerUserId(), vlanDbId, UserContext.current().getCaller()); } @Override @@ -3620,7 +3679,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura Transaction txn = Transaction.currentTxn(); txn.start(); for (AccountVlanMapVO map : maps) { - if (!deleteVlanAndPublicIpRange(_accountMgr.getSystemUser().getId(), map.getVlanDbId())) { + if (!deleteVlanAndPublicIpRange(_accountMgr.getSystemUser().getId(), map.getVlanDbId(), + _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM))) { result = false; } } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index da490f70348..235771baf87 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -614,7 +614,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } else if (addr.getState() == IpAddress.State.Releasing) { // Cleanup all the resources for ip address if there are any, and only then un-assign ip in the -// system + // system if (cleanupIpResources(addr.getId(), Account.ACCOUNT_ID_SYSTEM, _accountMgr.getSystemAccount())) { _ipAddressDao.unassignIpAddress(addr.getId()); } else { @@ -3144,7 +3144,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag txn.start(); guru.trash(network, _networkOfferingDao.findById(network.getNetworkOfferingId()), owner); - if (!deleteVlansInNetwork(network.getId(), context.getCaller().getId())) { + if (!deleteVlansInNetwork(network.getId(), context.getCaller().getId(), callerAccount)) { success = false; s_logger.warn("Failed to delete network " + network + "; was unable to cleanup corresponding ip ranges"); } else { @@ -3159,11 +3159,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return success; } - private boolean deleteVlansInNetwork(long networkId, long userId) { + private boolean deleteVlansInNetwork(long networkId, long userId, Account callerAccount) { List vlans = _vlanDao.listVlansByNetworkId(networkId); boolean result = true; for (VlanVO vlan : vlans) { - if (!_configMgr.deleteVlanAndPublicIpRange(_accountMgr.getSystemUser().getId(), vlan.getId())) { + if (!_configMgr.deleteVlanAndPublicIpRange(_accountMgr.getSystemUser().getId(), vlan.getId(), callerAccount)) { s_logger.warn("Failed to delete vlan " + vlan.getId() + ");"); result = false; }