This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch 4.18
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.18 by this push:
new ab0297ea9b3 VM.CREATE/VOLUME.DELETE/VOLUME.DESTROY not being emitted
(#7760)
ab0297ea9b3 is described below
commit ab0297ea9b3bba8ceb5a04aa347ac7c238893067
Author: mprokopchuk <[email protected]>
AuthorDate: Sun Aug 6 21:48:17 2023 -0700
VM.CREATE/VOLUME.DELETE/VOLUME.DESTROY not being emitted (#7760)
VM.CREATE/VOLUME.DELETE/VOLUME.DESTROY not being emitted
* Update server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
Co-authored-by: dahn <[email protected]>
* Update
api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
Co-authored-by: dahn <[email protected]>
---------
Co-authored-by: Maxim Prokopchuk <[email protected]>
Co-authored-by: dahn <[email protected]>
---
.../java/com/cloud/storage/VolumeApiService.java | 2 +
api/src/main/java/com/cloud/vm/UserVmService.java | 8 ++++
.../api/command/user/vm/DeployVMCmd.java | 50 +++++++++++++---------
.../com/cloud/vm/VirtualMachineManagerImpl.java | 35 +++++++++------
.../engine/orchestration/VolumeOrchestrator.java | 25 ++++++++---
.../java/com/cloud/api/query/QueryManagerImpl.java | 4 ++
.../com/cloud/storage/VolumeApiServiceImpl.java | 6 +++
.../main/java/com/cloud/vm/UserVmManagerImpl.java | 35 +++++++++++++--
test/integration/smoke/test_events_resource.py | 3 +-
9 files changed, 123 insertions(+), 45 deletions(-)
diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java
b/api/src/main/java/com/cloud/storage/VolumeApiService.java
index b85195dafae..e5c938b1603 100644
--- a/api/src/main/java/com/cloud/storage/VolumeApiService.java
+++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java
@@ -163,6 +163,8 @@ public interface VolumeApiService {
Volume destroyVolume(long volumeId, Account caller, boolean expunge,
boolean forceExpunge);
+ void destroyVolume(long volumeId);
+
Volume recoverVolume(long volumeId);
void validateCustomDiskOfferingSizeRange(Long sizeInGB);
diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java
b/api/src/main/java/com/cloud/vm/UserVmService.java
index 258e87002da..b9fa2ee4a65 100644
--- a/api/src/main/java/com/cloud/vm/UserVmService.java
+++ b/api/src/main/java/com/cloud/vm/UserVmService.java
@@ -432,6 +432,14 @@ public interface UserVmService {
UserVm createVirtualMachine(DeployVMCmd cmd) throws
InsufficientCapacityException, ResourceUnavailableException,
ConcurrentOperationException,
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);
VirtualMachine getVm(long vmId);
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
index 78d6155d012..7aa69bd11ee 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java
@@ -753,7 +753,10 @@ public class DeployVMCmd extends
BaseAsyncCreateCustomIdCmd implements SecurityG
@Override
public String getEventDescription() {
- return "starting Vm. Vm Id: " + getEntityUuid();
+ if(getStartVm()) {
+ return "starting Vm. Vm Id: " + getEntityUuid();
+ }
+ return "deploying Vm. Vm Id: " + getEntityUuid();
}
@Override
@@ -765,28 +768,33 @@ public class DeployVMCmd extends
BaseAsyncCreateCustomIdCmd implements SecurityG
public void execute() {
UserVm result;
- try {
- CallContext.current().setEventDetails("Vm Id: " + getEntityUuid());
- result = _userVmService.startVirtualMachine(this);
- } catch (ResourceUnavailableException ex) {
- s_logger.warn("Exception: ", ex);
- throw new
ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
- } catch (ResourceAllocationException ex) {
- s_logger.warn("Exception: ", ex);
- throw new
ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
- } catch (ConcurrentOperationException ex) {
- s_logger.warn("Exception: ", ex);
- throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
ex.getMessage());
- } catch (InsufficientCapacityException ex) {
- StringBuilder message = new StringBuilder(ex.getMessage());
- if (ex instanceof InsufficientServerCapacityException) {
- if
(((InsufficientServerCapacityException)ex).isAffinityApplied()) {
- message.append(", Please check the affinity groups
provided, there may not be sufficient capacity to follow them");
+ CallContext.current().setEventDetails("Vm Id: " + getEntityUuid());
+ if (getStartVm()) {
+ try {
+ result = _userVmService.startVirtualMachine(this);
+ } catch (ResourceUnavailableException ex) {
+ s_logger.warn("Exception: ", ex);
+ throw new
ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
+ } catch (ResourceAllocationException ex) {
+ s_logger.warn("Exception: ", ex);
+ throw new
ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
+ } catch (ConcurrentOperationException ex) {
+ s_logger.warn("Exception: ", ex);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
ex.getMessage());
+ } catch (InsufficientCapacityException ex) {
+ StringBuilder message = new StringBuilder(ex.getMessage());
+ if (ex instanceof InsufficientServerCapacityException) {
+ if
(((InsufficientServerCapacityException)ex).isAffinityApplied()) {
+ message.append(", Please check the affinity groups
provided, there may not be sufficient capacity to follow them");
+ }
}
+ s_logger.info(String.format("%s: %s", message.toString(),
ex.getLocalizedMessage()));
+ s_logger.debug(message.toString(), ex);
+ throw new
ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR,
message.toString());
}
- s_logger.info(ex);
- s_logger.info(message.toString(), ex);
- 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) {
diff --git
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
index d3ba95061b6..cf188cbf58d 100755
---
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -500,22 +500,29 @@ public class VirtualMachineManagerImpl extends
ManagerBase implements VirtualMac
allocateRootVolume(persistedVm, template, rootDiskOfferingInfo,
owner, rootDiskSizeFinal);
- if (dataDiskOfferings != null) {
- for (final DiskOfferingInfo dataDiskOfferingInfo :
dataDiskOfferings) {
- volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" +
persistedVm.getId(), dataDiskOfferingInfo.getDiskOffering(),
dataDiskOfferingInfo.getSize(),
- dataDiskOfferingInfo.getMinIops(),
dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, null);
+ // 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) {
+ for (final DiskOfferingInfo dataDiskOfferingInfo :
dataDiskOfferings) {
+ volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" +
persistedVm.getId(), dataDiskOfferingInfo.getDiskOffering(),
dataDiskOfferingInfo.getSize(),
+ dataDiskOfferingInfo.getMinIops(),
dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, null);
+ }
}
- }
- if (datadiskTemplateToDiskOfferingMap != null &&
!datadiskTemplateToDiskOfferingMap.isEmpty()) {
- int diskNumber = 1;
- for (Entry<Long, DiskOffering>
dataDiskTemplateToDiskOfferingMap :
datadiskTemplateToDiskOfferingMap.entrySet()) {
- DiskOffering diskOffering =
dataDiskTemplateToDiskOfferingMap.getValue();
- long diskOfferingSize = diskOffering.getDiskSize() / (1024
* 1024 * 1024);
- VMTemplateVO dataDiskTemplate =
_templateDao.findById(dataDiskTemplateToDiskOfferingMap.getKey());
- volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" +
persistedVm.getId() + "-" + String.valueOf(diskNumber), diskOffering,
diskOfferingSize, null, null,
- persistedVm, dataDiskTemplate, owner,
Long.valueOf(diskNumber));
- diskNumber++;
+ if (datadiskTemplateToDiskOfferingMap != null &&
!datadiskTemplateToDiskOfferingMap.isEmpty()) {
+ int diskNumber = 1;
+ for (Entry<Long, DiskOffering>
dataDiskTemplateToDiskOfferingMap :
datadiskTemplateToDiskOfferingMap.entrySet()) {
+ DiskOffering diskOffering =
dataDiskTemplateToDiskOfferingMap.getValue();
+ long diskOfferingSize = diskOffering.getDiskSize() /
(1024 * 1024 * 1024);
+ VMTemplateVO dataDiskTemplate =
_templateDao.findById(dataDiskTemplateToDiskOfferingMap.getKey());
+ volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" +
persistedVm.getId() + "-" + String.valueOf(diskNumber), diskOffering,
diskOfferingSize, null, null,
+ persistedVm, dataDiskTemplate, owner,
Long.valueOf(diskNumber));
+ diskNumber++;
+ }
}
+ } finally {
+ // Remove volumeContext and pop vmContext back
+ CallContext.unregister();
}
if (s_logger.isDebugEnabled()) {
diff --git
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
index 2aa997e13aa..f7c8c9c70bf 100644
---
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
+++
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
@@ -819,7 +819,7 @@ public class VolumeOrchestrator extends ManagerBase
implements VolumeOrchestrati
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
public DiskProfile allocateRawVolume(Type type, String name, DiskOffering
offering, Long size, Long minIops, Long maxIops, VirtualMachine vm,
VirtualMachineTemplate template, Account owner,
Long deviceId) {
@@ -1035,13 +1035,13 @@ public class VolumeOrchestrator extends ManagerBase
implements VolumeOrchestrati
private void updateRootDiskVolumeEventDetails(Type type, VirtualMachine
vm, List<DiskProfile> diskProfiles) {
CallContext callContext = CallContext.current();
// 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());
if (!volumeIds.isEmpty()) {
callContext.setEventResourceId(volumeIds.get(0));
}
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
boolean volumeAlreadyDestroyed = (vol.getState() ==
Volume.State.Destroy || vol.getState() == Volume.State.Expunged ||
vol.getState() == Volume.State.Expunging);
if (!volumeAlreadyDestroyed) {
- volService.destroyVolume(vol.getId());
+ destroyVolumeInContext(vol);
} else {
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
public void revokeAccess(DataObject dataObject, Host host, DataStore
dataStore) {
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.primary_storage, volume.isDisplay(), new Long(volume.getSize()));
} 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.
// publish usage event for the volume
diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
index 5aad6afcdbb..f1e370de33d 100644
--- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
@@ -721,6 +721,10 @@ public class QueryManagerImpl extends
MutualExclusiveIdsManagerBase implements Q
ListProjectResourcesCriteria listProjectResourcesCriteria =
domainIdRecursiveListProject.third();
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();
_accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive,
permittedAccounts, listProjectResourcesCriteria);
diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
index e39fac147e7..e03942edc59 100644
--- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
@@ -1728,6 +1728,12 @@ public class VolumeApiServiceImpl extends ManagerBase
implements VolumeApiServic
return volume;
}
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DESTROY, eventDescription
= "destroying a volume")
+ public void destroyVolume(long volumeId) {
+ volService.destroyVolume(volumeId);
+ }
+
@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_RECOVER, eventDescription
= "recovering a volume in Destroy state")
public Volume recoverVolume(long volumeId) {
diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 7ec3450acb1..ecf60556db6 100644
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@ -3272,7 +3272,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
autoScaleManager.removeVmFromVmGroup(vmId);
- deleteVolumesFromVm(volumesToBeDeleted, expunge);
+ deleteVolumesFromVm(vm, volumesToBeDeleted, expunge);
if (getDestroyRootVolumeOnVmDestruction(vm.getDomainId())) {
VolumeVO rootVolume = _volsDao.getInstanceRootVolume(vm.getId());
@@ -3716,6 +3716,19 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
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,
List<HypervisorType> vpcSupportedHTypes, Long networkId) {
NetworkVO network = _networkDao.findById(networkId);
@@ -8002,7 +8015,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
// 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.
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.setEventResourceId(volume.getId());
@@ -8020,15 +8033,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) {
+ 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);
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();
}
}
diff --git a/test/integration/smoke/test_events_resource.py
b/test/integration/smoke/test_events_resource.py
index 4d6872af57e..660cbd37bce 100644
--- a/test/integration/smoke/test_events_resource.py
+++ b/test/integration/smoke/test_events_resource.py
@@ -16,6 +16,7 @@
# under the License.
""" BVT tests for Events Resource
"""
+import json
import os
import tempfile
import time
@@ -184,7 +185,7 @@ class TestEventsResource(cloudstackTestCase):
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.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!")
else:
self.debug("Event %s at %s:: Resource Type: %s, Resource
ID: %s" % (event.type, event.created, event.resourcetype, event.resourceid))