Release NAT IP subnet when VPC is removed or IP is released (#44)

* Release NAT IP subnet when VPC is removed or IP is released

* add license
This commit is contained in:
Pearl Dsilva 2025-01-09 10:24:45 -05:00 committed by GitHub
parent b525255e85
commit f54cb50d17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 276 additions and 1 deletions

View File

@ -23,6 +23,7 @@ import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
@ -87,6 +88,12 @@ public interface NetworkElement extends Adapter {
boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException;
/**
* Release IP from the network provider if reserved
* @param ipAddress
*/
boolean releaseIp(IpAddress ipAddress);
/**
* The network is being shutdown.
* @param network

View File

@ -46,4 +46,6 @@ public interface NetrisService {
boolean addOrUpdateStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId, boolean updateRoute);
boolean deleteStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId);
boolean releaseNatIp(long zoneId, String publicIp);
}

View File

@ -40,4 +40,6 @@ public interface VpcOfferingServiceMapDao extends GenericDao<VpcOfferingServiceM
boolean isProviderForVpcOffering(Network.Provider provider, long vpcOfferingId);
List<VpcOfferingServiceMapVO> listProvidersForServiceForVpcOffering(long vpcOfferingId, Service service);
}

View File

@ -119,4 +119,14 @@ public class VpcOfferingServiceMapDaoImpl extends GenericDaoBase<VpcOfferingServ
sc.setParameters("provider", provider.getName());
return findOneBy(sc) != null;
}
@Override
public List<VpcOfferingServiceMapVO> listProvidersForServiceForVpcOffering(long vpcOfferingId, Service service) {
SearchCriteria<VpcOfferingServiceMapVO> sc = AllFieldsSearch.create();
sc.setParameters("vpcOffId", vpcOfferingId);
sc.setParameters("service", service.getName());
return customSearch(sc, null);
}
}

View File

@ -34,6 +34,7 @@ import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
@ -125,6 +126,11 @@ public class BaremetalDhcpElement extends AdapterBase implements DhcpServiceProv
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;

View File

@ -29,6 +29,7 @@ import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
@ -161,6 +162,11 @@ public class BaremetalPxeElement extends AdapterBase implements NetworkElement {
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
private void releaseVlan(Network network, VirtualMachineProfile vm) {
vlanMgr.releaseVlan(network, vm);
}

View File

@ -30,6 +30,7 @@ import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
@ -124,6 +125,11 @@ public class BaremetalUserdataElement extends AdapterBase implements NetworkElem
return false;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub

View File

@ -24,7 +24,7 @@ import java.util.Set;
import javax.inject.Inject;
import com.cloud.network.IpAddress;
import com.cloud.api.commands.DeleteCiscoNexusVSMCmd;
import com.cloud.api.commands.DisableCiscoNexusVSMCmd;
import com.cloud.api.commands.EnableCiscoNexusVSMCmd;
@ -106,6 +106,11 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;

View File

@ -29,6 +29,7 @@ import java.util.UUID;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.IpAddress;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
import org.apache.commons.net.util.SubnetUtils;
@ -318,6 +319,11 @@ NetworkACLServiceProvider, FirewallServiceProvider, ResourceStateAdapter {
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
if (!canHandle(network, Service.Connectivity)) {

View File

@ -27,6 +27,7 @@ import java.util.UUID;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.IpAddress;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
import org.springframework.stereotype.Component;
@ -194,6 +195,11 @@ public class BrocadeVcsElement extends AdapterBase implements NetworkElement, Re
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
if (!canHandle(network, Service.Connectivity)) {

View File

@ -434,6 +434,11 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
private boolean cleanupLogicalEdgeFirewall(long vlanId, long hostId) {
CleanupLogicalEdgeFirewallCommand cmd = new CleanupLogicalEdgeFirewallCommand(vlanId);
Answer answer = _agentMgr.easySend(hostId, cmd);

View File

@ -26,6 +26,7 @@ import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
@ -86,6 +87,11 @@ public class DnsNotifier extends AdapterBase implements NetworkElement {
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;

View File

@ -24,6 +24,7 @@ import java.util.Set;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.IpAddress;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@ -136,6 +137,11 @@ public class ElasticLoadBalancerElement extends AdapterBase implements LoadBalan
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO kill all loadbalancer vms by calling the ElasticLoadBalancerManager

View File

@ -26,6 +26,7 @@ import java.util.Set;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.IpAddress;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.springframework.stereotype.Component;
@ -175,6 +176,11 @@ public class GloboDnsElement extends AdapterBase implements ResourceStateAdapter
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;

View File

@ -26,6 +26,7 @@ import java.util.Set;
import javax.inject.Inject;
import com.cloud.network.IpAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@ -221,6 +222,11 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
List<? extends VirtualRouter> internalLbVms = _routerDao.listByNetworkAndRole(network.getId(), Role.INTERNAL_LB_VM);

View File

@ -244,6 +244,11 @@ public class ContrailElementImpl extends AdapterBase
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return false;
}
/**
* Network disable
*/

View File

@ -0,0 +1,30 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.agent.api;
public class ReleaseNatIpCommand extends NetrisCommand {
private String natIp;
public ReleaseNatIpCommand(long zoneId, Long accountId, Long domainId, String name, Long id, boolean isVpc, String natIp) {
super(zoneId, accountId, domainId, name, id, isVpc);
this.natIp = natIp;
}
public String getNatIp() {
return natIp;
}
}

View File

@ -38,6 +38,7 @@ import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.NetrisAnswer;
import org.apache.cloudstack.StartupNetrisCommand;
import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
import org.apache.cloudstack.service.NetrisApiClient;
import org.apache.cloudstack.service.NetrisApiClientImpl;
@ -109,6 +110,8 @@ public class NetrisResource implements ServerResource {
return executeRequest((DeleteNetrisStaticRouteCommand) cmd);
} else if (cmd instanceof AddOrUpdateNetrisStaticRouteCommand) {
return executeRequest((AddOrUpdateNetrisStaticRouteCommand) cmd);
} else if (cmd instanceof ReleaseNatIpCommand) {
return executeRequest((ReleaseNatIpCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@ -319,6 +322,14 @@ public class NetrisResource implements ServerResource {
return new NetrisAnswer(cmd, true, "OK");
}
private Answer executeRequest(ReleaseNatIpCommand cmd) {
boolean result = netrisApiClient.releaseNatIp(cmd);
if (!result) {
return new NetrisAnswer(cmd, false, String.format("Failed to release NAT IP: %s", cmd.getNatIp()));
}
return new NetrisAnswer(cmd, true, "OK");
}
@Override
public boolean start() {
return true;

View File

@ -28,6 +28,7 @@ import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
import java.util.List;
@ -78,4 +79,5 @@ public interface NetrisApiClient {
boolean deleteNatRule(DeleteNetrisNatRuleCommand cmd);
boolean addOrUpdateStaticRoute(AddOrUpdateNetrisStaticRouteCommand cmd);
boolean deleteStaticRoute(DeleteNetrisStaticRouteCommand cmd);
boolean releaseNatIp(ReleaseNatIpCommand cmd);
}

View File

@ -88,6 +88,7 @@ import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
import org.apache.cloudstack.resource.NetrisResourceObjectUtils;
import org.apache.commons.collections.CollectionUtils;
@ -441,6 +442,31 @@ public class NetrisApiClientImpl implements NetrisApiClient {
return false;
}
@Override
public boolean releaseNatIp(ReleaseNatIpCommand cmd) {
String natIp = cmd.getNatIp() + "/32";
try {
VPCListing systemVpc = getSystemVpc();
IpamApi ipamApi = apiClient.getApiStubForMethod(IpamApi.class);
FilterByVpc vpcFilter = new FilterByVpc();
vpcFilter.add(systemVpc.getId());
SubnetResBody subnetResponse = ipamApi.apiV2IpamSubnetsGet(vpcFilter);
if (subnetResponse == null || !subnetResponse.isIsSuccess()) {
String reason = subnetResponse == null ? "Empty response" : "Operation failed on Netris";
logger.debug("Failed to retrieve Netris Public NAT IPs due to {}", reason);
throw new CloudRuntimeException(reason);
}
List<IpTreeSubnet> natIps = subnetResponse.getData().stream().filter(ip -> ip.getPrefix().equals(natIp)).collect(Collectors.toList());
if (!natIps.isEmpty()) {
ipamApi.apiV2IpamTypeIdDelete("subnet", natIps.get(0).getId().intValue());
}
} catch (ApiException e) {
logAndThrowException("Failed to release Netris IP", e);
}
return true;
}
private Pair<Boolean, RoutesGetBody> staticRouteExists(Integer netrisVpcId, String prefix, String nextHop, String description) {
try {
FilterByVpc vpcFilter = new FilterByVpc();

View File

@ -320,6 +320,11 @@ public class NetrisElement extends AdapterBase implements DhcpServiceProvider, D
return false;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return netrisService.releaseNatIp(ipAddress.getDataCenterId(), ipAddress.getAddress().addr());
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return canHandle(network, Network.Service.Connectivity);

View File

@ -52,6 +52,7 @@ import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.NetrisAnswer;
import org.apache.cloudstack.agent.api.NetrisCommand;
import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -354,6 +355,13 @@ public class NetrisServiceImpl implements NetrisService, Configurable {
return answer.getResult();
}
@Override
public boolean releaseNatIp(long zoneId, String publicIp) {
ReleaseNatIpCommand cmd = new ReleaseNatIpCommand(zoneId, null, null, null, null, false, publicIp);
NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
return answer.getResult();
}
private String getResourceSuffix(Long vpcId, Long networkId, boolean isForVpc) {
String suffix;
if (isForVpc) {

View File

@ -420,6 +420,11 @@ IpDeployer, StaticNatServiceProvider, GslbServiceProvider {
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network guestConfig, ReservationContext context, boolean cleanup)
throws ResourceUnavailableException, ConcurrentOperationException {

View File

@ -448,6 +448,11 @@ NiciraNvpElementService, ResourceStateAdapter, IpDeployer {
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
if (!canHandle(network, Service.Connectivity)) {

View File

@ -284,6 +284,11 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns
return false;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return canHandle(network, Network.Service.Connectivity);

View File

@ -27,6 +27,7 @@ import java.util.Set;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.IpAddress;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.network.opendaylight.agent.commands.StartupOpenDaylightControllerCommand;
@ -102,6 +103,11 @@ public class OpendaylightElement extends AdapterBase implements ConnectivityProv
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;

View File

@ -25,6 +25,7 @@ import java.util.Set;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.IpAddress;
import org.apache.cloudstack.network.topology.NetworkTopology;
import org.apache.cloudstack.network.topology.NetworkTopologyContext;
@ -208,6 +209,11 @@ StaticNatServiceProvider, IpDeployer {
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(final Network network, final ReservationContext context,
final boolean cleanup) throws ConcurrentOperationException,

View File

@ -25,6 +25,7 @@ import java.util.Set;
import javax.inject.Inject;
import com.cloud.network.IpAddress;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
@ -174,6 +175,11 @@ public class PaloAltoExternalFirewallElement extends ExternalFirewallDeviceManag
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ResourceUnavailableException, ConcurrentOperationException {
DataCenter zone = _entityMgr.findById(DataCenter.class, network.getDataCenterId());

View File

@ -30,6 +30,7 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.IpAddress;
import org.apache.cloudstack.api.commands.AddSspCmd;
import org.apache.cloudstack.api.commands.DeleteSspCmd;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@ -510,6 +511,11 @@ public class SspElement extends AdapterBase implements ConnectivityProvider, Ssp
return deleteNicEnv(network, nic, context);
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
/* (non-Javadoc)
* Destroy a network implementation.
*

View File

@ -41,6 +41,7 @@ import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.IpAddress;
import com.cloud.network.IpAddressManager;
import com.cloud.network.Network;
import com.cloud.network.NetworkMigrationResponder;
@ -689,6 +690,11 @@ public class TungstenElement extends AdapterBase
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup)
throws ConcurrentOperationException {

View File

@ -43,6 +43,10 @@ import com.cloud.network.dao.Site2SiteVpnGatewayDao;
import com.cloud.network.element.NetrisProviderVO;
import com.cloud.network.element.NsxProviderVO;
import com.cloud.network.vo.PublicIpQuarantineVO;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.network.vpc.VpcOfferingServiceMapVO;
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
import com.cloud.resourcelimit.CheckedReservation;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -275,6 +279,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
@Inject
NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
@Inject
VpcOfferingServiceMapDao vpcOfferingServiceMapDao;
@Inject
PhysicalNetworkDao _physicalNetworkDao;
@Inject
PhysicalNetworkServiceProviderDao _pNSPDao;
@ -806,6 +812,30 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
} else if (publicIpQuarantine != null) {
removePublicIpAddressFromQuarantine(publicIpQuarantine.getId(), "Public IP address removed from quarantine as there was an error while disassociating it.");
}
Network network = _networksDao.findById(ipToBeDisassociated.getAssociatedWithNetworkId());
Vpc vpc = _vpcDao.findById(ip.getVpcId());
if (ObjectUtils.allNull(network, vpc)) {
return success;
}
List<String> providers;
if (Objects.nonNull(network)) {
NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
providers = _ntwkOfferingSrvcDao.listProvidersForServiceForNetworkOffering(offering.getId(), Service.NetworkACL);
} else {
VpcOffering offering = vpcOfferingDao.findById(vpc.getVpcOfferingId());
List<VpcOfferingServiceMapVO> servicesMap = vpcOfferingServiceMapDao.listProvidersForServiceForVpcOffering(offering.getId(), Service.NetworkACL);
providers = servicesMap.stream().map(VpcOfferingServiceMapVO::getProvider).collect(Collectors.toList());
}
if (providers.isEmpty()) {
throw new InvalidParameterValueException("Unable to find the provider for this network");
}
String provider = providers.get(0);
NetworkElement element = _networkModel.getElementImplementingProvider(provider);
if (element != null) {
element.releaseIp(ipToBeDisassociated);
}
} finally {
_ipAddressDao.releaseFromLockTable(addrId);
}

View File

@ -25,6 +25,7 @@ import java.util.Set;
import javax.inject.Inject;
import com.cloud.network.IpAddress;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@ -179,6 +180,11 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
}
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true; // assume that the agent will remove userdata etc

View File

@ -25,6 +25,7 @@ import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
@ -77,6 +78,11 @@ public class SecurityGroupElement extends AdapterBase implements NetworkElement
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;

View File

@ -24,6 +24,7 @@ import java.util.Set;
import javax.inject.Inject;
import com.cloud.network.IpAddress;
import org.apache.cloudstack.network.BgpPeer;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
@ -943,6 +944,11 @@ NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource, DnsServ
return true;
}
@Override
public boolean releaseIp(IpAddress ipAddress) {
return true;
}
@Override
public boolean configDhcpSupportForSubnet(final Network network, final NicProfile nic, final VirtualMachineProfile vm, final DeployDestination dest,

View File

@ -68,6 +68,11 @@ public class MockVpcOfferingServiceMapDaoImpl extends GenericDaoBase<VpcOffering
return false;
}
@Override
public List<VpcOfferingServiceMapVO> listProvidersForServiceForVpcOffering(long vpcOfferingId, Service service) {
return List.of();
}
@Override
public VpcOfferingServiceMapVO persist(VpcOfferingServiceMapVO vo) {
return vo;

View File

@ -86,4 +86,9 @@ public class NetrisServiceMockTest implements NetrisService {
public boolean deleteStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId) {
return true;
}
@Override
public boolean releaseNatIp(long zoneId, String publicIp) {
return true;
}
}