mirror of https://github.com/apache/cloudstack.git
Address public IP limit validations
This commit is contained in:
parent
e8f8aca694
commit
dc7068a135
|
|
@ -27,6 +27,6 @@ public interface AccountVlanMapDao extends GenericDao<AccountVlanMapVO, Long> {
|
|||
|
||||
public List<AccountVlanMapVO> listAccountVlanMapsByVlan(long vlanDbId);
|
||||
|
||||
public AccountVlanMapVO findAccountVlanMap(long accountId, long vlanDbId);
|
||||
public AccountVlanMapVO findAccountVlanMap(Long accountId, long vlanDbId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ public class AccountVlanMapDaoImpl extends GenericDaoBase<AccountVlanMapVO, Long
|
|||
}
|
||||
|
||||
@Override
|
||||
public AccountVlanMapVO findAccountVlanMap(long accountId, long vlanDbId) {
|
||||
public AccountVlanMapVO findAccountVlanMap(Long accountId, long vlanDbId) {
|
||||
SearchCriteria<AccountVlanMapVO> sc = AccountVlanSearch.create();
|
||||
sc.setParameters("accountId", accountId);
|
||||
sc.setParametersIfNotNull("accountId", accountId);
|
||||
sc.setParameters("vlanDbId", vlanDbId);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,5 +24,5 @@ import com.cloud.utils.db.GenericDao;
|
|||
public interface DomainVlanMapDao extends GenericDao<DomainVlanMapVO, Long> {
|
||||
public List<DomainVlanMapVO> listDomainVlanMapsByDomain(long domainId);
|
||||
public List<DomainVlanMapVO> listDomainVlanMapsByVlan(long vlanDbId);
|
||||
public DomainVlanMapVO findDomainVlanMap(long domainId, long vlanDbId);
|
||||
public DomainVlanMapVO findDomainVlanMap(Long domainId, long vlanDbId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ public class DomainVlanMapDaoImpl extends GenericDaoBase<DomainVlanMapVO, Long>
|
|||
}
|
||||
|
||||
@Override
|
||||
public DomainVlanMapVO findDomainVlanMap(long domainId, long vlanDbId) {
|
||||
public DomainVlanMapVO findDomainVlanMap(Long domainId, long vlanDbId) {
|
||||
SearchCriteria<DomainVlanMapVO> sc = DomainVlanSearch.create();
|
||||
sc.setParameters("domainId", domainId);
|
||||
sc.setParametersIfNotNull("domainId", domainId);
|
||||
sc.setParameters("vlanDbId", vlanDbId);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2244,6 +2244,10 @@ public class ApiDBUtils {
|
|||
return s_accountService.isAdmin(account.getId());
|
||||
}
|
||||
|
||||
public static Account getSystemAccount() {
|
||||
return s_accountService.getSystemAccount();
|
||||
}
|
||||
|
||||
public static List<ResourceTagJoinVO> listResourceTagViewByResourceUUID(String resourceUUID, ResourceObjectType resourceType) {
|
||||
return s_tagJoinDao.listBy(resourceUUID, resourceType);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ import javax.naming.ConfigurationException;
|
|||
|
||||
import com.cloud.exception.UnsupportedServiceException;
|
||||
import com.cloud.network.as.AutoScaleManager;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.user.AccountManagerImpl;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
|
|
@ -128,6 +129,7 @@ import org.apache.cloudstack.region.PortableIpVO;
|
|||
import org.apache.cloudstack.region.Region;
|
||||
import org.apache.cloudstack.region.RegionVO;
|
||||
import org.apache.cloudstack.region.dao.RegionDao;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
|
|
@ -395,6 +397,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
@Inject
|
||||
ResourceLimitService _resourceLimitMgr;
|
||||
@Inject
|
||||
ReservationDao reservationDao;
|
||||
@Inject
|
||||
ProjectManager _projectMgr;
|
||||
@Inject
|
||||
DataStoreManager _dataStoreMgr;
|
||||
|
|
@ -4833,22 +4837,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks");
|
||||
}
|
||||
|
||||
if (forVirtualNetwork) {
|
||||
if (vlanOwner != null) {
|
||||
|
||||
final long accountIpRange = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1;
|
||||
|
||||
// check resource limits
|
||||
_resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountIpRange);
|
||||
}
|
||||
}
|
||||
// Check if the IP range overlaps with the private ip
|
||||
if (ipv4) {
|
||||
checkOverlapPrivateIpRange(zoneId, startIP, endIP);
|
||||
}
|
||||
|
||||
return commitVlan(zoneId, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId, forVirtualNetwork, forSystemVms, networkId, physicalNetworkId, startIPv6, endIPv6, ip6Gateway,
|
||||
ip6Cidr, domain, vlanOwner, network, sameSubnet, cmd.isForNsx());
|
||||
long reservedIpAddressesAmount = 0L;
|
||||
if (forVirtualNetwork && vlanOwner != null) {
|
||||
reservedIpAddressesAmount = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1;
|
||||
}
|
||||
|
||||
try (CheckedReservation publicIpReservation = new CheckedReservation(vlanOwner, ResourceType.public_ip, null, null, null, reservedIpAddressesAmount, null, reservationDao, _resourceLimitMgr)) {
|
||||
return commitVlan(zoneId, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId, forVirtualNetwork, forSystemVms, networkId, physicalNetworkId, startIPv6, endIPv6, ip6Gateway,
|
||||
ip6Cidr, domain, vlanOwner, network, sameSubnet, cmd.isForNsx());
|
||||
}
|
||||
}
|
||||
|
||||
private Network getNetwork(Long networkId) {
|
||||
|
|
@ -5377,7 +5379,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
String endIpv6,
|
||||
String ip6Gateway,
|
||||
String ip6Cidr,
|
||||
Boolean forSystemVms) throws ConcurrentOperationException {
|
||||
Boolean forSystemVms) throws ConcurrentOperationException, ResourceAllocationException {
|
||||
|
||||
VlanVO vlanRange = _vlanDao.findById(id);
|
||||
if (vlanRange == null) {
|
||||
|
|
@ -5397,24 +5399,50 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
}
|
||||
|
||||
AccountVlanMapVO accountMap = _accountVlanMapDao.findAccountVlanMap(null, id);
|
||||
Account account = accountMap != null ? _accountDao.findById(accountMap.getAccountId()) : null;
|
||||
|
||||
DomainVlanMapVO domainMap = _domainVlanMapDao.findDomainVlanMap(null, id);
|
||||
Long domainId = domainMap != null ? domainMap.getDomainId() : null;
|
||||
|
||||
final Boolean isRangeForSystemVM = checkIfVlanRangeIsForSystemVM(id);
|
||||
if (forSystemVms != null && isRangeForSystemVM != forSystemVms) {
|
||||
if (VlanType.DirectAttached.equals(vlanRange.getVlanType())) {
|
||||
throw new InvalidParameterValueException("forSystemVms is not available for this IP range with vlan type: " + VlanType.DirectAttached);
|
||||
}
|
||||
// Check if range has already been dedicated
|
||||
final List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByVlan(id);
|
||||
if (maps != null && !maps.isEmpty()) {
|
||||
if (account != null) {
|
||||
throw new InvalidParameterValueException("Specified Public IP range has already been dedicated to an account");
|
||||
}
|
||||
|
||||
List<DomainVlanMapVO> domainmaps = _domainVlanMapDao.listDomainVlanMapsByVlan(id);
|
||||
if (domainmaps != null && !domainmaps.isEmpty()) {
|
||||
if (domainId != null) {
|
||||
throw new InvalidParameterValueException("Specified Public IP range has already been dedicated to a domain");
|
||||
}
|
||||
}
|
||||
if (ipv4) {
|
||||
long existingIpAddressAmount = 0L;
|
||||
long newIpAddressAmount = 0L;
|
||||
|
||||
if (account != null) {
|
||||
// IPv4 public range is dedicated to an account (IPv6 cannot be dedicated at the moment).
|
||||
// We need to update the resource count.
|
||||
existingIpAddressAmount = _publicIpAddressDao.countIPs(vlanRange.getDataCenterId(), id, false);
|
||||
newIpAddressAmount = NetUtils.ip2Long(endIp) - NetUtils.ip2Long(startIp) + 1;
|
||||
}
|
||||
|
||||
try (CheckedReservation publicIpReservation = new CheckedReservation(account, ResourceType.public_ip, null, null, null, newIpAddressAmount, existingIpAddressAmount, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
updateVlanAndIpv4Range(id, vlanRange, startIp, endIp, gateway, netmask, isRangeForSystemVM, forSystemVms);
|
||||
|
||||
if (account != null) {
|
||||
long countDiff = newIpAddressAmount - existingIpAddressAmount;
|
||||
if (countDiff > 0) {
|
||||
_resourceLimitMgr.incrementResourceCount(account.getId(), ResourceType.public_ip, countDiff);
|
||||
} else if (countDiff < 0) {
|
||||
_resourceLimitMgr.decrementResourceCount(account.getId(), ResourceType.public_ip, Math.abs(countDiff));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (ipv6) {
|
||||
updateVlanAndIpv6Range(id, vlanRange, startIpv6, endIpv6, ip6Gateway, ip6Cidr, isRangeForSystemVM, forSystemVms);
|
||||
|
|
@ -5801,12 +5829,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
throw new InvalidParameterValueException("Public IP range can be dedicated to an account only in the zone of type " + NetworkType.Advanced);
|
||||
}
|
||||
|
||||
// Check Public IP resource limits
|
||||
if (vlanOwner != null) {
|
||||
final int accountPublicIpRange = _publicIpAddressDao.countIPs(zoneId, vlanDbId, false);
|
||||
_resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountPublicIpRange);
|
||||
}
|
||||
|
||||
// Check if any of the Public IP addresses is allocated to another
|
||||
// account
|
||||
final List<IPAddressVO> ips = _publicIpAddressDao.listByVlanId(vlanDbId);
|
||||
|
|
@ -5827,6 +5849,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
}
|
||||
|
||||
// Check Public IP resource limits
|
||||
long reservedIpAddressesAmount = vlanOwner != null ? _publicIpAddressDao.countIPs(zoneId, vlanDbId, false) : 0L;
|
||||
try (CheckedReservation publicIpReservation = new CheckedReservation(vlanOwner, ResourceType.public_ip, null, null, null, reservedIpAddressesAmount, null, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
if (vlanOwner != null) {
|
||||
// Create an AccountVlanMapVO entry
|
||||
final AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(vlanOwner.getId(), vlan.getId());
|
||||
|
|
@ -5850,6 +5876,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
|
||||
return vlan;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import java.util.UUID;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
import org.apache.cloudstack.alert.AlertService;
|
||||
|
|
@ -75,6 +76,7 @@ import org.apache.cloudstack.network.NetworkPermissionVO;
|
|||
import org.apache.cloudstack.network.RoutedIpv4Manager;
|
||||
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
|
||||
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
|
@ -328,6 +330,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
@Inject
|
||||
ResourceLimitService _resourceLimitMgr;
|
||||
@Inject
|
||||
ReservationDao reservationDao;
|
||||
@Inject
|
||||
DomainManager _domainMgr;
|
||||
@Inject
|
||||
ProjectManager _projectMgr;
|
||||
|
|
@ -1143,15 +1147,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
if (ipDedicatedAccountId != null && !ipDedicatedAccountId.equals(account.getAccountId())) {
|
||||
throw new InvalidParameterValueException("Unable to reserve a IP because it is dedicated to another Account.");
|
||||
}
|
||||
if (ipDedicatedAccountId == null) {
|
||||
// Check that the maximum number of public IPs for the given accountId will not be exceeded
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(account, Resource.ResourceType.public_ip);
|
||||
} catch (ResourceAllocationException ex) {
|
||||
logger.warn("Failed to allocate resource of type " + ex.getResourceType() + " for account " + account);
|
||||
throw new AccountLimitException("Maximum number of public IP addresses for account: " + account.getAccountName() + " has been exceeded.");
|
||||
}
|
||||
}
|
||||
|
||||
long reservedIpAddressesAmount = ipDedicatedAccountId == null ? 1L : 0L;
|
||||
try (CheckedReservation publicIpAddressReservation = new CheckedReservation(account, Resource.ResourceType.public_ip, reservedIpAddressesAmount, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByVlan(ipVO.getVlanId());
|
||||
ipVO.setAllocatedTime(new Date());
|
||||
ipVO.setAllocatedToAccountId(account.getAccountId());
|
||||
|
|
@ -1161,10 +1160,15 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
ipVO.setDisplay(displayIp);
|
||||
}
|
||||
ipVO = _ipAddressDao.persist(ipVO);
|
||||
if (ipDedicatedAccountId == null) {
|
||||
if (reservedIpAddressesAmount > 0) {
|
||||
_resourceLimitMgr.incrementResourceCount(account.getId(), Resource.ResourceType.public_ip);
|
||||
}
|
||||
return ipVO;
|
||||
|
||||
} catch (ResourceAllocationException ex) {
|
||||
logger.warn("Failed to allocate resource of type " + ex.getResourceType() + " for account " + account);
|
||||
throw new AccountLimitException("Maximum number of public IP addresses for account: " + account.getAccountName() + " has been exceeded.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.reservation.ReservationVO;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
|
|
@ -146,6 +147,11 @@ public class CheckedReservation implements Reserver {
|
|||
|
||||
this.reservationDao = reservationDao;
|
||||
this.resourceLimitService = resourceLimitService;
|
||||
|
||||
// When allocating to a domain instead of a specific account, consider the system account as the owner for the validations here.
|
||||
if (account == null) {
|
||||
account = ApiDBUtils.getSystemAccount();
|
||||
}
|
||||
this.account = account;
|
||||
|
||||
if (domainId == null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue