diff --git a/server/src/com/cloud/resource/ResourceLifeCycleListener.java b/server/src/com/cloud/resource/ResourceLifeCycleListener.java
deleted file mode 100644
index 62d88cd6062..00000000000
--- a/server/src/com/cloud/resource/ResourceLifeCycleListener.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
- *
- * This software is licensed under the GNU General Public License v3 or later.
- *
- * It is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-package com.cloud.resource;
-
-import com.cloud.agent.api.StartupCommand;
-import com.cloud.host.Host;
-import com.cloud.host.HostVO;
-
-/**
- * Listener registered with the ResourceManager if you want to be informed
- * of a certain type of host's life cycles.
- *
- */
-public interface ResourceLifeCycleListener {
- /**
- * @return the type of resource this listener can process.
- */
- Host.Type getType();
-
- void add(HostVO host, StartupCommand cmd, boolean created);
-
- /**
- * Put the resource into maintenance mode.
- */
- void maintain(HostVO host, boolean force);
-
- void removed(HostVO host, boolean force);
-
- void enable(HostVO host);
-
- void disable(HostVO host);
-
-}
diff --git a/server/src/com/cloud/resource/ResourceManager.java b/server/src/com/cloud/resource/ResourceManager.java
old mode 100644
new mode 100755
index cc27eaf5d1f..526c22bb642
--- a/server/src/com/cloud/resource/ResourceManager.java
+++ b/server/src/com/cloud/resource/ResourceManager.java
@@ -28,8 +28,10 @@ public interface ResourceManager {
* Register a listener for different types of resource life cycle events.
* There can only be one type of listener per type of host.
*
- * @param type the resource type the listener is responsible to.
+ * @param Event type see ResourceListener.java, allow combination of multiple events.
* @param listener the listener to notify.
*/
- void registerForLifeCycleEvents(Host.Type type, ResourceLifeCycleListener listener);
+ public void registerResourceEvent(Integer event, ResourceListener listener);
+
+ public void unregisterResourceEvent(ResourceListener listener);
}
diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java
index fc97b8238af..d5f55911734 100644
--- a/server/src/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/com/cloud/resource/ResourceManagerImpl.java
@@ -23,6 +23,7 @@ import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
@@ -118,11 +119,103 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
protected long _nodeId = ManagementServerNode.getManagementServerId();
- protected HashMap _listeners = new HashMap();
+ protected HashMap> _lifeCycleListeners = new HashMap>();
+ private void insertListener(Integer event, ResourceListener listener) {
+ List lst = _lifeCycleListeners.get(event);
+ if (lst == null) {
+ lst = new ArrayList();
+ _lifeCycleListeners.put(event, lst);
+ }
+
+ if (lst.contains(listener)) {
+ throw new CloudRuntimeException("Duplicate resource lisener:" + listener.getName());
+ }
+
+ lst.add(listener);
+ }
+
@Override
- public void registerForLifeCycleEvents(Host.Type type, ResourceLifeCycleListener listener) {
- _listeners.put(type, listener);
+ public void registerResourceEvent(Integer event, ResourceListener listener) {
+ synchronized (_lifeCycleListeners) {
+ if ((event & ResourceListener.EVENT_DISCOVER_BEFORE) == 1) {
+ insertListener(ResourceListener.EVENT_DISCOVER_BEFORE, listener);
+ }
+ if ((event & ResourceListener.EVENT_DISCOVER_AFTER) == 1) {
+ insertListener(ResourceListener.EVENT_DISCOVER_AFTER, listener);
+ }
+ if ((event & ResourceListener.EVENT_DELETE_HOST_BEFORE) == 1) {
+ insertListener(ResourceListener.EVENT_DELETE_HOST_BEFORE, listener);
+ }
+ if ((event & ResourceListener.EVENT_DELETE_HOST_AFTER) == 1) {
+ insertListener(ResourceListener.EVENT_DELETE_HOST_AFTER, listener);
+ }
+ if ((event & ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE) == 1) {
+ insertListener(ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE, listener);
+ }
+ if ((event & ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER) == 1) {
+ insertListener(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, listener);
+ }
+ if ((event & ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE) == 1) {
+ insertListener(ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE, listener);
+ }
+ if ((event & ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER) == 1) {
+ insertListener(ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER, listener);
+ }
+ }
+ }
+
+ @Override
+ public void unregisterResourceEvent(ResourceListener listener) {
+ synchronized (_lifeCycleListeners) {
+ Iterator it = _lifeCycleListeners.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry> items = (Map.Entry>)it.next();
+ List lst = items.getValue();
+ lst.remove(listener);
+ }
+ }
+ }
+
+ protected void processResourceEvent(Integer event, Object...params) {
+ synchronized (_lifeCycleListeners) {
+ List lst = _lifeCycleListeners.get(event);
+ if (lst == null || lst.size() == 0) {
+ return;
+ }
+
+ String eventName;
+ for (ResourceListener l : lst) {
+ if (event == ResourceListener.EVENT_DISCOVER_BEFORE) {
+ l.processDiscoverEventBefore((Long)params[0], (Long)params[1], (Long)params[2], (URI)params[3], (String)params[4], (String)params[5], (List)params[6]);
+ eventName = "EVENT_DISCOVER_BEFORE";
+ } else if (event == ResourceListener.EVENT_DISCOVER_AFTER) {
+ l.processDiscoverEventAfter((Map extends ServerResource, Map>)params[0]);
+ eventName = "EVENT_DISCOVER_AFTER";
+ } else if (event == ResourceListener.EVENT_DELETE_HOST_BEFORE) {
+ l.processDeleteHostEventBefore((HostVO)params[0]);
+ eventName = "EVENT_DELETE_HOST_BEFORE";
+ } else if (event == ResourceListener.EVENT_DELETE_HOST_AFTER) {
+ l.processDeletHostEventAfter((HostVO)params[0]);
+ eventName = "EVENT_DELETE_HOST_AFTER";
+ } else if (event == ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE) {
+ l.processCancelMaintenaceEventBefore((Long)params[0]);
+ eventName = "EVENT_CANCEL_MAINTENANCE_BEFORE";
+ } else if (event == ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER) {
+ l.processCancelMaintenaceEventAfter((Long)params[0]);
+ eventName = "EVENT_CANCEL_MAINTENANCE_AFTER";
+ } else if (event == ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE) {
+ l.processPrepareMaintenaceEventBefore((Long)params[0]);
+ eventName = "EVENT_PREPARE_MAINTENANCE_BEFORE";
+ } else if (event == ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER) {
+ l.processPrepareMaintenaceEventAfter((Long)params[0]);
+ eventName = "EVENT_PREPARE_MAINTENANCE_AFTER";
+ } else {
+ throw new CloudRuntimeException("Unknown resource event:" + event);
+ }
+ s_logger.debug("Send resource event " + eventName + " to listener " + l.getName());
+ }
+ }
}
@Override
@@ -479,6 +572,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
isHypervisorTypeSupported = true;
Map extends ServerResource, Map> resources = null;
+ processResourceEvent(ResourceListener.EVENT_DISCOVER_BEFORE, dcId, podId, clusterId, uri, username, password, hostTags);
try {
resources = discoverer.find(dcId, podId, clusterId, uri, username, password);
} catch(DiscoveryException e) {
@@ -486,6 +580,9 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
} catch (Exception e) {
s_logger.info("Exception in host discovery process with discoverer: " + discoverer.getName() + ", skip to another discoverer if there is any");
}
+ processResourceEvent(ResourceListener.EVENT_DISCOVER_AFTER, resources);
+
+ //TODO: move this out using resource listener
if (resources != null) {
for (Map.Entry extends ServerResource, Map> entry : resources.entrySet()) {
ServerResource resource = entry.getKey();
@@ -538,12 +635,17 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
throw new InvalidParameterValueException("Host with id " + hostId + " doesn't exist");
}
_accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), host.getDataCenterId());
+
+ processResourceEvent(ResourceListener.EVENT_DELETE_HOST_BEFORE, host);
+ boolean res = false;
if (Host.Type.SecondaryStorage.equals(host.getType())) {
_secondaryStorageMgr.deleteHost(hostId);
- return true;
+ res = true;
} else {
- return _agentMgr.deleteHost(hostId, isForced, forceDestroy, caller);
+ res = _agentMgr.deleteHost(hostId, isForced, forceDestroy, caller);
}
+ processResourceEvent(ResourceListener.EVENT_DELETE_HOST_AFTER, host);
+ return res;
}
@Override
@@ -735,7 +837,9 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
throw new InvalidParameterValueException("Host with id " + hostId.toString() + " doesn't exist");
}
+ processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE, hostId);
boolean success = _agentMgr.cancelMaintenance(hostId);
+ processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, hostId);
if (!success) {
throw new CloudRuntimeException("Internal error cancelling maintenance.");
}
@@ -777,7 +881,9 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
}
try {
+ processResourceEvent(ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE, hostId);
if (_agentMgr.maintain(hostId)) {
+ processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, hostId);
return _hostDao.findById(hostId);
} else {
throw new CloudRuntimeException("Unable to prepare for maintenance host " + hostId);