Reserve source NAT IP when its not passed for NSX VPC

This commit is contained in:
nvazquez 2023-10-26 01:16:59 -03:00
parent 3615b10e49
commit d7afd53164
No known key found for this signature in database
GPG Key ID: 656E1BCC8CB54F84
4 changed files with 82 additions and 0 deletions

View File

@ -19,6 +19,7 @@ package com.cloud.network;
import java.util.List;
import java.util.Map;
import com.cloud.dc.DataCenter;
import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
@ -85,6 +86,8 @@ public interface NetworkService {
IpAddress reserveIpAddress(Account account, Boolean displayIp, Long ipAddressId) throws ResourceAllocationException;
IpAddress reserveIpAddressWithVlanDetail(Account account, DataCenter zone, Boolean displayIp, String vlanDetailKey) throws ResourceAllocationException;
boolean releaseReservedIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;
boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;

View File

@ -41,6 +41,8 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.dc.VlanDetailsVO;
import com.cloud.dc.dao.VlanDetailsDao;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.dao.ServiceOfferingDao;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
@ -281,6 +283,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
@Inject
VlanDao _vlanDao = null;
@Inject
private VlanDetailsDao vlanDetailsDao;
@Inject
IPAddressDao _ipAddressDao = null;
@Inject
AccountDao _accountDao = null;
@ -1134,6 +1138,58 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
return ipVO;
}
@Override
public IpAddress reserveIpAddressWithVlanDetail(Account account, DataCenter zone, Boolean displayIp, String vlanDetailKey) throws ResourceAllocationException {
// verify permissions
Account caller = CallContext.current().getCallingAccount();
_accountMgr.checkAccess(caller, null, true, account);
VlanVO vlan = findOneVlanRangeMatchingVlanDetailKey(zone, vlanDetailKey);
if (vlan == null) {
String msg = String.format("Cannot find any vlan matching the detail key %s on zone %s", vlanDetailKey, zone.getName());
s_logger.error(msg);
throw new CloudRuntimeException(msg);
}
List<IPAddressVO> freeIps = _ipAddressDao.listByVlanIdAndState(vlan.getId(), State.Free);
if (CollectionUtils.isEmpty(freeIps)) {
String msg = String.format("Cannot find any free IP matching on the VLAN range %s on zone %s", vlan.getIpRange(), zone.getName());
s_logger.error(msg);
throw new CloudRuntimeException(msg);
}
Collections.shuffle(freeIps);
IPAddressVO selectedIp = freeIps.get(0);
selectedIp.setAllocatedTime(new Date());
selectedIp.setAllocatedToAccountId(account.getAccountId());
selectedIp.setAllocatedInDomainId(account.getDomainId());
selectedIp.setState(State.Reserved);
if (displayIp != null) {
selectedIp.setDisplay(displayIp);
}
selectedIp = _ipAddressDao.persist(selectedIp);
Long ipDedicatedAccountId = getIpDedicatedAccountId(selectedIp.getVlanId());
if (ipDedicatedAccountId == null) {
_resourceLimitMgr.incrementResourceCount(account.getId(), Resource.ResourceType.public_ip);
}
return selectedIp;
}
private VlanVO findOneVlanRangeMatchingVlanDetailKey(DataCenter zone, String vlanDetailKey) {
List<VlanVO> zoneVlans = _vlanDao.listByZone(zone.getId());
for (VlanVO zoneVlan : zoneVlans) {
VlanDetailsVO detail = vlanDetailsDao.findDetail(zoneVlan.getId(), vlanDetailKey);
if (detail != null && detail.getValue().equalsIgnoreCase("true")) {
s_logger.debug(String.format("Found the VLAN range %s is set for NSX on zone %s", zoneVlan.getIpRange(), zone.getName()));
return zoneVlan;
}
}
return null;
}
private Long getIpDedicatedAccountId(Long vlanId) {
List<AccountVlanMapVO> accountVlanMaps = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanId);
if (CollectionUtils.isNotEmpty(accountVlanMaps)) {

View File

@ -1171,11 +1171,23 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
return vpc;
}
private boolean isVpcForNsx(Vpc vpc) {
VpcOfferingServiceMapVO mapVO = _vpcOffSvcMapDao.findByServiceProviderAndOfferingId(Service.SourceNat.getName(), Provider.Nsx.getName(), vpc.getVpcOfferingId());
if (mapVO != null) {
s_logger.debug(String.format("The VPC %s is NSX-based and supports the %s service", vpc.getName(), Service.SourceNat.getName()));
}
return mapVO != null;
}
private void allocateSourceNatIp(Vpc vpc, String sourceNatIP) {
Account account = _accountMgr.getAccount(vpc.getAccountId());
DataCenter zone = _dcDao.findById(vpc.getZoneId());
// reserve this ip and then
try {
if (isVpcForNsx(vpc) && org.apache.commons.lang3.StringUtils.isBlank(sourceNatIP)) {
s_logger.debug(String.format("Reserving a source NAT IP for NSX VPC %s", vpc.getName()));
sourceNatIP = reserveSourceNatIpForNsxVpc(account, zone, vpc);
}
IpAddress ip = _ipAddrMgr.allocateIp(account, false, CallContext.current().getCallingAccount(), CallContext.current().getCallingUserId(), zone, null, sourceNatIP);
this.associateIPToVpc(ip.getId(), vpc.getId());
} catch (ResourceAllocationException | ResourceUnavailableException | InsufficientAddressCapacityException e){
@ -1183,6 +1195,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
}
}
private String reserveSourceNatIpForNsxVpc(Account account, DataCenter zone, Vpc vpc) throws ResourceAllocationException {
IpAddress ipAddress = _ntwkSvc.reserveIpAddressWithVlanDetail(account, zone, true, ApiConstants.NSX_DETAIL_KEY);
return ipAddress.getAddress().addr();
}
@DB
protected Vpc createVpc(final Boolean displayVpc, final VpcVO vpc) {
final String cidr = vpc.getCidr();

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.vpc;
import com.cloud.dc.DataCenter;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
@ -176,6 +177,11 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
return null;
}
@Override
public IpAddress reserveIpAddressWithVlanDetail(Account account, DataCenter zone, Boolean displayIp, String vlanDetailKey) throws ResourceAllocationException {
return null;
}
@Override
public boolean releaseReservedIpAddress(long ipAddressId) throws InsufficientAddressCapacityException {
return false;