Merge branch '4.18'

This commit is contained in:
Daan Hoogland 2023-08-07 11:13:17 +02:00
commit 32448e1ac7
12 changed files with 213 additions and 64 deletions

View File

@ -164,6 +164,8 @@ public interface VolumeApiService {
Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge); Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge);
void destroyVolume(long volumeId);
Volume recoverVolume(long volumeId); Volume recoverVolume(long volumeId);
void validateCustomDiskOfferingSizeRange(Long sizeInGB); void validateCustomDiskOfferingSizeRange(Long sizeInGB);

View File

@ -429,6 +429,14 @@ public interface UserVmService {
UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
StorageUnavailableException, ResourceAllocationException; StorageUnavailableException, ResourceAllocationException;
/**
* This API is mostly to trigger VM.CREATE event for deployVirtualMachine with startvm=false, because there is no code in "execute" part of VM creation.
* However, it can be used for additional VM customization in the future.
* @param vmId - Virtual Machine Id
* @return - Virtual Machine
*/
UserVm finalizeCreateVirtualMachine(long vmId);
UserVm getUserVm(long vmId); UserVm getUserVm(long vmId);
VirtualMachine getVm(long vmId); VirtualMachine getVm(long vmId);

View File

@ -769,8 +769,11 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
@Override @Override
public String getEventDescription() { public String getEventDescription() {
if(getStartVm()) {
return "starting Vm. Vm Id: " + getEntityUuid(); return "starting Vm. Vm Id: " + getEntityUuid();
} }
return "deploying Vm. Vm Id: " + getEntityUuid();
}
@Override @Override
public ApiCommandResourceType getApiResourceType() { public ApiCommandResourceType getApiResourceType() {
@ -781,8 +784,9 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
public void execute() { public void execute() {
UserVm result; UserVm result;
try {
CallContext.current().setEventDetails("Vm Id: " + getEntityUuid()); CallContext.current().setEventDetails("Vm Id: " + getEntityUuid());
if (getStartVm()) {
try {
result = _userVmService.startVirtualMachine(this); result = _userVmService.startVirtualMachine(this);
} catch (ResourceUnavailableException ex) { } catch (ResourceUnavailableException ex) {
s_logger.warn("Exception: ", ex); s_logger.warn("Exception: ", ex);
@ -800,10 +804,14 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them"); message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them");
} }
} }
s_logger.info(ex); s_logger.info(String.format("%s: %s", message.toString(), ex.getLocalizedMessage()));
s_logger.info(message.toString(), ex); s_logger.debug(message.toString(), ex);
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString()); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString());
} }
} else {
s_logger.info("VM " + getEntityUuid() + " already created, load UserVm from DB");
result = _userVmService.finalizeCreateVirtualMachine(getEntityId());
}
if (result != null) { if (result != null) {
UserVmResponse response = _responseGenerator.createUserVmResponse(getResponseView(), "virtualmachine", result).get(0); UserVmResponse response = _responseGenerator.createUserVmResponse(getResponseView(), "virtualmachine", result).get(0);

View File

@ -500,6 +500,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
allocateRootVolume(persistedVm, template, rootDiskOfferingInfo, owner, rootDiskSizeFinal); allocateRootVolume(persistedVm, template, rootDiskOfferingInfo, owner, rootDiskSizeFinal);
// Create new Volume context and inject event resource type, id and details to generate VOLUME.CREATE event for the ROOT disk.
CallContext volumeContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Volume);
try {
if (dataDiskOfferings != null) { if (dataDiskOfferings != null) {
for (final DiskOfferingInfo dataDiskOfferingInfo : dataDiskOfferings) { for (final DiskOfferingInfo dataDiskOfferingInfo : dataDiskOfferings) {
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId(), dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(), volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId(), dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(),
@ -517,6 +520,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
diskNumber++; diskNumber++;
} }
} }
} finally {
// Remove volumeContext and pop vmContext back
CallContext.unregister();
}
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug("Allocation completed for VM: " + persistedVm); s_logger.debug("Allocation completed for VM: " + persistedVm);

View File

@ -819,7 +819,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
vol.getTemplateId()); vol.getTemplateId());
} }
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating ROOT volume", create = true) @ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating volume", create = true)
@Override @Override
public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner, public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner,
Long deviceId) { Long deviceId) {
@ -1035,13 +1035,13 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
private void updateRootDiskVolumeEventDetails(Type type, VirtualMachine vm, List<DiskProfile> diskProfiles) { private void updateRootDiskVolumeEventDetails(Type type, VirtualMachine vm, List<DiskProfile> diskProfiles) {
CallContext callContext = CallContext.current(); CallContext callContext = CallContext.current();
// Update only for volume type ROOT and API command resource type Volume // Update only for volume type ROOT and API command resource type Volume
if (type == Type.ROOT && callContext != null && callContext.getEventResourceType() == ApiCommandResourceType.Volume) { if ((type == Type.ROOT || type == Type.DATADISK) && callContext != null && callContext.getEventResourceType() == ApiCommandResourceType.Volume) {
List<Long> volumeIds = diskProfiles.stream().map(DiskProfile::getVolumeId).filter(volumeId -> volumeId != null).collect(Collectors.toList()); List<Long> volumeIds = diskProfiles.stream().map(DiskProfile::getVolumeId).filter(volumeId -> volumeId != null).collect(Collectors.toList());
if (!volumeIds.isEmpty()) { if (!volumeIds.isEmpty()) {
callContext.setEventResourceId(volumeIds.get(0)); callContext.setEventResourceId(volumeIds.get(0));
} }
String volumeUuids = volumeIds.stream().map(volumeId -> this._uuidMgr.getUuid(Volume.class, volumeId)).collect(Collectors.joining(", ")); String volumeUuids = volumeIds.stream().map(volumeId -> this._uuidMgr.getUuid(Volume.class, volumeId)).collect(Collectors.joining(", "));
callContext.setEventDetails("Volume Id: " + volumeUuids + " Vm Id: " + this._uuidMgr.getUuid(VirtualMachine.class, vm.getId())); callContext.setEventDetails("Volume Type: " + type + "Volume Id: " + volumeUuids + " Vm Id: " + this._uuidMgr.getUuid(VirtualMachine.class, vm.getId()));
} }
} }
@ -1245,7 +1245,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
// Destroy volume if not already destroyed // Destroy volume if not already destroyed
boolean volumeAlreadyDestroyed = (vol.getState() == Volume.State.Destroy || vol.getState() == Volume.State.Expunged || vol.getState() == Volume.State.Expunging); boolean volumeAlreadyDestroyed = (vol.getState() == Volume.State.Destroy || vol.getState() == Volume.State.Expunged || vol.getState() == Volume.State.Expunging);
if (!volumeAlreadyDestroyed) { if (!volumeAlreadyDestroyed) {
volService.destroyVolume(vol.getId()); destroyVolumeInContext(vol);
} else { } else {
s_logger.debug(String.format("Skipping destroy for the volume [%s] as it is in [%s] state.", volumeToString, vol.getState().toString())); s_logger.debug(String.format("Skipping destroy for the volume [%s] as it is in [%s] state.", volumeToString, vol.getState().toString()));
} }
@ -1277,6 +1277,21 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
} }
} }
private void destroyVolumeInContext(Volume volume) {
// Create new context and inject correct event resource type, id and details,
// otherwise VOLUME.DESTROY event will be associated with VirtualMachine and contain VM id and other information.
CallContext volumeContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Volume);
volumeContext.setEventDetails("Volume Type: " + volume.getVolumeType() + " Volume Id: " + volume.getUuid() + " Vm Id: " + _uuidMgr.getUuid(VirtualMachine.class, volume.getInstanceId()));
volumeContext.setEventResourceType(ApiCommandResourceType.Volume);
volumeContext.setEventResourceId(volume.getId());
try {
_volumeApiService.destroyVolume(volume.getId());
} finally {
// Remove volumeContext and pop vmContext back
CallContext.unregister();
}
}
@Override @Override
public void revokeAccess(DataObject dataObject, Host host, DataStore dataStore) { public void revokeAccess(DataObject dataObject, Host host, DataStore dataStore) {
DataStoreDriver dataStoreDriver = dataStore != null ? dataStore.getDriver() : null; DataStoreDriver dataStoreDriver = dataStore != null ? dataStore.getDriver() : null;
@ -2080,7 +2095,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplay()); _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplay());
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplay(), new Long(volume.getSize())); _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplay(), new Long(volume.getSize()));
} else { } else {
volService.destroyVolume(volume.getId()); destroyVolumeInContext(volume);
} }
// FIXME - All this is boiler plate code and should be done as part of state transition. This shouldn't be part of orchestrator. // FIXME - All this is boiler plate code and should be done as part of state transition. This shouldn't be part of orchestrator.
// publish usage event for the volume // publish usage event for the volume

View File

@ -31,3 +31,8 @@ CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2022 (64-bit)', 'VM
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2022 (64-bit)', 'VMware', '8.0', 'windows2019srvNext_64Guest'); CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2022 (64-bit)', 'VMware', '8.0', 'windows2019srvNext_64Guest');
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2022 (64-bit)', 'VMware', '8.0.0.1', 'windows2019srvNext_64Guest'); CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2022 (64-bit)', 'VMware', '8.0.0.1', 'windows2019srvNext_64Guest');
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2022 (64-bit)', 'Xenserver', '8.2.0', 'Windows Server 2022 (64-bit)'); CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2022 (64-bit)', 'Xenserver', '8.2.0', 'Windows Server 2022 (64-bit)');
-- Don't enable CPU cap for default system offerings, fixes regression from https://github.com/apache/cloudstack/pull/6420
UPDATE `cloud`.`service_offering` so
SET so.limit_cpu_use = 0
WHERE so.default_use = 1 AND so.vm_type IN ('domainrouter', 'secondarystoragevm', 'consoleproxy', 'internalloadbalancervm', 'elasticloadbalancervm');

View File

@ -727,6 +727,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
Filter searchFilter = new Filter(EventJoinVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal()); Filter searchFilter = new Filter(EventJoinVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());
// additional order by since createdDate does not have milliseconds
// and two events, created within one second can be incorrectly ordered (for example VM.CREATE Completed before Scheduled)
searchFilter.addOrderBy(EventJoinVO.class, "id", false);
SearchBuilder<EventJoinVO> sb = _eventJoinDao.createSearchBuilder(); SearchBuilder<EventJoinVO> sb = _eventJoinDao.createSearchBuilder();
_accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
@ -1317,7 +1321,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
vmIds[i++] = v.getId(); vmIds[i++] = v.getId();
} }
List<UserVmJoinVO> vms = _userVmJoinDao.searchByIds(vmIds); List<UserVmJoinVO> vms = _userVmJoinDao.searchByIds(vmIds);
return new Pair<List<UserVmJoinVO>, Integer>(vms, count); return new Pair<>(vms, count);
} }
@Override @Override

View File

@ -1728,6 +1728,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
return volume; return volume;
} }
@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DESTROY, eventDescription = "destroying a volume")
public void destroyVolume(long volumeId) {
volService.destroyVolume(volumeId);
}
@Override @Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_RECOVER, eventDescription = "recovering a volume in Destroy state") @ActionEvent(eventType = EventTypes.EVENT_VOLUME_RECOVER, eventDescription = "recovering a volume in Destroy state")
public Volume recoverVolume(long volumeId) { public Volume recoverVolume(long volumeId) {

View File

@ -24,7 +24,15 @@ import java.util.UUID;
import javax.inject.Inject; import javax.inject.Inject;
import com.cloud.api.query.dao.NetworkOfferingJoinDao;
import com.cloud.api.query.dao.VpcOfferingJoinDao;
import com.cloud.api.query.vo.NetworkOfferingJoinVO;
import com.cloud.api.query.vo.VpcOfferingJoinVO;
import com.cloud.domain.dao.DomainDetailsDao; import com.cloud.domain.dao.DomainDetailsDao;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import com.cloud.network.vpc.dao.VpcOfferingDetailsDao;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao; import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
@ -106,12 +114,24 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom
@Inject @Inject
private DiskOfferingDetailsDao diskOfferingDetailsDao; private DiskOfferingDetailsDao diskOfferingDetailsDao;
@Inject @Inject
private NetworkOfferingDao networkOfferingDao;
@Inject
private NetworkOfferingJoinDao networkOfferingJoinDao;
@Inject
private NetworkOfferingDetailsDao networkOfferingDetailsDao;
@Inject
private ServiceOfferingJoinDao serviceOfferingJoinDao; private ServiceOfferingJoinDao serviceOfferingJoinDao;
@Inject @Inject
private ServiceOfferingDao serviceOfferingDao; private ServiceOfferingDao serviceOfferingDao;
@Inject @Inject
private ServiceOfferingDetailsDao serviceOfferingDetailsDao; private ServiceOfferingDetailsDao serviceOfferingDetailsDao;
@Inject @Inject
private VpcOfferingDao vpcOfferingDao;
@Inject
private VpcOfferingJoinDao vpcOfferingJoinDao;
@Inject
private VpcOfferingDetailsDao vpcOfferingDetailsDao;
@Inject
private ProjectDao _projectDao; private ProjectDao _projectDao;
@Inject @Inject
private ProjectManager _projectMgr; private ProjectManager _projectMgr;
@ -483,18 +503,48 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom
} }
String domainIdString = String.valueOf(domainId); String domainIdString = String.valueOf(domainId);
List<Long> diskOfferingsDetailsToRemove = new ArrayList<>();
List<Long> serviceOfferingsDetailsToRemove = new ArrayList<>();
// delete the service and disk offerings associated with this domain removeDiskOfferings(domainId, domainIdString);
List<DiskOfferingJoinVO> diskOfferingsForThisDomain = diskOfferingJoinDao.findByDomainId(domainId);
for (DiskOfferingJoinVO diskOffering : diskOfferingsForThisDomain) { removeServiceOfferings(domainId, domainIdString);
if (domainIdString.equals(diskOffering.getDomainId())) {
diskOfferingDao.remove(diskOffering.getId()); removeNetworkOfferings(domainId, domainIdString);
removeVpcOfferings(domainId, domainIdString);
}
private void removeVpcOfferings(Long domainId, String domainIdString) {
List<Long> vpcOfferingsDetailsToRemove = new ArrayList<>();
List<VpcOfferingJoinVO> vpcOfferingsForThisDomain = vpcOfferingJoinDao.findByDomainId(domainId);
for (VpcOfferingJoinVO vpcOffering : vpcOfferingsForThisDomain) {
if (domainIdString.equals(vpcOffering.getDomainId())) {
vpcOfferingDao.remove(vpcOffering.getId());
} else { } else {
diskOfferingsDetailsToRemove.add(diskOffering.getId()); vpcOfferingsDetailsToRemove.add(vpcOffering.getId());
} }
} }
for (final Long vpcOfferingId : vpcOfferingsDetailsToRemove) {
vpcOfferingDetailsDao.removeDetail(vpcOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
}
}
private void removeNetworkOfferings(Long domainId, String domainIdString) {
List<Long> networkOfferingsDetailsToRemove = new ArrayList<>();
List<NetworkOfferingJoinVO> networkOfferingsForThisDomain = networkOfferingJoinDao.findByDomainId(domainId, false);
for (NetworkOfferingJoinVO networkOffering : networkOfferingsForThisDomain) {
if (domainIdString.equals(networkOffering.getDomainId())) {
networkOfferingDao.remove(networkOffering.getId());
} else {
networkOfferingsDetailsToRemove.add(networkOffering.getId());
}
}
for (final Long networkOfferingId : networkOfferingsDetailsToRemove) {
networkOfferingDetailsDao.removeDetail(networkOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
}
}
private void removeServiceOfferings(Long domainId, String domainIdString) {
List<Long> serviceOfferingsDetailsToRemove = new ArrayList<>();
List<ServiceOfferingJoinVO> serviceOfferingsForThisDomain = serviceOfferingJoinDao.findByDomainId(domainId); List<ServiceOfferingJoinVO> serviceOfferingsForThisDomain = serviceOfferingJoinDao.findByDomainId(domainId);
for (ServiceOfferingJoinVO serviceOffering : serviceOfferingsForThisDomain) { for (ServiceOfferingJoinVO serviceOffering : serviceOfferingsForThisDomain) {
if (domainIdString.equals(serviceOffering.getDomainId())) { if (domainIdString.equals(serviceOffering.getDomainId())) {
@ -503,14 +553,25 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom
serviceOfferingsDetailsToRemove.add(serviceOffering.getId()); serviceOfferingsDetailsToRemove.add(serviceOffering.getId());
} }
} }
for (final Long serviceOfferingId : serviceOfferingsDetailsToRemove) {
serviceOfferingDetailsDao.removeDetail(serviceOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
}
}
private void removeDiskOfferings(Long domainId, String domainIdString) {
List<Long> diskOfferingsDetailsToRemove = new ArrayList<>();
List<DiskOfferingJoinVO> diskOfferingsForThisDomain = diskOfferingJoinDao.findByDomainId(domainId);
for (DiskOfferingJoinVO diskOffering : diskOfferingsForThisDomain) {
if (domainIdString.equals(diskOffering.getDomainId())) {
diskOfferingDao.remove(diskOffering.getId());
} else {
diskOfferingsDetailsToRemove.add(diskOffering.getId());
}
}
// Remove domain IDs for offerings which may be multi-domain // Remove domain IDs for offerings which may be multi-domain
for (final Long diskOfferingId : diskOfferingsDetailsToRemove) { for (final Long diskOfferingId : diskOfferingsDetailsToRemove) {
diskOfferingDetailsDao.removeDetail(diskOfferingId, ApiConstants.DOMAIN_ID, domainIdString); diskOfferingDetailsDao.removeDetail(diskOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
} }
for (final Long serviceOfferingId : serviceOfferingsDetailsToRemove) {
serviceOfferingDetailsDao.removeDetail(serviceOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
}
} }
protected boolean cleanupDomain(Long domainId, Long ownerId) throws ConcurrentOperationException, ResourceUnavailableException { protected boolean cleanupDomain(Long domainId, Long ownerId) throws ConcurrentOperationException, ResourceUnavailableException {

View File

@ -3274,9 +3274,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
autoScaleManager.removeVmFromVmGroup(vmId); autoScaleManager.removeVmFromVmGroup(vmId);
vmScheduleManager.removeScheduleByVmId(vmId, expunge); deleteVolumesFromVm(vm, volumesToBeDeleted, expunge);
deleteVolumesFromVm(volumesToBeDeleted, expunge);
if (getDestroyRootVolumeOnVmDestruction(vm.getDomainId())) { if (getDestroyRootVolumeOnVmDestruction(vm.getDomainId())) {
VolumeVO rootVolume = _volsDao.getInstanceRootVolume(vm.getId()); VolumeVO rootVolume = _volsDao.getInstanceRootVolume(vm.getId());
@ -3720,6 +3718,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
dataDiskTemplateToDiskOfferingMap, userVmOVFPropertiesMap, dynamicScalingEnabled, vmType, overrideDiskOfferingId); dataDiskTemplateToDiskOfferingMap, userVmOVFPropertiesMap, dynamicScalingEnabled, vmType, overrideDiskOfferingId);
} }
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm")
public UserVm finalizeCreateVirtualMachine(long vmId) {
s_logger.info("Loading UserVm " + vmId + " from DB");
UserVm userVm = getUserVm(vmId);
if (userVm == null) {
s_logger.info("Loaded UserVm " + vmId + " (" + userVm.getUuid() + ") from DB");
} else {
s_logger.warn("UserVm " + vmId + " does not exist in DB");
}
return userVm;
}
private NetworkVO getNetworkToAddToNetworkList(VirtualMachineTemplate template, Account owner, HypervisorType hypervisor, private NetworkVO getNetworkToAddToNetworkList(VirtualMachineTemplate template, Account owner, HypervisorType hypervisor,
List<HypervisorType> vpcSupportedHTypes, Long networkId) { List<HypervisorType> vpcSupportedHTypes, Long networkId) {
NetworkVO network = _networkDao.findById(networkId); NetworkVO network = _networkDao.findById(networkId);
@ -7974,7 +7985,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
// Create new context and inject correct event resource type, id and details, // Create new context and inject correct event resource type, id and details,
// otherwise VOLUME.DETACH event will be associated with VirtualMachine and contain VM id and other information. // otherwise VOLUME.DETACH event will be associated with VirtualMachine and contain VM id and other information.
CallContext volumeContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Volume); CallContext volumeContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Volume);
volumeContext.setEventDetails("Volume Id: " + this._uuidMgr.getUuid(Volume.class, volume.getId()) + " Vm Id: " + this._uuidMgr.getUuid(VirtualMachine.class, volume.getInstanceId())); volumeContext.setEventDetails("Volume Type: " + volume.getVolumeType() + " Volume Id: " + this._uuidMgr.getUuid(Volume.class, volume.getId()) + " Vm Id: " + this._uuidMgr.getUuid(VirtualMachine.class, volume.getInstanceId()));
volumeContext.setEventResourceType(ApiCommandResourceType.Volume); volumeContext.setEventResourceType(ApiCommandResourceType.Volume);
volumeContext.setEventResourceId(volume.getId()); volumeContext.setEventResourceId(volume.getId());
@ -7992,15 +8003,29 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
} }
private void deleteVolumesFromVm(List<VolumeVO> volumes, boolean expunge) { private void deleteVolumesFromVm(UserVmVO vm, List<VolumeVO> volumes, boolean expunge) {
for (VolumeVO volume : volumes) { for (VolumeVO volume : volumes) {
destroyVolumeInContext(vm, expunge, volume);
}
}
private void destroyVolumeInContext(UserVmVO vm, boolean expunge, VolumeVO volume) {
// Create new context and inject correct event resource type, id and details,
// otherwise VOLUME.DESTROY event will be associated with VirtualMachine and contain VM id and other information.
CallContext volumeContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Volume);
volumeContext.setEventDetails("Volume Type: " + volume.getVolumeType() + " Volume Id: " + this._uuidMgr.getUuid(Volume.class, volume.getId()) + " Vm Id: " + vm.getUuid());
volumeContext.setEventResourceType(ApiCommandResourceType.Volume);
volumeContext.setEventResourceId(volume.getId());
try {
Volume result = _volumeService.destroyVolume(volume.getId(), CallContext.current().getCallingAccount(), expunge, false); Volume result = _volumeService.destroyVolume(volume.getId(), CallContext.current().getCallingAccount(), expunge, false);
if (result == null) { if (result == null) {
s_logger.error("DestroyVM remove volume - failed to delete volume " + volume.getInstanceId() + " from instance " + volume.getId()); s_logger.error(String.format("DestroyVM remove volume - failed to delete volume %s from instance %s", volume.getId(), volume.getInstanceId()));
} }
} finally {
// Remove volumeContext and pop vmContext back
CallContext.unregister();
} }
} }

View File

@ -22,6 +22,8 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import com.cloud.api.query.dao.NetworkOfferingJoinDao;
import com.cloud.api.query.dao.VpcOfferingJoinDao;
import com.cloud.configuration.ResourceLimit; import com.cloud.configuration.ResourceLimit;
import com.cloud.domain.dao.DomainDetailsDao; import com.cloud.domain.dao.DomainDetailsDao;
import com.cloud.utils.UuidUtils; import com.cloud.utils.UuidUtils;
@ -82,7 +84,11 @@ public class DomainManagerImplTest {
@Mock @Mock
DiskOfferingJoinDao _diskOfferingDao; DiskOfferingJoinDao _diskOfferingDao;
@Mock @Mock
ServiceOfferingJoinDao _offeringsDao; NetworkOfferingJoinDao networkOfferingJoinDao;
@Mock
ServiceOfferingJoinDao serviceOfferingJoinDao;
@Mock
VpcOfferingJoinDao vpcOfferingJoinDao;
@Mock @Mock
ProjectDao _projectDao; ProjectDao _projectDao;
@Mock @Mock
@ -142,6 +148,11 @@ public class DomainManagerImplTest {
Mockito.when(_accountDao.findCleanupsForRemovedAccounts(DOMAIN_ID)).thenReturn(domainAccountsForCleanup); Mockito.when(_accountDao.findCleanupsForRemovedAccounts(DOMAIN_ID)).thenReturn(domainAccountsForCleanup);
Mockito.when(_networkDomainDao.listNetworkIdsByDomain(DOMAIN_ID)).thenReturn(domainNetworkIds); Mockito.when(_networkDomainDao.listNetworkIdsByDomain(DOMAIN_ID)).thenReturn(domainNetworkIds);
Mockito.when(_dedicatedDao.listByDomainId(DOMAIN_ID)).thenReturn(domainDedicatedResources); Mockito.when(_dedicatedDao.listByDomainId(DOMAIN_ID)).thenReturn(domainDedicatedResources);
Mockito.when(_diskOfferingDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
Mockito.when(networkOfferingJoinDao.findByDomainId(Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(Collections.emptyList());
Mockito.when(serviceOfferingJoinDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
Mockito.when(vpcOfferingJoinDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
} }
@Test @Test
@ -266,8 +277,6 @@ public class DomainManagerImplTest {
Mockito.when(_dedicatedDao.listByDomainId(Mockito.anyLong())).thenReturn(new ArrayList<DedicatedResourceVO>()); Mockito.when(_dedicatedDao.listByDomainId(Mockito.anyLong())).thenReturn(new ArrayList<DedicatedResourceVO>());
Mockito.when(domainDaoMock.remove(Mockito.anyLong())).thenReturn(true); Mockito.when(domainDaoMock.remove(Mockito.anyLong())).thenReturn(true);
Mockito.when(_configMgr.releaseDomainSpecificVirtualRanges(Mockito.anyLong())).thenReturn(true); Mockito.when(_configMgr.releaseDomainSpecificVirtualRanges(Mockito.anyLong())).thenReturn(true);
Mockito.when(_diskOfferingDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
Mockito.when(_offeringsDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
try { try {
Assert.assertTrue(domainManager.deleteDomain(20l, false)); Assert.assertTrue(domainManager.deleteDomain(20l, false));
@ -299,8 +308,6 @@ public class DomainManagerImplTest {
Mockito.when(_resourceCountDao.removeEntriesByOwner(Mockito.anyLong(), Mockito.eq(ResourceOwnerType.Domain))).thenReturn(1l); Mockito.when(_resourceCountDao.removeEntriesByOwner(Mockito.anyLong(), Mockito.eq(ResourceOwnerType.Domain))).thenReturn(1l);
Mockito.when(_resourceLimitDao.removeEntriesByOwner(Mockito.anyLong(), Mockito.eq(ResourceOwnerType.Domain))).thenReturn(1l); Mockito.when(_resourceLimitDao.removeEntriesByOwner(Mockito.anyLong(), Mockito.eq(ResourceOwnerType.Domain))).thenReturn(1l);
Mockito.when(_configMgr.releaseDomainSpecificVirtualRanges(Mockito.anyLong())).thenReturn(true); Mockito.when(_configMgr.releaseDomainSpecificVirtualRanges(Mockito.anyLong())).thenReturn(true);
Mockito.when(_diskOfferingDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
Mockito.when(_offeringsDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
try { try {
Assert.assertTrue(domainManager.deleteDomain(20l, true)); Assert.assertTrue(domainManager.deleteDomain(20l, true));

View File

@ -16,6 +16,7 @@
# under the License. # under the License.
""" BVT tests for Events Resource """ BVT tests for Events Resource
""" """
import json
import os import os
import tempfile import tempfile
import time import time
@ -184,7 +185,7 @@ class TestEventsResource(cloudstackTestCase):
for event in events: for event in events:
if event.type.startswith("VM.") or (event.type.startswith("NETWORK.") and not event.type.startswith("NETWORK.ELEMENT")) or event.type.startswith("VOLUME.") or event.type.startswith("ACCOUNT.") or event.type.startswith("DOMAIN.") or event.type.startswith("TEMPLATE."): if event.type.startswith("VM.") or (event.type.startswith("NETWORK.") and not event.type.startswith("NETWORK.ELEMENT")) or event.type.startswith("VOLUME.") or event.type.startswith("ACCOUNT.") or event.type.startswith("DOMAIN.") or event.type.startswith("TEMPLATE."):
if event.resourceid is None or event.resourcetype is None: if event.resourceid is None or event.resourcetype is None:
self.debug("Failed event:: %" % event) self.debug("Failed event:: %s" % json.dumps(event, indent=2))
self.fail("resourceid or resourcetype for the event not found!") self.fail("resourceid or resourcetype for the event not found!")
else: else:
self.debug("Event %s at %s:: Resource Type: %s, Resource ID: %s" % (event.type, event.created, event.resourcetype, event.resourceid)) self.debug("Event %s at %s:: Resource Type: %s, Resource ID: %s" % (event.type, event.created, event.resourcetype, event.resourceid))