diff --git a/server/src/com/cloud/event/ActionEventCallback.java b/server/src/com/cloud/event/ActionEventCallback.java
new file mode 100644
index 00000000000..1c8f8d93759
--- /dev/null
+++ b/server/src/com/cloud/event/ActionEventCallback.java
@@ -0,0 +1,139 @@
+/**
+ * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.cloud.event;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+
+import com.cloud.api.BaseAsyncCmd;
+import com.cloud.user.Account;
+import com.cloud.user.User;
+import com.cloud.user.UserContext;
+import com.cloud.utils.component.AnnotationInterceptor;
+
+public class ActionEventCallback implements MethodInterceptor, AnnotationInterceptor {
+ boolean create = false;
+ private String eventType = null;
+ private long accountId = Account.ACCOUNT_ID_SYSTEM;
+ private long userId = User.UID_SYSTEM;
+ private String description = null;
+ private long startEventId = 0;
+
+ @Override
+ public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
+ if(args.length > 0){
+ if((args[0] != null) && (args[0] instanceof BaseAsyncCmd)){
+ UserContext ctx = UserContext.current();
+ Long userID = ctx.getCallerUserId();
+ userId = (userID == null) ? User.UID_SYSTEM : userID;
+ BaseAsyncCmd cmd = (BaseAsyncCmd)args[0];
+ eventType = cmd.getEventType();
+ accountId = cmd.getEntityOwnerId();
+ description = cmd.getEventDescription();
+ Long startEventID = cmd.getStartEventId();
+ if(startEventID == null){
+ startEventId = 0;
+ }
+ }
+ }
+ EventVO event = null;
+ ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
+ if (actionEvent != null) {
+ create = actionEvent.create();
+ }
+ if(!create){
+ event = interceptStart(method);
+ }
+ try {
+ return methodProxy.invokeSuper(object, args);
+ } finally {
+ interceptComplete(method, event);
+ }
+ }
+
+ @Override
+ public boolean needToIntercept(AnnotatedElement element) {
+ if (!(element instanceof Method)) {
+ return false;
+
+ }
+ Method method = (Method)element;
+ ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
+ if (actionEvent != null) {
+ create = actionEvent.create();
+ return true;
+ }
+
+ Class> clazz = method.getDeclaringClass();
+ do {
+ actionEvent = clazz.getAnnotation(ActionEvent.class);
+ if (actionEvent != null) {
+ return true;
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != Object.class && clazz != null);
+
+ return false;
+ }
+
+ @Override
+ public EventVO interceptStart(AnnotatedElement element) {
+ EventVO event = null;
+ if(eventType != null){
+ long eventId = EventUtils.saveStartedEvent(userId, accountId, eventType, description, startEventId);
+ if(startEventId == 0){
+ // There was no scheduled event. so Started event Id
+ startEventId = eventId;
+ }
+ }
+ return event;
+ }
+
+ @Override
+ public void interceptComplete(AnnotatedElement element, EventVO event) {
+ if(eventType != null){
+ if(create){
+ //This start event has to be used for subsequent events of this action
+ startEventId = EventUtils.saveCreatedEvent(userId, accountId, EventVO.LEVEL_INFO, eventType, "Successfully created entity for "+description);
+ } else {
+ EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, eventType, "Successfully completed "+description, startEventId);
+ }
+ }
+ }
+
+ @Override
+ public void interceptException(AnnotatedElement element, EventVO event) {
+ if(eventType != null){
+ if(create){
+ EventUtils.saveCreatedEvent(userId, accountId, EventVO.LEVEL_ERROR, eventType, "Error while creating entity for "+description);
+ } else {
+ EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, eventType, "Error while "+description, startEventId);
+ }
+ }
+ }
+
+ @Override
+ public Callback getCallback() {
+ return this;
+ }
+
+}