diff --git a/framework/events/pom.xml b/framework/events/pom.xml new file mode 100644 index 00000000000..c536c172b45 --- /dev/null +++ b/framework/events/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + cloud-framework-events + Apache CloudStack Event Notification Framework + + org.apache.cloudstack + cloudstack + 4.0.0-SNAPSHOT + ../../pom.xml + + diff --git a/framework/events/src/org/apache/cloudstack/framework/events/EventBus.java b/framework/events/src/org/apache/cloudstack/framework/events/EventBus.java new file mode 100644 index 00000000000..8a2478869b4 --- /dev/null +++ b/framework/events/src/org/apache/cloudstack/framework/events/EventBus.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.framework.events; + +import com.cloud.utils.component.Adapter; +import java.util.Map; + +/** + * Publish and Subscribe provider interface + * + */ +public interface EventBus extends Adapter{ + /** + * Publish an event + * + * @param category category of the event being published (e.g. action, usage, alert etc) + * @param type type of the event (e.g. vm stop, volume delete etc) + * @param description description of the event + * @return true if the event has been successfully published. + */ + boolean publish(String category, String type, Map description); + + /** + * Subscribe to events of a category and a type + * + * @param category category of the event being subscribed (e.g. action, usage, alert etc) + * @param type type of the event (e.g. vm stop, volume delete etc) + * @param subscriber class that is intends to receive subscribed event + * @return true if the subscribe has been successfully registered. + */ + boolean subscribe(String category, String type, EventSubscriber subscriber); +} \ No newline at end of file diff --git a/framework/events/src/org/apache/cloudstack/framework/events/EventCategory.java b/framework/events/src/org/apache/cloudstack/framework/events/EventCategory.java new file mode 100644 index 00000000000..f9d5e678aaf --- /dev/null +++ b/framework/events/src/org/apache/cloudstack/framework/events/EventCategory.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.framework.events; + +public class EventCategory { + public static final String ACTION_EVENT = "Action Event"; + public static final String USAGE_EVENT = "Usage Event"; + public static final String ALERT_EVENT = "Alert Event"; +} diff --git a/framework/events/src/org/apache/cloudstack/framework/events/EventPublisher.java b/framework/events/src/org/apache/cloudstack/framework/events/EventPublisher.java new file mode 100644 index 00000000000..b54757e674a --- /dev/null +++ b/framework/events/src/org/apache/cloudstack/framework/events/EventPublisher.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.framework.events; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import com.cloud.utils.component.Adapters; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.AnnotationInterceptor; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +public class EventPublisher implements MethodInterceptor, AnnotationInterceptor { + + private static EventBus _eventBus = null; + + @Override + public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + Publish event = interceptStart(method); + boolean success = true; + try { + return methodProxy.invokeSuper(object, args); + } catch (Exception e){ + success = false; + interceptException(method, event); + throw e; + } finally { + if(success){ + interceptComplete(method, event); + } + } + } + + @Override + public boolean needToIntercept(AnnotatedElement element) { + if (!(element instanceof Method)) { + return false; + + } + Method method = (Method)element; + Publish event = method.getAnnotation(Publish.class); + if (event != null) { + return true; + } + return false; + } + + @Override + public Publish interceptStart(AnnotatedElement element) { + return null; + } + + @Override + public void interceptComplete(AnnotatedElement element, Publish event) { + _eventBus = getEventBus(); + if (_eventBus != null) { + Map description = new HashMap(); + description.put("description", event.eventDescription()); + _eventBus.publish(event.eventCategory(), event.eventType(), description); + } + } + + @Override + public void interceptException(AnnotatedElement element, Publish attach) { + return; + } + + @Override + public Callback getCallback() { + return this; + } + + private EventBus getEventBus() { + if (_eventBus == null) { + ComponentLocator locator = ComponentLocator.getLocator("management-server"); + Adapters eventBusImpls = locator.getAdapters(EventBus.class); + if (eventBusImpls != null) { + Enumeration eventBusenum = eventBusImpls.enumeration(); + _eventBus = eventBusenum.nextElement(); + } + } + return _eventBus; + } +} \ No newline at end of file diff --git a/framework/events/src/org/apache/cloudstack/framework/events/EventSubscriber.java b/framework/events/src/org/apache/cloudstack/framework/events/EventSubscriber.java new file mode 100644 index 00000000000..50a8bd39e17 --- /dev/null +++ b/framework/events/src/org/apache/cloudstack/framework/events/EventSubscriber.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.framework.events; + +import java.util.Map; + +public interface EventSubscriber { + + /** + * Callback method. EventBus calls this method on occurrence of subscribed event + * + * @param category category of the event being subscribed (e.g. action, usage, alert etc) + * @param type type of the event (e.g. vm stop, volume delete etc) + * @param description description of the event + */ + void recieve(String category, String type, Map description); +} diff --git a/framework/events/src/org/apache/cloudstack/framework/events/Publish.java b/framework/events/src/org/apache/cloudstack/framework/events/Publish.java new file mode 100644 index 00000000000..8f1097211fc --- /dev/null +++ b/framework/events/src/org/apache/cloudstack/framework/events/Publish.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.framework.events; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target({ TYPE, METHOD }) +@Retention(RUNTIME) +public @interface Publish { + + String eventCategory(); + + String eventType(); + + String eventDescription(); +} \ No newline at end of file diff --git a/framework/events/src/org/apache/cloudstack/framework/events/Subscribe.java b/framework/events/src/org/apache/cloudstack/framework/events/Subscribe.java new file mode 100644 index 00000000000..00aa5e571d7 --- /dev/null +++ b/framework/events/src/org/apache/cloudstack/framework/events/Subscribe.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.framework.events; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target({METHOD }) +@Retention(RUNTIME) +public @interface Subscribe { + + String eventCategory(); + + String eventType(); +} diff --git a/pom.xml b/pom.xml index 17ea0502fcb..dc23d5482e7 100644 --- a/pom.xml +++ b/pom.xml @@ -157,6 +157,7 @@ awsapi patches test + framework/events diff --git a/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java b/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java index ced2618cec6..c5c65e344f6 100644 --- a/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java +++ b/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java @@ -22,6 +22,7 @@ import com.cloud.event.ActionEventCallback; import com.cloud.utils.component.AnnotationInterceptor; import com.cloud.utils.component.InterceptorLibrary; import com.cloud.utils.db.DatabaseCallback; +import org.apache.cloudstack.framework.events.EventPublisher; public class DefaultInterceptorLibrary implements InterceptorLibrary { @@ -29,5 +30,6 @@ public class DefaultInterceptorLibrary implements InterceptorLibrary { public void addInterceptors(List> interceptors) { interceptors.add(new DatabaseCallback()); interceptors.add(new ActionEventCallback()); + interceptors.add(new EventPublisher()); } }