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