Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ env:

- TESTS="component/test_project_usage
component/test_protocol_number_security_group
component/test_public_ip
component/test_resource_limits"

- TESTS="component/test_regions_accounts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,5 +208,22 @@ void allocateNicValues(NicProfile nic, DataCenter dc, VirtualMachineProfile vm,
void releasePodIp(Long id) throws CloudRuntimeException;

boolean isUsageHidden(IPAddressVO address);

List<IPAddressVO> listAvailablePublicIps(final long dcId,
final Long podId,
final List<Long> vlanDbIds,
final Account owner,
final VlanType vlanUse,
final Long guestNetworkId,
final boolean sourceNat,
final boolean assign,
final boolean allocate,
final String requestedIp,
final boolean isSystem,
final Long vpcId,
final Boolean displayIp,
final boolean forSystemVms,
final boolean lockOneRow)
throws InsufficientAddressCapacityException;
}

14 changes: 14 additions & 0 deletions server/src/main/java/com/cloud/api/ApiDBUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import javax.annotation.PostConstruct;
import javax.inject.Inject;

import com.cloud.vm.NicVO;
import com.cloud.vm.dao.NicDao;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RoleService;
import org.apache.cloudstack.affinity.AffinityGroup;
Expand Down Expand Up @@ -458,6 +460,7 @@ public class ApiDBUtils {
static BackupDao s_backupDao;
static BackupScheduleDao s_backupScheduleDao;
static BackupOfferingDao s_backupOfferingDao;
static NicDao s_nicDao;

@Inject
private ManagementServer ms;
Expand Down Expand Up @@ -702,6 +705,8 @@ public class ApiDBUtils {
private BackupOfferingDao backupOfferingDao;
@Inject
private BackupScheduleDao backupScheduleDao;
@Inject
private NicDao nicDao;

@PostConstruct
void init() {
Expand Down Expand Up @@ -811,6 +816,7 @@ void init() {
s_hostDetailsDao = hostDetailsDao;
s_clusterDetailsDao = clusterDetailsDao;
s_vmSnapshotDao = vmSnapshotDao;
s_nicDao = nicDao;
s_nicSecondaryIpDao = nicSecondaryIpDao;
s_vpcProvSvc = vpcProvSvc;
s_affinityGroupDao = affinityGroupDao;
Expand Down Expand Up @@ -2079,4 +2085,12 @@ public static BackupScheduleResponse newBackupScheduleResponse(BackupSchedule sc
public static BackupOfferingResponse newBackupOfferingResponse(BackupOffering policy) {
return s_backupOfferingDao.newBackupOfferingResponse(policy);
}

public static NicVO findByIp4AddressAndNetworkId(String ip4Address, long networkId) {
return s_nicDao.findByIp4AddressAndNetworkId(ip4Address, networkId);
}

public static NicSecondaryIpVO findSecondaryIpByIp4AddressAndNetworkId(String ip4Address, long networkId) {
return s_nicSecondaryIpDao.findByIp4AddressAndNetworkId(ip4Address, networkId);
}
}
39 changes: 39 additions & 0 deletions server/src/main/java/com/cloud/api/ApiResponseHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,9 @@ public IPAddressResponse createIPAddressResponse(ResponseView view, IpAddress ip
}
}

// show vm info for shared networks
showVmInfoForSharedNetworks(forVirtualNetworks, ipAddr, ipResponse);

// show this info to full view only
if (view == ResponseView.Full) {
VlanVO vl = ApiDBUtils.findVlanById(ipAddr.getVlanId());
Expand Down Expand Up @@ -954,6 +957,42 @@ public IPAddressResponse createIPAddressResponse(ResponseView view, IpAddress ip
return ipResponse;
}

private void showVmInfoForSharedNetworks(boolean forVirtualNetworks, IpAddress ipAddr, IPAddressResponse ipResponse) {
if (!forVirtualNetworks) {
NicVO nic = ApiDBUtils.findByIp4AddressAndNetworkId(ipAddr.getAddress().toString(), ipAddr.getNetworkId());

if (nic == null) { // find in nic_secondary_ips, user vm only
NicSecondaryIpVO secondaryIp =
ApiDBUtils.findSecondaryIpByIp4AddressAndNetworkId(ipAddr.getAddress().toString(), ipAddr.getNetworkId());
if (secondaryIp != null) {
UserVm vm = ApiDBUtils.findUserVmById(secondaryIp.getVmId());
if (vm != null) {
ipResponse.setVirtualMachineId(vm.getUuid());
ipResponse.setVirtualMachineName(vm.getHostName());
if (vm.getDisplayName() != null) {
ipResponse.setVirtualMachineDisplayName(vm.getDisplayName());
} else {
ipResponse.setVirtualMachineDisplayName(vm.getHostName());
}
}
}
} else if (nic.getVmType() == VirtualMachine.Type.User) {
UserVm vm = ApiDBUtils.findUserVmById(nic.getInstanceId());
if (vm != null) {
ipResponse.setVirtualMachineId(vm.getUuid());
ipResponse.setVirtualMachineName(vm.getHostName());
if (vm.getDisplayName() != null) {
ipResponse.setVirtualMachineDisplayName(vm.getDisplayName());
} else {
ipResponse.setVirtualMachineDisplayName(vm.getHostName());
}
}
} else if (nic.getVmType() == VirtualMachine.Type.DomainRouter) {
ipResponse.setIsSystem(true);
}
}
}

@Override
public LoadBalancerResponse createLoadBalancerResponse(LoadBalancer loadBalancer) {
LoadBalancerResponse lbResponse = new LoadBalancerResponse();
Expand Down
112 changes: 65 additions & 47 deletions server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,31 +322,30 @@ private IPAddressVO assignAndAllocateIpAddressEntry(final Account owner, final V
}
}

for (final IPAddressVO possibleAddr : addressVOS) {
for (IPAddressVO possibleAddr : addressVOS) {
if (possibleAddr.getState() != State.Free) {
continue;
}
final IPAddressVO addressVO = possibleAddr;
addressVO.setSourceNat(sourceNat);
addressVO.setAllocatedTime(new Date());
addressVO.setAllocatedInDomainId(owner.getDomainId());
addressVO.setAllocatedToAccountId(owner.getId());
addressVO.setSystem(isSystem);
possibleAddr.setSourceNat(sourceNat);
possibleAddr.setAllocatedTime(new Date());
possibleAddr.setAllocatedInDomainId(owner.getDomainId());
possibleAddr.setAllocatedToAccountId(owner.getId());
possibleAddr.setSystem(isSystem);

if (displayIp != null) {
addressVO.setDisplay(displayIp);
possibleAddr.setDisplay(displayIp);
}

if (vlanUse != VlanType.DirectAttached) {
addressVO.setAssociatedWithNetworkId(guestNetworkId);
addressVO.setVpcId(vpcId);
possibleAddr.setAssociatedWithNetworkId(guestNetworkId);
possibleAddr.setVpcId(vpcId);
}
if (_ipAddressDao.lockRow(possibleAddr.getId(), true) != null) {
final IPAddressVO userIp = _ipAddressDao.findById(addressVO.getId());
final IPAddressVO userIp = _ipAddressDao.findById(possibleAddr.getId());
if (userIp.getState() == State.Free) {
addressVO.setState(State.Allocating);
if (_ipAddressDao.update(addressVO.getId(), addressVO)) {
finalAddress = addressVO;
possibleAddr.setState(State.Allocating);
if (_ipAddressDao.update(possibleAddr.getId(), possibleAddr)) {
finalAddress = possibleAddr;
break;
}
}
Expand Down Expand Up @@ -783,9 +782,22 @@ public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List<L
public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId,
final boolean sourceNat, final boolean assign, final boolean allocate, final String requestedIp, final boolean isSystem, final Long vpcId, final Boolean displayIp, final boolean forSystemVms)
throws InsufficientAddressCapacityException {
IPAddressVO addr = Transaction.execute(new TransactionCallbackWithException<IPAddressVO, InsufficientAddressCapacityException>() {
List<IPAddressVO> addrs = listAvailablePublicIps(dcId, podId, vlanDbIds, owner, vlanUse, guestNetworkId, sourceNat, assign, allocate, requestedIp, isSystem, vpcId, displayIp, forSystemVms, true);
IPAddressVO addr = addrs.get(0);
if (vlanUse == VlanType.VirtualNetwork) {
_firewallMgr.addSystemFirewallRules(addr, owner);
}

return PublicIp.createFromAddrAndVlan(addr, _vlanDao.findById(addr.getVlanId()));
}

@Override
public List<IPAddressVO> listAvailablePublicIps(final long dcId, final Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId,
final boolean sourceNat, final boolean assign, final boolean allocate, final String requestedIp, final boolean isSystem,
final Long vpcId, final Boolean displayIp, final boolean forSystemVms, final boolean lockOneRow) throws InsufficientAddressCapacityException {
return Transaction.execute(new TransactionCallbackWithException<List<IPAddressVO>, InsufficientAddressCapacityException>() {
@Override
public IPAddressVO doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
public List<IPAddressVO> doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
StringBuilder errorMessage = new StringBuilder("Unable to get ip address in ");
boolean fetchFromDedicatedRange = false;
List<Long> dedicatedVlanDbIds = new ArrayList<Long>();
Expand Down Expand Up @@ -823,23 +835,26 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
if (vlanDbIds == null || vlanDbIds.contains(nonDedicatedVlan.getId()))
nonDedicatedVlanDbIds.add(nonDedicatedVlan.getId());
}
if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds.isEmpty()) {
fetchFromDedicatedRange = true;
sc.setParameters("vlanId", dedicatedVlanDbIds.toArray());
errorMessage.append(", vlanId id=" + Arrays.toString(dedicatedVlanDbIds.toArray()));
} else if (nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
} else {
if (podId != null) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());

if (vlanUse == VlanType.VirtualNetwork) {
if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds.isEmpty()) {
fetchFromDedicatedRange = true;
sc.setParameters("vlanId", dedicatedVlanDbIds.toArray());
errorMessage.append(", vlanId id=" + Arrays.toString(dedicatedVlanDbIds.toArray()));
} else if (nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
} else {
if (podId != null) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
throw ex;
}
s_logger.warn(errorMessage.toString());
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId);
ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
throw ex;
}
s_logger.warn(errorMessage.toString());
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId);
ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
throw ex;
}

sc.setParameters("dc", dcId);
Expand All @@ -864,21 +879,31 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient

filter.addOrderBy(IPAddressVO.class,"vlanId", true);

List<IPAddressVO> addrs = _ipAddressDao.search(sc, filter, false);
List<IPAddressVO> addrs;

if (lockOneRow) {
addrs = _ipAddressDao.lockRows(sc, filter, true);
} else {
addrs = new ArrayList<>(_ipAddressDao.search(sc, null));
}

// If all the dedicated IPs of the owner are in use fetch an IP from the system pool
if (addrs.size() == 0 && fetchFromDedicatedRange) {
if ((!lockOneRow || (lockOneRow && addrs.size() == 0)) && fetchFromDedicatedRange && vlanUse == VlanType.VirtualNetwork) {
// Verify if account is allowed to acquire IPs from the system
boolean useSystemIps = UseSystemPublicIps.valueIn(owner.getId());
if (useSystemIps && nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
fetchFromDedicatedRange = false;
sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
errorMessage.append(", vlanId id=" + Arrays.toString(nonDedicatedVlanDbIds.toArray()));
addrs = _ipAddressDao.search(sc, filter, false);
if (lockOneRow) {
addrs = _ipAddressDao.lockRows(sc, filter, true);
} else {
addrs.addAll(_ipAddressDao.search(sc, null));
}
}
}

if (addrs.size() == 0) {
if (lockOneRow && addrs.size() == 0) {
if (podId != null) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
// for now, we hardcode the table names, but we should ideally do a lookup for the tablename from the VO object.
Expand All @@ -891,23 +916,16 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
throw ex;
}

assert(addrs.size() == 1) : "Return size is incorrect: " + addrs.size();
IPAddressVO finalAddr = null;
if (lockOneRow) {
assert (addrs.size() == 1) : "Return size is incorrect: " + addrs.size();
}
if (assign) {
finalAddr = assignAndAllocateIpAddressEntry(owner, vlanUse, guestNetworkId, sourceNat, allocate,
assignAndAllocateIpAddressEntry(owner, vlanUse, guestNetworkId, sourceNat, allocate,
isSystem,vpcId, displayIp, fetchFromDedicatedRange, addrs);
} else {
finalAddr = addrs.get(0);
}
return finalAddr;
return addrs;
}
});

if (vlanUse == VlanType.VirtualNetwork) {
_firewallMgr.addSystemFirewallRules(addr, owner);
}

return PublicIp.createFromAddrAndVlan(addr, _vlanDao.findById(addr.getVlanId()));
}

@DB
Expand Down
Loading