You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ah...@apache.org on 2013/07/26 05:11:04 UTC

[1/8] git commit: updated refs/heads/master to 111febc

Updated Branches:
  refs/heads/master db93ebf16 -> 111febc56


Move the rest of the generics out of virtualmachinemanager


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/395cbcc0
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/395cbcc0
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/395cbcc0

Branch: refs/heads/master
Commit: 395cbcc02322b7cc609da035a22ded527e596582
Parents: db93ebf
Author: Alex Huang <al...@citrix.com>
Authored: Tue Jul 23 19:34:36 2013 -0700
Committer: Alex Huang <al...@citrix.com>
Committed: Thu Jul 25 19:00:25 2013 -0700

----------------------------------------------------------------------
 .../consoleproxy/ConsoleProxyManagerImpl.java   |   6 +
 server/src/com/cloud/vm/UserVmManagerImpl.java  |  13 +-
 .../src/com/cloud/vm/VirtualMachineManager.java |  16 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 312 +++++++++----------
 .../cloud/vm/VirtualMachineManagerImplTest.java |   5 +-
 5 files changed, 169 insertions(+), 183 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/395cbcc0/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
index a1ceac5..4cb4a33 100755
--- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
+++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
@@ -1153,6 +1153,12 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
         try {
             //expunge the vm
             _itMgr.expunge(proxy.getUuid());
+            proxy.setPublicIpAddress(null);
+            proxy.setPublicMacAddress(null);
+            proxy.setPublicNetmask(null);
+            proxy.setPrivateMacAddress(null);
+            proxy.setPrivateIpAddress(null);
+            _consoleProxyDao.update(proxy.getId(), proxy);
             _consoleProxyDao.remove(vmId);
             HostVO host = _hostDao.findByTypeNameAndZoneId(proxy.getDataCenterId(), proxy.getHostName(),
                     Host.Type.ConsoleProxy);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/395cbcc0/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 4603431..e4d1c78 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -1210,7 +1210,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
 
                     // #2 migrate the vm if host doesn't have capacity or is in avoid set
                     if (!existingHostHasCapacity){
-                        vmInstance = _itMgr.findHostAndMigrate(vmInstance.getType(), vmInstance, newServiceOfferingId, excludes);
+                        _itMgr.findHostAndMigrate(vmInstance.getUuid(), newServiceOfferingId, excludes);
                     }
 
                     // #3 scale the vm now
@@ -1225,14 +1225,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                     s_logger.warn("Received exception while scaling ",e);
                 } catch (ConcurrentOperationException e) {
                     s_logger.warn("Received exception while scaling ",e);
-                } catch (VirtualMachineMigrationException e) {
-                    s_logger.warn("Received exception while scaling ",e);
-                } catch (ManagementServerException e) {
-                    s_logger.warn("Received exception while scaling ",e);
                 } catch (Exception e) {
                     s_logger.warn("Received exception while scaling ",e);
-                }
-                finally{
+                } finally {
                     if(!success){
                         _itMgr.upgradeVmDb(vmId, currentServiceOffering.getId()); // rollback
                         // Decrement CPU and Memory count accordingly.
@@ -3752,8 +3747,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                             + destHypervisorType.toString() + ", vm: "
                             + vm.getHypervisorType().toString());
         }
-        VMInstanceVO migratedVm = _itMgr.storageMigration(vm, destPool);
-        return migratedVm;
+        _itMgr.storageMigration(vm.getUuid(), destPool);
+        return _vmDao.findById(vm.getId());
 
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/395cbcc0/server/src/com/cloud/vm/VirtualMachineManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java
index 79fa6f1..a0a8464 100644
--- a/server/src/com/cloud/vm/VirtualMachineManager.java
+++ b/server/src/com/cloud/vm/VirtualMachineManager.java
@@ -29,10 +29,8 @@ import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.InsufficientServerCapacityException;
-import com.cloud.exception.ManagementServerException;
 import com.cloud.exception.OperationTimedoutException;
 import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.VirtualMachineMigrationException;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.network.Network;
 import com.cloud.network.dao.NetworkVO;
@@ -114,7 +112,7 @@ public interface VirtualMachineManager extends Manager {
     
     VirtualMachine findById(long vmId);
 
-	<T extends VMInstanceVO> T storageMigration(T vm, StoragePool storagePoolId);
+    void storageMigration(String vmUuid, StoragePool storagePoolId);
 
     /**
      * @param vmInstance
@@ -175,15 +173,11 @@ public interface VirtualMachineManager extends Manager {
     VirtualMachineTO toVmTO(VirtualMachineProfile profile);
 
 
-    VMInstanceVO reConfigureVm(VMInstanceVO vm, ServiceOffering newServiceOffering, boolean sameHost)
-            throws ResourceUnavailableException, ConcurrentOperationException;
+    VMInstanceVO reConfigureVm(VMInstanceVO vm, ServiceOffering newServiceOffering, boolean sameHost) throws ResourceUnavailableException, ConcurrentOperationException;
 
-    VMInstanceVO findHostAndMigrate(VirtualMachine.Type vmType, VMInstanceVO vm, Long newSvcOfferingId, DeploymentPlanner.ExcludeList excludeHostList) throws InsufficientCapacityException,
-            ConcurrentOperationException, ResourceUnavailableException,
-            VirtualMachineMigrationException, ManagementServerException;
+    void findHostAndMigrate(String vmUuid, Long newSvcOfferingId, DeploymentPlanner.ExcludeList excludeHostList) throws InsufficientCapacityException,
+            ConcurrentOperationException, ResourceUnavailableException;
 
-    <T extends VMInstanceVO> T migrateForScale(T vm, long srcHostId, DeployDestination dest, Long newSvcOfferingId)
-            throws ResourceUnavailableException, ConcurrentOperationException,
-            ManagementServerException, VirtualMachineMigrationException;
+    void migrateForScale(String vmUuid, long srcHostId, DeployDestination dest, Long newSvcOfferingId) throws ResourceUnavailableException, ConcurrentOperationException;
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/395cbcc0/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 50e6812..1fb118f 100755
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -109,10 +109,8 @@ import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.InsufficientServerCapacityException;
 import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
 import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.ManagementServerException;
 import com.cloud.exception.OperationTimedoutException;
 import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.VirtualMachineMigrationException;
 import com.cloud.ha.HighAvailabilityManager;
 import com.cloud.ha.HighAvailabilityManager.WorkType;
 import com.cloud.host.Host;
@@ -269,9 +267,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     protected EntityManager _entityMgr;
 
     protected List<HostAllocator> _hostAllocators;
+
     public List<HostAllocator> getHostAllocators() {
         return _hostAllocators;
     }
+
     public void setHostAllocators(List<HostAllocator> _hostAllocators) {
         this._hostAllocators = _hostAllocators;
     }
@@ -288,7 +288,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     @Inject
     protected VMSnapshotManager _vmSnapshotMgr = null;
     @Inject
-    protected ClusterDetailsDao  _clusterDetailsDao;
+    protected ClusterDetailsDao _clusterDetailsDao;
     @Inject
     protected UserVmDetailsDao _uservmDetailsDao;
 
@@ -436,7 +436,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
 
         if (vm.getType() == VirtualMachine.Type.User) {
-              removeDhcpServiceInsubnet(vm);
+            removeDhcpServiceInsubnet(vm);
         }
 
         VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
@@ -457,9 +457,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         // send hypervisor-dependent commands before removing
         List<Command> finalizeExpungeCommands = hvGuru.finalizeExpunge(vm);
-        if(finalizeExpungeCommands != null && finalizeExpungeCommands.size() > 0){
+        if (finalizeExpungeCommands != null && finalizeExpungeCommands.size() > 0) {
             Long hostId = vm.getHostId() != null ? vm.getHostId() : vm.getLastHostId();
-            if(hostId != null){
+            if (hostId != null) {
                 Commands cmds = new Commands(OnError.Stop);
                 for (Command command : finalizeExpungeCommands) {
                     cmds.addCommand(command);
@@ -470,8 +470,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     }
                 }
                 _agentMgr.send(hostId, cmds);
-                if(!cmds.isSuccessful()){
-                    for (Answer answer : cmds.getAnswers()){
+                if (!cmds.isSuccessful()) {
+                    for (Answer answer : cmds.getAnswers()) {
                         if (!answer.getResult()) {
                             s_logger.warn("Failed to expunge vm due to: " + answer.getDetails());
                             throw new CloudRuntimeException("Unable to expunge " + vm + " due to " + answer.getDetails());
@@ -493,7 +493,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         //we are using the info in these nics to remove the dhcp sercvice for these subnets.
         List<NicVO> nicList = listLastNicsInSubnet(vm);
 
-        if(nicList != null && nicList.size() != 0) {
+        if (nicList != null && nicList.size() != 0) {
             for (NicVO nic : nicList) {
                 //free the ipalias on the routers corresponding to each of the nics.
                 Network network = _networkDao.findById(nic.getNetworkId());
@@ -504,7 +504,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                         ipAlias.setState(NicIpAlias.state.revoked);
                         Transaction txn = Transaction.currentTxn();
                         txn.start();
-                        _nicIpAliasDao.update(ipAlias.getId(),ipAlias);
+                        _nicIpAliasDao.update(ipAlias.getId(), ipAlias);
                         IPAddressVO aliasIpaddressVo = _publicIpAddressDao.findByIpAndSourceNetworkId(ipAlias.getNetworkId(), ipAlias.getIp4Address());
                         _publicIpAddressDao.unassignIpAddress(aliasIpaddressVo.getId());
                         txn.commit();
@@ -512,10 +512,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                             s_logger.warn("Failed to remove the ip alias on the router, marking it as removed in db and freed the allocated ip " + ipAlias.getIp4Address());
                         }
                     }
-                }
-                catch (ResourceUnavailableException e) {
+                } catch (ResourceUnavailableException e) {
                     //failed to remove the dhcpconfig on the router.
-                    s_logger.info ("Unable to delete the ip alias due to unable to contact the virtualrouter.");
+                    s_logger.info("Unable to delete the ip alias due to unable to contact the virtualrouter.");
                 }
 
             }
@@ -719,7 +718,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         CallContext cctxt = CallContext.current();
         Account account = cctxt.getCallingAccount();
         User caller = cctxt.getCallingUser();
-        
+
         VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
         VirtualMachineGuru vmGuru = getVmGuru(vm);
@@ -741,12 +740,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.debug("Trying to deploy VM, vm has dcId: " + vm.getDataCenterId() + " and podId: " + vm.getPodIdToDeployIn());
         }
         DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null, ctx);
-        if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){
+        if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("advanceStart: DeploymentPlan is provided, using dcId:" + planToDeploy.getDataCenterId() + ", podId: " + planToDeploy.getPodId() + ", clusterId: "
                         + planToDeploy.getClusterId() + ", hostId: " + planToDeploy.getHostId() + ", poolId: " + planToDeploy.getPoolId());
             }
-            plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId(), ctx);
+            plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(),
+                    planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId(), ctx);
         }
 
         HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
@@ -756,7 +756,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         try {
             Journal journal = start.second().getJournal();
 
-
             if (planToDeploy != null) {
                 avoids = planToDeploy.getAvoids();
             }
@@ -767,7 +766,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + ", clusters: " + avoids.getClustersToAvoid() + ", hosts: " + avoids.getHostsToAvoid());
             }
 
-
             boolean planChangedByVolume = false;
             boolean reuseVolume = true;
             DataCenterDeployment originalPlan = plan;
@@ -775,7 +773,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             int retry = _retry;
             while (retry-- != 0) { // It's != so that it can match -1.
 
-                if(reuseVolume){
+                if (reuseVolume) {
                     // edit plan if this vm's ROOT volume is in READY state already
                     List<VolumeVO> vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
                     for (VolumeVO vol : vols) {
@@ -805,18 +803,22 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                                         // cannot satisfy the plan passed in to the
                                         // planner
                                         if (s_logger.isDebugEnabled()) {
-                                            s_logger.debug("Cannot satisfy the deployment plan passed in since the ready Root volume is in different cluster. volume's cluster: " + rootVolClusterId
+                                            s_logger.debug("Cannot satisfy the deployment plan passed in since the ready Root volume is in different cluster. volume's cluster: "
+                                                    + rootVolClusterId
                                                     + ", cluster specified: " + clusterIdSpecified);
                                         }
-                                        throw new ResourceUnavailableException("Root volume is ready in different cluster, Deployment plan provided cannot be satisfied, unable to create a deployment for "
-                                                + vm, Cluster.class, clusterIdSpecified);
+                                        throw new ResourceUnavailableException(
+                                                "Root volume is ready in different cluster, Deployment plan provided cannot be satisfied, unable to create a deployment for "
+                                                        + vm, Cluster.class, clusterIdSpecified);
                                     }
                                 }
-                                plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), vol.getPoolId(), null, ctx);
+                                plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(),
+                                        vol.getPoolId(), null, ctx);
                             } else {
                                 plan = new DataCenterDeployment(rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId(), null, ctx);
                                 if (s_logger.isDebugEnabled()) {
-                                    s_logger.debug(vol + " is READY, changing deployment plan to use this pool's dcId: " + rootVolDcId + " , podId: " + rootVolPodId + " , and clusterId: " + rootVolClusterId);
+                                    s_logger.debug(vol + " is READY, changing deployment plan to use this pool's dcId: " + rootVolDcId + " , podId: " + rootVolPodId
+                                            + " , and clusterId: " + rootVolClusterId);
                                 }
                                 planChangedByVolume = true;
                             }
@@ -855,8 +857,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 long destHostId = dest.getHost().getId();
                 vm.setPodId(dest.getPod().getId());
                 Long cluster_id = dest.getCluster().getId();
-                ClusterDetailsVO cluster_detail_cpu =  _clusterDetailsDao.findDetail(cluster_id,"cpuOvercommitRatio");
-                ClusterDetailsVO cluster_detail_ram =  _clusterDetailsDao.findDetail(cluster_id,"memoryOvercommitRatio");
+                ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id, "cpuOvercommitRatio");
+                ClusterDetailsVO cluster_detail_ram = _clusterDetailsDao.findDetail(cluster_id, "memoryOvercommitRatio");
                 vmProfile.setCpuOvercommitRatio(Float.parseFloat(cluster_detail_cpu.getValue()));
                 vmProfile.setMemoryOvercommitRatio(Float.parseFloat(cluster_detail_ram.getValue()));
                 StartAnswer startAnswer = null;
@@ -878,7 +880,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                         volumeMgr.prepare(vmProfile, dest);
                     }
                     //since StorageMgr succeeded in volume creation, reuse Volume for further tries until current cluster has capacity
-                    if(!reuseVolume){
+                    if (!reuseVolume) {
                         reuseVolume = true;
                     }
 
@@ -892,7 +894,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx);
 
-
                     work = _workDao.findById(work.getId());
                     if (work == null || work.getStep() != Step.Prepare) {
                         throw new ConcurrentOperationException("Work steps have been changed: " + work);
@@ -903,13 +904,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _workDao.updateStep(work, Step.Started);
 
-
                     startAnswer = cmds.getAnswer(StartAnswer.class);
                     if (startAnswer != null && startAnswer.getResult()) {
                         String host_guid = startAnswer.getHost_guid();
-                        if( host_guid != null ) {
+                        if (host_guid != null) {
                             HostVO finalHost = _resourceMgr.findHostByGuid(host_guid);
-                            if (finalHost == null ) {
+                            if (finalHost == null) {
                                 throw new CloudRuntimeException("Host Guid " + host_guid + " doesn't exist in DB, something wrong here");
                             }
                             destHostId = finalHost.getId();
@@ -930,7 +930,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                             }
 
                             StopCommand cmd = new StopCommand(vm, _mgmtServer.getExecuteInSequence());
-                            StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd);
+                            StopAnswer answer = (StopAnswer)_agentMgr.easySend(destHostId, cmd);
                             if (answer == null || !answer.getResult()) {
                                 s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers"));
                                 _haMgr.scheduleStop(vm, destHostId, WorkType.ForceStop);
@@ -975,7 +975,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                         Step prevStep = work.getStep();
                         _workDao.updateStep(work, Step.Release);
                         // If previous step was started/ing && we got a valid answer
-                        if((prevStep == Step.Started || prevStep == Step.Starting) && (startAnswer != null && startAnswer.getResult())){  //TODO check the response of cleanup and record it in DB for retry
+                        if ((prevStep == Step.Started || prevStep == Step.Starting) && (startAnswer != null && startAnswer.getResult())) {  //TODO check the response of cleanup and record it in DB for retry
                             cleanup(vmGuru, vmProfile, work, Event.OperationFailed, false);
                         } else {
                             //if step is not starting/started, send cleanup command with force=true
@@ -1027,7 +1027,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 return false;
             }
 
-            guru.finalizeStop(profile, (StopAnswer) answer);
+            guru.finalizeStop(profile, (StopAnswer)answer);
         } catch (AgentUnavailableException e) {
             if (!force) {
                 return false;
@@ -1216,7 +1216,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         boolean stopped = false;
         StopAnswer answer = null;
         try {
-            answer = (StopAnswer) _agentMgr.send(vm.getHostId(), stop);
+            answer = (StopAnswer)_agentMgr.send(vm.getHostId(), stop);
             stopped = answer.getResult();
             if (!stopped) {
                 throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails());
@@ -1306,7 +1306,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     @Override
     public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) throws NoTransitionException {
         // if there are active vm snapshots task, state change is not allowed
-        if(_vmSnapshotMgr.hasActiveVMSnapshotTasks(vm.getId())){
+        if (_vmSnapshotMgr.hasActiveVMSnapshotTasks(vm.getId())) {
             s_logger.error("State transit with event: " + e + " failed due to: " + vm.getInstanceName() + " has active VM snapshots tasks");
             return false;
         }
@@ -1340,7 +1340,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         advanceStop(vm, _forceStop);
 
-        if (!_vmSnapshotMgr.deleteAllVMSnapshots(vm.getId(),null)){
+        if (!_vmSnapshotMgr.deleteAllVMSnapshots(vm.getId(), null)) {
             s_logger.debug("Unable to delete all snapshots for " + vm);
             throw new CloudRuntimeException("Unable to delete vm snapshots for " + vm);
         }
@@ -1358,13 +1358,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     //list all the nics which belong to this vm and are the last nics  in the subnets.
     //we are using the info in these nics to remove the dhcp sercvice for these subnets.
-    private  List<NicVO> listLastNicsInSubnet(VirtualMachine vm) {
-        List<NicVO>  nicList  = _nicsDao.listByVmId(vm.getId());
-        List<NicVO>  copyOfnicList = new ArrayList<NicVO>(nicList);
+    private List<NicVO> listLastNicsInSubnet(VirtualMachine vm) {
+        List<NicVO> nicList = _nicsDao.listByVmId(vm.getId());
+        List<NicVO> copyOfnicList = new ArrayList<NicVO>(nicList);
         for (NicVO nic : nicList) {
             Network network = _networkDao.findById(nic.getNetworkId());
             DhcpServiceProvider dhcpServiceProvider = _networkMgr.getDhcpServiceProvider(network);
-            Map <Network.Capability, String> capabilities = dhcpServiceProvider.getCapabilities().get(Network.Service.Dhcp);
+            Map<Network.Capability, String> capabilities = dhcpServiceProvider.getCapabilities().get(Network.Service.Dhcp);
             String supportsMultipleSubnets = capabilities.get(Network.Capability.DhcpAccrossMultipleSubnets);
             if ((supportsMultipleSubnets != null && Boolean.valueOf(supportsMultipleSubnets) && network.getTrafficType() == Networks.TrafficType.Guest && network.getGuestType() == Network.GuestType.Shared)) {
                 //including the ip of the vm and the ipAlias
@@ -1379,7 +1379,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     protected boolean checkVmOnHost(VirtualMachine vm, long hostId) throws AgentUnavailableException, OperationTimedoutException {
-        CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(hostId, new CheckVirtualMachineCommand(vm.getInstanceName()));
+        CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer)_agentMgr.send(hostId, new CheckVirtualMachineCommand(vm.getInstanceName()));
         if (!answer.getResult() || answer.getState() == State.Stopped) {
             return false;
         }
@@ -1388,8 +1388,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     @Override
-    public <T extends VMInstanceVO> T storageMigration(T vmm, StoragePool destPool) {
-        VMInstanceVO vm = _vmDao.findByUuid(vmm.getUuid());
+    public void storageMigration(String vmUuid, StoragePool destPool) {
+        VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
         try {
             stateTransitTo(vm, VirtualMachine.Event.StorageMigrationRequested, null);
@@ -1438,8 +1438,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new CloudRuntimeException("Failed to change vm state: " + e.toString());
             }
         }
-
-        return vmm;
     }
 
     @Override
@@ -1486,7 +1484,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
 
         VirtualMachineProfile vmSrc = new VirtualMachineProfileImpl(vm);
-        for(NicProfile nic: _networkMgr.getNicProfiles(vm)){
+        for (NicProfile nic : _networkMgr.getNicProfiles(vm)) {
             vmSrc.addNic(nic);
         }
 
@@ -1505,7 +1503,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         PrepareForMigrationAnswer pfma = null;
         try {
-            pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
+            pfma = (PrepareForMigrationAnswer)_agentMgr.send(dstHostId, pfmc);
             if (!pfma.getResult()) {
                 String msg = "Unable to prepare for migration due to " + pfma.getDetails();
                 pfma = null;
@@ -1541,7 +1539,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             mc.setHostGuid(dest.getHost().getGuid());
 
             try {
-                MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
+                MigrateAnswer ma = (MigrateAnswer)_agentMgr.send(vm.getLastHostId(), mc);
                 if (!ma.getResult()) {
                     throw new CloudRuntimeException("Unable to migrate due to " + ma.getDetails());
                 }
@@ -1581,7 +1579,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 s_logger.info("Migration was unsuccessful.  Cleaning up: " + vm);
                 _networkMgr.rollbackNicForMigration(vmSrc, profile);
 
-                _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone "
+                _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName()
+                        + " in zone "
                         + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed.  Please check logs.");
                 try {
                     _agentMgr.send(dstHostId, new Commands(cleanup(vm)), null);
@@ -1594,7 +1593,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 } catch (NoTransitionException e) {
                     s_logger.warn(e.getMessage());
                 }
-            }else{
+            } else {
                 _networkMgr.commitNicForMigration(vmSrc, profile);
             }
 
@@ -1619,7 +1618,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                             " while migrating vm to host " + host + ". Either the pool is not accessible from the " +
                             "host or because of the offering with which the volume is created it cannot be placed on " +
                             "the given pool.");
-                } else if (pool.getId() == currentPool.getId()){
+                } else if (pool.getId() == currentPool.getId()) {
                     // If the pool to migrate too is the same as current pool, remove the volume from the list of
                     // volumes to be migrated.
                     volumeToPool.remove(volume);
@@ -1912,9 +1911,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     @Override
     public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
         boolean isMachineUpgradable = true;
-        for(HostAllocator allocator : _hostAllocators) {
+        for (HostAllocator allocator : _hostAllocators) {
             isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
-            if(isMachineUpgradable)
+            if (isMachineUpgradable)
                 continue;
             else
                 break;
@@ -1982,13 +1981,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             AgentVmInfo info = infos.remove(vm.getId());
 
             // sync VM Snapshots related transient states
-            List<VMSnapshotVO> vmSnapshotsInTrasientStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging,VMSnapshot.State.Reverting, VMSnapshot.State.Creating);
-            if(vmSnapshotsInTrasientStates.size() > 1){
+            List<VMSnapshotVO> vmSnapshotsInTrasientStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Reverting,
+                    VMSnapshot.State.Creating);
+            if (vmSnapshotsInTrasientStates.size() > 1) {
                 s_logger.info("Found vm " + vm.getInstanceName() + " with VM snapshots in transient states, needs to sync VM snapshot state");
-                if(!_vmSnapshotMgr.syncVMSnapshot(vm, hostId)){
+                if (!_vmSnapshotMgr.syncVMSnapshot(vm, hostId)) {
                     s_logger.warn("Failed to sync VM in a transient snapshot related state: " + vm.getInstanceName());
                     continue;
-                }else{
+                } else {
                     s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName());
                 }
             }
@@ -2020,7 +2020,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     commands.addCommand(cleanup(left.name));
                 }
             }
-            if ( ! found ) {
+            if (!found) {
                 s_logger.warn("Stopping a VM that we have no record of <fullHostSync>: " + left.name);
                 commands.addCommand(cleanup(left.name));
             }
@@ -2057,8 +2057,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         return commands;
     }
 
-
-
     public void deltaSync(Map<String, Pair<String, State>> newStates) {
         Map<Long, AgentVmInfo> states = convertToInfos(newStates);
 
@@ -2078,10 +2076,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 }
                 command = cleanup(info.name);
             }
-            if (command != null){
+            if (command != null) {
                 try {
                     Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
-                    if (host != null){
+                    if (host != null) {
                         Answer answer = _agentMgr.send(host.getId(), cleanup(info.name));
                         if (!answer.getResult()) {
                             s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
@@ -2094,31 +2092,32 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
     }
 
-
     public void fullSync(final long clusterId, Map<String, Pair<String, State>> newStates) {
-        if (newStates==null)return;
+        if (newStates == null)
+            return;
         Map<Long, AgentVmInfo> infos = convertToInfos(newStates);
         Set<VMInstanceVO> set_vms = Collections.synchronizedSet(new HashSet<VMInstanceVO>());
         set_vms.addAll(_vmDao.listByClusterId(clusterId));
         set_vms.addAll(_vmDao.listLHByClusterId(clusterId));
 
         for (VMInstanceVO vm : set_vms) {
-            AgentVmInfo info =  infos.remove(vm.getId());
+            AgentVmInfo info = infos.remove(vm.getId());
 
             // sync VM Snapshots related transient states
-            List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Creating,VMSnapshot.State.Reverting);
-            if(vmSnapshotsInExpungingStates.size() > 0){
+            List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Creating,
+                    VMSnapshot.State.Reverting);
+            if (vmSnapshotsInExpungingStates.size() > 0) {
                 s_logger.info("Found vm " + vm.getInstanceName() + " in state. " + vm.getState() + ", needs to sync VM snapshot state");
                 Long hostId = null;
                 Host host = null;
-                if(info != null && info.getHostUuid() != null){
+                if (info != null && info.getHostUuid() != null) {
                     host = _hostDao.findByGuid(info.getHostUuid());
                 }
                 hostId = host == null ? (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId()) : host.getId();
-                if(!_vmSnapshotMgr.syncVMSnapshot(vm, hostId)){
+                if (!_vmSnapshotMgr.syncVMSnapshot(vm, hostId)) {
                     s_logger.warn("Failed to sync VM with transient snapshot: " + vm.getInstanceName());
                     continue;
-                }else{
+                } else {
                     s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName());
                 }
             }
@@ -2153,7 +2152,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     long hostId = host == null ? (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId()) : host.getId();
                     HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                     Command command = compareState(hostId, vm, info, true, hvGuru.trackVmHostChange());
-                    if (command != null){
+                    if (command != null) {
                         Answer answer = _agentMgr.send(hostId, command);
                         if (!answer.getResult()) {
                             s_logger.warn("Failed to update state of the VM due to " + answer.getDetails());
@@ -2167,7 +2166,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             else if (info != null && (vm.getState() == State.Stopped || vm.getState() == State.Stopping
                     || vm.isRemoved() || vm.getState() == State.Destroyed || vm.getState() == State.Expunging)) {
                 Host host = _hostDao.findByGuid(info.getHostUuid());
-                if (host != null){
+                if (host != null) {
                     s_logger.warn("Stopping a VM which is stopped/stopping/destroyed/expunging " + info.name);
                     if (vm.getState() == State.Stopped || vm.getState() == State.Stopping) {
                         vm.setState(State.Stopped); // set it as stop and clear it from host
@@ -2179,26 +2178,25 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                         if (!answer.getResult()) {
                             s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                         }
-                    }
-                    catch (Exception e) {
+                    } catch (Exception e) {
                         s_logger.warn("Unable to stop a VM due to " + e.getMessage());
                     }
                 }
             }
             else
-                // host id can change
+            // host id can change
             if (info != null && vm.getState() == State.Running) {
-                    // check for host id changes
-                    Host host = _hostDao.findByGuid(info.getHostUuid());
-                    if (host != null && (vm.getHostId() == null || host.getId() != vm.getHostId())){
-                        s_logger.info("Found vm " + vm.getInstanceName() + " with inconsistent host in db, new host is " +  host.getId());
-                        try {
-                            stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, host.getId());
-                        } catch (NoTransitionException e) {
-                            s_logger.warn(e.getMessage());
-                        }
+                // check for host id changes
+                Host host = _hostDao.findByGuid(info.getHostUuid());
+                if (host != null && (vm.getHostId() == null || host.getId() != vm.getHostId())) {
+                    s_logger.info("Found vm " + vm.getInstanceName() + " with inconsistent host in db, new host is " + host.getId());
+                    try {
+                        stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, host.getId());
+                    } catch (NoTransitionException e) {
+                        s_logger.warn(e.getMessage());
                     }
                 }
+            }
             /* else if(info == null && vm.getState() == State.Stopping) { //Handling CS-13376
                         s_logger.warn("Marking the VM as Stopped as it was still stopping on the CS" +vm.getName());
                         vm.setState(State.Stopped); // Setting the VM as stopped on the DB and clearing it from the host
@@ -2209,10 +2207,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
 
         for (final AgentVmInfo left : infos.values()) {
-            if (!VirtualMachineName.isValidVmName(left.name)) continue;  // if the vm doesn't follow CS naming ignore it for stopping
+            if (!VirtualMachineName.isValidVmName(left.name))
+                continue;  // if the vm doesn't follow CS naming ignore it for stopping
             try {
                 Host host = _hostDao.findByGuid(left.getHostUuid());
-                if (host != null){
+                if (host != null) {
                     s_logger.warn("Stopping a VM which we do not have any record of " + left.name);
                     Answer answer = _agentMgr.send(host.getId(), cleanup(left.name));
                     if (!answer.getResult()) {
@@ -2226,8 +2225,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     }
 
-
-
     protected Map<Long, AgentVmInfo> convertToInfos(final Map<String, Pair<String, State>> newStates) {
         final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>();
         if (newStates == null) {
@@ -2244,7 +2241,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 is_alien_vm = false;
             }
             // alien VMs
-            if (is_alien_vm){
+            if (is_alien_vm) {
                 map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, entry.getValue().second(), entry.getValue().first()));
                 s_logger.warn("Found an alien VM " + entry.getKey());
             }
@@ -2288,8 +2285,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         return map;
     }
 
-
-
     /**
      * compareState does as its name suggests and compares the states between
      * management server and agent. It returns whether something should be
@@ -2324,14 +2319,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             HostVO hostVO = _hostDao.findById(vm.getHostId());
 
             String hostDesc = "name: " + hostVO.getName() + " (id:" + hostVO.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName();
-            _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host " + hostDesc
-                    + " due to storage failure", "Virtual Machine " + vm.getInstanceName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + "] stopped due to storage failure.");
+            _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host "
+                    + hostDesc
+                    + " due to storage failure", "Virtual Machine " + vm.getInstanceName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId()
+                    + "] stopped due to storage failure.");
         }
 
         if (trackExternalChange) {
             if (serverState == State.Starting) {
                 if (vm.getHostId() != null && vm.getHostId() != hostId) {
-                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: "
+                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId
+                            + ", skip status sync for vm: "
                             + vm.getInstanceName());
                     return null;
                 }
@@ -2339,7 +2337,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             if (vm.getHostId() == null || hostId != vm.getHostId()) {
                 try {
                     ItWorkVO workItem = _workDao.findByOutstandingWork(vm.getId(), State.Migrating);
-                    if(workItem == null){
+                    if (workItem == null) {
                         stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
                     }
                 } catch (NoTransitionException e) {
@@ -2356,7 +2354,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         if (trackExternalChange) {
             if (serverState == State.Starting) {
                 if (vm.getHostId() != null && vm.getHostId() != hostId) {
-                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: "
+                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId
+                            + ", skip status sync for vm: "
                             + vm.getInstanceName());
                     return null;
                 }
@@ -2372,7 +2371,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     //
                     if (vm.getHostId() == null || hostId != vm.getHostId()) {
                         if (s_logger.isDebugEnabled()) {
-                            s_logger.debug("detected host change when VM " + vm + " is at running state, VM could be live-migrated externally from host " + vm.getHostId() + " to host " + hostId);
+                            s_logger.debug("detected host change when VM " + vm + " is at running state, VM could be live-migrated externally from host " + vm.getHostId()
+                                    + " to host " + hostId);
                         }
 
                         stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
@@ -2449,10 +2449,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     } catch (ResourceUnavailableException e) {
                         s_logger.error("Exception during update for running vm: " + vm, e);
                         return null;
-                    }catch (InsufficientAddressCapacityException e) {
+                    } catch (InsufficientAddressCapacityException e) {
                         s_logger.error("Exception during update for running vm: " + vm, e);
                         return null;
-                    }catch (NoTransitionException e) {
+                    } catch (NoTransitionException e) {
                         s_logger.warn(e.getMessage());
                     }
                 }
@@ -2469,7 +2469,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         return command;
     }
 
-    private void ensureVmRunningContext(long hostId, VMInstanceVO vm, Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException, InsufficientAddressCapacityException {
+    private void ensureVmRunningContext(long hostId, VMInstanceVO vm, Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException,
+            InsufficientAddressCapacityException {
         VirtualMachineGuru vmGuru = getVmGuru(vm);
 
         s_logger.debug("VM state is starting on full sync so updating it to running");
@@ -2537,8 +2538,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     public boolean processAnswers(long agentId, long seq, Answer[] answers) {
         for (final Answer answer : answers) {
             if (answer instanceof ClusterSyncAnswer) {
-                ClusterSyncAnswer hs = (ClusterSyncAnswer) answer;
-                if (!hs.isExceuted()){
+                ClusterSyncAnswer hs = (ClusterSyncAnswer)answer;
+                if (!hs.isExceuted()) {
                     deltaSync(hs.getNewStates());
                     hs.setExecuted();
                 }
@@ -2562,7 +2563,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         boolean processed = false;
         for (Command cmd : cmds) {
             if (cmd instanceof PingRoutingCommand) {
-                PingRoutingCommand ping = (PingRoutingCommand) cmd;
+                PingRoutingCommand ping = (PingRoutingCommand)cmd;
                 if (ping.getNewStates() != null && ping.getNewStates().size() > 0) {
                     Commands commands = deltaHostSync(agentId, ping.getNewStates());
                     if (commands.size() > 0) {
@@ -2609,9 +2610,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         long agentId = agent.getId();
 
         if (agent.getHypervisorType() == HypervisorType.XenServer) { // only for Xen
-            StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
+            StartupRoutingCommand startup = (StartupRoutingCommand)cmd;
             HashMap<String, Pair<String, State>> allStates = startup.getClusterVMStateChanges();
-            if (allStates != null){
+            if (allStates != null) {
                 fullSync(clusterId, allStates);
             }
 
@@ -2625,7 +2626,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             }
         }
         else { // for others KVM and VMWare
-            StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
+            StartupRoutingCommand startup = (StartupRoutingCommand)cmd;
             Commands commands = fullHostSync(agentId, startup);
 
             if (commands.size() > 0) {
@@ -2795,7 +2796,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     @Override
     public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException,
-    ResourceUnavailableException, InsufficientCapacityException {
+            ResourceUnavailableException, InsufficientCapacityException {
 
         s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested);
         VMInstanceVO vmVO = _vmDao.findById(vm.getId());
@@ -2824,7 +2825,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.debug("Plugging nic for vm " + vm + " in network " + network);
 
             boolean result = false;
-            try{
+            try {
                 result = plugNic(network, nicTO, vmTO, context, dest);
                 if (result) {
                     s_logger.debug("Nic is plugged successfully for vm " + vm + " in network " + network + ". Vm  is a part of network now");
@@ -2838,8 +2839,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network);
                     return null;
                 }
-            }finally{
-                if(!result){
+            } finally {
+                if (!result) {
                     _networkMgr.removeNic(vmProfile, _nicsDao.findById(nic.getId()));
                 }
             }
@@ -2878,13 +2879,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
 
         // don't delete default NIC on a user VM
-        if (nic.isDefaultNic() && vm.getType() == VirtualMachine.Type.User ) {
+        if (nic.isDefaultNic() && vm.getType() == VirtualMachine.Type.User) {
             s_logger.warn("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
             throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
         }
 
         // if specified nic is associated with PF/LB/Static NAT
-        if(rulesMgr.listAssociatedRulesForGuestNic(nic).size() > 0){
+        if (rulesMgr.listAssociatedRulesForGuestNic(nic).size() > 0) {
             throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network
                     + ", nic has associated Port forwarding or Load balancer or Static NAT rules.");
         }
@@ -2905,7 +2906,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.debug("Un-plugging nic " + nic + " for vm " + vm + " from network " + network);
             boolean result = unplugNic(network, nicTO, vmTO, context, dest);
             if (result) {
-                s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
+                s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network);
                 long isDefault = (nic.isDefaultNic()) ? 1 : 0;
                 UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(),
                         vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null,
@@ -2922,7 +2923,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         //2) Release the nic
         _networkMgr.releaseNic(vmProfile, nic);
-        s_logger.debug("Successfully released nic " + nic +  "for vm " + vm);
+        s_logger.debug("Successfully released nic " + nic + "for vm " + vm);
 
         //3) Remove the nic
         _networkMgr.removeNic(vmProfile, nic);
@@ -2953,13 +2954,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             nic = _networkModel.getNicInNetwork(vm.getId(), network.getId());
         }
 
-        if (nic == null){
+        if (nic == null) {
             s_logger.warn("Could not get a nic with " + network);
             return false;
         }
 
         // don't delete default NIC on a user VM
-        if (nic.isDefaultNic() && vm.getType() == VirtualMachine.Type.User ) {
+        if (nic.isDefaultNic() && vm.getType() == VirtualMachine.Type.User) {
             s_logger.warn("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
             throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
         }
@@ -2975,7 +2976,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network);
             boolean result = unplugNic(network, nicTO, vmTO, context, dest);
             if (result) {
-                s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
+                s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network);
             } else {
                 s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
                 return false;
@@ -2988,7 +2989,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         //2) Release the nic
         _networkMgr.releaseNic(vmProfile, nic);
-        s_logger.debug("Successfully released nic " + nic +  "for vm " + vm);
+        s_logger.debug("Successfully released nic " + nic + "for vm " + vm);
 
         //3) Remove the nic
         _networkMgr.removeNic(vmProfile, nic);
@@ -2996,8 +2997,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     @Override
-    public VMInstanceVO findHostAndMigrate(VirtualMachine.Type vmType, VMInstanceVO vm, Long newSvcOfferingId, ExcludeList excludes)
-            throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, VirtualMachineMigrationException, ManagementServerException {
+    public void findHostAndMigrate(String vmUuid, Long newSvcOfferingId, ExcludeList excludes) throws InsufficientCapacityException, ConcurrentOperationException,
+            ResourceUnavailableException {
+
+        VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
+        if (vm == null) {
+            throw new CloudRuntimeException("Unable to find " + vmUuid);
+        }
 
         VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
 
@@ -3032,39 +3038,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
 
         excludes.addHost(dest.getHost().getId());
-        VMInstanceVO vmInstance = null;
         try {
-            vmInstance = migrateForScale(vm, srcHostId, dest, oldSvcOfferingId);
+            migrateForScale(vm.getUuid(), srcHostId, dest, oldSvcOfferingId);
         } catch (ResourceUnavailableException e) {
             s_logger.debug("Unable to migrate to unavailable " + dest);
             throw e;
         } catch (ConcurrentOperationException e) {
             s_logger.debug("Unable to migrate VM due to: " + e.getMessage());
             throw e;
-        } catch (ManagementServerException e) {
-            s_logger.debug("Unable to migrate VM: " + e.getMessage());
-            throw e;
-        } catch (VirtualMachineMigrationException e) {
-            s_logger.debug("Got VirtualMachineMigrationException, Unable to migrate: " + e.getMessage());
-            if (vm.getState() == State.Starting) {
-                s_logger.debug("VM seems to be still Starting, we should retry migration later");
-                throw e;
-            } else {
-                s_logger.debug("Unable to migrate VM, VM is not in Running or even Starting state, current state: " + vm.getState().toString());
-            }
-        }
-        if (vmInstance != null) {
-            return vmInstance;
-        }else{
-            return null;
         }
     }
 
     @Override
-    public <T extends VMInstanceVO> T migrateForScale(T vmm, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException,
-            ConcurrentOperationException, ManagementServerException,
-    VirtualMachineMigrationException {
-        VMInstanceVO vm = _vmDao.findByUuid(vmm.getUuid());
+    public void migrateForScale(String vmUuid, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException, ConcurrentOperationException {
+        VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
         s_logger.info("Migrating " + vm + " to " + dest);
 
         vm.getServiceOfferingId();
@@ -3083,19 +3070,19 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         VirtualMachineGuru vmGuru = getVmGuru(vm);
 
         long vmId = vm.getId();
-        vm = _vmDao.findByUuid(vmm.getUuid());
+        vm = _vmDao.findByUuid(vmUuid);
         if (vm == null) {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("Unable to find the vm " + vm);
             }
-            throw new ManagementServerException("Unable to find a virtual machine with id " + vmId);
+            throw new CloudRuntimeException("Unable to find a virtual machine with id " + vmId);
         }
 
         if (vm.getState() != State.Running) {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("VM is not Running, unable to migrate the vm " + vm);
             }
-            throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString());
+            throw new CloudRuntimeException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString());
         }
 
         short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
@@ -3120,7 +3107,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         PrepareForMigrationAnswer pfma = null;
         try {
-            pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
+            pfma = (PrepareForMigrationAnswer)_agentMgr.send(dstHostId, pfmc);
             if (!pfma.getResult()) {
                 String msg = "Unable to prepare for migration due to " + pfma.getDetails();
                 pfma = null;
@@ -3153,10 +3140,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             mc.setHostGuid(dest.getHost().getGuid());
 
             try {
-                MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
+                MigrateAnswer ma = (MigrateAnswer)_agentMgr.send(vm.getLastHostId(), mc);
                 if (!ma.getResult()) {
                     s_logger.error("Unable to migrate due to " + ma.getDetails());
-                    return null;
+                    throw new CloudRuntimeException("Unable to migrate due to " + ma.getDetails());
                 }
             } catch (OperationTimedoutException e) {
                 if (e.isActive()) {
@@ -3186,18 +3173,18 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                         s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
                     }
                     cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true);
-                    return null;
+                    throw new CloudRuntimeException("Unable to complete migration for " + vm);
                 }
             } catch (OperationTimedoutException e) {
             }
 
             migrated = true;
-            return vmm;
         } finally {
             if (!migrated) {
                 s_logger.info("Migration was unsuccessful.  Cleaning up: " + vm);
 
-                _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone "
+                _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName()
+                        + " in zone "
                         + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed.  Please check logs.");
                 try {
                     _agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null);
@@ -3285,7 +3272,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     @Override
-    public VMInstanceVO reConfigureVm(VMInstanceVO vm , ServiceOffering oldServiceOffering, boolean reconfiguringOnExistingHost) throws ResourceUnavailableException, ConcurrentOperationException {
+    public VMInstanceVO reConfigureVm(VMInstanceVO vm, ServiceOffering oldServiceOffering, boolean reconfiguringOnExistingHost) throws ResourceUnavailableException,
+            ConcurrentOperationException {
 
         UserVmDetailVO vmDetailVO = _uservmDetailsDao.findDetail(vm.getId(), VirtualMachine.IsDynamicScalingEnabled);
         Boolean isDynamicallyScalable;
@@ -3299,11 +3287,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         ServiceOffering newServiceOffering = _configMgr.getServiceOffering(newServiceofferingId);
         HostVO hostVo = _hostDao.findById(vm.getHostId());
 
-        Float memoryOvercommitRatio = Float.parseFloat(_configServer.getConfigValue(Config.MemOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), hostVo.getClusterId()));
-        Float cpuOvercommitRatio = Float.parseFloat(_configServer.getConfigValue(Config.CPUOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), hostVo.getClusterId()));
-        long minMemory = (long) (newServiceOffering.getRamSize()/memoryOvercommitRatio);
+        Float memoryOvercommitRatio = Float.parseFloat(_configServer.getConfigValue(Config.MemOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(),
+                hostVo.getClusterId()));
+        Float cpuOvercommitRatio = Float.parseFloat(_configServer.getConfigValue(Config.CPUOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(),
+                hostVo.getClusterId()));
+        long minMemory = (long)(newServiceOffering.getRamSize() / memoryOvercommitRatio);
         ScaleVmCommand reconfigureCmd = new ScaleVmCommand(vm.getInstanceName(), newServiceOffering.getCpu(),
-                (int) (newServiceOffering.getSpeed()/cpuOvercommitRatio), newServiceOffering.getSpeed(), minMemory * 1024L * 1024L, newServiceOffering.getRamSize() * 1024L * 1024L, newServiceOffering.getLimitCpuUse(), isDynamicallyScalable);
+                (int)(newServiceOffering.getSpeed() / cpuOvercommitRatio), newServiceOffering.getSpeed(), minMemory * 1024L * 1024L,
+                newServiceOffering.getRamSize() * 1024L * 1024L, newServiceOffering.getLimitCpuUse(), isDynamicallyScalable);
 
         Long dstHostId = vm.getHostId();
         ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Running, vm.getType(), vm.getId());
@@ -3313,7 +3304,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         work = _workDao.persist(work);
         boolean success = false;
         try {
-            if(reconfiguringOnExistingHost){
+            if (reconfiguringOnExistingHost) {
                 vm.setServiceOfferingId(oldServiceOffering.getId());
                 _capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); //release the old capacity
                 vm.setServiceOfferingId(newServiceofferingId);
@@ -3331,10 +3322,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             throw new AgentUnavailableException("Operation timed out on reconfiguring " + vm, dstHostId);
         } catch (AgentUnavailableException e) {
             throw e;
-        } finally{
+        } finally {
             // work.setStep(Step.Done);
             //_workDao.update(work.getId(), work);
-            if(!success){
+            if (!success) {
                 _capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); // release the new capacity
                 vm.setServiceOfferingId(oldServiceOffering.getId());
                 _capacityMgr.allocateVmCapacity(vm, false); // allocate the old capacity
@@ -3345,5 +3336,4 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/395cbcc0/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java
index 44a703d..56b14cd 100644
--- a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java
+++ b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java
@@ -254,7 +254,7 @@ public class VirtualMachineManagerImplTest {
         long l = 1L;
 
         when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance);
-        _vmMgr.migrateForScale(_vmInstance, l, dest, l);
+        _vmMgr.migrateForScale(_vmInstance.getUuid(), l, dest, l);
 
     }
 
@@ -298,8 +298,9 @@ public class VirtualMachineManagerImplTest {
 
         when(_vmInstance.getHostId()).thenReturn(null);
         when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance);
+        when(_vmInstanceDao.findByUuid(any(String.class))).thenReturn(_vmInstance);
         DeploymentPlanner.ExcludeList excludeHostList = new DeploymentPlanner.ExcludeList();
-        _vmMgr.findHostAndMigrate(VirtualMachine.Type.User, _vmInstance, 2l, excludeHostList);
+        _vmMgr.findHostAndMigrate(_vmInstance.getUuid(), 2l, excludeHostList);
 
     }
 


[5/8] Moved ClusterManager into it's own package. Removed the agent load balancing code.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java b/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java
new file mode 100644
index 0000000..dd7a603
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterManagerImpl.java
@@ -0,0 +1,1198 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.nio.channels.SocketChannel;
+import java.rmi.RemoteException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLRecoverableException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.config.ConfigDepot;
+import org.apache.cloudstack.config.ConfigKey;
+import org.apache.cloudstack.config.ConfigValue;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+
+import com.cloud.cluster.dao.ManagementServerHostDao;
+import com.cloud.cluster.dao.ManagementServerHostPeerDao;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.Profiler;
+import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.component.ComponentLifecycle;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.concurrency.NamedThreadFactory;
+import com.cloud.utils.db.ConnectionConcierge;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.events.SubscriptionMgr;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.exception.ExceptionUtil;
+import com.cloud.utils.mgmt.JmxUtil;
+import com.cloud.utils.net.NetUtils;
+
+@Local(value = { ClusterManager.class })
+public class ClusterManagerImpl extends ManagerBase implements ClusterManager {
+    private static final Logger s_logger = Logger.getLogger(ClusterManagerImpl.class);
+
+    private static final int EXECUTOR_SHUTDOWN_TIMEOUT = 1000; // 1 second
+    private static final int DEFAULT_OUTGOING_WORKERS = 5;
+
+    private final List<ClusterManagerListener> _listeners = new ArrayList<ClusterManagerListener>();
+    private final Map<Long, ManagementServerHostVO> _activePeers = new HashMap<Long, ManagementServerHostVO>();
+    private ConfigValue<Integer> _heartbeatInterval;
+    private ConfigValue<Integer> _heartbeatThreshold;
+
+    private final Map<String, ClusterService> _clusterPeers;
+
+    @Inject
+    protected ConfigDepot _configDepot;
+
+    private final ScheduledExecutorService _heartbeatScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Cluster-Heartbeat"));
+    private final ExecutorService _notificationExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("Cluster-Notification"));
+    private final List<ClusterManagerMessage> _notificationMsgs = new ArrayList<ClusterManagerMessage>();
+    private ConnectionConcierge _heartbeatConnection = null;
+
+    private final ExecutorService _executor;
+
+    private ClusterServiceAdapter _currentServiceAdapter;
+
+    @Inject
+    private List<ClusterServiceAdapter> _serviceAdapters;
+
+    @Inject private ManagementServerHostDao _mshostDao;
+    @Inject private ManagementServerHostPeerDao _mshostPeerDao;
+
+    protected Dispatcher _dispatcher;
+
+    //
+    // pay attention to _mshostId and _msid
+    // _mshostId is the primary key of management host table
+    // _msid is the unique persistent identifier that peer name is based upon
+    //
+    private Long _mshostId = null;
+    protected long _msId = ManagementServerNode.getManagementServerId();
+    protected long _runId = System.currentTimeMillis();
+
+    private boolean _peerScanInited = false;
+
+    private String _clusterNodeIP = "127.0.0.1";
+    
+    private final List<ClusterServicePdu> _clusterPduOutgoingQueue = new ArrayList<ClusterServicePdu>();
+    private final List<ClusterServicePdu> _clusterPduIncomingQueue = new ArrayList<ClusterServicePdu>();
+    private final Map<Long, ClusterServiceRequestPdu> _outgoingPdusWaitingForAck = new HashMap<Long, ClusterServiceRequestPdu>();
+    
+    public ClusterManagerImpl() {
+        _clusterPeers = new HashMap<String, ClusterService>();
+
+        // executor to perform remote-calls in another thread context, to avoid potential
+        // recursive remote calls between nodes
+        //
+        _executor = Executors.newCachedThreadPool(new NamedThreadFactory("Cluster-Worker"));
+        setRunLevel(ComponentLifecycle.RUN_LEVEL_FRAMEWORK);
+    }
+    
+    private void registerRequestPdu(ClusterServiceRequestPdu pdu) {
+        synchronized(_outgoingPdusWaitingForAck) {
+            _outgoingPdusWaitingForAck.put(pdu.getSequenceId(), pdu);
+        }
+    }
+    
+    @Override
+    public void registerDispatcher(Dispatcher dispatcher) {
+        _dispatcher = dispatcher;
+    }
+
+    private ClusterServiceRequestPdu popRequestPdu(long ackSequenceId) {
+        synchronized(_outgoingPdusWaitingForAck) {
+            if(_outgoingPdusWaitingForAck.get(ackSequenceId) != null) {
+                ClusterServiceRequestPdu pdu = _outgoingPdusWaitingForAck.get(ackSequenceId);
+                _outgoingPdusWaitingForAck.remove(ackSequenceId);
+                return pdu;
+            }
+        }
+        
+        return null;
+    }
+    
+    private void cancelClusterRequestToPeer(String strPeer) {
+        List<ClusterServiceRequestPdu> candidates = new ArrayList<ClusterServiceRequestPdu>();
+        synchronized(_outgoingPdusWaitingForAck) {
+            for(Map.Entry<Long, ClusterServiceRequestPdu> entry : _outgoingPdusWaitingForAck.entrySet()) {
+                if(entry.getValue().getDestPeer().equalsIgnoreCase(strPeer))
+                    candidates.add(entry.getValue());
+            }
+
+            for(ClusterServiceRequestPdu pdu : candidates) {
+                _outgoingPdusWaitingForAck.remove(pdu.getSequenceId());
+            }
+        }
+        
+        for(ClusterServiceRequestPdu pdu : candidates) {
+            s_logger.warn("Cancel cluster request PDU to peer: " + strPeer + ", pdu: " + pdu.getJsonPackage());
+            synchronized(pdu) {
+                pdu.notifyAll();
+            }
+        }
+    }
+    
+    private void addOutgoingClusterPdu(ClusterServicePdu pdu) {
+    	synchronized(_clusterPduOutgoingQueue) {
+    		_clusterPduOutgoingQueue.add(pdu);
+    		_clusterPduOutgoingQueue.notifyAll();
+    	}
+    }
+    
+    private ClusterServicePdu popOutgoingClusterPdu(long timeoutMs) {
+    	synchronized(_clusterPduOutgoingQueue) {
+    		try {
+				_clusterPduOutgoingQueue.wait(timeoutMs);
+			} catch (InterruptedException e) {
+			}
+			
+			if(_clusterPduOutgoingQueue.size() > 0) {
+				ClusterServicePdu pdu = _clusterPduOutgoingQueue.get(0);
+				_clusterPduOutgoingQueue.remove(0);
+				return pdu;
+			}
+    	}
+    	return null;
+    }
+
+    private void addIncomingClusterPdu(ClusterServicePdu pdu) {
+    	synchronized(_clusterPduIncomingQueue) {
+    		_clusterPduIncomingQueue.add(pdu);
+    		_clusterPduIncomingQueue.notifyAll();
+    	}
+    }
+    
+    private ClusterServicePdu popIncomingClusterPdu(long timeoutMs) {
+    	synchronized(_clusterPduIncomingQueue) {
+    		try {
+    			_clusterPduIncomingQueue.wait(timeoutMs);
+			} catch (InterruptedException e) {
+			}
+			
+			if(_clusterPduIncomingQueue.size() > 0) {
+				ClusterServicePdu pdu = _clusterPduIncomingQueue.get(0);
+				_clusterPduIncomingQueue.remove(0);
+				return pdu;
+			}
+    	}
+    	return null;
+    }
+    
+    private Runnable getClusterPduSendingTask() {
+        return new Runnable() {
+            @Override
+            public void run() {
+                onSendingClusterPdu();
+            }
+        };
+    }
+    
+    private Runnable getClusterPduNotificationTask() {
+        return new Runnable() {
+            @Override
+            public void run() {
+                onNotifyingClusterPdu();
+            }
+        };
+    }
+    
+    private void onSendingClusterPdu() {
+        while(true) {
+            try {
+                ClusterServicePdu pdu = popOutgoingClusterPdu(1000);
+                if(pdu == null)
+                	continue;
+                	
+                ClusterService peerService =  null;
+                for(int i = 0; i < 2; i++) {
+                    try {
+                        peerService = getPeerService(pdu.getDestPeer());
+                    } catch (RemoteException e) {
+                        s_logger.error("Unable to get cluster service on peer : " + pdu.getDestPeer());
+                    }
+
+                    if(peerService != null) {
+                        try {
+                            if(s_logger.isDebugEnabled()) {
+                                s_logger.debug("Cluster PDU " + getSelfPeerName() + " -> " + pdu.getDestPeer() + ". agent: " + pdu.getAgentId()
+                                    + ", pdu seq: " + pdu.getSequenceId() + ", pdu ack seq: " + pdu.getAckSequenceId() + ", json: " + pdu.getJsonPackage());
+                            }
+
+                            long startTick = System.currentTimeMillis();
+                            String strResult = peerService.execute(pdu);
+                            if(s_logger.isDebugEnabled()) {
+                                s_logger.debug("Cluster PDU " + getSelfPeerName() + " -> " + pdu.getDestPeer() + " completed. time: " +
+                                    (System.currentTimeMillis() - startTick) + "ms. agent: " + pdu.getAgentId()
+                                     + ", pdu seq: " + pdu.getSequenceId() + ", pdu ack seq: " + pdu.getAckSequenceId() + ", json: " + pdu.getJsonPackage());
+                            }
+                            
+                            if("true".equals(strResult))
+                                break;
+                            
+                        } catch (RemoteException e) {
+                            invalidatePeerService(pdu.getDestPeer());
+                            if(s_logger.isInfoEnabled()) {
+                                s_logger.info("Exception on remote execution, peer: " + pdu.getDestPeer() + ", iteration: "
+                                        + i + ", exception message :" + e.getMessage());
+                            }
+                        }
+                    }
+                }
+            } catch(Throwable e) {
+                s_logger.error("Unexcpeted exception: ", e);
+            }
+        }
+    }
+    
+    private void onNotifyingClusterPdu() {
+        while(true) {
+            try {
+                final ClusterServicePdu pdu = popIncomingClusterPdu(1000);
+                if(pdu == null)
+                	continue;
+
+                _executor.execute(new Runnable() {
+                    @Override
+                	public void run() {
+		                if(pdu.getPduType() == ClusterServicePdu.PDU_TYPE_RESPONSE) {
+		                    ClusterServiceRequestPdu requestPdu = popRequestPdu(pdu.getAckSequenceId());
+		                    if(requestPdu != null) {
+		                        requestPdu.setResponseResult(pdu.getJsonPackage());
+		                        synchronized(requestPdu) {
+		                            requestPdu.notifyAll();
+		                        }
+		                    } else {
+                                s_logger.warn("Original request has already been cancelled. pdu: " + pdu.getJsonPackage());
+		                    }
+		                } else {
+                            String result = _dispatcher.dispatch(pdu);
+		                    if(result == null)
+		                        result = "";
+		                    
+		                    if(pdu.getPduType() == ClusterServicePdu.PDU_TYPE_REQUEST) {
+			                    ClusterServicePdu responsePdu = new ClusterServicePdu();
+			                    responsePdu.setPduType(ClusterServicePdu.PDU_TYPE_RESPONSE);
+			                    responsePdu.setSourcePeer(pdu.getDestPeer());
+			                    responsePdu.setDestPeer(pdu.getSourcePeer());
+			                    responsePdu.setAckSequenceId(pdu.getSequenceId());
+			                    responsePdu.setJsonPackage(result);
+			                    
+			                    addOutgoingClusterPdu(responsePdu);
+		                    }
+		                }
+                	}
+                });
+            } catch(Throwable e) {
+                s_logger.error("Unexcpeted exception: ", e);
+            }
+        }
+    }
+
+
+
+    @Override
+    public void OnReceiveClusterServicePdu(ClusterServicePdu pdu) {
+    	addIncomingClusterPdu(pdu);
+    }
+    
+
+
+    /**
+     * called by DatabaseUpgradeChecker to see if there are other peers running.
+     * 
+     * @param notVersion
+     *            If version is passed in, the peers CANNOT be running at this version. If version is null, return true if any
+     *            peer is running regardless of version.
+     * @return true if there are peers running and false if not.
+     */
+    public static final boolean arePeersRunning(String notVersion) {
+        return false; // TODO: Leaving this for Kelven to take care of.
+    }
+
+    @Override
+    public void broadcast(long agentId, String cmds) {
+        Date cutTime = DateUtil.currentGMTTime();
+
+        List<ManagementServerHostVO> peers = _mshostDao.getActiveList(new Date(cutTime.getTime() - _heartbeatThreshold.value()));
+        for (ManagementServerHostVO peer : peers) {
+            String peerName = Long.toString(peer.getMsid());
+            if (getSelfPeerName().equals(peerName)) {
+                continue; // Skip myself.
+            }
+            try {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Forwarding " + cmds + " to " + peer.getMsid());
+                }
+                executeAsync(peerName, agentId, cmds, true);
+            } catch (Exception e) {
+                s_logger.warn("Caught exception while talkign to " + peer.getMsid());
+            }
+        }
+    }
+
+    public void executeAsync(String strPeer, long agentId, String cmds, boolean stopOnError) {
+        ClusterServicePdu pdu = new ClusterServicePdu();
+        pdu.setSourcePeer(getSelfPeerName());
+        pdu.setDestPeer(strPeer);
+        pdu.setAgentId(agentId);
+        pdu.setJsonPackage(cmds);
+        pdu.setStopOnError(true);
+        addOutgoingClusterPdu(pdu);
+    }
+
+    @Override
+    public String execute(String strPeer, long agentId, String cmds, boolean stopOnError) {
+        if(s_logger.isDebugEnabled()) {
+            s_logger.debug(getSelfPeerName() + " -> " + strPeer + "." + agentId + " " + cmds);
+        }
+        
+        ClusterServiceRequestPdu pdu = new ClusterServiceRequestPdu();
+        pdu.setSourcePeer(getSelfPeerName());
+        pdu.setDestPeer(strPeer);
+        pdu.setAgentId(agentId);
+        pdu.setJsonPackage(cmds);
+        pdu.setStopOnError(stopOnError);
+        registerRequestPdu(pdu);
+        addOutgoingClusterPdu(pdu);
+        
+        synchronized(pdu) {
+            try {
+                pdu.wait();
+            } catch (InterruptedException e) {
+            }
+        }
+
+        if(s_logger.isDebugEnabled()) {
+            s_logger.debug(getSelfPeerName() + " -> " + strPeer + "." + agentId + " completed. result: " +
+                pdu.getResponseResult());
+        }
+        
+        if(pdu.getResponseResult() != null && pdu.getResponseResult().length() > 0) {
+            return pdu.getResponseResult();
+        }
+
+        return null;
+    }
+    
+    @Override
+    public ManagementServerHostVO getPeer(String mgmtServerId) {
+        return _mshostDao.findByMsid(Long.valueOf(mgmtServerId));
+    }
+
+    @Override
+    public String getSelfPeerName() {
+        return Long.toString(_msId);
+    }
+
+    public String getSelfNodeIP() {
+        return _clusterNodeIP;
+    }
+
+    @Override
+    public void registerListener(ClusterManagerListener listener) {
+        // Note : we don't check duplicates
+        synchronized (_listeners) {
+
+    		s_logger.info("register cluster listener " + listener.getClass());
+    		
+        	_listeners.add(listener);
+        }
+    }
+
+    @Override
+    public void unregisterListener(ClusterManagerListener listener) {
+        synchronized(_listeners) {
+    		s_logger.info("unregister cluster listener " + listener.getClass());
+        	
+        	_listeners.remove(listener);
+        }
+    }
+
+    public void notifyNodeJoined(List<ManagementServerHostVO> nodeList) {
+        if(s_logger.isDebugEnabled()) {
+            s_logger.debug("Notify management server node join to listeners.");
+
+            for(ManagementServerHostVO mshost : nodeList) {
+                s_logger.debug("Joining node, IP: " + mshost.getServiceIP() + ", msid: " + mshost.getMsid());
+            }
+        }
+
+        synchronized(_listeners) {
+            for(ClusterManagerListener listener : _listeners) {
+                listener.onManagementNodeJoined(nodeList, _mshostId);
+            }
+        }
+
+        SubscriptionMgr.getInstance().notifySubscribers(ClusterManager.ALERT_SUBJECT, this,
+                new ClusterNodeJoinEventArgs(_mshostId, nodeList));
+    }
+
+    public void notifyNodeLeft(List<ManagementServerHostVO> nodeList) {
+        if(s_logger.isDebugEnabled()) {
+            s_logger.debug("Notify management server node left to listeners.");
+        }
+        
+        for(ManagementServerHostVO mshost : nodeList) {
+            if(s_logger.isDebugEnabled())
+                s_logger.debug("Leaving node, IP: " + mshost.getServiceIP() + ", msid: " + mshost.getMsid());
+            cancelClusterRequestToPeer(String.valueOf(mshost.getMsid()));
+        }
+
+        synchronized(_listeners) {
+            for(ClusterManagerListener listener : _listeners) {
+                listener.onManagementNodeLeft(nodeList, _mshostId);
+            }
+        }
+
+        SubscriptionMgr.getInstance().notifySubscribers(ClusterManager.ALERT_SUBJECT, this,
+                new ClusterNodeLeftEventArgs(_mshostId, nodeList));
+    }
+
+    public void notifyNodeIsolated() {
+        if(s_logger.isDebugEnabled())
+            s_logger.debug("Notify management server node isolation to listeners");
+
+        synchronized(_listeners) {
+            for(ClusterManagerListener listener : _listeners) {
+                listener.onManagementNodeIsolated();
+            }
+        }
+    }
+
+    public ClusterService getPeerService(String strPeer) throws RemoteException {
+        synchronized(_clusterPeers) {
+            if(_clusterPeers.containsKey(strPeer)) {
+                return _clusterPeers.get(strPeer);
+            }
+        }
+
+        ClusterService service = _currentServiceAdapter.getPeerService(strPeer);
+
+        if(service != null) {
+            synchronized(_clusterPeers) {
+                // re-check the peer map again to deal with the
+                // race conditions
+                if(!_clusterPeers.containsKey(strPeer)) {
+                    _clusterPeers.put(strPeer, service);
+                }
+            }
+        }
+
+        return service;
+    }
+
+    public void invalidatePeerService(String strPeer) {
+        synchronized(_clusterPeers) {
+            if(_clusterPeers.containsKey(strPeer)) {
+                _clusterPeers.remove(strPeer);
+            }
+        }
+    }
+
+    private Runnable getHeartbeatTask() {
+        return new Runnable() {
+            @Override
+            public void run() {
+                Transaction txn = Transaction.open("ClusterHeartBeat");
+                try {
+                    Profiler profiler = new Profiler();
+                    Profiler profilerHeartbeatUpdate = new Profiler();
+                    Profiler profilerPeerScan = new Profiler();
+                    
+                    try {
+                        profiler.start();
+                        
+                        profilerHeartbeatUpdate.start();
+                        txn.transitToUserManagedConnection(getHeartbeatConnection());
+                        if(s_logger.isTraceEnabled()) {
+                            s_logger.trace("Cluster manager heartbeat update, id:" + _mshostId);
+                        }
+    
+                        _mshostDao.update(_mshostId, getCurrentRunId(), DateUtil.currentGMTTime());
+                        profilerHeartbeatUpdate.stop();
+    
+                        profilerPeerScan.start();
+                        if (s_logger.isTraceEnabled()) {
+                            s_logger.trace("Cluster manager peer-scan, id:" + _mshostId);
+                        }
+    
+                        if (!_peerScanInited) {
+                            _peerScanInited = true;
+                            initPeerScan();
+                        }
+                        
+                        peerScan();
+                        profilerPeerScan.stop();
+                        
+                    } finally {
+                        profiler.stop();
+                        
+                        if (profiler.getDuration() >= _heartbeatInterval.value()) {
+                            if(s_logger.isDebugEnabled())
+                                s_logger.debug("Management server heartbeat takes too long to finish. profiler: " + profiler.toString() +
+                                    ", profilerHeartbeatUpdate: " + profilerHeartbeatUpdate.toString() +
+                                        ", profilerPeerScan: " + profilerPeerScan.toString());
+                        }
+                    }
+                    
+                } catch(CloudRuntimeException e) {
+                    s_logger.error("Runtime DB exception ", e.getCause());
+
+                    if(e.getCause() instanceof ClusterInvalidSessionException) {
+                        s_logger.error("Invalid cluster session found, fence it");
+                        queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeIsolated));
+                    }
+
+                    if(isRootCauseConnectionRelated(e.getCause())) {
+                        s_logger.error("DB communication problem detected, fence it");
+                        queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeIsolated));
+                    }
+
+                    invalidHeartbeatConnection();
+                } catch(ActiveFencingException e) {
+                    queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeIsolated));
+                } catch (Throwable e) {
+                    s_logger.error("Unexpected exception in cluster heartbeat", e);
+                    if(isRootCauseConnectionRelated(e.getCause())) {
+                        s_logger.error("DB communication problem detected, fence it");
+                        queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeIsolated));
+                    }
+
+                    invalidHeartbeatConnection();
+                } finally {
+                    txn.transitToAutoManagedConnection(Transaction.CLOUD_DB);
+                    txn.close("ClusterHeartBeat");
+                }
+            }
+        };
+    }
+
+    private boolean isRootCauseConnectionRelated(Throwable e) {
+        while (e != null) {
+            if (e instanceof SQLRecoverableException) {
+                return true;
+            }
+
+            e = e.getCause();
+        }
+
+        return false;
+    }
+
+    private Connection getHeartbeatConnection() throws SQLException {
+        if(_heartbeatConnection == null) {
+            Connection conn = Transaction.getStandaloneConnectionWithException();
+            _heartbeatConnection = new ConnectionConcierge("ClusterManagerHeartBeat", conn, false);
+        }
+
+        return _heartbeatConnection.conn();
+    }
+
+    private void invalidHeartbeatConnection() {
+        if(_heartbeatConnection != null) {
+            Connection conn = Transaction.getStandaloneConnection();
+            if (conn != null) {
+                _heartbeatConnection.reset(Transaction.getStandaloneConnection());
+            }
+        }
+    }
+
+    private Runnable getNotificationTask() {
+        return new Runnable() {
+            @Override
+            public void run() {
+                while(true) {
+                    synchronized(_notificationMsgs) {
+                        try {
+                            _notificationMsgs.wait(1000);
+                        } catch (InterruptedException e) {
+                        }
+                    }
+
+                    ClusterManagerMessage msg = null;
+                    while((msg = getNextNotificationMessage()) != null) {
+                        try {
+                            switch(msg.getMessageType()) {
+                            case nodeAdded:
+                                if(msg.getNodes() != null && msg.getNodes().size() > 0) {
+                                    Profiler profiler = new Profiler();
+                                    profiler.start();
+
+                                    notifyNodeJoined(msg.getNodes());
+
+                                    profiler.stop();
+                                    if(profiler.getDuration() > 1000) {
+                                        if(s_logger.isDebugEnabled()) {
+                                            s_logger.debug("Notifying management server join event took " + profiler.getDuration() + " ms");
+                                        }
+                                    } else {
+                                        s_logger.warn("Notifying management server join event took " + profiler.getDuration() + " ms");
+                                    }
+                                }
+                                break;
+
+                            case nodeRemoved:
+                                if(msg.getNodes() != null && msg.getNodes().size() > 0) {
+                                    Profiler profiler = new Profiler();
+                                    profiler.start();
+
+                                    notifyNodeLeft(msg.getNodes());
+
+                                    profiler.stop();
+                                    if(profiler.getDuration() > 1000) {
+                                        if(s_logger.isDebugEnabled()) {
+                                            s_logger.debug("Notifying management server leave event took " + profiler.getDuration() + " ms");
+                                        }
+                                    } else {
+                                        s_logger.warn("Notifying management server leave event took " + profiler.getDuration() + " ms");
+                                    }
+                                }
+                                break;
+
+                            case nodeIsolated:
+                                notifyNodeIsolated();
+                                break;
+
+                            default :
+                                assert(false);
+                                break;
+                            }
+
+                        } catch (Throwable e) {
+                            s_logger.warn("Unexpected exception during cluster notification. ", e);
+                        }
+                    }
+
+                    try { Thread.sleep(1000); } catch (InterruptedException e) {}
+                }
+            }
+        };
+    }
+
+    private void queueNotification(ClusterManagerMessage msg) {
+        synchronized(_notificationMsgs) {
+            _notificationMsgs.add(msg);
+            _notificationMsgs.notifyAll();
+        }
+        
+        switch(msg.getMessageType()) {
+        case nodeAdded:
+            {
+                List<ManagementServerHostVO> l = msg.getNodes();
+                if(l != null && l.size() > 0) {
+                    for(ManagementServerHostVO mshost: l) {
+                        _mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Up);
+                    }
+                }
+            }
+            break;
+            
+        case nodeRemoved:
+            {
+                List<ManagementServerHostVO> l = msg.getNodes();
+                if(l != null && l.size() > 0) {
+                    for(ManagementServerHostVO mshost: l) {
+                        _mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Down);
+                    }
+                }
+            }
+            break;
+            
+        default :
+            break;
+        
+        }
+    }
+
+    private ClusterManagerMessage getNextNotificationMessage() {
+        synchronized(_notificationMsgs) {
+            if(_notificationMsgs.size() > 0) {
+                return _notificationMsgs.remove(0);
+            }
+        }
+
+        return null;
+    }
+
+    private void initPeerScan() {
+        // upon startup, for all inactive management server nodes that we see at startup time, we will send notification also to help upper layer perform
+        // missed cleanup
+        Date cutTime = DateUtil.currentGMTTime();
+        List<ManagementServerHostVO> inactiveList = _mshostDao.getInactiveList(new Date(cutTime.getTime() - _heartbeatThreshold.value()));
+       
+        // We don't have foreign key constraints to enforce the mgmt_server_id integrity in host table, when user manually
+        // remove records from mshost table, this will leave orphan mgmt_serve_id reference in host table.
+        List<Long> orphanList = _mshostDao.listOrphanMsids();
+        if(orphanList.size() > 0) {
+	        for(Long orphanMsid : orphanList) {
+	        	// construct fake ManagementServerHostVO based on orphan MSID
+	        	s_logger.info("Add orphan management server msid found in host table to initial clustering notification, orphan msid: " + orphanMsid);
+	        	inactiveList.add(new ManagementServerHostVO(orphanMsid, 0, "orphan", 0, new Date()));
+	        }
+        } else {
+        	s_logger.info("We are good, no orphan management server msid in host table is found");
+        }
+        
+        if(inactiveList.size() > 0) {
+        	if(s_logger.isInfoEnabled()) {
+        		s_logger.info("Found " + inactiveList.size() + " inactive management server node based on timestamp");
+        		for(ManagementServerHostVO host : inactiveList)
+        			s_logger.info("management server node msid: " + host.getMsid() + ", name: " + host.getName() + ", service ip: " + host.getServiceIP() + ", version: " + host.getVersion());
+        	}
+
+        	List<ManagementServerHostVO> downHostList = new ArrayList<ManagementServerHostVO>();
+            for(ManagementServerHostVO host : inactiveList) {
+	            if(!pingManagementNode(host)) {
+	                s_logger.warn("Management node " + host.getId() + " is detected inactive by timestamp and also not pingable");
+	                downHostList.add(host);
+	            }
+            }
+            
+            if(downHostList.size() > 0)
+            	queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, downHostList));
+        } else {
+        	s_logger.info("No inactive management server node found");
+        }
+    }
+
+    private void peerScan() throws ActiveFencingException {
+        Date cutTime = DateUtil.currentGMTTime();
+
+        Profiler profiler = new Profiler();
+        profiler.start();
+        
+        Profiler profilerQueryActiveList = new Profiler();
+        profilerQueryActiveList.start();
+        List<ManagementServerHostVO> currentList = _mshostDao.getActiveList(new Date(cutTime.getTime() - _heartbeatThreshold.value()));
+        profilerQueryActiveList.stop();
+
+        Profiler profilerSyncClusterInfo = new Profiler();
+        profilerSyncClusterInfo.start();
+        List<ManagementServerHostVO> removedNodeList = new ArrayList<ManagementServerHostVO>();
+        List<ManagementServerHostVO> invalidatedNodeList = new ArrayList<ManagementServerHostVO>();
+
+        if(_mshostId != null) {
+            
+            if(_mshostPeerDao.countStateSeenInPeers(_mshostId, _runId, ManagementServerHost.State.Down) > 0) {
+                String msg = "We have detected that at least one management server peer reports that this management server is down, perform active fencing to avoid split-brain situation";
+                s_logger.error(msg);
+                throw new ActiveFencingException(msg);
+            }
+            
+            // only if we have already attached to cluster, will we start to check leaving nodes
+            for(Map.Entry<Long, ManagementServerHostVO>  entry : _activePeers.entrySet()) {
+
+                ManagementServerHostVO current = getInListById(entry.getKey(), currentList);
+                if(current == null) {
+                    if(entry.getKey().longValue() != _mshostId.longValue()) {
+                        if(s_logger.isDebugEnabled()) {
+                            s_logger.debug("Detected management node left, id:" + entry.getKey() + ", nodeIP:" + entry.getValue().getServiceIP());
+                        }
+                        removedNodeList.add(entry.getValue());
+                    }
+                } else {
+                    if(current.getRunid() == 0) {
+                        if(entry.getKey().longValue() != _mshostId.longValue()) {
+                            if(s_logger.isDebugEnabled()) {
+                                s_logger.debug("Detected management node left because of invalidated session, id:" + entry.getKey() + ", nodeIP:" + entry.getValue().getServiceIP());
+                            }
+                            invalidatedNodeList.add(entry.getValue());
+                        }
+                    } else {
+                        if(entry.getValue().getRunid() != current.getRunid()) {
+                            if(s_logger.isDebugEnabled()) {
+                                s_logger.debug("Detected management node left and rejoined quickly, id:" + entry.getKey() + ", nodeIP:" + entry.getValue().getServiceIP());
+                            }
+
+                            entry.getValue().setRunid(current.getRunid());
+                        }
+                    }
+                }
+            }
+        }
+        profilerSyncClusterInfo.stop();
+        
+        Profiler profilerInvalidatedNodeList = new Profiler();
+        profilerInvalidatedNodeList.start();
+        // process invalidated node list
+        if(invalidatedNodeList.size() > 0) {
+            for(ManagementServerHostVO mshost : invalidatedNodeList) {
+                _activePeers.remove(mshost.getId());
+                try {
+                    JmxUtil.unregisterMBean("ClusterManager", "Node " + mshost.getId());
+                } catch(Exception e) {
+                    s_logger.warn("Unable to deregiester cluster node from JMX monitoring due to exception " + e.toString());
+                }
+            }
+
+            queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, invalidatedNodeList));
+        }
+        profilerInvalidatedNodeList.stop();
+
+        Profiler profilerRemovedList = new Profiler();
+        profilerRemovedList.start();
+        // process removed node list
+        Iterator<ManagementServerHostVO> it = removedNodeList.iterator();
+        while(it.hasNext()) {
+            ManagementServerHostVO mshost = it.next();
+            if(!pingManagementNode(mshost)) {
+                s_logger.warn("Management node " + mshost.getId() + " is detected inactive by timestamp and also not pingable");
+                _activePeers.remove(mshost.getId());
+                try {
+                    JmxUtil.unregisterMBean("ClusterManager", "Node " + mshost.getId());
+                } catch(Exception e) {
+                    s_logger.warn("Unable to deregiester cluster node from JMX monitoring due to exception " + e.toString());
+                }
+            } else {
+                s_logger.info("Management node " + mshost.getId() + " is detected inactive by timestamp but is pingable");
+                it.remove();
+            }
+        }
+
+        if(removedNodeList.size() > 0) {
+            queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, removedNodeList));
+        }
+        profilerRemovedList.stop();
+
+        List<ManagementServerHostVO> newNodeList = new ArrayList<ManagementServerHostVO>();
+        for(ManagementServerHostVO mshost : currentList) {
+            if(!_activePeers.containsKey(mshost.getId())) {
+                _activePeers.put(mshost.getId(), mshost);
+
+                if(s_logger.isDebugEnabled()) {
+                    s_logger.debug("Detected management node joined, id:" + mshost.getId() + ", nodeIP:" + mshost.getServiceIP());
+                }
+                newNodeList.add(mshost);
+
+                try {
+                    JmxUtil.registerMBean("ClusterManager", "Node " + mshost.getId(), new ClusterManagerMBeanImpl(this, mshost));
+                } catch(Exception e) {
+                    s_logger.warn("Unable to regiester cluster node into JMX monitoring due to exception " + ExceptionUtil.toString(e));
+                }
+            }
+        }
+
+        if(newNodeList.size() > 0) {
+            queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeAdded, newNodeList));
+        }
+        
+        profiler.stop();
+        
+        if (profiler.getDuration() >= _heartbeatInterval.value()) {
+            if(s_logger.isDebugEnabled())
+                s_logger.debug("Peer scan takes too long to finish. profiler: " + profiler.toString()
+                  + ", profilerQueryActiveList: " + profilerQueryActiveList.toString()
+                  + ", profilerSyncClusterInfo: " + profilerSyncClusterInfo.toString()
+                  + ", profilerInvalidatedNodeList: " + profilerInvalidatedNodeList.toString()
+                  + ", profilerRemovedList: " + profilerRemovedList.toString());
+        }
+    }
+
+    private static ManagementServerHostVO getInListById(Long id, List<ManagementServerHostVO> l) {
+        for(ManagementServerHostVO mshost : l) {
+            if(mshost.getId() == id) {
+                return mshost;
+            }
+        }
+        return null;
+    }
+
+    @Override @DB
+    public boolean start() {
+        if(s_logger.isInfoEnabled()) {
+            s_logger.info("Starting cluster manager, msid : " + _msId);
+        }
+
+        Transaction txn = Transaction.currentTxn();
+        try {
+            txn.start();
+
+            final Class<?> c = this.getClass();
+            String version = c.getPackage().getImplementationVersion();
+
+            ManagementServerHostVO mshost = _mshostDao.findByMsid(_msId);
+            if (mshost == null) {
+                mshost = new ManagementServerHostVO();
+                mshost.setMsid(_msId);
+                mshost.setRunid(getCurrentRunId());
+                mshost.setName(NetUtils.getHostName());
+                mshost.setVersion(version);
+                mshost.setServiceIP(_clusterNodeIP);
+                mshost.setServicePort(_currentServiceAdapter.getServicePort());
+                mshost.setLastUpdateTime(DateUtil.currentGMTTime());
+                mshost.setRemoved(null);
+                mshost.setAlertCount(0);
+                mshost.setState(ManagementServerHost.State.Up);
+                _mshostDao.persist(mshost);
+
+                if (s_logger.isInfoEnabled()) {
+                    s_logger.info("New instance of management server msid " + _msId + " is being started");
+                }
+            } else {
+                if (s_logger.isInfoEnabled()) {
+                    s_logger.info("Management server " + _msId + " is being started");
+                }
+
+                _mshostDao.update(mshost.getId(), getCurrentRunId(), NetUtils.getHostName(), version, _clusterNodeIP, _currentServiceAdapter.getServicePort(), DateUtil.currentGMTTime());
+            }
+
+            txn.commit();
+
+            _mshostId = mshost.getId();
+            if (s_logger.isInfoEnabled()) {
+                s_logger.info("Management server (host id : " + _mshostId + ") is being started at " + _clusterNodeIP + ":" + _currentServiceAdapter.getServicePort());
+            }
+            
+            _mshostPeerDao.clearPeerInfo(_mshostId);
+
+            // use seperate thread for heartbeat updates
+            _heartbeatScheduler.scheduleAtFixedRate(getHeartbeatTask(), _heartbeatInterval.value(), _heartbeatInterval.value(), TimeUnit.MILLISECONDS);
+            _notificationExecutor.submit(getNotificationTask());
+
+        } catch (Throwable e) {
+            s_logger.error("Unexpected exception : ", e);
+            txn.rollback();
+
+            throw new CloudRuntimeException("Unable to initialize cluster info into database");
+        }
+
+        if (s_logger.isInfoEnabled()) {
+            s_logger.info("Cluster manager was started successfully");
+        }
+
+        return true;
+    }
+
+    @Override @DB
+    public boolean stop() {
+        if(_mshostId != null) {
+            ManagementServerHostVO mshost = _mshostDao.findByMsid(_msId);
+            mshost.setState(ManagementServerHost.State.Down);
+            _mshostDao.update(_mshostId, mshost);
+        }
+
+        _heartbeatScheduler.shutdownNow();
+        _executor.shutdownNow();
+
+        try {
+            _heartbeatScheduler.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
+            _executor.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+        }
+
+        if(s_logger.isInfoEnabled()) {
+            s_logger.info("Cluster manager is stopped");
+        }
+
+        return true;
+    }
+
+    protected final ConfigKey<Integer> HeartBeatInterval = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.interval", "management-server", ClusterManager.class,
+            "1500", "Interval to check for the heart beat between management server nodes", false, "Seconds");
+    protected final ConfigKey<Integer> HeartBeatThreshold = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.threshold", "management-server", ClusterManager.class,
+            "150000", "Threshold before self-fence the management server", true, "Seconds");
+    
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        if(s_logger.isInfoEnabled()) {
+            s_logger.info("Start configuring cluster manager : " + name);
+        }
+
+        _heartbeatInterval = _configDepot.get(HeartBeatInterval);
+        _heartbeatThreshold = _configDepot.get(HeartBeatThreshold);
+
+        File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
+        Properties dbProps = new Properties();
+        try {
+            dbProps.load(new FileInputStream(dbPropsFile));
+        } catch (FileNotFoundException e) {
+            throw new ConfigurationException("Unable to find db.properties");
+        } catch (IOException e) {
+            throw new ConfigurationException("Unable to load db.properties content");
+        }
+        _clusterNodeIP = dbProps.getProperty("cluster.node.IP");
+        if (_clusterNodeIP == null) {
+            _clusterNodeIP = "127.0.0.1";
+        }
+        _clusterNodeIP = _clusterNodeIP.trim();
+
+        if(s_logger.isInfoEnabled()) {
+            s_logger.info("Cluster node IP : " + _clusterNodeIP);
+        }
+
+        if(!NetUtils.isLocalAddress(_clusterNodeIP)) {
+            throw new ConfigurationException("cluster node IP should be valid local address where the server is running, please check your configuration");
+        }
+
+        for(int i = 0; i < DEFAULT_OUTGOING_WORKERS; i++)
+        	_executor.execute(getClusterPduSendingTask());
+        
+        // notification task itself in turn works as a task dispatcher
+        _executor.execute(getClusterPduNotificationTask());
+
+        if (_serviceAdapters == null) {
+            throw new ConfigurationException("Unable to get cluster service adapters");
+        }
+        _currentServiceAdapter = _serviceAdapters.get(0);
+
+        if(_currentServiceAdapter == null) {
+            throw new ConfigurationException("Unable to set current cluster service adapter");
+        }
+
+        checkConflicts();
+
+        if(s_logger.isInfoEnabled()) {
+            s_logger.info("Cluster manager is configured.");
+        }
+        return true;
+    }
+
+    public long getCurrentRunId() {
+        return _runId;
+    }
+
+    public boolean isManagementNodeAlive(long msid) {
+        ManagementServerHostVO mshost = _mshostDao.findByMsid(msid);
+        if(mshost != null) {
+            if (mshost.getLastUpdateTime().getTime() >= DateUtil.currentGMTTime().getTime() - _heartbeatThreshold.value()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public boolean pingManagementNode(long msid) {
+        ManagementServerHostVO mshost = _mshostDao.findByMsid(msid);
+        if(mshost == null) {
+            return false;
+        }
+
+        return pingManagementNode(mshost);
+    }
+
+    private boolean pingManagementNode(ManagementServerHostVO mshost) {
+
+        String targetIp = mshost.getServiceIP();
+        if("127.0.0.1".equals(targetIp) || "0.0.0.0".equals(targetIp)) {
+            s_logger.info("ping management node cluster service can not be performed on self");
+            return false;
+        }
+     
+        int retry = 10;
+        while (--retry > 0) {
+            SocketChannel sch = null;
+            try {
+                s_logger.info("Trying to connect to " + targetIp);
+                sch = SocketChannel.open();
+                sch.configureBlocking(true);
+                sch.socket().setSoTimeout(5000);
+
+                InetSocketAddress addr = new InetSocketAddress(targetIp, mshost.getServicePort());
+                sch.connect(addr);
+                return true;
+            } catch (IOException e) {
+                if (e instanceof ConnectException) {
+                    s_logger.error("Unable to ping management server at " + targetIp + ":" + mshost.getServicePort() + " due to ConnectException", e);
+                	return false;
+                }
+            } finally {
+                if (sch != null) {
+                    try {
+                        sch.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ex) {
+            }
+        }
+        
+        s_logger.error("Unable to ping management server at " + targetIp + ":" + mshost.getServicePort() + " after retries");
+        return false;
+    }
+
+
+    @Override
+    public int getHeartbeatThreshold() {
+        return _heartbeatThreshold.value();
+    }
+
+    public int getHeartbeatInterval() {
+        return _heartbeatInterval.value();
+    }
+
+    private void checkConflicts() throws ConfigurationException {
+        Date cutTime = DateUtil.currentGMTTime();
+        List<ManagementServerHostVO> peers = _mshostDao.getActiveList(new Date(cutTime.getTime() - _heartbeatThreshold.value()));
+        for(ManagementServerHostVO peer : peers) {
+            String peerIP = peer.getServiceIP().trim();
+            if(_clusterNodeIP.equals(peerIP)) {
+                if("127.0.0.1".equals(_clusterNodeIP)) {
+                    if(pingManagementNode(peer.getMsid())) {
+                        String msg = "Detected another management node with localhost IP is already running, please check your cluster configuration";
+                        s_logger.error(msg);
+                        throw new ConfigurationException(msg);
+                    } else {
+                        String msg = "Detected another management node with localhost IP is considered as running in DB, however it is not pingable, we will continue cluster initialization with this management server node";
+                        s_logger.info(msg);
+                    }
+                } else {
+                    if(pingManagementNode(peer.getMsid())) {
+                        String msg = "Detected that another management node with the same IP " + peer.getServiceIP() + " is already running, please check your cluster configuration";
+                        s_logger.error(msg);
+                        throw new ConfigurationException(msg);
+                    } else {
+                        String msg = "Detected that another management node with the same IP " + peer.getServiceIP()
+                                + " is considered as running in DB, however it is not pingable, we will continue cluster initialization with this management server node";
+                        s_logger.info(msg);
+                    }
+                }
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterManagerListener.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManagerListener.java b/framework/cluster/src/com/cloud/cluster/ClusterManagerListener.java
new file mode 100644
index 0000000..bcb1736
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterManagerListener.java
@@ -0,0 +1,25 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.util.List;
+
+public interface ClusterManagerListener {
+	void onManagementNodeJoined(List<ManagementServerHostVO> nodeList, long selfNodeId);
+	void onManagementNodeLeft(List<ManagementServerHostVO> nodeList, long selfNodeId);
+	void onManagementNodeIsolated();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterManagerMBean.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManagerMBean.java b/framework/cluster/src/com/cloud/cluster/ClusterManagerMBean.java
new file mode 100644
index 0000000..961ed72
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterManagerMBean.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+public interface ClusterManagerMBean {
+	public long getMsid();
+	public String getLastUpdateTime();
+	public String getClusterNodeIP();
+	public String getVersion();
+	public int getHeartbeatInterval();
+	public int getHeartbeatThreshold();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterManagerMBeanImpl.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManagerMBeanImpl.java b/framework/cluster/src/com/cloud/cluster/ClusterManagerMBeanImpl.java
new file mode 100644
index 0000000..7071832
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterManagerMBeanImpl.java
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+import javax.management.StandardMBean;
+
+import com.cloud.utils.DateUtil;
+
+public class ClusterManagerMBeanImpl extends StandardMBean implements ClusterManagerMBean {
+	private final ClusterManagerImpl _clusterMgr;
+	private final ManagementServerHostVO _mshostVo;
+	
+	public ClusterManagerMBeanImpl(ClusterManagerImpl clusterMgr, ManagementServerHostVO mshostVo) {
+		super(ClusterManagerMBean.class, false);
+		
+		_clusterMgr = clusterMgr;
+		_mshostVo = mshostVo;
+	}
+	
+	@Override
+    public long getMsid() {
+		return _mshostVo.getMsid();
+	}
+	
+	@Override
+    public String getLastUpdateTime() {
+		Date date = _mshostVo.getLastUpdateTime();
+		return DateUtil.getDateDisplayString(TimeZone.getDefault(), date);
+	}
+	
+	@Override
+    public String getClusterNodeIP() {
+		return _mshostVo.getServiceIP();
+	}
+	
+	@Override
+    public String getVersion() {
+		return _mshostVo.getVersion();
+	}
+	
+	@Override
+    public int getHeartbeatInterval() {
+		return _clusterMgr.getHeartbeatInterval();
+	}
+	
+	@Override
+    public int getHeartbeatThreshold() {
+		return _clusterMgr.getHeartbeatThreshold();
+	}
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterManagerMessage.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManagerMessage.java b/framework/cluster/src/com/cloud/cluster/ClusterManagerMessage.java
new file mode 100644
index 0000000..7f3e596
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterManagerMessage.java
@@ -0,0 +1,44 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.util.List;
+
+public class ClusterManagerMessage {
+	public static enum MessageType { nodeAdded, nodeRemoved, nodeIsolated };
+
+	MessageType _type;
+	List<ManagementServerHostVO> _nodes;
+	
+	public ClusterManagerMessage(MessageType type) {
+		_type = type;
+	}
+	
+	public ClusterManagerMessage(MessageType type, List<ManagementServerHostVO> nodes) {
+		_type = type;
+		_nodes = nodes;
+	}
+	
+	public MessageType getMessageType() {
+		return _type;
+	}
+	
+	public List<ManagementServerHostVO> getNodes() {
+		return _nodes;
+	}
+    
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterNodeJoinEventArgs.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterNodeJoinEventArgs.java b/framework/cluster/src/com/cloud/cluster/ClusterNodeJoinEventArgs.java
new file mode 100644
index 0000000..594862d
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterNodeJoinEventArgs.java
@@ -0,0 +1,43 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.util.List;
+
+import com.cloud.utils.events.EventArgs;
+
+public class ClusterNodeJoinEventArgs extends EventArgs {
+	private static final long serialVersionUID = 6284545402661799476L;
+	
+	private List<ManagementServerHostVO> joinedNodes;
+	private Long self;
+	
+	public ClusterNodeJoinEventArgs(Long self, List<ManagementServerHostVO> joinedNodes) {
+		super(ClusterManager.ALERT_SUBJECT);
+		
+		this.self = self;
+		this.joinedNodes = joinedNodes;
+	}
+	
+	public List<ManagementServerHostVO> getJoinedNodes() {
+		return joinedNodes;
+	}
+
+	public Long getSelf() {
+		return self;
+	}
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterNodeLeftEventArgs.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterNodeLeftEventArgs.java b/framework/cluster/src/com/cloud/cluster/ClusterNodeLeftEventArgs.java
new file mode 100644
index 0000000..be54b9f
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterNodeLeftEventArgs.java
@@ -0,0 +1,44 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.util.List;
+
+import com.cloud.utils.events.EventArgs;
+
+public class ClusterNodeLeftEventArgs extends EventArgs {
+	private static final long serialVersionUID = 7236743316223611935L;
+	
+	private List<ManagementServerHostVO> leftNodes;
+	private Long self;
+	
+	public ClusterNodeLeftEventArgs(Long self, List<ManagementServerHostVO> leftNodes) {
+		super(ClusterManager.ALERT_SUBJECT);
+		
+		this.self = self;
+		this.leftNodes = leftNodes;
+	}
+	
+	public List<ManagementServerHostVO> getLeftNodes() {
+		return leftNodes;
+	}
+
+	public Long getSelf() {
+		return self;
+	}
+}
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterService.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterService.java b/framework/cluster/src/com/cloud/cluster/ClusterService.java
new file mode 100644
index 0000000..295c3b2
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterService.java
@@ -0,0 +1,25 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface ClusterService extends Remote {
+    String execute(ClusterServicePdu pdu) throws RemoteException;
+    boolean ping(String callingPeer) throws RemoteException;
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterServiceAdapter.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceAdapter.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceAdapter.java
new file mode 100644
index 0000000..28e2cab
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterServiceAdapter.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.rmi.RemoteException;
+
+import com.cloud.cluster.ClusterService;
+import com.cloud.utils.component.Adapter;
+
+public interface ClusterServiceAdapter extends Adapter {
+	public ClusterService getPeerService(String strPeer) throws RemoteException;
+	public String getServiceEndpointName(String strPeer);
+	public int getServicePort();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterServicePdu.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServicePdu.java b/framework/cluster/src/com/cloud/cluster/ClusterServicePdu.java
new file mode 100644
index 0000000..81ff5d8
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterServicePdu.java
@@ -0,0 +1,112 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+public class ClusterServicePdu {
+	public final static int PDU_TYPE_MESSAGE = 0;
+	public final static int PDU_TYPE_REQUEST = 1;
+	public final static int PDU_TYPE_RESPONSE = 2;
+	
+    private long sequenceId;
+    private long ackSequenceId;
+    
+    private String sourcePeer;
+    private String destPeer;
+    
+    private long agentId;
+    private boolean stopOnError;
+    private String jsonPackage;
+    
+    private int pduType = PDU_TYPE_MESSAGE;
+    
+    private static long s_nextPduSequenceId = 1;
+    
+    public ClusterServicePdu() {
+        sequenceId = getNextPduSequenceId();
+        ackSequenceId = 0;
+        agentId = 0;
+        stopOnError = false;
+    }
+    
+    public synchronized long getNextPduSequenceId() {
+        return s_nextPduSequenceId++;
+    }
+
+    public long getSequenceId() {
+        return sequenceId;
+    }
+
+    public void setSequenceId(long sequenceId) {
+        this.sequenceId = sequenceId;
+    }
+
+    public long getAckSequenceId() {
+        return ackSequenceId;
+    }
+
+    public void setAckSequenceId(long ackSequenceId) {
+        this.ackSequenceId = ackSequenceId;
+    }
+
+    public String getSourcePeer() {
+        return sourcePeer;
+    }
+
+    public void setSourcePeer(String sourcePeer) {
+        this.sourcePeer = sourcePeer;
+    }
+
+    public String getDestPeer() {
+        return destPeer;
+    }
+
+    public void setDestPeer(String destPeer) {
+        this.destPeer = destPeer;
+    }
+
+    public long getAgentId() {
+        return agentId;
+    }
+
+    public void setAgentId(long agentId) {
+        this.agentId = agentId;
+    }
+
+    public boolean isStopOnError() {
+        return stopOnError;
+    }
+
+    public void setStopOnError(boolean stopOnError) {
+        this.stopOnError = stopOnError;
+    }
+
+    public String getJsonPackage() {
+        return jsonPackage;
+    }
+
+    public void setJsonPackage(String jsonPackage) {
+        this.jsonPackage = jsonPackage;
+    }
+    
+    public int getPduType() {
+    	return pduType;
+    }
+    
+    public void setPduType(int pduType) {
+    	this.pduType = pduType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterServiceRequestPdu.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceRequestPdu.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceRequestPdu.java
new file mode 100644
index 0000000..09bc22e
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterServiceRequestPdu.java
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+public class ClusterServiceRequestPdu extends ClusterServicePdu {
+
+    private String responseResult;
+    private long startTick;
+    private long timeout;
+    
+    public ClusterServiceRequestPdu() {
+        startTick = System.currentTimeMillis();
+        timeout = -1;
+        setPduType(PDU_TYPE_REQUEST);
+    }
+
+    public String getResponseResult() {
+        return responseResult;
+    }
+
+    public void setResponseResult(String responseResult) {
+        this.responseResult = responseResult;
+    }
+
+    public long getStartTick() {
+        return startTick;
+    }
+
+    public void setStartTick(long startTick) {
+        this.startTick = startTick;
+    }
+
+    public long getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(long timeout) {
+        this.timeout = timeout;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java
new file mode 100644
index 0000000..13b466d
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletAdapter.java
@@ -0,0 +1,152 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.config.ConfigDepot;
+import org.apache.cloudstack.config.ConfigKey;
+import org.apache.cloudstack.config.ConfigValue;
+
+import com.cloud.cluster.dao.ManagementServerHostDao;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.component.AdapterBase;
+
+@Component
+@Local(value={ClusterServiceAdapter.class})
+public class ClusterServiceServletAdapter extends AdapterBase implements ClusterServiceAdapter {
+
+    private static final Logger s_logger = Logger.getLogger(ClusterServiceServletAdapter.class);
+    private static final int DEFAULT_SERVICE_PORT = 9090;
+    private static final int DEFAULT_REQUEST_TIMEOUT = 300;			// 300 seconds
+    
+    @Inject private ClusterManager _manager;
+    
+    @Inject private ManagementServerHostDao _mshostDao;
+    @Inject
+    protected ConfigDepot _configDepot;
+    
+    private ClusterServiceServletContainer _servletContainer;
+    
+    private int _clusterServicePort = DEFAULT_SERVICE_PORT;
+    
+    private ConfigValue<Integer> _clusterRequestTimeoutSeconds;
+    
+    @Override
+	public ClusterService getPeerService(String strPeer) throws RemoteException {
+    	try {
+    		init();
+    	} catch (ConfigurationException e) {
+    		s_logger.error("Unable to init ClusterServiceServletAdapter");
+    		throw new RemoteException("Unable to init ClusterServiceServletAdapter");
+    	}
+    	
+    	String serviceUrl = getServiceEndpointName(strPeer);
+    	if(serviceUrl == null)
+    		return null;
+    	
+        return new ClusterServiceServletImpl(serviceUrl, _clusterRequestTimeoutSeconds);
+	}
+    
+    @Override
+	public String getServiceEndpointName(String strPeer) {
+    	try {
+    		init();
+    	} catch (ConfigurationException e) {
+    		s_logger.error("Unable to init ClusterServiceServletAdapter");
+    		return null;
+    	}
+    	
+    	long msid = Long.parseLong(strPeer);
+    	
+    	ManagementServerHostVO mshost = _mshostDao.findByMsid(msid);
+    	if(mshost == null)
+    		return null;
+    	
+    	return composeEndpointName(mshost.getServiceIP(), mshost.getServicePort());
+    }
+    
+    @Override
+	public int getServicePort() {
+    	return _clusterServicePort;
+    }
+    
+    private String composeEndpointName(String nodeIP, int port) {
+    	StringBuffer sb = new StringBuffer();
+    	sb.append("http://").append(nodeIP).append(":").append(port).append("/clusterservice");
+    	return sb.toString();
+    }
+	
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+    	init();
+    	return true;
+    }
+    
+    @Override
+    public boolean start() {
+    	_servletContainer = new ClusterServiceServletContainer();
+    	_servletContainer.start(new ClusterServiceServletHttpHandler(_manager), _clusterServicePort);
+    	return true;
+    }
+    
+    @Override
+    public boolean stop() {
+    	if(_servletContainer != null)
+    		_servletContainer.stop();
+    	return true;
+    }
+    
+    private final ConfigKey<Integer> ClusterMessageTimeOut = new ConfigKey<Integer>(Integer.class, "cluster.message.timeout.seconds", "Advance", ClusterManager.class, "300",
+            "Time (in seconds) to wait before a inter-management server message post times out.", true, "Seconds");
+
+    private void init() throws ConfigurationException {
+    	if(_mshostDao != null)
+    		return;
+    	
+        _clusterRequestTimeoutSeconds = _configDepot.get(ClusterMessageTimeOut);
+    	s_logger.info("Configure cluster request time out. timeout: " + _clusterRequestTimeoutSeconds + " seconds");
+        
+        File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
+        Properties dbProps = new Properties();
+        try {
+			dbProps.load(new FileInputStream(dbPropsFile));
+		} catch (FileNotFoundException e) {
+            throw new ConfigurationException("Unable to find db.properties");
+		} catch (IOException e) {
+            throw new ConfigurationException("Unable to load db.properties content");
+		}
+		
+        _clusterServicePort = NumbersUtil.parseInt(dbProps.getProperty("cluster.servlet.port"), DEFAULT_SERVICE_PORT);
+        if(s_logger.isInfoEnabled())
+        	s_logger.info("Cluster servlet port : " + _clusterServicePort);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java
new file mode 100644
index 0000000..def3e17
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletContainer.java
@@ -0,0 +1,179 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.http.ConnectionClosedException;
+import org.apache.http.HttpException;
+import org.apache.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.http.impl.DefaultHttpResponseFactory;
+import org.apache.http.impl.DefaultHttpServerConnection;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.CoreProtocolPNames;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.BasicHttpProcessor;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.protocol.HttpRequestHandlerRegistry;
+import org.apache.http.protocol.HttpService;
+import org.apache.http.protocol.ResponseConnControl;
+import org.apache.http.protocol.ResponseContent;
+import org.apache.http.protocol.ResponseDate;
+import org.apache.http.protocol.ResponseServer;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.concurrency.NamedThreadFactory;
+
+public class ClusterServiceServletContainer {
+	private static final Logger s_logger = Logger.getLogger(ClusterServiceServletContainer.class);
+	
+	private ListenerThread listenerThread;
+	
+	public ClusterServiceServletContainer() {
+	}
+	
+	public boolean start(HttpRequestHandler requestHandler, int port) {
+	
+		listenerThread = new ListenerThread(requestHandler, port);
+		listenerThread.start();
+		
+		return true;
+	}
+	
+	public void stop() {
+		if(listenerThread != null) {
+			listenerThread.stopRunning();
+		}
+	}
+	
+    static class ListenerThread extends Thread {
+        private HttpService _httpService = null;
+        private volatile ServerSocket _serverSocket = null;
+        private HttpParams _params = null;
+        private ExecutorService _executor;
+
+        public ListenerThread(HttpRequestHandler requestHandler, int port) {
+    		_executor = Executors.newCachedThreadPool(new NamedThreadFactory("Cluster-Listener"));
+        	
+            try {
+                _serverSocket = new ServerSocket(port);
+            } catch (IOException ioex) {
+                s_logger.error("error initializing cluster service servlet container", ioex);
+                return;
+            }
+
+            _params = new BasicHttpParams();
+            _params
+                .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
+                .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
+                .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
+                .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
+                .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");
+
+            // Set up the HTTP protocol processor
+            BasicHttpProcessor httpproc = new BasicHttpProcessor();
+            httpproc.addInterceptor(new ResponseDate());
+            httpproc.addInterceptor(new ResponseServer());
+            httpproc.addInterceptor(new ResponseContent());
+            httpproc.addInterceptor(new ResponseConnControl());
+
+            // Set up request handlers
+            HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
+            reqistry.register("/clusterservice", requestHandler);
+
+            // Set up the HTTP service
+            _httpService = new HttpService(httpproc, new DefaultConnectionReuseStrategy(), new DefaultHttpResponseFactory());
+            _httpService.setParams(_params);
+            _httpService.setHandlerResolver(reqistry);
+        }
+        
+        public void stopRunning() {
+        	if(_serverSocket != null) {
+        		try {
+					_serverSocket.close();
+				} catch (IOException e) {
+				}
+				_serverSocket = null;
+        	}
+        }
+
+        public void run() {
+        	if(s_logger.isInfoEnabled())
+        		s_logger.info("Cluster service servlet container listening on port " + _serverSocket.getLocalPort());
+            
+            while (_serverSocket != null) {
+                try {
+                    // Set up HTTP connection
+                    Socket socket = _serverSocket.accept();
+                    final DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
+                    conn.bind(socket, _params);
+
+                    _executor.execute(new Runnable() {
+                    	public void run() {
+                            HttpContext context = new BasicHttpContext(null);
+                            try {
+                            	while(!Thread.interrupted() && conn.isOpen()) {
+	                            	if(s_logger.isTraceEnabled())
+	                            		s_logger.trace("dispatching cluster request from " + conn.getRemoteAddress().toString());
+	                            	
+	                                _httpService.handleRequest(conn, context);
+	                                
+	                            	if(s_logger.isTraceEnabled())
+	                            		s_logger.trace("Cluster request from " + conn.getRemoteAddress().toString() + " is processed");
+                            	}
+                            } catch (ConnectionClosedException ex) {
+                            	// client close and read time out exceptions are expected
+                            	// when KEEP-AVLIE is enabled
+                                s_logger.trace("Client closed connection", ex);
+                            } catch (IOException ex) {
+                                s_logger.trace("I/O error", ex);
+                            } catch (HttpException ex) {
+                                s_logger.error("Unrecoverable HTTP protocol violation", ex);
+                            } finally {
+                                try {
+                                    conn.shutdown();
+                                } catch (IOException ignore) {
+                                    s_logger.error("unexpected exception", ignore);
+                                }
+                            }
+                    	}
+                    });
+                    
+                } catch (Throwable e) {
+                	s_logger.error("Unexpected exception ", e);
+                
+                	// back off to avoid spinning if the exception condition keeps coming back
+                	try {
+						Thread.sleep(1000);
+					} catch (InterruptedException e1) {
+					}
+                } 
+            }
+            
+            _executor.shutdown();
+        	if(s_logger.isInfoEnabled())
+        		s_logger.info("Cluster service servlet container shutdown");
+        }
+    }
+}


[3/8] Moved ClusterManager into it's own package. Removed the agent load balancing code.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterManagerImpl.java b/server/src/com/cloud/cluster/ClusterManagerImpl.java
deleted file mode 100755
index 5a08f87..0000000
--- a/server/src/com/cloud/cluster/ClusterManagerImpl.java
+++ /dev/null
@@ -1,1517 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.ConnectException;
-import java.net.InetSocketAddress;
-import java.nio.channels.SocketChannel;
-import java.rmi.RemoteException;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.SQLRecoverableException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.ejb.Local;
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import org.apache.log4j.Logger;
-
-import com.cloud.agent.AgentManager;
-import com.cloud.agent.AgentManager.OnError;
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.ChangeAgentAnswer;
-import com.cloud.agent.api.ChangeAgentCommand;
-import com.cloud.agent.api.Command;
-import com.cloud.agent.api.PropagateResourceEventCommand;
-import com.cloud.agent.api.TransferAgentCommand;
-import com.cloud.agent.api.ScheduleHostScanTaskCommand;
-import com.cloud.agent.manager.ClusteredAgentManagerImpl;
-import com.cloud.agent.manager.Commands;
-import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
-import com.cloud.cluster.dao.ManagementServerHostDao;
-import com.cloud.cluster.dao.ManagementServerHostPeerDao;
-import com.cloud.configuration.Config;
-import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.exception.AgentUnavailableException;
-import com.cloud.exception.OperationTimedoutException;
-import com.cloud.host.Host;
-import com.cloud.host.HostVO;
-import com.cloud.host.Status.Event;
-import com.cloud.host.dao.HostDao;
-import com.cloud.resource.ResourceManager;
-import com.cloud.resource.ResourceState;
-import com.cloud.serializer.GsonHelper;
-import com.cloud.utils.DateUtil;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.Profiler;
-import com.cloud.utils.PropertiesUtil;
-import com.cloud.utils.component.ComponentContext;
-import com.cloud.utils.component.ComponentLifecycle;
-import com.cloud.utils.component.ManagerBase;
-import com.cloud.utils.concurrency.NamedThreadFactory;
-import com.cloud.utils.db.ConnectionConcierge;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.SearchCriteria2;
-import com.cloud.utils.db.SearchCriteriaService;
-import com.cloud.utils.db.Transaction;
-import com.cloud.utils.events.SubscriptionMgr;
-import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.exception.ExceptionUtil;
-import com.cloud.utils.mgmt.JmxUtil;
-import com.cloud.utils.net.NetUtils;
-
-import com.google.gson.Gson;
-
-import org.apache.cloudstack.utils.identity.ManagementServerNode;
-
-@Local(value = { ClusterManager.class })
-public class ClusterManagerImpl extends ManagerBase implements ClusterManager {
-    private static final Logger s_logger = Logger.getLogger(ClusterManagerImpl.class);
-
-    private static final int EXECUTOR_SHUTDOWN_TIMEOUT = 1000; // 1 second
-    private static final int DEFAULT_OUTGOING_WORKERS = 5; 
-
-    private final List<ClusterManagerListener> _listeners = new ArrayList<ClusterManagerListener>();
-    private final Map<Long, ManagementServerHostVO> _activePeers = new HashMap<Long, ManagementServerHostVO>();
-    private int _heartbeatInterval = ClusterManager.DEFAULT_HEARTBEAT_INTERVAL;
-    private int _heartbeatThreshold = ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD;
-
-    private final Map<String, ClusterService> _clusterPeers;
-    private final Gson _gson;
-
-    @Inject
-    private AgentManager _agentMgr;
-    @Inject
-    private ClusteredAgentRebalanceService _rebalanceService;
-    @Inject
-    private ResourceManager _resourceMgr;
-
-    private final ScheduledExecutorService _heartbeatScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Cluster-Heartbeat"));
-    private final ExecutorService _notificationExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("Cluster-Notification"));
-    private final List<ClusterManagerMessage> _notificationMsgs = new ArrayList<ClusterManagerMessage>();
-    private ConnectionConcierge _heartbeatConnection = null;
-
-    private final ExecutorService _executor;
-
-    private ClusterServiceAdapter _currentServiceAdapter;
-
-    @Inject
-    private List<ClusterServiceAdapter> _serviceAdapters;
-
-    @Inject private ManagementServerHostDao _mshostDao;
-    @Inject private ManagementServerHostPeerDao _mshostPeerDao;
-    @Inject private HostDao _hostDao;
-    @Inject private HostTransferMapDao _hostTransferDao;
-    @Inject private ConfigurationDao _configDao;
-
-    //
-    // pay attention to _mshostId and _msid
-    // _mshostId is the primary key of management host table
-    // _msid is the unique persistent identifier that peer name is based upon
-    //
-    private Long _mshostId = null;
-    protected long _msId = ManagementServerNode.getManagementServerId();
-    protected long _runId = System.currentTimeMillis();
-
-    private boolean _peerScanInited = false;
-
-    private String _clusterNodeIP = "127.0.0.1";
-    private boolean _agentLBEnabled = false;
-    private double _connectedAgentsThreshold = 0.7;
-    private static boolean _agentLbHappened = false;
-    
-    private final List<ClusterServicePdu> _clusterPduOutgoingQueue = new ArrayList<ClusterServicePdu>();
-    private final List<ClusterServicePdu> _clusterPduIncomingQueue = new ArrayList<ClusterServicePdu>();
-    private final Map<Long, ClusterServiceRequestPdu> _outgoingPdusWaitingForAck = new HashMap<Long, ClusterServiceRequestPdu>();
-    
-    public ClusterManagerImpl() {
-        _clusterPeers = new HashMap<String, ClusterService>();
-
-        _gson = GsonHelper.getGson();
-
-        // executor to perform remote-calls in another thread context, to avoid potential
-        // recursive remote calls between nodes
-        //
-        _executor = Executors.newCachedThreadPool(new NamedThreadFactory("Cluster-Worker"));
-        setRunLevel(ComponentLifecycle.RUN_LEVEL_FRAMEWORK);
-    }
-    
-    private void registerRequestPdu(ClusterServiceRequestPdu pdu) {
-        synchronized(_outgoingPdusWaitingForAck) {
-            _outgoingPdusWaitingForAck.put(pdu.getSequenceId(), pdu);
-        }
-    }
-    
-    private ClusterServiceRequestPdu popRequestPdu(long ackSequenceId) {
-        synchronized(_outgoingPdusWaitingForAck) {
-            if(_outgoingPdusWaitingForAck.get(ackSequenceId) != null) {
-                ClusterServiceRequestPdu pdu = _outgoingPdusWaitingForAck.get(ackSequenceId);
-                _outgoingPdusWaitingForAck.remove(ackSequenceId);
-                return pdu;
-            }
-        }
-        
-        return null;
-    }
-    
-    private void cancelClusterRequestToPeer(String strPeer) {
-        List<ClusterServiceRequestPdu> candidates = new ArrayList<ClusterServiceRequestPdu>();
-        synchronized(_outgoingPdusWaitingForAck) {
-            for(Map.Entry<Long, ClusterServiceRequestPdu> entry : _outgoingPdusWaitingForAck.entrySet()) {
-                if(entry.getValue().getDestPeer().equalsIgnoreCase(strPeer))
-                    candidates.add(entry.getValue());
-            }
-
-            for(ClusterServiceRequestPdu pdu : candidates) {
-                _outgoingPdusWaitingForAck.remove(pdu.getSequenceId());
-            }
-        }
-        
-        for(ClusterServiceRequestPdu pdu : candidates) {
-            s_logger.warn("Cancel cluster request PDU to peer: " + strPeer + ", pdu: " + _gson.toJson(pdu));
-            synchronized(pdu) {
-                pdu.notifyAll();
-            }
-        }
-    }
-    
-    private void addOutgoingClusterPdu(ClusterServicePdu pdu) {
-    	synchronized(_clusterPduOutgoingQueue) {
-    		_clusterPduOutgoingQueue.add(pdu);
-    		_clusterPduOutgoingQueue.notifyAll();
-    	}
-    }
-    
-    private ClusterServicePdu popOutgoingClusterPdu(long timeoutMs) {
-    	synchronized(_clusterPduOutgoingQueue) {
-    		try {
-				_clusterPduOutgoingQueue.wait(timeoutMs);
-			} catch (InterruptedException e) {
-			}
-			
-			if(_clusterPduOutgoingQueue.size() > 0) {
-				ClusterServicePdu pdu = _clusterPduOutgoingQueue.get(0);
-				_clusterPduOutgoingQueue.remove(0);
-				return pdu;
-			}
-    	}
-    	return null;
-    }
-
-    private void addIncomingClusterPdu(ClusterServicePdu pdu) {
-    	synchronized(_clusterPduIncomingQueue) {
-    		_clusterPduIncomingQueue.add(pdu);
-    		_clusterPduIncomingQueue.notifyAll();
-    	}
-    }
-    
-    private ClusterServicePdu popIncomingClusterPdu(long timeoutMs) {
-    	synchronized(_clusterPduIncomingQueue) {
-    		try {
-    			_clusterPduIncomingQueue.wait(timeoutMs);
-			} catch (InterruptedException e) {
-			}
-			
-			if(_clusterPduIncomingQueue.size() > 0) {
-				ClusterServicePdu pdu = _clusterPduIncomingQueue.get(0);
-				_clusterPduIncomingQueue.remove(0);
-				return pdu;
-			}
-    	}
-    	return null;
-    }
-    
-    private Runnable getClusterPduSendingTask() {
-        return new Runnable() {
-            @Override
-            public void run() {
-                onSendingClusterPdu();
-            }
-        };
-    }
-    
-    private Runnable getClusterPduNotificationTask() {
-        return new Runnable() {
-            @Override
-            public void run() {
-                onNotifyingClusterPdu();
-            }
-        };
-    }
-    
-    private void onSendingClusterPdu() {
-        while(true) {
-            try {
-                ClusterServicePdu pdu = popOutgoingClusterPdu(1000);
-                if(pdu == null)
-                	continue;
-                	
-                ClusterService peerService =  null;
-                for(int i = 0; i < 2; i++) {
-                    try {
-                        peerService = getPeerService(pdu.getDestPeer());
-                    } catch (RemoteException e) {
-                        s_logger.error("Unable to get cluster service on peer : " + pdu.getDestPeer());
-                    }
-
-                    if(peerService != null) {
-                        try {
-                            if(s_logger.isDebugEnabled()) {
-                                s_logger.debug("Cluster PDU " + getSelfPeerName() + " -> " + pdu.getDestPeer() + ". agent: " + pdu.getAgentId() 
-                                    + ", pdu seq: " + pdu.getSequenceId() + ", pdu ack seq: " + pdu.getAckSequenceId() + ", json: " + pdu.getJsonPackage());
-                            }
-
-                            long startTick = System.currentTimeMillis();
-                            String strResult = peerService.execute(pdu);
-                            if(s_logger.isDebugEnabled()) {
-                                s_logger.debug("Cluster PDU " + getSelfPeerName() + " -> " + pdu.getDestPeer() + " completed. time: " +
-                                    (System.currentTimeMillis() - startTick) + "ms. agent: " + pdu.getAgentId() 
-                                     + ", pdu seq: " + pdu.getSequenceId() + ", pdu ack seq: " + pdu.getAckSequenceId() + ", json: " + pdu.getJsonPackage());
-                            }
-                            
-                            if("true".equals(strResult))
-                                break;
-                            
-                        } catch (RemoteException e) {
-                            invalidatePeerService(pdu.getDestPeer());
-                            if(s_logger.isInfoEnabled()) {
-                                s_logger.info("Exception on remote execution, peer: " + pdu.getDestPeer() + ", iteration: "
-                                        + i + ", exception message :" + e.getMessage());
-                            }
-                        }
-                    }
-                }
-            } catch(Throwable e) {
-                s_logger.error("Unexcpeted exception: ", e);
-            }
-        }
-    }
-    
-    private void onNotifyingClusterPdu() {
-        while(true) {
-            try {
-                final ClusterServicePdu pdu = popIncomingClusterPdu(1000);
-                if(pdu == null)
-                	continue;
-
-                _executor.execute(new Runnable() {
-                    @Override
-                	public void run() {
-		                if(pdu.getPduType() == ClusterServicePdu.PDU_TYPE_RESPONSE) {
-		                    ClusterServiceRequestPdu requestPdu = popRequestPdu(pdu.getAckSequenceId());
-		                    if(requestPdu != null) {
-		                        requestPdu.setResponseResult(pdu.getJsonPackage());
-		                        synchronized(requestPdu) {
-		                            requestPdu.notifyAll();
-		                        }
-		                    } else {
-		                        s_logger.warn("Original request has already been cancelled. pdu: " + _gson.toJson(pdu));
-		                    }
-		                } else {
-		                    String result = dispatchClusterServicePdu(pdu);
-		                    if(result == null)
-		                        result = "";
-		                    
-		                    if(pdu.getPduType() == ClusterServicePdu.PDU_TYPE_REQUEST) {
-			                    ClusterServicePdu responsePdu = new ClusterServicePdu();
-			                    responsePdu.setPduType(ClusterServicePdu.PDU_TYPE_RESPONSE);
-			                    responsePdu.setSourcePeer(pdu.getDestPeer());
-			                    responsePdu.setDestPeer(pdu.getSourcePeer());
-			                    responsePdu.setAckSequenceId(pdu.getSequenceId());
-			                    responsePdu.setJsonPackage(result);
-			                    
-			                    addOutgoingClusterPdu(responsePdu);
-		                    }
-		                }
-                	}
-                });
-            } catch(Throwable e) {
-                s_logger.error("Unexcpeted exception: ", e);
-            }
-        }
-    }
-
-    private String handleScheduleHostScanTaskCommand(ScheduleHostScanTaskCommand cmd) {
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Intercepting resource manager command: " + _gson.toJson(cmd));
-        }
-
-        try {
-            // schedule a scan task immediately
-            if (_agentMgr instanceof ClusteredAgentManagerImpl) {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Received notification as part of addHost command to start a host scan task");
-                }
-                ClusteredAgentManagerImpl clusteredAgentMgr = (ClusteredAgentManagerImpl)_agentMgr;
-                clusteredAgentMgr.scheduleHostScanTask();
-            }
-        } catch (Exception e) {
-            // Scheduling host scan task in peer MS is a best effort operation during host add, regular host scan
-            // happens at fixed intervals anyways. So handling any exceptions that may be thrown
-            s_logger.warn("Exception happened while trying to schedule host scan task on mgmt server " + getSelfPeerName() + ", ignoring as regular host scan happens at fixed interval anyways", e);
-            return null;
-        }
-
-        Answer[] answers = new Answer[1];
-        answers[0] = new Answer(cmd, true, null);
-        return _gson.toJson(answers);
-    }
-
-    private String dispatchClusterServicePdu(ClusterServicePdu pdu) {
-
-        if(s_logger.isDebugEnabled()) {
-            s_logger.debug("Dispatch ->" + pdu.getAgentId() + ", json: " + pdu.getJsonPackage());
-        }
-
-        Command [] cmds = null;
-        try {
-            cmds = _gson.fromJson(pdu.getJsonPackage(), Command[].class);
-        } catch(Throwable e) {
-            assert(false);
-            s_logger.error("Excection in gson decoding : ", e);
-        }
-        
-        if (cmds.length == 1 && cmds[0] instanceof ChangeAgentCommand) {  //intercepted
-            ChangeAgentCommand cmd = (ChangeAgentCommand)cmds[0];
-
-            if (s_logger.isDebugEnabled()) {
-                s_logger.debug("Intercepting command for agent change: agent " + cmd.getAgentId() + " event: " + cmd.getEvent());
-            }
-            boolean result = false;
-            try {
-                result = executeAgentUserRequest(cmd.getAgentId(), cmd.getEvent());
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Result is " + result);
-                }
-
-            } catch (AgentUnavailableException e) {
-                s_logger.warn("Agent is unavailable", e);
-                return null;
-            }
-
-            Answer[] answers = new Answer[1];
-            answers[0] = new ChangeAgentAnswer(cmd, result);
-            return _gson.toJson(answers);
-        } else if (cmds.length == 1 && cmds[0] instanceof TransferAgentCommand) {
-            TransferAgentCommand cmd = (TransferAgentCommand) cmds[0];
-
-            if (s_logger.isDebugEnabled()) {
-                s_logger.debug("Intercepting command for agent rebalancing: agent " + cmd.getAgentId() + " event: " + cmd.getEvent());
-            }
-            boolean result = false;
-            try {
-                result = rebalanceAgent(cmd.getAgentId(), cmd.getEvent(), cmd.getCurrentOwner(), cmd.getFutureOwner());
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Result is " + result);
-                }
-
-            } catch (AgentUnavailableException e) {
-                s_logger.warn("Agent is unavailable", e);
-                return null;
-            } catch (OperationTimedoutException e) {
-                s_logger.warn("Operation timed out", e);
-                return null;
-            }
-            Answer[] answers = new Answer[1];
-            answers[0] = new Answer(cmd, result, null);
-            return _gson.toJson(answers);
-        } else if (cmds.length == 1 && cmds[0] instanceof PropagateResourceEventCommand ) {
-        	PropagateResourceEventCommand cmd = (PropagateResourceEventCommand) cmds[0];
-        	
-        	s_logger.debug("Intercepting command to propagate event " + cmd.getEvent().name() + " for host " + cmd.getHostId());
-        	
-        	boolean result = false;
-        	try {
-        		result = executeResourceUserRequest(cmd.getHostId(), cmd.getEvent());
-        		s_logger.debug("Result is " + result);
-        	} catch (AgentUnavailableException ex) {
-        		s_logger.warn("Agent is unavailable", ex);
-        		return null;
-        	}
-        	
-        	Answer[] answers = new Answer[1];
-        	answers[0] = new Answer(cmd, result, null);
-        	return _gson.toJson(answers);
-        } else if (cmds.length == 1 && cmds[0] instanceof ScheduleHostScanTaskCommand) {
-            ScheduleHostScanTaskCommand cmd = (ScheduleHostScanTaskCommand) cmds[0];
-            String response = handleScheduleHostScanTaskCommand(cmd);
-            return response;
-        }
-
-        try {
-            long startTick = System.currentTimeMillis();
-            if(s_logger.isDebugEnabled()) {
-                s_logger.debug("Dispatch -> " + pdu.getAgentId() + ", json: " + pdu.getJsonPackage());
-            }
-
-            Answer[] answers = sendToAgent(pdu.getAgentId(), cmds, pdu.isStopOnError());
-            if(answers != null) {
-                String jsonReturn =  _gson.toJson(answers);
-
-                if(s_logger.isDebugEnabled()) {
-                    s_logger.debug("Completed dispatching -> " + pdu.getAgentId() + ", json: " + pdu.getJsonPackage() +
-                            " in " + (System.currentTimeMillis() - startTick) + " ms, return result: " + jsonReturn);
-                }
-
-                return jsonReturn;
-            } else {
-                if(s_logger.isDebugEnabled()) {
-                    s_logger.debug("Completed dispatching -> " + pdu.getAgentId() + ", json: " + pdu.getJsonPackage() +
-                            " in " + (System.currentTimeMillis() - startTick) + " ms, return null result");
-                }
-            }
-        } catch(AgentUnavailableException e) {
-            s_logger.warn("Agent is unavailable", e);
-        } catch (OperationTimedoutException e) {
-            s_logger.warn("Timed Out", e);
-        }
-        
-        return null;
-    }
-
-    @Override
-    public void OnReceiveClusterServicePdu(ClusterServicePdu pdu) {
-    	addIncomingClusterPdu(pdu);
-    }
-    
-    @Override
-    public Answer[] sendToAgent(Long hostId, Command[] cmds, boolean stopOnError) throws AgentUnavailableException, OperationTimedoutException {
-        Commands commands = new Commands(stopOnError ? OnError.Stop : OnError.Continue);
-        for (Command cmd : cmds) {
-            commands.addCommand(cmd);
-        }
-        return _agentMgr.send(hostId, commands);
-    }
-
-    @Override
-    public boolean executeAgentUserRequest(long agentId, Event event) throws AgentUnavailableException {
-        return _agentMgr.executeUserRequest(agentId, event);
-    }
-
-    @Override
-    public Boolean propagateAgentEvent(long agentId, Event event) throws AgentUnavailableException {
-        final String msPeer = getPeerName(agentId);
-        if (msPeer == null) {
-            return null;
-        }
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Propagating agent change request event:" + event.toString() + " to agent:" + agentId);
-        }
-        Command[] cmds = new Command[1];
-        cmds[0] = new ChangeAgentCommand(agentId, event);
-
-        Answer[] answers = execute(msPeer, agentId, cmds, true);
-        if (answers == null) {
-            throw new AgentUnavailableException(agentId);
-        }
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Result for agent change is " + answers[0].getResult());
-        }
-
-        return answers[0].getResult();
-    }
-
-    /**
-     * called by DatabaseUpgradeChecker to see if there are other peers running.
-     * 
-     * @param notVersion
-     *            If version is passed in, the peers CANNOT be running at this version. If version is null, return true if any
-     *            peer is running regardless of version.
-     * @return true if there are peers running and false if not.
-     */
-    public static final boolean arePeersRunning(String notVersion) {
-        return false; // TODO: Leaving this for Kelven to take care of.
-    }
-
-    @Override
-    public void broadcast(long agentId, Command[] cmds) {
-        Date cutTime = DateUtil.currentGMTTime();
-
-        List<ManagementServerHostVO> peers = _mshostDao.getActiveList(new Date(cutTime.getTime() - _heartbeatThreshold));
-        for (ManagementServerHostVO peer : peers) {
-            String peerName = Long.toString(peer.getMsid());
-            if (getSelfPeerName().equals(peerName)) {
-                continue; // Skip myself.
-            }
-            try {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Forwarding " + cmds[0].toString() + " to " + peer.getMsid());
-                }
-                executeAsync(peerName, agentId, cmds, true);
-            } catch (Exception e) {
-                s_logger.warn("Caught exception while talkign to " + peer.getMsid());
-            }
-        }
-    }
-
-    @Override
-    public void executeAsync(String strPeer, long agentId, Command [] cmds, boolean stopOnError) {
-        ClusterServicePdu pdu = new ClusterServicePdu();
-        pdu.setSourcePeer(getSelfPeerName());
-        pdu.setDestPeer(strPeer);
-        pdu.setAgentId(agentId);
-        pdu.setJsonPackage(_gson.toJson(cmds, Command[].class));
-        pdu.setStopOnError(true);
-        addOutgoingClusterPdu(pdu);
-    }
-
-    @Override
-    public Answer[] execute(String strPeer, long agentId, Command [] cmds, boolean stopOnError) {
-        if(s_logger.isDebugEnabled()) {
-            s_logger.debug(getSelfPeerName() + " -> " + strPeer + "." + agentId + " " +
-                    _gson.toJson(cmds, Command[].class));
-        }
-        
-        ClusterServiceRequestPdu pdu = new ClusterServiceRequestPdu();
-        pdu.setSourcePeer(getSelfPeerName());
-        pdu.setDestPeer(strPeer);
-        pdu.setAgentId(agentId);
-        pdu.setJsonPackage(_gson.toJson(cmds, Command[].class));
-        pdu.setStopOnError(stopOnError);
-        registerRequestPdu(pdu);
-        addOutgoingClusterPdu(pdu);
-        
-        synchronized(pdu) {
-            try {
-                pdu.wait();
-            } catch (InterruptedException e) {
-            }
-        }
-
-        if(s_logger.isDebugEnabled()) {
-            s_logger.debug(getSelfPeerName() + " -> " + strPeer + "." + agentId + " completed. result: " +
-                pdu.getResponseResult());
-        }
-        
-        if(pdu.getResponseResult() != null && pdu.getResponseResult().length() > 0) {
-            try {
-                return _gson.fromJson(pdu.getResponseResult(), Answer[].class);
-            } catch(Throwable e) {
-                s_logger.error("Exception on parsing gson package from remote call to " + strPeer);
-            }
-        }
-
-        return null;
-    }
-    
-    @Override
-    public String getPeerName(long agentHostId) {
-
-        HostVO host = _hostDao.findById(agentHostId);
-        if(host != null && host.getManagementServerId() != null) {
-            if(getSelfPeerName().equals(Long.toString(host.getManagementServerId()))) {
-                return null;
-            }
-
-            return Long.toString(host.getManagementServerId());
-        }
-        return null;
-    }
-
-    @Override
-    public ManagementServerHostVO getPeer(String mgmtServerId) {
-        return _mshostDao.findByMsid(Long.valueOf(mgmtServerId));
-    }
-
-    @Override
-    public String getSelfPeerName() {
-        return Long.toString(_msId);
-    }
-
-    @Override
-    public String getSelfNodeIP() {
-        return _clusterNodeIP;
-    }
-
-    @Override
-    public void registerListener(ClusterManagerListener listener) {
-        // Note : we don't check duplicates
-        synchronized (_listeners) {
-
-    		s_logger.info("register cluster listener " + listener.getClass());
-    		
-        	_listeners.add(listener);
-        }
-    }
-
-    @Override
-    public void unregisterListener(ClusterManagerListener listener) {
-        synchronized(_listeners) {
-    		s_logger.info("unregister cluster listener " + listener.getClass());
-        	
-        	_listeners.remove(listener);
-        }
-    }
-
-    public void notifyNodeJoined(List<ManagementServerHostVO> nodeList) {
-        if(s_logger.isDebugEnabled()) {
-            s_logger.debug("Notify management server node join to listeners.");
-
-            for(ManagementServerHostVO mshost : nodeList) {
-                s_logger.debug("Joining node, IP: " + mshost.getServiceIP() + ", msid: " + mshost.getMsid());
-            }
-        }
-
-        synchronized(_listeners) {
-            for(ClusterManagerListener listener : _listeners) {
-                listener.onManagementNodeJoined(nodeList, _mshostId);
-            }
-        }
-
-        SubscriptionMgr.getInstance().notifySubscribers(ClusterManager.ALERT_SUBJECT, this,
-                new ClusterNodeJoinEventArgs(_mshostId, nodeList));
-    }
-
-    public void notifyNodeLeft(List<ManagementServerHostVO> nodeList) {
-        if(s_logger.isDebugEnabled()) {
-            s_logger.debug("Notify management server node left to listeners.");
-        }
-        
-        for(ManagementServerHostVO mshost : nodeList) {
-            if(s_logger.isDebugEnabled())
-                s_logger.debug("Leaving node, IP: " + mshost.getServiceIP() + ", msid: " + mshost.getMsid());
-            cancelClusterRequestToPeer(String.valueOf(mshost.getMsid()));
-        }
-
-        synchronized(_listeners) {
-            for(ClusterManagerListener listener : _listeners) {
-                listener.onManagementNodeLeft(nodeList, _mshostId);
-            }
-        }
-
-        SubscriptionMgr.getInstance().notifySubscribers(ClusterManager.ALERT_SUBJECT, this,
-                new ClusterNodeLeftEventArgs(_mshostId, nodeList));
-    }
-
-    public void notifyNodeIsolated() {
-        if(s_logger.isDebugEnabled())
-            s_logger.debug("Notify management server node isolation to listeners");
-
-        synchronized(_listeners) {
-            for(ClusterManagerListener listener : _listeners) {
-                listener.onManagementNodeIsolated();
-            }
-        }
-    }
-
-    public ClusterService getPeerService(String strPeer) throws RemoteException {
-        synchronized(_clusterPeers) {
-            if(_clusterPeers.containsKey(strPeer)) {
-                return _clusterPeers.get(strPeer);
-            }
-        }
-
-        ClusterService service = _currentServiceAdapter.getPeerService(strPeer);
-
-        if(service != null) {
-            synchronized(_clusterPeers) {
-                // re-check the peer map again to deal with the
-                // race conditions
-                if(!_clusterPeers.containsKey(strPeer)) {
-                    _clusterPeers.put(strPeer, service);
-                }
-            }
-        }
-
-        return service;
-    }
-
-    public void invalidatePeerService(String strPeer) {
-        synchronized(_clusterPeers) {
-            if(_clusterPeers.containsKey(strPeer)) {
-                _clusterPeers.remove(strPeer);
-            }
-        }
-    }
-
-    private Runnable getHeartbeatTask() {
-        return new Runnable() {
-            @Override
-            public void run() {
-                Transaction txn = Transaction.open("ClusterHeartBeat");
-                try {
-                    Profiler profiler = new Profiler();
-                    Profiler profilerHeartbeatUpdate = new Profiler();
-                    Profiler profilerPeerScan = new Profiler();
-                    Profiler profilerAgentLB = new Profiler();
-                    
-                    try {
-                        profiler.start();
-                        
-                        profilerHeartbeatUpdate.start();
-                        txn.transitToUserManagedConnection(getHeartbeatConnection());
-                        if(s_logger.isTraceEnabled()) {
-                            s_logger.trace("Cluster manager heartbeat update, id:" + _mshostId);
-                        }
-    
-                        _mshostDao.update(_mshostId, getCurrentRunId(), DateUtil.currentGMTTime());
-                        profilerHeartbeatUpdate.stop();
-    
-                        profilerPeerScan.start();
-                        if (s_logger.isTraceEnabled()) {
-                            s_logger.trace("Cluster manager peer-scan, id:" + _mshostId);
-                        }
-    
-                        if (!_peerScanInited) {
-                            _peerScanInited = true;
-                            initPeerScan();
-                        }
-                        
-                        peerScan();
-                        profilerPeerScan.stop();
-                        
-                        profilerAgentLB.start();
-                        //initiate agent lb task will be scheduled and executed only once, and only when number of agents loaded exceeds _connectedAgentsThreshold
-                        if (_agentLBEnabled && !_agentLbHappened) {
-                            SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
-                            sc.addAnd(sc.getEntity().getManagementServerId(), Op.NNULL);
-                            sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing);
-                            List<HostVO> allManagedRoutingAgents = sc.list();
-                            
-                            sc = SearchCriteria2.create(HostVO.class);
-                            sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing);
-                            List<HostVO> allAgents = sc.list();
-                            double allHostsCount = allAgents.size();
-                            double managedHostsCount = allManagedRoutingAgents.size();
-                            if (allHostsCount > 0.0) {
-                                double load = managedHostsCount/allHostsCount;
-                                if (load >= _connectedAgentsThreshold) {
-                                    s_logger.debug("Scheduling agent rebalancing task as the average agent load " + load + " is more than the threshold " + _connectedAgentsThreshold);
-                                    _rebalanceService.scheduleRebalanceAgents();
-                                    _agentLbHappened = true;
-                                } else {
-                                    s_logger.trace("Not scheduling agent rebalancing task as the averages load " + load + " is less than the threshold " + _connectedAgentsThreshold);
-                                }
-                            } 
-                        }
-                        profilerAgentLB.stop();
-                    } finally {
-                        profiler.stop();
-                        
-                        if(profiler.getDuration() >= _heartbeatInterval) {
-                            if(s_logger.isDebugEnabled())
-                                s_logger.debug("Management server heartbeat takes too long to finish. profiler: " + profiler.toString() + 
-                                    ", profilerHeartbeatUpdate: " + profilerHeartbeatUpdate.toString() +
-                                    ", profilerPeerScan: " + profilerPeerScan.toString() +
-                                    ", profilerAgentLB: " + profilerAgentLB.toString());
-                        }
-                    }
-                    
-                } catch(CloudRuntimeException e) {
-                    s_logger.error("Runtime DB exception ", e.getCause());
-
-                    if(e.getCause() instanceof ClusterInvalidSessionException) {
-                        s_logger.error("Invalid cluster session found, fence it");
-                        queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeIsolated));
-                    }
-
-                    if(isRootCauseConnectionRelated(e.getCause())) {
-                        s_logger.error("DB communication problem detected, fence it");
-                        queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeIsolated));
-                    }
-
-                    invalidHeartbeatConnection();
-                } catch(ActiveFencingException e) {
-                    queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeIsolated));
-                } catch (Throwable e) {
-                    s_logger.error("Unexpected exception in cluster heartbeat", e);
-                    if(isRootCauseConnectionRelated(e.getCause())) {
-                        s_logger.error("DB communication problem detected, fence it");
-                        queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeIsolated));
-                    }
-
-                    invalidHeartbeatConnection();
-                } finally {
-                    txn.transitToAutoManagedConnection(Transaction.CLOUD_DB);                         
-                    txn.close("ClusterHeartBeat");           	
-                }
-            }
-        };
-    }
-
-    private boolean isRootCauseConnectionRelated(Throwable e) {
-        while (e != null) {
-            if (e instanceof SQLRecoverableException) {
-                return true;
-            }
-
-            e = e.getCause();
-        }
-
-        return false;
-    }
-
-    private Connection getHeartbeatConnection() throws SQLException {
-        if(_heartbeatConnection == null) {
-            Connection conn = Transaction.getStandaloneConnectionWithException();
-            _heartbeatConnection = new ConnectionConcierge("ClusterManagerHeartBeat", conn, false);
-        }
-
-        return _heartbeatConnection.conn();
-    }
-
-    private void invalidHeartbeatConnection() {
-        if(_heartbeatConnection != null) {
-            Connection conn = Transaction.getStandaloneConnection();
-            if (conn != null) {
-                _heartbeatConnection.reset(Transaction.getStandaloneConnection());
-            }
-        }
-    }
-
-    private Runnable getNotificationTask() {
-        return new Runnable() {
-            @Override
-            public void run() {
-                while(true) {
-                    synchronized(_notificationMsgs) {
-                        try {
-                            _notificationMsgs.wait(1000);
-                        } catch (InterruptedException e) {
-                        }
-                    }
-
-                    ClusterManagerMessage msg = null;
-                    while((msg = getNextNotificationMessage()) != null) {
-                        try {
-                            switch(msg.getMessageType()) {
-                            case nodeAdded:
-                                if(msg.getNodes() != null && msg.getNodes().size() > 0) {
-                                    Profiler profiler = new Profiler();
-                                    profiler.start();
-
-                                    notifyNodeJoined(msg.getNodes());
-
-                                    profiler.stop();
-                                    if(profiler.getDuration() > 1000) {
-                                        if(s_logger.isDebugEnabled()) {
-                                            s_logger.debug("Notifying management server join event took " + profiler.getDuration() + " ms");
-                                        }
-                                    } else {
-                                        s_logger.warn("Notifying management server join event took " + profiler.getDuration() + " ms");
-                                    }
-                                }
-                                break;
-
-                            case nodeRemoved:
-                                if(msg.getNodes() != null && msg.getNodes().size() > 0) {
-                                    Profiler profiler = new Profiler();
-                                    profiler.start();
-
-                                    notifyNodeLeft(msg.getNodes());
-
-                                    profiler.stop();
-                                    if(profiler.getDuration() > 1000) {
-                                        if(s_logger.isDebugEnabled()) {
-                                            s_logger.debug("Notifying management server leave event took " + profiler.getDuration() + " ms");
-                                        }
-                                    } else {
-                                        s_logger.warn("Notifying management server leave event took " + profiler.getDuration() + " ms");
-                                    }
-                                }
-                                break;
-
-                            case nodeIsolated:
-                                notifyNodeIsolated();
-                                break;
-
-                            default :
-                                assert(false);
-                                break;
-                            }
-
-                        } catch (Throwable e) {
-                            s_logger.warn("Unexpected exception during cluster notification. ", e);
-                        }
-                    }
-
-                    try { Thread.sleep(1000); } catch (InterruptedException e) {}
-                }
-            }
-        };
-    }
-
-    private void queueNotification(ClusterManagerMessage msg) {
-        synchronized(this._notificationMsgs) {
-            this._notificationMsgs.add(msg);
-            this._notificationMsgs.notifyAll();
-        }
-        
-        switch(msg.getMessageType()) {
-        case nodeAdded:
-            {
-                List<ManagementServerHostVO> l = msg.getNodes();
-                if(l != null && l.size() > 0) {
-                    for(ManagementServerHostVO mshost: l) {
-                        _mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Up);
-                    }
-                }
-            }
-            break;
-            
-        case nodeRemoved:
-            {
-                List<ManagementServerHostVO> l = msg.getNodes();
-                if(l != null && l.size() > 0) {
-                    for(ManagementServerHostVO mshost: l) {
-                        _mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Down);
-                    }
-                }
-            }
-            break;
-            
-        default :
-            break;
-        
-        }
-    }
-
-    private ClusterManagerMessage getNextNotificationMessage() {
-        synchronized(this._notificationMsgs) {
-            if(this._notificationMsgs.size() > 0) {
-                return this._notificationMsgs.remove(0);
-            }
-        }
-
-        return null;
-    }
-
-    private void initPeerScan() {
-        // upon startup, for all inactive management server nodes that we see at startup time, we will send notification also to help upper layer perform
-        // missed cleanup
-        Date cutTime = DateUtil.currentGMTTime();
-        List<ManagementServerHostVO> inactiveList = _mshostDao.getInactiveList(new Date(cutTime.getTime() - _heartbeatThreshold));
-       
-        // We don't have foreign key constraints to enforce the mgmt_server_id integrity in host table, when user manually 
-        // remove records from mshost table, this will leave orphan mgmt_serve_id reference in host table.
-        List<Long> orphanList = _mshostDao.listOrphanMsids();
-        if(orphanList.size() > 0) {
-	        for(Long orphanMsid : orphanList) {
-	        	// construct fake ManagementServerHostVO based on orphan MSID
-	        	s_logger.info("Add orphan management server msid found in host table to initial clustering notification, orphan msid: " + orphanMsid);
-	        	inactiveList.add(new ManagementServerHostVO(orphanMsid, 0, "orphan", 0, new Date()));
-	        }
-        } else {
-        	s_logger.info("We are good, no orphan management server msid in host table is found");
-        }
-        
-        if(inactiveList.size() > 0) {
-        	if(s_logger.isInfoEnabled()) {
-        		s_logger.info("Found " + inactiveList.size() + " inactive management server node based on timestamp");
-        		for(ManagementServerHostVO host : inactiveList)
-        			s_logger.info("management server node msid: " + host.getMsid() + ", name: " + host.getName() + ", service ip: " + host.getServiceIP() + ", version: " + host.getVersion());
-        	}
-
-        	List<ManagementServerHostVO> downHostList = new ArrayList<ManagementServerHostVO>();
-            for(ManagementServerHostVO host : inactiveList) {
-	            if(!pingManagementNode(host)) {
-	                s_logger.warn("Management node " + host.getId() + " is detected inactive by timestamp and also not pingable");
-	                downHostList.add(host);	
-	            }
-            }
-            
-            if(downHostList.size() > 0)
-            	this.queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, downHostList));
-        } else {
-        	s_logger.info("No inactive management server node found");
-        }
-    }
-
-    private void peerScan() throws ActiveFencingException {
-        Date cutTime = DateUtil.currentGMTTime();
-
-        Profiler profiler = new Profiler();
-        profiler.start();
-        
-        Profiler profilerQueryActiveList = new Profiler();
-        profilerQueryActiveList.start();
-        List<ManagementServerHostVO> currentList = _mshostDao.getActiveList(new Date(cutTime.getTime() - _heartbeatThreshold));
-        profilerQueryActiveList.stop();
-
-        Profiler profilerSyncClusterInfo = new Profiler();
-        profilerSyncClusterInfo.start();
-        List<ManagementServerHostVO> removedNodeList = new ArrayList<ManagementServerHostVO>();
-        List<ManagementServerHostVO> invalidatedNodeList = new ArrayList<ManagementServerHostVO>();
-
-        if(_mshostId != null) {
-            
-            if(_mshostPeerDao.countStateSeenInPeers(_mshostId, _runId, ManagementServerHost.State.Down) > 0) {
-                String msg = "We have detected that at least one management server peer reports that this management server is down, perform active fencing to avoid split-brain situation";
-                s_logger.error(msg);
-                throw new ActiveFencingException(msg);
-            }
-            
-            // only if we have already attached to cluster, will we start to check leaving nodes
-            for(Map.Entry<Long, ManagementServerHostVO>  entry : _activePeers.entrySet()) {
-
-                ManagementServerHostVO current = getInListById(entry.getKey(), currentList);
-                if(current == null) {
-                    if(entry.getKey().longValue() != _mshostId.longValue()) {
-                        if(s_logger.isDebugEnabled()) {
-                            s_logger.debug("Detected management node left, id:" + entry.getKey() + ", nodeIP:" + entry.getValue().getServiceIP());
-                        }
-                        removedNodeList.add(entry.getValue());
-                    }
-                } else {
-                    if(current.getRunid() == 0) {
-                        if(entry.getKey().longValue() != _mshostId.longValue()) {
-                            if(s_logger.isDebugEnabled()) {
-                                s_logger.debug("Detected management node left because of invalidated session, id:" + entry.getKey() + ", nodeIP:" + entry.getValue().getServiceIP());
-                            }
-                            invalidatedNodeList.add(entry.getValue());
-                        }
-                    } else {
-                        if(entry.getValue().getRunid() != current.getRunid()) {
-                            if(s_logger.isDebugEnabled()) {
-                                s_logger.debug("Detected management node left and rejoined quickly, id:" + entry.getKey() + ", nodeIP:" + entry.getValue().getServiceIP());
-                            }
-
-                            entry.getValue().setRunid(current.getRunid());
-                        }
-                    }
-                }
-            }
-        }
-        profilerSyncClusterInfo.stop();
-        
-        Profiler profilerInvalidatedNodeList = new Profiler();
-        profilerInvalidatedNodeList.start();
-        // process invalidated node list
-        if(invalidatedNodeList.size() > 0) {
-            for(ManagementServerHostVO mshost : invalidatedNodeList) {
-                _activePeers.remove(mshost.getId());
-                try {
-                    JmxUtil.unregisterMBean("ClusterManager", "Node " + mshost.getId());
-                } catch(Exception e) {
-                    s_logger.warn("Unable to deregiester cluster node from JMX monitoring due to exception " + e.toString());
-                }
-            }
-
-            this.queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, invalidatedNodeList));
-        }
-        profilerInvalidatedNodeList.stop();
-
-        Profiler profilerRemovedList = new Profiler();
-        profilerRemovedList.start();
-        // process removed node list
-        Iterator<ManagementServerHostVO> it = removedNodeList.iterator();
-        while(it.hasNext()) {
-            ManagementServerHostVO mshost = it.next();
-            if(!pingManagementNode(mshost)) {
-                s_logger.warn("Management node " + mshost.getId() + " is detected inactive by timestamp and also not pingable");
-                _activePeers.remove(mshost.getId());
-                try {
-                    JmxUtil.unregisterMBean("ClusterManager", "Node " + mshost.getId());
-                } catch(Exception e) {
-                    s_logger.warn("Unable to deregiester cluster node from JMX monitoring due to exception " + e.toString());
-                }
-            } else {
-                s_logger.info("Management node " + mshost.getId() + " is detected inactive by timestamp but is pingable");
-                it.remove();
-            }
-        }
-
-        if(removedNodeList.size() > 0) {
-            this.queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, removedNodeList));
-        }
-        profilerRemovedList.stop();
-
-        List<ManagementServerHostVO> newNodeList = new ArrayList<ManagementServerHostVO>();
-        for(ManagementServerHostVO mshost : currentList) {
-            if(!_activePeers.containsKey(mshost.getId())) {
-                _activePeers.put(mshost.getId(), mshost);
-
-                if(s_logger.isDebugEnabled()) {
-                    s_logger.debug("Detected management node joined, id:" + mshost.getId() + ", nodeIP:" + mshost.getServiceIP());
-                }
-                newNodeList.add(mshost);
-
-                try {
-                    JmxUtil.registerMBean("ClusterManager", "Node " + mshost.getId(), new ClusterManagerMBeanImpl(this, mshost));
-                } catch(Exception e) {
-                    s_logger.warn("Unable to regiester cluster node into JMX monitoring due to exception " + ExceptionUtil.toString(e));
-                }
-            }
-        }
-
-        if(newNodeList.size() > 0) {
-            this.queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeAdded, newNodeList));
-        }
-        
-        profiler.stop();
-        
-        if(profiler.getDuration() >= this._heartbeatInterval) {
-            if(s_logger.isDebugEnabled())
-                s_logger.debug("Peer scan takes too long to finish. profiler: " + profiler.toString()
-                  + ", profilerQueryActiveList: " + profilerQueryActiveList.toString()
-                  + ", profilerSyncClusterInfo: " + profilerSyncClusterInfo.toString()
-                  + ", profilerInvalidatedNodeList: " + profilerInvalidatedNodeList.toString()
-                  + ", profilerRemovedList: " + profilerRemovedList.toString());
-        }
-    }
-
-    private static ManagementServerHostVO getInListById(Long id, List<ManagementServerHostVO> l) {
-        for(ManagementServerHostVO mshost : l) {
-            if(mshost.getId() == id) {
-                return mshost;
-            }
-        }
-        return null;
-    }
-
-    @Override @DB
-    public boolean start() {
-        if(s_logger.isInfoEnabled()) {
-            s_logger.info("Starting cluster manager, msid : " + _msId);
-        }
-
-        Transaction txn = Transaction.currentTxn();
-        try {
-            txn.start();
-
-            final Class<?> c = this.getClass();
-            String version = c.getPackage().getImplementationVersion();
-
-            ManagementServerHostVO mshost = _mshostDao.findByMsid(_msId);
-            if (mshost == null) {
-                mshost = new ManagementServerHostVO();
-                mshost.setMsid(_msId);
-                mshost.setRunid(this.getCurrentRunId());
-                mshost.setName(NetUtils.getHostName());
-                mshost.setVersion(version);
-                mshost.setServiceIP(_clusterNodeIP);
-                mshost.setServicePort(_currentServiceAdapter.getServicePort());
-                mshost.setLastUpdateTime(DateUtil.currentGMTTime());
-                mshost.setRemoved(null);
-                mshost.setAlertCount(0);
-                mshost.setState(ManagementServerHost.State.Up);
-                _mshostDao.persist(mshost);
-
-                if (s_logger.isInfoEnabled()) {
-                    s_logger.info("New instance of management server msid " + _msId + " is being started");
-                }
-            } else {
-                if (s_logger.isInfoEnabled()) {
-                    s_logger.info("Management server " + _msId + " is being started");
-                }
-
-                _mshostDao.update(mshost.getId(), getCurrentRunId(), NetUtils.getHostName(), version, _clusterNodeIP, _currentServiceAdapter.getServicePort(), DateUtil.currentGMTTime());
-            }
-
-            txn.commit();
-
-            _mshostId = mshost.getId();
-            if (s_logger.isInfoEnabled()) {
-                s_logger.info("Management server (host id : " + _mshostId + ") is being started at " + _clusterNodeIP + ":" + _currentServiceAdapter.getServicePort());
-            }
-            
-            _mshostPeerDao.clearPeerInfo(_mshostId);
-
-            // use seperate thread for heartbeat updates
-            _heartbeatScheduler.scheduleAtFixedRate(getHeartbeatTask(), _heartbeatInterval, _heartbeatInterval, TimeUnit.MILLISECONDS);
-            _notificationExecutor.submit(getNotificationTask());
-
-        } catch (Throwable e) {
-            s_logger.error("Unexpected exception : ", e);
-            txn.rollback();
-
-            throw new CloudRuntimeException("Unable to initialize cluster info into database");
-        }
-
-        if (s_logger.isInfoEnabled()) {
-            s_logger.info("Cluster manager was started successfully");
-        }
-
-        return true;
-    }
-
-    @Override @DB
-    public boolean stop() {
-        if(_mshostId != null) {
-            ManagementServerHostVO mshost = _mshostDao.findByMsid(_msId);
-            mshost.setState(ManagementServerHost.State.Down);
-            _mshostDao.update(_mshostId, mshost);
-        }
-
-        _heartbeatScheduler.shutdownNow();
-        _executor.shutdownNow();
-
-        try {
-            _heartbeatScheduler.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
-            _executor.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-        }
-
-        if(s_logger.isInfoEnabled()) {
-            s_logger.info("Cluster manager is stopped");
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
-        if(s_logger.isInfoEnabled()) {
-            s_logger.info("Start configuring cluster manager : " + name);
-        }
-
-        Map<String, String> configs = _configDao.getConfiguration("management-server", params);
-
-        String value = configs.get("cluster.heartbeat.interval");
-        if (value != null) {
-            _heartbeatInterval = NumbersUtil.parseInt(value, ClusterManager.DEFAULT_HEARTBEAT_INTERVAL);
-        }
-
-        value = configs.get("cluster.heartbeat.threshold");
-        if (value != null) {
-            _heartbeatThreshold = NumbersUtil.parseInt(value, ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD);
-        }
-
-        File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
-        Properties dbProps = new Properties();
-        try {
-            dbProps.load(new FileInputStream(dbPropsFile));
-        } catch (FileNotFoundException e) {
-            throw new ConfigurationException("Unable to find db.properties");
-        } catch (IOException e) {
-            throw new ConfigurationException("Unable to load db.properties content");
-        }
-        _clusterNodeIP = dbProps.getProperty("cluster.node.IP");
-        if (_clusterNodeIP == null) {
-            _clusterNodeIP = "127.0.0.1";
-        }
-        _clusterNodeIP = _clusterNodeIP.trim();
-
-        if(s_logger.isInfoEnabled()) {
-            s_logger.info("Cluster node IP : " + _clusterNodeIP);
-        }
-
-        if(!NetUtils.isLocalAddress(_clusterNodeIP)) {
-            throw new ConfigurationException("cluster node IP should be valid local address where the server is running, please check your configuration");
-        }
-
-        for(int i = 0; i < DEFAULT_OUTGOING_WORKERS; i++)
-        	_executor.execute(getClusterPduSendingTask());
-        
-        // notification task itself in turn works as a task dispatcher
-        _executor.execute(getClusterPduNotificationTask());
-
-        if (_serviceAdapters == null) {
-            throw new ConfigurationException("Unable to get cluster service adapters");
-        }
-        _currentServiceAdapter = _serviceAdapters.get(0);
-
-        if(_currentServiceAdapter == null) {
-            throw new ConfigurationException("Unable to set current cluster service adapter");
-        }
-
-        _agentLBEnabled = Boolean.valueOf(_configDao.getValue(Config.AgentLbEnable.key()));
-        
-        String connectedAgentsThreshold = configs.get("agent.load.threshold");
-        
-        if (connectedAgentsThreshold != null) {
-            _connectedAgentsThreshold = Double.parseDouble(connectedAgentsThreshold);
-        }
-
-        this.registerListener(new LockMasterListener(_msId));
-
-        checkConflicts();
-
-        if(s_logger.isInfoEnabled()) {
-            s_logger.info("Cluster manager is configured.");
-        }
-        return true;
-    }
-
-    @Override
-    public long getManagementNodeId() {
-        return _msId;
-    }
-
-    @Override
-    public long getCurrentRunId() {
-        return _runId;
-    }
-
-    @Override
-    public boolean isManagementNodeAlive(long msid) {
-        ManagementServerHostVO mshost = _mshostDao.findByMsid(msid);
-        if(mshost != null) {
-            if(mshost.getLastUpdateTime().getTime() >=  DateUtil.currentGMTTime().getTime() - _heartbeatThreshold) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public boolean pingManagementNode(long msid) {
-        ManagementServerHostVO mshost = _mshostDao.findByMsid(msid);
-        if(mshost == null) {
-            return false;
-        }
-
-        return pingManagementNode(mshost);
-    }
-
-    private boolean pingManagementNode(ManagementServerHostVO mshost) {
-
-        String targetIp = mshost.getServiceIP();
-        if("127.0.0.1".equals(targetIp) || "0.0.0.0".equals(targetIp)) {
-            s_logger.info("ping management node cluster service can not be performed on self");
-            return false;
-        }
-     
-        int retry = 10;
-        while (--retry > 0) {
-            SocketChannel sch = null;
-            try {
-                s_logger.info("Trying to connect to " + targetIp);
-                sch = SocketChannel.open();
-                sch.configureBlocking(true);
-                sch.socket().setSoTimeout(5000);
-
-                InetSocketAddress addr = new InetSocketAddress(targetIp, mshost.getServicePort());
-                sch.connect(addr);
-                return true;
-            } catch (IOException e) {
-                if (e instanceof ConnectException) {
-                    s_logger.error("Unable to ping management server at " + targetIp + ":" + mshost.getServicePort() + " due to ConnectException", e);
-                	return false;
-                }
-            } finally {
-                if (sch != null) {
-                    try {
-                        sch.close();
-                    } catch (IOException e) {
-                    }
-                }
-            }
-
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException ex) {
-            }
-        }
-        
-        s_logger.error("Unable to ping management server at " + targetIp + ":" + mshost.getServicePort() + " after retries");
-        return false;
-    }
-
-
-    @Override
-    public int getHeartbeatThreshold() {
-        return this._heartbeatThreshold;
-    }
-
-    public int getHeartbeatInterval() {
-        return this._heartbeatInterval;
-    }
-
-    public void setHeartbeatThreshold(int threshold) {
-        _heartbeatThreshold = threshold;
-    }
-
-    private void checkConflicts() throws ConfigurationException {
-        Date cutTime = DateUtil.currentGMTTime();
-        List<ManagementServerHostVO> peers = _mshostDao.getActiveList(new Date(cutTime.getTime() - _heartbeatThreshold));
-        for(ManagementServerHostVO peer : peers) {
-            String peerIP = peer.getServiceIP().trim();
-            if(_clusterNodeIP.equals(peerIP)) {
-                if("127.0.0.1".equals(_clusterNodeIP)) {
-                    if(pingManagementNode(peer.getMsid())) {
-                        String msg = "Detected another management node with localhost IP is already running, please check your cluster configuration";
-                        s_logger.error(msg);
-                        throw new ConfigurationException(msg);
-                    } else {
-                        String msg = "Detected another management node with localhost IP is considered as running in DB, however it is not pingable, we will continue cluster initialization with this management server node";
-                        s_logger.info(msg);
-                    }
-                } else {
-                    if(pingManagementNode(peer.getMsid())) {
-                        String msg = "Detected that another management node with the same IP " + peer.getServiceIP() + " is already running, please check your cluster configuration";
-                        s_logger.error(msg);
-                        throw new ConfigurationException(msg);
-                    } else {
-                        String msg = "Detected that another management node with the same IP " + peer.getServiceIP()
-                                + " is considered as running in DB, however it is not pingable, we will continue cluster initialization with this management server node";
-                        s_logger.info(msg);
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean rebalanceAgent(long agentId, Event event, long currentOwnerId, long futureOwnerId) throws AgentUnavailableException, OperationTimedoutException {
-        return _rebalanceService.executeRebalanceRequest(agentId, currentOwnerId, futureOwnerId, event);
-    }
-
-    @Override
-    public  boolean isAgentRebalanceEnabled() {
-        return _agentLBEnabled;
-    }
-    
-    @Override
-    public Boolean propagateResourceEvent(long agentId, ResourceState.Event event) throws AgentUnavailableException {
-        final String msPeer = getPeerName(agentId);
-        if (msPeer == null) {
-            return null;
-        }
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Propagating agent change request event:" + event.toString() + " to agent:" + agentId);
-        }
-        Command[] cmds = new Command[1];
-        cmds[0] = new PropagateResourceEventCommand(agentId, event);
-
-        Answer[] answers = execute(msPeer, agentId, cmds, true);
-        if (answers == null) {
-            throw new AgentUnavailableException(agentId);
-        }
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Result for agent change is " + answers[0].getResult());
-        }
-
-        return answers[0].getResult();
-    }
-    
-    @Override
-    public boolean executeResourceUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException {
-        return _resourceMgr.executeUserRequest(hostId, event);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterManagerListener.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterManagerListener.java b/server/src/com/cloud/cluster/ClusterManagerListener.java
deleted file mode 100644
index bcb1736..0000000
--- a/server/src/com/cloud/cluster/ClusterManagerListener.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.List;
-
-public interface ClusterManagerListener {
-	void onManagementNodeJoined(List<ManagementServerHostVO> nodeList, long selfNodeId);
-	void onManagementNodeLeft(List<ManagementServerHostVO> nodeList, long selfNodeId);
-	void onManagementNodeIsolated();
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterManagerMBean.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterManagerMBean.java b/server/src/com/cloud/cluster/ClusterManagerMBean.java
deleted file mode 100644
index 9804f23..0000000
--- a/server/src/com/cloud/cluster/ClusterManagerMBean.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-public interface ClusterManagerMBean {
-	public long getMsid();
-	public String getLastUpdateTime();
-	public String getClusterNodeIP();
-	public String getVersion();
-	public int getHeartbeatInterval();
-	public int getHeartbeatThreshold();
-	public void setHeartbeatThreshold(int threshold);
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterManagerMBeanImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterManagerMBeanImpl.java b/server/src/com/cloud/cluster/ClusterManagerMBeanImpl.java
deleted file mode 100644
index 51b3b42..0000000
--- a/server/src/com/cloud/cluster/ClusterManagerMBeanImpl.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.Date;
-import java.util.TimeZone;
-
-import javax.management.StandardMBean;
-
-import com.cloud.utils.DateUtil;
-
-public class ClusterManagerMBeanImpl extends StandardMBean implements ClusterManagerMBean {
-	private ClusterManagerImpl _clusterMgr;
-	private ManagementServerHostVO _mshostVo;
-	
-	public ClusterManagerMBeanImpl(ClusterManagerImpl clusterMgr, ManagementServerHostVO mshostVo) {
-		super(ClusterManagerMBean.class, false);
-		
-		_clusterMgr = clusterMgr;
-		_mshostVo = mshostVo;
-	}
-	
-	public long getMsid() {
-		return _mshostVo.getMsid();
-	}
-	
-	public String getLastUpdateTime() {
-		Date date = _mshostVo.getLastUpdateTime();
-		return DateUtil.getDateDisplayString(TimeZone.getDefault(), date);
-	}
-	
-	public String getClusterNodeIP() {
-		return _mshostVo.getServiceIP();
-	}
-	
-	public String getVersion() {
-		return _mshostVo.getVersion();
-	}
-	
-	public int getHeartbeatInterval() {
-		return _clusterMgr.getHeartbeatInterval();
-	}
-	
-	public int getHeartbeatThreshold() {
-		return _clusterMgr.getHeartbeatThreshold();
-	}
-	
-	public void setHeartbeatThreshold(int threshold) {
-		// to avoid accidentally screwing up cluster manager, we put some guarding logic here
-    	if(threshold >= ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD)
-    		_clusterMgr.setHeartbeatThreshold(threshold);
-	}
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterManagerMessage.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterManagerMessage.java b/server/src/com/cloud/cluster/ClusterManagerMessage.java
deleted file mode 100644
index 7f3e596..0000000
--- a/server/src/com/cloud/cluster/ClusterManagerMessage.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.List;
-
-public class ClusterManagerMessage {
-	public static enum MessageType { nodeAdded, nodeRemoved, nodeIsolated };
-
-	MessageType _type;
-	List<ManagementServerHostVO> _nodes;
-	
-	public ClusterManagerMessage(MessageType type) {
-		_type = type;
-	}
-	
-	public ClusterManagerMessage(MessageType type, List<ManagementServerHostVO> nodes) {
-		_type = type;
-		_nodes = nodes;
-	}
-	
-	public MessageType getMessageType() {
-		return _type;
-	}
-	
-	public List<ManagementServerHostVO> getNodes() {
-		return _nodes;
-	}
-    
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterNodeJoinEventArgs.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterNodeJoinEventArgs.java b/server/src/com/cloud/cluster/ClusterNodeJoinEventArgs.java
deleted file mode 100644
index 594862d..0000000
--- a/server/src/com/cloud/cluster/ClusterNodeJoinEventArgs.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.List;
-
-import com.cloud.utils.events.EventArgs;
-
-public class ClusterNodeJoinEventArgs extends EventArgs {
-	private static final long serialVersionUID = 6284545402661799476L;
-	
-	private List<ManagementServerHostVO> joinedNodes;
-	private Long self;
-	
-	public ClusterNodeJoinEventArgs(Long self, List<ManagementServerHostVO> joinedNodes) {
-		super(ClusterManager.ALERT_SUBJECT);
-		
-		this.self = self;
-		this.joinedNodes = joinedNodes;
-	}
-	
-	public List<ManagementServerHostVO> getJoinedNodes() {
-		return joinedNodes;
-	}
-
-	public Long getSelf() {
-		return self;
-	}
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterNodeLeftEventArgs.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterNodeLeftEventArgs.java b/server/src/com/cloud/cluster/ClusterNodeLeftEventArgs.java
deleted file mode 100644
index be54b9f..0000000
--- a/server/src/com/cloud/cluster/ClusterNodeLeftEventArgs.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.List;
-
-import com.cloud.utils.events.EventArgs;
-
-public class ClusterNodeLeftEventArgs extends EventArgs {
-	private static final long serialVersionUID = 7236743316223611935L;
-	
-	private List<ManagementServerHostVO> leftNodes;
-	private Long self;
-	
-	public ClusterNodeLeftEventArgs(Long self, List<ManagementServerHostVO> leftNodes) {
-		super(ClusterManager.ALERT_SUBJECT);
-		
-		this.self = self;
-		this.leftNodes = leftNodes;
-	}
-	
-	public List<ManagementServerHostVO> getLeftNodes() {
-		return leftNodes;
-	}
-
-	public Long getSelf() {
-		return self;
-	}
-}
-

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterService.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterService.java b/server/src/com/cloud/cluster/ClusterService.java
deleted file mode 100644
index 295c3b2..0000000
--- a/server/src/com/cloud/cluster/ClusterService.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-public interface ClusterService extends Remote {
-    String execute(ClusterServicePdu pdu) throws RemoteException;
-    boolean ping(String callingPeer) throws RemoteException;
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterServiceAdapter.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterServiceAdapter.java b/server/src/com/cloud/cluster/ClusterServiceAdapter.java
deleted file mode 100644
index 28e2cab..0000000
--- a/server/src/com/cloud/cluster/ClusterServiceAdapter.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.rmi.RemoteException;
-
-import com.cloud.cluster.ClusterService;
-import com.cloud.utils.component.Adapter;
-
-public interface ClusterServiceAdapter extends Adapter {
-	public ClusterService getPeerService(String strPeer) throws RemoteException;
-	public String getServiceEndpointName(String strPeer);
-	public int getServicePort();
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterServicePdu.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterServicePdu.java b/server/src/com/cloud/cluster/ClusterServicePdu.java
deleted file mode 100644
index 81ff5d8..0000000
--- a/server/src/com/cloud/cluster/ClusterServicePdu.java
+++ /dev/null
@@ -1,112 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-public class ClusterServicePdu {
-	public final static int PDU_TYPE_MESSAGE = 0;
-	public final static int PDU_TYPE_REQUEST = 1;
-	public final static int PDU_TYPE_RESPONSE = 2;
-	
-    private long sequenceId;
-    private long ackSequenceId;
-    
-    private String sourcePeer;
-    private String destPeer;
-    
-    private long agentId;
-    private boolean stopOnError;
-    private String jsonPackage;
-    
-    private int pduType = PDU_TYPE_MESSAGE;
-    
-    private static long s_nextPduSequenceId = 1;
-    
-    public ClusterServicePdu() {
-        sequenceId = getNextPduSequenceId();
-        ackSequenceId = 0;
-        agentId = 0;
-        stopOnError = false;
-    }
-    
-    public synchronized long getNextPduSequenceId() {
-        return s_nextPduSequenceId++;
-    }
-
-    public long getSequenceId() {
-        return sequenceId;
-    }
-
-    public void setSequenceId(long sequenceId) {
-        this.sequenceId = sequenceId;
-    }
-
-    public long getAckSequenceId() {
-        return ackSequenceId;
-    }
-
-    public void setAckSequenceId(long ackSequenceId) {
-        this.ackSequenceId = ackSequenceId;
-    }
-
-    public String getSourcePeer() {
-        return sourcePeer;
-    }
-
-    public void setSourcePeer(String sourcePeer) {
-        this.sourcePeer = sourcePeer;
-    }
-
-    public String getDestPeer() {
-        return destPeer;
-    }
-
-    public void setDestPeer(String destPeer) {
-        this.destPeer = destPeer;
-    }
-
-    public long getAgentId() {
-        return agentId;
-    }
-
-    public void setAgentId(long agentId) {
-        this.agentId = agentId;
-    }
-
-    public boolean isStopOnError() {
-        return stopOnError;
-    }
-
-    public void setStopOnError(boolean stopOnError) {
-        this.stopOnError = stopOnError;
-    }
-
-    public String getJsonPackage() {
-        return jsonPackage;
-    }
-
-    public void setJsonPackage(String jsonPackage) {
-        this.jsonPackage = jsonPackage;
-    }
-    
-    public int getPduType() {
-    	return pduType;
-    }
-    
-    public void setPduType(int pduType) {
-    	this.pduType = pduType;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterServiceRequestPdu.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterServiceRequestPdu.java b/server/src/com/cloud/cluster/ClusterServiceRequestPdu.java
deleted file mode 100644
index 09bc22e..0000000
--- a/server/src/com/cloud/cluster/ClusterServiceRequestPdu.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-public class ClusterServiceRequestPdu extends ClusterServicePdu {
-
-    private String responseResult;
-    private long startTick;
-    private long timeout;
-    
-    public ClusterServiceRequestPdu() {
-        startTick = System.currentTimeMillis();
-        timeout = -1;
-        setPduType(PDU_TYPE_REQUEST);
-    }
-
-    public String getResponseResult() {
-        return responseResult;
-    }
-
-    public void setResponseResult(String responseResult) {
-        this.responseResult = responseResult;
-    }
-
-    public long getStartTick() {
-        return startTick;
-    }
-
-    public void setStartTick(long startTick) {
-        this.startTick = startTick;
-    }
-
-    public long getTimeout() {
-        return timeout;
-    }
-
-    public void setTimeout(long timeout) {
-        this.timeout = timeout;
-    }
-}


[4/8] Moved ClusterManager into it's own package. Removed the agent load balancing code.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java
new file mode 100644
index 0000000..2d77ce0
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java
@@ -0,0 +1,192 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URLDecoder;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.entity.BasicHttpEntity;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.util.EntityUtils;
+import org.apache.log4j.Logger;
+
+public class ClusterServiceServletHttpHandler implements HttpRequestHandler {
+    private static final Logger s_logger = Logger.getLogger(ClusterServiceServletHttpHandler.class);
+
+    private final ClusterManager manager;
+
+    public ClusterServiceServletHttpHandler(ClusterManager manager) {
+        this.manager = manager;
+    }
+
+    @Override
+    public void handle(HttpRequest request, HttpResponse response, HttpContext context)
+    throws HttpException, IOException {
+
+        try {
+            if(s_logger.isTraceEnabled()) {
+                s_logger.trace("Start Handling cluster HTTP request");
+            }
+
+            parseRequest(request);
+            handleRequest(request, response);
+
+            if(s_logger.isTraceEnabled()) {
+                s_logger.trace("Handle cluster HTTP request done");
+            }
+
+        } catch(Throwable e) {
+            if(s_logger.isDebugEnabled()) {
+                s_logger.debug("Exception " + e.toString());
+            }
+
+            try {
+            	writeResponse(response, HttpStatus.SC_INTERNAL_SERVER_ERROR, null);
+            } catch(Throwable e2) {
+                if(s_logger.isDebugEnabled()) {
+                    s_logger.debug("Exception " + e2.toString());
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void parseRequest(HttpRequest request) throws IOException {
+        if(request instanceof HttpEntityEnclosingRequest) {
+            HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest)request;
+
+            String body = EntityUtils.toString(entityRequest.getEntity());
+            if(body != null) {
+                String[] paramArray = body.split("&");
+                if(paramArray != null) {
+                    for (String paramEntry : paramArray) {
+                        String[] paramValue = paramEntry.split("=");
+                        if (paramValue.length != 2) {
+                            continue;
+                        }
+
+                        String name = URLDecoder.decode(paramValue[0]);
+                        String value = URLDecoder.decode(paramValue[1]);
+
+                        if(s_logger.isTraceEnabled()) {
+                            s_logger.trace("Parsed request parameter " + name + "=" + value);
+                        }
+                        request.getParams().setParameter(name, value);
+                    }
+                }
+            }
+        }
+    }
+
+    private void writeResponse(HttpResponse response, int statusCode, String content) {
+        if(content == null) {
+            content = "";
+        }
+        response.setStatusCode(statusCode);
+        BasicHttpEntity body = new BasicHttpEntity();
+        body.setContentType("text/html; charset=UTF-8");
+
+        byte[] bodyData = content.getBytes();
+        body.setContent(new ByteArrayInputStream(bodyData));
+        body.setContentLength(bodyData.length);
+        response.setEntity(body);
+    }
+
+    protected void handleRequest(HttpRequest req, HttpResponse response) {
+        String method = (String)req.getParams().getParameter("method");
+
+        int nMethod = RemoteMethodConstants.METHOD_UNKNOWN;
+        String responseContent = null;
+        try {
+            if(method != null) {
+                nMethod = Integer.parseInt(method);
+            }
+
+            switch(nMethod) {
+            case RemoteMethodConstants.METHOD_DELIVER_PDU :
+                responseContent = handleDeliverPduMethodCall(req);
+                break;
+
+            case RemoteMethodConstants.METHOD_PING :
+                responseContent = handlePingMethodCall(req);
+                break;
+
+            case RemoteMethodConstants.METHOD_UNKNOWN :
+            default :
+                assert(false);
+                s_logger.error("unrecognized method " + nMethod);
+                break;
+            }
+        } catch(Throwable e) {
+            s_logger.error("Unexpected exception when processing cluster service request : ", e);
+        }
+
+        if(responseContent != null) {
+        	if(s_logger.isTraceEnabled())
+        		s_logger.trace("Write reponse with HTTP OK " + responseContent);
+        	
+            writeResponse(response, HttpStatus.SC_OK, responseContent);
+        } else {
+        	if(s_logger.isTraceEnabled())
+        		s_logger.trace("Write reponse with HTTP Bad request");
+        	
+            writeResponse(response, HttpStatus.SC_BAD_REQUEST, null);
+        }
+    }
+
+    private String handleDeliverPduMethodCall(HttpRequest req) {
+        
+        String pduSeq = (String)req.getParams().getParameter("pduSeq");
+        String pduAckSeq = (String)req.getParams().getParameter("pduAckSeq");
+        String sourcePeer = (String)req.getParams().getParameter("sourcePeer");
+        String destPeer = (String)req.getParams().getParameter("destPeer");
+        String agentId = (String)req.getParams().getParameter("agentId");
+        String gsonPackage = (String)req.getParams().getParameter("gsonPackage");
+        String stopOnError = (String)req.getParams().getParameter("stopOnError");
+        String pduType = (String)req.getParams().getParameter("pduType");
+
+        ClusterServicePdu pdu = new ClusterServicePdu();
+        pdu.setSourcePeer(sourcePeer);
+        pdu.setDestPeer(destPeer);
+        pdu.setAgentId(Long.parseLong(agentId));
+        pdu.setSequenceId(Long.parseLong(pduSeq));
+        pdu.setAckSequenceId(Long.parseLong(pduAckSeq));
+        pdu.setJsonPackage(gsonPackage);
+        pdu.setStopOnError("1".equals(stopOnError));
+        pdu.setPduType(Integer.parseInt(pduType));
+        
+        manager.OnReceiveClusterServicePdu(pdu);
+        return "true";
+    }
+
+    private String handlePingMethodCall(HttpRequest req) {
+        String callingPeer = (String)req.getParams().getParameter("callingPeer");
+
+        if(s_logger.isDebugEnabled()) {
+            s_logger.debug("Handle ping request from " + callingPeer);
+        }
+
+        return "true";
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletImpl.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterServiceServletImpl.java b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletImpl.java
new file mode 100644
index 0000000..c3ed3fe
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterServiceServletImpl.java
@@ -0,0 +1,148 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpClientParams;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.config.ConfigValue;
+
+public class ClusterServiceServletImpl implements ClusterService {
+    private static final long serialVersionUID = 4574025200012566153L;
+    private static final Logger s_logger = Logger.getLogger(ClusterServiceServletImpl.class);
+    
+    private String _serviceUrl;
+
+    private ConfigValue<Integer> _requestTimeoutSeconds;
+    protected static HttpClient s_client = null;
+    
+    public ClusterServiceServletImpl() {
+    }
+
+    public ClusterServiceServletImpl(String serviceUrl, ConfigValue<Integer> requestTimeoutSeconds) {
+        s_logger.info("Setup cluster service servlet. service url: " + serviceUrl + ", request timeout: " + requestTimeoutSeconds.value() + " seconds");
+    	
+        _serviceUrl = serviceUrl;
+        _requestTimeoutSeconds = requestTimeoutSeconds;
+    }
+    
+    @Override
+    public String execute(ClusterServicePdu pdu) throws RemoteException {
+
+        HttpClient client = getHttpClient();
+        PostMethod method = new PostMethod(_serviceUrl);
+
+        method.addParameter("method", Integer.toString(RemoteMethodConstants.METHOD_DELIVER_PDU));
+        method.addParameter("sourcePeer", pdu.getSourcePeer());
+        method.addParameter("destPeer", pdu.getDestPeer());
+        method.addParameter("pduSeq", Long.toString(pdu.getSequenceId()));
+        method.addParameter("pduAckSeq", Long.toString(pdu.getAckSequenceId()));
+        method.addParameter("agentId", Long.toString(pdu.getAgentId()));
+        method.addParameter("gsonPackage", pdu.getJsonPackage());
+        method.addParameter("stopOnError", pdu.isStopOnError() ? "1" : "0");
+        method.addParameter("pduType", Integer.toString(pdu.getPduType()));
+
+        return executePostMethod(client, method);
+    }
+
+    @Override
+    public boolean ping(String callingPeer) throws RemoteException {
+        if(s_logger.isDebugEnabled()) {
+            s_logger.debug("Ping at " + _serviceUrl);
+        }
+
+        HttpClient client = getHttpClient();
+        PostMethod method = new PostMethod(_serviceUrl);
+
+        method.addParameter("method", Integer.toString(RemoteMethodConstants.METHOD_PING));
+        method.addParameter("callingPeer", callingPeer);
+        
+        String returnVal =  executePostMethod(client, method);
+        if("true".equalsIgnoreCase(returnVal)) {
+            return true;
+        }
+        return false;
+    }
+
+    private String executePostMethod(HttpClient client, PostMethod method) {
+        int response = 0;
+        String result = null;
+        try {
+            long startTick = System.currentTimeMillis();
+            response = client.executeMethod(method);
+            if(response == HttpStatus.SC_OK) {
+                result = method.getResponseBodyAsString();
+                if(s_logger.isDebugEnabled()) {
+                    s_logger.debug("POST " + _serviceUrl + " response :" + result + ", responding time: "
+                            + (System.currentTimeMillis() - startTick) + " ms");
+                }
+            } else {
+                s_logger.error("Invalid response code : " + response + ", from : "
+                        + _serviceUrl + ", method : " + method.getParameter("method")
+                        + " responding time: " + (System.currentTimeMillis() - startTick));
+            }
+        } catch (HttpException e) {
+            s_logger.error("HttpException from : " + _serviceUrl + ", method : " + method.getParameter("method"));
+        } catch (IOException e) {
+            s_logger.error("IOException from : " + _serviceUrl + ", method : " + method.getParameter("method"));
+        } catch(Throwable e) {
+            s_logger.error("Exception from : " + _serviceUrl + ", method : " + method.getParameter("method") + ", exception :", e);
+        } finally {
+            method.releaseConnection();
+        }
+
+        return result;
+    }
+    
+    private HttpClient getHttpClient() {
+
+    	if(s_client == null) {
+    		MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
+    		mgr.getParams().setDefaultMaxConnectionsPerHost(4);
+    		
+    		// TODO make it configurable
+    		mgr.getParams().setMaxTotalConnections(1000);
+    		
+	        s_client = new HttpClient(mgr);
+	        HttpClientParams clientParams = new HttpClientParams();
+            clientParams.setSoTimeout(_requestTimeoutSeconds.value() * 1000);
+	        
+	        s_client.setParams(clientParams);
+    	}
+    	return s_client;
+    }
+
+    // for test purpose only
+    public static void main(String[] args) {
+/*
+        ClusterServiceServletImpl service = new ClusterServiceServletImpl("http://localhost:9090/clusterservice", 300);
+        try {
+            String result = service.execute("test", 1, "{ p1:v1, p2:v2 }", true);
+            System.out.println(result);
+        } catch (RemoteException e) {
+        }
+*/
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ManagementServerHost.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ManagementServerHost.java b/framework/cluster/src/com/cloud/cluster/ManagementServerHost.java
new file mode 100644
index 0000000..a5764fb
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ManagementServerHost.java
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+
+public interface ManagementServerHost {
+    long getId();
+
+    public static enum State {
+        Up, Starting, Down
+    };
+
+    long getMsid();
+
+    State getState();
+
+    String getVersion();
+
+    String getServiceIP();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ManagementServerHostPeerVO.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ManagementServerHostPeerVO.java b/framework/cluster/src/com/cloud/cluster/ManagementServerHostPeerVO.java
new file mode 100644
index 0000000..060dd0a
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ManagementServerHostPeerVO.java
@@ -0,0 +1,119 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import com.cloud.utils.DateUtil;
+
+@Entity
+@Table(name="mshost_peer")
+public class ManagementServerHostPeerVO {
+    
+    @Id
+    @GeneratedValue(strategy=GenerationType.IDENTITY)
+    @Column(name="id")
+    private long id;
+    
+    @Column(name="owner_mshost", updatable=true, nullable=false)
+    private long ownerMshost;
+    
+    @Column(name="peer_mshost", updatable=true, nullable=false)
+    private long peerMshost;
+    
+    @Column(name="peer_runid", updatable=true, nullable=false)
+    private long peerRunid;
+
+    @Column(name="peer_state", updatable = true, nullable=false)
+    @Enumerated(value=EnumType.STRING)
+    private ManagementServerHost.State peerState;
+    
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name="last_update", updatable=true, nullable=true)
+    private Date lastUpdateTime;
+
+    public ManagementServerHostPeerVO() {
+    }
+    
+    public ManagementServerHostPeerVO(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState) {
+        this.ownerMshost = ownerMshost;
+        this.peerMshost = peerMshost;
+        this.peerRunid = peerRunid;
+        this.peerState = peerState;
+        
+        lastUpdateTime = DateUtil.currentGMTTime();
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public long getOwnerMshost() {
+        return ownerMshost;
+    }
+
+    public void setOwnerMshost(long ownerMshost) {
+        this.ownerMshost = ownerMshost;
+    }
+
+    public long getPeerMshost() {
+        return peerMshost;
+    }
+
+    public void setPeerMshost(long peerMshost) {
+        this.peerMshost = peerMshost;
+    }
+
+    public long getPeerRunid() {
+        return peerRunid;
+    }
+
+    public void setPeerRunid(long peerRunid) {
+        this.peerRunid = peerRunid;
+    }
+
+    public ManagementServerHost.State getPeerState() {
+        return peerState;
+    }
+
+    public void setPeerState(ManagementServerHost.State peerState) {
+        this.peerState = peerState;
+    }
+
+    public Date getLastUpdateTime() {
+        return lastUpdateTime;
+    }
+
+    public void setLastUpdateTime(Date lastUpdateTime) {
+        this.lastUpdateTime = lastUpdateTime;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ManagementServerHostVO.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ManagementServerHostVO.java b/framework/cluster/src/com/cloud/cluster/ManagementServerHostVO.java
new file mode 100644
index 0000000..966a874
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ManagementServerHostVO.java
@@ -0,0 +1,182 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name="mshost")
+public class ManagementServerHostVO implements ManagementServerHost {
+
+	@Id
+	@GeneratedValue(strategy=GenerationType.IDENTITY)
+	@Column(name="id")
+	private long id;
+
+	@Column(name="msid", updatable=true, nullable=false)
+	private long msid;
+	
+	@Column(name="runid", updatable=true, nullable=false)
+	private long runid;
+
+	@Column(name="name", updatable=true, nullable=true)
+	private String name;
+	
+    @Column(name="state", updatable = true, nullable=false)
+    @Enumerated(value=EnumType.STRING)
+	private ManagementServerHost.State state;
+	
+	@Column(name="version", updatable=true, nullable=true)
+	private String version;
+	
+	@Column(name="service_ip", updatable=true, nullable=false)
+	private String serviceIP;
+	
+	@Column(name="service_port", updatable=true, nullable=false)
+	private int servicePort;
+	
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name="last_update", updatable=true, nullable=true)
+    private Date lastUpdateTime;
+    
+    @Column(name=GenericDao.REMOVED_COLUMN)
+    private Date removed;
+    
+	@Column(name="alert_count", updatable=true, nullable=false)
+	private int alertCount;
+
+    public ManagementServerHostVO() {
+    }
+    
+    public ManagementServerHostVO(long msid, long runid, String serviceIP, int servicePort, Date updateTime) {
+    	this.msid = msid;
+    	this.runid = runid;
+    	this.serviceIP = serviceIP;
+    	this.servicePort = servicePort;
+    	lastUpdateTime = updateTime;
+    }
+    
+	@Override
+    public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+	
+	public long getRunid() {
+		return runid;
+	}
+	
+	public void setRunid(long runid) {
+		this.runid = runid;
+	}
+
+	@Override
+	public long getMsid() {
+		return msid;
+	}
+
+	public void setMsid(long msid) {
+		this.msid = msid;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	@Override
+	public ManagementServerHost.State getState() {
+		return state;
+	}
+	
+	public void setState(ManagementServerHost.State state) {
+		this.state = state;
+	}
+	
+	@Override
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public String getServiceIP() {
+		return serviceIP;
+	}
+
+	public void setServiceIP(String serviceIP) {
+		this.serviceIP = serviceIP;
+	}
+
+	public int getServicePort() {
+		return servicePort;
+	}
+
+	public void setServicePort(int servicePort) {
+		this.servicePort = servicePort;
+	}
+
+	public Date getLastUpdateTime() {
+		return lastUpdateTime;
+	}
+
+	public void setLastUpdateTime(Date lastUpdateTime) {
+		this.lastUpdateTime = lastUpdateTime;
+	}
+	
+	public Date getRemoved() {
+		return removed;
+	}
+	
+	public void setRemoved(Date removedTime) {
+		removed = removedTime;
+	}
+	
+	public int getAlertCount() {
+		return alertCount; 
+	}
+	
+	public void setAlertCount(int count) {
+		alertCount = count;
+	}
+	
+	@Override
+    public String toString() {
+        return new StringBuilder("ManagementServer[").append("-").append(id).append("-").append(msid).append("-").append(state).append("]").toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/RemoteMethodConstants.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/RemoteMethodConstants.java b/framework/cluster/src/com/cloud/cluster/RemoteMethodConstants.java
new file mode 100644
index 0000000..1174bd3
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/RemoteMethodConstants.java
@@ -0,0 +1,23 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+public interface RemoteMethodConstants {
+    public static final int METHOD_UNKNOWN = 0;
+    public static final int METHOD_PING = 4;
+    public static final int METHOD_DELIVER_PDU = 5;
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostDao.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostDao.java b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostDao.java
new file mode 100644
index 0000000..fec0679
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostDao.java
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster.dao;
+
+import java.util.Date;
+import java.util.List;
+
+import com.cloud.cluster.ManagementServerHost;
+import com.cloud.cluster.ManagementServerHost.State;
+import com.cloud.cluster.ManagementServerHostVO;
+import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.GenericDao;
+
+public interface ManagementServerHostDao extends GenericDao<ManagementServerHostVO, Long> {
+    @Override
+    boolean remove(Long id);
+
+	ManagementServerHostVO findByMsid(long msid);
+	int increaseAlertCount(long id);
+	
+	void update(long id, long runid, String name, String version, String serviceIP, int servicePort, Date lastUpdate);
+	void update(long id, long runid, Date lastUpdate);
+	List<ManagementServerHostVO> getActiveList(Date cutTime);
+	List<ManagementServerHostVO> getInactiveList(Date cutTime);
+
+	void invalidateRunSession(long id, long runid);
+	
+	void update(long id, long runId, State state, Date lastUpdate);
+	
+	List<ManagementServerHostVO> listBy(ManagementServerHost.State...states);
+	public List<Long> listOrphanMsids();
+
+	ManagementServerHostVO findOneInUpState(Filter filter);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java
new file mode 100644
index 0000000..879c4ce
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java
@@ -0,0 +1,274 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster.dao;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.cluster.ClusterInvalidSessionException;
+import com.cloud.cluster.ManagementServerHost;
+import com.cloud.cluster.ManagementServerHost.State;
+import com.cloud.cluster.ManagementServerHostVO;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@Local(value={ManagementServerHostDao.class})
+public class ManagementServerHostDaoImpl extends GenericDaoBase<ManagementServerHostVO, Long> implements ManagementServerHostDao {
+    private static final Logger s_logger = Logger.getLogger(ManagementServerHostDaoImpl.class);
+    
+    private final SearchBuilder<ManagementServerHostVO> MsIdSearch;
+    private final SearchBuilder<ManagementServerHostVO> ActiveSearch;
+    private final SearchBuilder<ManagementServerHostVO> InactiveSearch;
+    private final SearchBuilder<ManagementServerHostVO> StateSearch;
+
+	@Override
+    public void invalidateRunSession(long id, long runid) {
+	    Transaction txn = Transaction.currentTxn();
+        PreparedStatement pstmt = null;
+        try {
+            pstmt = txn.prepareAutoCloseStatement("update mshost set runid=0, state='Down' where id=? and runid=?");
+            pstmt.setLong(1, id);
+            pstmt.setLong(2, runid);
+            
+            pstmt.executeUpdate();
+        } catch (SQLException e) {
+        	throw new CloudRuntimeException("DB exception on " + pstmt.toString(), e);
+        }
+	}
+	
+	@Override
+    public ManagementServerHostVO findByMsid(long msid) {
+        SearchCriteria<ManagementServerHostVO> sc = MsIdSearch.create();
+        sc.setParameters("msid", msid);
+		
+		List<ManagementServerHostVO> l = listIncludingRemovedBy(sc);
+		if(l != null && l.size() > 0) {
+            return l.get(0);
+        }
+		 
+		return null;
+	}
+	
+	@Override
+    @DB
+	public void update(long id, long runid, String name, String version, String serviceIP, int servicePort, Date lastUpdate) {
+        Transaction txn = Transaction.currentTxn();
+        PreparedStatement pstmt = null;
+        try {
+            txn.start();
+            
+            pstmt = txn.prepareAutoCloseStatement("update mshost set name=?, version=?, service_ip=?, service_port=?, last_update=?, removed=null, alert_count=0, runid=?, state=? where id=?");
+            pstmt.setString(1, name);
+            pstmt.setString(2, version);
+            pstmt.setString(3, serviceIP);
+            pstmt.setInt(4, servicePort);
+            pstmt.setString(5, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate));
+            pstmt.setLong(6, runid);
+            pstmt.setString(7, ManagementServerHost.State.Up.toString());
+            pstmt.setLong(8, id);
+            
+            pstmt.executeUpdate();
+            txn.commit();
+        } catch(Exception e) {
+            s_logger.warn("Unexpected exception, ", e);
+        }
+	}
+	
+	@Override
+    @DB
+    public boolean remove(Long id) {
+        Transaction txn = Transaction.currentTxn();
+    
+        try {
+        	txn.start();
+        	
+        	ManagementServerHostVO msHost = findById(id);
+        	msHost.setState(ManagementServerHost.State.Down);
+        	super.remove(id);
+        	
+        	txn.commit();
+        	return true;
+        } catch(Exception e) {
+            s_logger.warn("Unexpected exception, ", e);
+        }
+        
+        return false;
+    }
+
+	@Override
+    @DB
+	public void update(long id, long runid, Date lastUpdate) {
+        Transaction txn = Transaction.currentTxn();
+        PreparedStatement pstmt = null;
+        try {
+            txn.start();
+            
+            pstmt = txn.prepareAutoCloseStatement("update mshost set last_update=?, removed=null, alert_count=0 where id=? and runid=?");
+            pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate));
+            pstmt.setLong(2, id);
+            pstmt.setLong(3, runid);
+            
+            int count = pstmt.executeUpdate();
+            txn.commit();
+
+            if(count < 1) {
+                throw new CloudRuntimeException("Invalid cluster session detected", new ClusterInvalidSessionException("runid " + runid + " is no longer valid"));
+            }
+        } catch(Exception e) {
+            s_logger.warn("Unexpected exception, ", e);
+        }
+	}
+	
+	@Override
+    public List<ManagementServerHostVO> getActiveList(Date cutTime) {
+	    SearchCriteria<ManagementServerHostVO> sc = ActiveSearch.create();
+	    sc.setParameters("lastUpdateTime", cutTime);
+	    
+	    return listIncludingRemovedBy(sc);
+	}
+
+	@Override
+    public List<ManagementServerHostVO> getInactiveList(Date cutTime) {
+	    SearchCriteria<ManagementServerHostVO> sc = InactiveSearch.create();
+	    sc.setParameters("lastUpdateTime", cutTime);
+	    
+	    return listIncludingRemovedBy(sc);
+	}
+	
+	@Override
+    @DB
+	public int increaseAlertCount(long id) {
+        Transaction txn = Transaction.currentTxn();
+        PreparedStatement pstmt = null;
+        int changedRows = 0;
+        try {
+            txn.start();
+            
+            pstmt = txn.prepareAutoCloseStatement("update mshost set alert_count=alert_count+1 where id=? and alert_count=0");
+            pstmt.setLong(1, id);
+            
+            changedRows = pstmt.executeUpdate();
+            txn.commit();
+        } catch(Exception e) {
+            s_logger.warn("Unexpected exception, ", e);
+            txn.rollback();
+        }
+        
+        return changedRows;
+	}
+	
+	protected ManagementServerHostDaoImpl() {
+		MsIdSearch = createSearchBuilder();
+		MsIdSearch.and("msid",  MsIdSearch.entity().getMsid(), SearchCriteria.Op.EQ);
+		MsIdSearch.done();
+		
+	    ActiveSearch = createSearchBuilder();
+	    ActiveSearch.and("lastUpdateTime", ActiveSearch.entity().getLastUpdateTime(),  SearchCriteria.Op.GT);
+	    ActiveSearch.and("removed", ActiveSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
+	    ActiveSearch.done();
+
+	    InactiveSearch = createSearchBuilder();
+	    InactiveSearch.and("lastUpdateTime", InactiveSearch.entity().getLastUpdateTime(),  SearchCriteria.Op.LTEQ);
+	    InactiveSearch.and("removed", InactiveSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
+	    InactiveSearch.done();
+	    
+	    StateSearch = createSearchBuilder();
+	    StateSearch.and("state", StateSearch.entity().getState(), SearchCriteria.Op.IN);
+	    StateSearch.done();
+	}
+	
+	
+	@Override
+    public void update(long id, long runId, State state, Date lastUpdate) {
+	    Transaction txn = Transaction.currentTxn();
+        PreparedStatement pstmt = null;
+        try {
+            pstmt = txn.prepareAutoCloseStatement("update mshost set state=?, last_update=? where id=? and runid=?");
+            pstmt.setString(1, state.toString());
+            pstmt.setString(2, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate));
+            pstmt.setLong(3, id);
+            pstmt.setLong(4, runId);
+            
+            int count = pstmt.executeUpdate();
+            
+            if(count < 1) {
+                throw new CloudRuntimeException("Invalid cluster session detected", new ClusterInvalidSessionException("runid " + runId + " is no longer valid"));
+            }
+        } catch (SQLException e) {
+            throw new CloudRuntimeException("DB exception on " + pstmt.toString(), e);
+        }
+    }
+	
+	@Override
+	public List<ManagementServerHostVO> listBy(ManagementServerHost.State...states) {
+	    SearchCriteria<ManagementServerHostVO> sc = StateSearch.create();
+
+        sc.setParameters("state", (Object[]) states);
+        
+        return listBy(sc);
+	}
+	
+	@Override
+	public List<Long> listOrphanMsids() {
+		List<Long> orphanList = new ArrayList<Long>();
+		
+	    Transaction txn = Transaction.currentTxn();
+        PreparedStatement pstmt = null;
+        try {
+            pstmt = txn.prepareAutoCloseStatement(
+            	"select t.mgmt_server_id from (select mgmt_server_id, count(*) as count from host group by mgmt_server_id) as t WHERE t.count > 0 AND t.mgmt_server_id NOT IN (select msid from mshost)");
+
+            ResultSet rs = pstmt.executeQuery();
+            while(rs.next()) {
+            	orphanList.add(rs.getLong(1));
+            }
+        } catch (SQLException e) {
+            throw new CloudRuntimeException("DB exception on " + pstmt.toString(), e);
+        }
+        
+        return orphanList;
+	}
+
+	@Override
+	public ManagementServerHostVO findOneInUpState(Filter filter) {
+	    SearchCriteria<ManagementServerHostVO> sc = StateSearch.create();
+
+        sc.setParameters("state", ManagementServerHost.State.Up);
+        
+        List<ManagementServerHostVO> mshosts =  listBy(sc, filter);
+        if(mshosts != null && mshosts.size() > 0){
+        	return mshosts.get(0);	
+        }
+        return null;
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostPeerDao.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostPeerDao.java b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostPeerDao.java
new file mode 100644
index 0000000..14c872a
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostPeerDao.java
@@ -0,0 +1,27 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster.dao;
+
+import com.cloud.cluster.ManagementServerHost;
+import com.cloud.cluster.ManagementServerHostPeerVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface ManagementServerHostPeerDao extends GenericDao<ManagementServerHostPeerVO, Long> {
+    void clearPeerInfo(long ownerMshost);
+    void updatePeerInfo(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState);
+    int countStateSeenInPeers(long mshost, long runid, ManagementServerHost.State state);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostPeerDaoImpl.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostPeerDaoImpl.java b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostPeerDaoImpl.java
new file mode 100644
index 0000000..8ef2e82
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/dao/ManagementServerHostPeerDaoImpl.java
@@ -0,0 +1,106 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.cluster.ManagementServerHost;
+import com.cloud.cluster.ManagementServerHostPeerVO;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+
+@Local(value={ManagementServerHostPeerDao.class})
+public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementServerHostPeerVO, Long> implements ManagementServerHostPeerDao {
+    private static final Logger s_logger = Logger.getLogger(ManagementServerHostPeerDaoImpl.class);
+    
+    private final SearchBuilder<ManagementServerHostPeerVO> ClearPeerSearch;
+    private final SearchBuilder<ManagementServerHostPeerVO> FindForUpdateSearch;
+    private final SearchBuilder<ManagementServerHostPeerVO> CountSearch;
+
+    public ManagementServerHostPeerDaoImpl() {
+        ClearPeerSearch = createSearchBuilder();
+        ClearPeerSearch.and("ownerMshost", ClearPeerSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ);
+        ClearPeerSearch.done();
+        
+        FindForUpdateSearch = createSearchBuilder();
+        FindForUpdateSearch.and("ownerMshost", FindForUpdateSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ);
+        FindForUpdateSearch.and("peerMshost", FindForUpdateSearch.entity().getPeerMshost(), SearchCriteria.Op.EQ);
+        FindForUpdateSearch.and("peerRunid", FindForUpdateSearch.entity().getPeerRunid(), SearchCriteria.Op.EQ);
+        FindForUpdateSearch.done();
+        
+        CountSearch = createSearchBuilder();
+        CountSearch.and("peerMshost", CountSearch.entity().getPeerMshost(), SearchCriteria.Op.EQ);
+        CountSearch.and("peerRunid", CountSearch.entity().getPeerRunid(), SearchCriteria.Op.EQ);
+        CountSearch.and("peerState", CountSearch.entity().getPeerState(), SearchCriteria.Op.EQ);
+        CountSearch.done();
+    }
+    
+    @Override
+    @DB
+    public void clearPeerInfo(long ownerMshost) {
+        SearchCriteria<ManagementServerHostPeerVO>  sc = ClearPeerSearch.create();
+        sc.setParameters("ownerMshost", ownerMshost);
+        
+        expunge(sc);
+    }
+    
+    @Override
+    @DB
+    public void updatePeerInfo(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState) {
+        Transaction txn = Transaction.currentTxn();
+        try {
+            txn.start();
+        
+            SearchCriteria<ManagementServerHostPeerVO> sc = FindForUpdateSearch.create();
+            sc.setParameters("ownerMshost", ownerMshost);
+            sc.setParameters("peerMshost", peerMshost);
+            sc.setParameters("peerRunid", peerRunid);
+            List<ManagementServerHostPeerVO> l = listBy(sc);
+            if(l.size() == 1) {
+                ManagementServerHostPeerVO peer = l.get(0);
+                peer.setPeerState(peerState);
+                update(peer.getId(), peer);
+            } else {
+                ManagementServerHostPeerVO peer = new ManagementServerHostPeerVO(ownerMshost, peerMshost, peerRunid, peerState);
+                persist(peer);
+            }
+            txn.commit();
+        } catch(Exception e) {
+            s_logger.warn("Unexpected exception, ", e);
+            txn.rollback();
+        }
+    }
+    
+    @Override
+    @DB
+    public int countStateSeenInPeers(long mshost, long runid, ManagementServerHost.State state) {
+        SearchCriteria<ManagementServerHostPeerVO> sc = CountSearch.create();
+        sc.setParameters("peerMshost", mshost);
+        sc.setParameters("peerRunid", runid);
+        sc.setParameters("peerState", state);
+        
+        List<ManagementServerHostPeerVO> l = listBy(sc);
+        return l.size();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/pom.xml
----------------------------------------------------------------------
diff --git a/framework/pom.xml b/framework/pom.xml
index ddcdcb0..12cb946 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -34,5 +34,7 @@
     <module>rest</module>
     <module>events</module>
     <module>jobs</module>
+	<module>cluster</module>
+	<module>db</module>
   </modules>
 </project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 4511804..484d603 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -34,6 +34,11 @@
       <version>${project.version}</version>
     </dependency>
     <dependency>
+      <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-framework-cluster</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>servlet-api</artifactId>
       <version>${cs.servlet.version}</version>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
index 4fdb3c6..a399af3 100755
--- a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
+++ b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
@@ -44,22 +44,30 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
 
 import org.apache.log4j.Logger;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Component;
+
+import com.google.gson.Gson;
+
+import org.apache.cloudstack.config.ConfigDepot;
+import org.apache.cloudstack.config.ConfigKey;
+import org.apache.cloudstack.config.ConfigValue;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
 
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.CancelCommand;
+import com.cloud.agent.api.ChangeAgentAnswer;
 import com.cloud.agent.api.ChangeAgentCommand;
 import com.cloud.agent.api.Command;
-import com.cloud.agent.api.TransferAgentCommand;
+import com.cloud.agent.api.PropagateResourceEventCommand;
 import com.cloud.agent.api.ScheduleHostScanTaskCommand;
+import com.cloud.agent.api.TransferAgentCommand;
 import com.cloud.agent.transport.Request;
 import com.cloud.agent.transport.Request.Version;
 import com.cloud.agent.transport.Response;
 import com.cloud.api.ApiDBUtils;
 import com.cloud.cluster.ClusterManager;
 import com.cloud.cluster.ClusterManagerListener;
+import com.cloud.cluster.ClusterServicePdu;
 import com.cloud.cluster.ClusteredAgentRebalanceService;
 import com.cloud.cluster.ManagementServerHost;
 import com.cloud.cluster.ManagementServerHostVO;
@@ -68,7 +76,6 @@ import com.cloud.cluster.agentlb.HostTransferMapVO;
 import com.cloud.cluster.agentlb.HostTransferMapVO.HostTransferState;
 import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
 import com.cloud.cluster.dao.ManagementServerHostDao;
-import com.cloud.configuration.Config;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.OperationTimedoutException;
@@ -76,10 +83,11 @@ import com.cloud.host.Host;
 import com.cloud.host.HostVO;
 import com.cloud.host.Status;
 import com.cloud.host.Status.Event;
+import com.cloud.resource.ResourceState;
 import com.cloud.resource.ServerResource;
 import com.cloud.storage.resource.DummySecondaryStorageResource;
 import com.cloud.utils.DateUtil;
-import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.Profiler;
 import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.db.SearchCriteria.Op;
 import com.cloud.utils.db.SearchCriteria2;
@@ -98,10 +106,10 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
     public final static long STARTUP_DELAY = 5000;
     public final static long SCAN_INTERVAL = 90000; // 90 seconds, it takes 60 sec for xenserver to fail login
     public final static int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 5; // 5 seconds
-    public long _loadSize = 100;
-    protected int _directAgentScanInterval = 90; // 90 seconds
     protected Set<Long> _agentToTransferIds = new HashSet<Long>();
 
+    Gson _gson;
+
     @Inject
     protected ClusterManager _clusterMgr = null;
 
@@ -118,30 +126,46 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
     @Inject protected List<AgentLoadBalancerPlanner> _lbPlanners;
 
     @Inject ConfigurationDao _configDao;
+    @Inject
+    ConfigDepot _configDepot;
 
     protected ClusteredAgentManagerImpl() {
         super();
     }
 
+    protected final ConfigKey<Boolean> EnableLB = new ConfigKey<Boolean>(Boolean.class, "agent.lb.enabled", "Advanced", AgentManager.class, "false",
+            "Enable agent load balancing between management server nodes", true, "True/False");
+    protected final ConfigKey<Double> ConnectedAgentThreshold = new ConfigKey<Double>(Double.class, "agent.load.threshold", "Advanced", AgentManager.class, "0.7",
+            "What percentage of the agents can be held by one management server before load balancing happens", true, "0-1");
+    protected final ConfigKey<Integer> LoadSize = new ConfigKey<Integer>(Integer.class, "direct.agent.load.size", "Advanced", AgentManager.class, "16",
+            "How many agents to connect to in each round", true, "");
+    protected final ConfigKey<Integer> ScanInterval = new ConfigKey<Integer>(Integer.class, "direct.agent.scan.interval", "Advanced", AgentManager.class, "90",
+            "Interval between scans to load agents", false, "Seconds");
+    
+
+    protected ConfigValue<Boolean> _agentLBEnabled;
+    protected ConfigValue<Double> _connectedAgentsThreshold;
+    protected ConfigValue<Integer> _loadSize;
+    protected ConfigValue<Integer> _directAgentScanInterval;
+
     @Override
     public boolean configure(String name, Map<String, Object> xmlParams) throws ConfigurationException {
         _peers = new HashMap<String, SocketChannel>(7);
         _sslEngines = new HashMap<String, SSLEngine>(7);
-        _nodeId = _clusterMgr.getManagementNodeId();
+        _nodeId = ManagementServerNode.getManagementServerId();
 
         s_logger.info("Configuring ClusterAgentManagerImpl. management server node id(msid): " + _nodeId);
 
-        Map<String, String> params = _configDao.getConfiguration(xmlParams);
-        String value = params.get(Config.DirectAgentLoadSize.key());
-        _loadSize = NumbersUtil.parseInt(value, 16);
-
-        value = params.get(Config.DirectAgentScanInterval.key());
-        _directAgentScanInterval = NumbersUtil.parseInt(value, 90); // defaulted to 90 seconds
+        _loadSize = _configDepot.get(LoadSize);
+        _directAgentScanInterval = _configDepot.get(ScanInterval).setMultiplier(1000);
+        _agentLBEnabled = _configDepot.get(EnableLB);
+        _connectedAgentsThreshold = _configDepot.get(ConnectedAgentThreshold);
 
         ClusteredAgentAttache.initialize(this);
 
         _clusterMgr.registerListener(this);
-
+        _clusterMgr.registerDispatcher(new ClusterDispatcher());
+        
         return super.configure(name, xmlParams);
     }
 
@@ -150,13 +174,13 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
         if (!super.start()) {
             return false;
         }
-        _timer.schedule(new DirectAgentScanTimerTask(), STARTUP_DELAY, _directAgentScanInterval * 1000);
+        _timer.schedule(new DirectAgentScanTimerTask(), STARTUP_DELAY, _directAgentScanInterval.value());
         if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Scheduled direct agent scan task to run at an interval of " + _directAgentScanInterval + " seconds");
+            s_logger.debug("Scheduled direct agent scan task to run at an interval of " + _directAgentScanInterval.value() + " seconds");
         }
 
         // schedule transfer scan executor - if agent LB is enabled
-        if (_clusterMgr.isAgentRebalanceEnabled()) {
+        if (isAgentRebalanceEnabled()) {
             s_transferExecutor.scheduleAtFixedRate(getTransferScanTask(), 60000, ClusteredAgentRebalanceService.DEFAULT_TRANSFER_CHECK_INTERVAL,
                     TimeUnit.MILLISECONDS);
         }
@@ -182,7 +206,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
 
         // for agents that are self-managed, threshold to be considered as disconnected after pingtimeout
         long cutSeconds = (System.currentTimeMillis() >> 10) - (_pingTimeout);
-        List<HostVO> hosts = _hostDao.findAndUpdateDirectAgentToLoad(cutSeconds, _loadSize, _nodeId);
+        List<HostVO> hosts = _hostDao.findAndUpdateDirectAgentToLoad(cutSeconds, _loadSize.value().longValue(), _nodeId);
         List<HostVO> appliances = _hostDao.findAndUpdateApplianceToLoad(cutSeconds, _nodeId);
         hosts.addAll(appliances);
 
@@ -319,7 +343,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
             AgentAttache attache = findAttache(hostId);
             if (attache != null) {
                 //don't process disconnect if the host is being rebalanced
-                if (_clusterMgr.isAgentRebalanceEnabled()) {
+                if (isAgentRebalanceEnabled()) {
                     HostTransferMapVO transferVO = _hostTransferDao.findById(hostId);
                     if (transferVO != null) {
                         if (transferVO.getFutureOwner() == _nodeId && transferVO.getState() == HostTransferState.TransferStarted) {
@@ -351,7 +375,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
     public boolean reconnect(final long hostId) {
         Boolean result;
         try {
-	        result = _clusterMgr.propagateAgentEvent(hostId, Event.ShutdownRequested);
+            result = propagateAgentEvent(hostId, Event.ShutdownRequested);
 	        if (result != null) {
 	            return result;
 	        }
@@ -366,7 +390,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
     public void notifyNodesInCluster(AgentAttache attache) {
         s_logger.debug("Notifying other nodes of to disconnect");
         Command[] cmds = new Command[] { new ChangeAgentCommand(attache.getId(), Event.AgentDisconnected) };
-        _clusterMgr.broadcast(attache.getId(), cmds);
+        _clusterMgr.broadcast(attache.getId(), _gson.toJson(cmds));
     }
 
     // notifies MS peers to schedule a host scan task immediately, triggered during addHost operation
@@ -375,7 +399,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
             s_logger.debug("Notifying other MS nodes to run host scan task");
         }
         Command[] cmds = new Command[] { new ScheduleHostScanTaskCommand() };
-        _clusterMgr.broadcast(0, cmds);
+        _clusterMgr.broadcast(0, _gson.toJson(cmds));
     }
 
     protected static void logT(byte[] bytes, final String msg) {
@@ -428,7 +452,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
     }
 
     public String findPeer(long hostId) {
-        return _clusterMgr.getPeerName(hostId);
+        return getPeerName(hostId);
     }
 
     public SSLEngine getSSLEngine(String peerName) {
@@ -468,7 +492,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
                 }
             }
             if (ch == null || ch == prevCh) {
-                ManagementServerHostVO ms = _clusterMgr.getPeer(peerName);
+                ManagementServerHost ms = _clusterMgr.getPeer(peerName);
                 if (ms == null) {
                     s_logger.info("Unable to find peer: " + peerName);
                     return null;
@@ -514,7 +538,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
     }
 
     public SocketChannel connectToPeer(long hostId, SocketChannel prevCh) {
-        String peerName = _clusterMgr.getPeerName(hostId);
+        String peerName = getPeerName(hostId);
         if (peerName == null) {
             return null;
         }
@@ -861,7 +885,9 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
                 s_logger.debug("Forwarding " + cmds[0].toString() + " to " + peer);
             }
             String peerName = Long.toString(peer);
-            Answer[] answers = _clusterMgr.execute(peerName, agentId, cmds, true);
+            String cmdStr = _gson.toJson(cmds);
+            String ansStr = _clusterMgr.execute(peerName, agentId, cmdStr, true);
+            Answer[] answers = _gson.fromJson(ansStr, Answer[].class);
             return answers;
         } catch (Exception e) {
             s_logger.warn("Caught exception while talking to " + currentOwnerId, e);
@@ -869,6 +895,46 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
         }
     }
 
+    public String getPeerName(long agentHostId) {
+
+        HostVO host = _hostDao.findById(agentHostId);
+        if (host != null && host.getManagementServerId() != null) {
+            if (_clusterMgr.getSelfPeerName().equals(Long.toString(host.getManagementServerId()))) {
+                return null;
+            }
+
+            return Long.toString(host.getManagementServerId());
+        }
+        return null;
+    }
+
+
+    public Boolean propagateAgentEvent(long agentId, Event event) throws AgentUnavailableException {
+        final String msPeer = getPeerName(agentId);
+        if (msPeer == null) {
+            return null;
+        }
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Propagating agent change request event:" + event.toString() + " to agent:" + agentId);
+        }
+        Command[] cmds = new Command[1];
+        cmds[0] = new ChangeAgentCommand(agentId, event);
+
+        String ansStr = _clusterMgr.execute(msPeer, agentId, _gson.toJson(cmds), true);
+        if (ansStr == null) {
+            throw new AgentUnavailableException(agentId);
+        }
+        
+        Answer[] answers = _gson.fromJson(ansStr, Answer[].class);
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Result for agent change is " + answers[0].getResult());
+        }
+
+        return answers[0].getResult();
+    }
+
     private Runnable getTransferScanTask() {
         return new Runnable() {
             @Override
@@ -1143,4 +1209,227 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
         }
     }
 
+    private String handleScheduleHostScanTaskCommand(ScheduleHostScanTaskCommand cmd) {
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Intercepting resource manager command: " + _gson.toJson(cmd));
+        }
+
+        try {
+            scheduleHostScanTask();
+        } catch (Exception e) {
+            // Scheduling host scan task in peer MS is a best effort operation during host add, regular host scan
+            // happens at fixed intervals anyways. So handling any exceptions that may be thrown
+            s_logger.warn("Exception happened while trying to schedule host scan task on mgmt server " + _clusterMgr.getSelfPeerName()
+                    + ", ignoring as regular host scan happens at fixed interval anyways", e);
+            return null;
+        }
+
+        Answer[] answers = new Answer[1];
+        answers[0] = new Answer(cmd, true, null);
+        return _gson.toJson(answers);
+    }
+
+    public Answer[] sendToAgent(Long hostId, Command[] cmds, boolean stopOnError) throws AgentUnavailableException, OperationTimedoutException {
+        Commands commands = new Commands(stopOnError ? OnError.Stop : OnError.Continue);
+        for (Command cmd : cmds) {
+            commands.addCommand(cmd);
+        }
+        return send(hostId, commands);
+    }
+
+    public Boolean propagateResourceEvent(long agentId, ResourceState.Event event) throws AgentUnavailableException {
+        final String msPeer = getPeerName(agentId);
+        if (msPeer == null) {
+            return null;
+        }
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Propagating agent change request event:" + event.toString() + " to agent:" + agentId);
+        }
+        Command[] cmds = new Command[1];
+        cmds[0] = new PropagateResourceEventCommand(agentId, event);
+
+        String AnsStr = _clusterMgr.execute(msPeer, agentId, _gson.toJson(cmds), true);
+        if (AnsStr == null) {
+            throw new AgentUnavailableException(agentId);
+        }
+
+        Answer[] answers = _gson.fromJson(AnsStr, Answer[].class);
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Result for agent change is " + answers[0].getResult());
+        }
+
+        return answers[0].getResult();
+    }
+
+    public boolean executeResourceUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException {
+        return _resourceMgr.executeUserRequest(hostId, event);
+    }
+
+    protected class ClusterDispatcher implements ClusterManager.Dispatcher {
+        @Override
+        public String getName() {
+            return "ClusterDispatcher";
+        }
+
+        @Override
+        public String dispatch(ClusterServicePdu pdu) {
+
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("Dispatch ->" + pdu.getAgentId() + ", json: " + pdu.getJsonPackage());
+            }
+
+            Command[] cmds = null;
+            try {
+                cmds = _gson.fromJson(pdu.getJsonPackage(), Command[].class);
+            } catch (Throwable e) {
+                assert (false);
+                s_logger.error("Excection in gson decoding : ", e);
+            }
+
+            if (cmds.length == 1 && cmds[0] instanceof ChangeAgentCommand) {  //intercepted
+                ChangeAgentCommand cmd = (ChangeAgentCommand)cmds[0];
+
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Intercepting command for agent change: agent " + cmd.getAgentId() + " event: " + cmd.getEvent());
+                }
+                boolean result = false;
+                try {
+                    result = executeAgentUserRequest(cmd.getAgentId(), cmd.getEvent());
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("Result is " + result);
+                    }
+
+                } catch (AgentUnavailableException e) {
+                    s_logger.warn("Agent is unavailable", e);
+                    return null;
+                }
+
+                Answer[] answers = new Answer[1];
+                answers[0] = new ChangeAgentAnswer(cmd, result);
+                return _gson.toJson(answers);
+            } else if (cmds.length == 1 && cmds[0] instanceof TransferAgentCommand) {
+                TransferAgentCommand cmd = (TransferAgentCommand)cmds[0];
+
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Intercepting command for agent rebalancing: agent " + cmd.getAgentId() + " event: " + cmd.getEvent());
+                }
+                boolean result = false;
+                try {
+                    result = rebalanceAgent(cmd.getAgentId(), cmd.getEvent(), cmd.getCurrentOwner(), cmd.getFutureOwner());
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("Result is " + result);
+                    }
+
+                } catch (AgentUnavailableException e) {
+                    s_logger.warn("Agent is unavailable", e);
+                    return null;
+                } catch (OperationTimedoutException e) {
+                    s_logger.warn("Operation timed out", e);
+                    return null;
+                }
+                Answer[] answers = new Answer[1];
+                answers[0] = new Answer(cmd, result, null);
+                return _gson.toJson(answers);
+            } else if (cmds.length == 1 && cmds[0] instanceof PropagateResourceEventCommand) {
+                PropagateResourceEventCommand cmd = (PropagateResourceEventCommand)cmds[0];
+
+                s_logger.debug("Intercepting command to propagate event " + cmd.getEvent().name() + " for host " + cmd.getHostId());
+
+                boolean result = false;
+                try {
+                    result = executeResourceUserRequest(cmd.getHostId(), cmd.getEvent());
+                    s_logger.debug("Result is " + result);
+                } catch (AgentUnavailableException ex) {
+                    s_logger.warn("Agent is unavailable", ex);
+                    return null;
+                }
+
+                Answer[] answers = new Answer[1];
+                answers[0] = new Answer(cmd, result, null);
+                return _gson.toJson(answers);
+            } else if (cmds.length == 1 && cmds[0] instanceof ScheduleHostScanTaskCommand) {
+                ScheduleHostScanTaskCommand cmd = (ScheduleHostScanTaskCommand)cmds[0];
+                String response = handleScheduleHostScanTaskCommand(cmd);
+                return response;
+            }
+
+            try {
+                long startTick = System.currentTimeMillis();
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Dispatch -> " + pdu.getAgentId() + ", json: " + pdu.getJsonPackage());
+                }
+
+                Answer[] answers = sendToAgent(pdu.getAgentId(), cmds, pdu.isStopOnError());
+                if (answers != null) {
+                    String jsonReturn = _gson.toJson(answers);
+
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("Completed dispatching -> " + pdu.getAgentId() + ", json: " + pdu.getJsonPackage() +
+                                " in " + (System.currentTimeMillis() - startTick) + " ms, return result: " + jsonReturn);
+                    }
+
+                    return jsonReturn;
+                } else {
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("Completed dispatching -> " + pdu.getAgentId() + ", json: " + pdu.getJsonPackage() +
+                                " in " + (System.currentTimeMillis() - startTick) + " ms, return null result");
+                    }
+                }
+            } catch (AgentUnavailableException e) {
+                s_logger.warn("Agent is unavailable", e);
+            } catch (OperationTimedoutException e) {
+                s_logger.warn("Timed Out", e);
+            }
+
+            return null;
+        }
+
+    }
+
+    public boolean executeAgentUserRequest(long agentId, Event event) throws AgentUnavailableException {
+        return executeUserRequest(agentId, event);
+    }
+
+    public boolean rebalanceAgent(long agentId, Event event, long currentOwnerId, long futureOwnerId) throws AgentUnavailableException, OperationTimedoutException {
+        return _rebalanceService.executeRebalanceRequest(agentId, currentOwnerId, futureOwnerId, event);
+    }
+
+    public boolean isAgentRebalanceEnabled() {
+        return _agentLBEnabled.value();
+    }
+
+    @Inject
+    private ClusteredAgentRebalanceService _rebalanceService;
+
+    boolean _agentLbHappened = false;
+    public void agentrebalance() {
+        Profiler profilerAgentLB = new Profiler();
+        profilerAgentLB.start();
+        //initiate agent lb task will be scheduled and executed only once, and only when number of agents loaded exceeds _connectedAgentsThreshold
+        if (_agentLBEnabled.value() && !_agentLbHappened) {
+            SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class);
+            sc.addAnd(sc.getEntity().getManagementServerId(), Op.NNULL);
+            sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing);
+            List<HostVO> allManagedRoutingAgents = sc.list();
+
+            sc = SearchCriteria2.create(HostVO.class);
+            sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing);
+            List<HostVO> allAgents = sc.list();
+            double allHostsCount = allAgents.size();
+            double managedHostsCount = allManagedRoutingAgents.size();
+            if (allHostsCount > 0.0) {
+                double load = managedHostsCount / allHostsCount;
+                if (load >= _connectedAgentsThreshold.value()) {
+                    s_logger.debug("Scheduling agent rebalancing task as the average agent load " + load + " is more than the threshold " + _connectedAgentsThreshold);
+                    _rebalanceService.scheduleRebalanceAgents();
+                    _agentLbHappened = true;
+                } else {
+                    s_logger.trace("Not scheduling agent rebalancing task as the averages load " + load + " is less than the threshold " + _connectedAgentsThreshold);
+                }
+            }
+        }
+        profilerAgentLB.stop();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/async/AsyncJobManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/async/AsyncJobManagerImpl.java b/server/src/com/cloud/async/AsyncJobManagerImpl.java
index f5c6904..f388d36 100644
--- a/server/src/com/cloud/async/AsyncJobManagerImpl.java
+++ b/server/src/com/cloud/async/AsyncJobManagerImpl.java
@@ -53,6 +53,7 @@ import org.apache.cloudstack.api.response.ExceptionResponse;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.framework.events.EventBus;
 import org.apache.cloudstack.framework.events.EventBusException;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
 
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.ApiDispatcher;
@@ -87,7 +88,6 @@ import com.cloud.utils.db.Transaction;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.exception.ExceptionUtil;
 import com.cloud.utils.mgmt.JmxUtil;
-import com.cloud.utils.net.MacAddress;
 
 @Component
 @Local(value={AsyncJobManager.class})
@@ -773,11 +773,7 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
     }
 
     private long getMsid() {
-        if(_clusterMgr != null) {
-            return _clusterMgr.getManagementNodeId();
-        }
-
-        return MacAddress.getMacAddress().toLong();
+        return ManagementServerNode.getManagementServerId();
     }
 
     private void cleanupPendingJobs(List<SyncQueueItemVO> l) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ActiveFencingException.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ActiveFencingException.java b/server/src/com/cloud/cluster/ActiveFencingException.java
deleted file mode 100644
index 512219d..0000000
--- a/server/src/com/cloud/cluster/ActiveFencingException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import com.cloud.exception.CloudException;
-
-public class ActiveFencingException extends CloudException {
-    private static final long serialVersionUID = -3975376101728211726L;
-
-    public ActiveFencingException(String message) {
-        super(message);
-    }
-
-    public ActiveFencingException(String message, Throwable th) {
-        super(message, th);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterFenceManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterFenceManager.java b/server/src/com/cloud/cluster/ClusterFenceManager.java
deleted file mode 100644
index b9782ad..0000000
--- a/server/src/com/cloud/cluster/ClusterFenceManager.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import com.cloud.utils.component.Manager;
-
-public interface ClusterFenceManager extends Manager {
-	public static final int SELF_FENCING_EXIT_CODE = 219;
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterFenceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterFenceManagerImpl.java b/server/src/com/cloud/cluster/ClusterFenceManagerImpl.java
deleted file mode 100644
index 7e4922e..0000000
--- a/server/src/com/cloud/cluster/ClusterFenceManagerImpl.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.List;
-import java.util.Map;
-
-import javax.ejb.Local;
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import com.cloud.utils.component.ManagerBase;
-
-
-@Component
-@Local(value={ClusterFenceManager.class})
-public class ClusterFenceManagerImpl extends ManagerBase implements ClusterFenceManager, ClusterManagerListener {
-    private static final Logger s_logger = Logger.getLogger(ClusterFenceManagerImpl.class);
-	
-	@Inject ClusterManager _clusterMgr;
-	
-	@Override
-	public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
-		_clusterMgr.registerListener(this);
-		return true;
-	}
-
-	@Override
-	public void onManagementNodeJoined(List<ManagementServerHostVO> nodeList, long selfNodeId) {
-	}
-
-	@Override
-	public void onManagementNodeLeft(List<ManagementServerHostVO> nodeList, long selfNodeId) {
-	}
-
-	@Override
-	public void onManagementNodeIsolated() {
-		s_logger.error("Received node isolation notification, will perform self-fencing and shut myself down");
-		System.exit(SELF_FENCING_EXIT_CODE);
-	}
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterManager.java b/server/src/com/cloud/cluster/ClusterManager.java
deleted file mode 100755
index 017ba31..0000000
--- a/server/src/com/cloud/cluster/ClusterManager.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.Command;
-import com.cloud.exception.AgentUnavailableException;
-import com.cloud.exception.OperationTimedoutException;
-import com.cloud.host.Status.Event;
-import com.cloud.resource.ResourceState;
-import com.cloud.utils.component.Manager;
-
-public interface ClusterManager extends Manager {
-	public static final int DEFAULT_HEARTBEAT_INTERVAL = 1500;
-	public static final int DEFAULT_HEARTBEAT_THRESHOLD = 150000;
-	public static final String ALERT_SUBJECT = "cluster-alert";
-	
-	public void OnReceiveClusterServicePdu(ClusterServicePdu pdu);
-    public void executeAsync(String strPeer, long agentId, Command [] cmds, boolean stopOnError);
-    public Answer[] execute(String strPeer, long agentId, Command [] cmds, boolean stopOnError);
-
-    public Answer[] sendToAgent(Long hostId, Command []  cmds, boolean stopOnError) throws AgentUnavailableException, OperationTimedoutException;
-    public boolean executeAgentUserRequest(long agentId, Event event) throws AgentUnavailableException;
-    public Boolean propagateAgentEvent(long agentId, Event event) throws AgentUnavailableException;
-    public Boolean propagateResourceEvent(long agentId, ResourceState.Event event) throws AgentUnavailableException;
-    public boolean executeResourceUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException;
-	
-	public int getHeartbeatThreshold();
-	
-	public long getManagementNodeId();		// msid of current management server node
-    public boolean isManagementNodeAlive(long msid);
-    public boolean pingManagementNode(long msid);
-	public long getCurrentRunId();
-    
-	public String getSelfPeerName();
-	public String getSelfNodeIP();
-    public String getPeerName(long agentHostId);
-	
-	public void registerListener(ClusterManagerListener listener);
-	public void unregisterListener(ClusterManagerListener listener);
-    public ManagementServerHostVO getPeer(String peerName);
-    
-    /**
-     * Broadcast the command to all of the  management server nodes.
-     * @param agentId agent id this broadcast is regarding
-     * @param cmds commands to broadcast
-     */
-    public void broadcast(long agentId, Command[] cmds);
-    
-    boolean rebalanceAgent(long agentId, Event event, long currentOwnerId, long futureOwnerId) throws AgentUnavailableException, OperationTimedoutException;
-    
-    boolean isAgentRebalanceEnabled();
-}


[2/8] Moved ClusterManager into it's own package. Removed the agent load balancing code.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterServiceServletAdapter.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterServiceServletAdapter.java b/server/src/com/cloud/cluster/ClusterServiceServletAdapter.java
deleted file mode 100644
index 04026d30..0000000
--- a/server/src/com/cloud/cluster/ClusterServiceServletAdapter.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.rmi.RemoteException;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.ejb.Local;
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import com.cloud.cluster.dao.ManagementServerHostDao;
-import com.cloud.configuration.Config;
-import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.PropertiesUtil;
-import com.cloud.utils.component.AdapterBase;
-
-@Component
-@Local(value={ClusterServiceAdapter.class})
-public class ClusterServiceServletAdapter extends AdapterBase implements ClusterServiceAdapter {
-
-    private static final Logger s_logger = Logger.getLogger(ClusterServiceServletAdapter.class);
-    private static final int DEFAULT_SERVICE_PORT = 9090;
-    private static final int DEFAULT_REQUEST_TIMEOUT = 300;			// 300 seconds
-    
-    @Inject private ClusterManager _manager;
-    
-    @Inject private ManagementServerHostDao _mshostDao;
-    
-    @Inject private ConfigurationDao _configDao;
-    
-    private ClusterServiceServletContainer _servletContainer;
-    
-    private int _clusterServicePort = DEFAULT_SERVICE_PORT;
-    
-    private int _clusterRequestTimeoutSeconds = DEFAULT_REQUEST_TIMEOUT;
-    
-    @Override
-	public ClusterService getPeerService(String strPeer) throws RemoteException {
-    	try {
-    		init();
-    	} catch (ConfigurationException e) {
-    		s_logger.error("Unable to init ClusterServiceServletAdapter");
-    		throw new RemoteException("Unable to init ClusterServiceServletAdapter");
-    	}
-    	
-    	String serviceUrl = getServiceEndpointName(strPeer);
-    	if(serviceUrl == null)
-    		return null;
-    	
-    	return new ClusterServiceServletImpl(serviceUrl, _clusterRequestTimeoutSeconds);
-	}
-    
-    @Override
-	public String getServiceEndpointName(String strPeer) {
-    	try {
-    		init();
-    	} catch (ConfigurationException e) {
-    		s_logger.error("Unable to init ClusterServiceServletAdapter");
-    		return null;
-    	}
-    	
-    	long msid = Long.parseLong(strPeer);
-    	
-    	ManagementServerHostVO mshost = _mshostDao.findByMsid(msid);
-    	if(mshost == null)
-    		return null;
-    	
-    	return composeEndpointName(mshost.getServiceIP(), mshost.getServicePort());
-    }
-    
-    @Override
-	public int getServicePort() {
-    	return _clusterServicePort;
-    }
-    
-    private String composeEndpointName(String nodeIP, int port) {
-    	StringBuffer sb = new StringBuffer();
-    	sb.append("http://").append(nodeIP).append(":").append(port).append("/clusterservice");
-    	return sb.toString();
-    }
-	
-    @Override
-    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
-    	init();
-    	return true;
-    }
-    
-    @Override
-    public boolean start() {
-    	_servletContainer = new ClusterServiceServletContainer();
-    	_servletContainer.start(new ClusterServiceServletHttpHandler(_manager), _clusterServicePort);
-    	return true;
-    }
-    
-    @Override
-    public boolean stop() {
-    	if(_servletContainer != null)
-    		_servletContainer.stop();
-    	return true;
-    }
-    
-    private void init() throws ConfigurationException {
-    	if(_mshostDao != null)
-    		return;
-    	
-        String value = _configDao.getValue(Config.ClusterMessageTimeOutSeconds.key());
-    	_clusterRequestTimeoutSeconds = NumbersUtil.parseInt(value, DEFAULT_REQUEST_TIMEOUT);
-    	s_logger.info("Configure cluster request time out. timeout: " + _clusterRequestTimeoutSeconds + " seconds");
-        
-        File dbPropsFile = PropertiesUtil.findConfigFile("db.properties");
-        Properties dbProps = new Properties();
-        try {
-			dbProps.load(new FileInputStream(dbPropsFile));
-		} catch (FileNotFoundException e) {
-            throw new ConfigurationException("Unable to find db.properties");
-		} catch (IOException e) {
-            throw new ConfigurationException("Unable to load db.properties content");
-		}
-		
-        _clusterServicePort = NumbersUtil.parseInt(dbProps.getProperty("cluster.servlet.port"), DEFAULT_SERVICE_PORT);
-        if(s_logger.isInfoEnabled())
-        	s_logger.info("Cluster servlet port : " + _clusterServicePort);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterServiceServletContainer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterServiceServletContainer.java b/server/src/com/cloud/cluster/ClusterServiceServletContainer.java
deleted file mode 100644
index def3e17..0000000
--- a/server/src/com/cloud/cluster/ClusterServiceServletContainer.java
+++ /dev/null
@@ -1,179 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.apache.http.ConnectionClosedException;
-import org.apache.http.HttpException;
-import org.apache.http.impl.DefaultConnectionReuseStrategy;
-import org.apache.http.impl.DefaultHttpResponseFactory;
-import org.apache.http.impl.DefaultHttpServerConnection;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.CoreConnectionPNames;
-import org.apache.http.params.CoreProtocolPNames;
-import org.apache.http.params.HttpParams;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.BasicHttpProcessor;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.HttpRequestHandler;
-import org.apache.http.protocol.HttpRequestHandlerRegistry;
-import org.apache.http.protocol.HttpService;
-import org.apache.http.protocol.ResponseConnControl;
-import org.apache.http.protocol.ResponseContent;
-import org.apache.http.protocol.ResponseDate;
-import org.apache.http.protocol.ResponseServer;
-import org.apache.log4j.Logger;
-
-import com.cloud.utils.concurrency.NamedThreadFactory;
-
-public class ClusterServiceServletContainer {
-	private static final Logger s_logger = Logger.getLogger(ClusterServiceServletContainer.class);
-	
-	private ListenerThread listenerThread;
-	
-	public ClusterServiceServletContainer() {
-	}
-	
-	public boolean start(HttpRequestHandler requestHandler, int port) {
-	
-		listenerThread = new ListenerThread(requestHandler, port);
-		listenerThread.start();
-		
-		return true;
-	}
-	
-	public void stop() {
-		if(listenerThread != null) {
-			listenerThread.stopRunning();
-		}
-	}
-	
-    static class ListenerThread extends Thread {
-        private HttpService _httpService = null;
-        private volatile ServerSocket _serverSocket = null;
-        private HttpParams _params = null;
-        private ExecutorService _executor;
-
-        public ListenerThread(HttpRequestHandler requestHandler, int port) {
-    		_executor = Executors.newCachedThreadPool(new NamedThreadFactory("Cluster-Listener"));
-        	
-            try {
-                _serverSocket = new ServerSocket(port);
-            } catch (IOException ioex) {
-                s_logger.error("error initializing cluster service servlet container", ioex);
-                return;
-            }
-
-            _params = new BasicHttpParams();
-            _params
-                .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
-                .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
-                .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
-                .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
-                .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");
-
-            // Set up the HTTP protocol processor
-            BasicHttpProcessor httpproc = new BasicHttpProcessor();
-            httpproc.addInterceptor(new ResponseDate());
-            httpproc.addInterceptor(new ResponseServer());
-            httpproc.addInterceptor(new ResponseContent());
-            httpproc.addInterceptor(new ResponseConnControl());
-
-            // Set up request handlers
-            HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
-            reqistry.register("/clusterservice", requestHandler);
-
-            // Set up the HTTP service
-            _httpService = new HttpService(httpproc, new DefaultConnectionReuseStrategy(), new DefaultHttpResponseFactory());
-            _httpService.setParams(_params);
-            _httpService.setHandlerResolver(reqistry);
-        }
-        
-        public void stopRunning() {
-        	if(_serverSocket != null) {
-        		try {
-					_serverSocket.close();
-				} catch (IOException e) {
-				}
-				_serverSocket = null;
-        	}
-        }
-
-        public void run() {
-        	if(s_logger.isInfoEnabled())
-        		s_logger.info("Cluster service servlet container listening on port " + _serverSocket.getLocalPort());
-            
-            while (_serverSocket != null) {
-                try {
-                    // Set up HTTP connection
-                    Socket socket = _serverSocket.accept();
-                    final DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
-                    conn.bind(socket, _params);
-
-                    _executor.execute(new Runnable() {
-                    	public void run() {
-                            HttpContext context = new BasicHttpContext(null);
-                            try {
-                            	while(!Thread.interrupted() && conn.isOpen()) {
-	                            	if(s_logger.isTraceEnabled())
-	                            		s_logger.trace("dispatching cluster request from " + conn.getRemoteAddress().toString());
-	                            	
-	                                _httpService.handleRequest(conn, context);
-	                                
-	                            	if(s_logger.isTraceEnabled())
-	                            		s_logger.trace("Cluster request from " + conn.getRemoteAddress().toString() + " is processed");
-                            	}
-                            } catch (ConnectionClosedException ex) {
-                            	// client close and read time out exceptions are expected
-                            	// when KEEP-AVLIE is enabled
-                                s_logger.trace("Client closed connection", ex);
-                            } catch (IOException ex) {
-                                s_logger.trace("I/O error", ex);
-                            } catch (HttpException ex) {
-                                s_logger.error("Unrecoverable HTTP protocol violation", ex);
-                            } finally {
-                                try {
-                                    conn.shutdown();
-                                } catch (IOException ignore) {
-                                    s_logger.error("unexpected exception", ignore);
-                                }
-                            }
-                    	}
-                    });
-                    
-                } catch (Throwable e) {
-                	s_logger.error("Unexpected exception ", e);
-                
-                	// back off to avoid spinning if the exception condition keeps coming back
-                	try {
-						Thread.sleep(1000);
-					} catch (InterruptedException e1) {
-					}
-                } 
-            }
-            
-            _executor.shutdown();
-        	if(s_logger.isInfoEnabled())
-        		s_logger.info("Cluster service servlet container shutdown");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java b/server/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java
deleted file mode 100755
index 2d77ce0..0000000
--- a/server/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java
+++ /dev/null
@@ -1,192 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.net.URLDecoder;
-
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.entity.BasicHttpEntity;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.HttpRequestHandler;
-import org.apache.http.util.EntityUtils;
-import org.apache.log4j.Logger;
-
-public class ClusterServiceServletHttpHandler implements HttpRequestHandler {
-    private static final Logger s_logger = Logger.getLogger(ClusterServiceServletHttpHandler.class);
-
-    private final ClusterManager manager;
-
-    public ClusterServiceServletHttpHandler(ClusterManager manager) {
-        this.manager = manager;
-    }
-
-    @Override
-    public void handle(HttpRequest request, HttpResponse response, HttpContext context)
-    throws HttpException, IOException {
-
-        try {
-            if(s_logger.isTraceEnabled()) {
-                s_logger.trace("Start Handling cluster HTTP request");
-            }
-
-            parseRequest(request);
-            handleRequest(request, response);
-
-            if(s_logger.isTraceEnabled()) {
-                s_logger.trace("Handle cluster HTTP request done");
-            }
-
-        } catch(Throwable e) {
-            if(s_logger.isDebugEnabled()) {
-                s_logger.debug("Exception " + e.toString());
-            }
-
-            try {
-            	writeResponse(response, HttpStatus.SC_INTERNAL_SERVER_ERROR, null);
-            } catch(Throwable e2) {
-                if(s_logger.isDebugEnabled()) {
-                    s_logger.debug("Exception " + e2.toString());
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    private void parseRequest(HttpRequest request) throws IOException {
-        if(request instanceof HttpEntityEnclosingRequest) {
-            HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest)request;
-
-            String body = EntityUtils.toString(entityRequest.getEntity());
-            if(body != null) {
-                String[] paramArray = body.split("&");
-                if(paramArray != null) {
-                    for (String paramEntry : paramArray) {
-                        String[] paramValue = paramEntry.split("=");
-                        if (paramValue.length != 2) {
-                            continue;
-                        }
-
-                        String name = URLDecoder.decode(paramValue[0]);
-                        String value = URLDecoder.decode(paramValue[1]);
-
-                        if(s_logger.isTraceEnabled()) {
-                            s_logger.trace("Parsed request parameter " + name + "=" + value);
-                        }
-                        request.getParams().setParameter(name, value);
-                    }
-                }
-            }
-        }
-    }
-
-    private void writeResponse(HttpResponse response, int statusCode, String content) {
-        if(content == null) {
-            content = "";
-        }
-        response.setStatusCode(statusCode);
-        BasicHttpEntity body = new BasicHttpEntity();
-        body.setContentType("text/html; charset=UTF-8");
-
-        byte[] bodyData = content.getBytes();
-        body.setContent(new ByteArrayInputStream(bodyData));
-        body.setContentLength(bodyData.length);
-        response.setEntity(body);
-    }
-
-    protected void handleRequest(HttpRequest req, HttpResponse response) {
-        String method = (String)req.getParams().getParameter("method");
-
-        int nMethod = RemoteMethodConstants.METHOD_UNKNOWN;
-        String responseContent = null;
-        try {
-            if(method != null) {
-                nMethod = Integer.parseInt(method);
-            }
-
-            switch(nMethod) {
-            case RemoteMethodConstants.METHOD_DELIVER_PDU :
-                responseContent = handleDeliverPduMethodCall(req);
-                break;
-
-            case RemoteMethodConstants.METHOD_PING :
-                responseContent = handlePingMethodCall(req);
-                break;
-
-            case RemoteMethodConstants.METHOD_UNKNOWN :
-            default :
-                assert(false);
-                s_logger.error("unrecognized method " + nMethod);
-                break;
-            }
-        } catch(Throwable e) {
-            s_logger.error("Unexpected exception when processing cluster service request : ", e);
-        }
-
-        if(responseContent != null) {
-        	if(s_logger.isTraceEnabled())
-        		s_logger.trace("Write reponse with HTTP OK " + responseContent);
-        	
-            writeResponse(response, HttpStatus.SC_OK, responseContent);
-        } else {
-        	if(s_logger.isTraceEnabled())
-        		s_logger.trace("Write reponse with HTTP Bad request");
-        	
-            writeResponse(response, HttpStatus.SC_BAD_REQUEST, null);
-        }
-    }
-
-    private String handleDeliverPduMethodCall(HttpRequest req) {
-        
-        String pduSeq = (String)req.getParams().getParameter("pduSeq");
-        String pduAckSeq = (String)req.getParams().getParameter("pduAckSeq");
-        String sourcePeer = (String)req.getParams().getParameter("sourcePeer");
-        String destPeer = (String)req.getParams().getParameter("destPeer");
-        String agentId = (String)req.getParams().getParameter("agentId");
-        String gsonPackage = (String)req.getParams().getParameter("gsonPackage");
-        String stopOnError = (String)req.getParams().getParameter("stopOnError");
-        String pduType = (String)req.getParams().getParameter("pduType");
-
-        ClusterServicePdu pdu = new ClusterServicePdu();
-        pdu.setSourcePeer(sourcePeer);
-        pdu.setDestPeer(destPeer);
-        pdu.setAgentId(Long.parseLong(agentId));
-        pdu.setSequenceId(Long.parseLong(pduSeq));
-        pdu.setAckSequenceId(Long.parseLong(pduAckSeq));
-        pdu.setJsonPackage(gsonPackage);
-        pdu.setStopOnError("1".equals(stopOnError));
-        pdu.setPduType(Integer.parseInt(pduType));
-        
-        manager.OnReceiveClusterServicePdu(pdu);
-        return "true";
-    }
-
-    private String handlePingMethodCall(HttpRequest req) {
-        String callingPeer = (String)req.getParams().getParameter("callingPeer");
-
-        if(s_logger.isDebugEnabled()) {
-            s_logger.debug("Handle ping request from " + callingPeer);
-        }
-
-        return "true";
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/ClusterServiceServletImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/ClusterServiceServletImpl.java b/server/src/com/cloud/cluster/ClusterServiceServletImpl.java
deleted file mode 100644
index 3270315..0000000
--- a/server/src/com/cloud/cluster/ClusterServiceServletImpl.java
+++ /dev/null
@@ -1,146 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.io.IOException;
-import java.rmi.RemoteException;
-
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
-import org.apache.commons.httpclient.methods.PostMethod;
-import org.apache.commons.httpclient.params.HttpClientParams;
-import org.apache.log4j.Logger;
-
-public class ClusterServiceServletImpl implements ClusterService {
-    private static final long serialVersionUID = 4574025200012566153L;
-    private static final Logger s_logger = Logger.getLogger(ClusterServiceServletImpl.class);
-    
-    private String _serviceUrl;
-
-    private int _requestTimeoutSeconds;
-    protected static HttpClient s_client = null;
-    
-    public ClusterServiceServletImpl() {
-    }
-
-    public ClusterServiceServletImpl(String serviceUrl, int requestTimeoutSeconds) {
-    	s_logger.info("Setup cluster service servlet. service url: " + serviceUrl + ", request timeout: " + requestTimeoutSeconds + " seconds");
-    	
-        this._serviceUrl = serviceUrl;
-        this._requestTimeoutSeconds = requestTimeoutSeconds;
-    }
-    
-    @Override
-    public String execute(ClusterServicePdu pdu) throws RemoteException {
-
-        HttpClient client = getHttpClient();
-        PostMethod method = new PostMethod(_serviceUrl);
-
-        method.addParameter("method", Integer.toString(RemoteMethodConstants.METHOD_DELIVER_PDU));
-        method.addParameter("sourcePeer", pdu.getSourcePeer());
-        method.addParameter("destPeer", pdu.getDestPeer());
-        method.addParameter("pduSeq", Long.toString(pdu.getSequenceId()));
-        method.addParameter("pduAckSeq", Long.toString(pdu.getAckSequenceId()));
-        method.addParameter("agentId", Long.toString(pdu.getAgentId()));
-        method.addParameter("gsonPackage", pdu.getJsonPackage());
-        method.addParameter("stopOnError", pdu.isStopOnError() ? "1" : "0");
-        method.addParameter("pduType", Integer.toString(pdu.getPduType()));
-
-        return executePostMethod(client, method);
-    }
-
-    @Override
-    public boolean ping(String callingPeer) throws RemoteException {
-        if(s_logger.isDebugEnabled()) {
-            s_logger.debug("Ping at " + _serviceUrl);
-        }
-
-        HttpClient client = getHttpClient();
-        PostMethod method = new PostMethod(_serviceUrl);
-
-        method.addParameter("method", Integer.toString(RemoteMethodConstants.METHOD_PING));
-        method.addParameter("callingPeer", callingPeer);
-        
-        String returnVal =  executePostMethod(client, method);
-        if("true".equalsIgnoreCase(returnVal)) {
-            return true;
-        }
-        return false;
-    }
-
-    private String executePostMethod(HttpClient client, PostMethod method) {
-        int response = 0;
-        String result = null;
-        try {
-            long startTick = System.currentTimeMillis();
-            response = client.executeMethod(method);
-            if(response == HttpStatus.SC_OK) {
-                result = method.getResponseBodyAsString();
-                if(s_logger.isDebugEnabled()) {
-                    s_logger.debug("POST " + _serviceUrl + " response :" + result + ", responding time: "
-                            + (System.currentTimeMillis() - startTick) + " ms");
-                }
-            } else {
-                s_logger.error("Invalid response code : " + response + ", from : "
-                        + _serviceUrl + ", method : " + method.getParameter("method")
-                        + " responding time: " + (System.currentTimeMillis() - startTick));
-            }
-        } catch (HttpException e) {
-            s_logger.error("HttpException from : " + _serviceUrl + ", method : " + method.getParameter("method"));
-        } catch (IOException e) {
-            s_logger.error("IOException from : " + _serviceUrl + ", method : " + method.getParameter("method"));
-        } catch(Throwable e) {
-            s_logger.error("Exception from : " + _serviceUrl + ", method : " + method.getParameter("method") + ", exception :", e);
-        } finally {
-            method.releaseConnection();
-        }
-
-        return result;
-    }
-    
-    private HttpClient getHttpClient() {
-
-    	if(s_client == null) {
-    		MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
-    		mgr.getParams().setDefaultMaxConnectionsPerHost(4);
-    		
-    		// TODO make it configurable
-    		mgr.getParams().setMaxTotalConnections(1000);
-    		
-	        s_client = new HttpClient(mgr);
-	        HttpClientParams clientParams = new HttpClientParams();
-	        clientParams.setSoTimeout(_requestTimeoutSeconds * 1000);
-	        
-	        s_client.setParams(clientParams);
-    	}
-    	return s_client;
-    }
-
-    // for test purpose only
-    public static void main(String[] args) {
-/*
-        ClusterServiceServletImpl service = new ClusterServiceServletImpl("http://localhost:9090/clusterservice", 300);
-        try {
-            String result = service.execute("test", 1, "{ p1:v1, p2:v2 }", true);
-            System.out.println(result);
-        } catch (RemoteException e) {
-        }
-*/        
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/DummyClusterManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/DummyClusterManagerImpl.java b/server/src/com/cloud/cluster/DummyClusterManagerImpl.java
deleted file mode 100755
index 12972b9..0000000
--- a/server/src/com/cloud/cluster/DummyClusterManagerImpl.java
+++ /dev/null
@@ -1,179 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.Map;
-
-import javax.ejb.Local;
-import javax.naming.ConfigurationException;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.Command;
-import com.cloud.exception.AgentUnavailableException;
-import com.cloud.exception.OperationTimedoutException;
-import com.cloud.host.Status.Event;
-import com.cloud.utils.component.ManagerBase;
-import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.net.MacAddress;
-
-@Local(value={ClusterManager.class})
-public class DummyClusterManagerImpl extends ManagerBase implements ClusterManager {
-    private static final Logger s_logger = Logger.getLogger(DummyClusterManagerImpl.class);
-	
-    protected long _id = MacAddress.getMacAddress().toLong();
-    protected long _runId = System.currentTimeMillis();
-    
-    private final String _clusterNodeIP = "127.0.0.1";
-
-    @Override
-    public void OnReceiveClusterServicePdu(ClusterServicePdu pdu) {
-        throw new CloudRuntimeException("Unsupported feature");
-    }
-
-    @Override
-    public void executeAsync(String strPeer, long agentId, Command [] cmds, boolean stopOnError) {
-    	throw new CloudRuntimeException("Unsupported feature");
-    }
-    
-    @Override
-    public Answer[] execute(String strPeer, long agentId, Command [] cmds, boolean stopOnError) {
-    	throw new CloudRuntimeException("Unsupported feature");
-    }
-  
-    @Override
-    public Answer[] sendToAgent(Long hostId, Command []  cmds, boolean stopOnError)
-    	throws AgentUnavailableException, OperationTimedoutException {
-    	throw new CloudRuntimeException("Unsupported feature");
-    }
-    
-/*    
-    @Override
-    public long sendToAgent(Long hostId, Command[] cmds, boolean stopOnError, Listener listener) throws AgentUnavailableException {
-    	throw new CloudRuntimeException("Unsupported feature");
-    }
-*/    
-    @Override
-    public boolean executeAgentUserRequest(long agentId, Event event) throws AgentUnavailableException {
-    	throw new CloudRuntimeException("Unsupported feature");
-    }
-    
-    @Override
-    public Boolean propagateAgentEvent(long agentId, Event event) throws AgentUnavailableException {
-    	throw new CloudRuntimeException("Unsupported feature");
-    }
-	
-	@Override
-    public int getHeartbeatThreshold() {
-    	return ClusterManager.DEFAULT_HEARTBEAT_INTERVAL;
-	}
-	
-	@Override
-    public long getManagementNodeId() {
-        return _id;
-	}
-	
-    @Override
-    public long getCurrentRunId() {
-        return _runId;
-    }
-	
-	@Override
-	public ManagementServerHostVO getPeer(String str) {
-		return null;
-	}
-	
-	@Override
-    public String getSelfPeerName() {
-		return Long.toString(_id);
-	}
-	
-	@Override
-    public String getSelfNodeIP() {
-		return _clusterNodeIP;
-	}
-	
-    @Override
-    public boolean isManagementNodeAlive(long msid) {
-    	return true;
-    }
-    
-    @Override
-    public boolean pingManagementNode(long msid) {
-    	return false;
-    }
-	
-    @Override
-    public String getPeerName(long agentHostId) {
-    	throw new CloudRuntimeException("Unsupported feature");
-    }
-	
-	@Override
-    public void registerListener(ClusterManagerListener listener) {
-	}
-	
-	@Override
-    public void unregisterListener(ClusterManagerListener listener) {
-	}
-
-	@Override
-	public boolean configure(String name, Map<String, Object> params)
-			throws ConfigurationException {
-		return true;
-	}
-	
-	@Override
-	public void broadcast(long hostId, Command[] cmds) {
-	}
-
-	@Override
-	public boolean start() {
-    	if(s_logger.isInfoEnabled())
-    		s_logger.info("Starting cluster manager, msid : " + _id);
-    	
-        return true;
-	}
-
-	@Override
-	public boolean stop() {
-		return true;
-	}
-	
-	@Override
-	public boolean rebalanceAgent(long agentId, Event event, long currentOwnerId, long futureOwnerId) throws AgentUnavailableException, OperationTimedoutException {
-	    return false;
-	}
-	
-	@Override
-    public  boolean isAgentRebalanceEnabled() {
-        return false;
-    }
-
-	@Override
-    public Boolean propagateResourceEvent(long agentId, com.cloud.resource.ResourceState.Event event) throws AgentUnavailableException {
-	    // TODO Auto-generated method stub
-	    return null;
-    }
-
-	@Override
-    public boolean executeResourceUserRequest(long hostId, com.cloud.resource.ResourceState.Event event) throws AgentUnavailableException {
-	    // TODO Auto-generated method stub
-	    return false;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/LockMasterListener.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/LockMasterListener.java b/server/src/com/cloud/cluster/LockMasterListener.java
deleted file mode 100644
index cc10e2c..0000000
--- a/server/src/com/cloud/cluster/LockMasterListener.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.List;
-
-import com.cloud.utils.db.Merovingian2;
-
-/**
- * when a management server is down.
- *
- */
-public class LockMasterListener implements ClusterManagerListener {
-    Merovingian2 _lockMaster;
-    
-    public LockMasterListener(long msId) {
-        _lockMaster = Merovingian2.createLockMaster(msId);
-    }
-
-    @Override
-    public void onManagementNodeJoined(List<ManagementServerHostVO> nodeList, long selfNodeId) {
-    }
-
-    @Override
-    public void onManagementNodeLeft(List<ManagementServerHostVO> nodeList, long selfNodeId) {
-        for (ManagementServerHostVO node : nodeList) {
-            _lockMaster.cleanupForServer(node.getMsid());
-        }
-    }
-
-    @Override
-    public void onManagementNodeIsolated() {
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/cluster/RemoteMethodConstants.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/cluster/RemoteMethodConstants.java b/server/src/com/cloud/cluster/RemoteMethodConstants.java
deleted file mode 100644
index 1174bd3..0000000
--- a/server/src/com/cloud/cluster/RemoteMethodConstants.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-public interface RemoteMethodConstants {
-    public static final int METHOD_UNKNOWN = 0;
-    public static final int METHOD_PING = 4;
-    public static final int METHOD_DELIVER_PDU = 5;
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/server/LockMasterListener.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/LockMasterListener.java b/server/src/com/cloud/server/LockMasterListener.java
new file mode 100644
index 0000000..ee9c9a9
--- /dev/null
+++ b/server/src/com/cloud/server/LockMasterListener.java
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.server;
+
+import java.util.List;
+
+import com.cloud.cluster.ClusterManagerListener;
+import com.cloud.cluster.ManagementServerHostVO;
+import com.cloud.utils.db.Merovingian2;
+
+/**
+ * when a management server is down.
+ *
+ */
+public class LockMasterListener implements ClusterManagerListener {
+    Merovingian2 _lockMaster;
+    
+    public LockMasterListener(long msId) {
+        _lockMaster = Merovingian2.createLockMaster(msId);
+    }
+
+    @Override
+    public void onManagementNodeJoined(List<ManagementServerHostVO> nodeList, long selfNodeId) {
+    }
+
+    @Override
+    public void onManagementNodeLeft(List<ManagementServerHostVO> nodeList, long selfNodeId) {
+        for (ManagementServerHostVO node : nodeList) {
+            _lockMaster.cleanupForServer(node.getMsid());
+        }
+    }
+
+    @Override
+    public void onManagementNodeIsolated() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 77c77e1..d96536e 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -427,6 +427,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
 
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.api.GetVncPortAnswer;
@@ -825,6 +826,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     public boolean start() {
         s_logger.info("Startup CloudStack management server...");
 
+        _clusterMgr.registerListener(new LockMasterListener(ManagementServerNode.getManagementServerId()));
+
         enableAdminUser("password");
         return true;
     }


[8/8] git commit: updated refs/heads/master to 111febc

Posted by ah...@apache.org.
Fixed up the rest of the management server code that calls clustermanager


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/111febc5
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/111febc5
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/111febc5

Branch: refs/heads/master
Commit: 111febc567f6a672de5f635432336872f93b256c
Parents: 1caa566
Author: Alex Huang <al...@citrix.com>
Authored: Thu Jul 25 19:57:45 2013 -0700
Committer: Alex Huang <al...@citrix.com>
Committed: Thu Jul 25 19:57:45 2013 -0700

----------------------------------------------------------------------
 .../com/cloud/hypervisor/guru/VMwareGuru.java   |  4 +-
 .../vmware/manager/VmwareManagerImpl.java       | 19 +++----
 .../manager/ClusteredAgentManagerImpl.java      | 28 +--------
 .../com/cloud/async/AsyncJobManagerImpl.java    |  2 -
 .../consoleproxy/ConsoleProxyManagerImpl.java   |  4 +-
 .../com/cloud/resource/ResourceManagerImpl.java | 60 +++++++++++++++++---
 .../com/cloud/server/ManagementServerImpl.java  | 18 ------
 7 files changed, 69 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/111febc5/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
index f2cfbf7..c589713 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -28,7 +28,6 @@ import java.util.UUID;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
-import com.cloud.host.Host;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.storage.command.CopyCommand;
@@ -48,10 +47,10 @@ import com.cloud.agent.api.to.DataStoreTO;
 import com.cloud.agent.api.to.DataTO;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
-import com.cloud.cluster.ClusterManager;
 import com.cloud.configuration.Config;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.host.Host;
 import com.cloud.host.HostVO;
 import com.cloud.host.dao.HostDao;
 import com.cloud.host.dao.HostDetailsDao;
@@ -100,7 +99,6 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
     @Inject HostDao _hostDao;
     @Inject HostDetailsDao _hostDetailsDao;
     @Inject CommandExecLogDao _cmdExecLogDao;
-    @Inject ClusterManager _clusterMgr;
     @Inject VmwareManager _vmwareMgr;
     @Inject SecondaryStorageVmManager _secStorageMgr;
     @Inject NetworkModel _networkMgr;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/111febc5/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
index 0c7ce2e..07e0fc0 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
@@ -43,6 +43,13 @@ import com.vmware.vim25.AboutInfo;
 import com.vmware.vim25.HostConnectSpec;
 import com.vmware.vim25.ManagedObjectReference;
 
+import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
+import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
+import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.Listener;
 import com.cloud.agent.api.AgentControlAnswer;
@@ -51,7 +58,6 @@ import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.StartupCommand;
 import com.cloud.agent.api.StartupRoutingCommand;
-import com.cloud.cluster.ClusterManager;
 import com.cloud.configuration.Config;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.dc.ClusterDetailsDao;
@@ -116,12 +122,6 @@ import com.cloud.utils.script.Script;
 import com.cloud.utils.ssh.SshHelper;
 import com.cloud.vm.DomainRouterVO;
 
-import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
-import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
-import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-
 
 @Local(value = {VmwareManager.class, VmwareDatacenterService.class})
 public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService {
@@ -142,7 +142,6 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
     @Inject ClusterDao _clusterDao;
     @Inject ClusterDetailsDao _clusterDetailsDao;
     @Inject CommandExecLogDao _cmdExecLogDao;
-    @Inject ClusterManager _clusterMgr;
     @Inject SecondaryStorageVmManager _ssvmMgr;
     @Inject DataStoreManager _dataStoreMgr;
     @Inject CiscoNexusVSMDeviceDao _nexusDao;
@@ -664,7 +663,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
 
     private String setupMountPoint(String parent) {
         String mountPoint = null;
-        long mshostId = _clusterMgr.getManagementNodeId();
+        long mshostId = ManagementServerNode.getManagementServerId();
         for (int i = 0; i < 10; i++) {
             String mntPt = parent + File.separator + String.valueOf(mshostId) + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
             File file = new File(mntPt);
@@ -683,7 +682,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
     private void startupCleanup(String parent) {
         s_logger.info("Cleanup mounted NFS mount points used in previous session");
 
-        long mshostId = _clusterMgr.getManagementNodeId();
+        long mshostId = ManagementServerNode.getManagementServerId();
 
         // cleanup left-over NFS mounts from previous session
         String[] mounts = _storage.listFiles(parent + File.separator + String.valueOf(mshostId) + ".*");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/111febc5/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
index a399af3..4622885 100755
--- a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
+++ b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java
@@ -85,6 +85,7 @@ import com.cloud.host.Status;
 import com.cloud.host.Status.Event;
 import com.cloud.resource.ResourceState;
 import com.cloud.resource.ServerResource;
+import com.cloud.serializer.GsonHelper;
 import com.cloud.storage.resource.DummySecondaryStorageResource;
 import com.cloud.utils.DateUtil;
 import com.cloud.utils.Profiler;
@@ -166,6 +167,8 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
         _clusterMgr.registerListener(this);
         _clusterMgr.registerDispatcher(new ClusterDispatcher());
         
+        _gson = GsonHelper.getGson();
+
         return super.configure(name, xmlParams);
     }
 
@@ -1237,31 +1240,6 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
         return send(hostId, commands);
     }
 
-    public Boolean propagateResourceEvent(long agentId, ResourceState.Event event) throws AgentUnavailableException {
-        final String msPeer = getPeerName(agentId);
-        if (msPeer == null) {
-            return null;
-        }
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Propagating agent change request event:" + event.toString() + " to agent:" + agentId);
-        }
-        Command[] cmds = new Command[1];
-        cmds[0] = new PropagateResourceEventCommand(agentId, event);
-
-        String AnsStr = _clusterMgr.execute(msPeer, agentId, _gson.toJson(cmds), true);
-        if (AnsStr == null) {
-            throw new AgentUnavailableException(agentId);
-        }
-
-        Answer[] answers = _gson.fromJson(AnsStr, Answer[].class);
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Result for agent change is " + answers[0].getResult());
-        }
-
-        return answers[0].getResult();
-    }
 
     public boolean executeResourceUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException {
         return _resourceMgr.executeUserRequest(hostId, event);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/111febc5/server/src/com/cloud/async/AsyncJobManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/async/AsyncJobManagerImpl.java b/server/src/com/cloud/async/AsyncJobManagerImpl.java
index f388d36..faf3e71 100644
--- a/server/src/com/cloud/async/AsyncJobManagerImpl.java
+++ b/server/src/com/cloud/async/AsyncJobManagerImpl.java
@@ -60,7 +60,6 @@ import com.cloud.api.ApiDispatcher;
 import com.cloud.api.ApiGsonHelper;
 import com.cloud.api.ApiSerializerHelper;
 import com.cloud.async.dao.AsyncJobDao;
-import com.cloud.cluster.ClusterManager;
 import com.cloud.cluster.ClusterManagerListener;
 import com.cloud.cluster.ManagementServerHostVO;
 import com.cloud.configuration.Config;
@@ -101,7 +100,6 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
 
     @Inject private AsyncJobExecutorContext _context;
     @Inject private SyncQueueManager _queueMgr;
-    @Inject private ClusterManager _clusterMgr;
     @Inject private AccountManager _accountMgr;
     @Inject private AccountDao _accountDao;
     @Inject private AsyncJobDao _jobDao;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/111febc5/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
index 4cb4a33..bae2405 100755
--- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
+++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
@@ -221,6 +221,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
     IPAddressDao _ipAddressDao;
     @Inject
     ManagementServer _ms;
+    @Inject
+    ClusterManager _clusterMgr;
 
     private ConsoleProxyListener _listener;
 
@@ -981,7 +983,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
 
     private synchronized Map<Long, ZoneHostInfo> getZoneHostInfo() {
         Date cutTime = DateUtil.currentGMTTime();
-        List<RunningHostCountInfo> l = _hostDao.getRunningHostCounts(new Date(cutTime.getTime() - ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD));
+        List<RunningHostCountInfo> l = _hostDao.getRunningHostCounts(new Date(cutTime.getTime() - _clusterMgr.getHeartbeatThreshold()));
 
         RunningHostInfoAgregator aggregator = new RunningHostInfoAgregator();
         if (l.size() > 0) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/111febc5/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 cb0e633..b96805c 100755
--- a/server/src/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/com/cloud/resource/ResourceManagerImpl.java
@@ -30,10 +30,11 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
-import com.cloud.server.ConfigurationServer;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
+import com.google.gson.Gson;
+
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd;
 import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd;
@@ -53,10 +54,12 @@ import org.apache.cloudstack.utils.identity.ManagementServerNode;
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.AgentManager.TapAgentsAction;
 import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
 import com.cloud.agent.api.GetHostStatsAnswer;
 import com.cloud.agent.api.GetHostStatsCommand;
 import com.cloud.agent.api.MaintainAnswer;
 import com.cloud.agent.api.MaintainCommand;
+import com.cloud.agent.api.PropagateResourceEventCommand;
 import com.cloud.agent.api.StartupCommand;
 import com.cloud.agent.api.StartupRoutingCommand;
 import com.cloud.agent.api.UnsupportedAnswer;
@@ -119,6 +122,7 @@ import com.cloud.org.Cluster;
 import com.cloud.org.Grouping;
 import com.cloud.org.Grouping.AllocationState;
 import com.cloud.org.Managed;
+import com.cloud.serializer.GsonHelper;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.storage.GuestOSCategoryVO;
 import com.cloud.storage.StorageManager;
@@ -165,6 +169,8 @@ import com.cloud.vm.dao.VMInstanceDao;
 public class ResourceManagerImpl extends ManagerBase implements ResourceManager, ResourceService, Manager {
     private static final Logger s_logger = Logger.getLogger(ResourceManagerImpl.class);
 
+    Gson _gson;
+
     @Inject
     AccountManager _accountMgr;
     @Inject
@@ -908,7 +914,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
     @Override
     public boolean deleteHost(long hostId, boolean isForced, boolean isForceDeleteStorage) {
         try {
-            Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.DeleteHost);
+            Boolean result = propagateResourceEvent(hostId, ResourceState.Event.DeleteHost);
             if (result != null) {
                 return result;
             }
@@ -1222,7 +1228,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 
     @Override
     public boolean maintain(final long hostId) throws AgentUnavailableException {
-        Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.AdminAskMaintenace);
+        Boolean result = propagateResourceEvent(hostId, ResourceState.Event.AdminAskMaintenace);
         if (result != null) {
             return result;
         }
@@ -1329,6 +1335,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
     @Override
     public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
         _defaultSystemVMHypervisor = HypervisorType.getType(_configDao.getValue(Config.SystemVMDefaultHypervisor.toString()));
+        _gson = GsonHelper.getGson();
         return true;
     }
 
@@ -2138,7 +2145,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 
     private boolean cancelMaintenance(long hostId) {
         try {
-            Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.AdminCancelMaintenance);
+            Boolean result = propagateResourceEvent(hostId, ResourceState.Event.AdminCancelMaintenance);
 
             if (result != null) {
                 return result;
@@ -2186,7 +2193,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
     @Override
     public boolean umanageHost(long hostId) {
         try {
-            Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.Unmanaged);
+            Boolean result = propagateResourceEvent(hostId, ResourceState.Event.Unmanaged);
 
             if (result != null) {
                 return result;
@@ -2218,7 +2225,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
         if (cmd.getClusterId() == null) {
             // update agent attache password
             try {
-                Boolean result = _clusterMgr.propagateResourceEvent(cmd.getHostId(), ResourceState.Event.UpdatePassword);
+                Boolean result = propagateResourceEvent(cmd.getHostId(), ResourceState.Event.UpdatePassword);
                 if (result != null) {
                     return result;
                 }
@@ -2235,7 +2242,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
                      * FIXME: this is a buggy logic, check with alex. Shouldn't
                      * return if propagation return non null
                      */
-                    Boolean result = _clusterMgr.propagateResourceEvent(h.getId(), ResourceState.Event.UpdatePassword);
+                    Boolean result = propagateResourceEvent(h.getId(), ResourceState.Event.UpdatePassword);
                     if (result != null) {
                         return result;
                     }
@@ -2249,6 +2256,45 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
         }
     }
 
+    public String getPeerName(long agentHostId) {
+
+        HostVO host = _hostDao.findById(agentHostId);
+        if (host != null && host.getManagementServerId() != null) {
+            if (_clusterMgr.getSelfPeerName().equals(Long.toString(host.getManagementServerId()))) {
+                return null;
+            }
+
+            return Long.toString(host.getManagementServerId());
+        }
+        return null;
+    }
+
+    public Boolean propagateResourceEvent(long agentId, ResourceState.Event event) throws AgentUnavailableException {
+        final String msPeer = getPeerName(agentId);
+        if (msPeer == null) {
+            return null;
+        }
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Propagating agent change request event:" + event.toString() + " to agent:" + agentId);
+        }
+        Command[] cmds = new Command[1];
+        cmds[0] = new PropagateResourceEventCommand(agentId, event);
+
+        String AnsStr = _clusterMgr.execute(msPeer, agentId, _gson.toJson(cmds), true);
+        if (AnsStr == null) {
+            throw new AgentUnavailableException(agentId);
+        }
+
+        Answer[] answers = _gson.fromJson(AnsStr, Answer[].class);
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Result for agent change is " + answers[0].getResult());
+        }
+
+        return answers[0].getResult();
+    }
+
     @Override
     public boolean maintenanceFailed(long hostId) {
         HostVO host = _hostDao.findById(hostId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/111febc5/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index d96536e..0bdb114 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -438,14 +438,12 @@ import com.cloud.alert.AlertManager;
 import com.cloud.alert.AlertVO;
 import com.cloud.alert.dao.AlertDao;
 import com.cloud.api.ApiDBUtils;
-import com.cloud.async.AsyncJobManager;
 import com.cloud.capacity.Capacity;
 import com.cloud.capacity.CapacityVO;
 import com.cloud.capacity.dao.CapacityDao;
 import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
 import com.cloud.cluster.ClusterManager;
 import com.cloud.configuration.Config;
-import com.cloud.configuration.ConfigurationManager;
 import com.cloud.configuration.ConfigurationVO;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.consoleproxy.ConsoleProxyManagementState;
@@ -513,7 +511,6 @@ import com.cloud.projects.ProjectManager;
 import com.cloud.resource.ResourceManager;
 import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.server.auth.UserAuthenticator;
-import com.cloud.service.dao.ServiceOfferingDao;
 import com.cloud.storage.DiskOfferingVO;
 import com.cloud.storage.GuestOS;
 import com.cloud.storage.GuestOSCategoryVO;
@@ -530,13 +527,11 @@ import com.cloud.storage.VolumeVO;
 import com.cloud.storage.dao.DiskOfferingDao;
 import com.cloud.storage.dao.GuestOSCategoryDao;
 import com.cloud.storage.dao.GuestOSDao;
-import com.cloud.storage.dao.UploadDao;
 import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.s3.S3Manager;
 import com.cloud.storage.secondary.SecondaryStorageVmManager;
 import com.cloud.storage.snapshot.SnapshotManager;
-import com.cloud.storage.upload.UploadMonitor;
 import com.cloud.tags.ResourceTagVO;
 import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.template.TemplateManager;
@@ -584,7 +579,6 @@ import com.cloud.vm.VirtualMachineManager;
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.VirtualMachineProfileImpl;
 import com.cloud.vm.dao.ConsoleProxyDao;
-import com.cloud.vm.dao.DomainRouterDao;
 import com.cloud.vm.dao.InstanceGroupDao;
 import com.cloud.vm.dao.SecondaryStorageVmDao;
 import com.cloud.vm.dao.UserVmDao;
@@ -606,8 +600,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     @Inject
     private IPAddressDao _publicIpAddressDao;
     @Inject
-    private DomainRouterDao _routerDao;
-    @Inject
     private ConsoleProxyDao _consoleProxyDao;
     @Inject
     private ClusterDao _clusterDao;
@@ -638,8 +630,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     @Inject
     private SecondaryStorageVmManager _secStorageVmMgr;
     @Inject
-    private ServiceOfferingDao _offeringsDao;
-    @Inject
     private DiskOfferingDao _diskOfferingDao;
     @Inject
     private VMTemplateDao _templateDao;
@@ -671,17 +661,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     private VMInstanceDao _vmInstanceDao;
     @Inject
     private VolumeDao _volumeDao;
-    @Inject
-    private AsyncJobManager _asyncMgr;
     private int _purgeDelay;
     private int _alertPurgeDelay;
     @Inject
     private InstanceGroupDao _vmGroupDao;
     @Inject
-    private UploadMonitor _uploadMonitor;
-    @Inject
-    private UploadDao _uploadDao;
-    @Inject
     private SSHKeyPairDao _sshKeyPairDao;
     @Inject
     private LoadBalancerDao _loadbalancerDao;
@@ -691,8 +675,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     @Inject
     private List<StoragePoolAllocator> _storagePoolAllocators;
     @Inject
-    private ConfigurationManager _configMgr;
-    @Inject
     private ResourceTagDao _resourceTagDao;
 
     @Inject


[7/8] git commit: updated refs/heads/master to 111febc

Posted by ah...@apache.org.
created a project for db framework


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/1caa5662
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1caa5662
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1caa5662

Branch: refs/heads/master
Commit: 1caa566280898b8ca7bdff4881d8efef721b6d58
Parents: 9aaa378
Author: Alex Huang <al...@citrix.com>
Authored: Thu Jul 25 19:00:03 2013 -0700
Committer: Alex Huang <al...@citrix.com>
Committed: Thu Jul 25 19:00:26 2013 -0700

----------------------------------------------------------------------
 framework/db/pom.xml | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1caa5662/framework/db/pom.xml
----------------------------------------------------------------------
diff --git a/framework/db/pom.xml b/framework/db/pom.xml
new file mode 100644
index 0000000..b4011c7
--- /dev/null
+++ b/framework/db/pom.xml
@@ -0,0 +1,28 @@
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+  license agreements. See the NOTICE file distributed with this work for additional 
+  information regarding copyright ownership. The ASF licenses this file to you under 
+  the Apache License, Version 2.0 (the "License"); you may not use this file except 
+  in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
+  Unless required by applicable law or agreed to in writing, software distributed under 
+  the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+  OF ANY KIND, either express or implied. See the License for the specific language 
+  governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>cloud-framework-db</artifactId>
+  <name>Apache CloudStack Framework - Event Notification</name>
+  <parent>
+    <groupId>org.apache.cloudstack</groupId>
+    <artifactId>cloudstack-framework</artifactId>
+    <version>4.2.0-SNAPSHOT</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-utils</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>


[6/8] git commit: updated refs/heads/master to 111febc

Posted by ah...@apache.org.
Moved ClusterManager into it's own package.  Removed the agent load balancing code.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/9aaa378b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/9aaa378b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/9aaa378b

Branch: refs/heads/master
Commit: 9aaa378b087271bf44f27ac9ca7f5ff8e9ec767f
Parents: 395cbcc
Author: Alex Huang <al...@citrix.com>
Authored: Thu Jul 25 18:59:30 2013 -0700
Committer: Alex Huang <al...@citrix.com>
Committed: Thu Jul 25 19:00:26 2013 -0700

----------------------------------------------------------------------
 .../com/cloud/cluster/ManagementServerHost.java |   32 -
 .../agent/api/ScheduleHostScanTaskCommand.java  |    0
 .../cluster/ClusterInvalidSessionException.java |   33 -
 .../cluster/ManagementServerHostPeerVO.java     |  120 --
 .../cloud/cluster/ManagementServerHostVO.java   |  182 ---
 .../cluster/dao/ManagementServerHostDao.java    |   48 -
 .../dao/ManagementServerHostDaoImpl.java        |  276 ----
 .../dao/ManagementServerHostPeerDao.java        |   27 -
 .../dao/ManagementServerHostPeerDaoImpl.java    |  108 --
 framework/cluster/pom.xml                       |   28 +
 .../cloud/cluster/ActiveFencingException.java   |   30 +
 .../com/cloud/cluster/ClusterFenceManager.java  |   23 +
 .../cloud/cluster/ClusterFenceManagerImpl.java  |   58 +
 .../cluster/ClusterInvalidSessionException.java |   32 +
 .../src/com/cloud/cluster/ClusterManager.java   |   58 +
 .../com/cloud/cluster/ClusterManagerImpl.java   | 1198 ++++++++++++++
 .../cloud/cluster/ClusterManagerListener.java   |   25 +
 .../com/cloud/cluster/ClusterManagerMBean.java  |   26 +
 .../cloud/cluster/ClusterManagerMBeanImpl.java  |   67 +
 .../cloud/cluster/ClusterManagerMessage.java    |   44 +
 .../cloud/cluster/ClusterNodeJoinEventArgs.java |   43 +
 .../cloud/cluster/ClusterNodeLeftEventArgs.java |   44 +
 .../src/com/cloud/cluster/ClusterService.java   |   25 +
 .../cloud/cluster/ClusterServiceAdapter.java    |   28 +
 .../com/cloud/cluster/ClusterServicePdu.java    |  112 ++
 .../cloud/cluster/ClusterServiceRequestPdu.java |   54 +
 .../cluster/ClusterServiceServletAdapter.java   |  152 ++
 .../cluster/ClusterServiceServletContainer.java |  179 +++
 .../ClusterServiceServletHttpHandler.java       |  192 +++
 .../cluster/ClusterServiceServletImpl.java      |  148 ++
 .../com/cloud/cluster/ManagementServerHost.java |   34 +
 .../cluster/ManagementServerHostPeerVO.java     |  119 ++
 .../cloud/cluster/ManagementServerHostVO.java   |  182 +++
 .../cloud/cluster/RemoteMethodConstants.java    |   23 +
 .../cluster/dao/ManagementServerHostDao.java    |   48 +
 .../dao/ManagementServerHostDaoImpl.java        |  274 ++++
 .../dao/ManagementServerHostPeerDao.java        |   27 +
 .../dao/ManagementServerHostPeerDaoImpl.java    |  106 ++
 framework/pom.xml                               |    2 +
 server/pom.xml                                  |    5 +
 .../manager/ClusteredAgentManagerImpl.java      |  343 +++-
 .../com/cloud/async/AsyncJobManagerImpl.java    |    8 +-
 .../cloud/cluster/ActiveFencingException.java   |   31 -
 .../com/cloud/cluster/ClusterFenceManager.java  |   23 -
 .../cloud/cluster/ClusterFenceManagerImpl.java  |   58 -
 .../src/com/cloud/cluster/ClusterManager.java   |   67 -
 .../com/cloud/cluster/ClusterManagerImpl.java   | 1517 ------------------
 .../cloud/cluster/ClusterManagerListener.java   |   25 -
 .../com/cloud/cluster/ClusterManagerMBean.java  |   27 -
 .../cloud/cluster/ClusterManagerMBeanImpl.java  |   67 -
 .../cloud/cluster/ClusterManagerMessage.java    |   44 -
 .../cloud/cluster/ClusterNodeJoinEventArgs.java |   43 -
 .../cloud/cluster/ClusterNodeLeftEventArgs.java |   44 -
 .../src/com/cloud/cluster/ClusterService.java   |   25 -
 .../cloud/cluster/ClusterServiceAdapter.java    |   28 -
 .../com/cloud/cluster/ClusterServicePdu.java    |  112 --
 .../cloud/cluster/ClusterServiceRequestPdu.java |   54 -
 .../cluster/ClusterServiceServletAdapter.java   |  148 --
 .../cluster/ClusterServiceServletContainer.java |  179 ---
 .../ClusterServiceServletHttpHandler.java       |  192 ---
 .../cluster/ClusterServiceServletImpl.java      |  146 --
 .../cloud/cluster/DummyClusterManagerImpl.java  |  179 ---
 .../com/cloud/cluster/LockMasterListener.java   |   49 -
 .../cloud/cluster/RemoteMethodConstants.java    |   23 -
 .../com/cloud/server/LockMasterListener.java    |   51 +
 .../com/cloud/server/ManagementServerImpl.java  |    3 +
 66 files changed, 3758 insertions(+), 3940 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/api/src/com/cloud/cluster/ManagementServerHost.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/cluster/ManagementServerHost.java b/api/src/com/cloud/cluster/ManagementServerHost.java
deleted file mode 100644
index 9c88a2b..0000000
--- a/api/src/com/cloud/cluster/ManagementServerHost.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import org.apache.cloudstack.api.InternalIdentity;
-
-public interface ManagementServerHost extends InternalIdentity {
-
-    public static enum State {
-        Up, Starting, Down
-    };
-
-    long getMsid();
-
-    State getState();
-
-    String getVersion();
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/core/src/com/cloud/agent/api/ScheduleHostScanTaskCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/ScheduleHostScanTaskCommand.java b/core/src/com/cloud/agent/api/ScheduleHostScanTaskCommand.java
old mode 100755
new mode 100644

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/engine/schema/src/com/cloud/cluster/ClusterInvalidSessionException.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/cluster/ClusterInvalidSessionException.java b/engine/schema/src/com/cloud/cluster/ClusterInvalidSessionException.java
deleted file mode 100644
index 8ac94f2..0000000
--- a/engine/schema/src/com/cloud/cluster/ClusterInvalidSessionException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import com.cloud.exception.CloudException;
-
-public class ClusterInvalidSessionException extends CloudException {
-
-	private static final long serialVersionUID = -6636524194520997512L;
-
-    public ClusterInvalidSessionException(String message) {
-        super(message);
-    }
-
-    public ClusterInvalidSessionException(String message, Throwable th) {
-        super(message, th);
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/engine/schema/src/com/cloud/cluster/ManagementServerHostPeerVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/cluster/ManagementServerHostPeerVO.java b/engine/schema/src/com/cloud/cluster/ManagementServerHostPeerVO.java
deleted file mode 100644
index e5e12ec..0000000
--- a/engine/schema/src/com/cloud/cluster/ManagementServerHostPeerVO.java
+++ /dev/null
@@ -1,120 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.Date;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-
-import com.cloud.utils.DateUtil;
-import org.apache.cloudstack.api.InternalIdentity;
-
-@Entity
-@Table(name="mshost_peer")
-public class ManagementServerHostPeerVO implements InternalIdentity {
-    
-    @Id
-    @GeneratedValue(strategy=GenerationType.IDENTITY)
-    @Column(name="id")
-    private long id;
-    
-    @Column(name="owner_mshost", updatable=true, nullable=false)
-    private long ownerMshost;
-    
-    @Column(name="peer_mshost", updatable=true, nullable=false)
-    private long peerMshost;
-    
-    @Column(name="peer_runid", updatable=true, nullable=false)
-    private long peerRunid;
-
-    @Column(name="peer_state", updatable = true, nullable=false)
-    @Enumerated(value=EnumType.STRING)
-    private ManagementServerHost.State peerState;
-    
-    @Temporal(TemporalType.TIMESTAMP)
-    @Column(name="last_update", updatable=true, nullable=true)
-    private Date lastUpdateTime;
-
-    public ManagementServerHostPeerVO() {
-    }
-    
-    public ManagementServerHostPeerVO(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState) {
-        this.ownerMshost = ownerMshost;
-        this.peerMshost = peerMshost;
-        this.peerRunid = peerRunid;
-        this.peerState = peerState;
-        
-        this.lastUpdateTime = DateUtil.currentGMTTime();
-    }
-
-    public long getId() {
-        return id;
-    }
-
-    public void setId(long id) {
-        this.id = id;
-    }
-
-    public long getOwnerMshost() {
-        return ownerMshost;
-    }
-
-    public void setOwnerMshost(long ownerMshost) {
-        this.ownerMshost = ownerMshost;
-    }
-
-    public long getPeerMshost() {
-        return peerMshost;
-    }
-
-    public void setPeerMshost(long peerMshost) {
-        this.peerMshost = peerMshost;
-    }
-
-    public long getPeerRunid() {
-        return peerRunid;
-    }
-
-    public void setPeerRunid(long peerRunid) {
-        this.peerRunid = peerRunid;
-    }
-
-    public ManagementServerHost.State getPeerState() {
-        return peerState;
-    }
-
-    public void setPeerState(ManagementServerHost.State peerState) {
-        this.peerState = peerState;
-    }
-
-    public Date getLastUpdateTime() {
-        return lastUpdateTime;
-    }
-
-    public void setLastUpdateTime(Date lastUpdateTime) {
-        this.lastUpdateTime = lastUpdateTime;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/engine/schema/src/com/cloud/cluster/ManagementServerHostVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/cluster/ManagementServerHostVO.java b/engine/schema/src/com/cloud/cluster/ManagementServerHostVO.java
deleted file mode 100644
index 31642e4..0000000
--- a/engine/schema/src/com/cloud/cluster/ManagementServerHostVO.java
+++ /dev/null
@@ -1,182 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster;
-
-import java.util.Date;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-
-import com.cloud.utils.db.GenericDao;
-import org.apache.cloudstack.api.InternalIdentity;
-
-@Entity
-@Table(name="mshost")
-public class ManagementServerHostVO implements ManagementServerHost {
-
-	@Id
-	@GeneratedValue(strategy=GenerationType.IDENTITY)
-	@Column(name="id")
-	private long id;
-
-	@Column(name="msid", updatable=true, nullable=false)
-	private long msid;
-	
-	@Column(name="runid", updatable=true, nullable=false)
-	private long runid;
-
-	@Column(name="name", updatable=true, nullable=true)
-	private String name;
-	
-    @Column(name="state", updatable = true, nullable=false)
-    @Enumerated(value=EnumType.STRING)
-	private ManagementServerHost.State state;
-	
-	@Column(name="version", updatable=true, nullable=true)
-	private String version;
-	
-	@Column(name="service_ip", updatable=true, nullable=false)
-	private String serviceIP;
-	
-	@Column(name="service_port", updatable=true, nullable=false)
-	private int servicePort;
-	
-    @Temporal(TemporalType.TIMESTAMP)
-    @Column(name="last_update", updatable=true, nullable=true)
-    private Date lastUpdateTime;
-    
-    @Column(name=GenericDao.REMOVED_COLUMN)
-    private Date removed;
-    
-	@Column(name="alert_count", updatable=true, nullable=false)
-	private int alertCount;
-
-    public ManagementServerHostVO() {
-    }
-    
-    public ManagementServerHostVO(long msid, long runid, String serviceIP, int servicePort, Date updateTime) {
-    	this.msid = msid;
-    	this.runid = runid;
-    	this.serviceIP = serviceIP;
-    	this.servicePort = servicePort;
-    	this.lastUpdateTime = updateTime;
-    }
-    
-	public long getId() {
-		return id;
-	}
-
-	public void setId(long id) {
-		this.id = id;
-	}
-	
-	public long getRunid() {
-		return runid;
-	}
-	
-	public void setRunid(long runid) {
-		this.runid = runid;
-	}
-
-	@Override
-	public long getMsid() {
-		return msid;
-	}
-
-	public void setMsid(long msid) {
-		this.msid = msid;
-	}
-	
-	public String getName() {
-		return name;
-	}
-	
-	public void setName(String name) {
-		this.name = name;
-	}
-	
-	@Override
-	public ManagementServerHost.State getState() {
-		return this.state;
-	}
-	
-	public void setState(ManagementServerHost.State state) {
-		this.state = state;
-	}
-	
-	@Override
-	public String getVersion() {
-		return version;
-	}
-	
-	public void setVersion(String version) {
-		this.version = version;
-	}
-	
-	public String getServiceIP() {
-		return serviceIP;
-	}
-
-	public void setServiceIP(String serviceIP) {
-		this.serviceIP = serviceIP;
-	}
-
-	public int getServicePort() {
-		return servicePort;
-	}
-
-	public void setServicePort(int servicePort) {
-		this.servicePort = servicePort;
-	}
-
-	public Date getLastUpdateTime() {
-		return lastUpdateTime;
-	}
-
-	public void setLastUpdateTime(Date lastUpdateTime) {
-		this.lastUpdateTime = lastUpdateTime;
-	}
-	
-	public Date getRemoved() {
-		return removed;
-	}
-	
-	public void setRemoved(Date removedTime) {
-		removed = removedTime;
-	}
-	
-	public int getAlertCount() {
-		return alertCount; 
-	}
-	
-	public void setAlertCount(int count) {
-		alertCount = count;
-	}
-	
-	@Override
-    public String toString() {
-        return new StringBuilder("ManagementServer[").append("-").append(id).append("-").append(msid).append("-").append(state).append("]").toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostDao.java b/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostDao.java
deleted file mode 100644
index fec0679..0000000
--- a/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostDao.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster.dao;
-
-import java.util.Date;
-import java.util.List;
-
-import com.cloud.cluster.ManagementServerHost;
-import com.cloud.cluster.ManagementServerHost.State;
-import com.cloud.cluster.ManagementServerHostVO;
-import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.GenericDao;
-
-public interface ManagementServerHostDao extends GenericDao<ManagementServerHostVO, Long> {
-    @Override
-    boolean remove(Long id);
-
-	ManagementServerHostVO findByMsid(long msid);
-	int increaseAlertCount(long id);
-	
-	void update(long id, long runid, String name, String version, String serviceIP, int servicePort, Date lastUpdate);
-	void update(long id, long runid, Date lastUpdate);
-	List<ManagementServerHostVO> getActiveList(Date cutTime);
-	List<ManagementServerHostVO> getInactiveList(Date cutTime);
-
-	void invalidateRunSession(long id, long runid);
-	
-	void update(long id, long runId, State state, Date lastUpdate);
-	
-	List<ManagementServerHostVO> listBy(ManagementServerHost.State...states);
-	public List<Long> listOrphanMsids();
-
-	ManagementServerHostVO findOneInUpState(Filter filter);
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java b/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java
deleted file mode 100644
index 3866da1..0000000
--- a/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java
+++ /dev/null
@@ -1,276 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster.dao;
-
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.TimeZone;
-
-import javax.ejb.Local;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import com.cloud.cluster.ClusterInvalidSessionException;
-import com.cloud.cluster.ManagementServerHost;
-import com.cloud.cluster.ManagementServerHost.State;
-import com.cloud.cluster.ManagementServerHostVO;
-import com.cloud.utils.DateUtil;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
-import com.cloud.utils.db.Transaction;
-import com.cloud.utils.exception.CloudRuntimeException;
-
-@Component
-@Local(value={ManagementServerHostDao.class})
-public class ManagementServerHostDaoImpl extends GenericDaoBase<ManagementServerHostVO, Long> implements ManagementServerHostDao {
-    private static final Logger s_logger = Logger.getLogger(ManagementServerHostDaoImpl.class);
-    
-    private final SearchBuilder<ManagementServerHostVO> MsIdSearch;
-    private final SearchBuilder<ManagementServerHostVO> ActiveSearch;
-    private final SearchBuilder<ManagementServerHostVO> InactiveSearch;
-    private final SearchBuilder<ManagementServerHostVO> StateSearch;
-
-	@Override
-    public void invalidateRunSession(long id, long runid) {
-	    Transaction txn = Transaction.currentTxn();
-        PreparedStatement pstmt = null;
-        try {
-            pstmt = txn.prepareAutoCloseStatement("update mshost set runid=0, state='Down' where id=? and runid=?");
-            pstmt.setLong(1, id);
-            pstmt.setLong(2, runid);
-            
-            pstmt.executeUpdate();
-        } catch (SQLException e) {
-        	throw new CloudRuntimeException("DB exception on " + pstmt.toString(), e);
-        }
-	}
-	
-	@Override
-    public ManagementServerHostVO findByMsid(long msid) {
-        SearchCriteria<ManagementServerHostVO> sc = MsIdSearch.create();
-        sc.setParameters("msid", msid);
-		
-		List<ManagementServerHostVO> l = listIncludingRemovedBy(sc);
-		if(l != null && l.size() > 0) {
-            return l.get(0);
-        }
-		 
-		return null;
-	}
-	
-	@Override
-    @DB
-	public void update(long id, long runid, String name, String version, String serviceIP, int servicePort, Date lastUpdate) {
-        Transaction txn = Transaction.currentTxn();
-        PreparedStatement pstmt = null;
-        try {
-            txn.start();
-            
-            pstmt = txn.prepareAutoCloseStatement("update mshost set name=?, version=?, service_ip=?, service_port=?, last_update=?, removed=null, alert_count=0, runid=?, state=? where id=?");
-            pstmt.setString(1, name);
-            pstmt.setString(2, version);
-            pstmt.setString(3, serviceIP);
-            pstmt.setInt(4, servicePort);
-            pstmt.setString(5, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate));
-            pstmt.setLong(6, runid);
-            pstmt.setString(7, ManagementServerHost.State.Up.toString());
-            pstmt.setLong(8, id);
-            
-            pstmt.executeUpdate();
-            txn.commit();
-        } catch(Exception e) {
-            s_logger.warn("Unexpected exception, ", e);
-        }
-	}
-	
-	@Override
-    @DB
-    public boolean remove(Long id) {
-        Transaction txn = Transaction.currentTxn();
-    
-        try {
-        	txn.start();
-        	
-        	ManagementServerHostVO msHost = findById(id);
-        	msHost.setState(ManagementServerHost.State.Down);
-        	super.remove(id);
-        	
-        	txn.commit();
-        	return true;
-        } catch(Exception e) {
-            s_logger.warn("Unexpected exception, ", e);
-        }
-        
-        return false;
-    }
-
-	@Override
-    @DB
-	public void update(long id, long runid, Date lastUpdate) {
-        Transaction txn = Transaction.currentTxn();
-        PreparedStatement pstmt = null;
-        try {
-            txn.start();
-            
-            pstmt = txn.prepareAutoCloseStatement("update mshost set last_update=?, removed=null, alert_count=0 where id=? and runid=?");
-            pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate));
-            pstmt.setLong(2, id);
-            pstmt.setLong(3, runid);
-            
-            int count = pstmt.executeUpdate();
-            txn.commit();
-
-            if(count < 1) {
-                throw new CloudRuntimeException("Invalid cluster session detected", new ClusterInvalidSessionException("runid " + runid + " is no longer valid"));
-            }
-        } catch(Exception e) {
-            s_logger.warn("Unexpected exception, ", e);
-        }
-	}
-	
-	@Override
-    public List<ManagementServerHostVO> getActiveList(Date cutTime) {
-	    SearchCriteria<ManagementServerHostVO> sc = ActiveSearch.create();
-	    sc.setParameters("lastUpdateTime", cutTime);
-	    
-	    return listIncludingRemovedBy(sc);
-	}
-
-	@Override
-    public List<ManagementServerHostVO> getInactiveList(Date cutTime) {
-	    SearchCriteria<ManagementServerHostVO> sc = InactiveSearch.create();
-	    sc.setParameters("lastUpdateTime", cutTime);
-	    
-	    return listIncludingRemovedBy(sc);
-	}
-	
-	@Override
-    @DB
-	public int increaseAlertCount(long id) {
-        Transaction txn = Transaction.currentTxn();
-        PreparedStatement pstmt = null;
-        int changedRows = 0;
-        try {
-            txn.start();
-            
-            pstmt = txn.prepareAutoCloseStatement("update mshost set alert_count=alert_count+1 where id=? and alert_count=0");
-            pstmt.setLong(1, id);
-            
-            changedRows = pstmt.executeUpdate();
-            txn.commit();
-        } catch(Exception e) {
-            s_logger.warn("Unexpected exception, ", e);
-            txn.rollback();
-        }
-        
-        return changedRows;
-	}
-	
-	protected ManagementServerHostDaoImpl() {
-		MsIdSearch = createSearchBuilder();
-		MsIdSearch.and("msid",  MsIdSearch.entity().getMsid(), SearchCriteria.Op.EQ);
-		MsIdSearch.done();
-		
-	    ActiveSearch = createSearchBuilder();
-	    ActiveSearch.and("lastUpdateTime", ActiveSearch.entity().getLastUpdateTime(),  SearchCriteria.Op.GT);
-	    ActiveSearch.and("removed", ActiveSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
-	    ActiveSearch.done();
-
-	    InactiveSearch = createSearchBuilder();
-	    InactiveSearch.and("lastUpdateTime", InactiveSearch.entity().getLastUpdateTime(),  SearchCriteria.Op.LTEQ);
-	    InactiveSearch.and("removed", InactiveSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
-	    InactiveSearch.done();
-	    
-	    StateSearch = createSearchBuilder();
-	    StateSearch.and("state", StateSearch.entity().getState(), SearchCriteria.Op.IN);
-	    StateSearch.done();
-	}
-	
-	
-	@Override
-    public void update(long id, long runId, State state, Date lastUpdate) {
-	    Transaction txn = Transaction.currentTxn();
-        PreparedStatement pstmt = null;
-        try {
-            pstmt = txn.prepareAutoCloseStatement("update mshost set state=?, last_update=? where id=? and runid=?");
-            pstmt.setString(1, state.toString());
-            pstmt.setString(2, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate));
-            pstmt.setLong(3, id);
-            pstmt.setLong(4, runId);
-            
-            int count = pstmt.executeUpdate();
-            
-            if(count < 1) {
-                throw new CloudRuntimeException("Invalid cluster session detected", new ClusterInvalidSessionException("runid " + runId + " is no longer valid"));
-            }
-        } catch (SQLException e) {
-            throw new CloudRuntimeException("DB exception on " + pstmt.toString(), e);
-        }
-    }
-	
-	@Override
-	public List<ManagementServerHostVO> listBy(ManagementServerHost.State...states) {
-	    SearchCriteria<ManagementServerHostVO> sc = StateSearch.create();
-
-        sc.setParameters("state", (Object[]) states);
-        
-        return listBy(sc);
-	}
-	
-	@Override
-	public List<Long> listOrphanMsids() {
-		List<Long> orphanList = new ArrayList<Long>();
-		
-	    Transaction txn = Transaction.currentTxn();
-        PreparedStatement pstmt = null;
-        try {
-            pstmt = txn.prepareAutoCloseStatement(
-            	"select t.mgmt_server_id from (select mgmt_server_id, count(*) as count from host group by mgmt_server_id) as t WHERE t.count > 0 AND t.mgmt_server_id NOT IN (select msid from mshost)");
-
-            ResultSet rs = pstmt.executeQuery();
-            while(rs.next()) {
-            	orphanList.add(rs.getLong(1));
-            }
-        } catch (SQLException e) {
-            throw new CloudRuntimeException("DB exception on " + pstmt.toString(), e);
-        }
-        
-        return orphanList;
-	}
-
-	@Override
-	public ManagementServerHostVO findOneInUpState(Filter filter) {
-	    SearchCriteria<ManagementServerHostVO> sc = StateSearch.create();
-
-        sc.setParameters("state", ManagementServerHost.State.Up);
-        
-        List<ManagementServerHostVO> mshosts =  listBy(sc, filter);
-        if(mshosts != null && mshosts.size() > 0){
-        	return mshosts.get(0);	
-        }
-        return null;
-	}
-	
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostPeerDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostPeerDao.java b/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostPeerDao.java
deleted file mode 100644
index 14c872a..0000000
--- a/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostPeerDao.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster.dao;
-
-import com.cloud.cluster.ManagementServerHost;
-import com.cloud.cluster.ManagementServerHostPeerVO;
-import com.cloud.utils.db.GenericDao;
-
-public interface ManagementServerHostPeerDao extends GenericDao<ManagementServerHostPeerVO, Long> {
-    void clearPeerInfo(long ownerMshost);
-    void updatePeerInfo(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState);
-    int countStateSeenInPeers(long mshost, long runid, ManagementServerHost.State state);
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostPeerDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostPeerDaoImpl.java b/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostPeerDaoImpl.java
deleted file mode 100644
index 8ad02cd..0000000
--- a/engine/schema/src/com/cloud/cluster/dao/ManagementServerHostPeerDaoImpl.java
+++ /dev/null
@@ -1,108 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.cluster.dao;
-
-import java.util.List;
-
-import javax.ejb.Local;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import com.cloud.cluster.ManagementServerHost;
-import com.cloud.cluster.ManagementServerHostPeerVO;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
-import com.cloud.utils.db.Transaction;
-
-@Component
-@Local(value={ManagementServerHostPeerDao.class})
-public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementServerHostPeerVO, Long> implements ManagementServerHostPeerDao {
-    private static final Logger s_logger = Logger.getLogger(ManagementServerHostPeerDaoImpl.class);
-    
-    private final SearchBuilder<ManagementServerHostPeerVO> ClearPeerSearch;
-    private final SearchBuilder<ManagementServerHostPeerVO> FindForUpdateSearch;
-    private final SearchBuilder<ManagementServerHostPeerVO> CountSearch;
-
-    public ManagementServerHostPeerDaoImpl() {
-        ClearPeerSearch = createSearchBuilder();
-        ClearPeerSearch.and("ownerMshost", ClearPeerSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ);
-        ClearPeerSearch.done();
-        
-        FindForUpdateSearch = createSearchBuilder();
-        FindForUpdateSearch.and("ownerMshost", FindForUpdateSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ);
-        FindForUpdateSearch.and("peerMshost", FindForUpdateSearch.entity().getPeerMshost(), SearchCriteria.Op.EQ);
-        FindForUpdateSearch.and("peerRunid", FindForUpdateSearch.entity().getPeerRunid(), SearchCriteria.Op.EQ);
-        FindForUpdateSearch.done();
-        
-        CountSearch = createSearchBuilder();
-        CountSearch.and("peerMshost", CountSearch.entity().getPeerMshost(), SearchCriteria.Op.EQ);
-        CountSearch.and("peerRunid", CountSearch.entity().getPeerRunid(), SearchCriteria.Op.EQ);
-        CountSearch.and("peerState", CountSearch.entity().getPeerState(), SearchCriteria.Op.EQ);
-        CountSearch.done();
-    }
-    
-    @Override
-    @DB
-    public void clearPeerInfo(long ownerMshost) {
-        SearchCriteria<ManagementServerHostPeerVO>  sc = ClearPeerSearch.create();
-        sc.setParameters("ownerMshost", ownerMshost);
-        
-        expunge(sc);
-    }
-    
-    @Override
-    @DB
-    public void updatePeerInfo(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState) {
-        Transaction txn = Transaction.currentTxn();
-        try {
-            txn.start();
-        
-            SearchCriteria<ManagementServerHostPeerVO> sc = FindForUpdateSearch.create();
-            sc.setParameters("ownerMshost", ownerMshost);
-            sc.setParameters("peerMshost", peerMshost);
-            sc.setParameters("peerRunid", peerRunid);
-            List<ManagementServerHostPeerVO> l = listBy(sc);
-            if(l.size() == 1) {
-                ManagementServerHostPeerVO peer = l.get(0);
-                peer.setPeerState(peerState);
-                update(peer.getId(), peer);
-            } else {
-                ManagementServerHostPeerVO peer = new ManagementServerHostPeerVO(ownerMshost, peerMshost, peerRunid, peerState);
-                persist(peer);
-            }
-            txn.commit();
-        } catch(Exception e) {
-            s_logger.warn("Unexpected exception, ", e);
-            txn.rollback();
-        }
-    }
-    
-    @Override
-    @DB
-    public int countStateSeenInPeers(long mshost, long runid, ManagementServerHost.State state) {
-        SearchCriteria<ManagementServerHostPeerVO> sc = CountSearch.create();
-        sc.setParameters("peerMshost", mshost);
-        sc.setParameters("peerRunid", runid);
-        sc.setParameters("peerState", state);
-        
-        List<ManagementServerHostPeerVO> l = listBy(sc);
-        return l.size();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/pom.xml
----------------------------------------------------------------------
diff --git a/framework/cluster/pom.xml b/framework/cluster/pom.xml
new file mode 100644
index 0000000..116b635
--- /dev/null
+++ b/framework/cluster/pom.xml
@@ -0,0 +1,28 @@
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+  license agreements. See the NOTICE file distributed with this work for additional 
+  information regarding copyright ownership. The ASF licenses this file to you under 
+  the Apache License, Version 2.0 (the "License"); you may not use this file except 
+  in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
+  Unless required by applicable law or agreed to in writing, software distributed under 
+  the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+  OF ANY KIND, either express or implied. See the License for the specific language 
+  governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>cloud-framework-cluster</artifactId>
+  <name>Apache CloudStack Framework - Clustering</name>
+  <parent>
+    <groupId>org.apache.cloudstack</groupId>
+    <artifactId>cloudstack-framework</artifactId>
+    <version>4.2.0-SNAPSHOT</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-utils</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ActiveFencingException.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ActiveFencingException.java b/framework/cluster/src/com/cloud/cluster/ActiveFencingException.java
new file mode 100644
index 0000000..a445086
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ActiveFencingException.java
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+
+public class ActiveFencingException extends Exception {
+    private static final long serialVersionUID = -3975376101728211726L;
+
+    public ActiveFencingException(String message) {
+        super(message);
+    }
+
+    public ActiveFencingException(String message, Throwable th) {
+        super(message, th);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterFenceManager.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterFenceManager.java b/framework/cluster/src/com/cloud/cluster/ClusterFenceManager.java
new file mode 100644
index 0000000..b9782ad
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterFenceManager.java
@@ -0,0 +1,23 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import com.cloud.utils.component.Manager;
+
+public interface ClusterFenceManager extends Manager {
+	public static final int SELF_FENCING_EXIT_CODE = 219;
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterFenceManagerImpl.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterFenceManagerImpl.java b/framework/cluster/src/com/cloud/cluster/ClusterFenceManagerImpl.java
new file mode 100644
index 0000000..7e4922e
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterFenceManagerImpl.java
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.component.ManagerBase;
+
+
+@Component
+@Local(value={ClusterFenceManager.class})
+public class ClusterFenceManagerImpl extends ManagerBase implements ClusterFenceManager, ClusterManagerListener {
+    private static final Logger s_logger = Logger.getLogger(ClusterFenceManagerImpl.class);
+	
+	@Inject ClusterManager _clusterMgr;
+	
+	@Override
+	public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+		_clusterMgr.registerListener(this);
+		return true;
+	}
+
+	@Override
+	public void onManagementNodeJoined(List<ManagementServerHostVO> nodeList, long selfNodeId) {
+	}
+
+	@Override
+	public void onManagementNodeLeft(List<ManagementServerHostVO> nodeList, long selfNodeId) {
+	}
+
+	@Override
+	public void onManagementNodeIsolated() {
+		s_logger.error("Received node isolation notification, will perform self-fencing and shut myself down");
+		System.exit(SELF_FENCING_EXIT_CODE);
+	}
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterInvalidSessionException.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterInvalidSessionException.java b/framework/cluster/src/com/cloud/cluster/ClusterInvalidSessionException.java
new file mode 100644
index 0000000..e9378b7
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterInvalidSessionException.java
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+
+public class ClusterInvalidSessionException extends Exception {
+
+	private static final long serialVersionUID = -6636524194520997512L;
+
+    public ClusterInvalidSessionException(String message) {
+        super(message);
+    }
+
+    public ClusterInvalidSessionException(String message, Throwable th) {
+        super(message, th);
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9aaa378b/framework/cluster/src/com/cloud/cluster/ClusterManager.java
----------------------------------------------------------------------
diff --git a/framework/cluster/src/com/cloud/cluster/ClusterManager.java b/framework/cluster/src/com/cloud/cluster/ClusterManager.java
new file mode 100644
index 0000000..51d993e
--- /dev/null
+++ b/framework/cluster/src/com/cloud/cluster/ClusterManager.java
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cluster;
+
+import com.cloud.utils.component.Manager;
+
+public interface ClusterManager extends Manager {
+    static final String ALERT_SUBJECT = "cluster-alert";
+	
+    void OnReceiveClusterServicePdu(ClusterServicePdu pdu);
+
+    /**
+     * This executes
+     * @param strPeer
+     * @param agentId
+     * @param cmds
+     * @param stopOnError
+     * @return
+     */
+    String execute(String strPeer, long agentId, String cmds, boolean stopOnError);
+
+    /**
+     * Broadcast the command to all of the  management server nodes.
+     * @param agentId agent id this broadcast is regarding
+     * @param cmds commands to broadcast
+     */
+    void broadcast(long agentId, String cmds);
+
+    int getHeartbeatThreshold();
+	
+    void registerListener(ClusterManagerListener listener);
+    void unregisterListener(ClusterManagerListener listener);
+
+    void registerDispatcher(Dispatcher dispatcher);
+
+    ManagementServerHost getPeer(String peerName);
+    
+    String getSelfPeerName();
+
+    public interface Dispatcher {
+        String getName();
+        String dispatch(ClusterServicePdu pdu);
+    }
+}