Merging events framework branch into master. This commit will bring
following changes
- introduced notion of event bus with publish, subscribe, unsubscribe
semantics
- a plug-in can implement the EventBus abstraction to provide event
bug to CloudStack
- A rabbitMQ based plug-in that can interact with AMQP servers to
provide message broker based event-bug
- stream lines, action events, usage events, alerts publishing in to
convineance classed which are also used to publish corresponding
event on to event bus
- introduced notion of state change event. On a state change, in the
state machine corrsponding to the resource, a state change event is
published on the event bug
- associated a state machined with Snapshot and Network objects
- Virtual Machine, Volume, Snaphost, Network object state changes wil
result in a state change event
diff --git a/api/src/com/cloud/event/EventCategory.java b/api/src/com/cloud/event/EventCategory.java
new file mode 100644
index 0000000..cee6529
--- /dev/null
+++ b/api/src/com/cloud/event/EventCategory.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.cloud.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EventCategory {
+ private static List<EventCategory> eventCategories = new ArrayList<EventCategory>();
+ private String eventCategoryName;
+
+ public EventCategory(String categoryName) {
+ this.eventCategoryName = categoryName;
+ eventCategories.add(this);
+ }
+
+ public String getName() {
+ return eventCategoryName;
+ }
+
+ public static List<EventCategory> listAllEventCategories() {
+ return eventCategories;
+ }
+
+ public static EventCategory getEventCategory(String categoryName) {
+ for (EventCategory category : eventCategories) {
+ if (category.getName().equalsIgnoreCase(categoryName)) {
+ return category;
+ }
+ }
+ return null;
+ }
+
+ public static final EventCategory ACTION_EVENT = new EventCategory("ActionEvent");
+ public static final EventCategory ALERT_EVENT = new EventCategory("AlertEvent");
+ public static final EventCategory USAGE_EVENT = new EventCategory("UsageEvent");
+ public static final EventCategory RESOURCE_STATE_CHANGE_EVENT = new EventCategory("ResourceStateEvent");
+}
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index d666c1e..0dd97cb 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -16,7 +16,41 @@
// under the License.
package com.cloud.event;
+import com.cloud.configuration.Configuration;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.Pod;
+import com.cloud.dc.StorageNetworkIpRange;
+import com.cloud.dc.Vlan;
+import com.cloud.domain.Domain;
+import com.cloud.host.Host;
+import com.cloud.network.*;
+import com.cloud.network.as.*;
+import com.cloud.network.router.VirtualRouter;
+import com.cloud.network.rules.LoadBalancer;
+import com.cloud.network.rules.StaticNat;
+import com.cloud.network.security.SecurityGroup;
+import com.cloud.network.vpc.PrivateGateway;
+import com.cloud.network.vpc.StaticRoute;
+import com.cloud.network.vpc.Vpc;
+import com.cloud.offering.DiskOffering;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.offering.ServiceOffering;
+import com.cloud.projects.Project;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Volume;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+import com.cloud.user.User;
+import com.cloud.vm.VirtualMachine;
+
+import java.util.HashMap;
+import java.util.Map;
+
public class EventTypes {
+
+ //map of Event and corresponding entity for which Event is applicable
+ private static Map<String, String> entityEventDetails = null;
+
// VM Events
public static final String EVENT_VM_CREATE = "VM.CREATE";
public static final String EVENT_VM_DESTROY = "VM.DESTROY";
@@ -319,10 +353,323 @@
public static final String EVENT_AUTOSCALEVMGROUP_UPDATE = "AUTOSCALEVMGROUP.UPDATE";
public static final String EVENT_AUTOSCALEVMGROUP_ENABLE = "AUTOSCALEVMGROUP.ENABLE";
public static final String EVENT_AUTOSCALEVMGROUP_DISABLE = "AUTOSCALEVMGROUP.DISABLE";
-
+
+
public static final String EVENT_BAREMETAL_DHCP_SERVER_ADD = "PHYSICAL.DHCP.ADD";
public static final String EVENT_BAREMETAL_DHCP_SERVER_DELETE = "PHYSICAL.DHCP.DELETE";
-
public static final String EVENT_BAREMETAL_PXE_SERVER_ADD = "PHYSICAL.PXE.ADD";
public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE = "PHYSICAL.PXE.DELETE";
+
+ static {
+
+ // TODO: need a way to force author adding event types to declare the entity details as well, with out braking
+ // current ActionEvent annotation semantics
+
+ entityEventDetails = new HashMap<String, String>();
+
+ entityEventDetails.put(EVENT_VM_CREATE, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_DESTROY, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_START, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_STOP, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_REBOOT, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_UPDATE, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_UPGRADE, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_RESETPASSWORD, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_MIGRATE, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_MOVE, VirtualMachine.class.getName());
+ entityEventDetails.put(EVENT_VM_RESTORE, VirtualMachine.class.getName());
+
+ entityEventDetails.put(EVENT_ROUTER_CREATE, VirtualRouter.class.getName());
+ entityEventDetails.put(EVENT_ROUTER_DESTROY, VirtualRouter.class.getName());
+ entityEventDetails.put(EVENT_ROUTER_START, VirtualRouter.class.getName());
+ entityEventDetails.put(EVENT_ROUTER_STOP, VirtualRouter.class.getName());
+ entityEventDetails.put(EVENT_ROUTER_REBOOT, VirtualRouter.class.getName());
+ entityEventDetails.put(EVENT_ROUTER_HA, VirtualRouter.class.getName());
+ entityEventDetails.put(EVENT_ROUTER_UPGRADE, VirtualRouter.class.getName());
+
+ entityEventDetails.put(EVENT_PROXY_CREATE, "ConsoleProxy");
+ entityEventDetails.put(EVENT_PROXY_DESTROY, "ConsoleProxy");
+ entityEventDetails.put(EVENT_PROXY_START, "ConsoleProxy");
+ entityEventDetails.put(EVENT_PROXY_STOP, "ConsoleProxy");
+ entityEventDetails.put(EVENT_PROXY_REBOOT, "ConsoleProxy");
+ entityEventDetails.put(EVENT_ROUTER_HA, "ConsoleProxy");
+ entityEventDetails.put(EVENT_PROXY_HA, "ConsoleProxy");
+
+ entityEventDetails.put(EVENT_VNC_CONNECT, "VNC");
+ entityEventDetails.put(EVENT_VNC_DISCONNECT, "VNC");
+
+ // Network Events
+ entityEventDetails.put(EVENT_NETWORK_CREATE, Network.class.getName());
+ entityEventDetails.put(EVENT_NETWORK_DELETE, Network.class.getName());
+ entityEventDetails.put(EVENT_NETWORK_UPDATE, Network.class.getName());
+ entityEventDetails.put(EVENT_NETWORK_RESTART, Network.class.getName());
+ entityEventDetails.put(EVENT_NET_IP_ASSIGN, PublicIpAddress.class.getName());
+ entityEventDetails.put(EVENT_NET_IP_RELEASE, PublicIpAddress.class.getName());
+ entityEventDetails.put(EVENT_NET_RULE_ADD, Network.class.getName());
+ entityEventDetails.put(EVENT_NET_RULE_DELETE, Network.class.getName());
+ entityEventDetails.put(EVENT_NET_RULE_MODIFY, Network.class.getName());
+ entityEventDetails.put(EVENT_FIREWALL_OPEN, Network.class.getName());
+ entityEventDetails.put(EVENT_FIREWALL_CLOSE, Network.class.getName());
+
+ // Load Balancers
+ entityEventDetails.put(EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, LoadBalancer.class.getName());
+ entityEventDetails.put(EVENT_REMOVE_FROM_LOAD_BALANCER_RULE, LoadBalancer.class.getName());
+ entityEventDetails.put(EVENT_LOAD_BALANCER_CREATE, LoadBalancer.class.getName());
+ entityEventDetails.put(EVENT_LOAD_BALANCER_DELETE, LoadBalancer.class.getName());
+ entityEventDetails.put(EVENT_LB_STICKINESSPOLICY_CREATE, LoadBalancer.class.getName());
+ entityEventDetails.put(EVENT_LB_STICKINESSPOLICY_DELETE, LoadBalancer.class.getName());
+ entityEventDetails.put(EVENT_LOAD_BALANCER_UPDATE, LoadBalancer.class.getName());
+
+ // Account events
+ entityEventDetails.put(EVENT_ACCOUNT_DISABLE, Account.class.getName());
+ entityEventDetails.put(EVENT_ACCOUNT_CREATE, Account.class.getName());
+ entityEventDetails.put(EVENT_ACCOUNT_DELETE, Account.class.getName());
+ entityEventDetails.put(EVENT_ACCOUNT_MARK_DEFAULT_ZONE, Account.class.getName());
+
+ // UserVO Events
+ entityEventDetails.put(EVENT_USER_LOGIN, User.class.getName());
+ entityEventDetails.put(EVENT_USER_LOGOUT, User.class.getName());
+ entityEventDetails.put(EVENT_USER_CREATE, User.class.getName());
+ entityEventDetails.put(EVENT_USER_DELETE, User.class.getName());
+ entityEventDetails.put(EVENT_USER_DISABLE, User.class.getName());
+ entityEventDetails.put(EVENT_USER_UPDATE, User.class.getName());
+ entityEventDetails.put(EVENT_USER_ENABLE, User.class.getName());
+ entityEventDetails.put(EVENT_USER_LOCK, User.class.getName());
+
+ // Template Events
+ entityEventDetails.put(EVENT_TEMPLATE_CREATE, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_DELETE, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_UPDATE, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_START, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_SUCCESS, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_FAILED, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_COPY, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_EXTRACT, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_UPLOAD, VirtualMachineTemplate.class.getName());
+ entityEventDetails.put(EVENT_TEMPLATE_CLEANUP, VirtualMachineTemplate.class.getName());
+
+ // Volume Events
+ entityEventDetails.put(EVENT_VOLUME_CREATE, Volume.class.getName());
+ entityEventDetails.put(EVENT_VOLUME_DELETE, Volume.class.getName());
+ entityEventDetails.put(EVENT_VOLUME_ATTACH, Volume.class.getName());
+ entityEventDetails.put(EVENT_VOLUME_DETACH, Volume.class.getName());
+ entityEventDetails.put(EVENT_VOLUME_EXTRACT, Volume.class.getName());
+ entityEventDetails.put(EVENT_VOLUME_UPLOAD, Volume.class.getName());
+ entityEventDetails.put(EVENT_VOLUME_MIGRATE, Volume.class.getName());
+ entityEventDetails.put(EVENT_VOLUME_RESIZE, Volume.class.getName());
+
+ // Domains
+ entityEventDetails.put(EVENT_DOMAIN_CREATE, Domain.class.getName());
+ entityEventDetails.put(EVENT_DOMAIN_DELETE, Domain.class.getName());
+ entityEventDetails.put(EVENT_DOMAIN_UPDATE, Domain.class.getName());
+
+ // Snapshots
+ entityEventDetails.put(EVENT_SNAPSHOT_CREATE, Snapshot.class.getName());
+ entityEventDetails.put(EVENT_SNAPSHOT_DELETE, Snapshot.class.getName());
+ entityEventDetails.put(EVENT_SNAPSHOT_POLICY_CREATE, Snapshot.class.getName());
+ entityEventDetails.put(EVENT_SNAPSHOT_POLICY_UPDATE, Snapshot.class.getName());
+ entityEventDetails.put(EVENT_SNAPSHOT_POLICY_DELETE, Snapshot.class.getName());
+
+ // ISO
+ entityEventDetails.put(EVENT_ISO_CREATE, "Iso");
+ entityEventDetails.put(EVENT_ISO_DELETE, "Iso");
+ entityEventDetails.put(EVENT_ISO_COPY, "Iso");
+ entityEventDetails.put(EVENT_ISO_ATTACH, "Iso");
+ entityEventDetails.put(EVENT_ISO_DETACH, "Iso");
+ entityEventDetails.put(EVENT_ISO_EXTRACT, "Iso");
+ entityEventDetails.put(EVENT_ISO_UPLOAD, "Iso");
+
+ // SSVM
+ entityEventDetails.put(EVENT_SSVM_CREATE, "SecondaryStorageVm");
+ entityEventDetails.put(EVENT_SSVM_DESTROY, "SecondaryStorageVm");
+ entityEventDetails.put(EVENT_SSVM_START, "SecondaryStorageVm");
+ entityEventDetails.put(EVENT_SSVM_STOP, "SecondaryStorageVm");
+ entityEventDetails.put(EVENT_SSVM_REBOOT, "SecondaryStorageVm");
+ entityEventDetails.put(EVENT_SSVM_HA, "SecondaryStorageVm");
+
+ // Service Offerings
+ entityEventDetails.put(EVENT_SERVICE_OFFERING_CREATE, ServiceOffering.class.getName());
+ entityEventDetails.put(EVENT_SERVICE_OFFERING_EDIT, ServiceOffering.class.getName());
+ entityEventDetails.put(EVENT_SERVICE_OFFERING_DELETE, ServiceOffering.class.getName());
+
+ // Disk Offerings
+ entityEventDetails.put(EVENT_DISK_OFFERING_CREATE, DiskOffering.class.getName());
+ entityEventDetails.put(EVENT_DISK_OFFERING_EDIT, DiskOffering.class.getName());
+ entityEventDetails.put(EVENT_DISK_OFFERING_DELETE, DiskOffering.class.getName());
+
+ // Network offerings
+ entityEventDetails.put(EVENT_NETWORK_OFFERING_CREATE, NetworkOffering.class.getName());
+ entityEventDetails.put(EVENT_NETWORK_OFFERING_ASSIGN, NetworkOffering.class.getName());
+ entityEventDetails.put(EVENT_NETWORK_OFFERING_EDIT, NetworkOffering.class.getName());
+ entityEventDetails.put(EVENT_NETWORK_OFFERING_REMOVE, NetworkOffering.class.getName());
+ entityEventDetails.put(EVENT_NETWORK_OFFERING_DELETE, NetworkOffering.class.getName());
+
+ // Pods
+ entityEventDetails.put(EVENT_POD_CREATE, Pod.class.getName());
+ entityEventDetails.put(EVENT_POD_EDIT, Pod.class.getName());
+ entityEventDetails.put(EVENT_POD_DELETE, Pod.class.getName());
+
+ // Zones
+ entityEventDetails.put(EVENT_ZONE_CREATE, DataCenter.class.getName());
+ entityEventDetails.put(EVENT_ZONE_EDIT, DataCenter.class.getName());
+ entityEventDetails.put(EVENT_ZONE_DELETE, DataCenter.class.getName());
+
+ // VLANs/IP ranges
+ entityEventDetails.put(EVENT_VLAN_IP_RANGE_CREATE, Vlan.class.getName());
+ entityEventDetails.put(EVENT_VLAN_IP_RANGE_DELETE,Vlan.class.getName());
+
+ entityEventDetails.put(EVENT_STORAGE_IP_RANGE_CREATE, StorageNetworkIpRange.class.getName());
+ entityEventDetails.put(EVENT_STORAGE_IP_RANGE_DELETE, StorageNetworkIpRange.class.getName());
+ entityEventDetails.put(EVENT_STORAGE_IP_RANGE_UPDATE, StorageNetworkIpRange.class.getName());
+
+ // Configuration Table
+ entityEventDetails.put(EVENT_CONFIGURATION_VALUE_EDIT, Configuration.class.getName());
+
+ // Security Groups
+ entityEventDetails.put(EVENT_SECURITY_GROUP_AUTHORIZE_INGRESS, SecurityGroup.class.getName());
+ entityEventDetails.put(EVENT_SECURITY_GROUP_REVOKE_INGRESS, SecurityGroup.class.getName());
+ entityEventDetails.put(EVENT_SECURITY_GROUP_AUTHORIZE_EGRESS, SecurityGroup.class.getName());
+ entityEventDetails.put(EVENT_SECURITY_GROUP_REVOKE_EGRESS, SecurityGroup.class.getName());
+ entityEventDetails.put(EVENT_SECURITY_GROUP_CREATE, SecurityGroup.class.getName());
+ entityEventDetails.put(EVENT_SECURITY_GROUP_DELETE, SecurityGroup.class.getName());
+ entityEventDetails.put(EVENT_SECURITY_GROUP_ASSIGN, SecurityGroup.class.getName());
+ entityEventDetails.put(EVENT_SECURITY_GROUP_REMOVE, SecurityGroup.class.getName());
+
+ // Host
+ entityEventDetails.put(EVENT_HOST_RECONNECT, Host.class.getName());
+
+ // Maintenance
+ entityEventDetails.put(EVENT_MAINTENANCE_CANCEL, Host.class.getName());
+ entityEventDetails.put(EVENT_MAINTENANCE_CANCEL_PRIMARY_STORAGE, Host.class.getName());
+ entityEventDetails.put(EVENT_MAINTENANCE_PREPARE, Host.class.getName());
+ entityEventDetails.put(EVENT_MAINTENANCE_PREPARE_PRIMARY_STORAGE, Host.class.getName());
+
+ // VPN
+ entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_CREATE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_DESTROY, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_VPN_USER_ADD, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_VPN_USER_REMOVE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_S2S_VPN_GATEWAY_CREATE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_S2S_VPN_GATEWAY_DELETE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_CREATE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_DELETE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_UPDATE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_CREATE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_DELETE, RemoteAccessVpn.class.getName());
+ entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_RESET, RemoteAccessVpn.class.getName());
+
+ // Custom certificates
+ entityEventDetails.put(EVENT_UPLOAD_CUSTOM_CERTIFICATE, "Certificate");
+
+ // OneToOnenat
+ entityEventDetails.put(EVENT_ENABLE_STATIC_NAT, StaticNat.class.getName());
+ entityEventDetails.put(EVENT_DISABLE_STATIC_NAT, StaticNat.class.getName());
+
+ entityEventDetails.put(EVENT_ZONE_VLAN_ASSIGN,Vlan.class.getName());
+ entityEventDetails.put(EVENT_ZONE_VLAN_RELEASE,Vlan.class.getName());
+
+ // Projects
+ entityEventDetails.put(EVENT_PROJECT_CREATE, Project.class.getName());
+ entityEventDetails.put(EVENT_PROJECT_UPDATE, Project.class.getName());
+ entityEventDetails.put(EVENT_PROJECT_DELETE, Project.class.getName());
+ entityEventDetails.put(EVENT_PROJECT_ACTIVATE, Project.class.getName());
+ entityEventDetails.put(EVENT_PROJECT_SUSPEND, Project.class.getName());
+ entityEventDetails.put(EVENT_PROJECT_ACCOUNT_ADD, Project.class.getName());
+ entityEventDetails.put(EVENT_PROJECT_INVITATION_UPDATE, Project.class.getName());
+ entityEventDetails.put(EVENT_PROJECT_INVITATION_REMOVE, Project.class.getName());
+ entityEventDetails.put(EVENT_PROJECT_ACCOUNT_REMOVE, Project.class.getName());
+
+ // Network as a Service
+ entityEventDetails.put(EVENT_NETWORK_ELEMENT_CONFIGURE,Network.class.getName());
+
+ // Physical Network Events
+ entityEventDetails.put(EVENT_PHYSICAL_NETWORK_CREATE, PhysicalNetwork.class.getName());
+ entityEventDetails.put(EVENT_PHYSICAL_NETWORK_DELETE, PhysicalNetwork.class.getName());
+ entityEventDetails.put(EVENT_PHYSICAL_NETWORK_UPDATE, PhysicalNetwork.class.getName());
+
+ // Physical Network Service Provider Events
+ entityEventDetails.put(EVENT_SERVICE_PROVIDER_CREATE, PhysicalNetworkServiceProvider.class.getName());
+ entityEventDetails.put(EVENT_SERVICE_PROVIDER_DELETE, PhysicalNetworkServiceProvider.class.getName());
+ entityEventDetails.put(EVENT_SERVICE_PROVIDER_UPDATE, PhysicalNetworkServiceProvider.class.getName());
+
+ // Physical Network TrafficType Events
+ entityEventDetails.put(EVENT_TRAFFIC_TYPE_CREATE, PhysicalNetworkTrafficType.class.getName());
+ entityEventDetails.put(EVENT_TRAFFIC_TYPE_DELETE, PhysicalNetworkTrafficType.class.getName());
+ entityEventDetails.put(EVENT_TRAFFIC_TYPE_UPDATE, PhysicalNetworkTrafficType.class.getName());
+
+ // external network device events
+ entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_ADD, PhysicalNetwork.class.getName());
+ entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_DELETE, PhysicalNetwork.class.getName());
+ entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_CONFIGURE, PhysicalNetwork.class.getName());
+
+ // external switch management device events (E.g.: Cisco Nexus 1000v Virtual Supervisor Module.
+ entityEventDetails.put(EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_ADD, "Nexus1000v");
+ entityEventDetails.put(EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_DELETE, "Nexus1000v");
+ entityEventDetails.put(EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_CONFIGURE, "Nexus1000v");
+ entityEventDetails.put(EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_ENABLE, "Nexus1000v");
+ entityEventDetails.put(EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_DISABLE, "Nexus1000v");
+
+
+ entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_ADD, PhysicalNetwork.class.getName());
+ entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_DELETE, PhysicalNetwork.class.getName());
+ entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_CONFIGURE, PhysicalNetwork.class.getName());
+
+ // VPC
+ entityEventDetails.put(EVENT_VPC_CREATE, Vpc.class.getName());
+ entityEventDetails.put(EVENT_VPC_UPDATE, Vpc.class.getName());
+ entityEventDetails.put(EVENT_VPC_DELETE, Vpc.class.getName());
+ entityEventDetails.put(EVENT_VPC_RESTART, Vpc.class.getName());
+
+ // VPC offerings
+ entityEventDetails.put(EVENT_VPC_OFFERING_CREATE, Vpc.class.getName());
+ entityEventDetails.put(EVENT_VPC_OFFERING_UPDATE, Vpc.class.getName());
+ entityEventDetails.put(EVENT_VPC_OFFERING_DELETE, Vpc.class.getName());
+
+ // Private gateway
+ entityEventDetails.put(EVENT_PRIVATE_GATEWAY_CREATE, PrivateGateway.class.getName());
+ entityEventDetails.put(EVENT_PRIVATE_GATEWAY_DELETE, PrivateGateway.class.getName());
+
+ // Static routes
+ entityEventDetails.put(EVENT_STATIC_ROUTE_CREATE, StaticRoute.class.getName());
+ entityEventDetails.put(EVENT_STATIC_ROUTE_DELETE, StaticRoute.class.getName());
+
+ // tag related events
+ entityEventDetails.put(EVENT_TAGS_CREATE, "Tag");
+ entityEventDetails.put(EVENT_TAGS_DELETE, "tag");
+
+ // external network device events
+ entityEventDetails.put(EVENT_EXTERNAL_NVP_CONTROLLER_ADD, "NvpController");
+ entityEventDetails.put(EVENT_EXTERNAL_NVP_CONTROLLER_DELETE, "NvpController");
+ entityEventDetails.put(EVENT_EXTERNAL_NVP_CONTROLLER_CONFIGURE, "NvpController");
+
+ // AutoScale
+ entityEventDetails.put(EVENT_COUNTER_CREATE, AutoScaleCounter.class.getName());
+ entityEventDetails.put(EVENT_COUNTER_DELETE, AutoScaleCounter.class.getName());
+ entityEventDetails.put(EVENT_CONDITION_CREATE, Condition.class.getName());
+ entityEventDetails.put(EVENT_CONDITION_DELETE, Condition.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEPOLICY_CREATE, AutoScalePolicy.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEPOLICY_UPDATE, AutoScalePolicy.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEPOLICY_DELETE, AutoScalePolicy.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_CREATE, AutoScaleVmProfile.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_DELETE, AutoScaleVmProfile.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_UPDATE, AutoScaleVmProfile.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_CREATE, AutoScaleVmGroup.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_DELETE, AutoScaleVmGroup.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_UPDATE, AutoScaleVmGroup.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_ENABLE, AutoScaleVmGroup.class.getName());
+ entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_DISABLE, AutoScaleVmGroup.class.getName());
+ }
+
+ public static String getEntityForEvent (String eventName) {
+ String entityClassName = entityEventDetails.get(eventName);
+ if (entityClassName == null || entityClassName.isEmpty()) {
+ return null;
+ }
+ int index = entityClassName.lastIndexOf(".");
+ String entityName = entityClassName;
+ if (index != -1) {
+ entityName = entityClassName.substring(index+1);
+ }
+ return entityName;
+ }
}
diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index 413b6d9..1dbb327 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -16,26 +16,25 @@
// under the License.
package com.cloud.network;
-import org.apache.cloudstack.acl.ControlledEntity;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
-import com.cloud.utils.fsm.FiniteState;
-import com.cloud.utils.fsm.StateMachine;
+import com.cloud.utils.fsm.StateMachine2;
+import com.cloud.utils.fsm.StateObject;
+import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
/**
* owned by an account.
*/
-public interface Network extends ControlledEntity, InternalIdentity, Identity {
+public interface Network extends ControlledEntity, StateObject<Network.State>, InternalIdentity, Identity {
- public enum GuestType {
+ public enum GuestType {
Shared,
Isolated
}
@@ -204,7 +203,8 @@
OperationFailed;
}
- enum State implements FiniteState<State, Event> {
+ public enum State {
+
Allocated("Indicates the network configuration is in allocated but not setup"),
Setup("Indicates the network configuration is setup"),
Implementing("Indicates the network configuration is being implemented"),
@@ -212,39 +212,8 @@
Shutdown("Indicates the network configuration is being destroyed"),
Destroy("Indicates that the network is destroyed");
+ protected static final StateMachine2<State, Network.Event, Network> s_fsm = new StateMachine2<State, Network.Event, Network>();
- @Override
- public StateMachine<State, Event> getStateMachine() {
- return s_fsm;
- }
-
- @Override
- public State getNextState(Event event) {
- return s_fsm.getNextState(this, event);
- }
-
- @Override
- public List<State> getFromStates(Event event) {
- return s_fsm.getFromStates(this, event);
- }
-
- @Override
- public Set<Event> getPossibleEvents() {
- return s_fsm.getPossibleEvents(this);
- }
-
- String _description;
-
- @Override
- public String getDescription() {
- return _description;
- }
-
- private State(String description) {
- _description = description;
- }
-
- private static StateMachine<State, Event> s_fsm = new StateMachine<State, Event>();
static {
s_fsm.addTransition(State.Allocated, Event.ImplementNetwork, State.Implementing);
s_fsm.addTransition(State.Implementing, Event.OperationSucceeded, State.Implemented);
@@ -253,6 +222,15 @@
s_fsm.addTransition(State.Shutdown, Event.OperationSucceeded, State.Allocated);
s_fsm.addTransition(State.Shutdown, Event.OperationFailed, State.Implemented);
}
+
+ public static StateMachine2<State, Network.Event, Network> getStateMachine() {
+ return s_fsm;
+ }
+
+ String _description;
+ private State(String description) {
+ _description = description;
+ }
}
String getName();
diff --git a/api/src/com/cloud/storage/Snapshot.java b/api/src/com/cloud/storage/Snapshot.java
index 99bdee6..2e2965a 100644
--- a/api/src/com/cloud/storage/Snapshot.java
+++ b/api/src/com/cloud/storage/Snapshot.java
@@ -16,14 +16,16 @@
// under the License.
package com.cloud.storage;
-import java.util.Date;
-
-import org.apache.cloudstack.acl.ControlledEntity;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.utils.fsm.StateMachine2;
+import com.cloud.utils.fsm.StateObject;
+import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
-public interface Snapshot extends ControlledEntity, Identity, InternalIdentity {
+import java.util.Date;
+
+public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, StateObject<Snapshot.State> {
public enum Type {
MANUAL,
RECURRING,
@@ -51,13 +53,29 @@
}
}
- public enum Status {
+ public enum State {
Creating,
CreatedOnPrimary,
BackingUp,
BackedUp,
Error;
+ private final static StateMachine2<State, Event, Snapshot> s_fsm = new StateMachine2<State, Event, Snapshot>();
+
+ public static StateMachine2<State, Event, Snapshot> getStateMachine() {
+ return s_fsm;
+ }
+
+ static {
+ s_fsm.addTransition(null, Event.CreateRequested, Creating);
+ s_fsm.addTransition(Creating, Event.OperationSucceeded, CreatedOnPrimary);
+ s_fsm.addTransition(Creating, Event.OperationNotPerformed, BackedUp);
+ s_fsm.addTransition(Creating, Event.OperationFailed, Error);
+ s_fsm.addTransition(CreatedOnPrimary, Event.BackupToSecondary, BackingUp);
+ s_fsm.addTransition(BackingUp, Event.OperationSucceeded, BackedUp);
+ s_fsm.addTransition(BackingUp, Event.OperationFailed, Error);
+ }
+
public String toString() {
return this.name();
}
@@ -67,6 +85,15 @@
}
}
+ enum Event {
+ CreateRequested,
+ OperationNotPerformed,
+ BackupToSecondary,
+ BackedupToSecondary,
+ OperationSucceeded,
+ OperationFailed
+ }
+
public static final long MANUAL_POLICY_ID = 0L;
long getAccountId();
@@ -81,7 +108,7 @@
Type getType();
- Status getStatus();
+ State getState();
HypervisorType getHypervisorType();
diff --git a/api/src/org/apache/cloudstack/api/response/SnapshotResponse.java b/api/src/org/apache/cloudstack/api/response/SnapshotResponse.java
index 8ea0d7f..58b7cf1 100644
--- a/api/src/org/apache/cloudstack/api/response/SnapshotResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/SnapshotResponse.java
@@ -16,16 +16,16 @@
// under the License.
package org.apache.cloudstack.api.response;
-import java.util.Date;
-import java.util.List;
-
-import org.apache.cloudstack.api.ApiConstants;
import com.cloud.serializer.Param;
import com.cloud.storage.Snapshot;
import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
+import java.util.Date;
+import java.util.List;
+
@EntityReference(value=Snapshot.class)
@SuppressWarnings("unused")
public class SnapshotResponse extends BaseResponse implements ControlledEntityResponse {
@@ -81,7 +81,7 @@
@SerializedName(ApiConstants.STATE)
@Param(description = "the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage")
- private Snapshot.Status state;
+ private Snapshot.State state;
@SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with snapshot", responseObject = ResourceTagResponse.class)
private List<ResourceTagResponse> tags;
@@ -149,7 +149,7 @@
this.intervalType = intervalType;
}
- public void setState(Snapshot.Status state) {
+ public void setState(Snapshot.State state) {
this.state = state;
}
diff --git a/client/pom.xml b/client/pom.xml
index 7ebe50c..63ec2ef 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -117,6 +117,11 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-mom-rabbitmq</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${cs.mysql.version}</version>
diff --git a/core/src/com/cloud/storage/SnapshotVO.java b/core/src/com/cloud/storage/SnapshotVO.java
index e5e3650..c1c5f21 100644
--- a/core/src/com/cloud/storage/SnapshotVO.java
+++ b/core/src/com/cloud/storage/SnapshotVO.java
@@ -16,23 +16,13 @@
// under the License.
package com.cloud.storage;
-import java.util.Date;
-import java.util.UUID;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
-
-import org.apache.cloudstack.api.Identity;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.db.GenericDao;
import com.google.gson.annotations.Expose;
-import org.apache.cloudstack.api.InternalIdentity;
+
+import javax.persistence.*;
+import java.util.Date;
+import java.util.UUID;
@Entity
@Table(name="snapshots")
@@ -69,7 +59,7 @@
@Expose
@Column(name="status", updatable = true, nullable=false)
@Enumerated(value=EnumType.STRING)
- private Status status;
+ private State status;
@Column(name="snapshot_type")
short snapshotType;
@@ -127,7 +117,7 @@
this.snapshotType = snapshotType;
this.typeDescription = typeDescription;
this.size = size;
- this.status = Status.Creating;
+ this.status = State.Creating;
this.prevSnapshotId = 0;
this.hypervisorType = hypervisorType;
this.version = "2.2";
@@ -252,11 +242,11 @@
}
@Override
- public Status getStatus() {
+ public State getState() {
return status;
}
- public void setStatus(Status status) {
+ public void setStatus(State status) {
this.status = status;
}
diff --git a/framework/events/pom.xml b/framework/events/pom.xml
new file mode 100644
index 0000000..ef812e5
--- /dev/null
+++ b/framework/events/pom.xml
@@ -0,0 +1,47 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cloud-framework-events</artifactId>
+ <name>Apache CloudStack Event Notification Framework</name>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack-framework</artifactId>
+ <version>4.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>${cs.gson.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <defaultGoal>install</defaultGoal>
+ <sourceDirectory>src</sourceDirectory>
+ <testSourceDirectory>test</testSourceDirectory>
+ </build>
+</project>
diff --git a/framework/events/src/org/apache/cloudstack/framework/events/Event.java b/framework/events/src/org/apache/cloudstack/framework/events/Event.java
new file mode 100644
index 0000000..eb6f48d
--- /dev/null
+++ b/framework/events/src/org/apache/cloudstack/framework/events/Event.java
@@ -0,0 +1,94 @@
+/*
+ * 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.google.gson.Gson;
+
+public class Event {
+
+ String eventCategory;
+ String eventType;
+ String eventSource;
+ String resourceType;
+ String resourceUUID;
+ String description;
+
+ public Event(String eventSource, String eventCategory, String eventType, String resourceType,
+ String resourceUUID) {
+ this.eventCategory = eventCategory;
+ this.eventType = eventType;
+ this.eventSource = eventSource;
+ this.resourceType = resourceType;
+ this.resourceUUID = resourceUUID;
+ }
+
+ public String getEventCategory() {
+ return eventCategory;
+ }
+
+ public void setEventCategory(String category) {
+ eventCategory = category;
+ }
+
+ public String getEventType() {
+ return eventType;
+ }
+
+ public void setEventType(String type) {
+ eventType = type;
+ }
+
+ public String getEventSource() {
+ return eventSource;
+ }
+
+ void setEventSource(String source) {
+ eventSource = source;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription (Object message) {
+ Gson gson = new Gson();
+ this.description = gson.toJson(message).toString();
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ public void setResourceType(String resourceType) {
+ this.resourceType = resourceType;
+ }
+
+ public void setResourceUUID(String uuid) {
+ this.resourceUUID = uuid;
+ }
+
+ public String getResourceUUID () {
+ return resourceUUID;
+ }
+}
\ No newline at end of file
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 0000000..c16ee6f
--- /dev/null
+++ b/framework/events/src/org/apache/cloudstack/framework/events/EventBus.java
@@ -0,0 +1,55 @@
+/*
+ * 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.UUID;
+
+/**
+ * Interface to publish and subscribe to CloudStack events
+ *
+ */
+public interface EventBus extends Adapter{
+
+ /**
+ * publish an event on to the event bus
+ *
+ * @param event event that needs to be published on the event bus
+ */
+ void publish(Event event) throws EventBusException;
+
+ /**
+ * subscribe to events that matches specified event topics
+ *
+ * @param topic defines category and type of the events being subscribed to
+ * @param subscriber subscriber that intends to receive event notification
+ * @return UUID returns the subscription ID
+ */
+ UUID subscribe(EventTopic topic, EventSubscriber subscriber) throws EventBusException;
+
+ /**
+ * unsubscribe to events of a category and a type
+ *
+ * @param subscriber subscriber that intends to unsubscribe from the event notification
+ */
+ void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws EventBusException;
+
+}
diff --git a/framework/events/src/org/apache/cloudstack/framework/events/EventBusException.java b/framework/events/src/org/apache/cloudstack/framework/events/EventBusException.java
new file mode 100644
index 0000000..5654ba0
--- /dev/null
+++ b/framework/events/src/org/apache/cloudstack/framework/events/EventBusException.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 EventBusException extends Exception{
+ public EventBusException (String msg) {
+ super(msg);
+ }
+}
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 0000000..b1c30c2
--- /dev/null
+++ b/framework/events/src/org/apache/cloudstack/framework/events/EventSubscriber.java
@@ -0,0 +1,30 @@
+/*
+ * 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/LICENSE2.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 interface EventSubscriber {
+
+ /**
+ * Callback method. EventBus calls this method on occurrence of subscribed event
+ *
+ * @param event details of the event
+ */
+ void onEvent(Event event);
+}
diff --git a/framework/events/src/org/apache/cloudstack/framework/events/EventTopic.java b/framework/events/src/org/apache/cloudstack/framework/events/EventTopic.java
new file mode 100644
index 0000000..19b727d
--- /dev/null
+++ b/framework/events/src/org/apache/cloudstack/framework/events/EventTopic.java
@@ -0,0 +1,57 @@
+/*
+ * 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 EventTopic {
+
+ String eventCategory;
+ String eventType;
+ String resourceType;
+ String resourceUUID;
+ String eventSource;
+
+ public EventTopic(String eventCategory, String eventType, String resourceType, String resourceUUID, String eventSource) {
+ this.eventCategory = eventCategory;
+ this.eventType = eventType;
+ this.resourceType = resourceType;
+ this.resourceUUID = resourceUUID;
+ this.eventSource = eventSource;
+ }
+
+ public String getEventCategory() {
+ return eventCategory;
+ }
+
+ public String getEventType() {
+ return eventType;
+ }
+
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ public String getEventSource() {
+ return eventSource;
+ }
+
+ public String getResourceUUID() {
+ return resourceUUID;
+ }
+}
diff --git a/framework/pom.xml b/framework/pom.xml
new file mode 100644
index 0000000..81e0916
--- /dev/null
+++ b/framework/pom.xml
@@ -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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cloudstack-framework</artifactId>
+ <name>Apache CloudStack framework POM</name>
+ <packaging>pom</packaging>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack</artifactId>
+ <version>4.1.0-SNAPSHOT</version>
+ </parent>
+ <build>
+ <defaultGoal>install</defaultGoal>
+ </build>
+ <modules>
+ <module>events</module>
+ </modules>
+</project>
diff --git a/plugins/event-bus/rabbitmq/pom.xml b/plugins/event-bus/rabbitmq/pom.xml
new file mode 100644
index 0000000..6a47983
--- /dev/null
+++ b/plugins/event-bus/rabbitmq/pom.xml
@@ -0,0 +1,46 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cloud-mom-rabbitmq</artifactId>
+ <name>Apache CloudStack Plugin - RabbitMQ Event Bus</name>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack-plugins</artifactId>
+ <version>4.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+ <dependencies>
+ <dependency>
+ <groupId>com.rabbitmq</groupId>
+ <artifactId>amqp-client</artifactId>
+ <version>2.8.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-framework-events</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <defaultGoal>install</defaultGoal>
+ <sourceDirectory>src</sourceDirectory>
+ </build>
+</project>
diff --git a/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java b/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java
new file mode 100644
index 0000000..3a06c42
--- /dev/null
+++ b/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java
@@ -0,0 +1,555 @@
+/*
+ * 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.mom.rabbitmq;
+
+import com.rabbitmq.client.*;
+import org.apache.cloudstack.framework.events.*;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.Ternary;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Local(value=EventBus.class)
+public class RabbitMQEventBus implements EventBus {
+
+ // details of AMQP server
+ private static String _amqpHost;
+ private static Integer _port;
+ private static String _username;
+ private static String _password;
+
+ // AMQP exchange name where all CloudStack events will be published
+ private static String _amqpExchangeName;
+
+ // hashmap to book keep the registered subscribers
+ private static ConcurrentHashMap<String, Ternary<String, Channel, EventSubscriber>> _subscribers;
+
+ // connection to AMQP server,
+ private static Connection _connection=null;
+
+ // AMQP server should consider messages acknowledged once delivered if _autoAck is true
+ private static boolean _autoAck = true;
+
+ private ExecutorService executorService;
+ private String _name;
+ private static DisconnectHandler disconnectHandler;
+ private static Integer _retryInterval;
+ private static final Logger s_logger = Logger.getLogger(RabbitMQEventBus.class);
+
+ @Override
+ public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+
+ _amqpHost = (String) params.get("server");
+ if (_amqpHost == null || _amqpHost.isEmpty()) {
+ throw new ConfigurationException("Unable to get the AMQP server details");
+ }
+
+ _username = (String) params.get("username");
+ if (_username == null || _username.isEmpty()) {
+ throw new ConfigurationException("Unable to get the username details");
+ }
+
+ _password = (String) params.get("password");
+ if (_password == null || _password.isEmpty()) {
+ throw new ConfigurationException("Unable to get the password details");
+ }
+
+ _amqpExchangeName = (String) params.get("exchangename");
+ if (_amqpExchangeName == null || _amqpExchangeName.isEmpty()) {
+ throw new ConfigurationException("Unable to get the _exchange details on the AMQP server");
+ }
+
+ try {
+ String portStr = (String) params.get("port");
+ if (portStr == null || portStr.isEmpty()) {
+ throw new ConfigurationException("Unable to get the port details of AMQP server");
+ }
+ _port = Integer.parseInt(portStr);
+
+ String retryIntervalStr = (String) params.get("retryinterval");
+ if (retryIntervalStr == null || retryIntervalStr.isEmpty()) {
+ // default to 10s to try out reconnect
+ retryIntervalStr = "10000";
+ }
+ _retryInterval = Integer.parseInt(retryIntervalStr);
+ } catch (NumberFormatException e) {
+ throw new ConfigurationException("Invalid port number/retry interval");
+ }
+
+ _subscribers = new ConcurrentHashMap<String, Ternary<String, Channel, EventSubscriber>>();
+
+ executorService = Executors.newCachedThreadPool();
+ disconnectHandler = new DisconnectHandler();
+ _name = name;
+ return true;
+ }
+
+ /** Call to subscribe to interested set of events
+ *
+ * @param topic defines category and type of the events being subscribed to
+ * @param subscriber subscriber that intends to receive event notification
+ * @return UUID that represents the subscription with event bus
+ * @throws EventBusException
+ */
+ @Override
+ public UUID subscribe(EventTopic topic, EventSubscriber subscriber) throws EventBusException {
+
+ if (subscriber == null || topic == null) {
+ throw new EventBusException("Invalid EventSubscriber/EventTopic object passed.");
+ }
+
+ // create a UUID, that will be used for managing subscriptions and also used as queue name
+ // for on the queue used for the subscriber on the AMQP broker
+ UUID queueId = UUID.randomUUID();
+ String queueName = queueId.toString();
+
+ try {
+ String bindingKey = createBindingKey(topic);
+
+ // store the subscriber details before creating channel
+ _subscribers.put(queueName, new Ternary(bindingKey, null, subscriber));
+
+ // create a channel dedicated for this subscription
+ Connection connection = getConnection();
+ Channel channel = createChannel(connection);
+
+ // create a queue and bind it to the exchange with binding key formed from event topic
+ createExchange(channel, _amqpExchangeName);
+ channel.queueDeclare(queueName, false, false, false, null);
+ channel.queueBind(queueName, _amqpExchangeName, bindingKey);
+
+ // register a callback handler to receive the events that a subscriber subscribed to
+ channel.basicConsume(queueName, _autoAck, queueName,
+ new DefaultConsumer(channel) {
+ @Override
+ public void handleDelivery(String queueName,
+ Envelope envelope,
+ AMQP.BasicProperties properties,
+ byte[] body)
+ throws IOException {
+ Ternary<String, Channel, EventSubscriber> queueDetails = _subscribers.get(queueName);
+ if (queueDetails != null) {
+ EventSubscriber subscriber = queueDetails.third();
+ String routingKey = envelope.getRoutingKey();
+ String eventSource = getEventSourceFromRoutingKey(routingKey);
+ String eventCategory = getEventCategoryFromRoutingKey(routingKey);
+ String eventType = getEventTypeFromRoutingKey(routingKey);
+ String resourceType = getResourceTypeFromRoutingKey(routingKey);
+ String resourceUUID = getResourceUUIDFromRoutingKey(routingKey);
+ Event event = new Event(eventSource, eventCategory, eventType,
+ resourceType, resourceUUID);
+ event.setDescription(new String(body));
+
+ // deliver the event to call back object provided by subscriber
+ subscriber.onEvent(event);
+ }
+ }
+ }
+ );
+
+ // update the channel details for the subscription
+ Ternary<String, Channel, EventSubscriber> queueDetails = _subscribers.get(queueName);
+ queueDetails.second(channel);
+ _subscribers.put(queueName, queueDetails);
+
+ } catch (AlreadyClosedException closedException) {
+ s_logger.warn("Connection to AMQP service is lost. Subscription:" + queueName +
+ " will be active after reconnection");
+ } catch (ConnectException connectException) {
+ s_logger.warn("Connection to AMQP service is lost. Subscription:" + queueName +
+ " will be active after reconnection");
+ } catch (Exception e) {
+ throw new EventBusException("Failed to subscribe to event due to " + e.getMessage());
+ }
+
+ return queueId;
+ }
+
+ @Override
+ public void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws EventBusException {
+ try {
+ String classname = subscriber.getClass().getName();
+ String queueName = UUID.nameUUIDFromBytes(classname.getBytes()).toString();
+ Ternary<String, Channel, EventSubscriber> queueDetails = _subscribers.get(queueName);
+ Channel channel = queueDetails.second();
+ channel.basicCancel(queueName);
+ _subscribers.remove(queueName, queueDetails);
+ } catch (Exception e) {
+ throw new EventBusException("Failed to unsubscribe from event bus due to " + e.getMessage());
+ }
+ }
+
+ // publish event on to the exchange created on AMQP server
+ @Override
+ public void publish(Event event) throws EventBusException {
+
+ String routingKey = createRoutingKey(event);
+ String eventDescription = event.getDescription();
+
+ try {
+ Connection connection = getConnection();
+ Channel channel = createChannel(connection);
+ createExchange(channel, _amqpExchangeName);
+ publishEventToExchange(channel, _amqpExchangeName, routingKey, eventDescription);
+ channel.close();
+ } catch (AlreadyClosedException e) {
+ closeConnection();
+ throw new EventBusException("Failed to publish event to message broker as connection to AMQP broker in lost");
+ } catch (Exception e) {
+ throw new EventBusException("Failed to publish event to message broker due to " + e.getMessage());
+ }
+ }
+
+ /** creates a routing key from the event details.
+ * created routing key will be used while publishing the message to exchange on AMQP server
+ */
+ private String createRoutingKey(Event event) {
+
+ StringBuilder routingKey = new StringBuilder();
+
+ String eventSource = replaceNullWithWildcard(event.getEventSource());
+ eventSource = eventSource.replace(".", "-");
+
+ String eventCategory = replaceNullWithWildcard(event.getEventCategory());
+ eventCategory = eventCategory.replace(".", "-");
+
+ String eventType = replaceNullWithWildcard(event.getEventType());
+ eventType = eventType.replace(".", "-");
+
+ String resourceType = replaceNullWithWildcard(event.getResourceType());
+ resourceType = resourceType.replace(".", "-");
+
+ String resourceUuid = replaceNullWithWildcard(event.getResourceUUID());
+ resourceUuid = resourceUuid.replace(".", "-");
+
+ // routing key will be of format: eventSource.eventCategory.eventType.resourceType.resourceUuid
+ routingKey.append(eventSource);
+ routingKey.append(".");
+ routingKey.append(eventCategory);
+ routingKey.append(".");
+ routingKey.append(eventType);
+ routingKey.append(".");
+ routingKey.append(resourceType);
+ routingKey.append(".");
+ routingKey.append(resourceUuid);
+
+ return routingKey.toString();
+ }
+
+ /** creates a binding key from the event topic that subscriber specified
+ * binding key will be used to bind the queue created for subscriber to exchange on AMQP server
+ */
+ private String createBindingKey(EventTopic topic) {
+
+ StringBuilder bindingKey = new StringBuilder();
+
+ String eventSource = replaceNullWithWildcard(topic.getEventSource());
+ eventSource = eventSource.replace(".", "-");
+
+ String eventCategory = replaceNullWithWildcard(topic.getEventCategory());
+ eventCategory = eventCategory.replace(".", "-");
+
+ String eventType = replaceNullWithWildcard(topic.getEventType());
+ eventType = eventType.replace(".", "-");
+
+ String resourceType = replaceNullWithWildcard(topic.getResourceType());
+ resourceType = resourceType.replace(".", "-");
+
+ String resourceUuid = replaceNullWithWildcard(topic.getResourceUUID());
+ resourceUuid = resourceUuid.replace(".", "-");
+
+ // binding key will be of format: eventSource.eventCategory.eventType.resourceType.resourceUuid
+ bindingKey.append(eventSource);
+ bindingKey.append(".");
+ bindingKey.append(eventCategory);
+ bindingKey.append(".");
+ bindingKey.append(eventType);
+ bindingKey.append(".");
+ bindingKey.append(resourceType);
+ bindingKey.append(".");
+ bindingKey.append(resourceUuid);
+
+ return bindingKey.toString();
+ }
+
+ private synchronized Connection getConnection() throws Exception {
+ if (_connection == null) {
+ try {
+ return createConnection();
+ } catch (Exception e) {
+ s_logger.error("Failed to create a connection to AMQP server due to " + e.getMessage());
+ throw e;
+ }
+ } else {
+ return _connection;
+ }
+ }
+
+ private synchronized Connection createConnection() throws Exception {
+ try {
+ ConnectionFactory factory = new ConnectionFactory();
+ factory.setUsername(_username);
+ factory.setPassword(_password);
+ factory.setVirtualHost("/");
+ factory.setHost(_amqpHost);
+ factory.setPort(_port);
+ Connection connection = factory.newConnection();
+ connection.addShutdownListener(disconnectHandler);
+ _connection = connection;
+ return _connection;
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+
+ private synchronized void closeConnection() {
+ try {
+ if (_connection != null) {
+ _connection.close();
+ }
+ } catch (Exception e) {
+ s_logger.warn("Failed to close connection to AMQP server due to " + e.getMessage());
+ }
+ _connection = null;
+ }
+
+ private synchronized void abortConnection () {
+ if (_connection == null)
+ return;
+
+ try {
+ _connection.abort();
+ } catch (Exception e) {
+ s_logger.warn("Failed to abort connection due to " + e.getMessage());
+ }
+ _connection = null;
+ }
+
+ private String replaceNullWithWildcard(String key) {
+ if (key == null || key.isEmpty()) {
+ return "*";
+ } else {
+ return key;
+ }
+ }
+
+ private Channel createChannel(Connection connection) throws Exception {
+ try {
+ return connection.createChannel();
+ } catch (java.io.IOException exception) {
+ s_logger.warn("Failed to create a channel due to " + exception.getMessage());
+ throw exception;
+ }
+ }
+
+ private void createExchange(Channel channel, String exchangeName) throws Exception {
+ try {
+ channel.exchangeDeclare(exchangeName, "topic", true);
+ } catch (java.io.IOException exception) {
+ s_logger.error("Failed to create exchange" + exchangeName + " on RabbitMQ server");
+ throw exception;
+ }
+ }
+
+ private void publishEventToExchange(Channel channel, String exchangeName,
+ String routingKey, String eventDescription) throws Exception {
+ try {
+ byte[] messageBodyBytes = eventDescription.getBytes();
+ channel.basicPublish(exchangeName, routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN, messageBodyBytes);
+ } catch (Exception e) {
+ s_logger.error("Failed to publish event " + routingKey + " on exchange " + exchangeName +
+ " of message broker due to " + e.getMessage());
+ throw e;
+ }
+ }
+
+ private String getEventCategoryFromRoutingKey(String routingKey) {
+ String[] keyParts = routingKey.split("\\.");
+ return keyParts[1];
+ }
+
+ private String getEventTypeFromRoutingKey(String routingKey) {
+ String[] keyParts = routingKey.split("\\.");
+ return keyParts[2];
+ }
+
+ private String getEventSourceFromRoutingKey(String routingKey) {
+ String[] keyParts = routingKey.split("\\.");
+ return keyParts[0];
+ }
+
+ private String getResourceTypeFromRoutingKey(String routingKey) {
+ String[] keyParts = routingKey.split("\\.");
+ return keyParts[3];
+ }
+
+ private String getResourceUUIDFromRoutingKey(String routingKey) {
+ String[] keyParts = routingKey.split("\\.");
+ return keyParts[4];
+ }
+
+ @Override
+ public String getName() {
+ return _name;
+ }
+
+ @Override
+ public boolean start() {
+ ReconnectionTask reconnect = new ReconnectionTask(); // initiate connection to AMQP server
+ executorService.submit(reconnect);
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+
+ if (_connection.isOpen()) {
+ for (String subscriberId : _subscribers.keySet()) {
+ Ternary<String, Channel, EventSubscriber> subscriberDetails = _subscribers.get(subscriberId);
+ Channel channel = subscriberDetails.second();
+ String queueName = subscriberId;
+ try {
+ channel.queueDelete(queueName);
+ channel.abort();
+ } catch (IOException ioe) {
+ s_logger.warn("Failed to delete queue: " + queueName + " on AMQP server due to " + ioe.getMessage() );
+ }
+ }
+ }
+
+ closeConnection();
+ return true;
+ }
+
+ // logic to deal with loss of connection to AMQP server
+ private class DisconnectHandler implements ShutdownListener {
+
+ @Override
+ public void shutdownCompleted(ShutdownSignalException shutdownSignalException) {
+ if (!shutdownSignalException.isInitiatedByApplication()) {
+
+ for (String subscriberId : _subscribers.keySet()) {
+ Ternary<String, Channel, EventSubscriber> subscriberDetails = _subscribers.get(subscriberId);
+ subscriberDetails.second(null);
+ _subscribers.put(subscriberId, subscriberDetails);
+ }
+
+ abortConnection(); // disconnected to AMQP server, so abort the connection and channels
+ s_logger.warn("Connection has been shutdown by AMQP server. Attempting to reconnect.");
+
+ // initiate re-connect process
+ ReconnectionTask reconnect = new ReconnectionTask();
+ executorService.submit(reconnect);
+ }
+ }
+ }
+
+ // retry logic to connect back to AMQP server after loss of connection
+ private class ReconnectionTask implements Runnable {
+
+ boolean connected = false;
+ Connection connection = null;
+
+ public void run() {
+
+ while (!connected) {
+ try {
+ Thread.sleep(_retryInterval);
+ } catch (InterruptedException ie) {
+ // ignore timer interrupts
+ }
+
+ try {
+ try {
+ connection = createConnection();
+ connected = true;
+ } catch (IOException ie) {
+ continue; // can't establish connection to AMQP server yet, so continue
+ }
+
+ // prepare consumer on AMQP server for each of subscriber
+ for (String subscriberId : _subscribers.keySet()) {
+ Ternary<String, Channel, EventSubscriber> subscriberDetails = _subscribers.get(subscriberId);
+ String bindingKey = subscriberDetails.first();
+ EventSubscriber subscriber = subscriberDetails.third();
+
+ /** create a queue with subscriber ID as queue name and bind it to the exchange
+ * with binding key formed from event topic
+ */
+ Channel channel = createChannel(connection);
+ createExchange(channel, _amqpExchangeName);
+ channel.queueDeclare(subscriberId, false, false, false, null);
+ channel.queueBind(subscriberId, _amqpExchangeName, bindingKey);
+
+ // register a callback handler to receive the events that a subscriber subscribed to
+ channel.basicConsume(subscriberId, _autoAck, subscriberId,
+ new DefaultConsumer(channel) {
+ @Override
+ public void handleDelivery(String queueName,
+ Envelope envelope,
+ AMQP.BasicProperties properties,
+ byte[] body)
+ throws IOException {
+
+ Ternary<String, Channel, EventSubscriber> subscriberDetails
+ = _subscribers.get(queueName); // queue name == subscriber ID
+
+ if (subscriberDetails != null) {
+ EventSubscriber subscriber = subscriberDetails.third();
+ String routingKey = envelope.getRoutingKey();
+ String eventSource = getEventSourceFromRoutingKey(routingKey);
+ String eventCategory = getEventCategoryFromRoutingKey(routingKey);
+ String eventType = getEventTypeFromRoutingKey(routingKey);
+ String resourceType = getResourceTypeFromRoutingKey(routingKey);
+ String resourceUUID = getResourceUUIDFromRoutingKey(routingKey);
+
+ // create event object from the message details obtained from AMQP server
+ Event event = new Event(eventSource, eventCategory, eventType,
+ resourceType, resourceUUID);
+ event.setDescription(new String(body));
+
+ // deliver the event to call back object provided by subscriber
+ subscriber.onEvent(event);
+ }
+ }
+ }
+ );
+
+ // update the channel details for the subscription
+ subscriberDetails.second(channel);
+ _subscribers.put(subscriberId, subscriberDetails);
+ }
+ } catch (Exception e) {
+ s_logger.warn("Failed to recreate queues and binding for the subscribers due to " + e.getMessage());
+ }
+ }
+ return;
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java b/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
index 30a1129..2104322 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
@@ -18,6 +18,7 @@
import javax.ejb.Local;
+import com.cloud.event.ActionEventUtils;
import org.apache.log4j.Logger;
import com.cloud.dc.DataCenter;
@@ -25,7 +26,6 @@
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.event.EventTypes;
-import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.network.Network;
@@ -95,7 +95,7 @@
throw new InsufficientVirtualNetworkCapcityException("Unable to allocate vnet as a part of network " + network + " implement ", DataCenter.class, dcId);
}
implemented.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(vnet));
- EventUtils.saveEvent(UserContext.current().getCallerUserId(), network.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: "+vnet+ " Network Id: "+network.getId(), 0);
+ ActionEventUtils.onCompletedActionEvent(UserContext.current().getCallerUserId(), network.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: " + vnet + " Network Id: " + network.getId(), 0);
} else {
implemented.setBroadcastUri(network.getBroadcastUri());
}
diff --git a/plugins/pom.xml b/plugins/pom.xml
index c5b6e58..f91c6ee 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -41,6 +41,7 @@
<module>hypervisors/ovm</module>
<module>hypervisors/xen</module>
<module>hypervisors/kvm</module>
+ <module>event-bus/rabbitmq</module>
<module>hypervisors/simulator</module>
<module>hypervisors/baremetal</module>
<module>network-elements/elastic-loadbalancer</module>
diff --git a/pom.xml b/pom.xml
index 35d6520..59feef5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -163,6 +163,7 @@
<module>patches</module>
<module>client</module>
<module>test</module>
+ <module>framework</module>
</modules>
<dependencyManagement>
diff --git a/server/pom.xml b/server/pom.xml
index 4c3ba6f..ef1b68a 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -80,6 +80,11 @@
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-framework-events</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>
diff --git a/server/src/com/cloud/alert/AlertManagerImpl.java b/server/src/com/cloud/alert/AlertManagerImpl.java
index a4c0fac..1a93f97 100755
--- a/server/src/com/cloud/alert/AlertManagerImpl.java
+++ b/server/src/com/cloud/alert/AlertManagerImpl.java
@@ -59,6 +59,7 @@
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDao;
import com.cloud.dc.dao.HostPodDao;
+import com.cloud.event.AlertGenerator;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
@@ -260,6 +261,10 @@
@Override
public void sendAlert(short alertType, long dataCenterId, Long podId, String subject, String body) {
+
+ // publish alert
+ AlertGenerator.publishAlertOnEventBus(getAlertType(alertType), dataCenterId, podId, subject, body);
+
// TODO: queue up these messages and send them as one set of issues once a certain number of issues is reached? If that's the case,
// shouldn't we have a type/severity as part of the API so that severe errors get sent right away?
try {
@@ -271,6 +276,65 @@
}
}
+ private String getAlertType(short alertType) {
+ if (alertType == ALERT_TYPE_MEMORY) {
+ return "ALERT.MEMORY";
+ } else if (alertType == ALERT_TYPE_CPU) {
+ return "ALERT.MEMORY";
+ } else if (alertType == ALERT_TYPE_STORAGE) {
+ return "ALERT.STORAGE";
+ } else if (alertType == ALERT_TYPE_STORAGE_ALLOCATED) {
+ return "ALERT.STORAGE.ALLOCATED";
+ } else if (alertType == ALERT_TYPE_VIRTUAL_NETWORK_PUBLIC_IP) {
+ return "ALERT.NETWORK.PUBLICIP";
+ } else if (alertType == ALERT_TYPE_PRIVATE_IP) {
+ return "ALERT.NETWORK.PRIVATEIP";
+ } else if (alertType == ALERT_TYPE_SECONDARY_STORAGE) {
+ return "ALERT.STORAGE.SECONDARY";
+ } else if (alertType == ALERT_TYPE_HOST) {
+ return "ALERT.COMPUTE.HOST";
+ } else if (alertType == ALERT_TYPE_USERVM) {
+ return "ALERT.USERVM";
+ } else if (alertType == ALERT_TYPE_DOMAIN_ROUTER) {
+ return "ALERT.SERVICE.DOMAINROUTER";
+ } else if (alertType == ALERT_TYPE_CONSOLE_PROXY) {
+ return "ALERT.SERVICE.CONSOLEPROXY";
+ } else if (alertType == ALERT_TYPE_ROUTING) {
+ return "ALERT.NETWORK.ROUTING";
+ } else if (alertType == ALERT_TYPE_STORAGE_MISC) {
+ return "ALERT.STORAGE.MISC";
+ } else if (alertType == ALERT_TYPE_USAGE_SERVER) {
+ return "ALERT.USAGE";
+ } else if (alertType == ALERT_TYPE_MANAGMENT_NODE) {
+ return "ALERT.MANAGEMENT";
+ } else if (alertType == ALERT_TYPE_DOMAIN_ROUTER_MIGRATE) {
+ return "ALERT.NETWORK.DOMAINROUTERMIGRATE";
+ } else if (alertType == ALERT_TYPE_CONSOLE_PROXY_MIGRATE) {
+ return "ALERT.SERVICE.CONSOLEPROXYMIGRATE";
+ } else if (alertType == ALERT_TYPE_USERVM_MIGRATE) {
+ return "ALERT.USERVM.MIGRATE";
+ } else if (alertType == ALERT_TYPE_VLAN) {
+ return "ALERT.NETWORK.VLAN";
+ } else if (alertType == ALERT_TYPE_SSVM) {
+ return "ALERT.SERVICE.SSVM";
+ } else if (alertType == ALERT_TYPE_USAGE_SERVER_RESULT) {
+ return "ALERT.USAGE.RESULT";
+ } else if (alertType == ALERT_TYPE_STORAGE_DELETE) {
+ return "ALERT.STORAGE.DELETE";
+ } else if (alertType == ALERT_TYPE_UPDATE_RESOURCE_COUNT) {
+ return "ALERT.RESOURCE.COUNT";
+ } else if (alertType == ALERT_TYPE_USAGE_SANITY_RESULT) {
+ return "ALERT.USAGE.SANITY";
+ } else if (alertType == ALERT_TYPE_DIRECT_ATTACHED_PUBLIC_IP) {
+ return "ALERT.NETWORK.DIRECTPUBLICIP";
+ } else if (alertType == ALERT_TYPE_LOCAL_STORAGE) {
+ return "ALERT.STORAGE.LOCAL";
+ } else if (alertType == ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED) {
+ return "ALERT.RESOURCE.EXCEED";
+ }
+ return "UNKNOWN";
+ }
+
@Override @DB
public void recalculateCapacity() {
// FIXME: the right way to do this is to register a listener (see RouterStatsListener, VMSyncListener)
diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java
index 0b08b26..143e280 100755
--- a/server/src/com/cloud/api/ApiDBUtils.java
+++ b/server/src/com/cloud/api/ApiDBUtils.java
@@ -16,68 +16,8 @@
// under the License.
package com.cloud.api;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.cloudstack.api.ApiConstants.HostDetails;
-import org.apache.cloudstack.api.ApiConstants.VMDetails;
-import org.apache.cloudstack.api.response.AccountResponse;
-import org.apache.cloudstack.api.response.AsyncJobResponse;
-import org.apache.cloudstack.api.response.DiskOfferingResponse;
-import org.apache.cloudstack.api.response.DomainRouterResponse;
-import org.apache.cloudstack.api.response.EventResponse;
-import org.apache.cloudstack.api.response.HostResponse;
-import org.apache.cloudstack.api.response.InstanceGroupResponse;
-import org.apache.cloudstack.api.response.ProjectAccountResponse;
-import org.apache.cloudstack.api.response.ProjectInvitationResponse;
-import org.apache.cloudstack.api.response.ProjectResponse;
-import org.apache.cloudstack.api.response.ResourceTagResponse;
-import org.apache.cloudstack.api.response.SecurityGroupResponse;
-import org.apache.cloudstack.api.response.ServiceOfferingResponse;
-import org.apache.cloudstack.api.response.StoragePoolResponse;
-import org.apache.cloudstack.api.response.UserResponse;
-import org.apache.cloudstack.api.response.UserVmResponse;
-import org.apache.cloudstack.api.response.VolumeResponse;
-import org.apache.cloudstack.api.response.ZoneResponse;
-
-import com.cloud.api.query.dao.AccountJoinDao;
-import com.cloud.api.query.dao.AsyncJobJoinDao;
-import com.cloud.api.query.dao.DataCenterJoinDao;
-import com.cloud.api.query.dao.DiskOfferingJoinDao;
-import com.cloud.api.query.dao.DomainRouterJoinDao;
-import com.cloud.api.query.dao.HostJoinDao;
-import com.cloud.api.query.dao.InstanceGroupJoinDao;
-import com.cloud.api.query.dao.ProjectAccountJoinDao;
-import com.cloud.api.query.dao.ProjectInvitationJoinDao;
-import com.cloud.api.query.dao.ProjectJoinDao;
-import com.cloud.api.query.dao.ResourceTagJoinDao;
-import com.cloud.api.query.dao.SecurityGroupJoinDao;
-import com.cloud.api.query.dao.ServiceOfferingJoinDao;
-import com.cloud.api.query.dao.StoragePoolJoinDao;
-import com.cloud.api.query.dao.UserAccountJoinDao;
-import com.cloud.api.query.dao.UserVmJoinDao;
-import com.cloud.api.query.dao.VolumeJoinDao;
-import com.cloud.api.query.vo.AccountJoinVO;
-import com.cloud.api.query.vo.AsyncJobJoinVO;
-import com.cloud.api.query.vo.DataCenterJoinVO;
-import com.cloud.api.query.vo.DiskOfferingJoinVO;
-import com.cloud.api.query.vo.DomainRouterJoinVO;
-import com.cloud.api.query.vo.EventJoinVO;
-import com.cloud.api.query.vo.HostJoinVO;
-import com.cloud.api.query.vo.InstanceGroupJoinVO;
-import com.cloud.api.query.vo.ProjectAccountJoinVO;
-import com.cloud.api.query.vo.ProjectInvitationJoinVO;
-import com.cloud.api.query.vo.ProjectJoinVO;
-import com.cloud.api.query.vo.ResourceTagJoinVO;
-import com.cloud.api.query.vo.SecurityGroupJoinVO;
-import com.cloud.api.query.vo.ServiceOfferingJoinVO;
-import com.cloud.api.query.vo.StoragePoolJoinVO;
-import com.cloud.api.query.vo.UserAccountJoinVO;
-import com.cloud.api.query.vo.UserVmJoinVO;
-import com.cloud.api.query.vo.VolumeJoinVO;
+import com.cloud.api.query.dao.*;
+import com.cloud.api.query.vo.*;
import com.cloud.async.AsyncJob;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobVO;
@@ -89,18 +29,8 @@
import com.cloud.configuration.ConfigurationService;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.dc.AccountVlanMapVO;
-import com.cloud.dc.ClusterVO;
-import com.cloud.dc.DataCenter;
-import com.cloud.dc.DataCenterVO;
-import com.cloud.dc.HostPodVO;
-import com.cloud.dc.Vlan;
-import com.cloud.dc.VlanVO;
-import com.cloud.dc.dao.AccountVlanMapDao;
-import com.cloud.dc.dao.ClusterDao;
-import com.cloud.dc.dao.DataCenterDao;
-import com.cloud.dc.dao.HostPodDao;
-import com.cloud.dc.dao.VlanDao;
+import com.cloud.dc.*;
+import com.cloud.dc.dao.*;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.Event;
@@ -112,65 +42,23 @@
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.network.IPAddressVO;
-import com.cloud.network.IpAddress;
-import com.cloud.network.LoadBalancerVO;
-import com.cloud.network.Network;
+import com.cloud.network.*;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
-import com.cloud.network.NetworkDomainVO;
-import com.cloud.network.NetworkManager;
-import com.cloud.network.NetworkModel;
-import com.cloud.network.NetworkProfile;
-import com.cloud.network.NetworkRuleConfigVO;
-import com.cloud.network.NetworkVO;
-import com.cloud.network.PhysicalNetworkServiceProvider;
-import com.cloud.network.PhysicalNetworkVO;
-import com.cloud.network.Site2SiteVpnGatewayVO;
-import com.cloud.network.Site2SiteCustomerGatewayVO;
import com.cloud.network.Networks.TrafficType;
-import com.cloud.network.as.AutoScalePolicy;
-import com.cloud.network.as.AutoScalePolicyConditionMapVO;
-import com.cloud.network.as.AutoScalePolicyVO;
-import com.cloud.network.as.AutoScaleVmGroupPolicyMapVO;
-import com.cloud.network.as.AutoScaleVmGroupVO;
-import com.cloud.network.as.AutoScaleVmProfileVO;
-import com.cloud.network.as.ConditionVO;
-import com.cloud.network.as.CounterVO;
-import com.cloud.network.as.dao.AutoScalePolicyConditionMapDao;
-import com.cloud.network.as.dao.AutoScalePolicyDao;
-import com.cloud.network.as.dao.AutoScaleVmGroupDao;
-import com.cloud.network.as.dao.AutoScaleVmGroupPolicyMapDao;
-import com.cloud.network.as.dao.AutoScaleVmProfileDao;
-import com.cloud.network.as.dao.ConditionDao;
-import com.cloud.network.as.dao.CounterDao;
-import com.cloud.network.dao.FirewallRulesCidrsDao;
-import com.cloud.network.dao.FirewallRulesDao;
-import com.cloud.network.dao.IPAddressDao;
-import com.cloud.network.dao.LoadBalancerDao;
-import com.cloud.network.dao.NetworkDao;
-import com.cloud.network.dao.PhysicalNetworkDao;
-import com.cloud.network.dao.NetworkDomainDao;
-import com.cloud.network.dao.NetworkRuleConfigDao;
-import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
-import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
-import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
-import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
-import com.cloud.network.dao.Site2SiteVpnGatewayDao;
-import com.cloud.network.dao.Site2SiteCustomerGatewayDao;
+import com.cloud.network.as.*;
+import com.cloud.network.as.dao.*;
+import com.cloud.network.dao.*;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.security.SecurityGroup;
import com.cloud.network.security.SecurityGroupManager;
import com.cloud.network.security.SecurityGroupVO;
import com.cloud.network.security.dao.SecurityGroupDao;
-import com.cloud.network.vpc.StaticRouteVO;
-import com.cloud.network.vpc.VpcGatewayVO;
-import com.cloud.network.vpc.VpcManager;
-import com.cloud.network.vpc.VpcOffering;
-import com.cloud.network.vpc.VpcVO;
+import com.cloud.network.vpc.*;
import com.cloud.network.vpc.dao.StaticRouteDao;
+import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpc.dao.VpcGatewayDao;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import com.cloud.offering.DiskOffering;
@@ -183,57 +71,16 @@
import com.cloud.projects.ProjectInvitation;
import com.cloud.projects.ProjectService;
import com.cloud.resource.ResourceManager;
-import com.cloud.server.Criteria;
-import com.cloud.server.ManagementServer;
-import com.cloud.server.ResourceTag;
+import com.cloud.server.*;
import com.cloud.server.ResourceTag.TaggedResourceType;
-import com.cloud.server.StatsCollector;
-import com.cloud.server.TaggedResourceService;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
-import com.cloud.storage.DiskOfferingVO;
-import com.cloud.storage.GuestOS;
-import com.cloud.storage.GuestOSCategoryVO;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.*;
import com.cloud.storage.Storage.ImageFormat;
-import com.cloud.storage.StorageManager;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.StoragePoolVO;
-import com.cloud.storage.StorageStats;
-import com.cloud.storage.UploadVO;
-import com.cloud.storage.VMTemplateHostVO;
-import com.cloud.storage.VMTemplateS3VO;
-import com.cloud.storage.VMTemplateSwiftVO;
-import com.cloud.storage.VMTemplateVO;
-import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type;
-import com.cloud.storage.VolumeHostVO;
-import com.cloud.storage.VolumeVO;
-import com.cloud.storage.dao.DiskOfferingDao;
-import com.cloud.storage.dao.GuestOSCategoryDao;
-import com.cloud.storage.dao.GuestOSDao;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.dao.SnapshotPolicyDao;
-import com.cloud.storage.dao.StoragePoolDao;
-import com.cloud.storage.dao.UploadDao;
-import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.dao.VMTemplateDetailsDao;
-import com.cloud.storage.dao.VMTemplateHostDao;
-import com.cloud.storage.dao.VMTemplateS3Dao;
-import com.cloud.storage.dao.VMTemplateSwiftDao;
-import com.cloud.storage.dao.VolumeDao;
-import com.cloud.storage.dao.VolumeHostDao;
+import com.cloud.storage.dao.*;
import com.cloud.storage.snapshot.SnapshotPolicy;
-import com.cloud.user.Account;
-import com.cloud.user.AccountDetailsDao;
-import com.cloud.user.AccountVO;
-import com.cloud.user.ResourceLimitService;
-import com.cloud.user.SSHKeyPairVO;
-import com.cloud.user.User;
-import com.cloud.user.UserAccount;
-import com.cloud.user.UserStatisticsVO;
-import com.cloud.user.UserVO;
+import com.cloud.user.*;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.SSHKeyPairDao;
import com.cloud.user.dao.UserDao;
@@ -242,23 +89,13 @@
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentLocator;
-import com.cloud.vm.ConsoleProxyVO;
-import com.cloud.vm.DomainRouterVO;
-import com.cloud.vm.InstanceGroup;
-import com.cloud.vm.InstanceGroupVO;
-import com.cloud.vm.NicProfile;
-import com.cloud.vm.UserVmDetailVO;
-import com.cloud.vm.UserVmManager;
-import com.cloud.vm.UserVmVO;
-import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VmStats;
-import com.cloud.vm.dao.ConsoleProxyDao;
-import com.cloud.vm.dao.DomainRouterDao;
-import com.cloud.vm.dao.UserVmDao;
-import com.cloud.vm.dao.UserVmDetailsDao;
-import com.cloud.vm.dao.VMInstanceDao;
-import com.cloud.network.vpc.dao.VpcDao;
+import com.cloud.vm.*;
+import com.cloud.vm.dao.*;
+import org.apache.cloudstack.api.ApiConstants.HostDetails;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.api.response.*;
+
+import java.util.*;
public class ApiDBUtils {
private static ManagementServer _ms;
@@ -699,7 +536,7 @@
public static Snapshot findSnapshotById(long snapshotId) {
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
- if (snapshot != null && snapshot.getRemoved() == null && snapshot.getStatus() == Snapshot.Status.BackedUp) {
+ if (snapshot != null && snapshot.getRemoved() == null && snapshot.getState() == Snapshot.State.BackedUp) {
return snapshot;
} else {
return null;
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 641f25b..54639a8 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -16,125 +16,9 @@
// under the License.
package com.cloud.api;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.ResponseGenerator;
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.acl.ControlledEntity;
-import org.apache.cloudstack.acl.ControlledEntity.ACLType;
-import org.apache.cloudstack.api.ApiConstants.HostDetails;
-import org.apache.cloudstack.api.ApiConstants.VMDetails;
-import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
-import org.apache.cloudstack.api.response.AccountResponse;
-
import com.cloud.api.query.ViewResponseHelper;
-import com.cloud.api.query.vo.AccountJoinVO;
-import com.cloud.api.query.vo.AsyncJobJoinVO;
-import com.cloud.api.query.vo.ControlledViewEntity;
-import com.cloud.api.query.vo.DataCenterJoinVO;
-import com.cloud.api.query.vo.DiskOfferingJoinVO;
-import com.cloud.api.query.vo.DomainRouterJoinVO;
-import com.cloud.api.query.vo.EventJoinVO;
-import com.cloud.api.query.vo.HostJoinVO;
-import com.cloud.api.query.vo.InstanceGroupJoinVO;
-import com.cloud.api.query.vo.ProjectAccountJoinVO;
-import com.cloud.api.query.vo.ProjectInvitationJoinVO;
-import com.cloud.api.query.vo.ProjectJoinVO;
-import com.cloud.api.query.vo.ResourceTagJoinVO;
-import com.cloud.api.query.vo.SecurityGroupJoinVO;
-import com.cloud.api.query.vo.ServiceOfferingJoinVO;
-import com.cloud.api.query.vo.StoragePoolJoinVO;
-import com.cloud.api.query.vo.UserAccountJoinVO;
-import com.cloud.api.query.vo.UserVmJoinVO;
-import com.cloud.api.query.vo.VolumeJoinVO;
+import com.cloud.api.query.vo.*;
import com.cloud.api.response.ApiResponseSerializer;
-import org.apache.cloudstack.api.response.AsyncJobResponse;
-import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
-import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
-import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse;
-import org.apache.cloudstack.api.response.CapabilityResponse;
-import org.apache.cloudstack.api.response.CapacityResponse;
-import org.apache.cloudstack.api.response.ClusterResponse;
-import org.apache.cloudstack.api.response.ConditionResponse;
-import org.apache.cloudstack.api.response.ConfigurationResponse;
-import org.apache.cloudstack.api.response.ControlledEntityResponse;
-import org.apache.cloudstack.api.response.CounterResponse;
-import org.apache.cloudstack.api.response.CreateCmdResponse;
-import org.apache.cloudstack.api.response.DiskOfferingResponse;
-import org.apache.cloudstack.api.response.DomainResponse;
-import org.apache.cloudstack.api.response.DomainRouterResponse;
-import org.apache.cloudstack.api.response.EventResponse;
-import org.apache.cloudstack.api.response.ExtractResponse;
-import org.apache.cloudstack.api.response.FirewallResponse;
-import org.apache.cloudstack.api.response.FirewallRuleResponse;
-import org.apache.cloudstack.api.response.GuestOSResponse;
-import org.apache.cloudstack.api.response.HostResponse;
-import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse;
-import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
-import org.apache.cloudstack.api.response.IPAddressResponse;
-import org.apache.cloudstack.api.response.InstanceGroupResponse;
-import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
-import org.apache.cloudstack.api.response.LBStickinessPolicyResponse;
-import org.apache.cloudstack.api.response.LBStickinessResponse;
-import org.apache.cloudstack.api.response.LDAPConfigResponse;
-import org.apache.cloudstack.api.response.LoadBalancerResponse;
-import org.apache.cloudstack.api.response.NetworkACLResponse;
-import org.apache.cloudstack.api.response.NetworkOfferingResponse;
-import org.apache.cloudstack.api.response.NetworkResponse;
-import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
-import org.apache.cloudstack.api.response.PodResponse;
-import org.apache.cloudstack.api.response.PrivateGatewayResponse;
-import org.apache.cloudstack.api.response.ProjectAccountResponse;
-import org.apache.cloudstack.api.response.ProjectInvitationResponse;
-import org.apache.cloudstack.api.response.ProjectResponse;
-import org.apache.cloudstack.api.response.ProviderResponse;
-import org.apache.cloudstack.api.response.RemoteAccessVpnResponse;
-import org.apache.cloudstack.api.response.ResourceCountResponse;
-import org.apache.cloudstack.api.response.ResourceLimitResponse;
-import org.apache.cloudstack.api.response.ResourceTagResponse;
-import org.apache.cloudstack.api.response.SecurityGroupResponse;
-import org.apache.cloudstack.api.response.SecurityGroupRuleResponse;
-import org.apache.cloudstack.api.response.ServiceOfferingResponse;
-import org.apache.cloudstack.api.response.ServiceResponse;
-import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse;
-import org.apache.cloudstack.api.response.Site2SiteVpnConnectionResponse;
-import org.apache.cloudstack.api.response.Site2SiteVpnGatewayResponse;
-import org.apache.cloudstack.api.response.SnapshotPolicyResponse;
-import org.apache.cloudstack.api.response.SnapshotResponse;
-import org.apache.cloudstack.api.response.SnapshotScheduleResponse;
-import org.apache.cloudstack.api.response.StaticRouteResponse;
-import org.apache.cloudstack.api.response.StorageNetworkIpRangeResponse;
-import org.apache.cloudstack.api.response.StoragePoolResponse;
-import org.apache.cloudstack.api.response.SwiftResponse;
-import org.apache.cloudstack.api.response.SystemVmInstanceResponse;
-import org.apache.cloudstack.api.response.SystemVmResponse;
-import org.apache.cloudstack.api.response.TemplatePermissionsResponse;
-import org.apache.cloudstack.api.response.TemplateResponse;
-import org.apache.cloudstack.api.response.TrafficTypeResponse;
-import org.apache.cloudstack.api.response.UserResponse;
-import org.apache.cloudstack.api.response.UserVmResponse;
-import org.apache.cloudstack.api.response.VirtualRouterProviderResponse;
-import org.apache.cloudstack.api.response.VlanIpRangeResponse;
-import org.apache.cloudstack.api.response.VolumeResponse;
-import org.apache.cloudstack.api.response.VpcOfferingResponse;
-import org.apache.cloudstack.api.response.VpcResponse;
-import org.apache.cloudstack.api.response.VpnUsersResponse;
-import org.apache.cloudstack.api.response.ZoneResponse;
-
-import org.apache.cloudstack.api.response.S3Response;
import com.cloud.async.AsyncJob;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityVO;
@@ -143,53 +27,21 @@
import com.cloud.configuration.Resource.ResourceOwnerType;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceLimit;
-import com.cloud.dc.ClusterVO;
-import com.cloud.dc.DataCenter;
-import com.cloud.dc.DataCenterVO;
-import com.cloud.dc.HostPodVO;
-import com.cloud.dc.Pod;
-import com.cloud.dc.StorageNetworkIpRange;
-import com.cloud.dc.Vlan;
+import com.cloud.dc.*;
import com.cloud.dc.Vlan.VlanType;
-import com.cloud.dc.VlanVO;
import com.cloud.domain.Domain;
import com.cloud.event.Event;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.HypervisorCapabilities;
-import com.cloud.network.IPAddressVO;
-import com.cloud.network.IpAddress;
-import com.cloud.network.Network;
+import com.cloud.network.*;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
-import com.cloud.network.NetworkProfile;
-import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType;
-import com.cloud.network.PhysicalNetwork;
-import com.cloud.network.PhysicalNetworkServiceProvider;
-import com.cloud.network.PhysicalNetworkTrafficType;
-import com.cloud.network.PhysicalNetworkVO;
-import com.cloud.network.RemoteAccessVpn;
-import com.cloud.network.Site2SiteCustomerGateway;
-import com.cloud.network.Site2SiteVpnConnection;
-import com.cloud.network.Site2SiteVpnGateway;
-import com.cloud.network.VirtualRouterProvider;
-import com.cloud.network.VpnUser;
-import com.cloud.network.as.AutoScalePolicy;
-import com.cloud.network.as.AutoScaleVmGroup;
-import com.cloud.network.as.AutoScaleVmProfile;
-import com.cloud.network.as.AutoScaleVmProfileVO;
-import com.cloud.network.as.Condition;
-import com.cloud.network.as.ConditionVO;
-import com.cloud.network.as.Counter;
+import com.cloud.network.as.*;
import com.cloud.network.router.VirtualRouter;
-import com.cloud.network.rules.FirewallRule;
-import com.cloud.network.rules.FirewallRuleVO;
-import com.cloud.network.rules.LoadBalancer;
-import com.cloud.network.rules.PortForwardingRule;
-import com.cloud.network.rules.StaticNatRule;
-import com.cloud.network.rules.StickinessPolicy;
+import com.cloud.network.rules.*;
import com.cloud.network.security.SecurityGroup;
import com.cloud.network.security.SecurityRule;
import com.cloud.network.security.SecurityRule.SecurityRuleType;
@@ -207,25 +59,11 @@
import com.cloud.server.Criteria;
import com.cloud.server.ResourceTag;
import com.cloud.server.ResourceTag.TaggedResourceType;
-import com.cloud.storage.GuestOS;
-import com.cloud.storage.GuestOSCategoryVO;
-import com.cloud.storage.S3;
-import com.cloud.storage.Snapshot;
+import com.cloud.storage.*;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.TemplateType;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.StoragePoolVO;
-import com.cloud.storage.StorageStats;
-import com.cloud.storage.Swift;
-import com.cloud.storage.UploadVO;
-import com.cloud.storage.VMTemplateHostVO;
-import com.cloud.storage.VMTemplateS3VO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
-import com.cloud.storage.VMTemplateSwiftVO;
-import com.cloud.storage.VMTemplateVO;
-import com.cloud.storage.Volume;
-import com.cloud.storage.VolumeVO;
import com.cloud.storage.snapshot.SnapshotPolicy;
import com.cloud.storage.snapshot.SnapshotSchedule;
import com.cloud.template.VirtualMachineTemplate;
@@ -242,6 +80,21 @@
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.api.ApiConstants.HostDetails;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ResponseGenerator;
+import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
+import org.apache.cloudstack.api.response.*;
+import org.apache.log4j.Logger;
+
+import java.text.DecimalFormat;
+import java.util.*;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
public class ApiResponseHelper implements ResponseGenerator {
@@ -378,7 +231,7 @@
snapshotResponse.setCreated(snapshot.getCreated());
snapshotResponse.setName(snapshot.getName());
snapshotResponse.setIntervalType(ApiDBUtils.getSnapshotIntervalTypes(snapshot.getId()));
- snapshotResponse.setState(snapshot.getStatus());
+ snapshotResponse.setState(snapshot.getState());
//set tag information
List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Snapshot, snapshot.getId());
diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
index ed27200..b4612ae 100755
--- a/server/src/com/cloud/api/ApiServer.java
+++ b/server/src/com/cloud/api/ApiServer.java
@@ -50,10 +50,10 @@
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import com.cloud.event.ActionEventUtils;
import com.cloud.utils.ReflectUtil;
import org.apache.cloudstack.acl.APILimitChecker;
import org.apache.cloudstack.acl.APIChecker;
-import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.*;
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
@@ -116,7 +116,6 @@
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
-import com.cloud.event.EventUtils;
import com.cloud.exception.AccountLimitException;
import com.cloud.exception.CloudAuthenticationException;
import com.cloud.exception.InsufficientCapacityException;
@@ -467,7 +466,7 @@
asyncCmd.setStartEventId(startEventId);
// save the scheduled event
- Long eventId = EventUtils.saveScheduledEvent((callerUserId == null) ? User.UID_SYSTEM : callerUserId,
+ Long eventId = ActionEventUtils.onScheduledActionEvent((callerUserId == null) ? User.UID_SYSTEM : callerUserId,
asyncCmd.getEntityOwnerId(), asyncCmd.getEventType(), asyncCmd.getEventDescription(),
startEventId);
if (startEventId == 0) {
diff --git a/server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java b/server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java
index 25298a9..74200e2 100755
--- a/server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java
+++ b/server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java
@@ -16,20 +16,10 @@
// under the License.
package com.cloud.baremetal;
-import java.util.Date;
-import java.util.List;
-
-import javax.ejb.Local;
-
-import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
-import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
-import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
-import org.apache.log4j.Logger;
-
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenterVO;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
@@ -46,6 +36,14 @@
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
+import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
+import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import java.util.Date;
+import java.util.List;
@Local(value=TemplateAdapter.class)
public class BareMetalTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter {
@@ -82,9 +80,9 @@
private void templateCreateUsage(VMTemplateVO template, HostVO host) {
if (template.getAccountId() != Account.ACCOUNT_ID_SYSTEM) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), host.getDataCenterId(),
- template.getId(), template.getName(), null, template.getSourceTemplateId(), 0L);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), host.getDataCenterId(),
+ template.getId(), template.getName(), null, template.getSourceTemplateId(), 0L,
+ template.getClass().getName(), template.getUuid());
}
}
@@ -172,8 +170,8 @@
_tmpltZoneDao.remove(templateZone.getId());
}
- UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), pxeServer.getDataCenterId(), templateId, null);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(eventType, account.getId(), pxeServer.getDataCenterId(),
+ templateId, null, template.getClass().getName(), template.getUuid());
} finally {
if (lock != null) {
_tmpltHostDao.releaseFromLockTable(lock.getId());
diff --git a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java
index 57cfb39..6ff37ea 100755
--- a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java
+++ b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java
@@ -16,28 +16,11 @@
// under the License.
package com.cloud.baremetal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executors;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
-import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
-import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
-import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
-import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
-import org.apache.log4j.Logger;
-
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmiBootorResetCommand;
import com.cloud.agent.manager.Commands;
-import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
import com.cloud.baremetal.PxeServerManager.PxeServerType;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
@@ -47,14 +30,8 @@
import com.cloud.deploy.DeployDestination;
import com.cloud.domain.DomainVO;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.StorageUnavailableException;
+import com.cloud.event.UsageEventUtils;
+import com.cloud.exception.*;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -71,11 +48,7 @@
import com.cloud.template.TemplateAdapter;
import com.cloud.template.TemplateAdapter.TemplateAdapterType;
import com.cloud.template.TemplateProfile;
-import com.cloud.user.Account;
-import com.cloud.user.AccountVO;
-import com.cloud.user.SSHKeyPair;
-import com.cloud.user.User;
-import com.cloud.user.UserContext;
+import com.cloud.user.*;
import com.cloud.uservm.UserVm;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@@ -88,19 +61,26 @@
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.StateListener;
import com.cloud.utils.net.NetUtils;
-import com.cloud.vm.BareMetalVmService;
-import com.cloud.vm.NicProfile;
-import com.cloud.vm.NicVO;
-import com.cloud.vm.ReservationContext;
-import com.cloud.vm.UserVmManagerImpl;
-import com.cloud.vm.UserVmVO;
-import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.*;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachine.Type;
-import com.cloud.vm.VirtualMachineName;
-import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfile.Param;
+import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
+import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
+import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
+import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
+import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
+import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
@Local(value={BareMetalVmManager.class, BareMetalVmService.class})
public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMetalVmManager, BareMetalVmService, Manager,
@@ -367,8 +347,9 @@
s_logger.debug("Successfully allocated DB entry for " + vm);
}
UserContext.current().setEventDetails("Vm Id: " + vm.getId());
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_CREATE, accountId, cmd.getZoneId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), HypervisorType.BareMetal.toString());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, cmd.getZoneId(), vm.getId(),
+ vm.getHostName(), offering.getId(), template.getId(), HypervisorType.BareMetal.toString(),
+ VirtualMachine.class.getName(), vm.getUuid());
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm);
diff --git a/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java b/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java
index ced2618..13a22db 100644
--- a/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java
+++ b/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java
@@ -16,18 +16,18 @@
// under the License.
package com.cloud.configuration;
-import java.util.List;
-
-import com.cloud.event.ActionEventCallback;
+import com.cloud.event.ActionEventUtils;
import com.cloud.utils.component.AnnotationInterceptor;
import com.cloud.utils.component.InterceptorLibrary;
import com.cloud.utils.db.DatabaseCallback;
+import java.util.List;
+
public class DefaultInterceptorLibrary implements InterceptorLibrary {
@Override
public void addInterceptors(List<AnnotationInterceptor<?>> interceptors) {
interceptors.add(new DatabaseCallback());
- interceptors.add(new ActionEventCallback());
+ interceptors.add(new ActionEventUtils.ActionEventCallback());
}
}
diff --git a/server/src/com/cloud/event/ActionEventCallback.java b/server/src/com/cloud/event/ActionEventCallback.java
deleted file mode 100644
index f941400..0000000
--- a/server/src/com/cloud/event/ActionEventCallback.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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 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.user.UserContext;
-import com.cloud.utils.component.AnnotationInterceptor;
-
-public class ActionEventCallback implements MethodInterceptor, AnnotationInterceptor<EventVO> {
-
- @Override
- public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- EventVO 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;
- ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
- if (actionEvent != null) {
- return true;
- }
-
- return false;
- }
-
- @Override
- public EventVO interceptStart(AnnotatedElement element) {
- EventVO event = null;
- Method method = (Method)element;
- ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
- if (actionEvent != null) {
- boolean async = actionEvent.async();
- if(async){
- UserContext ctx = UserContext.current();
- long userId = ctx.getCallerUserId();
- long accountId = ctx.getAccountId();
- long startEventId = ctx.getStartEventId();
- String eventDescription = actionEvent.eventDescription();
- if(ctx.getEventDetails() != null){
- eventDescription += ". "+ctx.getEventDetails();
- }
- EventUtils.saveStartedEvent(userId, accountId, actionEvent.eventType(), eventDescription, startEventId);
- }
- }
- return event;
- }
-
- @Override
- public void interceptComplete(AnnotatedElement element, EventVO event) {
- Method method = (Method)element;
- ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
- if (actionEvent != null) {
- UserContext ctx = UserContext.current();
- long userId = ctx.getCallerUserId();
- long accountId = ctx.getAccountId();
- long startEventId = ctx.getStartEventId();
- String eventDescription = actionEvent.eventDescription();
- if(ctx.getEventDetails() != null){
- eventDescription += ". "+ctx.getEventDetails();
- }
- if(actionEvent.create()){
- //This start event has to be used for subsequent events of this action
- startEventId = EventUtils.saveCreatedEvent(userId, accountId, EventVO.LEVEL_INFO, actionEvent.eventType(), "Successfully created entity for "+eventDescription);
- ctx.setStartEventId(startEventId);
- } else {
- EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, actionEvent.eventType(), "Successfully completed "+eventDescription, startEventId);
- }
- }
- }
-
- @Override
- public void interceptException(AnnotatedElement element, EventVO event) {
- Method method = (Method)element;
- ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
- if (actionEvent != null) {
- UserContext ctx = UserContext.current();
- long userId = ctx.getCallerUserId();
- long accountId = ctx.getAccountId();
- long startEventId = ctx.getStartEventId();
- String eventDescription = actionEvent.eventDescription();
- if(ctx.getEventDetails() != null){
- eventDescription += ". "+ctx.getEventDetails();
- }
- if(actionEvent.create()){
- long eventId = EventUtils.saveCreatedEvent(userId, accountId, EventVO.LEVEL_ERROR, actionEvent.eventType(), "Error while creating entity for "+eventDescription);
- ctx.setStartEventId(eventId);
- } else {
- EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, actionEvent.eventType(), "Error while "+eventDescription, startEventId);
- }
- }
- }
-
- @Override
- public Callback getCallback() {
- return this;
- }
-
-}
diff --git a/server/src/com/cloud/event/ActionEventUtils.java b/server/src/com/cloud/event/ActionEventUtils.java
new file mode 100755
index 0000000..744f46f
--- /dev/null
+++ b/server/src/com/cloud/event/ActionEventUtils.java
@@ -0,0 +1,288 @@
+// 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 com.cloud.event;
+
+import com.cloud.event.dao.EventDao;
+import com.cloud.server.ManagementServer;
+import com.cloud.user.Account;
+import com.cloud.user.AccountVO;
+import com.cloud.user.User;
+import com.cloud.user.UserContext;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.component.Adapters;
+import com.cloud.utils.component.AnnotationInterceptor;
+import com.cloud.utils.component.ComponentLocator;
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+import org.apache.cloudstack.framework.events.EventBus;
+import org.apache.cloudstack.framework.events.EventBusException;
+import org.apache.log4j.Logger;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ActionEventUtils {
+
+ private static EventDao _eventDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(EventDao.class);
+ private static AccountDao _accountDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(AccountDao.class);
+ protected static UserDao _userDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(UserDao.class);
+ private static final Logger s_logger = Logger.getLogger(ActionEventUtils.class);
+
+ // get the event bus provider if configured
+ protected static EventBus _eventBus = null;
+
+ static {
+ Adapters<EventBus> eventBusImpls = ComponentLocator.getLocator(ManagementServer.Name).getAdapters(EventBus.class);
+ if (eventBusImpls != null) {
+ Enumeration<EventBus> eventBusenum = eventBusImpls.enumeration();
+ if (eventBusenum != null && eventBusenum.hasMoreElements()) {
+ _eventBus = eventBusenum.nextElement(); // configure event bus if configured
+ }
+ }
+ }
+
+ public static Long onActionEvent(Long userId, Long accountId, Long domainId, String type, String description) {
+
+ publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(),
+ type, com.cloud.event.Event.State.Completed);
+
+ Event event = persistActionEvent(userId, accountId, domainId, null, type, Event.State.Completed,
+ description, null);
+
+ return event.getId();
+ }
+
+ /*
+ * Save event after scheduling an async job
+ */
+ public static Long onScheduledActionEvent(Long userId, Long accountId, String type, String description,
+ long startEventId) {
+
+ publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type,
+ com.cloud.event.Event.State.Scheduled);
+
+ Event event = persistActionEvent(userId, accountId, null, null, type, Event.State.Scheduled,
+ description, startEventId);
+
+ return event.getId();
+ }
+
+ /*
+ * Save event after starting execution of an async job
+ */
+ public static Long onStartedActionEvent(Long userId, Long accountId, String type, String description,
+ long startEventId) {
+
+ publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type,
+ com.cloud.event.Event.State.Started);
+
+ Event event = persistActionEvent(userId, accountId, null, null, type, Event.State.Started,
+ description, startEventId);
+ return event.getId();
+ }
+
+ public static Long onCompletedActionEvent(Long userId, Long accountId, String level, String type,
+ String description, long startEventId) {
+
+ publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type,
+ com.cloud.event.Event.State.Completed);
+
+ Event event = persistActionEvent(userId, accountId, null, level, type, Event.State.Completed,
+ description, startEventId);
+
+ return event.getId();
+ }
+
+ public static Long onCreatedActionEvent(Long userId, Long accountId, String level, String type, String description) {
+
+ publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type,
+ com.cloud.event.Event.State.Created);
+
+ Event event = persistActionEvent(userId, accountId, null, level, type, Event.State.Created, description, null);
+
+ return event.getId();
+ }
+
+ private static Event persistActionEvent(Long userId, Long accountId, Long domainId, String level, String type,
+ Event.State state, String description, Long startEventId) {
+ EventVO event = new EventVO();
+ event.setUserId(userId);
+ event.setAccountId(accountId);
+ event.setType(type);
+ event.setState(state);
+ event.setDescription(description);
+ if (domainId != null) {
+ event.setDomainId(domainId);
+ } else {
+ event.setDomainId(getDomainId(accountId));
+ }
+ if (level != null && !level.isEmpty()) {
+ event.setLevel(level);
+ }
+ if (startEventId != null) {
+ event.setStartId(startEventId);
+ }
+ event = _eventDao.persist(event);
+ return event;
+ }
+
+ private static void publishOnEventBus(long userId, long accountId, String eventCategory,
+ String eventType, Event.State state) {
+ if (_eventBus == null) {
+ return; // no provider is configured to provide events bus, so just return
+ }
+
+ org.apache.cloudstack.framework.events.Event event = new org.apache.cloudstack.framework.events.Event(
+ ManagementServer.Name,
+ eventCategory,
+ eventType,
+ EventTypes.getEntityForEvent(eventType), null);
+
+ Map<String, String> eventDescription = new HashMap<String, String>();
+ Account account = _accountDao.findById(accountId);
+ User user = _userDao.findById(userId);
+ eventDescription.put("user", user.getUuid());
+ eventDescription.put("account", account.getUuid());
+ eventDescription.put("event", eventType);
+ eventDescription.put("status", state.toString());
+ event.setDescription(eventDescription);
+
+ try {
+ _eventBus.publish(event);
+ } catch (EventBusException e) {
+ s_logger.warn("Failed to publish action event on the the event bus.");
+ }
+ }
+
+ private static long getDomainId(long accountId){
+ AccountVO account = _accountDao.findByIdIncludingRemoved(accountId);
+ return account.getDomainId();
+ }
+
+ public static class ActionEventCallback implements MethodInterceptor, AnnotationInterceptor<EventVO> {
+
+ @Override
+ public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
+ EventVO 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;
+ ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
+ if (actionEvent != null) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public EventVO interceptStart(AnnotatedElement element) {
+ EventVO event = null;
+ Method method = (Method)element;
+ ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
+ if (actionEvent != null) {
+ boolean async = actionEvent.async();
+ if(async){
+ UserContext ctx = UserContext.current();
+ long userId = ctx.getCallerUserId();
+ long accountId = ctx.getAccountId();
+ long startEventId = ctx.getStartEventId();
+ String eventDescription = actionEvent.eventDescription();
+ if(ctx.getEventDetails() != null){
+ eventDescription += ". "+ctx.getEventDetails();
+ }
+ ActionEventUtils.onStartedActionEvent(userId, accountId, actionEvent.eventType(), eventDescription, startEventId);
+ }
+ }
+ return event;
+ }
+
+ @Override
+ public void interceptComplete(AnnotatedElement element, EventVO event) {
+ Method method = (Method)element;
+ ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
+ if (actionEvent != null) {
+ UserContext ctx = UserContext.current();
+ long userId = ctx.getCallerUserId();
+ long accountId = ctx.getAccountId();
+ long startEventId = ctx.getStartEventId();
+ String eventDescription = actionEvent.eventDescription();
+ if(ctx.getEventDetails() != null){
+ eventDescription += ". "+ctx.getEventDetails();
+ }
+ if(actionEvent.create()){
+ //This start event has to be used for subsequent events of this action
+ startEventId = ActionEventUtils.onCreatedActionEvent(userId, accountId, EventVO.LEVEL_INFO, actionEvent.eventType(), "Successfully created entity for " + eventDescription);
+ ctx.setStartEventId(startEventId);
+ } else {
+ ActionEventUtils.onCompletedActionEvent(userId, accountId, EventVO.LEVEL_INFO, actionEvent.eventType(), "Successfully completed " + eventDescription, startEventId);
+ }
+ }
+ }
+
+ @Override
+ public void interceptException(AnnotatedElement element, EventVO event) {
+ Method method = (Method)element;
+ ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
+ if (actionEvent != null) {
+ UserContext ctx = UserContext.current();
+ long userId = ctx.getCallerUserId();
+ long accountId = ctx.getAccountId();
+ long startEventId = ctx.getStartEventId();
+ String eventDescription = actionEvent.eventDescription();
+ if(ctx.getEventDetails() != null){
+ eventDescription += ". "+ctx.getEventDetails();
+ }
+ if(actionEvent.create()){
+ long eventId = ActionEventUtils.onCreatedActionEvent(userId, accountId, EventVO.LEVEL_ERROR, actionEvent.eventType(), "Error while creating entity for " + eventDescription);
+ ctx.setStartEventId(eventId);
+ } else {
+ ActionEventUtils.onCompletedActionEvent(userId, accountId, EventVO.LEVEL_ERROR, actionEvent.eventType(), "Error while " + eventDescription, startEventId);
+ }
+ }
+ }
+
+ @Override
+ public Callback getCallback() {
+ return this;
+ }
+ }
+}
diff --git a/server/src/com/cloud/event/AlertGenerator.java b/server/src/com/cloud/event/AlertGenerator.java
new file mode 100644
index 0000000..4286377
--- /dev/null
+++ b/server/src/com/cloud/event/AlertGenerator.java
@@ -0,0 +1,87 @@
+// 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 com.cloud.event;
+
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.HostPodDao;
+import com.cloud.server.ManagementServer;
+import com.cloud.utils.component.Adapters;
+import com.cloud.utils.component.ComponentLocator;
+import org.apache.cloudstack.framework.events.*;
+import org.apache.log4j.Logger;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AlertGenerator {
+
+ private static final Logger s_logger = Logger.getLogger(AlertGenerator.class);
+ private static DataCenterDao _dcDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(DataCenterDao.class);
+ private static HostPodDao _podDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(HostPodDao.class);
+
+ // get the event bus provider if configured
+ protected static EventBus _eventBus = null;
+ static {
+ Adapters<EventBus> eventBusImpls = ComponentLocator.getLocator(ManagementServer.Name).getAdapters(EventBus.class);
+ if (eventBusImpls != null) {
+ Enumeration<EventBus> eventBusenum = eventBusImpls.enumeration();
+ if (eventBusenum != null && eventBusenum.hasMoreElements()) {
+ _eventBus = eventBusenum.nextElement(); // configure event bus if configured
+ }
+ }
+ }
+
+ public static void publishAlertOnEventBus(String alertType, long dataCenterId, Long podId, String subject, String body) {
+ if (_eventBus == null) {
+ return; // no provider is configured to provider events bus, so just return
+ }
+
+ org.apache.cloudstack.framework.events.Event event =
+ new org.apache.cloudstack.framework.events.Event(ManagementServer.Name,
+ EventCategory.ALERT_EVENT.getName(),
+ alertType,
+ null,
+ null);
+
+ Map<String, String> eventDescription = new HashMap<String, String>();
+ DataCenterVO dc = _dcDao.findById(dataCenterId);
+ HostPodVO pod = _podDao.findById(podId);
+
+ eventDescription.put("event", alertType);
+ if (dc != null) {
+ eventDescription.put("dataCenterId", dc.getUuid());
+ } else {
+ eventDescription.put("dataCenterId", null);
+ }
+ if (pod != null) {
+ eventDescription.put("podId", pod.getUuid());
+ } else {
+ eventDescription.put("podId", null);
+ }
+ event.setDescription(eventDescription);
+
+ try {
+ _eventBus.publish(event);
+ } catch (EventBusException e) {
+ s_logger.warn("Failed to publish alert on the the event bus.");
+ }
+ }
+}
diff --git a/server/src/com/cloud/event/EventUtils.java b/server/src/com/cloud/event/EventUtils.java
deleted file mode 100755
index 3672ee7..0000000
--- a/server/src/com/cloud/event/EventUtils.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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 com.cloud.event;
-
-import com.cloud.event.dao.EventDao;
-import com.cloud.server.ManagementServer;
-import com.cloud.user.AccountVO;
-import com.cloud.user.dao.AccountDao;
-import com.cloud.utils.component.ComponentLocator;
-
-public class EventUtils {
- private static EventDao _eventDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(EventDao.class);
- private static AccountDao _accountDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(AccountDao.class);
-
- public static Long saveEvent(Long userId, Long accountId, Long domainId, String type, String description) {
- EventVO event = new EventVO();
- event.setUserId(userId);
- event.setAccountId(accountId);
- event.setDomainId(domainId);
- event.setType(type);
- event.setDescription(description);
- event = _eventDao.persist(event);
- return event.getId();
- }
-
- /*
- * Save event after scheduling an async job
- */
- public static Long saveScheduledEvent(Long userId, Long accountId, String type, String description, long startEventId) {
- EventVO event = new EventVO();
- event.setUserId(userId);
- event.setAccountId(accountId);
- event.setDomainId(getDomainId(accountId));
- event.setType(type);
- event.setStartId(startEventId);
- event.setState(Event.State.Scheduled);
- event.setDescription("Scheduled async job for "+description);
- event = _eventDao.persist(event);
- return event.getId();
- }
-
- /*
- * Save event after starting execution of an async job
- */
- public static Long saveStartedEvent(Long userId, Long accountId, String type, String description, long startEventId) {
- EventVO event = new EventVO();
- event.setUserId(userId);
- event.setAccountId(accountId);
- event.setDomainId(getDomainId(accountId));
- event.setType(type);
- event.setState(Event.State.Started);
- event.setDescription("Starting job for "+description);
- event.setStartId(startEventId);
- event = _eventDao.persist(event);
- return event.getId();
- }
-
- public static Long saveEvent(Long userId, Long accountId, String level, String type, String description, long startEventId) {
- EventVO event = new EventVO();
- event.setUserId(userId);
- event.setAccountId(accountId);
- event.setDomainId(getDomainId(accountId));
- event.setType(type);
- event.setDescription(description);
- event.setLevel(level);
- event.setStartId(startEventId);
- event = _eventDao.persist(event);
- return (event != null ? event.getId() : null);
- }
-
- public static Long saveCreatedEvent(Long userId, Long accountId, String level, String type, String description) {
- EventVO event = new EventVO();
- event.setUserId(userId);
- event.setAccountId(accountId);
- event.setDomainId(getDomainId(accountId));
- event.setType(type);
- event.setLevel(level);
- event.setState(Event.State.Created);
- event.setDescription(description);
- event = _eventDao.persist(event);
- return event.getId();
- }
-
- private static long getDomainId(long accountId){
- AccountVO account = _accountDao.findByIdIncludingRemoved(accountId);
- return account.getDomainId();
- }
-}
diff --git a/server/src/com/cloud/event/UsageEventUtils.java b/server/src/com/cloud/event/UsageEventUtils.java
new file mode 100644
index 0000000..904525e
--- /dev/null
+++ b/server/src/com/cloud/event/UsageEventUtils.java
@@ -0,0 +1,119 @@
+package com.cloud.event;
+
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.event.dao.UsageEventDao;
+import com.cloud.server.ManagementServer;
+import com.cloud.user.Account;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.component.Adapters;
+import com.cloud.utils.component.ComponentLocator;
+import org.apache.cloudstack.framework.events.EventBus;
+import org.apache.cloudstack.framework.events.Event;
+import org.apache.cloudstack.framework.events.EventBusException;
+import org.apache.log4j.Logger;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class UsageEventUtils {
+
+ private static UsageEventDao _usageEventDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(UsageEventDao.class);
+ private static AccountDao _accountDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(AccountDao.class);
+ private static DataCenterDao _dcDao = ComponentLocator.getLocator(ManagementServer.Name).getDao(DataCenterDao.class);
+ private static final Logger s_logger = Logger.getLogger(UsageEventUtils.class);
+
+ // get the event bus provider if configured
+ protected static EventBus _eventBus = null;
+ static {
+ Adapters<EventBus> eventBusImpls = ComponentLocator.getLocator(ManagementServer.Name).getAdapters(EventBus.class);
+ if (eventBusImpls != null) {
+ Enumeration<EventBus> eventBusenum = eventBusImpls.enumeration();
+ if (eventBusenum != null && eventBusenum.hasMoreElements()) {
+ _eventBus = eventBusenum.nextElement(); // configure event bus if configured
+ }
+ }
+ }
+
+ public static void publishUsageEvent(String usageType, long accountId, long zoneId,
+ long resourceId, String resourceName,
+ Long offeringId, Long templateId, Long size,
+ String entityType, String entityUUID) {
+ saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size);
+ publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID);
+ }
+
+ public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId,
+ String resourceName, String entityType, String entityUUID) {
+ saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName);
+ publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID);
+ }
+
+ public static void publishUsageEvent(String usageType, long accountId, long zoneId,
+ long ipAddressId, String ipAddress, boolean isSourceNat,
+ String guestType, boolean isSystem, String entityType, String entityUUID) {
+ saveUsageEvent(usageType, accountId, zoneId, ipAddressId, ipAddress, isSourceNat, guestType, isSystem);
+ publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID);
+ }
+
+ public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId,
+ String resourceName, Long offeringId, Long templateId, String resourceType,
+ String entityType, String entityUUID) {
+ saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType);
+ publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID);
+ }
+
+ public static void publishUsageEvent(String usageType, long accountId,long zoneId, long vmId,
+ long securityGroupId, String entityType, String entityUUID) {
+ saveUsageEvent(usageType, accountId, zoneId, vmId, securityGroupId);
+ publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID);
+ }
+
+ public static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, Long size) {
+ _usageEventDao.persist( new UsageEventVO(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size));
+ }
+
+ public static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName) {
+ _usageEventDao.persist( new UsageEventVO(usageType, accountId, zoneId, resourceId, resourceName));
+ }
+
+ public static void saveUsageEvent(String usageType, long accountId, long zoneId, long ipAddressId, String ipAddress, boolean isSourceNat, String guestType, boolean isSystem) {
+ _usageEventDao.persist( new UsageEventVO(usageType, accountId, zoneId, ipAddressId, ipAddress, isSourceNat, guestType, isSystem));
+ }
+
+ public static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, String resourceType) {
+ _usageEventDao.persist( new UsageEventVO(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType));
+ }
+
+ public static void saveUsageEvent(String usageType, long accountId,long zoneId, long vmId, long securityGroupId) {
+ _usageEventDao.persist( new UsageEventVO( usageType, accountId, zoneId, vmId, securityGroupId));
+ }
+
+ private static void publishUsageEvent(String usageEventType, Long accountId, Long zoneId, String resourceType, String resourceUUID) {
+
+ if (_eventBus == null) {
+ return; // no provider is configured to provider events bus, so just return
+ }
+
+ Account account = _accountDao.findById(accountId);
+ DataCenterVO dc = _dcDao.findById(zoneId);
+
+ Event event = new Event(ManagementServer.Name, EventCategory.USAGE_EVENT.getName(), usageEventType,
+ resourceType, resourceUUID);
+
+ Map<String, String> eventDescription = new HashMap<String, String>();
+ eventDescription.put("account", account.getUuid());
+ eventDescription.put("zone", dc.getUuid());
+ eventDescription.put("event", usageEventType);
+ eventDescription.put("resource", resourceType);
+ eventDescription.put("id", resourceUUID);
+ event.setDescription(eventDescription);
+
+ try {
+ _eventBus.publish(event);
+ } catch (EventBusException e) {
+ s_logger.warn("Failed to publish usage event on the the event bus.");
+ }
+ }
+}
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index 0a4851f..3d83487 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -16,39 +16,9 @@
// under the License.
package com.cloud.network;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.acl.ControlledEntity.ACLType;
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
-import org.apache.log4j.Logger;
-
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
-import com.cloud.agent.api.AgentControlAnswer;
-import com.cloud.agent.api.AgentControlCommand;
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.CheckNetworkAnswer;
-import com.cloud.agent.api.CheckNetworkCommand;
-import com.cloud.agent.api.Command;
-import com.cloud.agent.api.StartupCommand;
-import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.agent.api.*;
import com.cloud.agent.api.to.NicTO;
import com.cloud.alert.AlertManager;
import com.cloud.api.ApiDBUtils;
@@ -56,15 +26,9 @@
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.dc.AccountVlanMapVO;
-import com.cloud.dc.DataCenter;
+import com.cloud.dc.*;
import com.cloud.dc.DataCenter.NetworkType;
-import com.cloud.dc.DataCenterVO;
-import com.cloud.dc.Pod;
-import com.cloud.dc.PodVlanMapVO;
-import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
-import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.PodVlanMapDao;
@@ -75,63 +39,30 @@
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.UsageEventDao;
-import com.cloud.exception.AccountLimitException;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.ConnectionException;
-import com.cloud.exception.InsufficientAddressCapacityException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.UnsupportedServiceException;
+import com.cloud.exception.*;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress.State;
-import com.cloud.network.Network.Capability;
-import com.cloud.network.Network.GuestType;
-import com.cloud.network.Network.Provider;
-import com.cloud.network.Network.Service;
+import com.cloud.network.Network.*;
import com.cloud.network.Networks.AddressFormat;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.IsolationType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.addr.PublicIp;
-import com.cloud.network.dao.FirewallRulesDao;
-import com.cloud.network.dao.IPAddressDao;
-import com.cloud.network.dao.LoadBalancerDao;
-import com.cloud.network.dao.NetworkDao;
-import com.cloud.network.dao.NetworkServiceMapDao;
-import com.cloud.network.dao.PhysicalNetworkDao;
-import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
-import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
-import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
-import com.cloud.network.element.DhcpServiceProvider;
-import com.cloud.network.element.IpDeployer;
-import com.cloud.network.element.LoadBalancingServiceProvider;
-import com.cloud.network.element.NetworkElement;
-import com.cloud.network.element.StaticNatServiceProvider;
-import com.cloud.network.element.UserDataServiceProvider;
+import com.cloud.network.dao.*;
+import com.cloud.network.element.*;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy;
import com.cloud.network.lb.LoadBalancingRulesManager;
-import com.cloud.network.rules.FirewallManager;
-import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.*;
import com.cloud.network.rules.FirewallRule.Purpose;
-import com.cloud.network.rules.FirewallRuleVO;
-import com.cloud.network.rules.PortForwardingRuleVO;
-import com.cloud.network.rules.RulesManager;
-import com.cloud.network.rules.StaticNat;
-import com.cloud.network.rules.StaticNatRule;
-import com.cloud.network.rules.StaticNatRuleImpl;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.network.vpc.NetworkACLManager;
import com.cloud.network.vpc.VpcManager;
@@ -144,11 +75,7 @@
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.org.Grouping;
-import com.cloud.user.Account;
-import com.cloud.user.AccountManager;
-import com.cloud.user.ResourceLimitService;
-import com.cloud.user.User;
-import com.cloud.user.UserContext;
+import com.cloud.user.*;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@@ -156,30 +83,30 @@
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
import com.cloud.utils.concurrency.NamedThreadFactory;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.*;
import com.cloud.utils.db.JoinBuilder.JoinType;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
-import com.cloud.vm.Nic;
-import com.cloud.vm.NicProfile;
-import com.cloud.vm.NicVO;
-import com.cloud.vm.ReservationContext;
-import com.cloud.vm.ReservationContextImpl;
-import com.cloud.vm.UserVmVO;
-import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.*;
import com.cloud.vm.VirtualMachine.Type;
-import com.cloud.vm.VirtualMachineProfile;
-import com.cloud.vm.VirtualMachineProfileImpl;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.acl.SecurityChecker.AccessType;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.net.URI;
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
/**
* NetworkManagerImpl implements NetworkManager.
@@ -222,8 +149,6 @@
@Inject
LoadBalancingRulesManager _lbMgr;
@Inject
- UsageEventDao _usageEventDao;
- @Inject
RemoteAccessVpnService _vpnMgr;
@Inject
PodVlanMapDao _podVlanMapDao;
@@ -272,8 +197,14 @@
@Inject
NetworkACLManager _networkACLMgr;
@Inject
+ UsageEventDao _usageEventDao;
+ @Inject
NetworkModel _networkModel;
+ protected StateMachine2<Network.State, Network.Event, Network> _stateMachine;
+ private final HashMap<String, NetworkOfferingVO> _systemNetworks = new HashMap<String, NetworkOfferingVO>(5);
+ private static Long _privateOfferingId = null;
+
ScheduledExecutorService _executor;
SearchBuilder<IPAddressVO> AssignIpAddressSearch;
@@ -405,11 +336,9 @@
VlanVO vlan = _vlanDao.findById(addr.getVlanId());
String guestType = vlan.getVlanType().toString();
-
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(),
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(),
addr.getDataCenterId(), addr.getId(), addr.getAddress().toString(), addr.isSourceNat(), guestType,
- addr.getSystem());
- _usageEventDao.persist(usageEvent);
+ addr.getSystem(), addr.getClass().getName(), addr.getUuid());
// don't increment resource count for direct ip addresses
if (addr.getAssociatedWithNetworkId() != null) {
_resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.public_ip);
@@ -1046,6 +975,8 @@
_agentMgr.registerForHostEvents(this, true, false, true);
+ Network.State.getStateMachine().registerListener(new NetworkStateListener(_usageEventDao, _networksDao));
+
s_logger.info("Network Manager is configured.");
return true;
@@ -1069,6 +1000,7 @@
}
protected NetworkManagerImpl() {
+ setStateMachine();
}
@Override
@@ -1425,9 +1357,7 @@
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
network.setReservationId(context.getReservationId());
- network.setState(Network.State.Implementing);
-
- _networksDao.update(networkId, network);
+ stateTransitTo(network, Event.ImplementNetwork);
Network result = guru.implement(network, offering, dest, context);
network.setCidr(result.getCidr());
@@ -1440,16 +1370,23 @@
// implement network elements and re-apply all the network rules
implementNetworkElementsAndResources(dest, context, network, offering);
- network.setState(Network.State.Implemented);
+ stateTransitTo(network,Event.OperationSucceeded);
+
network.setRestartRequired(false);
_networksDao.update(network.getId(), network);
implemented.set(guru, network);
return implemented;
+ } catch (NoTransitionException e) {
+ s_logger.error(e.getMessage());
+ return null;
} finally {
if (implemented.first() == null) {
s_logger.debug("Cleaning up because we're unable to implement the network " + network);
- network.setState(Network.State.Shutdown);
- _networksDao.update(networkId, network);
+ try {
+ stateTransitTo(network,Event.OperationFailed);
+ } catch (NoTransitionException e) {
+ s_logger.error(e.getMessage());
+ }
shutdownNetwork(networkId, context, false);
}
@@ -2045,9 +1982,12 @@
s_logger.debug("Network is not implemented: " + network);
return false;
}
-
- network.setState(Network.State.Shutdown);
- _networksDao.update(network.getId(), network);
+ try {
+ stateTransitTo(network, Event.DestroyNetwork);
+ } catch (NoTransitionException e) {
+ network.setState(Network.State.Shutdown);
+ _networksDao.update(network.getId(), network);
+ }
boolean success = shutdownNetworkElementsAndResources(context, cleanupElements, network);
@@ -2062,15 +2002,22 @@
guru.shutdown(profile, _networkOfferingDao.findById(network.getNetworkOfferingId()));
applyProfileToNetwork(network, profile);
-
- network.setState(Network.State.Allocated);
- network.setRestartRequired(false);
+ try {
+ stateTransitTo(network, Event.OperationSucceeded);
+ } catch (NoTransitionException e) {
+ network.setState(Network.State.Allocated);
+ network.setRestartRequired(false);
+ }
_networksDao.update(network.getId(), network);
_networksDao.clearCheckForGc(networkId);
result = true;
} else {
- network.setState(Network.State.Implemented);
- _networksDao.update(network.getId(), network);
+ try {
+ stateTransitTo(network, Event.OperationFailed);
+ } catch (NoTransitionException e) {
+ network.setState(Network.State.Implemented);
+ _networksDao.update(network.getId(), network);
+ }
result = false;
}
txn.commit();
@@ -2230,8 +2177,11 @@
s_logger.warn("Failed to delete network " + network + "; was unable to cleanup corresponding ip ranges");
} else {
// commit transaction only when ips and vlans for the network are released successfully
- network.setState(Network.State.Destroy);
- _networksDao.update(network.getId(), network);
+ try {
+ stateTransitTo(network, Event.DestroyNetwork);
+ } catch (NoTransitionException e) {
+ s_logger.debug(e.getMessage());
+ }
_networksDao.remove(network.getId());
NetworkOffering ntwkOff = _configMgr.getNetworkOffering(network.getNetworkOfferingId());
@@ -2737,10 +2687,9 @@
String guestType = vlan.getVlanType().toString();
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_RELEASE,
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_RELEASE,
ip.getAllocatedToAccountId(), ip.getDataCenterId(), addrId, ip.getAddress().addr(),
- ip.isSourceNat(), guestType, ip.getSystem());
- _usageEventDao.persist(usageEvent);
+ ip.isSourceNat(), guestType, ip.getSystem(), ip.getClass().getName(), ip.getUuid());
}
ip = _ipAddressDao.markAsUnavailable(addrId);
@@ -3458,6 +3407,15 @@
return _networkLockTimeout;
}
+
+ protected boolean stateTransitTo(NetworkVO network, Network.Event e) throws NoTransitionException {
+ return _stateMachine.transitTo(network, e, null, _networksDao);
+ }
+
+ private void setStateMachine() {
+ _stateMachine = Network.State.getStateMachine();
+ }
+
private Map<Service, Set<Provider>> getServiceProvidersMap(long networkId) {
Map<Service, Set<Provider>> map = new HashMap<Service, Set<Provider>>();
List<NetworkServiceMapVO> nsms = _ntwkSrvcDao.getServicesInNetwork(networkId);
@@ -3471,7 +3429,7 @@
}
return map;
}
-
+
@Override
public List<Provider> getProvidersForServiceInNetwork(Network network, Service service) {
Map<Service, Set<Provider>> service2ProviderMap = getServiceProvidersMap(network.getId());
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java
index 7530e94..bcd3f35 100755
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -16,31 +16,6 @@
// under the License.
package com.cloud.network;
-import java.security.InvalidParameterException;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.acl.ControlledEntity.ACLType;
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
-import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
-import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
-import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
-import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
-
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
@@ -58,17 +33,10 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.InsufficientAddressCapacityException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.UnsupportedServiceException;
+import com.cloud.exception.*;
import com.cloud.network.IpAddress.State;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
@@ -79,16 +47,7 @@
import com.cloud.network.PhysicalNetwork.BroadcastDomainRange;
import com.cloud.network.VirtualRouterProvider.VirtualRouterProviderType;
import com.cloud.network.addr.PublicIp;
-import com.cloud.network.dao.FirewallRulesDao;
-import com.cloud.network.dao.IPAddressDao;
-import com.cloud.network.dao.NetworkDao;
-import com.cloud.network.dao.NetworkDomainDao;
-import com.cloud.network.dao.NetworkServiceMapDao;
-import com.cloud.network.dao.PhysicalNetworkDao;
-import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
-import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
-import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
-import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
+import com.cloud.network.dao.*;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.VirtualRouterElement;
import com.cloud.network.element.VpcVirtualRouterElement;
@@ -109,13 +68,7 @@
import com.cloud.server.ResourceTag.TaggedResourceType;
import com.cloud.tags.ResourceTagVO;
import com.cloud.tags.dao.ResourceTagDao;
-import com.cloud.user.Account;
-import com.cloud.user.AccountManager;
-import com.cloud.user.AccountVO;
-import com.cloud.user.DomainManager;
-import com.cloud.user.ResourceLimitService;
-import com.cloud.user.User;
-import com.cloud.user.UserContext;
+import com.cloud.user.*;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.AnnotationHelper;
import com.cloud.utils.NumbersUtil;
@@ -123,25 +76,28 @@
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.JoinBuilder;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.*;
import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
-import com.cloud.vm.NicVO;
-import com.cloud.vm.ReservationContext;
-import com.cloud.vm.ReservationContextImpl;
-import com.cloud.vm.SecondaryStorageVmVO;
-import com.cloud.vm.UserVmVO;
-import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.*;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
+import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
+import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
+import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.security.InvalidParameterException;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.*;
/**
* NetworkServiceImpl implements NetworkService.
@@ -1623,10 +1579,8 @@
continue;
}
long isDefault = (nic.isDefaultNic()) ? 1 : 0;
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), null, oldNetworkOfferingId, null, 0L);
- _usageEventDao.persist(usageEvent);
- usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName(), networkOfferingId, null, isDefault);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.saveUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), null, oldNetworkOfferingId, null, 0L);
+ UsageEventUtils.saveUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName(), networkOfferingId, null, isDefault);
}
txn.commit();
} else {
diff --git a/server/src/com/cloud/network/NetworkStateListener.java b/server/src/com/cloud/network/NetworkStateListener.java
new file mode 100644
index 0000000..1300633
--- /dev/null
+++ b/server/src/com/cloud/network/NetworkStateListener.java
@@ -0,0 +1,90 @@
+package com.cloud.network;
+
+import com.cloud.event.EventCategory;
+import com.cloud.event.dao.UsageEventDao;
+import com.cloud.network.Network.Event;
+import com.cloud.network.Network.State;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.server.ManagementServer;
+import com.cloud.utils.component.Adapters;
+import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.fsm.StateListener;
+import org.apache.cloudstack.framework.events.EventBus;
+import org.apache.cloudstack.framework.events.EventBusException;
+import org.apache.log4j.Logger;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class NetworkStateListener implements StateListener<State, Event, Network> {
+
+ protected UsageEventDao _usageEventDao;
+ protected NetworkDao _networkDao;
+
+ // get the event bus provider if configured
+ protected static EventBus _eventBus = null;
+ static {
+ Adapters<EventBus> eventBusImpls = ComponentLocator.getLocator(ManagementServer.Name).getAdapters(EventBus.class);
+ if (eventBusImpls != null) {
+ Enumeration<EventBus> eventBusenum = eventBusImpls.enumeration();
+ if (eventBusenum != null && eventBusenum.hasMoreElements()) {
+ _eventBus = eventBusenum.nextElement(); // configure event bus if configured
+ }
+ }
+ }
+
+ private static final Logger s_logger = Logger.getLogger(NetworkStateListener.class);
+
+ public NetworkStateListener(UsageEventDao usageEventDao, NetworkDao networkDao) {
+ this._usageEventDao = usageEventDao;
+ this._networkDao = networkDao;
+ }
+
+ @Override
+ public boolean preStateTransitionEvent(State oldState, Event event, State newState, Network vo, boolean status, Object opaque) {
+ pubishOnEventBus(event.name(), "preStateTransitionEvent", vo, oldState, newState);
+ return true;
+ }
+
+ @Override
+ public boolean postStateTransitionEvent(State oldState, Event event, State newState, Network vo, boolean status, Object opaque) {
+ pubishOnEventBus(event.name(), "postStateTransitionEvent", vo, oldState, newState);
+ return true;
+ }
+
+ private void pubishOnEventBus(String event, String status, Network vo, State oldState, State newState) {
+
+ if (_eventBus == null) {
+ return; // no provider is configured to provide events bus, so just return
+ }
+
+ String resourceName = getEntityFromClassName(Network.class.getName());
+ org.apache.cloudstack.framework.events.Event eventMsg = new org.apache.cloudstack.framework.events.Event(
+ ManagementServer.Name,
+ EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(),
+ event,
+ resourceName,
+ vo.getUuid());
+ Map<String, String> eventDescription = new HashMap<String, String>();
+ eventDescription.put("resource", resourceName);
+ eventDescription.put("id", vo.getUuid());
+ eventDescription.put("old-state", oldState.name());
+ eventDescription.put("new-state", newState.name());
+ eventMsg.setDescription(eventDescription);
+ try {
+ _eventBus.publish(eventMsg);
+ } catch (EventBusException e) {
+ s_logger.warn("Failed to publish state change event on the the event bus.");
+ }
+ }
+
+ private String getEntityFromClassName(String entityClassName) {
+ int index = entityClassName.lastIndexOf(".");
+ String entityName = entityClassName;
+ if (index != -1) {
+ entityName = entityClassName.substring(index+1);
+ }
+ return entityName;
+ }
+}
diff --git a/server/src/com/cloud/network/NetworkVO.java b/server/src/com/cloud/network/NetworkVO.java
index 14b643b..d0209d7 100644
--- a/server/src/com/cloud/network/NetworkVO.java
+++ b/server/src/com/cloud/network/NetworkVO.java
@@ -246,6 +246,7 @@
return state;
}
+ // don't use this directly when possible, use Network state machine instead
public void setState(State state) {
this.state = state;
}
diff --git a/server/src/com/cloud/network/dao/NetworkDao.java b/server/src/com/cloud/network/dao/NetworkDao.java
index 1fefb75..18dcb6f 100644
--- a/server/src/com/cloud/network/dao/NetworkDao.java
+++ b/server/src/com/cloud/network/dao/NetworkDao.java
@@ -24,10 +24,12 @@
import com.cloud.network.NetworkAccountVO;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.Network.State;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.fsm.StateDao;
-public interface NetworkDao extends GenericDao<NetworkVO, Long> {
+public interface NetworkDao extends GenericDao<NetworkVO, Long> , StateDao<State, Network.Event, Network> {
List<NetworkVO> listByOwner(long ownerId);
diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java
index 29e2f81..2c5b46d 100644
--- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java
+++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java
@@ -28,6 +28,8 @@
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
+import com.cloud.network.Network.State;
+import com.cloud.network.Network.Event;
import com.cloud.network.NetworkAccountDaoImpl;
import com.cloud.network.NetworkAccountVO;
import com.cloud.network.NetworkDomainVO;
@@ -42,19 +44,18 @@
import com.cloud.server.ResourceTag.TaggedResourceType;
import com.cloud.tags.dao.ResourceTagsDaoImpl;
import com.cloud.utils.component.ComponentLocator;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.db.GenericSearchBuilder;
-import com.cloud.utils.db.JoinBuilder;
+import com.cloud.utils.db.*;
import com.cloud.utils.db.JoinBuilder.JoinType;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.SequenceFetcher;
-import com.cloud.utils.db.Transaction;
import com.cloud.utils.net.NetUtils;
+import javax.ejb.Local;
+import javax.persistence.TableGenerator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
@Local(value = NetworkDao.class)
@DB(txn = false)
public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements NetworkDao {
@@ -565,6 +566,20 @@
}
@Override
+ public boolean updateState(State currentState, Event event, State nextState, Network vo, Object data) {
+ // TODO: ensure this update is correct
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+
+ NetworkVO networkVo = (NetworkVO) vo;
+ networkVo.setState(nextState);
+ super.update(networkVo.getId(), networkVo);
+
+ txn.commit();
+ return true;
+ }
+
+ @Override
public List<NetworkVO> listNetworksByAccount(long accountId, long zoneId, Network.GuestType type, boolean isSystem) {
SearchCriteria<NetworkVO> sc = OfferingAccountNetworkSearch.create();
sc.setJoinParameters("ntwkOfferingSearch", "isSystem", isSystem);
@@ -580,7 +595,6 @@
public List<NetworkVO> listRedundantNetworks() {
SearchCriteria<NetworkVO> sc = AllFieldsSearch.create();
sc.setJoinParameters("offerings", "isRedundant", true);
-
return listBy(sc, null);
}
}
diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
index d4958f3..a3f60cb 100644
--- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
+++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
@@ -40,7 +40,7 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
@@ -61,18 +61,12 @@
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.element.FirewallServiceProvider;
import com.cloud.network.element.NetworkACLServiceProvider;
-import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.PortForwardingServiceProvider;
import com.cloud.network.element.StaticNatServiceProvider;
-import com.cloud.network.rules.FirewallManager;
-import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.*;
import com.cloud.network.rules.FirewallRule.FirewallRuleType;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRule.State;
-import com.cloud.network.rules.FirewallRuleVO;
-import com.cloud.network.rules.PortForwardingRule;
-import com.cloud.network.rules.PortForwardingRuleVO;
-import com.cloud.network.rules.StaticNat;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.network.vpc.VpcManager;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
@@ -88,17 +82,18 @@
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.JoinBuilder;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.*;
import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.dao.UserVmDao;
+import org.apache.cloudstack.api.command.user.firewall.ListFirewallRulesCmd;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.util.*;
@Local(value = { FirewallService.class, FirewallManager.class})
public class FirewallManagerImpl implements FirewallService, FirewallManager, NetworkRuleApplier, Manager {
@@ -709,8 +704,8 @@
}
if (generateUsageEvent && needUsageEvent) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_RULE_DELETE, rule.getAccountId(), 0, rule.getId(), null);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_RULE_DELETE, rule.getAccountId(), 0, rule.getId(),
+ null, rule.getClass().getName(), rule.getUuid());
}
txn.commit();
diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
index f8a8a95..bd6305d 100644
--- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
@@ -20,17 +20,16 @@
import javax.ejb.Local;
+import com.cloud.event.ActionEventUtils;
import org.apache.log4j.Logger;
import com.cloud.configuration.Config;
-import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.event.EventTypes;
-import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
@@ -42,9 +41,7 @@
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetwork.IsolationMethod;
-import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.NetworkDao;
-import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.rules.PortForwardingRuleVO;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offering.NetworkOffering;
@@ -142,7 +139,7 @@
}
implemented.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vlanTag));
- EventUtils.saveEvent(UserContext.current().getCallerUserId(), config.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: "+vnet+ " Network Id: "+config.getId(), 0);
+ ActionEventUtils.onCompletedActionEvent(UserContext.current().getCallerUserId(), config.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: " + vnet + " Network Id: " + config.getId(), 0);
} else {
vlanTag = Integer.parseInt(config.getBroadcastUri().getHost());
implemented.setBroadcastUri(config.getBroadcastUri());
diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java
index 9587885..e5371f5 100755
--- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java
@@ -19,12 +19,12 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
-import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.ejb.Local;
+import com.cloud.event.ActionEventUtils;
import org.apache.log4j.Logger;
import com.cloud.configuration.Config;
@@ -36,7 +36,6 @@
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.event.EventTypes;
-import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
@@ -298,8 +297,8 @@
"part of network " + network + " implement ", DataCenter.class, dcId);
}
implemented.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vnet));
- EventUtils.saveEvent(UserContext.current().getCallerUserId(), network.getAccountId(),
- EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: "+vnet+ " Network Id: "+network.getId(), 0);
+ ActionEventUtils.onCompletedActionEvent(UserContext.current().getCallerUserId(), network.getAccountId(),
+ EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: " + vnet + " Network Id: " + network.getId(), 0);
} else {
implemented.setBroadcastUri(network.getBroadcastUri());
}
@@ -433,9 +432,9 @@
s_logger.debug("Releasing vnet for the network id=" + profile.getId());
_dcDao.releaseVnet(profile.getBroadcastUri().getHost(), profile.getDataCenterId(),
profile.getPhysicalNetworkId(), profile.getAccountId(), profile.getReservationId());
- EventUtils.saveEvent(UserContext.current().getCallerUserId(), profile.getAccountId(),
+ ActionEventUtils.onCompletedActionEvent(UserContext.current().getCallerUserId(), profile.getAccountId(),
EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_RELEASE, "Released Zone Vlan: "
- +profile.getBroadcastUri().getHost()+" for Network: "+profile.getId(), 0);
+ + profile.getBroadcastUri().getHost() + " for Network: " + profile.getId(), 0);
}
profile.setBroadcastUri(null);
}
diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
index 482c1fe..8e47545 100755
--- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
+++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
@@ -30,6 +30,7 @@
import javax.ejb.Local;
import javax.naming.ConfigurationException;
+import com.cloud.event.UsageEventUtils;
import org.apache.cloudstack.api.command.user.loadbalancer.*;
import org.apache.log4j.Logger;
@@ -47,7 +48,6 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InsufficientAddressCapacityException;
@@ -93,7 +93,6 @@
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.element.LoadBalancingServiceProvider;
-import com.cloud.network.element.NetworkElement;
import com.cloud.network.lb.LoadBalancingRule.LbAutoScalePolicy;
import com.cloud.network.lb.LoadBalancingRule.LbAutoScaleVmGroup;
import com.cloud.network.lb.LoadBalancingRule.LbAutoScaleVmProfile;
@@ -871,8 +870,8 @@
if (generateUsageEvent) {
// Generate usage event right after all rules were marked for revoke
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_LOAD_BALANCER_DELETE, lb.getAccountId(), 0, lb.getId(), null);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_LOAD_BALANCER_DELETE, lb.getAccountId(), 0, lb.getId(),
+ null, LoadBalancingRule.class.getName(), lb.getUuid());
}
txn.commit();
@@ -1104,8 +1103,8 @@
}
s_logger.debug("Load balancer " + newRule.getId() + " for Ip address id=" + sourceIpId + ", public port " + srcPortStart + ", private port " + defPortStart + " is added successfully.");
UserContext.current().setEventDetails("Load balancer Id: " + newRule.getId());
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_LOAD_BALANCER_CREATE, ipAddr.getAllocatedToAccountId(), ipAddr.getDataCenterId(), newRule.getId(), null);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_LOAD_BALANCER_CREATE, ipAddr.getAllocatedToAccountId(),
+ ipAddr.getDataCenterId(), newRule.getId(), null, LoadBalancingRule.class.getName(), newRule.getUuid());
txn.commit();
return newRule;
diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java
index fe86a8e..605ffd6 100755
--- a/server/src/com/cloud/network/rules/RulesManagerImpl.java
+++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java
@@ -20,7 +20,7 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InsufficientAddressCapacityException;
@@ -276,9 +276,9 @@
throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
}
UserContext.current().setEventDetails("Rule Id: " + newRule.getId());
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_RULE_ADD, newRule.getAccountId(),
- ipAddress.getDataCenterId(), newRule.getId(), null);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_RULE_ADD, newRule.getAccountId(),
+ ipAddress.getDataCenterId(), newRule.getId(), null, PortForwardingRule.class.getName(),
+ newRule.getUuid());
txn.commit();
return newRule;
} catch (Exception e) {
@@ -358,8 +358,8 @@
throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
}
UserContext.current().setEventDetails("Rule Id: " + newRule.getId());
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_RULE_ADD, newRule.getAccountId(), 0, newRule.getId(), null);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_RULE_ADD, newRule.getAccountId(), 0, newRule.getId(),
+ null, FirewallRule.class.getName(), newRule.getUuid());
txn.commit();
StaticNatRule staticNatRule = new StaticNatRuleImpl(newRule, dstIp);
diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java
index b564e3d..5635f52 100755
--- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java
+++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java
@@ -16,30 +16,6 @@
// under the License.
package com.cloud.network.security;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.api.command.user.securitygroup.*;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.log4j.Logger;
-
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.NetworkRulesSystemVmCommand;
import com.cloud.agent.api.SecurityGroupRulesCmd;
@@ -47,33 +23,20 @@
import com.cloud.agent.manager.Commands;
import com.cloud.api.query.dao.SecurityGroupJoinDao;
import com.cloud.api.query.vo.SecurityGroupJoinVO;
-
-import org.apache.cloudstack.api.command.user.securitygroup.RevokeSecurityGroupEgressCmd;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
-import com.cloud.event.dao.UsageEventDao;
-import com.cloud.exception.AgentUnavailableException;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.OperationTimedoutException;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceInUseException;
+import com.cloud.event.UsageEventUtils;
+import com.cloud.exception.*;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkModel;
import com.cloud.network.security.SecurityGroupWork.Step;
import com.cloud.network.security.SecurityRule.SecurityRuleType;
-import com.cloud.network.security.dao.SecurityGroupDao;
-import com.cloud.network.security.dao.SecurityGroupRuleDao;
-import com.cloud.network.security.dao.SecurityGroupRulesDao;
-import com.cloud.network.security.dao.SecurityGroupVMMapDao;
-import com.cloud.network.security.dao.SecurityGroupWorkDao;
-import com.cloud.network.security.dao.VmRulesetLogDao;
-import com.cloud.projects.Project.ListProjectResourcesCriteria;
+import com.cloud.network.security.dao.*;
import com.cloud.projects.ProjectManager;
import com.cloud.server.ManagementServer;
import com.cloud.tags.dao.ResourceTagDao;
@@ -85,7 +48,6 @@
import com.cloud.uservm.UserVm;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
-import com.cloud.utils.Ternary;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
@@ -93,26 +55,26 @@
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
-import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.StateListener;
import com.cloud.utils.net.NetUtils;
-import com.cloud.vm.Nic;
-import com.cloud.vm.NicProfile;
-import com.cloud.vm.UserVmManager;
-import com.cloud.vm.UserVmVO;
-import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.*;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
-import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
-
import edu.emory.mathcs.backport.java.util.Collections;
+import org.apache.cloudstack.api.command.user.securitygroup.*;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
@Local(value = { SecurityGroupManager.class, SecurityGroupService.class })
public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityGroupService, Manager, StateListener<State, VirtualMachine.Event, VirtualMachine> {
@@ -159,8 +121,6 @@
@Inject
ProjectManager _projectMgr;
@Inject
- UsageEventDao _usageEventDao;
- @Inject
ResourceTagDao _resourceTagDao;
ScheduledExecutorService _executorPool;
@@ -460,8 +420,9 @@
// For each group, find the security rules that allow the group
for (SecurityGroupVMMapVO mapVO : groupsForVm) {// FIXME: use custom sql in the dao
//Add usage events for security group assign
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SECURITY_GROUP_ASSIGN, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), mapVO.getSecurityGroupId());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SECURITY_GROUP_ASSIGN, vm.getAccountId(),
+ vm.getDataCenterIdToDeployIn(), vm.getId(), mapVO.getSecurityGroupId(),
+ vm.getClass().getName(), vm.getUuid());
List<SecurityGroupRuleVO> allowingRules = _securityGroupRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId());
// For each security rule that allows a group that the vm belongs to, find the group it belongs to
@@ -476,8 +437,9 @@
// For each group, find the security rules rules that allow the group
for (SecurityGroupVMMapVO mapVO : groupsForVm) {// FIXME: use custom sql in the dao
//Add usage events for security group remove
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SECURITY_GROUP_REMOVE, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), mapVO.getSecurityGroupId());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SECURITY_GROUP_REMOVE,
+ vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), mapVO.getSecurityGroupId(),
+ vm.getClass().getName(), vm.getUuid());
List<SecurityGroupRuleVO> allowingRules = _securityGroupRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId());
// For each security rule that allows a group that the vm belongs to, find the group it belongs to
diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java
index e360bca..858c362 100755
--- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java
+++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java
@@ -16,44 +16,24 @@
// under the License.
package com.cloud.network.vpn;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.api.command.user.vpn.ListVpnUsersCmd;
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.api.command.user.vpn.ListRemoteAccessVpnsCmd;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.AccountLimitException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.network.IPAddressVO;
-import com.cloud.network.Network;
+import com.cloud.network.*;
import com.cloud.network.Network.Service;
-import com.cloud.network.NetworkModel;
-import com.cloud.network.PublicIpAddress;
-import com.cloud.network.RemoteAccessVpn;
-import com.cloud.network.RemoteAccessVpnVO;
-import com.cloud.network.VpnUser;
import com.cloud.network.VpnUser.State;
-import com.cloud.network.VpnUserVO;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.VpnUserDao;
-import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.RemoteAccessVPNServiceProvider;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
@@ -74,14 +54,19 @@
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.JoinBuilder;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.*;
import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.Transaction;
import com.cloud.utils.net.NetUtils;
+import org.apache.cloudstack.api.command.user.vpn.ListRemoteAccessVpnsCmd;
+import org.apache.cloudstack.api.command.user.vpn.ListVpnUsersCmd;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
@Local(value = RemoteAccessVpnService.class)
public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manager {
@@ -281,8 +266,8 @@
for(VpnUserVO user : vpnUsers){
// VPN_USER_REMOVE event is already generated for users in Revoke state
if(user.getState() != VpnUser.State.Revoke){
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VPN_USER_REMOVE, user.getAccountId(), 0, user.getId(), user.getUsername());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPN_USER_REMOVE, user.getAccountId(),
+ 0, user.getId(), user.getUsername(), user.getClass().getName(), user.getUuid());
}
}
if (vpnFwRules != null) {
@@ -333,8 +318,8 @@
}
VpnUser user = _vpnUsersDao.persist(new VpnUserVO(vpnOwnerId, owner.getDomainId(), username, password));
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VPN_USER_ADD, user.getAccountId(), 0, user.getId(), user.getUsername());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPN_USER_ADD, user.getAccountId(), 0, user.getId(),
+ user.getUsername(), user.getClass().getName(), user.getUuid());
txn.commit();
return user;
}
@@ -350,8 +335,8 @@
txn.start();
user.setState(State.Revoke);
_vpnUsersDao.update(user.getId(), user);
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VPN_USER_REMOVE, user.getAccountId(), 0, user.getId(), user.getUsername());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPN_USER_REMOVE, user.getAccountId(), 0, user.getId(),
+ user.getUsername(), user.getClass().getName(), user.getUuid());
txn.commit();
return true;
}
@@ -407,8 +392,8 @@
List<VpnUserVO> vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId());
for(VpnUserVO user : vpnUsers){
if(user.getState() != VpnUser.State.Revoke){
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VPN_USER_ADD, user.getAccountId(), 0, user.getId(), user.getUsername());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPN_USER_ADD, user.getAccountId(), 0,
+ user.getId(), user.getUsername(), user.getClass().getName(), user.getUuid());
}
}
txn.commit();
@@ -483,8 +468,8 @@
Transaction txn = Transaction.currentTxn();
txn.start();
_vpnUsersDao.remove(user.getId());
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VPN_USER_REMOVE, user.getAccountId(), 0, user.getId(), user.getUsername());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPN_USER_REMOVE, user.getAccountId(),
+ 0, user.getId(), user.getUsername(), user.getClass().getName(), user.getUuid());
txn.commit();
}
s_logger.warn("Failed to apply vpn for user " + user.getUsername() + ", accountId=" + user.getAccountId());
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 40c5508..0b5c531 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -29,7 +29,6 @@
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -42,6 +41,7 @@
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
+import com.cloud.event.ActionEventUtils;
import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd;
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
@@ -60,7 +60,6 @@
import org.apache.cloudstack.api.command.user.template.ListTemplatesCmd;
import org.apache.cloudstack.api.command.user.template.UpdateTemplateCmd;
import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
-import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
@@ -128,7 +127,6 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.ConcurrentOperationException;
@@ -230,7 +228,6 @@
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.ssh.SSHKeysHelper;
import com.cloud.vm.ConsoleProxyVO;
-import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmVO;
@@ -2422,12 +2419,12 @@
@Override
public Long saveStartedEvent(Long userId, Long accountId, String type, String description, long startEventId) {
- return EventUtils.saveStartedEvent(userId, accountId, type, description, startEventId);
+ return ActionEventUtils.onStartedActionEvent(userId, accountId, type, description, startEventId);
}
@Override
public Long saveCompletedEvent(Long userId, Long accountId, String level, String type, String description, long startEventId) {
- return EventUtils.saveEvent(userId, accountId, level, type, description, startEventId);
+ return ActionEventUtils.onCompletedActionEvent(userId, accountId, level, type, description, startEventId);
}
@Override
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index 07f4d8a..5a799f9 100755
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -16,68 +16,14 @@
// under the License.
package com.cloud.storage;
-import java.math.BigDecimal;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.api.command.admin.storage.*;
-import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
-import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
-import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
-import org.apache.log4j.Logger;
-
import com.cloud.agent.AgentManager;
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.BackupSnapshotCommand;
-import com.cloud.agent.api.CleanupSnapshotBackupCommand;
-import com.cloud.agent.api.Command;
-import com.cloud.agent.api.CreateStoragePoolCommand;
-import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
-import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
-import com.cloud.agent.api.DeleteStoragePoolCommand;
-import com.cloud.agent.api.ManageSnapshotCommand;
-import com.cloud.agent.api.ModifyStoragePoolAnswer;
-import com.cloud.agent.api.ModifyStoragePoolCommand;
-import com.cloud.agent.api.UpgradeSnapshotCommand;
-import com.cloud.agent.api.storage.CopyVolumeAnswer;
-import com.cloud.agent.api.storage.CopyVolumeCommand;
-import com.cloud.agent.api.storage.CreateAnswer;
-import com.cloud.agent.api.storage.CreateCommand;
-import com.cloud.agent.api.storage.DeleteTemplateCommand;
-import com.cloud.agent.api.storage.DeleteVolumeCommand;
-import com.cloud.agent.api.storage.DestroyCommand;
-import com.cloud.agent.api.storage.ResizeVolumeCommand;
-import com.cloud.agent.api.storage.ResizeVolumeAnswer;
+import com.cloud.agent.api.*;
+import com.cloud.agent.api.storage.*;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
import com.cloud.api.ApiDBUtils;
-import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
import com.cloud.async.AsyncJobManager;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityManager;
@@ -104,21 +50,9 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.EventDao;
-import com.cloud.event.dao.UsageEventDao;
-import com.cloud.exception.AgentUnavailableException;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.DiscoveryException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.InsufficientStorageCapacityException;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.OperationTimedoutException;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.exception.ResourceInUseException;
-import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.StorageUnavailableException;
+import com.cloud.exception.*;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
@@ -140,32 +74,17 @@
import com.cloud.storage.Volume.Event;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.allocator.StoragePoolAllocator;
-import com.cloud.storage.dao.DiskOfferingDao;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.dao.SnapshotPolicyDao;
-import com.cloud.storage.dao.StoragePoolDao;
-import com.cloud.storage.dao.StoragePoolHostDao;
-import com.cloud.storage.dao.StoragePoolWorkDao;
-import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.dao.VMTemplateHostDao;
-import com.cloud.storage.dao.VMTemplatePoolDao;
-import com.cloud.storage.dao.VMTemplateS3Dao;
-import com.cloud.storage.dao.VMTemplateSwiftDao;
-import com.cloud.storage.dao.VolumeDao;
-import com.cloud.storage.dao.VolumeHostDao;
+import com.cloud.storage.dao.*;
import com.cloud.storage.download.DownloadMonitor;
import com.cloud.storage.listener.StoragePoolMonitor;
+import com.cloud.storage.listener.VolumeStateListener;
import com.cloud.storage.s3.S3Manager;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.snapshot.SnapshotScheduler;
import com.cloud.tags.dao.ResourceTagDao;
import com.cloud.template.TemplateManager;
-import com.cloud.user.Account;
-import com.cloud.user.AccountManager;
-import com.cloud.user.ResourceLimitService;
-import com.cloud.user.User;
-import com.cloud.user.UserContext;
+import com.cloud.user.*;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.uservm.UserVm;
@@ -178,36 +97,35 @@
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
import com.cloud.utils.concurrency.NamedThreadFactory;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.GenericSearchBuilder;
-import com.cloud.utils.db.GlobalLock;
-import com.cloud.utils.db.JoinBuilder;
+import com.cloud.utils.db.*;
import com.cloud.utils.db.JoinBuilder.JoinType;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
-import com.cloud.vm.ConsoleProxyVO;
-import com.cloud.vm.DiskProfile;
-import com.cloud.vm.DomainRouterVO;
-import com.cloud.vm.SecondaryStorageVmVO;
-import com.cloud.vm.UserVmManager;
-import com.cloud.vm.UserVmVO;
-import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.*;
import com.cloud.vm.VirtualMachine.State;
-import com.cloud.vm.VirtualMachineManager;
-import com.cloud.vm.VirtualMachineProfile;
-import com.cloud.vm.VirtualMachineProfileImpl;
-import com.cloud.vm.dao.ConsoleProxyDao;
-import com.cloud.vm.dao.DomainRouterDao;
-import com.cloud.vm.dao.SecondaryStorageVmDao;
-import com.cloud.vm.dao.UserVmDao;
-import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.vm.dao.*;
+import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
+import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
+import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd;
+import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
+import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
+import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
+import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.math.BigDecimal;
+import java.net.*;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
@Local(value = { StorageManager.class, StorageService.class })
public class StorageManagerImpl implements StorageManager, Manager, ClusterManagerListener {
@@ -301,8 +219,6 @@
@Inject
protected ClusterDao _clusterDao;
@Inject
- protected UsageEventDao _usageEventDao;
- @Inject
protected VirtualMachineManager _vmMgr;
@Inject
protected DomainRouterDao _domrDao;
@@ -653,9 +569,9 @@
Pair<VolumeVO, String> volumeDetails = createVolumeFromSnapshot(volume, snapshot);
if (volumeDetails != null) {
createdVolume = volumeDetails.first();
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), createdVolume.getName(),
- createdVolume.getDiskOfferingId(), null, createdVolume.getSize());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(),
+ createdVolume.getDataCenterId(), createdVolume.getId(), createdVolume.getName(), createdVolume.getDiskOfferingId(),
+ null, createdVolume.getSize(), Volume.class.getName(), createdVolume.getUuid());
}
return createdVolume;
}
@@ -775,8 +691,9 @@
volume.setPoolId(destPool.getId());
volume.setPodId(destPool.getPodId());
stateTransitTo(volume, Event.CopySucceeded);
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(),
+ volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(),
+ null, volume.getSize(), Volume.class.getName(), volume.getUuid());
_volumeHostDao.remove(volumeHostVO.getId());
txn.commit();
return volume;
@@ -1050,6 +967,9 @@
LocalStorageSearch.join("poolHost", storageHostSearch, storageHostSearch.entity().getPoolId(), LocalStorageSearch.entity().getId(), JoinBuilder.JoinType.INNER);
LocalStorageSearch.and("type", LocalStorageSearch.entity().getPoolType(), SearchCriteria.Op.IN);
LocalStorageSearch.done();
+
+ Volume.State.getStateMachine().registerListener( new VolumeStateListener());
+
return true;
}
@@ -1967,8 +1887,8 @@
throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId);
}
- if (snapshotCheck.getStatus() != Snapshot.Status.BackedUp) {
- throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.Status.BackedUp + " state yet and can't be used for volume creation");
+ if (snapshotCheck.getState() != Snapshot.State.BackedUp) {
+ throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.State.BackedUp + " state yet and can't be used for volume creation");
}
diskOfferingId = snapshotCheck.getDiskOfferingId();
@@ -2058,9 +1978,10 @@
volume = _volsDao.persist(volume);
if(cmd.getSnapshotId() == null){
- //for volume created from snapshot, create usage event after volume creation
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), diskOfferingId, null, size);
- _usageEventDao.persist(usageEvent);
+ //for volume created from snapshot, create usage event after volume creation
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(),
+ volume.getDataCenterId(), volume.getId(), volume.getName(), diskOfferingId, null, size,
+ Volume.class.getName(), volume.getUuid());
}
UserContext.current().setEventDetails("Volume Id: " + volume.getId());
@@ -2305,8 +2226,9 @@
// Decrement the resource count for volumes belonging user VM's only
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume);
// Log usage event for volumes belonging user VM's only
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(),
+ volume.getDataCenterId(), volume.getId(), volume.getName(),
+ Volume.class.getName(), volume.getUuid());
}
try {
@@ -2471,7 +2393,7 @@
}
// remove snapshots in Error state
- List<SnapshotVO> snapshots = _snapshotDao.listAllByStatus(Snapshot.Status.Error);
+ List<SnapshotVO> snapshots = _snapshotDao.listAllByStatus(Snapshot.State.Error);
for (SnapshotVO snapshotVO : snapshots) {
try{
_snapshotDao.expunge(snapshotVO.getId());
@@ -3140,10 +3062,9 @@
// Save usage event and update resource count for user vm volumes
if (vm instanceof UserVm) {
-
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size);
- _usageEventDao.persist(usageEvent);
-
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(),
+ vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size,
+ Volume.class.getName(), vol.getUuid());
_resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume);
}
return toDiskProfile(vol, offering);
@@ -3204,9 +3125,9 @@
offeringId = offering.getId();
}
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offeringId, template.getId(),
- vol.getSize());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(),
+ vol.getDataCenterId(), vol.getId(), vol.getName(), offeringId, template.getId(),
+ vol.getSize(), Volume.class.getName(), vol.getUuid());
_resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume);
}
diff --git a/server/src/com/cloud/storage/dao/SnapshotDao.java b/server/src/com/cloud/storage/dao/SnapshotDao.java
index b32d278..3b961f6 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDao.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDao.java
@@ -16,15 +16,16 @@
// under the License.
package com.cloud.storage.dao;
-import java.util.List;
-
import com.cloud.storage.Snapshot;
import com.cloud.storage.Snapshot.Type;
import com.cloud.storage.SnapshotVO;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
+import com.cloud.utils.fsm.StateDao;
-public interface SnapshotDao extends GenericDao<SnapshotVO, Long> {
+import java.util.List;
+
+public interface SnapshotDao extends GenericDao<SnapshotVO, Long>, StateDao<Snapshot.State, Snapshot.Event, Snapshot> {
List<SnapshotVO> listByVolumeId(long volumeId);
List<SnapshotVO> listByVolumeId(Filter filter, long volumeId);
SnapshotVO findNextSnapshot(long parentSnapId);
@@ -39,7 +40,7 @@
List<SnapshotVO> listByHostId(Filter filter, long hostId);
List<SnapshotVO> listByHostId(long hostId);
public Long countSnapshotsForAccount(long accountId);
- List<SnapshotVO> listByInstanceId(long instanceId, Snapshot.Status... status);
- List<SnapshotVO> listByStatus(long volumeId, Snapshot.Status... status);
- List<SnapshotVO> listAllByStatus(Snapshot.Status... status);
+ List<SnapshotVO> listByInstanceId(long instanceId, Snapshot.State... status);
+ List<SnapshotVO> listByStatus(long volumeId, Snapshot.State... status);
+ List<SnapshotVO> listAllByStatus(Snapshot.State... status);
}
diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
index 65e2f5f..3fe1aba 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
@@ -16,33 +16,27 @@
// under the License.
package com.cloud.storage.dao;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.List;
-
-import javax.ejb.Local;
-
-import org.apache.log4j.Logger;
-
import com.cloud.server.ResourceTag.TaggedResourceType;
import com.cloud.storage.Snapshot;
+import com.cloud.storage.Snapshot.Event;
+import com.cloud.storage.Snapshot.State;
import com.cloud.storage.Snapshot.Type;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.tags.dao.ResourceTagsDaoImpl;
import com.cloud.utils.component.ComponentLocator;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.db.GenericSearchBuilder;
+import com.cloud.utils.db.*;
import com.cloud.utils.db.JoinBuilder.JoinType;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
-import com.cloud.utils.db.Transaction;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.VMInstanceDaoImpl;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.List;
@Local (value={SnapshotDao.class})
public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements SnapshotDao {
@@ -113,7 +107,7 @@
public List<SnapshotVO> listByHostId(Filter filter, long hostId ) {
SearchCriteria<SnapshotVO> sc = HostIdSearch.create();
sc.setParameters("hostId", hostId);
- sc.setParameters("status", Snapshot.Status.BackedUp);
+ sc.setParameters("status", Snapshot.State.BackedUp);
return listBy(sc, filter);
}
@@ -145,7 +139,7 @@
HostIdSearch = createSearchBuilder();
HostIdSearch.and("hostId", HostIdSearch.entity().getSecHostId(), SearchCriteria.Op.EQ);
- HostIdSearch.and("status", HostIdSearch.entity().getStatus(), SearchCriteria.Op.EQ);
+ HostIdSearch.and("status", HostIdSearch.entity().getState(), SearchCriteria.Op.EQ);
HostIdSearch.done();
VolumeIdTypeSearch = createSearchBuilder();
@@ -172,7 +166,7 @@
StatusSearch = createSearchBuilder();
StatusSearch.and("volumeId", StatusSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
- StatusSearch.and("status", StatusSearch.entity().getStatus(), SearchCriteria.Op.IN);
+ StatusSearch.and("status", StatusSearch.entity().getState(), SearchCriteria.Op.IN);
StatusSearch.done();
CountSnapshotsByAccount = createSearchBuilder(Long.class);
@@ -182,7 +176,7 @@
CountSnapshotsByAccount.done();
InstanceIdSearch = createSearchBuilder();
- InstanceIdSearch.and("status", InstanceIdSearch.entity().getStatus(), SearchCriteria.Op.IN);
+ InstanceIdSearch.and("status", InstanceIdSearch.entity().getState(), SearchCriteria.Op.IN);
SearchBuilder<VMInstanceVO> instanceSearch = _instanceDao.createSearchBuilder();
instanceSearch.and("instanceId", instanceSearch.entity().getId(), SearchCriteria.Op.EQ);
@@ -274,7 +268,7 @@
}
@Override
- public List<SnapshotVO> listByInstanceId(long instanceId, Snapshot.Status... status) {
+ public List<SnapshotVO> listByInstanceId(long instanceId, Snapshot.State... status) {
SearchCriteria<SnapshotVO> sc = this.InstanceIdSearch.create();
if (status != null && status.length != 0) {
@@ -287,7 +281,7 @@
}
@Override
- public List<SnapshotVO> listByStatus(long volumeId, Snapshot.Status... status) {
+ public List<SnapshotVO> listByStatus(long volumeId, Snapshot.State... status) {
SearchCriteria<SnapshotVO> sc = this.StatusSearch.create();
sc.setParameters("volumeId", volumeId);
sc.setParameters("status", (Object[])status);
@@ -309,9 +303,20 @@
}
@Override
- public List<SnapshotVO> listAllByStatus(Snapshot.Status... status) {
+ public List<SnapshotVO> listAllByStatus(Snapshot.State... status) {
SearchCriteria<SnapshotVO> sc = this.StatusSearch.create();
sc.setParameters("status", (Object[])status);
return listBy(sc, null);
}
+
+ @Override
+ public boolean updateState(State currentState, Event event, State nextState, Snapshot snapshot, Object data) {
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ SnapshotVO snapshotVO = (SnapshotVO)snapshot;
+ snapshotVO.setStatus(nextState);
+ super.update(snapshotVO.getId(), snapshotVO);
+ txn.commit();
+ return true;
+ }
}
diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java
index 2736777..cf51567 100755
--- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java
+++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java
@@ -16,36 +16,14 @@
// under the License.
package com.cloud.storage.download;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Timer;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.ejb.Local;
-
-import org.apache.log4j.Logger;
-
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
-import com.cloud.agent.api.storage.DeleteTemplateCommand;
-import com.cloud.agent.api.storage.DeleteVolumeCommand;
-import com.cloud.agent.api.storage.DownloadCommand;
-import com.cloud.agent.api.storage.ListVolumeAnswer;
-import com.cloud.agent.api.storage.ListVolumeCommand;
+import com.cloud.agent.api.storage.*;
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
-import com.cloud.agent.api.storage.DownloadProgressCommand;
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
-import com.cloud.agent.api.storage.ListTemplateAnswer;
-import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
import com.cloud.configuration.Config;
@@ -54,8 +32,7 @@
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
-import com.cloud.event.dao.UsageEventDao;
+import com.cloud.event.UsageEventUtils;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.StorageUnavailableException;
@@ -65,26 +42,9 @@
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.Storage.ImageFormat;
-import com.cloud.storage.StorageManager;
-import com.cloud.storage.SwiftVO;
-import com.cloud.storage.VMTemplateHostVO;
-import com.cloud.storage.VMTemplateStorageResourceAssoc;
-import com.cloud.storage.Volume;
-import com.cloud.storage.VolumeHostVO;
-import com.cloud.storage.VolumeVO;
+import com.cloud.storage.*;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
-import com.cloud.storage.Volume.Event;
-import com.cloud.storage.VMTemplateVO;
-import com.cloud.storage.VMTemplateZoneVO;
-import com.cloud.storage.dao.StoragePoolHostDao;
-import com.cloud.storage.dao.SwiftDao;
-import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.dao.VMTemplateHostDao;
-import com.cloud.storage.dao.VMTemplatePoolDao;
-import com.cloud.storage.dao.VMTemplateSwiftDao;
-import com.cloud.storage.dao.VMTemplateZoneDao;
-import com.cloud.storage.dao.VolumeDao;
-import com.cloud.storage.dao.VolumeHostDao;
+import com.cloud.storage.dao.*;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.swift.SwiftManager;
import com.cloud.storage.template.TemplateConstants;
@@ -92,19 +52,21 @@
import com.cloud.user.Account;
import com.cloud.user.ResourceLimitService;
import com.cloud.utils.component.Inject;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.JoinBuilder;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
-import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.*;
import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import edu.emory.mathcs.backport.java.util.Collections;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
@Local(value={DownloadMonitor.class})
@@ -147,11 +109,6 @@
ConfigurationDao _configDao;
@Inject
UserVmManager _vmMgr;
-
-
- @Inject
- private UsageEventDao _usageEventDao;
-
@Inject
private ClusterDao _clusterDao;
@Inject
@@ -517,8 +474,9 @@
eventType = EventTypes.EVENT_ISO_CREATE;
}
if(template.getAccountId() != Account.ACCOUNT_ID_SYSTEM){
- UsageEventVO usageEvent = new UsageEventVO(eventType, template.getAccountId(), host.getDataCenterId(), template.getId(), template.getName(), null, template.getSourceTemplateId() , size);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(eventType, template.getAccountId(), host.getDataCenterId(),
+ template.getId(), template.getName(), null, template.getSourceTemplateId(), size,
+ template.getClass().getName(), template.getUuid());
}
}
txn.commit();
@@ -550,8 +508,8 @@
}
String eventType = EventTypes.EVENT_VOLUME_UPLOAD;
if(volume.getAccountId() != Account.ACCOUNT_ID_SYSTEM){
- UsageEventVO usageEvent = new UsageEventVO(eventType, volume.getAccountId(), host.getDataCenterId(), volume.getId(), volume.getName(), null, 0l , size);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(eventType, volume.getAccountId(), host.getDataCenterId(),
+ volume.getId(), volume.getName(), null, 0l, size, volume.getClass().getName(), volume.getUuid());
}
}else if (dnldStatus == Status.DOWNLOAD_ERROR || dnldStatus == Status.ABANDONED || dnldStatus == Status.UNKNOWN){
//Decrement the volume count
diff --git a/server/src/com/cloud/storage/listener/SnapshotStateListener.java b/server/src/com/cloud/storage/listener/SnapshotStateListener.java
new file mode 100644
index 0000000..2b19887
--- /dev/null
+++ b/server/src/com/cloud/storage/listener/SnapshotStateListener.java
@@ -0,0 +1,85 @@
+package com.cloud.storage.listener;
+
+import com.cloud.event.EventCategory;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Snapshot.Event;
+import com.cloud.storage.Snapshot.State;
+import com.cloud.server.ManagementServer;
+import com.cloud.utils.component.Adapters;
+import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.fsm.StateListener;
+import org.apache.cloudstack.framework.events.EventBus;
+import org.apache.cloudstack.framework.events.EventBusException;
+import org.apache.log4j.Logger;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SnapshotStateListener implements StateListener<State, Event, Snapshot> {
+
+ // get the event bus provider if configured
+ protected static EventBus _eventBus = null;
+ static {
+ Adapters<EventBus> eventBusImpls = ComponentLocator.getLocator(ManagementServer.Name).getAdapters(EventBus.class);
+ if (eventBusImpls != null) {
+ Enumeration<EventBus> eventBusenum = eventBusImpls.enumeration();
+ if (eventBusenum != null && eventBusenum.hasMoreElements()) {
+ _eventBus = eventBusenum.nextElement(); // configure event bus if configured
+ }
+ }
+ }
+
+ private static final Logger s_logger = Logger.getLogger(VolumeStateListener.class);
+
+ public SnapshotStateListener() {
+
+ }
+
+ @Override
+ public boolean preStateTransitionEvent(State oldState, Event event, State newState, Snapshot vo, boolean status, Object opaque) {
+ pubishOnEventBus(event.name(), "preStateTransitionEvent", vo, oldState, newState);
+ return true;
+ }
+
+ @Override
+ public boolean postStateTransitionEvent(State oldState, Event event, State newState, Snapshot vo, boolean status, Object opaque) {
+ pubishOnEventBus(event.name(), "postStateTransitionEvent", vo, oldState, newState);
+ return true;
+ }
+
+ private void pubishOnEventBus(String event, String status, Snapshot vo, State oldState, State newState) {
+
+ if (_eventBus == null) {
+ return; // no provider is configured to provide events bus, so just return
+ }
+
+ String resourceName = getEntityFromClassName(Snapshot.class.getName());
+ org.apache.cloudstack.framework.events.Event eventMsg = new org.apache.cloudstack.framework.events.Event(
+ ManagementServer.Name,
+ EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(),
+ event,
+ resourceName,
+ vo.getUuid());
+ Map<String, String> eventDescription = new HashMap<String, String>();
+ eventDescription.put("resource", resourceName);
+ eventDescription.put("id", vo.getUuid());
+ eventDescription.put("old-state", oldState.name());
+ eventDescription.put("new-state", newState.name());
+ eventMsg.setDescription(eventDescription);
+ try {
+ _eventBus.publish(eventMsg);
+ } catch (EventBusException e) {
+ s_logger.warn("Failed to publish state change event on the the event bus.");
+ }
+ }
+
+ private String getEntityFromClassName(String entityClassName) {
+ int index = entityClassName.lastIndexOf(".");
+ String entityName = entityClassName;
+ if (index != -1) {
+ entityName = entityClassName.substring(index+1);
+ }
+ return entityName;
+ }
+}
diff --git a/server/src/com/cloud/storage/listener/VolumeStateListener.java b/server/src/com/cloud/storage/listener/VolumeStateListener.java
new file mode 100644
index 0000000..c460016
--- /dev/null
+++ b/server/src/com/cloud/storage/listener/VolumeStateListener.java
@@ -0,0 +1,85 @@
+package com.cloud.storage.listener;
+
+import com.cloud.event.EventCategory;
+import com.cloud.storage.Volume;
+import com.cloud.storage.Volume.Event;
+import com.cloud.storage.Volume.State;
+import com.cloud.server.ManagementServer;
+import com.cloud.utils.component.Adapters;
+import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.fsm.StateListener;
+import org.apache.cloudstack.framework.events.EventBus;
+import org.apache.cloudstack.framework.events.EventBusException;
+import org.apache.log4j.Logger;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class VolumeStateListener implements StateListener<State, Event, Volume> {
+
+ // get the event bus provider if configured
+ protected static EventBus _eventBus = null;
+ static {
+ Adapters<EventBus> eventBusImpls = ComponentLocator.getLocator(ManagementServer.Name).getAdapters(EventBus.class);
+ if (eventBusImpls != null) {
+ Enumeration<EventBus> eventBusenum = eventBusImpls.enumeration();
+ if (eventBusenum != null && eventBusenum.hasMoreElements()) {
+ _eventBus = eventBusenum.nextElement(); // configure event bus if configured
+ }
+ }
+ }
+
+ private static final Logger s_logger = Logger.getLogger(VolumeStateListener.class);
+
+ public VolumeStateListener() {
+
+ }
+
+ @Override
+ public boolean preStateTransitionEvent(State oldState, Event event, State newState, Volume vo, boolean status, Object opaque) {
+ pubishOnEventBus(event.name(), "preStateTransitionEvent", vo, oldState, newState);
+ return true;
+ }
+
+ @Override
+ public boolean postStateTransitionEvent(State oldState, Event event, State newState, Volume vo, boolean status, Object opaque) {
+ pubishOnEventBus(event.name(), "postStateTransitionEvent", vo, oldState, newState);
+ return true;
+ }
+
+ private void pubishOnEventBus(String event, String status, Volume vo, State oldState, State newState) {
+
+ if (_eventBus == null) {
+ return; // no provider is configured to provide events bus, so just return
+ }
+
+ String resourceName = getEntityFromClassName(Volume.class.getName());
+ org.apache.cloudstack.framework.events.Event eventMsg = new org.apache.cloudstack.framework.events.Event(
+ ManagementServer.Name,
+ EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(),
+ event,
+ resourceName,
+ vo.getUuid());
+ Map<String, String> eventDescription = new HashMap<String, String>();
+ eventDescription.put("resource", resourceName);
+ eventDescription.put("id", vo.getUuid());
+ eventDescription.put("old-state", oldState.name());
+ eventDescription.put("new-state", newState.name());
+ eventMsg.setDescription(eventDescription);
+ try {
+ _eventBus.publish(eventMsg);
+ } catch (EventBusException e) {
+ s_logger.warn("Failed to state change event on the the event bus.");
+ }
+ }
+
+ private String getEntityFromClassName(String entityClassName) {
+ int index = entityClassName.lastIndexOf(".");
+ String entityName = entityClassName;
+ if (index != -1) {
+ entityName = entityClassName.substring(index+1);
+ }
+ return entityName;
+ }
+}
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index 15d8c53..66eb8e1 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -16,37 +16,12 @@
// under the License.
package com.cloud.storage.snapshot;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotPolicyCmd;
-import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
-import org.apache.log4j.Logger;
-
import com.cloud.agent.AgentManager;
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.BackupSnapshotAnswer;
-import com.cloud.agent.api.BackupSnapshotCommand;
-import com.cloud.agent.api.Command;
-import com.cloud.agent.api.DeleteSnapshotBackupCommand;
-import com.cloud.agent.api.DeleteSnapshotsDirCommand;
-import com.cloud.agent.api.DownloadSnapshotFromS3Command;
-import com.cloud.agent.api.ManageSnapshotAnswer;
-import com.cloud.agent.api.ManageSnapshotCommand;
-import com.cloud.agent.api.downloadSnapshotFromSwiftCommand;
+import com.cloud.agent.api.*;
import com.cloud.agent.api.to.S3TO;
import com.cloud.agent.api.to.SwiftTO;
import com.cloud.alert.AlertManager;
-import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotPoliciesCmd;
import com.cloud.api.commands.ListRecurringSnapshotScheduleCmd;
-import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd;
import com.cloud.configuration.Config;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
@@ -55,11 +30,7 @@
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.dao.DomainDao;
-import com.cloud.event.ActionEvent;
-import com.cloud.event.EventTypes;
-import com.cloud.event.EventUtils;
-import com.cloud.event.EventVO;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.*;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
@@ -69,44 +40,21 @@
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.network.PhysicalNetworkTrafficType;
import com.cloud.org.Grouping;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
import com.cloud.resource.ResourceManager;
import com.cloud.server.ResourceTag.TaggedResourceType;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.Snapshot.Status;
+import com.cloud.storage.*;
import com.cloud.storage.Snapshot.Type;
-import com.cloud.storage.SnapshotPolicyVO;
-import com.cloud.storage.SnapshotScheduleVO;
-import com.cloud.storage.SnapshotVO;
-import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
-import com.cloud.storage.StorageManager;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.StoragePoolVO;
-import com.cloud.storage.VMTemplateVO;
-import com.cloud.storage.Volume;
-import com.cloud.storage.VolumeVO;
-import com.cloud.storage.dao.DiskOfferingDao;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.dao.SnapshotPolicyDao;
-import com.cloud.storage.dao.SnapshotScheduleDao;
-import com.cloud.storage.dao.StoragePoolDao;
-import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.dao.VolumeDao;
+import com.cloud.storage.dao.*;
+import com.cloud.storage.listener.SnapshotStateListener;
import com.cloud.storage.s3.S3Manager;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.swift.SwiftManager;
import com.cloud.tags.ResourceTagVO;
import com.cloud.tags.dao.ResourceTagDao;
-import com.cloud.user.Account;
-import com.cloud.user.AccountManager;
-import com.cloud.user.AccountVO;
-import com.cloud.user.DomainManager;
-import com.cloud.user.ResourceLimitService;
-import com.cloud.user.User;
-import com.cloud.user.UserContext;
+import com.cloud.user.*;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.DateUtil;
import com.cloud.utils.DateUtil.IntervalType;
@@ -116,18 +64,24 @@
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.JoinBuilder;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
-import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.*;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.UserVmDao;
+import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotPolicyCmd;
+import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotPoliciesCmd;
+import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd;
+import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.util.*;
@Local(value = { SnapshotManager.class, SnapshotService.class })
public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Manager {
@@ -195,6 +149,8 @@
private int _deltaSnapshotMax;
private int _backupsnapshotwait;
+ private StateMachine2<Snapshot.State, Snapshot.Event, Snapshot> _snapshotFsm;
+
protected SearchBuilder<SnapshotVO> PolicySnapshotSearch;
protected SearchBuilder<SnapshotPolicyVO> PoliciesForSnapSearch;
@@ -259,6 +215,13 @@
if (snapshot == null) {
throw new CloudRuntimeException("Can not find snapshot " + snapshotId);
}
+
+ try {
+ stateTransitTo(snapshot, Snapshot.Event.CreateRequested);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
+ }
+
// Send a ManageSnapshotCommand to the agent
String vmName = _storageMgr.getVmNameOnVolume(volume);
long volumeId = volume.getId();
@@ -289,14 +252,16 @@
if (preSnapshotPath != null && preSnapshotPath.equals(answer.getSnapshotPath())) {
// empty snapshot
s_logger.debug("CreateSnapshot: this is empty snapshot ");
- snapshot.setPath(preSnapshotPath);
- snapshot.setBackupSnapshotId(preSnapshotVO.getBackupSnapshotId());
- snapshot.setSwiftId(preSnapshotVO.getSwiftId());
-
- snapshot.setStatus(Snapshot.Status.BackedUp);
- snapshot.setPrevSnapshotId(preId);
- snapshot.setSecHostId(preSnapshotVO.getSecHostId());
- _snapshotDao.update(snapshotId, snapshot);
+ try {
+ snapshot.setPath(preSnapshotPath);
+ snapshot.setBackupSnapshotId(preSnapshotVO.getBackupSnapshotId());
+ snapshot.setSwiftId(preSnapshotVO.getSwiftId());
+ snapshot.setPrevSnapshotId(preId);
+ snapshot.setSecHostId(preSnapshotVO.getSecHostId());
+ stateTransitTo(snapshot, Snapshot.Event.OperationNotPerformed);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("CreateSnapshot: failed to update state of snapshot due to " + nte.getMessage());
+ }
} else {
long preSnapshotId = 0;
@@ -346,6 +311,11 @@
if (answer != null) {
s_logger.error(answer.getDetails());
}
+ try {
+ stateTransitTo(snapshot, Snapshot.Event.OperationFailed);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
+ }
throw new CloudRuntimeException("Creating snapshot for volume " + volumeId + " on primary storage failed.");
}
@@ -410,7 +380,7 @@
}
if(userVm.getHypervisorType() == HypervisorType.VMware || userVm.getHypervisorType() == HypervisorType.KVM) {
- List<SnapshotVO> activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(), Snapshot.Status.Creating, Snapshot.Status.CreatedOnPrimary, Snapshot.Status.BackingUp);
+ List<SnapshotVO> activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(), Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
if(activeSnapshots.size() > 1)
throw new CloudRuntimeException("There is other active snapshot tasks on the instance to which the volume is attached, please try again later");
}
@@ -419,19 +389,15 @@
snapshot = createSnapshotOnPrimary(volume, policyId, snapshotId);
if (snapshot != null) {
- if (snapshot.getStatus() == Snapshot.Status.CreatedOnPrimary) {
+ if (snapshot.getState() == Snapshot.State.CreatedOnPrimary) {
backedUp = backupSnapshotToSecondaryStorage(snapshot);
- } else if (snapshot.getStatus() == Snapshot.Status.BackedUp) {
+ } else if (snapshot.getState() == Snapshot.State.BackedUp) {
// For empty snapshot we set status to BackedUp in createSnapshotOnPrimary
backedUp = true;
} else {
- snapshot.setStatus(Status.Error);
- _snapshotDao.update(snapshot.getId(), snapshot);
throw new CloudRuntimeException("Failed to create snapshot: " + snapshot + " on primary storage");
}
if (!backedUp) {
- snapshot.setStatus(Status.Error);
- _snapshotDao.update(snapshot.getId(), snapshot);
throw new CloudRuntimeException("Created snapshot: " + snapshot + " on primary but failed to backup on secondary");
}
} else {
@@ -444,23 +410,15 @@
//Check if the snapshot was removed while backingUp. If yes, do not log snapshot create usage event
SnapshotVO freshSnapshot = _snapshotDao.findById(snapshot.getId());
if ((freshSnapshot != null) && backedUp) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
- volume.getSize());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
+ snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
+ volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
}
if( !backedUp ) {
- snapshot.setStatus(Status.Error);
- _snapshotDao.update(snapshot.getId(), snapshot);
} else {
_resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
}
- } else {
- snapshot = _snapshotDao.findById(snapshotId);
- if (snapshot != null) {
- snapshot.setStatus(Status.Error);
- _snapshotDao.update(snapshotId, snapshot);
- }
}
/*
@@ -478,9 +436,12 @@
private SnapshotVO updateDBOnCreate(Long id, String snapshotPath, long preSnapshotId) {
SnapshotVO createdSnapshot = _snapshotDao.findByIdIncludingRemoved(id);
createdSnapshot.setPath(snapshotPath);
- createdSnapshot.setStatus(Snapshot.Status.CreatedOnPrimary);
createdSnapshot.setPrevSnapshotId(preSnapshotId);
- _snapshotDao.update(id, createdSnapshot);
+ try {
+ stateTransitTo(createdSnapshot, Snapshot.Event.OperationSucceeded);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("Faile to update state of snapshot due to " + nte.getMessage());
+ }
return createdSnapshot;
}
@@ -622,9 +583,11 @@
throw new CloudRuntimeException("Can not acquire lock for snapshot: " + ss);
}
try {
-
- snapshot.setStatus(Snapshot.Status.BackingUp);
- _snapshotDao.update(snapshot.getId(), snapshot);
+ try {
+ stateTransitTo(snapshot, Snapshot.Event.BackupToSecondary);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("Failed to update the state of snapshot while backing up snapshot");
+ }
long volumeId = snapshot.getVolumeId();
VolumeVO volume = _volsDao.lockRow(volumeId, true);
@@ -705,10 +668,18 @@
if (answer.isFull()) {
snapshot.setPrevSnapshotId(0);
}
- snapshot.setStatus(Snapshot.Status.BackedUp);
- _snapshotDao.update(snapshotId, snapshot);
+ try {
+ stateTransitTo(snapshot, Snapshot.Event.OperationSucceeded);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("Failed to update the state of snapshot while backing up snapshot");
+ }
} else {
+ try {
+ stateTransitTo(snapshot, Snapshot.Event.OperationFailed);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("Failed to update the state of snapshot while backing up snapshot");
+ }
s_logger.warn("Failed to back up snapshot on secondary storage, deleting the record from the DB");
_snapshotDao.remove(snapshotId);
}
@@ -766,8 +737,8 @@
long oldSnapId = oldestSnapshot.getId();
s_logger.debug("Max snaps: " + policy.getMaxSnaps() + " exceeded for snapshot policy with Id: " + policyId + ". Deleting oldest snapshot: " + oldSnapId);
if(deleteSnapshotInternal(oldSnapId)){
- //log Snapshot delete event
- EventUtils.saveEvent(User.UID_SYSTEM, oldestSnapshot.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_SNAPSHOT_DELETE, "Successfully deleted oldest snapshot: " + oldSnapId, 0);
+ //log Snapshot delete event
+ ActionEventUtils.onCompletedActionEvent(User.UID_SYSTEM, oldestSnapshot.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_SNAPSHOT_DELETE, "Successfully deleted oldest snapshot: " + oldSnapId, 0);
}
snaps.remove(oldestSnapshot);
}
@@ -787,7 +758,7 @@
_accountMgr.checkAccess(caller, null, true, snapshotCheck);
- if( !Status.BackedUp.equals(snapshotCheck.getStatus() ) ) {
+ if( !Snapshot.State.BackedUp.equals(snapshotCheck.getState() ) ) {
throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + " due to it is not in BackedUp Status");
}
@@ -812,9 +783,10 @@
Transaction txn = Transaction.currentTxn();
txn.start();
_snapshotDao.remove(snapshotId);
- if (snapshot.getStatus() == Snapshot.Status.BackedUp) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(), snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null, 0L);
- _usageEventDao.persist(usageEvent);
+ if (snapshot.getState() == Snapshot.State.BackedUp) {
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(),
+ snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null, 0L,
+ snapshot.getClass().getName(), snapshot.getUuid());
}
_resourceLimitMgr.decrementResourceCount(snapshot.getAccountId(), ResourceType.snapshot);
txn.commit();
@@ -966,7 +938,7 @@
SearchBuilder<SnapshotVO> sb = _snapshotDao.createSearchBuilder();
_accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
- sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);
+ sb.and("status", sb.entity().getState(), SearchCriteria.Op.EQ);
sb.and("volumeId", sb.entity().getVolumeId(), SearchCriteria.Op.EQ);
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
@@ -1115,9 +1087,9 @@
}
// Log event after successful deletion
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(), volume.getDataCenterId(), snapshot.getId(), snapshot.getName(), null, null,
- volume.getSize());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(),
+ volume.getDataCenterId(), snapshot.getId(), snapshot.getName(), null, null,
+ volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
}
}
}
@@ -1452,6 +1424,9 @@
s_logger.info("Snapshot Manager is configured.");
+ _snapshotFsm = Snapshot.State.getStateMachine();
+ _snapshotFsm.registerListener(new SnapshotStateListener());
+
return true;
}
@@ -1538,11 +1513,15 @@
@Override
public boolean canOperateOnVolume(VolumeVO volume) {
- List<SnapshotVO> snapshots = _snapshotDao.listByStatus(volume.getId(), Status.Creating, Status.CreatedOnPrimary, Status.BackingUp);
+ List<SnapshotVO> snapshots = _snapshotDao.listByStatus(volume.getId(), Snapshot.State.Creating,
+ Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
if (snapshots.size() > 0) {
return false;
}
return true;
}
+ protected boolean stateTransitTo(Snapshot snapshot, Snapshot.Event e) throws NoTransitionException {
+ return _snapshotFsm.transitTo(snapshot, e, null, _snapshotDao);
+ }
}
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
index d7deb6f..9389893 100644
--- a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
@@ -26,6 +26,7 @@
import javax.ejb.Local;
import javax.naming.ConfigurationException;
+import com.cloud.event.ActionEventUtils;
import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotCmd;
import org.apache.log4j.Logger;
@@ -39,7 +40,6 @@
import com.cloud.async.dao.AsyncJobDao;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.event.EventTypes;
-import com.cloud.event.EventUtils;
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotScheduleVO;
@@ -232,8 +232,8 @@
tmpSnapshotScheduleVO = _snapshotScheduleDao.acquireInLockTable(snapshotScheId);
- Long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
- EventTypes.EVENT_SNAPSHOT_CREATE, "creating snapshot for volume Id:"+volumeId,0);
+ Long eventId = ActionEventUtils.onScheduledActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
+ EventTypes.EVENT_SNAPSHOT_CREATE, "creating snapshot for volume Id:" + volumeId, 0);
Map<String, String> params = new HashMap<String, String>();
params.put(ApiConstants.VOLUME_ID, "" + volumeId);
diff --git a/server/src/com/cloud/template/HyervisorTemplateAdapter.java b/server/src/com/cloud/template/HyervisorTemplateAdapter.java
index c80d1de..81a482b 100755
--- a/server/src/com/cloud/template/HyervisorTemplateAdapter.java
+++ b/server/src/com/cloud/template/HyervisorTemplateAdapter.java
@@ -16,28 +16,13 @@
// under the License.
package com.cloud.template;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.util.List;
-
-import javax.ejb.Local;
-
-import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
-import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
-import org.apache.log4j.Logger;
-
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DeleteTemplateCommand;
-import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
-import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenterVO;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.HostVO;
@@ -53,6 +38,15 @@
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
+import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
+import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
+import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import java.net.*;
+import java.util.List;
@Local(value=TemplateAdapter.class)
public class HyervisorTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter {
@@ -202,8 +196,7 @@
success = false;
break;
}
- UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), sZoneId, templateId, null);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(eventType, account.getId(), sZoneId, templateId, null, null, null);
templateHostVO.setDestroyed(true);
_tmpltHostDao.update(templateHostVO.getId(), templateHostVO);
String installPath = templateHostVO.getInstallPath();
diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java
index 1372111..42106b3 100755
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@ -16,41 +16,14 @@
// under the License.
package com.cloud.template;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd;
-import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd;
-import org.apache.cloudstack.api.command.user.iso.*;
-import org.apache.cloudstack.api.command.user.template.*;
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.downloadTemplateFromSwiftToSecondaryStorageCommand;
-import com.cloud.agent.api.uploadTemplateToSwiftFromSecondaryStorageCommand;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.to.SwiftTO;
-import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
-import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
+import com.cloud.agent.api.uploadTemplateToSwiftFromSecondaryStorageCommand;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobVO;
import com.cloud.configuration.Config;
@@ -63,7 +36,7 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
@@ -77,51 +50,19 @@
import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectManager;
-import com.cloud.storage.LaunchPermissionVO;
-import com.cloud.storage.SnapshotVO;
-import com.cloud.storage.Storage;
+import com.cloud.storage.*;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
-import com.cloud.storage.StorageManager;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.StoragePoolHostVO;
-import com.cloud.storage.StoragePoolStatus;
-import com.cloud.storage.StoragePoolVO;
-import com.cloud.storage.Upload;
import com.cloud.storage.Upload.Type;
-import com.cloud.storage.UploadVO;
-import com.cloud.storage.VMTemplateHostVO;
-import com.cloud.storage.VMTemplateStoragePoolVO;
-import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
-import com.cloud.storage.VMTemplateSwiftVO;
-import com.cloud.storage.VMTemplateVO;
-import com.cloud.storage.VMTemplateZoneVO;
-import com.cloud.storage.VolumeVO;
-import com.cloud.storage.dao.LaunchPermissionDao;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.dao.StoragePoolDao;
-import com.cloud.storage.dao.StoragePoolHostDao;
-import com.cloud.storage.dao.UploadDao;
-import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.dao.VMTemplateHostDao;
-import com.cloud.storage.dao.VMTemplatePoolDao;
-import com.cloud.storage.dao.VMTemplateS3Dao;
-import com.cloud.storage.dao.VMTemplateSwiftDao;
-import com.cloud.storage.dao.VMTemplateZoneDao;
-import com.cloud.storage.dao.VolumeDao;
+import com.cloud.storage.dao.*;
import com.cloud.storage.download.DownloadMonitor;
import com.cloud.storage.s3.S3Manager;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.swift.SwiftManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateAdapter.TemplateAdapterType;
-import com.cloud.user.Account;
-import com.cloud.user.AccountManager;
-import com.cloud.user.AccountService;
-import com.cloud.user.AccountVO;
-import com.cloud.user.ResourceLimitService;
-import com.cloud.user.UserContext;
+import com.cloud.user.*;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
@@ -132,12 +73,7 @@
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
import com.cloud.utils.concurrency.NamedThreadFactory;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.GlobalLock;
-import com.cloud.utils.db.JoinBuilder;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
-import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.*;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
@@ -145,6 +81,21 @@
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.acl.SecurityChecker.AccessType;
+import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd;
+import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd;
+import org.apache.cloudstack.api.command.user.iso.*;
+import org.apache.cloudstack.api.command.user.template.*;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
@Local(value={TemplateManager.class, TemplateService.class})
@@ -823,8 +774,8 @@
_tmpltDao.addTemplateToZone(template, dstZoneId);
if(account.getId() != Account.ACCOUNT_ID_SYSTEM){
- UsageEventVO usageEvent = new UsageEventVO(copyEventType, account.getId(), dstZoneId, tmpltId, null, null, null, srcTmpltHost.getSize());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(copyEventType, account.getId(), dstZoneId, tmpltId, null, null, null, srcTmpltHost.getSize(),
+ template.getClass().getName(), template.getUuid());
}
return true;
}
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index b910a03..f60d305 100755
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -36,6 +36,7 @@
import javax.ejb.Local;
import javax.naming.ConfigurationException;
+import com.cloud.event.ActionEventUtils;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker;
@@ -64,7 +65,6 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.EventUtils;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.CloudAuthenticationException;
import com.cloud.exception.ConcurrentOperationException;
@@ -1744,7 +1744,7 @@
public void logoutUser(Long userId) {
UserAccount userAcct = _userAccountDao.findById(userId);
if (userAcct != null) {
- EventUtils.saveEvent(userId, userAcct.getAccountId(), userAcct.getDomainId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
+ ActionEventUtils.onActionEvent(userId, userAcct.getAccountId(), userAcct.getDomainId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
} // else log some kind of error event? This likely means the user doesn't exist, or has been deleted...
}
@@ -1875,10 +1875,10 @@
s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
}
if (NetUtils.isValidIp(loginIpAddress)) {
- EventUtils.saveEvent(user.getId(), user.getAccountId(), user.getDomainId(), EventTypes.EVENT_USER_LOGIN,
+ ActionEventUtils.onActionEvent(user.getId(), user.getAccountId(), user.getDomainId(), EventTypes.EVENT_USER_LOGIN,
"user has logged in from IP Address " + loginIpAddress);
} else {
- EventUtils.saveEvent(user.getId(), user.getAccountId(), user.getDomainId(), EventTypes.EVENT_USER_LOGIN,
+ ActionEventUtils.onActionEvent(user.getId(), user.getAccountId(), user.getDomainId(), EventTypes.EVENT_USER_LOGIN,
"user has logged in. The IP Address cannot be determined");
}
return user;
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 3737450..969539c 100644
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -54,7 +54,7 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.*;
import com.cloud.ha.HighAvailabilityManager;
@@ -245,8 +245,6 @@
@Inject
protected LoadBalancingRulesManager _lbMgr;
@Inject
- protected UsageEventDao _usageEventDao;
- @Inject
protected SSHKeyPairDao _sshKeyPairDao;
@Inject
protected UserVmDetailsDao _vmDetailsDao;
@@ -280,6 +278,8 @@
PhysicalNetworkDao _physicalNetworkDao;
@Inject
VpcManager _vpcMgr;
+ @Inject
+ UsageEventDao _usageEventDao;
protected ScheduledExecutorService _executor = null;
protected int _expungeInterval;
@@ -841,7 +841,7 @@
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true)
+ @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true)
public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) {
Account caller = UserContext.current().getCaller();
if ((cmmd.getId() == null && cmmd.getDeviceId() == null && cmmd.getVirtualMachineId() == null) || (cmmd.getId() != null && (cmmd.getDeviceId() != null || cmmd.getVirtualMachineId() != null))
@@ -1372,9 +1372,9 @@
offeringId = offering.getId();
}
}
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), offeringId, templateId,
- volume.getSize());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(),
+ volume.getDataCenterId(), volume.getId(), volume.getName(), offeringId, templateId,
+ volume.getSize(), Volume.class.getName(), volume.getUuid());
}
}
@@ -1640,8 +1640,8 @@
//check permissions
_accountMgr.checkAccess(caller, null, true, snapshot);
- if (snapshot.getStatus() != Snapshot.Status.BackedUp) {
- throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.Status.BackedUp + " state yet and can't be used for template creation");
+ if (snapshot.getState() != Snapshot.State.BackedUp) {
+ throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.State.BackedUp + " state yet and can't be used for template creation");
}
/*
@@ -1888,9 +1888,10 @@
templateHostVO.setPhysicalSize(answer.getphysicalSize());
_templateHostDao.persist(templateHostVO);
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, privateTemplate.getAccountId(), secondaryStorageHost.getDataCenterId(), privateTemplate.getId(),
- privateTemplate.getName(), null, privateTemplate.getSourceTemplateId(), templateHostVO.getSize());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_TEMPLATE_CREATE, privateTemplate.getAccountId(),
+ secondaryStorageHost.getDataCenterId(), privateTemplate.getId(),
+ privateTemplate.getName(), null, privateTemplate.getSourceTemplateId(),
+ templateHostVO.getSize(), VirtualMachineTemplate.class.getName(), privateTemplate.getUuid());
txn.commit();
}
} finally {
@@ -2835,8 +2836,9 @@
}
UserContext.current().setEventDetails("Vm Id: " + vm.getId());
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), hypervisorType.toString());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(),
+ vm.getHostName(), offering.getId(), template.getId(), hypervisorType.toString(),
+ VirtualMachine.class.getName(), vm.getUuid());
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm);
txn.commit();
@@ -3006,8 +3008,9 @@
for (NicVO nic : nics) {
NetworkVO network = _networkDao.findById(nic.getNetworkId());
long isDefault = (nic.isDefaultNic()) ? 1 : 0;
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName(), network.getNetworkOfferingId(), null, isDefault);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(),
+ vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName(), network.getNetworkOfferingId(),
+ null, isDefault, VirtualMachine.class.getName(), vm.getUuid());
if (network.getTrafficType() == TrafficType.Guest) {
originalIp = nic.getIp4Address();
guestNic = nic;
@@ -3270,8 +3273,9 @@
List<VolumeVO> volumes = _volsDao.findByInstance(vmId);
for (VolumeVO volume : volumes) {
if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(),
+ volume.getDataCenterId(), volume.getId(), volume.getName(), Volume.class.getName(),
+ volume.getUuid());
}
}
@@ -3721,8 +3725,9 @@
Transaction txn = Transaction.currentTxn();
txn.start();
//generate destroy vm event for usage
- _usageEventDao.persist(new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(),
- vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm.getHypervisorType().toString()));
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(),
+ vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm.getHypervisorType().toString(),
+ VirtualMachine.class.getName(), vm.getUuid());
// update resource counts
_resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.user_vm);
@@ -3734,13 +3739,16 @@
// OS 2: update volume
List<VolumeVO> volumes = _volsDao.findByInstance(cmd.getVmId());
for (VolumeVO volume : volumes) {
- _usageEventDao.persist(new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName()));
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(),
+ volume.getDataCenterId(), volume.getId(), volume.getName(), Volume.class.getName(), volume.getUuid());
_resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.volume);
volume.setAccountId(newAccount.getAccountId());
_volsDao.persist(volume);
_resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.volume);
- _usageEventDao.persist(new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
- volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize()));
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(),
+ volume.getDataCenterId(), volume.getId(), volume.getName(),
+ volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(),
+ volume.getUuid());
//snapshots: mark these removed in db
List<SnapshotVO> snapshots = _snapshotDao.listByVolumeIdIncludingRemoved(volume.getId());
for (SnapshotVO snapshot: snapshots){
@@ -3750,8 +3758,9 @@
_resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.user_vm);
//generate usage events to account for this change
- _usageEventDao.persist(new UsageEventVO(EventTypes.EVENT_VM_CREATE, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(),
- vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm.getHypervisorType().toString()));
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(),
+ vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm.getHypervisorType().toString(),
+ VirtualMachine.class.getName(), vm.getUuid());
txn.commit();
diff --git a/server/src/com/cloud/vm/UserVmStateListener.java b/server/src/com/cloud/vm/UserVmStateListener.java
index 4d9bcc5..786387f 100644
--- a/server/src/com/cloud/vm/UserVmStateListener.java
+++ b/server/src/com/cloud/vm/UserVmStateListener.java
@@ -16,24 +16,48 @@
// under the License.
package com.cloud.vm;
-import java.util.List;
-
+import com.cloud.event.EventCategory;
import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventVO;
+import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.UsageEventDao;
+import com.cloud.network.Network;
import com.cloud.network.NetworkVO;
import com.cloud.network.dao.NetworkDao;
+import com.cloud.server.ManagementServer;
+import com.cloud.utils.component.Adapters;
+import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.fsm.StateListener;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.NicDao;
+import org.apache.cloudstack.framework.events.EventBus;
+import org.apache.cloudstack.framework.events.EventBusException;
+import org.apache.log4j.Logger;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
public class UserVmStateListener implements StateListener<State, VirtualMachine.Event, VirtualMachine> {
protected UsageEventDao _usageEventDao;
protected NetworkDao _networkDao;
protected NicDao _nicDao;
-
+ private static final Logger s_logger = Logger.getLogger(UserVmStateListener.class);
+
+ // get the event bus provider if configured
+ protected static EventBus _eventBus = null;
+ static {
+ Adapters<EventBus> eventBusImpls = ComponentLocator.getLocator(ManagementServer.Name).getAdapters(EventBus.class);
+ if (eventBusImpls != null) {
+ Enumeration<EventBus> eventBusenum = eventBusImpls.enumeration();
+ if (eventBusenum != null && eventBusenum.hasMoreElements()) {
+ _eventBus = eventBusenum.nextElement(); // configure event bus if configured
+ }
+ }
+ }
+
public UserVmStateListener(UsageEventDao usageEventDao, NetworkDao networkDao, NicDao nicDao) {
this._usageEventDao = usageEventDao;
this._networkDao = networkDao;
@@ -42,6 +66,7 @@
@Override
public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
+ pubishOnEventBus(event.name(), "preStateTransitionEvent", vo, oldState, newState);
return true;
}
@@ -54,29 +79,62 @@
if(vo.getType() != VirtualMachine.Type.User){
return true;
}
-
+
+ pubishOnEventBus(event.name(), "postStateTransitionEvent", vo, oldState, newState);
+
if (VirtualMachine.State.isVmCreated(oldState, event, newState)) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_CREATE, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), vo.getHostName(), vo.getServiceOfferingId(),
+ UsageEventUtils.saveUsageEvent(EventTypes.EVENT_VM_CREATE, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), vo.getHostName(), vo.getServiceOfferingId(),
vo.getTemplateId(), vo.getHypervisorType().toString());
- _usageEventDao.persist(usageEvent);
} else if (VirtualMachine.State.isVmStarted(oldState, event, newState)) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_START, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), vo.getHostName(), vo.getServiceOfferingId(),
+ UsageEventUtils.saveUsageEvent(EventTypes.EVENT_VM_START, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), vo.getHostName(), vo.getServiceOfferingId(),
vo.getTemplateId(), vo.getHypervisorType().toString());
- _usageEventDao.persist(usageEvent);
} else if (VirtualMachine.State.isVmStopped(oldState, event, newState)) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_STOP, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), vo.getHostName());
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.saveUsageEvent(EventTypes.EVENT_VM_STOP, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), vo.getHostName());
List<NicVO> nics = _nicDao.listByVmId(vo.getId());
for (NicVO nic : nics) {
NetworkVO network = _networkDao.findById(nic.getNetworkId());
- usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), null, network.getNetworkOfferingId(), null, 0L);
- _usageEventDao.persist(usageEvent);
+ UsageEventUtils.saveUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), null, network.getNetworkOfferingId(), null, 0L);
}
} else if (VirtualMachine.State.isVmDestroyed(oldState, event, newState)) {
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), vo.getHostName(), vo.getServiceOfferingId(),
+ UsageEventUtils.saveUsageEvent(EventTypes.EVENT_VM_DESTROY, vo.getAccountId(), vo.getDataCenterIdToDeployIn(), vo.getId(), vo.getHostName(), vo.getServiceOfferingId(),
vo.getTemplateId(), vo.getHypervisorType().toString());
- _usageEventDao.persist(usageEvent);
}
return true;
}
+
+ private void pubishOnEventBus(String event, String status, VirtualMachine vo, VirtualMachine.State oldState, VirtualMachine.State newState) {
+
+ if (_eventBus == null) {
+ return; // no provider is configured to provide events bus, so just return
+ }
+
+ String resourceName = getEntityFromClassName(Network.class.getName());
+ org.apache.cloudstack.framework.events.Event eventMsg = new org.apache.cloudstack.framework.events.Event(
+ ManagementServer.Name,
+ EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(),
+ event,
+ resourceName,
+ vo.getUuid());
+ Map<String, String> eventDescription = new HashMap<String, String>();
+ eventDescription.put("resource", resourceName);
+ eventDescription.put("id", vo.getUuid());
+ eventDescription.put("old-state", oldState.name());
+ eventDescription.put("new-state", newState.name());
+ eventMsg.setDescription(eventDescription);
+ try {
+ _eventBus.publish(eventMsg);
+ } catch (EventBusException e) {
+ s_logger.warn("Failed to publish state change event on the the event bus.");
+ }
+
+ }
+
+ private String getEntityFromClassName(String entityClassName) {
+ int index = entityClassName.lastIndexOf(".");
+ String entityName = entityClassName;
+ if (index != -1) {
+ entityName = entityClassName.substring(index+1);
+ }
+ return entityName;
+ }
}
diff --git a/server/test/com/cloud/snapshot/SnapshotDaoTest.java b/server/test/com/cloud/snapshot/SnapshotDaoTest.java
index c412f49..5dc9b91 100644
--- a/server/test/com/cloud/snapshot/SnapshotDaoTest.java
+++ b/server/test/com/cloud/snapshot/SnapshotDaoTest.java
@@ -16,24 +16,23 @@
// under the License.
package com.cloud.snapshot;
-import java.util.List;
-
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.dao.SnapshotDaoImpl;
import com.cloud.utils.component.ComponentLocator;
-
import junit.framework.Assert;
import junit.framework.TestCase;
+import java.util.List;
+
public class SnapshotDaoTest extends TestCase {
public void testListBy() {
SnapshotDaoImpl dao = ComponentLocator.inject(SnapshotDaoImpl.class);
- List<SnapshotVO> snapshots = dao.listByInstanceId(3, Snapshot.Status.BackedUp);
+ List<SnapshotVO> snapshots = dao.listByInstanceId(3, Snapshot.State.BackedUp);
for(SnapshotVO snapshot : snapshots) {
- Assert.assertTrue(snapshot.getStatus() == Snapshot.Status.BackedUp);
+ Assert.assertTrue(snapshot.getState() == Snapshot.State.BackedUp);
}
}
}
diff --git a/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java b/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java
index 7c9a582..f0e4b54 100644
--- a/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java
+++ b/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java
@@ -16,12 +16,7 @@
// under the License.
package com.cloud.vpc.dao;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import javax.ejb.Local;
-
+import com.cloud.network.Network;
import com.cloud.network.Network.GuestType;
import com.cloud.network.NetworkAccountVO;
import com.cloud.network.NetworkVO;
@@ -31,6 +26,11 @@
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
+import javax.ejb.Local;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
@Local(value = NetworkDao.class)
@DB(txn = false)
public class MockNetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements NetworkDao{
@@ -342,6 +342,11 @@
return 0;
}
+ @Override
+ public boolean updateState(Network.State currentState, Network.Event event, Network.State nextState, Network vo, Object data) {
+ return true;
+ }
+
/* (non-Javadoc)
* @see com.cloud.network.dao.NetworkDao#listNetworksByAccount(long, long, com.cloud.network.Network.GuestType, boolean)
*/
diff --git a/tools/whisker/LICENSE b/tools/whisker/LICENSE
index 7efac5c..025cb33 100644
--- a/tools/whisker/LICENSE
+++ b/tools/whisker/LICENSE
@@ -748,7 +748,7 @@
The Covered Software is a "commercial item," as that term is
defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
- computer software" (as that term is defined at 48 C.F.R. ¤
+ computer software" (as that term is defined at 48 C.F.R. �
252.227-7014(a)(1)) and "commercial computer software
documentation" as such terms are used in 48 C.F.R. 12.212 (Sept.
1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1
@@ -1138,7 +1138,7 @@
The Covered Software is a "commercial item," as that term is
defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
- computer software" (as that term is defined at 48 C.F.R. ¤
+ computer software" (as that term is defined at 48 C.F.R. �
252.227-7014(a)(1)) and "commercial computer software
documentation" as such terms are used in 48 C.F.R. 12.212 (Sept.
1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1
@@ -1526,7 +1526,7 @@
The Covered Software is a "commercial item," as that term is
defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
- computer software" (as that term is defined at 48 C.F.R. ¤
+ computer software" (as that term is defined at 48 C.F.R. �
252.227-7014(a)(1)) and "commercial computer software
documentation" as such terms are used in 48 C.F.R. 12.212 (Sept.
1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1
@@ -1867,7 +1867,9 @@
slf4j-api-1.5.11.jar from https://github.com/qos-ch/slf4j
slf4j-jdk14-1.5.11.jar from https://github.com/qos-ch/slf4j
- licensed under the Mozilla Public License, Version 1.0 http://www.mozilla.org/MPL/1.1/ (as follows)
+
+ licensed under the Mozilla Public License, Version 1.1 http://www.mozilla.org/MPL/1.1/ (as follows)
+
MOZILLA PUBLIC LICENSE
@@ -2344,6 +2346,486 @@
from Shigeru Chiba http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
javassist-3.9.0.GA.jar from http://sourceforge.net/projects/jboss/files/Javassist/
+
+ licensed under the Mozilla Public License, Version 1.1 http://www.mozilla.org/MPL/1.1/ (as follows)
+
+ Copyright (c) 2007-2012 VMware, Inc. All Rights Reserved.
+
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+ 1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+ 2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+ 3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+ 4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+ 5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+ 6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+ 7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+ 8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+ 9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+ 10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+ 11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+ 12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+ 13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+ EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (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.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations
+ under the License.
+
+ The Original Code is RabbitMQ.
+
+ The Initial Developer of the Original Code is VMware, Ltd..
+ Portions created by VMware, Ltd. are Copyright (C)
+ 2007-2012 VMware, Inc.. All Rights Reserved.
+
+ Contributor(s): .
+
+ Alternatively, the contents of this file may be used under the terms
+ of the GNU General Public License Version 2 license (the "[GPL] License"), in which case the
+ provisions of [GPL] License are applicable instead of those
+ above. If you wish to allow use of your version of this file only
+ under the terms of the [GPL] License and not to allow others to use
+ your version of this file under the MPL, indicate your decision by
+ deleting the provisions above and replace them with the notice and
+ other provisions required by the [GPL] License. If you do not delete
+ the provisions above, a recipient may use your version of this file
+ under either the MPL or the [GPL] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
+
+ from VMware, Inc http://www.vmware.com/
+ rabbitmq-client.jar from http://www.rabbitmq.com/java-client.html
+
+
Within the patches/systemvm/debian/config/etc directory
placed in the public domain
by Adiscon GmbH http://www.adiscon.com/
@@ -2980,7 +3462,7 @@
The Covered Software is a "commercial item," as that term is
defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
- computer software" (as that term is defined at 48 C.F.R. ¤
+ computer software" (as that term is defined at 48 C.F.R. �
252.227-7014(a)(1)) and "commercial computer software
documentation" as such terms are used in 48 C.F.R. 12.212 (Sept.
1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1
@@ -3369,7 +3851,7 @@
The Covered Software is a "commercial item," as that term is
defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
- computer software" (as that term is defined at 48 C.F.R. ¤
+ computer software" (as that term is defined at 48 C.F.R. �
252.227-7014(a)(1)) and "commercial computer software
documentation" as such terms are used in 48 C.F.R. 12.212 (Sept.
1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1
@@ -3895,7 +4377,7 @@
licensed under the MIT License http://www.opensource.org/licenses/mit-license.php (as follows)
- Copyright (C) 2008 Tóth István <stoty@tvnet.hu>
+ Copyright (C) 2008 T�th Istv�n <stoty@tvnet.hu>
2008-2012 Daniel Veillard <veillard@redhat.com>
2009-2011 Bryan Kearney <bkearney@redhat.com>
@@ -4026,7 +4508,7 @@
licensed under the MIT License http://www.opensource.org/licenses/mit-license.php (as follows)
- Copyright (c) 2006 - 2011 Jörn Zaefferer
+ Copyright (c) 2006 - 2011 J�rn Zaefferer
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -4221,7 +4703,7 @@
Within the ui/lib/qunit directory
licensed under the MIT License http://www.opensource.org/licenses/mit-license.php (as follows)
- Copyright (c) 2012 John Resig, Jörn Zaefferer
+ Copyright (c) 2012 John Resig, J�rn Zaefferer
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/tools/whisker/descriptor-for-packaging.xml b/tools/whisker/descriptor-for-packaging.xml
index 0144dbc..29a8284 100644
--- a/tools/whisker/descriptor-for-packaging.xml
+++ b/tools/whisker/descriptor-for-packaging.xml
@@ -2423,6 +2423,10 @@
id='adiscon.com'
name='Adiscon GmbH'
url='http://www.adiscon.com/' />
+ <organisation
+ id='vmware.com'
+ name='VMware, Inc'
+ url='http://www.vmware.com/' />
</organisations>
<primary-license id='ApacheLicenseVersion2'>
<copyright-notice>Copyright (c) 2013 The Apache Software Foundation</copyright-notice>
@@ -2948,5 +2952,19 @@
<resource name='javassist-3.9.0.GA.jar' source='http://sourceforge.net/projects/jboss/files/Javassist/' />
</by-organisation>
</with-license>
+ <with-license id='MPL1'>
+ <copyright-notice>Copyright (c) 2007-2012 VMware, Inc. All Rights Reserved.</copyright-notice>
+ <license-parameters>
+ <parameter><name>PROJECT</name><value>RabbitMQ</value></parameter>
+ <parameter><name>INITIAL_DEVELOPER</name><value>VMware, Ltd.</value></parameter>
+ <parameter><name>INITIAL_DEVELOPER_COPYRIGHT</name><value>2007-2012 VMware, Inc.</value></parameter>
+ <parameter><name>CONTRIBUTORS</name><value></value></parameter>
+ <parameter><name>ALT_LIC_NAME</name><value>GNU General Public License Version 2</value></parameter>
+ <parameter><name>ALT_LIC_SHORT</name><value>GPL</value></parameter>
+ </license-parameters>
+ <by-organisation id='vmware.com'>
+ <resource name='rabbitmq-client.jar' source='http://www.rabbitmq.com/java-client.html' />
+ </by-organisation>
+ </with-license>
</within>
</manifest>