Introduce new resource life cycle listener

This commit is contained in:
frank 2011-08-08 17:04:40 -07:00
parent 18f87c2108
commit 0f109dd037
3 changed files with 115 additions and 55 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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);
}

6
server/src/com/cloud/resource/ResourceManager.java Normal file → Executable file
View File

@ -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);
}

View File

@ -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<Host.Type, ResourceLifeCycleListener> _listeners = new HashMap<Host.Type, ResourceLifeCycleListener>();
protected HashMap<Integer, List<ResourceListener>> _lifeCycleListeners = new HashMap<Integer, List<ResourceListener>>();
private void insertListener(Integer event, ResourceListener listener) {
List<ResourceListener> lst = _lifeCycleListeners.get(event);
if (lst == null) {
lst = new ArrayList<ResourceListener>();
_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<Integer, List<ResourceListener>> items = (Map.Entry<Integer, List<ResourceListener>>)it.next();
List<ResourceListener> lst = items.getValue();
lst.remove(listener);
}
}
}
protected void processResourceEvent(Integer event, Object...params) {
synchronized (_lifeCycleListeners) {
List<ResourceListener> 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<String>)params[6]);
eventName = "EVENT_DISCOVER_BEFORE";
} else if (event == ResourceListener.EVENT_DISCOVER_AFTER) {
l.processDiscoverEventAfter((Map<? extends ServerResource, Map<String, String>>)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<String, String>> 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<String, String>> 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);