Get new elasticIp when releaseIpAddress is called for elasticIP of the vm

This commit is contained in:
Alena Prokharchyk 2012-01-13 16:41:53 -08:00
parent 6deeb7ddc9
commit 6325d21c50
21 changed files with 145 additions and 84 deletions

View File

@ -42,6 +42,7 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
@ -173,7 +174,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
@Override
public void create() throws ResourceAllocationException{
try {
IpAddress ip = _networkService.allocateIP(getNetworkId(), _accountService.getAccount(getEntityOwnerId()));
IpAddress ip = _networkService.allocateIP(getNetworkId(), _accountService.getAccount(getEntityOwnerId()), AllocatedBy.ipassoc);
if (ip != null) {
this.setEntityId(ip.getId());
} else {

View File

@ -31,6 +31,7 @@ import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.IpAddress.AllocatedBy;
@Implementation(description="Disables static rule for given ip address", responseObject=SuccessResponse.class)
public class DisableStaticNatCmd extends BaseAsyncCmd {

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.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
@ -81,7 +82,7 @@ public class EnableStaticNatCmd extends BaseCmd{
}
@Override
public void execute(){
public void execute() throws ResourceUnavailableException{
try {
boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId);
if (result) {

View File

@ -45,6 +45,11 @@ public interface IpAddress extends ControlledEntity{
Free // The IP address is ready to be allocated.
}
enum AllocatedBy {
ipassoc,
elasticip
}
long getDataCenterId();
Ip getAddress();
@ -77,4 +82,7 @@ public interface IpAddress extends ControlledEntity{
Long getAllocatedToAccountId();
Long getAllocatedInDomainId();
AllocatedBy getAllocatedBy();
}

View File

@ -30,6 +30,7 @@ import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
@ -42,7 +43,7 @@ public interface NetworkService {
List<? extends Network> getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner);
IpAddress allocateIP(long networkId, Account ipOwner) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException;
IpAddress allocateIP(long networkId, Account ipOwner, AllocatedBy allocatedBy) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException;
/**
* Associates a public IP address for a router.

View File

@ -22,6 +22,7 @@ import java.util.List;
import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.user.Account;
public interface RulesService {
@ -54,10 +55,8 @@ public interface RulesService {
boolean applyPortForwardingRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;
boolean enableStaticNat(long ipAddressId, long vmId) throws NetworkRuleConflictException;
boolean disableStaticNat(long ipAddressId) throws ResourceUnavailableException;
boolean enableStaticNat(long ipAddressId, long vmId) throws NetworkRuleConflictException, ResourceUnavailableException;
PortForwardingRule getPortForwardigRule(long ruleId);
FirewallRule getFirewallRule(long ruleId);
@ -70,5 +69,7 @@ public interface RulesService {
StaticNatRule buildStaticNatRule(FirewallRule rule);
List<String> getSourceCidrs(long ruleId);
boolean disableStaticNat(long ipId) throws ResourceUnavailableException;
}

View File

@ -73,6 +73,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceAllocationState;
import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceState;
import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.addr.PublicIp;
@ -476,7 +477,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
String dedicatedLb = offering.getDedicatedLB()?"true":"false";
//acquire a public IP to associate with lb appliance (used as subnet IP to make the appliance part of private network)
PublicIp publicIp = _networkMgr.assignPublicIpAddress(guestConfig.getDataCenterId(), null, _accountMgr.getSystemAccount(), VlanType.VirtualNetwork, null, null);
PublicIp publicIp = _networkMgr.assignPublicIpAddress(guestConfig.getDataCenterId(), null, _accountMgr.getSystemAccount(), VlanType.VirtualNetwork, null, null, AllocatedBy.ipassoc);
String publicIPNetmask = publicIp.getVlanNetmask();
String publicIPgateway = publicIp.getVlanGateway();
String publicIPVlanTag = publicIp.getVlanTag();

View File

@ -96,6 +96,10 @@ public class IPAddressVO implements IpAddress, Identity {
@Column(name="physical_network_id")
private Long physicalNetworkId;
@Column(name="allocated_by")
@Enumerated(value=EnumType.STRING)
private AllocatedBy allocatedBy;
@Column(name="account_id")
@Transient
private Long accountId = null;
@ -265,4 +269,13 @@ public class IPAddressVO implements IpAddress, Identity {
public void setPhysicalNetworkId(Long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
@Override
public AllocatedBy getAllocatedBy() {
return allocatedBy;
}
public void setAllocatedBy(AllocatedBy allocatedBy) {
this.allocatedBy = allocatedBy;
}
}

View File

@ -35,6 +35,7 @@ import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
@ -71,10 +72,11 @@ public interface NetworkManager extends NetworkService {
* @param type
* @param networkId
* @param requestedIp TODO
* @param allocatedBy TODO
* @return
* @throws InsufficientAddressCapacityException
*/
PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp) throws InsufficientAddressCapacityException;
PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, AllocatedBy allocatedBy) throws InsufficientAddressCapacityException;
/**
* assigns a source nat ip address to an account within a network.

View File

@ -103,6 +103,7 @@ import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.IpAddress.State;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
@ -340,12 +341,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp) throws InsufficientAddressCapacityException {
return fetchNewPublicIp(dcId, podId, null, owner, type, networkId, false, true, requestedIp);
public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, AllocatedBy allocatedBy) throws InsufficientAddressCapacityException {
return fetchNewPublicIp(dcId, podId, null, owner, type, networkId, false, true, requestedIp, allocatedBy);
}
@DB
public PublicIp fetchNewPublicIp(long dcId, Long podId, Long vlanDbId, Account owner, VlanType vlanUse, Long networkId, boolean sourceNat, boolean assign, String requestedIp)
public PublicIp fetchNewPublicIp(long dcId, Long podId, Long vlanDbId, Account owner, VlanType vlanUse, Long networkId, boolean sourceNat, boolean assign, String requestedIp, AllocatedBy allocatedBy)
throws InsufficientAddressCapacityException {
StringBuilder errorMessage = new StringBuilder("Unable to get ip adress in ");
Transaction txn = Transaction.currentTxn();
@ -401,6 +402,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
addr.setAllocatedTime(new Date());
addr.setAllocatedInDomainId(owner.getDomainId());
addr.setAllocatedToAccountId(owner.getId());
addr.setAllocatedBy(allocatedBy);
if (assign) {
markPublicIpAsAllocated(addr);
@ -505,7 +507,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
vlanId = maps.get(0).getVlanDbId();
}
ip = fetchNewPublicIp(dcId, null, vlanId, owner, VlanType.VirtualNetwork, network.getId(), true, false, null);
ip = fetchNewPublicIp(dcId, null, vlanId, owner, VlanType.VirtualNetwork, network.getId(), true, false, null, AllocatedBy.ipassoc);
sourceNat = ip.ip();
markPublicIpAsAllocated(sourceNat);
@ -920,7 +922,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true)
public IpAddress allocateIP(long networkId, Account ipOwner) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
public IpAddress allocateIP(long networkId, Account ipOwner, AllocatedBy allocatedBy) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
Account caller = UserContext.current().getCaller();
long userId = UserContext.current().getCallerUserId();
@ -1007,7 +1009,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
}
ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, network.getId(), isSourceNat, assign, null);
ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, network.getId(), isSourceNat, assign, null, allocatedBy);
if (ip == null) {
throw new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone.getId());
@ -3461,6 +3463,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
addr.setAllocatedTime(new Date());
addr.setAllocatedInDomainId(owner.getDomainId());
addr.setAllocatedToAccountId(owner.getId());
addr.setAllocatedBy(AllocatedBy.ipassoc);
addr.setState(IpAddress.State.Allocating);
markPublicIpAsAllocated(addr);
}
@ -5861,7 +5864,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
try {
s_logger.debug("Allocating elastic IP address for load balancer rule...");
//allocate ip
ip = allocateIP(networkId, owner);
ip = allocateIP(networkId, owner, AllocatedBy.elasticip);
//apply ip associations
ip = associateIP(ip.getId());
} catch (ResourceAllocationException ex) {
@ -5887,7 +5890,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (networkId != null) {
Network guestNetwork = getNetwork(networkId);
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
if (offering.getElasticIp()) {
if (offering.getElasticIp() && ip.getAllocatedBy() == AllocatedBy.elasticip) {
UserContext ctx = UserContext.current();
if (!releasePublicIpAddress(ip.getId(), ctx.getCallerUserId(), ctx.getCaller())) {
s_logger.warn("Unable to release elastic ip address id=" + ip.getId());

View File

@ -181,4 +181,9 @@ public class PublicIp implements PublicIpAddress {
public Long getAllocatedInDomainId() {
return _addr.getAllocatedInDomainId();
}
@Override
public AllocatedBy getAllocatedBy() {
return _addr.getAllocatedBy();
}
}

View File

@ -34,7 +34,6 @@ import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress.State;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
@ -43,7 +42,6 @@ import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.Ip;
@Local(value = { IPAddressDao.class })
@ -137,42 +135,6 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
return update(vo, sc) >= 1;
}
/**
* @deprecated This method is now deprecated because vlan has been
* added. The actual method is now within NetworkManager.
*/
@Deprecated
public IPAddressVO assignIpAddress(long accountId, long domainId, long vlanDbId, boolean sourceNat) {
Transaction txn = Transaction.currentTxn();
txn.start();
SearchCriteria<IPAddressVO> sc = VlanDbIdSearchUnallocated.create();
sc.setParameters("vlanDbId", vlanDbId);
Filter filter = new Filter(IPAddressVO.class, "vlanId", true, 0l, 1l);
List<IPAddressVO> ips = this.lockRows(sc, filter, true);
if (ips.size() == 0) {
s_logger.info("Unable to get an ip address in " + vlanDbId);
return null;
}
IPAddressVO ip = ips.get(0);
ip.setAllocatedToAccountId(accountId);
ip.setAllocatedTime(new Date());
ip.setAllocatedInDomainId(domainId);
ip.setSourceNat(sourceNat);
ip.setState(State.Allocated);
if (!update(ip.getId(), ip)) {
throw new CloudRuntimeException("How can I lock the row but can't update it: " + ip.getAddress());
}
txn.commit();
return ip;
}
@Override
public void unassignIpAddress(long ipAddressId) {
IPAddressVO address = createForUpdate();
@ -184,6 +146,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
address.setAssociatedWithVmId(null);
address.setState(State.Free);
address.setAssociatedWithNetworkId(null);
address.setAllocatedBy(null);
update(ipAddressId, address);
}

View File

@ -34,6 +34,7 @@ import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.Network;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Network.Service;
import com.cloud.network.Network.State;
import com.cloud.network.NetworkManager;
@ -154,7 +155,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile<? extends VirtualMachine> vm, Network network, String requestedIp) throws InsufficientVirtualNetworkCapcityException,
InsufficientAddressCapacityException, ConcurrentOperationException {
if (nic.getIp4Address() == null) {
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.DirectAttached, network.getId(), requestedIp);
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.DirectAttached, network.getId(), requestedIp, AllocatedBy.ipassoc);
nic.setIp4Address(ip.getAddress().toString());
nic.setGateway(ip.getGateway());
nic.setNetmask(ip.getNetmask());

View File

@ -42,6 +42,7 @@ import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Networks.AddressFormat;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
@ -162,7 +163,7 @@ public class DirectPodBasedNetworkGuru extends DirectNetworkGuru {
InsufficientAddressCapacityException, ConcurrentOperationException {
DataCenter dc = _dcDao.findById(pod.getDataCenterId());
if (nic.getIp4Address() == null) {
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), pod.getId(), vm.getOwner(), VlanType.DirectAttached, network.getId(), null);
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), pod.getId(), vm.getOwner(), VlanType.DirectAttached, network.getId(), null, AllocatedBy.ipassoc);
nic.setIp4Address(ip.getAddress().toString());
nic.setFormat(AddressFormat.Ip4);
nic.setGateway(ip.getGateway());

View File

@ -36,6 +36,7 @@ import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.Network;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Network.State;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkProfile;
@ -116,7 +117,7 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru {
protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile<? extends VirtualMachine> vm, Network network) throws InsufficientVirtualNetworkCapcityException,
InsufficientAddressCapacityException, ConcurrentOperationException {
if (nic.getIp4Address() == null) {
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.VirtualNetwork, null, null);
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.VirtualNetwork, null, null, AllocatedBy.ipassoc);
nic.setIp4Address(ip.getAddress().toString());
nic.setGateway(ip.getGateway());
nic.setNetmask(ip.getNetmask());

View File

@ -75,6 +75,7 @@ import com.cloud.network.ElasticLbVmMapVO;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.Network;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkManager;
@ -595,7 +596,8 @@ public class ElasticLoadBalancerManagerImpl implements
Network frontEndNetwork = _networkMgr.getNetwork(guestNetworkId);
Transaction txn = Transaction.currentTxn();
txn.start();
PublicIp ip = _networkMgr.assignPublicIpAddress(frontEndNetwork.getDataCenterId(), null, account, VlanType.DirectAttached, frontEndNetwork.getId(), null);
PublicIp ip = _networkMgr.assignPublicIpAddress(frontEndNetwork.getDataCenterId(), null, account, VlanType.DirectAttached, frontEndNetwork.getId(), null, AllocatedBy.elasticip);
IPAddressVO ipvo = _ipAddressDao.findById(ip.getId());
ipvo.setAssociatedWithNetworkId(frontEndNetwork.getId());
_ipAddressDao.update(ipvo.getId(), ipvo);

View File

@ -22,6 +22,7 @@ import java.util.List;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
@ -72,5 +73,7 @@ public interface RulesManager extends RulesService {
boolean applyStaticNatsForNetwork(long networkId, boolean continueOnError, Account caller);
boolean enableElasticIpAndStaticNatForVm(UserVm vm, boolean stopOnError);
boolean disableStaticNat(long ipAddressId, AllocatedBy allocatedBy) throws ResourceUnavailableException;
}

View File

@ -41,6 +41,7 @@ import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Network;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkManager;
@ -320,7 +321,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@Override
public boolean enableStaticNat(long ipId, long vmId) throws NetworkRuleConflictException {
public boolean enableStaticNat(long ipId, long vmId) throws NetworkRuleConflictException, ResourceUnavailableException {
Account caller = UserContext.current().getCaller();
@ -356,25 +357,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
// Verify ip address parameter
if (ipAddress.isSourceNat()) {
throw new InvalidParameterValueException("Can't enable static, ip address id=" + ipId + " is a sourceNat ip address");
}
if (!ipAddress.isOneToOneNat()) { // Dont allow to enable static nat if PF/LB rules exist for the IP
List<FirewallRuleVO> portForwardingRules = _firewallDao.listByIpAndPurposeAndNotRevoked(ipId, Purpose.PortForwarding);
if (portForwardingRules != null && !portForwardingRules.isEmpty()) {
throw new NetworkRuleConflictException("Failed to enable static nat for the ip address id=" + ipId + " as it already has PortForwarding rules assigned");
}
List<FirewallRuleVO> loadBalancingRules = _firewallDao.listByIpAndPurposeAndNotRevoked(ipId, Purpose.LoadBalancing);
if (loadBalancingRules != null && !loadBalancingRules.isEmpty()) {
throw new NetworkRuleConflictException("Failed to enable static nat for the ip address id=" + ipId + " as it already has LoadBalancing rules assigned");
}
} else {
if (ipAddress.getAssociatedWithVmId() != null && ipAddress.getAssociatedWithVmId().longValue() != vmId) {
throw new NetworkRuleConflictException("Failed to enable static for the ip address id=" + ipId + " and vm id=" + vmId + " as it's already assigned to antoher vm");
}
}
isIpReadyForStaticNat(vmId, ipAddress);
// If there is public ip address already associated with the vm, throw an exception
IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(vmId);
@ -406,6 +389,45 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
}
protected void isIpReadyForStaticNat(long vmId, IPAddressVO ipAddress) throws NetworkRuleConflictException, ResourceUnavailableException {
if (ipAddress.isSourceNat()) {
throw new InvalidParameterValueException("Can't enable static, ip address " + ipAddress + " is a sourceNat ip address");
}
if (!ipAddress.isOneToOneNat()) { // Dont allow to enable static nat if PF/LB rules exist for the IP
List<FirewallRuleVO> portForwardingRules = _firewallDao.listByIpAndPurposeAndNotRevoked(ipAddress.getId(), Purpose.PortForwarding);
if (portForwardingRules != null && !portForwardingRules.isEmpty()) {
throw new NetworkRuleConflictException("Failed to enable static nat for the ip address " + ipAddress + " as it already has PortForwarding rules assigned");
}
List<FirewallRuleVO> loadBalancingRules = _firewallDao.listByIpAndPurposeAndNotRevoked(ipAddress.getId(), Purpose.LoadBalancing);
if (loadBalancingRules != null && !loadBalancingRules.isEmpty()) {
throw new NetworkRuleConflictException("Failed to enable static nat for the ip address " + ipAddress + " as it already has LoadBalancing rules assigned");
}
}
if (ipAddress.getAssociatedWithVmId() != null && ipAddress.getAssociatedWithVmId().longValue() != vmId) {
Long networkId = ipAddress.getAssociatedWithNetworkId();
boolean reassignStaticNat = false;
if (networkId != null) {
Network guestNetwork = _networkMgr.getNetwork(networkId);
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
if (offering.getElasticIp()) {
reassignStaticNat = true;
}
}
if (!reassignStaticNat) {
throw new NetworkRuleConflictException("Failed to enable static for the ip address " + ipAddress + " and vm id=" + vmId + " as it's already assigned to antoher vm");
}
//unassign old static nat rule
s_logger.debug("Disassociating static nat for ");
if (!disableStaticNat(ipAddress.getId(), AllocatedBy.ipassoc)) {
throw new CloudRuntimeException("Failed to disable old static nat rule for vm id=" + vmId);
}
}
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_NET_RULE_DELETE, eventDescription = "revoking forwarding rule", async = true)
@ -996,9 +1018,32 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
public List<PortForwardingRuleVO> listByNetworkId(long networkId) {
return _portForwardingDao.listByNetwork(networkId);
}
@Override
public boolean disableStaticNat(long ipId) throws ResourceUnavailableException{
Account caller = UserContext.current().getCaller();
IPAddressVO ipAddress = _ipAddressDao.findById(ipId);
checkIpAndUserVm(ipAddress, null, caller);
Long vmId = ipAddress.getAssociatedWithVmId();
boolean success = disableStaticNat(ipId, AllocatedBy.ipassoc);
if (success && vmId != null) {
s_logger.debug("Allocating ip and enabling static nat for vm id=" + vmId + " as a part of disassociateIp command");
UserVm vm = _vmDao.findById(vmId);
success = enableElasticIpAndStaticNatForVm(vm, true);
if (!success) {
s_logger.warn("Failed to allocate ip and enable static nat for vm id=" + vmId + " as a part of disassociateIp command");
} else {
s_logger.debug("Successfully allocated ip and enabled static nat for vm id=" + vmId + " as a part of disassociateIp command");
}
}
return success;
}
@Override
public boolean disableStaticNat(long ipId) throws ResourceUnavailableException {
public boolean disableStaticNat(long ipId, AllocatedBy allocatedBy) throws ResourceUnavailableException {
boolean success = true;
UserContext ctx = UserContext.current();
@ -1031,11 +1076,17 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
if (success) {
ipAddress.setOneToOneNat(false);
ipAddress.setAssociatedWithVmId(null);
if (allocatedBy != null) {
ipAddress.setAllocatedBy(allocatedBy);
}
_ipAddressDao.update(ipAddress.getId(), ipAddress);
if (!_networkMgr.handleElasticIpRelease(ipAddress)) {
s_logger.warn("Failed to release elastic ip address " + ipAddress);
return false;
success = false;
}
return true;
} else {
s_logger.warn("Failed to disable one to one nat for the ip address id" + ipId);

View File

@ -1264,7 +1264,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(vmId);
try {
if (ip != null) {
if (_rulesMgr.disableStaticNat(ip.getId())) {
if (_rulesMgr.disableStaticNat(ip.getId(), null)) {
s_logger.debug("Disabled 1-1 nat for ip address " + ip + " as a part of vm id=" + vmId + " expunge");
} else {
s_logger.warn("Failed to disable static nat for ip address " + ip + " as a part of vm id=" + vmId + " expunge");

View File

@ -24,6 +24,7 @@ import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress.AllocatedBy;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
@ -58,7 +59,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS
}
@Override
public IpAddress allocateIP(long networkId, Account ipOwner) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
public IpAddress allocateIP(long networkId, Account ipOwner, AllocatedBy allocatedBy) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
// TODO Auto-generated method stub
return null;
}
@ -382,7 +383,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS
}
@Override
public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp) throws InsufficientAddressCapacityException {
public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, AllocatedBy allocatedBy) throws InsufficientAddressCapacityException {
// TODO Auto-generated method stub
return null;
}

View File

@ -918,6 +918,7 @@ CREATE TABLE `cloud`.`user_ip_address` (
`source_network_id` bigint unsigned NOT NULL COMMENT 'network id ip belongs to',
`network_id` bigint unsigned COMMENT 'network this public ip address is associated with',
`physical_network_id` bigint unsigned NOT NULL COMMENT 'physical network id that this configuration is based on',
`allocated_by` char (32) COMMENT 'the way ip address was allocated; can be by ipassoc or vmdeploy'
PRIMARY KEY (`id`),
UNIQUE (`public_ip_address`, `source_network_id`),
CONSTRAINT `fk_user_ip_address__source_network_id` FOREIGN KEY (`source_network_id`) REFERENCES `networks`(`id`),