Disassociate ip address - always allocate a new IP and enable static nat for it when elactic IP is enabled

This commit is contained in:
Alena Prokharchyk 2012-01-13 11:45:29 -08:00
parent 359185f567
commit 0e8104cca1
5 changed files with 93 additions and 63 deletions

View File

@ -170,6 +170,7 @@ import com.cloud.user.User;
import com.cloud.user.UserContext;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Adapters;
@ -1928,7 +1929,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
throw new InvalidParameterValueException("Ip address id=" + ipAddressId + " belongs to Account wide IP pool and cannot be disassociated");
}
return releasePublicIpAddress(ipAddressId, userId, caller);
boolean success = releasePublicIpAddress(ipAddressId, userId, caller);
if (success) {
Long vmId = ipVO.getAssociatedWithVmId();
UserVm vm = null;
if (vmId != null) {
vm = _userVmDao.findById(vmId);
}
return _rulesMgr.enableElasticIpAndStaticNatForVm(vm, true);
} else {
s_logger.warn("Failed to release public ip address id=" + ipAddressId);
return false;
}
}
@Deprecated // No one is using this method.

View File

@ -24,8 +24,8 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.firewall.FirewallService;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRule.FirewallRuleType;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.user.Account;
public interface FirewallManager extends FirewallService{
@ -77,5 +77,4 @@ public interface FirewallManager extends FirewallService{
boolean revokeFirewallRulesForVm(long vmId);
boolean addSystemFirewallRules(IPAddressVO ip, Account acct);
}

View File

@ -71,4 +71,6 @@ public interface RulesManager extends RulesService {
boolean applyStaticNatsForNetwork(long networkId, boolean continueOnError, Account caller);
boolean enableElasticIpAndStaticNatForVm(UserVm vm, boolean stopOnError);
}

View File

@ -29,6 +29,7 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
@ -49,6 +50,7 @@ import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.rules.FirewallRule.FirewallRuleType;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
@ -70,6 +72,7 @@ import com.cloud.utils.net.Ip;
import com.cloud.vm.Nic;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@Local(value = { RulesManager.class, RulesService.class })
@ -101,6 +104,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
FirewallManager _firewallMgr;
@Inject
DomainManager _domainMgr;
@Inject
ConfigurationManager _configMgr;
@Inject
NicDao _nicDao;
@Override
public void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) {
@ -1025,6 +1032,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
ipAddress.setOneToOneNat(false);
ipAddress.setAssociatedWithVmId(null);
_ipAddressDao.update(ipAddress.getId(), ipAddress);
if (!handleElasticIpRelease(ipAddress)) {
s_logger.warn("Failed to release elastic ip address " + ipAddress);
return false;
}
return true;
} else {
s_logger.warn("Failed to disable one to one nat for the ip address id" + ipId);
@ -1106,4 +1117,68 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return true;
}
@Override
public boolean enableElasticIpAndStaticNatForVm(UserVm vm, boolean stopOnError) {
boolean success = true;
//enable static nat if eIp capability is supported
List<? extends Nic> nics = _nicDao.listByVmId(vm.getId());
for (Nic nic : nics) {
Network guestNetwork = _networkMgr.getNetwork(nic.getNetworkId());
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
if (offering.getElasticIp()) {
try {
//check if there is already static nat enabled
if (_ipAddressDao.findByAssociatedVmId(vm.getId()) != null) {
s_logger.debug("Vm " + vm + " already has elastic ip associated with it in guest network " + guestNetwork);
continue;
}
s_logger.debug("Allocating elastic ip and enabling static nat for it for the vm " + vm + " in guest network " + guestNetwork);
IpAddress ip = _networkMgr.assignElasticIp(guestNetwork.getId(), _accountMgr.getAccount(vm.getAccountId()), false, true);
if (ip == null) {
s_logger.warn("Failed to allocate elastic ip for vm " + vm + " in guest network " + guestNetwork);
return false;
}
s_logger.debug("Allocated elastic ip " + ip + ", now enabling static nat on it for vm " + vm);
success = success && enableStaticNat(ip.getId(), vm.getId());
if (!success) {
s_logger.warn("Failed to enable static nat on elastic ip " + ip + " for the vm " + vm + ", releasing the ip...");
handleElasticIpRelease(ip);
} else {
s_logger.warn("Succesfully enabled static nat on elastic ip " + ip + " for the vm " + vm);
}
} catch (Exception ex) {
s_logger.warn("Failed to acquire elastic ip and enable static nat for vm " + vm + " on the network " + guestNetwork + " due to exception ", ex);
} finally {
if (!success && stopOnError) {
return false;
}
}
}
}
return success;
}
protected boolean handleElasticIpRelease(IpAddress ip) {
boolean success = true;
Long networkId = ip.getAssociatedWithNetworkId();
if (networkId != null) {
Network guestNetwork = _networkMgr.getNetwork(networkId);
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
if (offering.getElasticIp()) {
UserContext ctx = UserContext.current();
if (!_networkMgr.releasePublicIpAddress(ip.getId(), ctx.getCallerUserId(), ctx.getCaller())) {
s_logger.warn("Unable to release elastic ip address id=" + ip.getId());
success = false;
} else {
s_logger.warn("Successfully released elastic ip address id=" + ip.getId());
}
}
}
return success;
}
}

View File

@ -119,7 +119,6 @@ import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
@ -1271,21 +1270,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
s_logger.warn("Failed to disable static nat for ip address " + ip + " as a part of vm id=" + vmId + " expunge");
success = false;
}
Long networkId = ip.getAssociatedWithNetworkId();
if (networkId != null) {
Network guestNetwork = _networkMgr.getNetwork(networkId);
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
if (offering.getElasticIp()) {
UserContext ctx = UserContext.current();
if (!_networkMgr.releasePublicIpAddress(ip.getId(), ctx.getCallerUserId(), ctx.getCaller())) {
s_logger.warn("Unable to release elastic ip address id=" + ip.getId() + " as a part of vm id=" + vmId + " cleanup");
success = false;
} else {
s_logger.warn("Successfully released elastic ip address id=" + ip.getId() + " as a part of vm id=" + vmId + " cleanup");
}
}
}
}
} catch (ResourceUnavailableException e) {
success = false;
@ -2746,8 +2730,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
//enable elastic ip for vm
boolean success = enableElasticIpAndStaticNatForVm(profile.getVirtualMachine(), true);
return success;
return _rulesMgr.enableElasticIpAndStaticNatForVm(profile.getVirtualMachine(), true);
}
@Override
@ -3604,46 +3587,5 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
return vm;
}
protected boolean enableElasticIpAndStaticNatForVm(UserVm vm, boolean stopOnError) {
boolean success = true;
Account vmOwner = _accountMgr.getAccount(vm.getAccountId());
//enable static nat if eIp capability is supported
List<? extends Nic> nics = _nicDao.listByVmId(vm.getId());
for (Nic nic : nics) {
Network guestNetwork = _networkMgr.getNetwork(nic.getNetworkId());
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
if (offering.getElasticIp()) {
try {
//check if there is already static nat enabled
if (_ipAddressDao.findByAssociatedVmId(vm.getId()) != null) {
s_logger.debug("Vm " + vm + " already has elastic ip associated with it in guest network " + guestNetwork);
continue;
}
s_logger.debug("Allocating elastic ip and enabling static nat for it for the vm " + vm + " in guest network " + guestNetwork);
IpAddress ip = _networkMgr.assignElasticIp(guestNetwork.getId(), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM), false, true);
if (ip == null) {
s_logger.warn("Failed to allocate elastic ip as a part of vm deployment for vm " + vm);
return false;
}
s_logger.debug("Allocated elastic ip " + ip + ", now enabling static nat on it for vm " + vm);
success = success && _rulesMgr.enableStaticNat(ip.getId(), vm.getId());
if (!success) {
s_logger.warn("Failed to enable static nat on elastic ip " + ip + " for the vm " + vm);
} else {
s_logger.warn("Succesfully enabled static nat on elastic ip " + ip + " for the vm " + vm);
}
} catch (Exception ex) {
s_logger.warn("Failed to finalize vm deployment for vm " + vm + " on the network " + guestNetwork + " due to exception ", ex);
} finally {
if (!success && stopOnError) {
return false;
}
}
}
}
return success;
}
}