You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ya...@apache.org on 2012/06/22 22:33:30 UTC

[2/3] CS-15173: Additional Cluster is allowed to add with the same VSM IPaddress as the previous cluster

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/361ca964/server/src/com/cloud/resource/ResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java
index a49f1f6..423e6df 100755
--- a/server/src/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/com/cloud/resource/ResourceManagerImpl.java
@@ -79,6 +79,7 @@ import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.DiscoveryException;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.PermissionDeniedException;
+import com.cloud.exception.ResourceInUseException;
 import com.cloud.ha.HighAvailabilityManager;
 import com.cloud.ha.HighAvailabilityManager.WorkType;
 import com.cloud.host.DetailVO;
@@ -219,7 +220,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
     protected ClusterVSMMapDao				 _clusterVSMMapDao;
 
     protected long                           _nodeId  = ManagementServerNode.getManagementServerId();
-    
+
     protected HashMap<String, ResourceStateAdapter> _resourceStateAdapters = new HashMap<String, ResourceStateAdapter>();
 
     protected HashMap<Integer, List<ResourceListener>> _lifeCycleListeners = new HashMap<Integer, List<ResourceListener>>();
@@ -231,14 +232,14 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             lst = new ArrayList<ResourceListener>();
             _lifeCycleListeners.put(event, lst);
         }
-        
+
         if (lst.contains(listener)) {
             throw new CloudRuntimeException("Duplicate resource lisener:" + listener.getClass().getSimpleName());
         }
-        
+
         lst.add(listener);
     }
-    
+
     @Override
     public void registerResourceEvent(Integer event, ResourceListener listener) {
         synchronized (_lifeCycleListeners) {
@@ -268,7 +269,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             }
         }
     }
-    
+
     @Override
     public void unregisterResourceEvent(ResourceListener listener) {
         synchronized (_lifeCycleListeners) {
@@ -280,7 +281,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             }
         }
     }
-    
+
     protected void processResourceEvent(Integer event, Object...params) {
         List<ResourceListener> lst = _lifeCycleListeners.get(event);
         if (lst == null || lst.size() == 0) {
@@ -319,12 +320,12 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             }
             s_logger.debug("Sent resource event " + eventName + " to listener " + l.getClass().getSimpleName());
         }
-        
+
     }
 
     @DB
     @Override
-    public List<? extends Cluster> discoverCluster(AddClusterCmd cmd) throws IllegalArgumentException, DiscoveryException {
+    public List<? extends Cluster> discoverCluster(AddClusterCmd cmd) throws IllegalArgumentException, DiscoveryException, ResourceInUseException {
         long dcId = cmd.getZoneId();
         long podId = cmd.getPodId();
         String clusterName = cmd.getClusterName();
@@ -341,35 +342,35 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         // Check if the zone exists in the system
         DataCenterVO zone = _dcDao.findById(dcId);
         if (zone == null) {
-        	InvalidParameterValueException ex = new InvalidParameterValueException("Can't find zone by the id specified");
-        	ex.addProxyObject(zone, dcId, "dcId");
+            InvalidParameterValueException ex = new InvalidParameterValueException("Can't find zone by the id specified");
+            ex.addProxyObject(zone, dcId, "dcId");
             throw ex;
         }
 
         Account account = UserContext.current().getCaller();
         if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
-        	PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, Zone with specified id is currently disabled");
-        	ex.addProxyObject(zone, dcId, "dcId");
+            PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, Zone with specified id is currently disabled");
+            ex.addProxyObject(zone, dcId, "dcId");
             throw ex;
         }
 
         HostPodVO pod = _podDao.findById(podId);
         if (pod == null) {
-        	throw new InvalidParameterValueException("Can't find pod with specified podId " + podId);
+            throw new InvalidParameterValueException("Can't find pod with specified podId " + podId);
         }
-        
+
         // Check if the pod exists in the system
         if (_podDao.findById(podId) == null) {
             throw new InvalidParameterValueException("Can't find pod by id " + podId);
         }
         // check if pod belongs to the zone
         if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) {
-        	InvalidParameterValueException ex = new InvalidParameterValueException("Pod with specified id doesn't belong to the zone " + dcId);
-        	ex.addProxyObject(pod, podId, "podId");                
+            InvalidParameterValueException ex = new InvalidParameterValueException("Pod with specified id doesn't belong to the zone " + dcId);
+            ex.addProxyObject(pod, podId, "podId");
             ex.addProxyObject(zone, dcId, "dcId");
             throw ex;
         }
-        
+
 
         // Verify cluster information and create a new cluster if needed
         if (clusterName == null || clusterName.isEmpty()) {
@@ -424,82 +425,102 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             cluster = _clusterDao.persist(cluster);
         } catch (Exception e) {
             // no longer tolerate exception during the cluster creation phase
-        	CloudRuntimeException ex = new CloudRuntimeException("Unable to create cluster " + clusterName + " in pod and data center with specified ids", e);
+            CloudRuntimeException ex = new CloudRuntimeException("Unable to create cluster " + clusterName + " in pod and data center with specified ids", e);
             // Get the pod VO object's table name.
-        	ex.addProxyObject(pod, podId, "podId");
+            ex.addProxyObject(pod, podId, "podId");
             ex.addProxyObject(zone, dcId, "dcId");
             throw ex;
         }
         clusterId = cluster.getId();
         result.add(cluster);
-        
+
+        // Check if we're associating a Cisco Nexus VSM with a vmware cluster.
         if (hypervisorType == HypervisorType.VMware &&
-        		Boolean.parseBoolean(_configDao.getValue(Config.VmwareUseNexusVSwitch.toString()))) {
-        	String vsmIp = cmd.getVSMIpaddress();
+                Boolean.parseBoolean(_configDao.getValue(Config.VmwareUseNexusVSwitch.toString()))) {
+            String vsmIp = cmd.getVSMIpaddress();
             String vsmUser = cmd.getVSMUsername();
             String vsmPassword = cmd.getVSMPassword();
 
-        	if(vsmIp != null && vsmUser != null && vsmPassword != null) {
-	            NetconfHelper netconfClient;
-	            try {
-	                netconfClient = new NetconfHelper(vsmIp, vsmUser, vsmPassword);
-	                netconfClient.disconnect();
-	            } catch (CloudRuntimeException e) {
-	                String msg = "Invalid credentials supplied for user " + vsmUser + " for Cisco Nexus 1000v VSM at " + vsmIp;
-	                s_logger.error(msg);
-		            _clusterDao.remove(clusterId);
-	                throw new CloudRuntimeException(msg);
-	            }
-	            // persist credentials to database
-	            CiscoNexusVSMDeviceVO vsm = new CiscoNexusVSMDeviceVO(vsmIp, vsmUser, vsmPassword);
-	            
-	            Transaction txn = Transaction.currentTxn();
-	            try {
-	                txn.start();
-	                vsm = _vsmDao.persist(vsm);
-	                txn.commit();
-	            } catch (Exception e) {
-	                txn.rollback();	                
-	                s_logger.error("Failed to persist Cisco Nexus 1000v VSM details to database. Exception: " + e.getMessage());
-	                // Removing the cluster record which was added already because the persistence of Nexus VSM credentials has failed. 
-		            _clusterDao.remove(clusterId);
-	                throw new CloudRuntimeException(e.getMessage());
-	            }
-	            
-	            ClusterVSMMapVO connectorObj = new ClusterVSMMapVO(clusterId, vsm.getId());
-	            txn = Transaction.currentTxn();
-	            try {
-	                txn.start();
-	                _clusterVSMDao.persist(connectorObj);
-	                txn.commit();
-	            } catch (Exception e) {
-	                txn.rollback();
-	                s_logger.error("Failed to associate Cisco Nexus 1000v VSM with cluster: " + clusterName + ". Exception: " + e.getMessage());
-	                _clusterDao.remove(clusterId);
-	                throw new CloudRuntimeException(e.getMessage());
-	            }
-        	} else {
-        		String msg;
-        		msg = "The global parameter " + Config.VmwareUseNexusVSwitch.toString() + 
-        				" is set to \"true\". Following mandatory parameters are not specified. ";
-        		if(vsmIp == null) {
-        			msg += "vsmipaddress: Management IP address of Cisco Nexus 1000v dvSwitch. "; 
-        		} 
-        		if(vsmUser == null) {
-        			msg += "vsmusername: Name of a user account with admin privileges over Cisco Nexus 1000v dvSwitch. ";
-        		}
-        		if(vsmPassword == null) {
-        			if(vsmUser != null) {
-        				msg += "vsmpassword: Password of user account " + vsmUser + ". ";
-        			} else {
-        				msg += "vsmpassword: Password of user account with admin privileges over Cisco Nexus 1000v dvSwitch. ";        				
-        			}
-        		}
-        		s_logger.error(msg);
-        		// Cleaning up the cluster record as addCluster operation failed because Nexus dvSwitch credentials are supplied.
-	            _clusterDao.remove(clusterId);
-        		throw new CloudRuntimeException(msg);
-        	}
+            if(vsmIp != null && vsmUser != null && vsmPassword != null) {
+                NetconfHelper netconfClient;
+                try {
+                    netconfClient = new NetconfHelper(vsmIp, vsmUser, vsmPassword);
+                    netconfClient.disconnect();
+                } catch (CloudRuntimeException e) {
+                    String msg = "Invalid credentials supplied for user " + vsmUser + " for Cisco Nexus 1000v VSM at " + vsmIp;
+                    s_logger.error(msg);
+                    _clusterDao.remove(clusterId);
+                    throw new CloudRuntimeException(msg);
+                }
+
+                Transaction txn;
+
+                // If VSM already exists and is mapped to a cluster, fail this operation.
+                CiscoNexusVSMDeviceVO vsm = _vsmDao.getVSMbyIpaddress(vsmIp);
+                if(vsm != null) {
+                    List<ClusterVSMMapVO> clusterList = _clusterVSMDao.listByVSMId(vsm.getId());
+                    if (clusterList != null && !clusterList.isEmpty()) {
+                        s_logger.error("Failed to add cluster: specified Nexus VSM is already associated with another cluster");
+                        _clusterDao.remove(clusterId);
+                        ResourceInUseException ex = new ResourceInUseException("Failed to add cluster: specified Nexus VSM is already associated with another cluster with specified Id");
+                        ex.addProxyObject("cluster", clusterList.get(0).getClusterId(), "clusterId");
+                        throw ex;
+                    }
+                }
+                // persist credentials to database if the VSM entry is not already in the db.
+                if (_vsmDao.getVSMbyIpaddress(vsmIp) == null) {
+                    vsm = new CiscoNexusVSMDeviceVO(vsmIp, vsmUser, vsmPassword);
+                    txn = Transaction.currentTxn();
+                    try {
+                        txn.start();
+                        vsm = _vsmDao.persist(vsm);
+                        txn.commit();
+                    } catch (Exception e) {
+                        txn.rollback();
+                        s_logger.error("Failed to persist Cisco Nexus 1000v VSM details to database. Exception: " + e.getMessage());
+                        // Removing the cluster record which was added already because the persistence of Nexus VSM credentials has failed.
+                        _clusterDao.remove(clusterId);
+                        throw new CloudRuntimeException(e.getMessage());
+                    }
+                }
+                // Create a mapping between the cluster and the vsm.
+                vsm = _vsmDao.getVSMbyIpaddress(vsmIp);
+                if (vsm != null) {
+                    ClusterVSMMapVO connectorObj = new ClusterVSMMapVO(clusterId, vsm.getId());
+                    txn = Transaction.currentTxn();
+                    try {
+                        txn.start();
+                        _clusterVSMDao.persist(connectorObj);
+                        txn.commit();
+                    } catch (Exception e) {
+                        txn.rollback();
+                        s_logger.error("Failed to associate Cisco Nexus 1000v VSM with cluster: " + clusterName + ". Exception: " + e.getMessage());
+                        _clusterDao.remove(clusterId);
+                        throw new CloudRuntimeException(e.getMessage());
+                    }
+                }
+            } else {
+                String msg;
+                msg = "The global parameter " + Config.VmwareUseNexusVSwitch.toString() +
+                        " is set to \"true\". Following mandatory parameters are not specified. ";
+                if(vsmIp == null) {
+                    msg += "vsmipaddress: Management IP address of Cisco Nexus 1000v dvSwitch. ";
+                }
+                if(vsmUser == null) {
+                    msg += "vsmusername: Name of a user account with admin privileges over Cisco Nexus 1000v dvSwitch. ";
+                }
+                if(vsmPassword == null) {
+                    if(vsmUser != null) {
+                        msg += "vsmpassword: Password of user account " + vsmUser + ". ";
+                    } else {
+                        msg += "vsmpassword: Password of user account with admin privileges over Cisco Nexus 1000v dvSwitch. ";
+                    }
+                }
+                s_logger.error(msg);
+                // Cleaning up the cluster record as addCluster operation failed because Nexus dvSwitch credentials are supplied.
+                _clusterDao.remove(clusterId);
+                throw new CloudRuntimeException(msg);
+            }
         }
 
         if (clusterType == Cluster.ClusterType.CloudManaged) {
@@ -532,7 +553,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             List<HostVO> hosts = new ArrayList<HostVO>();
             Map<? extends ServerResource, Map<String, String>> resources = null;
             resources = discoverer.find(dcId, podId, clusterId, uri, username, password, null);
-            
+
             if (resources != null) {
                 for (Map.Entry<? extends ServerResource, Map<String, String>> entry : resources.entrySet()) {
                     ServerResource resource = entry.getKey();
@@ -596,15 +617,15 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         if (clusterId != null) {
             ClusterVO cluster = _clusterDao.findById(clusterId);
             if (cluster == null) {
-            	InvalidParameterValueException ex = new InvalidParameterValueException("can not find cluster for specified clusterId");
-            	ex.addProxyObject(cluster, clusterId, "clusterId");
+                InvalidParameterValueException ex = new InvalidParameterValueException("can not find cluster for specified clusterId");
+                ex.addProxyObject(cluster, clusterId, "clusterId");
                 throw ex;
             } else {
                 if (cluster.getGuid() == null) {
                     List<HostVO> hosts = listAllHostsInCluster(clusterId);
                     if (!hosts.isEmpty()) {
-                    	CloudRuntimeException ex = new CloudRuntimeException("Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up");
-                    	ex.addProxyObject(cluster, clusterId, "clusterId");
+                        CloudRuntimeException ex = new CloudRuntimeException("Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up");
+                        ex.addProxyObject(cluster, clusterId, "clusterId");
                         throw ex;
                     }
                 }
@@ -620,7 +641,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         String url = cmd.getUrl();
         return discoverHostsFull(dcId, null, null, null, url, null, null, "SecondaryStorage", null, null);
     }
-    
+
     @Override
     public Swift discoverSwift(AddSwiftCmd cmd) throws DiscoveryException {
         return _swiftMgr.addSwift(cmd);
@@ -643,22 +664,22 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
 
         Account account = UserContext.current().getCaller();
         if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
-        	PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, Zone with specified id is currently disabled");
-        	ex.addProxyObject(zone, dcId, "dcId");
+            PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, Zone with specified id is currently disabled");
+            ex.addProxyObject(zone, dcId, "dcId");
             throw ex;
         }
 
-        
+
         // Check if the pod exists in the system
         if (podId != null) {
             HostPodVO pod = _podDao.findById(podId);
             if (pod == null) {
-            	throw new InvalidParameterValueException("Can't find pod by id " + podId);
+                throw new InvalidParameterValueException("Can't find pod by id " + podId);
             }
             // check if pod belongs to the zone            
             if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) {
-            	InvalidParameterValueException ex = new InvalidParameterValueException("Pod with specified podId" + podId + " doesn't belong to the zone with specified zoneId" + dcId);
-            	ex.addProxyObject(pod, podId, "podId"); 
+                InvalidParameterValueException ex = new InvalidParameterValueException("Pod with specified podId" + podId + " doesn't belong to the zone with specified zoneId" + dcId);
+                ex.addProxyObject(pod, podId, "podId");
                 ex.addProxyObject(zone, dcId, "dcId");
                 throw ex;
             }
@@ -681,20 +702,20 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             if (_clusterDao.findById(clusterId) == null) {
                 throw new InvalidParameterValueException("Can't find cluster by id " + clusterId);
             }
-            
+
             if(hypervisorType.equalsIgnoreCase(HypervisorType.VMware.toString())) {
-	            // VMware only allows adding host to an existing cluster, as we already have a lot of information
-	            // in cluster object, to simplify user input, we will construct neccessary information here
-	            Map<String, String> clusterDetails = this._clusterDetailsDao.findDetails(clusterId);
-	            username = clusterDetails.get("username");
-	            assert(username != null);
-	            
-	            password = clusterDetails.get("password");
-	            assert(password != null);
-	            
+                // VMware only allows adding host to an existing cluster, as we already have a lot of information
+                // in cluster object, to simplify user input, we will construct neccessary information here
+                Map<String, String> clusterDetails = this._clusterDetailsDao.findDetails(clusterId);
+                username = clusterDetails.get("username");
+                assert(username != null);
+
+                password = clusterDetails.get("password");
+                assert(password != null);
+
                 try {
                     uri = new URI(UriUtils.encodeURIComponent(url));
-                
+
                     url = clusterDetails.get("url") + "/" + uri.getHost();
                 } catch (URISyntaxException e) {
                     throw new InvalidParameterValueException(url + " is not a valid uri");
@@ -705,17 +726,17 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         if (clusterName != null) {
             HostPodVO pod = _podDao.findById(podId);
             if (pod == null) {
-            	throw new InvalidParameterValueException("Can't find pod by id " + podId);
+                throw new InvalidParameterValueException("Can't find pod by id " + podId);
             }
-       	    ClusterVO cluster = new ClusterVO(dcId, podId, clusterName);
+            ClusterVO cluster = new ClusterVO(dcId, podId, clusterName);
             cluster.setHypervisorType(hypervisorType);
             try {
                 cluster = _clusterDao.persist(cluster);
             } catch (Exception e) {
                 cluster = _clusterDao.findBy(clusterName, podId);
                 if (cluster == null) {
-                	CloudRuntimeException ex = new CloudRuntimeException("Unable to create cluster " + clusterName + " in pod with specified podId and data center with specified dcID", e);
-                	ex.addProxyObject(pod, podId, "podId"); 
+                    CloudRuntimeException ex = new CloudRuntimeException("Unable to create cluster " + clusterName + " in pod with specified podId and data center with specified dcID", e);
+                    ex.addProxyObject(pod, podId, "podId");
                     ex.addProxyObject(zone, dcId, "dcId");
                     throw ex;   
                 }
@@ -756,12 +777,12 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             try {
                 resources = discoverer.find(dcId, podId, clusterId, uri, username, password, hostTags);
             } catch(DiscoveryException e) {
-            	throw e;
+                throw e;
             } 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);
-            
+
             if (resources != null) {
                 for (Map.Entry<? extends ServerResource, Map<String, String>> entry : resources.entrySet()) {
                     ServerResource resource = entry.getKey();
@@ -786,7 +807,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                         }
                         return null;
                     }
-                    
+
                     HostVO host = (HostVO)createHostAndAgent(resource, entry.getValue(), true, hostTags, false);
                     if (host != null) {
                         hosts.add(host);
@@ -821,7 +842,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             throw new InvalidParameterValueException("Host with id " + hostId + " doesn't exist");            
         }
         _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), host.getDataCenterId());
-        
+
         /*
          * TODO: check current agent status and updateAgentStatus to removed. If it was already removed, that means
          * someone is deleting host concurrently, return. And consider the situation of CloudStack shutdown during delete.
@@ -832,21 +853,21 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         // Get storage pool host mappings here because they can be removed as a part of handleDisconnect later
         //TODO: find out the bad boy, what's a buggy logic!
         List<StoragePoolHostVO> pools = _storagePoolHostDao.listByHostIdIncludingRemoved(hostId);
-        
+
         ResourceStateAdapter.DeleteHostAnswer answer = (ResourceStateAdapter.DeleteHostAnswer) dispatchToStateAdapters(ResourceStateAdapter.Event.DELETE_HOST, false, host, new Boolean(isForced), new Boolean(isForceDeleteStorage));
 
         if (answer == null) {
-        	throw new CloudRuntimeException("No resource adapter respond to DELETE_HOST event for " + host.getName() + " id = " + hostId + ", hypervisorType is " + host.getHypervisorType() + ", host type is " + host.getType());
+            throw new CloudRuntimeException("No resource adapter respond to DELETE_HOST event for " + host.getName() + " id = " + hostId + ", hypervisorType is " + host.getHypervisorType() + ", host type is " + host.getType());
         }
-        
+
         if (answer.getIsException()) {
             return false;
         }
-        
+
         if (!answer.getIsContinue()) {
             return true;
         }
-        
+
         Transaction txn = Transaction.currentTxn();
         txn.start();
 
@@ -871,12 +892,12 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             }
         }
 
-		try {
-			resourceStateTransitTo(host, ResourceState.Event.DeleteHost, _nodeId);
-		} catch (NoTransitionException e) {
-			s_logger.debug("Cannot transmit host " + host.getId() + "to Enabled state", e);
-		}
-        
+        try {
+            resourceStateTransitTo(host, ResourceState.Event.DeleteHost, _nodeId);
+        } catch (NoTransitionException e) {
+            s_logger.debug("Cannot transmit host " + host.getId() + "to Enabled state", e);
+        }
+
         // Delete the associated entries in host ref table
         _storagePoolHostDao.deletePrimaryRecordsForHost(hostId);
 
@@ -902,7 +923,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         txn.commit();
         return true;
     }
-    
+
     @Override
     public boolean deleteHost(long hostId, boolean isForced, boolean isForceDeleteStorage) {
         try {
@@ -913,7 +934,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         } catch (AgentUnavailableException e) {
             return false;
         }
-        
+
         return doDeleteHost(hostId, isForced, isForceDeleteStorage);
     }
 
@@ -933,7 +954,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             }
 
             Hypervisor.HypervisorType hypervisorType = cluster.getHypervisorType();
-            
+
             List<HostVO> hosts = listAllHostsInCluster(cmd.getId());
             if (hosts.size() > 0) {
                 if (s_logger.isDebugEnabled()) {
@@ -942,7 +963,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 txn.rollback();
                 throw new CloudRuntimeException("Cluster: " + cmd.getId() + " cannot be removed. Cluster still has hosts");
             }
-            
+
             //don't allow to remove the cluster if it has non-removed storage pools
             List<StoragePoolVO> storagePools = _storagePoolDao.listPoolsByCluster(cmd.getId());
             if (storagePools.size() > 0) {
@@ -958,19 +979,19 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 // If this cluster is of type vmware, and if the nexus vswitch global parameter setting is turned
                 // on, remove the row in cluster_vsm_map for this cluster id.
                 if (hypervisorType == HypervisorType.VMware &&
-                		Boolean.parseBoolean(_configDao.getValue(Config.VmwareUseNexusVSwitch.toString()))) {
-                	_clusterVSMMapDao.removeByClusterId(cmd.getId());
+                        Boolean.parseBoolean(_configDao.getValue(Config.VmwareUseNexusVSwitch.toString()))) {
+                    _clusterVSMMapDao.removeByClusterId(cmd.getId());
                 }
             }
 
             txn.commit();
             return true;
         } catch(CloudRuntimeException e){
-        	throw e;
+            throw e;
         } catch (Throwable t) {
-        	s_logger.error("Unable to delete cluster: " + cmd.getId(), t);
-        	txn.rollback();
-        	return false;
+            s_logger.error("Unable to delete cluster: " + cmd.getId(), t);
+            txn.rollback();
+            return false;
         }
     }
 
@@ -1025,7 +1046,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 doUpdate = true;
             }
         }
-        
+
         Managed.ManagedState newManagedState = null;
         Managed.ManagedState oldManagedState = cluster.getManagedState();
         if (managedstate != null && !managedstate.isEmpty()) {
@@ -1041,7 +1062,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 doUpdate = true;
             }
         }
-        
+
         if (doUpdate) {
             Transaction txn = Transaction.currentTxn();
             try {
@@ -1053,7 +1074,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 throw new CloudRuntimeException("Failed to update cluster. Please contact Cloud Support.");
             }
         }
-        
+
         if( newManagedState != null && !newManagedState.equals(oldManagedState)) {
             Transaction txn = Transaction.currentTxn();
             if( newManagedState.equals(Managed.ManagedState.Unmanaged) ) {
@@ -1069,12 +1090,12 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                                 && !host.getStatus().equals(Status.Up) && !host.getStatus().equals(Status.Alert) ) {
                             String msg = "host " + host.getPrivateIpAddress() + " should not be in " + host.getStatus().toString() + " status";
                             throw new CloudRuntimeException("PrepareUnmanaged Failed due to " + msg);                                   
-                         }
+                        }
                     }
-                    
+
                     for( HostVO host : hosts ) {
                         if ( host.getStatus().equals(Status.Up )) {
-                        	umanageHost(host.getId());
+                            umanageHost(host.getId());
                         }
                     }
                     int retry = 10;
@@ -1113,9 +1134,9 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 _clusterDao.update(cluster.getId(), cluster);
                 txn.commit();
             }
-            
+
         }
-        
+
         return cluster;
     }
 
@@ -1149,7 +1170,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
 
         return (_agentMgr.reconnect(hostId) ? host : null);
     }
-    
+
     @Override
     public boolean resourceStateTransitTo(Host host, ResourceState.Event event, long msId) throws NoTransitionException {
         ResourceState currentState = host.getResourceState();
@@ -1157,36 +1178,36 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         if (nextState == null) {
             throw new NoTransitionException("No next resource state found for current state =" + currentState + " event =" + event);
         }
-        
+
         // TO DO - Make it more granular and have better conversion into capacity type
 
         if(host.getType() == Type.Routing && host.getClusterId() != null){
-        	AllocationState capacityState =  _configMgr.findClusterAllocationState(ApiDBUtils.findClusterById(host.getClusterId()));
-        	if (capacityState == AllocationState.Enabled && nextState != ResourceState.Enabled){
-        		capacityState = AllocationState.Disabled;
-        	}
-        	_capacityDao.updateCapacityState(null, null, null, host.getId(), capacityState.toString());
+            AllocationState capacityState =  _configMgr.findClusterAllocationState(ApiDBUtils.findClusterById(host.getClusterId()));
+            if (capacityState == AllocationState.Enabled && nextState != ResourceState.Enabled){
+                capacityState = AllocationState.Disabled;
+            }
+            _capacityDao.updateCapacityState(null, null, null, host.getId(), capacityState.toString());
         }
         return _hostDao.updateResourceState(currentState, event, nextState, host);
     }
-    
+
     private boolean doMaintain(final long hostId) {
         HostVO host = _hostDao.findById(hostId);
         MaintainAnswer answer = (MaintainAnswer) _agentMgr.easySend(hostId, new MaintainCommand());
         if (answer == null || !answer.getResult()) {
             s_logger.warn("Unable to send MaintainCommand to host: " + hostId);
         }
-        
+
         try {
-        	resourceStateTransitTo(host, ResourceState.Event.AdminAskMaintenace, _nodeId);
+            resourceStateTransitTo(host, ResourceState.Event.AdminAskMaintenace, _nodeId);
         } catch (NoTransitionException e) {
             String err = "Cannot transimit resource state of host " + host.getId() + " to " + ResourceState.Maintenance;
             s_logger.debug(err, e);
             throw new CloudRuntimeException(err + e.getMessage());
         }
-        
+
         _agentMgr.pullAgentToMaintenance(hostId);
-        
+
         /*TODO: move below to listener */
         if (host.getType() == Host.Type.Routing) {
 
@@ -1208,16 +1229,17 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
 
         return true;
     }
-    
+
+    @Override
     public boolean maintain(final long hostId) throws AgentUnavailableException {
         Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.AdminAskMaintenace);
         if (result != null) {
             return result;
         }
-        
+
         return doMaintain(hostId);
     }
-    
+
     @Override
     public Host maintain(PrepareForMaintenanceCmd cmd) {
         Long hostId = cmd.getId();
@@ -1259,16 +1281,16 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         if (host == null) {
             throw new InvalidParameterValueException("Host with id " + hostId + " doesn't exist");
         }
-        
-		if (cmd.getAllocationState() != null) {
-			ResourceState.Event resourceEvent = ResourceState.Event.toEvent(cmd.getAllocationState());
-			if (resourceEvent != ResourceState.Event.Enable && resourceEvent != ResourceState.Event.Disable) {
-				throw new CloudRuntimeException("Invalid allocation state:" + cmd.getAllocationState() + ", only Enable/Disable are allowed");
-			}
-			
-			resourceStateTransitTo(host, resourceEvent, _nodeId);
-		}
-        
+
+        if (cmd.getAllocationState() != null) {
+            ResourceState.Event resourceEvent = ResourceState.Event.toEvent(cmd.getAllocationState());
+            if (resourceEvent != ResourceState.Event.Enable && resourceEvent != ResourceState.Event.Disable) {
+                throw new CloudRuntimeException("Invalid allocation state:" + cmd.getAllocationState() + ", only Enable/Disable are allowed");
+            }
+
+            resourceStateTransitTo(host, resourceEvent, _nodeId);
+        }
+
         if (guestOSCategoryId != null) {
             // Verify that the guest OS Category exists
             if (guestOSCategoryId > 0) {
@@ -1289,7 +1311,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             }
             _hostDetailsDao.persist(hostId, hostDetails);
         }
-        
+
         List<String> hostTags = cmd.getHostTags();
         if (hostTags != null) {
             if(s_logger.isDebugEnabled()){
@@ -1297,10 +1319,10 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             }
             _hostTagsDao.persist(hostId, hostTags);
         }
-        
+
         String url = cmd.getUrl();
         if (url != null) {
-        	_storageMgr.updateSecondaryStorage(cmd.getId(), cmd.getUrl());
+            _storageMgr.updateSecondaryStorage(cmd.getId(), cmd.getUrl());
         }
 
         HostVO updatedHost = _hostDao.findById(hostId);
@@ -1333,392 +1355,392 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
     public String getName() {
         return _name;
     }
-    
+
     @Override
     public List<HypervisorType> getSupportedHypervisorTypes(long zoneId, boolean forVirtualRouter, Long podId) {
         List<HypervisorType> hypervisorTypes = new ArrayList<HypervisorType>();
-        
+
         List<ClusterVO> clustersForZone = new ArrayList<ClusterVO>();
         if (podId != null) {
-        	clustersForZone = _clusterDao.listByPodId(podId);
+            clustersForZone = _clusterDao.listByPodId(podId);
         } else {
-        	clustersForZone = _clusterDao.listByZoneId(zoneId);
+            clustersForZone = _clusterDao.listByZoneId(zoneId);
         }
-        
+
         for (ClusterVO cluster : clustersForZone) {
-        	HypervisorType hType = cluster.getHypervisorType();
-        	if (!forVirtualRouter || (forVirtualRouter && hType != HypervisorType.BareMetal && hType != HypervisorType.Ovm)) {
+            HypervisorType hType = cluster.getHypervisorType();
+            if (!forVirtualRouter || (forVirtualRouter && hType != HypervisorType.BareMetal && hType != HypervisorType.Ovm)) {
                 hypervisorTypes.add(hType);
-        	}
+            }
         }
-        
+
         return hypervisorTypes;
     }
-    
+
     @Override
     public HypervisorType getDefaultHypervisor(long zoneId) {
-    	HypervisorType defaultHyper = HypervisorType.None;
-    	if (_defaultSystemVMHypervisor != HypervisorType.None) {
-    		defaultHyper = _defaultSystemVMHypervisor;
-    	}
-    	
-    	DataCenterVO dc = _dcDao.findById(zoneId);
-    	if (dc == null) {
-    		return HypervisorType.None;
-    	}
-    	_dcDao.loadDetails(dc);
-    	String defaultHypervisorInZone = dc.getDetail("defaultSystemVMHypervisorType");
-    	if (defaultHypervisorInZone != null) {
-    		defaultHyper = HypervisorType.getType(defaultHypervisorInZone);
-    	}
-    	
-    	List<VMTemplateVO> systemTemplates = _templateDao.listAllSystemVMTemplates();
-    	boolean isValid = false;
-    	for (VMTemplateVO template : systemTemplates) {
-    		if (template.getHypervisorType() == defaultHyper) {
-    			isValid = true;
-    			break;
-    		}
-    	}
-    	
-    	if (isValid) {
-    		List<ClusterVO> clusters = _clusterDao.listByDcHyType(zoneId, defaultHyper.toString());
-    		if (clusters.size() <= 0) {
-    			isValid = false;
-    		}
-    	}
-    	
-    	if (isValid) {
-    		return defaultHyper;
-    	} else {
-    		return HypervisorType.None;
-    	}
-    }
-    
+        HypervisorType defaultHyper = HypervisorType.None;
+        if (_defaultSystemVMHypervisor != HypervisorType.None) {
+            defaultHyper = _defaultSystemVMHypervisor;
+        }
+
+        DataCenterVO dc = _dcDao.findById(zoneId);
+        if (dc == null) {
+            return HypervisorType.None;
+        }
+        _dcDao.loadDetails(dc);
+        String defaultHypervisorInZone = dc.getDetail("defaultSystemVMHypervisorType");
+        if (defaultHypervisorInZone != null) {
+            defaultHyper = HypervisorType.getType(defaultHypervisorInZone);
+        }
+
+        List<VMTemplateVO> systemTemplates = _templateDao.listAllSystemVMTemplates();
+        boolean isValid = false;
+        for (VMTemplateVO template : systemTemplates) {
+            if (template.getHypervisorType() == defaultHyper) {
+                isValid = true;
+                break;
+            }
+        }
+
+        if (isValid) {
+            List<ClusterVO> clusters = _clusterDao.listByDcHyType(zoneId, defaultHyper.toString());
+            if (clusters.size() <= 0) {
+                isValid = false;
+            }
+        }
+
+        if (isValid) {
+            return defaultHyper;
+        } else {
+            return HypervisorType.None;
+        }
+    }
+
     @Override
     public HypervisorType getAvailableHypervisor(long zoneId) {
-    	  HypervisorType defaultHype = getDefaultHypervisor(zoneId);
-          if (defaultHype == HypervisorType.None) {
-          	List<HypervisorType> supportedHypes = getSupportedHypervisorTypes(zoneId, false, null);
-          	if (supportedHypes.size() > 0) {
-          		defaultHype = supportedHypes.get(0);
-          	}
-          }
-          
-          if (defaultHype == HypervisorType.None) {
-          	defaultHype = HypervisorType.Any;
-          }
-          return defaultHype;
-    }
-
-	@Override
-	public void registerResourceStateAdapter(String name, ResourceStateAdapter adapter) {
-		if (_resourceStateAdapters.get(name) != null) {
-			throw new CloudRuntimeException(name + " has registered");
-		}
-		
-		synchronized (_resourceStateAdapters) {
-			_resourceStateAdapters.put(name, adapter);
-		}
-	}
-
-	@Override
+        HypervisorType defaultHype = getDefaultHypervisor(zoneId);
+        if (defaultHype == HypervisorType.None) {
+            List<HypervisorType> supportedHypes = getSupportedHypervisorTypes(zoneId, false, null);
+            if (supportedHypes.size() > 0) {
+                defaultHype = supportedHypes.get(0);
+            }
+        }
+
+        if (defaultHype == HypervisorType.None) {
+            defaultHype = HypervisorType.Any;
+        }
+        return defaultHype;
+    }
+
+    @Override
+    public void registerResourceStateAdapter(String name, ResourceStateAdapter adapter) {
+        if (_resourceStateAdapters.get(name) != null) {
+            throw new CloudRuntimeException(name + " has registered");
+        }
+
+        synchronized (_resourceStateAdapters) {
+            _resourceStateAdapters.put(name, adapter);
+        }
+    }
+
+    @Override
     public void unregisterResourceStateAdapter(String name) {
         synchronized (_resourceStateAdapters) {
             _resourceStateAdapters.remove(name);
         }   
     }
-	
-	private Object dispatchToStateAdapters(ResourceStateAdapter.Event event, boolean singleTaker, Object... args) {
-		synchronized (_resourceStateAdapters) {
-			Iterator it = _resourceStateAdapters.entrySet().iterator();
-			Object result = null;
-			while (it.hasNext()) {
-				Map.Entry<String, ResourceStateAdapter> item = (Map.Entry<String, ResourceStateAdapter>) it.next();
-				ResourceStateAdapter adapter = item.getValue();
-				
-				String msg = new String("Dispatching resource state event " + event + " to " + item.getKey());
-				s_logger.debug(msg);
-				
-				if (event == ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED) {
-					result = adapter.createHostVOForConnectedAgent((HostVO) args[0], (StartupCommand[]) args[1]);
-					if (result != null && singleTaker) {
-						break;
-					}
-				} else if (event == ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT) {
-					result = adapter.createHostVOForDirectConnectAgent((HostVO) args[0], (StartupCommand[]) args[1], (ServerResource) args[2],
-					        (Map<String, String>) args[3], (List<String>) args[4]);
-					if (result != null && singleTaker) {
-						break;
-					}
-				} else if (event == ResourceStateAdapter.Event.DELETE_HOST) {
-					try {
-						result = adapter.deleteHost((HostVO) args[0], (Boolean) args[1], (Boolean) args[2]);
-						if (result != null) {
-							break;
-						}
-					} catch (UnableDeleteHostException e) {
-						s_logger.debug("Adapter " + adapter.getName() + " says unable to delete host", e);
-						result = new ResourceStateAdapter.DeleteHostAnswer(false, true);
-					}
-				} else {
-					throw new CloudRuntimeException("Unknown resource state event:" + event);
-				}
-			}
-
-			return result;
-		}
-	}
-
-	@Override
-	public void checkCIDR(HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask) throws IllegalArgumentException {
-		if (serverPrivateIP == null) {
-			return;
-		}
-		// Get the CIDR address and CIDR size
-		String cidrAddress = pod.getCidrAddress();
-		long cidrSize = pod.getCidrSize();
-
-		// If the server's private IP address is not in the same subnet as the
-		// pod's CIDR, return false
-		String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize);
-		String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask);
-		if (!cidrSubnet.equals(serverSubnet)) {
-			s_logger.warn("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName()
-			        + " and zone: " + dc.getName());
-			throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: "
-			        + pod.getName() + " and zone: " + dc.getName());
-		}
-
-		// If the server's private netmask is less inclusive than the pod's CIDR
-		// netmask, return false
-		String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize);
-		long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask);
-		long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask);
-		if (serverNetmaskNumeric > cidrNetmaskNumeric) {
-			throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: "
-			        + pod.getName() + " and zone: " + dc.getName());
-		}
-
-	}
-
-	private boolean checkCIDR(HostPodVO pod, String serverPrivateIP, String serverPrivateNetmask) {
-		if (serverPrivateIP == null) {
-			return true;
-		}
-		// Get the CIDR address and CIDR size
-		String cidrAddress = pod.getCidrAddress();
-		long cidrSize = pod.getCidrSize();
-
-		// If the server's private IP address is not in the same subnet as the
-		// pod's CIDR, return false
-		String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize);
-		String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask);
-		if (!cidrSubnet.equals(serverSubnet)) {
-			return false;
-		}
-
-		// If the server's private netmask is less inclusive than the pod's CIDR
-		// netmask, return false
-		String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize);
-		long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask);
-		long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask);
-		if (serverNetmaskNumeric > cidrNetmaskNumeric) {
-			return false;
-		}
-		return true;
-	}
-	 
-	protected HostVO createHostVO(StartupCommand[] cmds, ServerResource resource, Map<String, String> details, List<String> hostTags,
-	        ResourceStateAdapter.Event stateEvent) {
-		StartupCommand startup = cmds[0];
-		HostVO host = findHostByGuid(startup.getGuid());
-		boolean isNew = false;
-		if (host == null) {
-			host = findHostByGuid(startup.getGuidWithoutResource());
-		}
-		if (host == null) {
-			host = new HostVO(startup.getGuid());
-			isNew = true;
-		}
-
-		String dataCenter = startup.getDataCenter();
-		String pod = startup.getPod();
-		String cluster = startup.getCluster();
-
-		if (pod != null && dataCenter != null && pod.equalsIgnoreCase("default") && dataCenter.equalsIgnoreCase("default")) {
-			List<HostPodVO> pods = _podDao.listAllIncludingRemoved();
-			for (HostPodVO hpv : pods) {
-				if (checkCIDR(hpv, startup.getPrivateIpAddress(), startup.getPrivateNetmask())) {
-					pod = hpv.getName();
-					dataCenter = _dcDao.findById(hpv.getDataCenterId()).getName();
-					break;
-				}
-			}
-		}
-
-		long dcId = -1;
-		DataCenterVO dc = _dcDao.findByName(dataCenter);
-		if (dc == null) {
-			try {
-				dcId = Long.parseLong(dataCenter);
-				dc = _dcDao.findById(dcId);
-			} catch (final NumberFormatException e) {
-			}
-		}
-		if (dc == null) {
-			throw new IllegalArgumentException("Host " + startup.getPrivateIpAddress() + " sent incorrect data center: " + dataCenter);
-		}
-		dcId = dc.getId();
-
-		HostPodVO p = _podDao.findByName(pod, dcId);
-		if (p == null) {
-			try {
-				final long podId = Long.parseLong(pod);
-				p = _podDao.findById(podId);
-			} catch (final NumberFormatException e) {
-			}
-		}
-		/*
-		 * ResourceStateAdapter is responsible for throwing Exception if Pod is
-		 * null and non-null is required. for example, XcpServerDiscoever.
-		 * Others, like PxeServer, ExternalFireware don't require Pod
-		 */
-		Long podId = (p == null ? null : p.getId());
-
-		Long clusterId = null;
-		if (cluster != null) {
-			try {
-				clusterId = Long.valueOf(cluster);
-			} catch (NumberFormatException e) {
-				ClusterVO c = _clusterDao.findBy(cluster, podId);
-				if (c == null) {
-					c = new ClusterVO(dcId, podId, cluster);
-					c = _clusterDao.persist(c);
-				}
-				clusterId = c.getId();
-			}
-		}
-
-		host.setDataCenterId(dc.getId());
-		host.setPodId(podId);
-		host.setClusterId(clusterId);
-		host.setPrivateIpAddress(startup.getPrivateIpAddress());
-		host.setPrivateNetmask(startup.getPrivateNetmask());
-		host.setPrivateMacAddress(startup.getPrivateMacAddress());
-		host.setPublicIpAddress(startup.getPublicIpAddress());
-		host.setPublicMacAddress(startup.getPublicMacAddress());
-		host.setPublicNetmask(startup.getPublicNetmask());
-		host.setStorageIpAddress(startup.getStorageIpAddress());
-		host.setStorageMacAddress(startup.getStorageMacAddress());
-		host.setStorageNetmask(startup.getStorageNetmask());
-		host.setVersion(startup.getVersion());
-		host.setName(startup.getName());
-		host.setManagementServerId(_nodeId);
-		host.setStorageUrl(startup.getIqn());
-		host.setLastPinged(System.currentTimeMillis() >> 10);
-		host.setHostTags(hostTags);
-		host.setDetails(details);
-		if (startup.getStorageIpAddressDeux() != null) {
-			host.setStorageIpAddressDeux(startup.getStorageIpAddressDeux());
-			host.setStorageMacAddressDeux(startup.getStorageMacAddressDeux());
-			host.setStorageNetmaskDeux(startup.getStorageNetmaskDeux());
-		}
-		if (resource != null) {
-			/* null when agent is connected agent */
-			host.setResource(resource.getClass().getName());
-		}
-
-		host = (HostVO) dispatchToStateAdapters(stateEvent, true, host, cmds, resource, details, hostTags);
-		if (host == null) {
-			throw new CloudRuntimeException("No resource state adapter response");
-		}
-		
-		if (isNew) {
-			host = _hostDao.persist(host);
-		} else {
-			_hostDao.update(host.getId(), host);
-		}
-
-		try {
-			resourceStateTransitTo(host, ResourceState.Event.InternalCreated, _nodeId);
-			/* Agent goes to Connecting status */
-			_agentMgr.agentStatusTransitTo(host, Status.Event.AgentConnected, _nodeId);
-		} catch (Exception e) {
-			s_logger.debug("Cannot transmit host " + host.getId() + " to Creating state", e);
-			_agentMgr.agentStatusTransitTo(host, Status.Event.Error, _nodeId);
-			try {
-				resourceStateTransitTo(host, ResourceState.Event.Error, _nodeId);
+
+    private Object dispatchToStateAdapters(ResourceStateAdapter.Event event, boolean singleTaker, Object... args) {
+        synchronized (_resourceStateAdapters) {
+            Iterator it = _resourceStateAdapters.entrySet().iterator();
+            Object result = null;
+            while (it.hasNext()) {
+                Map.Entry<String, ResourceStateAdapter> item = (Map.Entry<String, ResourceStateAdapter>) it.next();
+                ResourceStateAdapter adapter = item.getValue();
+
+                String msg = new String("Dispatching resource state event " + event + " to " + item.getKey());
+                s_logger.debug(msg);
+
+                if (event == ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED) {
+                    result = adapter.createHostVOForConnectedAgent((HostVO) args[0], (StartupCommand[]) args[1]);
+                    if (result != null && singleTaker) {
+                        break;
+                    }
+                } else if (event == ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT) {
+                    result = adapter.createHostVOForDirectConnectAgent((HostVO) args[0], (StartupCommand[]) args[1], (ServerResource) args[2],
+                            (Map<String, String>) args[3], (List<String>) args[4]);
+                    if (result != null && singleTaker) {
+                        break;
+                    }
+                } else if (event == ResourceStateAdapter.Event.DELETE_HOST) {
+                    try {
+                        result = adapter.deleteHost((HostVO) args[0], (Boolean) args[1], (Boolean) args[2]);
+                        if (result != null) {
+                            break;
+                        }
+                    } catch (UnableDeleteHostException e) {
+                        s_logger.debug("Adapter " + adapter.getName() + " says unable to delete host", e);
+                        result = new ResourceStateAdapter.DeleteHostAnswer(false, true);
+                    }
+                } else {
+                    throw new CloudRuntimeException("Unknown resource state event:" + event);
+                }
+            }
+
+            return result;
+        }
+    }
+
+    @Override
+    public void checkCIDR(HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask) throws IllegalArgumentException {
+        if (serverPrivateIP == null) {
+            return;
+        }
+        // Get the CIDR address and CIDR size
+        String cidrAddress = pod.getCidrAddress();
+        long cidrSize = pod.getCidrSize();
+
+        // If the server's private IP address is not in the same subnet as the
+        // pod's CIDR, return false
+        String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize);
+        String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask);
+        if (!cidrSubnet.equals(serverSubnet)) {
+            s_logger.warn("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName()
+                    + " and zone: " + dc.getName());
+            throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: "
+                    + pod.getName() + " and zone: " + dc.getName());
+        }
+
+        // If the server's private netmask is less inclusive than the pod's CIDR
+        // netmask, return false
+        String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize);
+        long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask);
+        long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask);
+        if (serverNetmaskNumeric > cidrNetmaskNumeric) {
+            throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: "
+                    + pod.getName() + " and zone: " + dc.getName());
+        }
+
+    }
+
+    private boolean checkCIDR(HostPodVO pod, String serverPrivateIP, String serverPrivateNetmask) {
+        if (serverPrivateIP == null) {
+            return true;
+        }
+        // Get the CIDR address and CIDR size
+        String cidrAddress = pod.getCidrAddress();
+        long cidrSize = pod.getCidrSize();
+
+        // If the server's private IP address is not in the same subnet as the
+        // pod's CIDR, return false
+        String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize);
+        String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask);
+        if (!cidrSubnet.equals(serverSubnet)) {
+            return false;
+        }
+
+        // If the server's private netmask is less inclusive than the pod's CIDR
+        // netmask, return false
+        String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize);
+        long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask);
+        long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask);
+        if (serverNetmaskNumeric > cidrNetmaskNumeric) {
+            return false;
+        }
+        return true;
+    }
+
+    protected HostVO createHostVO(StartupCommand[] cmds, ServerResource resource, Map<String, String> details, List<String> hostTags,
+            ResourceStateAdapter.Event stateEvent) {
+        StartupCommand startup = cmds[0];
+        HostVO host = findHostByGuid(startup.getGuid());
+        boolean isNew = false;
+        if (host == null) {
+            host = findHostByGuid(startup.getGuidWithoutResource());
+        }
+        if (host == null) {
+            host = new HostVO(startup.getGuid());
+            isNew = true;
+        }
+
+        String dataCenter = startup.getDataCenter();
+        String pod = startup.getPod();
+        String cluster = startup.getCluster();
+
+        if (pod != null && dataCenter != null && pod.equalsIgnoreCase("default") && dataCenter.equalsIgnoreCase("default")) {
+            List<HostPodVO> pods = _podDao.listAllIncludingRemoved();
+            for (HostPodVO hpv : pods) {
+                if (checkCIDR(hpv, startup.getPrivateIpAddress(), startup.getPrivateNetmask())) {
+                    pod = hpv.getName();
+                    dataCenter = _dcDao.findById(hpv.getDataCenterId()).getName();
+                    break;
+                }
+            }
+        }
+
+        long dcId = -1;
+        DataCenterVO dc = _dcDao.findByName(dataCenter);
+        if (dc == null) {
+            try {
+                dcId = Long.parseLong(dataCenter);
+                dc = _dcDao.findById(dcId);
+            } catch (final NumberFormatException e) {
+            }
+        }
+        if (dc == null) {
+            throw new IllegalArgumentException("Host " + startup.getPrivateIpAddress() + " sent incorrect data center: " + dataCenter);
+        }
+        dcId = dc.getId();
+
+        HostPodVO p = _podDao.findByName(pod, dcId);
+        if (p == null) {
+            try {
+                final long podId = Long.parseLong(pod);
+                p = _podDao.findById(podId);
+            } catch (final NumberFormatException e) {
+            }
+        }
+        /*
+         * ResourceStateAdapter is responsible for throwing Exception if Pod is
+         * null and non-null is required. for example, XcpServerDiscoever.
+         * Others, like PxeServer, ExternalFireware don't require Pod
+         */
+        Long podId = (p == null ? null : p.getId());
+
+        Long clusterId = null;
+        if (cluster != null) {
+            try {
+                clusterId = Long.valueOf(cluster);
+            } catch (NumberFormatException e) {
+                ClusterVO c = _clusterDao.findBy(cluster, podId);
+                if (c == null) {
+                    c = new ClusterVO(dcId, podId, cluster);
+                    c = _clusterDao.persist(c);
+                }
+                clusterId = c.getId();
+            }
+        }
+
+        host.setDataCenterId(dc.getId());
+        host.setPodId(podId);
+        host.setClusterId(clusterId);
+        host.setPrivateIpAddress(startup.getPrivateIpAddress());
+        host.setPrivateNetmask(startup.getPrivateNetmask());
+        host.setPrivateMacAddress(startup.getPrivateMacAddress());
+        host.setPublicIpAddress(startup.getPublicIpAddress());
+        host.setPublicMacAddress(startup.getPublicMacAddress());
+        host.setPublicNetmask(startup.getPublicNetmask());
+        host.setStorageIpAddress(startup.getStorageIpAddress());
+        host.setStorageMacAddress(startup.getStorageMacAddress());
+        host.setStorageNetmask(startup.getStorageNetmask());
+        host.setVersion(startup.getVersion());
+        host.setName(startup.getName());
+        host.setManagementServerId(_nodeId);
+        host.setStorageUrl(startup.getIqn());
+        host.setLastPinged(System.currentTimeMillis() >> 10);
+        host.setHostTags(hostTags);
+        host.setDetails(details);
+        if (startup.getStorageIpAddressDeux() != null) {
+            host.setStorageIpAddressDeux(startup.getStorageIpAddressDeux());
+            host.setStorageMacAddressDeux(startup.getStorageMacAddressDeux());
+            host.setStorageNetmaskDeux(startup.getStorageNetmaskDeux());
+        }
+        if (resource != null) {
+            /* null when agent is connected agent */
+            host.setResource(resource.getClass().getName());
+        }
+
+        host = (HostVO) dispatchToStateAdapters(stateEvent, true, host, cmds, resource, details, hostTags);
+        if (host == null) {
+            throw new CloudRuntimeException("No resource state adapter response");
+        }
+
+        if (isNew) {
+            host = _hostDao.persist(host);
+        } else {
+            _hostDao.update(host.getId(), host);
+        }
+
+        try {
+            resourceStateTransitTo(host, ResourceState.Event.InternalCreated, _nodeId);
+            /* Agent goes to Connecting status */
+            _agentMgr.agentStatusTransitTo(host, Status.Event.AgentConnected, _nodeId);
+        } catch (Exception e) {
+            s_logger.debug("Cannot transmit host " + host.getId() + " to Creating state", e);
+            _agentMgr.agentStatusTransitTo(host, Status.Event.Error, _nodeId);
+            try {
+                resourceStateTransitTo(host, ResourceState.Event.Error, _nodeId);
             } catch (NoTransitionException e1) {
-            	s_logger.debug("Cannot transmit host " + host.getId() + "to Error state", e);
-            }
-		}
-		
-		return host;
-	}
-	 
-	private Host createHostAndAgent(ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags,
-	        boolean forRebalance) {
-		HostVO host = null;
-		AgentAttache attache = null;
-		StartupCommand[] cmds = null;
-
-		try {
-			cmds = resource.initialize();
-			if (cmds == null) {
-				s_logger.info("Unable to fully initialize the agent because no StartupCommands are returned");
-				return null;
-			}
-
-			if (s_logger.isDebugEnabled()) {
-				new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true);
-			}
-
-			if (old) {
-				StartupCommand firstCmd = cmds[0];
-				host = findHostByGuid(firstCmd.getGuid());
-				if (host == null) {
-					host = findHostByGuid(firstCmd.getGuidWithoutResource());
-				}
-				if (host != null && host.getRemoved() == null) {
-					s_logger.debug("Found the host " + host.getId() + " by guid: " + firstCmd.getGuid() + ", old host reconnected as new");
-					return null;
-				}
-			}
-
-			host = createHostVO(cmds, resource, details, hostTags, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT);
-			if (host != null) {
-				attache = _agentMgr.handleDirectConnectAgent(host, cmds, resource, forRebalance);
-				/* reload myself from database */
-				host = _hostDao.findById(host.getId());
-			}
-		} catch (Exception e) {
-			s_logger.warn("Unable to connect due to ", e);
-		} finally {
-			if (attache == null) {
-				if (cmds != null) {
-					resource.disconnected();
-				}
-
-				if (host != null) {
-					/* Change agent status to Alert */
-					_agentMgr.agentStatusTransitTo(host, Status.Event.AgentDisconnected, _nodeId);
-					/* Don't change resource state here since HostVO is already in database, which means resource state has had an appropriate value*/
-				}
-			}
-		}
-
-		return host;
-	}
-	 
-	@Override
-	public Host createHostAndAgent(Long hostId, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags, boolean forRebalance) {
-		_agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Add);
-		Host host = createHostAndAgent(resource, details, old, hostTags, forRebalance);
-		_agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Del);
-		return host;
-	}
-	
+                s_logger.debug("Cannot transmit host " + host.getId() + "to Error state", e);
+            }
+        }
+
+        return host;
+    }
+
+    private Host createHostAndAgent(ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags,
+            boolean forRebalance) {
+        HostVO host = null;
+        AgentAttache attache = null;
+        StartupCommand[] cmds = null;
+
+        try {
+            cmds = resource.initialize();
+            if (cmds == null) {
+                s_logger.info("Unable to fully initialize the agent because no StartupCommands are returned");
+                return null;
+            }
+
+            if (s_logger.isDebugEnabled()) {
+                new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true);
+            }
+
+            if (old) {
+                StartupCommand firstCmd = cmds[0];
+                host = findHostByGuid(firstCmd.getGuid());
+                if (host == null) {
+                    host = findHostByGuid(firstCmd.getGuidWithoutResource());
+                }
+                if (host != null && host.getRemoved() == null) {
+                    s_logger.debug("Found the host " + host.getId() + " by guid: " + firstCmd.getGuid() + ", old host reconnected as new");
+                    return null;
+                }
+            }
+
+            host = createHostVO(cmds, resource, details, hostTags, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT);
+            if (host != null) {
+                attache = _agentMgr.handleDirectConnectAgent(host, cmds, resource, forRebalance);
+                /* reload myself from database */
+                host = _hostDao.findById(host.getId());
+            }
+        } catch (Exception e) {
+            s_logger.warn("Unable to connect due to ", e);
+        } finally {
+            if (attache == null) {
+                if (cmds != null) {
+                    resource.disconnected();
+                }
+
+                if (host != null) {
+                    /* Change agent status to Alert */
+                    _agentMgr.agentStatusTransitTo(host, Status.Event.AgentDisconnected, _nodeId);
+                    /* Don't change resource state here since HostVO is already in database, which means resource state has had an appropriate value*/
+                }
+            }
+        }
+
+        return host;
+    }
+
+    @Override
+    public Host createHostAndAgent(Long hostId, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags, boolean forRebalance) {
+        _agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Add);
+        Host host = createHostAndAgent(resource, details, old, hostTags, forRebalance);
+        _agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Del);
+        return host;
+    }
+
     @Override
     public Host addHost(long zoneId, ServerResource resource, Type hostType, Map<String, String> hostDetails) {
         // Check if the zone exists in the system
@@ -1737,12 +1759,12 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
 
         return createHostAndAgent(resource, hostDetails, true, null, false);
     }
-    
+
     @Override
     public HostVO createHostVOForConnectedAgent(StartupCommand[] cmds) {
         return createHostVO(cmds, null, null, null, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED);
     }
-    
+
     private void checkIPConflicts(HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask, String serverPublicIP, String serverPublicNetmask) {
         // If the server's private IP is the same as is public IP, this host has
         // a host-only private network. Don't check for conflicts with the
@@ -1775,7 +1797,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             }
         }
     }
-    
+
     @Override
     public HostVO fillRoutingHostVO(HostVO host, StartupRoutingCommand ssCmd, HypervisorType hyType, Map<String, String> details, List<String> hostTags) {
         if (host.getPodId() == null) {
@@ -1788,7 +1810,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             throw new IllegalArgumentException("Can't add host whose hypervisor type is: " + hyType + " into cluster: " + clusterVO.getId() + " whose hypervisor type is: "
                     + clusterVO.getHypervisorType());
         }
-        
+
         final Map<String, String> hostDetails = ssCmd.getHostDetails();
         if (hostDetails != null) {
             if (details != null) {
@@ -1797,7 +1819,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 details = hostDetails;
             }
         }
-        
+
         HostPodVO pod = _podDao.findById(host.getPodId());
         DataCenterVO dc = _dcDao.findById(host.getDataCenterId());
         checkIPConflicts(pod, dc, ssCmd.getPrivateIpAddress(), ssCmd.getPublicIpAddress(), ssCmd.getPublicIpAddress(), ssCmd.getPublicNetmask());
@@ -1810,85 +1832,85 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         host.setHypervisorType(hyType);        
         return host;
     }
-    
-	@Override
-	public void deleteRoutingHost(HostVO host, boolean isForced, boolean forceDestroyStorage) throws UnableDeleteHostException {
-		if (host.getType() != Host.Type.Routing) {
-			throw new CloudRuntimeException("Non-Routing host gets in deleteRoutingHost, id is " + host.getId());
-		}
-
-		if (s_logger.isDebugEnabled()) {
-			s_logger.debug("Deleting Host: " + host.getId() + " Guid:" + host.getGuid());
-		}
-
-		User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId());
-		if (forceDestroyStorage) {
-			// put local storage into mainenance mode, will set all the VMs on
-			// this local storage into stopped state
-			StoragePool storagePool = _storageMgr.findLocalStorageOnHost(host.getId());
-			if (storagePool != null) {
-				if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) {
-					try {
-						storagePool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId());
-						if (storagePool == null) {
-							s_logger.debug("Failed to set primary storage into maintenance mode");
-							throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode");
-						}
-					} catch (Exception e) {
-						s_logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString());
-						throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode, due to: " + e.toString());
-					}
-				}
-
-				List<VMInstanceVO> vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId());
-				for (VMInstanceVO vm : vmsOnLocalStorage) {
-					try {
-						if (!_vmMgr.destroy(vm, caller, _accountMgr.getAccount(vm.getAccountId()))) {
-							String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId();
-							s_logger.warn(errorMsg);
-							throw new UnableDeleteHostException(errorMsg);
-						}
-					} catch (Exception e) {
-						String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId();
-						s_logger.debug(errorMsg, e);
-						throw new UnableDeleteHostException(errorMsg + "," + e.getMessage());
-					}
-				}
-			}
-		} else {
-			// Check if there are vms running/starting/stopping on this host
-			List<VMInstanceVO> vms = _vmDao.listByHostId(host.getId());
-			if (!vms.isEmpty()) {
-				if (isForced) {
-					// Stop HA disabled vms and HA enabled vms in Stopping state
-					// Restart HA enabled vms
-					for (VMInstanceVO vm : vms) {
-						if (!vm.isHaEnabled() || vm.getState() == State.Stopping) {
-							s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + host.getId());
-							try {
-								if (!_vmMgr.advanceStop(vm, true, caller, _accountMgr.getAccount(vm.getAccountId()))) {
-									String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId();
-									s_logger.warn(errorMsg);
-									throw new UnableDeleteHostException(errorMsg);
-								}
-							} catch (Exception e) {
-								String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId();
-								s_logger.debug(errorMsg, e);
-								throw new UnableDeleteHostException(errorMsg + "," + e.getMessage());
-							}
-						} else if (vm.isHaEnabled() && (vm.getState() == State.Running || vm.getState() == State.Starting)) {
-							s_logger.debug("Scheduling restart for vm: " + vm + " " + vm.getState() + " on the host id=" + host.getId());
-							_haMgr.scheduleRestart(vm, false);
-						}
-					}
-				} else {
-					throw new UnableDeleteHostException("Unable to delete the host as there are vms in " + vms.get(0).getState()
-					        + " state using this host and isForced=false specified");
-				}
-			}
-		}
-	}
-	
+
+    @Override
+    public void deleteRoutingHost(HostVO host, boolean isForced, boolean forceDestroyStorage) throws UnableDeleteHostException {
+        if (host.getType() != Host.Type.Routing) {
+            throw new CloudRuntimeException("Non-Routing host gets in deleteRoutingHost, id is " + host.getId());
+        }
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Deleting Host: " + host.getId() + " Guid:" + host.getGuid());
+        }
+
+        User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId());
+        if (forceDestroyStorage) {
+            // put local storage into mainenance mode, will set all the VMs on
+            // this local storage into stopped state
+            StoragePool storagePool = _storageMgr.findLocalStorageOnHost(host.getId());
+            if (storagePool != null) {
+                if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) {
+                    try {
+                        storagePool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId());
+                        if (storagePool == null) {
+                            s_logger.debug("Failed to set primary storage into maintenance mode");
+                            throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode");
+                        }
+                    } catch (Exception e) {
+                        s_logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString());
+                        throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode, due to: " + e.toString());
+                    }
+                }
+
+                List<VMInstanceVO> vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId());
+                for (VMInstanceVO vm : vmsOnLocalStorage) {
+                    try {
+                        if (!_vmMgr.destroy(vm, caller, _accountMgr.getAccount(vm.getAccountId()))) {
+                            String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId();
+                            s_logger.warn(errorMsg);
+                            throw new UnableDeleteHostException(errorMsg);
+                        }
+                    } catch (Exception e) {
+                        String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId();
+                        s_logger.debug(errorMsg, e);
+                        throw new UnableDeleteHostException(errorMsg + "," + e.getMessage());
+                    }
+                }
+            }
+        } else {
+            // Check if there are vms running/starting/stopping on this host
+            List<VMInstanceVO> vms = _vmDao.listByHostId(host.getId());
+            if (!vms.isEmpty()) {
+                if (isForced) {
+                    // Stop HA disabled vms and HA enabled vms in Stopping state
+                    // Restart HA enabled vms
+                    for (VMInstanceVO vm : vms) {
+                        if (!vm.isHaEnabled() || vm.getState() == State.Stopping) {
+                            s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + host.getId());
+                            try {
+                                if (!_vmMgr.advanceStop(vm, true, caller, _accountMgr.getAccount(vm.getAccountId()))) {
+                                    String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId();
+                                    s_logger.warn(errorMsg);
+                                    throw new UnableDeleteHostException(errorMsg);
+                                }
+                            } catch (Exception e) {
+                                String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId();
+                                s_logger.debug(errorMsg, e);
+                                throw new UnableDeleteHostException(errorMsg + "," + e.getMessage());
+                            }
+                        } else if (vm.isHaEnabled() && (vm.getState() == State.Running || vm.getState() == State.Starting)) {
+                            s_logger.debug("Scheduling restart for vm: " + vm + " " + vm.getState() + " on the host id=" + host.getId());
+                            _haMgr.scheduleRestart(vm, false);
+                        }
+                    }
+                } else {
+                    throw new UnableDeleteHostException("Unable to delete the host as there are vms in " + vms.get(0).getState()
+                            + " state using this host and isForced=false specified");
+                }
+            }
+        }
+    }
+
     private boolean doCancelMaintenance(long hostId) {
         HostVO host;
         host = _hostDao.findById(hostId);
@@ -1896,12 +1918,12 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             s_logger.warn("Unable to find host " + hostId);
             return true;
         }
-        
+
         /*TODO: think twice about returning true or throwing out exception, I really prefer to exception that always exposes bugs */
         if (host.getResourceState() != ResourceState.PrepareForMaintenance && host.getResourceState() != ResourceState.Maintenance && host.getResourceState() != ResourceState.ErrorInMaintenance) {
             throw new CloudRuntimeException("Cannot perform cancelMaintenance when resource state is " + host.getResourceState() + ", hostId = " + hostId);
         }
-        
+
         /*TODO: move to listener */
         _haMgr.cancelScheduledMigrations(host);
         List<VMInstanceVO> vms = _haMgr.findTakenMigrationWork();
@@ -1911,40 +1933,40 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 return false;
             }
         }
-        
-		try {
-			resourceStateTransitTo(host, ResourceState.Event.AdminCancelMaintenance, _nodeId);
-			_agentMgr.pullAgentOutMaintenance(hostId);
-			
-			//for kvm, need to log into kvm host, restart cloud-agent
-			if (host.getHypervisorType() == HypervisorType.KVM) {
-				_hostDao.loadDetails(host);
-				String password = host.getDetail("password");
-				String username = host.getDetail("username");
-				if (password == null || username == null) {
-					s_logger.debug("Can't find password/username");
-					return false;
-				}
-				com.trilead.ssh2.Connection connection = SSHCmdHelper.acquireAuthorizedConnection(host.getPrivateIpAddress(), 22, username, password);
-				if (connection == null) {
-					s_logger.debug("Failed to connect to host: " + host.getPrivateIpAddress());
-					return false;
-				}
-				
-				try {
-					SSHCmdHelper.sshExecuteCmdOneShot(connection, "service cloud-agent restart");
-				} catch (sshException e) {
-					return false;
-				}
-			}
-			
-			return true;
-		} catch (NoTransitionException e) {
-			s_logger.debug("Cannot transmit host " + host.getId() + "to Enabled state", e);
-			return false;
-		}        
-    }
-    
+
+        try {
+            resourceStateTransitTo(host, ResourceState.Event.AdminCancelMaintenance, _nodeId);
+            _agentMgr.pullAgentOutMaintenance(hostId);
+
+            //for kvm, need to log into kvm host, restart cloud-agent
+            if (host.getHypervisorType() == HypervisorType.KVM) {
+                _hostDao.loadDetails(host);
+                String password = host.getDetail("password");
+                String username = host.getDetail("username");
+                if (password == null || username == null) {
+                    s_logger.debug("Can't find password/username");
+                    return false;
+                }
+                com.trilead.ssh2.Connection connection = SSHCmdHelper.acquireAuthorizedConnection(host.getPrivateIpAddress(), 22, username, password);
+                if (connection == null) {
+                    s_logger.debug("Failed to connect to host: " + host.getPrivateIpAddress());
+                    return false;
+                }
+
+                try {
+                    SSHCmdHelper.sshExecuteCmdOneShot(connection, "service cloud-agent restart");
+                } catch (sshException e) {
+                    return false;
+                }
+            }
+
+            return true;
+        } catch (NoTransitionException e) {
+            s_logger.debug("Cannot transmit host " + host.getId() + "to Enabled state", e);
+            return false;
+        }
+    }
+
     private boolean cancelMaintenance(long hostId) {
         try {
             Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.AdminCancelMaintenance);
@@ -1955,10 +1977,10 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         } catch (AgentUnavailableException e) {
             return false;
         }
-        
+
         return doCancelMaintenance(hostId);
     }
-    
+
     @Override
     public boolean executeUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException {
         if (event == ResourceState.Event.AdminAskMaintenace) {
@@ -1976,23 +1998,23 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
             throw new CloudRuntimeException("Received an resource event we are not handling now, " + event);
         }
     }
-    
+
     private boolean doUmanageHost(long hostId) {
-		HostVO host = _hostDao.findById(hostId);
-		if (host == null) {
-			s_logger.debug("Cannot find host " + hostId + ", assuming it has been deleted, skip umanage");
-			return true;
-		}
-		
-		if (host.getHypervisorType() == HypervisorType.KVM) {
-			 MaintainAnswer answer = (MaintainAnswer) _agentMgr.easySend(hostId, new MaintainCommand());
-		}
-
-		_agentMgr.disconnectWithoutInvestigation(hostId, Event.ShutdownRequested);
-		return true;
-    }
-    
-    
+        HostVO host = _hostDao.findById(hostId);
+        if (host == null) {
+            s_logger.debug("Cannot find host " + hostId + ", assuming it has been deleted, skip umanage");
+            return true;
+        }
+
+        if (host.getHypervisorType() == HypervisorType.KVM) {
+            MaintainAnswer answer = (MaintainAnswer) _agentMgr.easySend(hostId, new MaintainCommand());
+        }
+
+        _agentMgr.disconnectWithoutInvestigation(hostId, Event.ShutdownRequested);
+        return true;
+    }
+
+
     @Override
     public boolean umanageHost(long hostId) {
         try {
@@ -2004,16 +2026,16 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         } catch (AgentUnavailableException e) {
             return false;
         }
-        
+
         return doUmanageHost(hostId);
     }
-    
+
     private boolean doUpdateHostPassword(long hostId) {
         AgentAttache attache = _agentMgr.findAttache(hostId);
         if (attache == null) {
             return false;
         }
-        
+
         DetailVO nv = _hostDetailsDao.findDetail(hostId, ApiConstants.USERNAME);
         String username = nv.getValue();
         nv = _hostDetailsDao.findDetail(hostId, ApiConstants.PASSWORD);
@@ -2022,7 +2044,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         attache.updatePassword(cmd);
         return true;
     }
-    
+
     @Override
     public boolean updateHostPassword(UpdateHostPasswordCmd cmd) {
         if (cmd.getClusterId() == null) {
@@ -2034,7 +2056,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                 }
             } catch (AgentUnavailableException e) {
             }
-            
+
             return doUpdateHostPassword(cmd.getHostId());
         } else {
             // get agents for the cluster
@@ -2046,16 +2068,16 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
                     if (result != null) {
                         return result;
                     }
-                    
+
                     doUpdateHostPassword(h.getId());
                 } catch (AgentUnavailableException e) {
                 }
             }
-            
+
             return true;
         }
     }
-    
+
     @Override
     public boolean maintenanceFailed(long hostId) {
         HostVO host = _hostDao.findById(hostId);
@@ -2074,140 +2096,140 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
         }
     }
 
-	@Override
+    @Override
     public List<HostVO> findDirectlyConnectedHosts() {
-		/* The resource column is not null for direct connected resource */
-		SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
-	    sc.addAnd(sc.getEntity().getResource(), Op.NNULL);
-	    sc.addAnd(sc.getEntity().getResourceState(), Op.NIN, ResourceState.Disabled);
-	    return sc.list();
+        /* The resource column is not null for direct connected resource */
+        SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
+        sc.addAnd(sc.getEntity().getResource(), Op.NNULL);
+        sc.addAnd(sc.getEntity().getResourceState(), Op.NIN, ResourceState.Disabled);
+        return sc.list();
     }
 
-	@Override
+    @Override
     public List<HostVO> listAllUpAndEnabledHosts(Type type, Long clusterId, Long podId, long dcId) {
-		SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
-		if (type != null) {
-			sc.addAnd(sc.getEntity().getType(), Op.EQ, type);
-		}
-		if (clusterId != null) {
-			sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, clusterId);
-		}
-		if (podId != null) {
-			sc.addAnd(sc.getEntity().getPodId(), Op.EQ, podId);
-		}
-		sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId);
-		sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up);
-		sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, ResourceState.Enabled);
-		return sc.list();
-    }
-	
-	@Override
+        SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
+        if (type != null) {
+            sc.addAnd(sc.getEntity().getType(), Op.EQ, type);
+        }
+        if (clusterId != null) {
+            sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, clusterId);
+        }
+        if (podId != null) {
+            sc.addAnd(sc.getEntity().getPodId(), Op.EQ, podId);
+        }
+        sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId);
+        sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up);
+        sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, ResourceState.Enabled);
+        return sc.list();
+    }
+
+    @Override
     public List<HostVO> listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId) {
-	    String haTag = _haMgr.getHaTag();
+        String haTag = _haMgr.getHaTag();
         return _hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, haTag);
     }
-	
-	@Override 
-	public List<HostVO> findHostByGuid(long dcId, String guid) {
-		SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
-		sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId);
-		sc.addAnd(sc.getEntity().getGuid(), Op.EQ, guid);
-		return sc.list();
-	}
 
-	@Override
+    @Override
+    public List<HostVO> findHostByGuid(long dcId, String guid) {
+        SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO

<TRUNCATED>