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/05/14 02:43:08 UTC
[45/50] [abbrv] Merged master to vmsync
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d4039743/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 5a4f179,521b5e0..752eb73
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@@ -32,29 -36,45 +32,46 @@@ import javax.ejb.Local
import javax.inject.Inject;
import javax.naming.ConfigurationException;
- import com.cloud.capacity.CapacityManager;
++import org.apache.log4j.Logger;
++
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+ import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
+ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+import org.apache.cloudstack.framework.messagebus.MessageBus;
+import org.apache.cloudstack.messagebus.TopicConstants;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
-
- import com.cloud.dc.*;
- import com.cloud.agent.api.*;
- import org.apache.log4j.Logger;
+ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
-import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.AgentManager.OnError;
import com.cloud.agent.Listener;
+ import com.cloud.agent.api.AgentControlAnswer;
+ import com.cloud.agent.api.AgentControlCommand;
+ import com.cloud.agent.api.Answer;
+ import com.cloud.agent.api.CheckVirtualMachineAnswer;
+ import com.cloud.agent.api.CheckVirtualMachineCommand;
+ import com.cloud.agent.api.ClusterSyncAnswer;
-import com.cloud.agent.api.ClusterSyncCommand;
+ import com.cloud.agent.api.Command;
-import com.cloud.agent.api.MigrateAnswer;
-import com.cloud.agent.api.MigrateCommand;
+ import com.cloud.agent.api.PingRoutingCommand;
-import com.cloud.agent.api.PrepareForMigrationAnswer;
-import com.cloud.agent.api.PrepareForMigrationCommand;
+ import com.cloud.agent.api.RebootAnswer;
+ import com.cloud.agent.api.RebootCommand;
-import com.cloud.agent.api.ScaleVmCommand;
+ import com.cloud.agent.api.StartAnswer;
+ import com.cloud.agent.api.StartCommand;
+ import com.cloud.agent.api.StartupCommand;
+ import com.cloud.agent.api.StartupRoutingCommand;
-import com.cloud.agent.api.StartupRoutingCommand.VmState;
+ import com.cloud.agent.api.StopAnswer;
+ import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.manager.Commands;
import com.cloud.agent.manager.allocator.HostAllocator;
import com.cloud.alert.AlertManager;
+import com.cloud.api.ApiSerializerHelper;
+import com.cloud.async.AsyncJob;
+import com.cloud.async.AsyncJobConstants;
+import com.cloud.async.AsyncJobExecutionContext;
+import com.cloud.async.AsyncJobManager;
+ import com.cloud.capacity.CapacityManager;
import com.cloud.cluster.ClusterManager;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
@@@ -133,16 -165,17 +164,16 @@@ import com.cloud.utils.exception.CloudR
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
--import com.cloud.vm.ItWorkVO.Step;
import com.cloud.vm.VirtualMachine.Event;
+import com.cloud.vm.VirtualMachine.PowerState;
import com.cloud.vm.VirtualMachine.State;
++import com.cloud.vm.VmWorkJobVO.Step;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
+ import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
-import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.vm.snapshot.VMSnapshotManager;
-import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
- import com.cloud.vm.dao.UserVmDetailsDao;
@Local(value = VirtualMachineManager.class)
public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMachineManager, Listener {
@@@ -172,12 -207,8 +205,12 @@@
protected DomainDao _domainDao;
@Inject
protected ClusterManager _clusterMgr;
+
- /*
++/*
@Inject
protected ItWorkDao _workDao;
+*/
+
@Inject
protected UserVmDao _userVmDao;
@Inject
@@@ -229,10 -270,16 +272,16 @@@
this._hostAllocators = _hostAllocators;
}
- @Inject
+ @Inject
+ protected List<StoragePoolAllocator> _storagePoolAllocators;
+
+ @Inject
protected ResourceManager _resourceMgr;
-
+
- @Inject
+ @Inject
+ protected SnapshotManager _snapshotMgr;
+
+ @Inject
protected VMSnapshotManager _vmSnapshotMgr = null;
@Inject
protected ClusterDetailsDao _clusterDetailsDao;
@@@ -243,11 -290,9 +292,13 @@@
protected ConfigurationDao _configDao;
@Inject
VolumeManager volumeMgr;
-
+
+ @Inject protected MessageBus _messageBus;
+ @Inject protected VirtualMachinePowerStateSync _syncMgr;
+ @Inject protected VmWorkJobDao _workJobDao;
+ @Inject protected AsyncJobManager _jobMgr;
+ @Inject
+ DeploymentPlanningManager _dpMgr;
Map<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>> _vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>>();
protected StateMachine2<State, VirtualMachine.Event, VirtualMachine> _stateMachine;
@@@ -327,15 -359,15 +378,15 @@@
}
if (template.getFormat() == ImageFormat.ISO) {
-- this.volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner);
++ volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner);
} else if (template.getFormat() == ImageFormat.BAREMETAL) {
// Do nothing
} else {
-- this.volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner);
++ volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner);
}
for (Pair<DiskOfferingVO, Long> offering : dataDiskOfferings) {
-- this.volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
++ volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
}
txn.commit();
@@@ -413,7 -450,8 +464,8 @@@
s_logger.debug("Cleaning up NICS");
_networkMgr.cleanupNics(profile);
// Clean up volumes based on the vm's instance id
- this.volumeMgr.cleanupVolumes(vm.getId());
+ List<VolumeVO> rootVol = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT);
- this.volumeMgr.cleanupVolumes(vm.getId());
++ volumeMgr.cleanupVolumes(vm.getId());
VirtualMachineGuru<T> guru = getVmGuru(vm);
guru.finalizeExpunge(vm);
@@@ -483,255 -550,143 +564,256 @@@
}
}
- /*
-- protected boolean checkWorkItems(VMInstanceVO vm, State state) throws ConcurrentOperationException {
-- while (true) {
-- ItWorkVO vo = _workDao.findByOutstandingWork(vm.getId(), state);
-- if (vo == null) {
-- if (s_logger.isDebugEnabled()) {
-- s_logger.debug("Unable to find work for VM: " + vm + " and state: " + state);
++ /*
++ protected boolean checkWorkItems(VMInstanceVO vm, State state) throws ConcurrentOperationException {
++ while (true) {
++ VmWorkJobVO vo = _workDao.findByOutstandingWork(vm.getId(), state);
++ if (vo == null) {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("Unable to find work for VM: " + vm + " and state: " + state);
++ }
++ return true;
}
-- return true;
-- }
-- if (vo.getStep() == Step.Done) {
-- if (s_logger.isDebugEnabled()) {
-- s_logger.debug("Work for " + vm + " is " + vo.getStep());
++ if (vo.getStep() == Step.Done) {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("Work for " + vm + " is " + vo.getStep());
++ }
++ return true;
}
-- return true;
-- }
-- if (vo.getSecondsTaskIsInactive() > _cancelWait) {
-- s_logger.warn("The task item for vm " + vm + " has been inactive for " + vo.getSecondsTaskIsInactive());
-- return false;
-- }
++ if (vo.getSecondsTaskIsInactive() > _cancelWait) {
++ s_logger.warn("The task item for vm " + vm + " has been inactive for " + vo.getSecondsTaskIsInactive());
++ return false;
++ }
-- try {
-- Thread.sleep(_opWaitInterval);
-- } catch (InterruptedException e) {
-- s_logger.info("Waiting for " + vm + " but is interrupted");
-- throw new ConcurrentOperationException("Waiting for " + vm + " but is interrupted");
++ try {
++ Thread.sleep(_opWaitInterval);
++ } catch (InterruptedException e) {
++ s_logger.info("Waiting for " + vm + " but is interrupted");
++ throw new ConcurrentOperationException("Waiting for " + vm + " but is interrupted");
++ }
++ s_logger.debug("Waiting some more to make sure there's no activity on " + vm);
}
-- s_logger.debug("Waiting some more to make sure there's no activity on " + vm);
}
- }
- */
++ */
+
- /*
- @DB
- protected <T extends VMInstanceVO> Ternary<T, ReservationContext, ItWorkVO> changeToStartState(VirtualMachineGuru<T> vmGuru, T vm, User caller, Account account)
- throws ConcurrentOperationException {
- long vmId = vm.getId();
++ /*
++ @DB
++ protected <T extends VMInstanceVO> Ternary<T, ReservationContext, VmWorkJobVO> changeToStartState(VirtualMachineGuru<T> vmGuru, T vm, User caller, Account account)
++ throws ConcurrentOperationException {
++ long vmId = vm.getId();
- ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Starting, vm.getType(), vm.getId());
- int retry = _lockStateRetry;
- while (retry-- != 0) {
- Transaction txn = Transaction.currentTxn();
- Ternary<T, ReservationContext, ItWorkVO> result = null;
- txn.start();
- try {
- Journal journal = new Journal.LogJournal("Creating " + vm, s_logger);
- work = _workDao.persist(work);
- ReservationContextImpl context = new ReservationContextImpl(work.getId(), journal, caller, account);
- }
-
- @DB
- protected <T extends VMInstanceVO> Ternary<T, ReservationContext, ItWorkVO> changeToStartState(VirtualMachineGuru<T> vmGuru, T vm, User caller, Account account)
- throws ConcurrentOperationException {
- long vmId = vm.getId();
-
- ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Starting, vm.getType(), vm.getId());
- int retry = _lockStateRetry;
- while (retry-- != 0) {
- Transaction txn = Transaction.currentTxn();
- Ternary<T, ReservationContext, ItWorkVO> result = null;
- txn.start();
- try {
- Journal journal = new Journal.LogJournal("Creating " + vm, s_logger);
- work = _workDao.persist(work);
- ReservationContextImpl context = new ReservationContextImpl(work.getId(), journal, caller, account);
++ VmWorkJobVO work = new VmWorkJobVO(UUID.randomUUID().toString(), _nodeId, State.Starting, vm.getType(), vm.getId());
++ int retry = _lockStateRetry;
++ while (retry-- != 0) {
++ Transaction txn = Transaction.currentTxn();
++ Ternary<T, ReservationContext, VmWorkJobVO> result = null;
++ txn.start();
++ try {
++ Journal journal = new Journal.LogJournal("Creating " + vm, s_logger);
++ work = _workDao.persist(work);
++ ReservationContextImpl context = new ReservationContextImpl(work.getId(), journal, caller, account);
-- if (stateTransitTo(vm, Event.StartRequested, null, work.getId())) {
++ if (stateTransitTo(vm, Event.StartRequested, null, work.getId())) {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("Successfully transitioned to start state for " + vm + " reservation id = " + work.getId());
++ }
++ result = new Ternary<T, ReservationContext, VmWorkJobVO>(vmGuru.findById(vmId), context, work);
++ txn.commit();
++ return result;
++ }
++ } catch (NoTransitionException e) {
if (s_logger.isDebugEnabled()) {
-- s_logger.debug("Successfully transitioned to start state for " + vm + " reservation id = " + work.getId());
++ s_logger.debug("Unable to transition into Starting state due to " + e.getMessage());
++ }
++ } finally {
++ if (result == null) {
++ txn.rollback();
}
-- result = new Ternary<T, ReservationContext, ItWorkVO>(vmGuru.findById(vmId), context, work);
-- txn.commit();
-- return result;
-- }
-- } catch (NoTransitionException e) {
-- if (s_logger.isDebugEnabled()) {
-- s_logger.debug("Unable to transition into Starting state due to " + e.getMessage());
}
-- } finally {
-- if (result == null) {
-- txn.rollback();
++
++ VMInstanceVO instance = _vmDao.findById(vmId);
++ if (instance == null) {
++ throw new ConcurrentOperationException("Unable to acquire lock on " + vm);
}
-- }
-- VMInstanceVO instance = _vmDao.findById(vmId);
-- if (instance == null) {
-- throw new ConcurrentOperationException("Unable to acquire lock on " + vm);
-- }
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("Determining why we're unable to update the state to Starting for " + instance + ". Retry=" + retry);
++ }
-- if (s_logger.isDebugEnabled()) {
-- s_logger.debug("Determining why we're unable to update the state to Starting for " + instance + ". Retry=" + retry);
-- }
++ State state = instance.getState();
++ if (state == State.Running) {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("VM is already started: " + vm);
++ }
++ return null;
++ }
-- State state = instance.getState();
-- if (state == State.Running) {
-- if (s_logger.isDebugEnabled()) {
-- s_logger.debug("VM is already started: " + vm);
++ if (state.isTransitional()) {
++ if (!checkWorkItems(vm, state)) {
++ throw new ConcurrentOperationException("There are concurrent operations on " + vm);
++ } else {
++ continue;
++ }
}
-- return null;
-- }
-- if (state.isTransitional()) {
-- if (!checkWorkItems(vm, state)) {
-- throw new ConcurrentOperationException("There are concurrent operations on " + vm);
-- } else {
-- continue;
++ if (state != State.Stopped) {
++ s_logger.debug("VM " + vm + " is not in a state to be started: " + state);
++ return null;
}
}
-- if (state != State.Stopped) {
-- s_logger.debug("VM " + vm + " is not in a state to be started: " + state);
-- return null;
-- }
++ throw new ConcurrentOperationException("Unable to change the state of " + vm);
}
-
- throw new ConcurrentOperationException("Unable to change the state of " + vm);
- }
- */
++ */
+ @DB
+ protected <T extends VMInstanceVO> Ternary<T, ReservationContext, VmWorkJobVO> changeToStartState(VirtualMachineGuru<T> vmGuru, T vm, User caller, Account account)
+ throws ConcurrentOperationException {
+
+ long vmId = vm.getId();
+
+ Ternary<T, ReservationContext, VmWorkJobVO> result = null;
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ try {
- VmWorkJobVO work = this._workJobDao.findById(AsyncJobExecutionContext.getCurrentExecutionContext().getJob().getId());
++ VmWorkJobVO work = _workJobDao.findById(AsyncJobExecutionContext.getCurrentExecutionContext().getJob().getId());
+
+ Journal journal = new Journal.LogJournal("Creating " + vm, s_logger);
+ ReservationContextImpl context = new ReservationContextImpl(work.getUuid(), journal, caller, account);
+ if (stateTransitTo(vm, Event.StartRequested, null, work.getUuid())) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Successfully transitioned to start state for " + vm + " reservation id = " + work.getId());
+ }
+ result = new Ternary<T, ReservationContext, VmWorkJobVO>(vmGuru.findById(vmId), context, work);
+ txn.commit();
+ return result;
+ }
+ } catch (NoTransitionException e) {
+ s_logger.warn("Unable to transition into Starting state due to " + e.getMessage());
+ } finally {
+ if(result == null)
+ txn.rollback();
+ }
+
throw new ConcurrentOperationException("Unable to change the state of " + vm);
}
-
- protected <T extends VMInstanceVO> boolean changeState(T vm, Event event, Long hostId, ItWorkVO work, Step step) throws NoTransitionException {
+
+ protected <T extends VMInstanceVO> boolean changeState(T vm, Event event, Long hostId, VmWorkJobVO work, Step step) throws NoTransitionException {
// FIXME: We should do this better.
- Step previousStep = work.getStep();
- _workDao.updateStep(work, step);
+ VmWorkJobVO.Step previousStep = work.getStep();
+
boolean result = false;
try {
result = stateTransitTo(vm, event, hostId);
return result;
} finally {
if (!result) {
- _workDao.updateStep(work, previousStep);
+ work.setStep(previousStep);
- this._workJobDao.update(work.getId(), work);
++ _workJobDao.update(work.getId(), work);
}
}
}
-
+
@Override
public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account) throws InsufficientCapacityException,
- ConcurrentOperationException, ResourceUnavailableException {
+ ConcurrentOperationException, ResourceUnavailableException {
return advanceStart(vm, params, caller, account, null);
}
+
++ @Override
+ @DB
+ public <T extends VMInstanceVO> T advanceStart(final T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy)
+ throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
+
+ VmWorkJobVO workJob = null;
+ Transaction txn = Transaction.currentTxn();
+ try {
+ txn.start();
+
+ _vmDao.lockRow(vm.getId(), true);
+
+ List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
+ VirtualMachine.Type.Instance, vm.getId(), VmWorkConstants.VM_WORK_START);
+
+ if(pendingWorkJobs != null && pendingWorkJobs.size() > 0) {
+ assert(pendingWorkJobs.size() == 1);
+ workJob = pendingWorkJobs.get(0);
+ } else {
+ workJob = new VmWorkJobVO();
+
+ workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+ workJob.setCmd(VmWorkConstants.VM_WORK_START);
+
+ workJob.setAccountId(account.getId());
+ workJob.setUserId(caller.getId());
+ workJob.setStep(VmWorkJobVO.Step.Starting);
+ workJob.setVmType(vm.getType());
+ workJob.setVmInstanceId(vm.getId());
+
+ // save work context info (there are some duplications)
+ VmWorkStart workInfo = new VmWorkStart();
+ workInfo.setAccountId(account.getId());
+ workInfo.setUserId(caller.getId());
+ workInfo.setVmId(vm.getId());
+ workInfo.setPlan(planToDeploy);
+ workInfo.setParams(params);
+ workJob.setCmdInfo(ApiSerializerHelper.toSerializedString(workInfo));
+
+ _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+ }
+
+ txn.commit();
+ } catch(Throwable e) {
+ s_logger.error("Unexpected exception", e);
+ txn.rollback();
+ throw new ConcurrentOperationException("Unhandled exception, converted to ConcurrentOperationException");
+ }
+
+ final long jobId = workJob.getId();
+
- AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
++ AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+ //
+ // TODO : this will be replaced with fully-asynchronized way later so that we don't need
+ // to wait here. The reason we do it synchronized here is that callers of advanceStart is expecting
+ // synchronized semantics
- //
++ //
+ //
+ _jobMgr.waitAndCheck(
- new String[] { TopicConstants.VM_POWER_STATE, TopicConstants.JOB_STATE },
++ new String[] { TopicConstants.VM_POWER_STATE, TopicConstants.JOB_STATE },
+ 3000L, 600000L, new Predicate() {
+
+ @Override
+ public boolean checkCondition() {
+ VMInstanceVO instance = _vmDao.findById(vm.getId());
+ if(instance.getPowerState() == VirtualMachine.PowerState.PowerOn)
+ return true;
+
+ VmWorkJobVO workJob = _workJobDao.findById(jobId);
+ if(workJob.getStatus() != AsyncJobConstants.STATUS_IN_PROGRESS)
+ return true;
+
+ return false;
+ }
+ });
+ AsyncJobExecutionContext.getCurrentExecutionContext().disjoinJob(jobId);
+
+ return vm;
+ }
@Override
- public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy)
+ public <T extends VMInstanceVO> T processVmStartWork(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
- long vmId = vm.getId();
VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
-
vm = vmGuru.findById(vm.getId());
- Ternary<T, ReservationContext, ItWorkVO> start = changeToStartState(vmGuru, vm, caller, account);
- if (start == null) {
- return vmGuru.findById(vmId);
- }
+
+ Ternary<T, ReservationContext, VmWorkJobVO> start = changeToStartState(vmGuru, vm, caller, account);
+ assert(start != null);
- vm = start.first();
ReservationContext ctx = start.second();
- ItWorkVO work = start.third();
+ VmWorkJobVO work = start.third();
T startedVm = null;
ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId());
@@@ -822,20 -780,15 +904,14 @@@
VirtualMachineProfileImpl<T> vmProfile = new VirtualMachineProfileImpl<T>(vm, template, offering, account, params);
DeployDestination dest = null;
- for (DeploymentPlanner planner : _planners) {
- if (planner.canHandle(vmProfile, plan, avoids)) {
- dest = planner.plan(vmProfile, plan, avoids);
- } else {
- continue;
- }
- if (dest != null) {
- avoids.addHost(dest.getHost().getId());
- AsyncJobExecutionContext.getCurrentExecutionContext().logJobJournal(
- AsyncJob.JournalType.SUCCESS, "Deployment found, dest host: " + dest.getHost().getId(), null);
- break;
- }
- }
+ try {
+ dest = _dpMgr.planDeployment(vmProfile, plan, avoids);
+ } catch (AffinityConflictException e2) {
+ s_logger.warn("Unable to create deployment, affinity rules associted to the VM conflict", e2);
+ throw new CloudRuntimeException(
+ "Unable to create deployment, affinity rules associted to the VM conflict");
+ }
-
if (dest == null) {
if (planChangedByVolume) {
plan = originalPlan;
@@@ -847,6 -800,11 +923,13 @@@
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
}
+ if (dest != null) {
+ avoids.addHost(dest.getHost().getId());
- journal.record("Deployment found ", vmProfile, dest);
++ AsyncJobExecutionContext.getCurrentExecutionContext().logJobJournal(
++ AsyncJob.JournalType.SUCCESS, "Deployment found, dest host: " + dest.getHost().getId(), null);
++ break;
+ }
+
long destHostId = dest.getHost().getId();
vm.setPodId(dest.getPod().getId());
Long cluster_id = dest.getCluster().getId();
@@@ -867,9 -825,9 +950,9 @@@
if (s_logger.isDebugEnabled()) {
s_logger.debug("VM is being created in podId: " + vm.getPodIdToDeployIn());
}
- _networkMgr.prepare(vmProfile, dest, ctx);
+ _networkMgr.prepare(vmProfile, dest, ctx);
if (vm.getHypervisorType() != HypervisorType.BareMetal) {
-- this.volumeMgr.prepare(vmProfile, dest);
++ volumeMgr.prepare(vmProfile, dest);
}
//since StorageMgr succeeded in volume creation, reuse Volume for further tries until current cluster has capacity
if(!reuseVolume){
@@@ -984,9 -946,14 +1067,14 @@@
}
}
+ if (startedVm == null) {
+ throw new CloudRuntimeException("Unable to start instance '" + vm.getHostName()
+ + "' (" + vm.getUuid() + "), see management server log for details");
+ }
+
return startedVm;
}
-
+
@Override
public <T extends VMInstanceVO> boolean stop(T vm, User user, Account account) throws ResourceUnavailableException {
try {
@@@ -1080,96 -1047,34 +1168,96 @@@
s_logger.warn("Unable to release some network resources.", e);
}
-- this.volumeMgr.release(profile);
++ volumeMgr.release(profile);
s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state");
return true;
}
+
+ @Override
+ public <T extends VMInstanceVO> boolean advanceStop(final T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
+ VmWorkJobVO workJob = null;
+ Transaction txn = Transaction.currentTxn();
+ try {
+ txn.start();
+
+ _vmDao.lockRow(vm.getId(), true);
+
+ List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
+ VirtualMachine.Type.Instance, vm.getId(), VmWorkConstants.VM_WORK_STOP);
+
+ if(pendingWorkJobs != null && pendingWorkJobs.size() > 0) {
+ assert(pendingWorkJobs.size() == 1);
+ workJob = pendingWorkJobs.get(0);
+ } else {
+ workJob = new VmWorkJobVO();
+
+ workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+ workJob.setCmd(VmWorkConstants.VM_WORK_STOP);
+
+ workJob.setAccountId(account.getId());
+ workJob.setUserId(user.getId());
+ workJob.setStep(VmWorkJobVO.Step.Prepare);
+ workJob.setVmType(vm.getType());
+ workJob.setVmInstanceId(vm.getId());
+
+ // save work context info (there are some duplications)
+ VmWorkStop workInfo = new VmWorkStop();
+ workInfo.setAccountId(account.getId());
+ workInfo.setUserId(user.getId());
+ workInfo.setVmId(vm.getId());
+ workInfo.setForceStop(forced);
+ workJob.setCmdInfo(ApiSerializerHelper.toSerializedString(workInfo));
+
+ _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+ }
+
+ txn.commit();
+ } catch(Throwable e) {
+ s_logger.error("Unexpected exception", e);
+ txn.rollback();
+ throw new ConcurrentOperationException("Unhandled exception, converted to ConcurrentOperationException");
+ }
+
+ final long jobId = workJob.getId();
+ AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+ //
+ // TODO : this will be replaced with fully-asynchronized way later so that we don't need
+ // to wait here. The reason we do it synchronized here is that callers of advanceStart is expecting
+ // synchronized semantics
- //
++ //
+ //
+ _jobMgr.waitAndCheck(
- new String[] { TopicConstants.VM_POWER_STATE, TopicConstants.JOB_STATE },
++ new String[] { TopicConstants.VM_POWER_STATE, TopicConstants.JOB_STATE },
+ 3000L, 600000L, new Predicate() {
+
+ @Override
+ public boolean checkCondition() {
+ VMInstanceVO instance = _vmDao.findById(vm.getId());
+ if(instance.getPowerState() == VirtualMachine.PowerState.PowerOff)
+ return true;
+
+ VmWorkJobVO workJob = _workJobDao.findById(jobId);
+ if(workJob.getStatus() != AsyncJobConstants.STATUS_IN_PROGRESS)
+ return true;
+
+ return false;
+ }
+ });
+
+ try {
+ AsyncJobExecutionContext.getCurrentExecutionContext().disjoinJob(jobId);
+ } catch(Exception e) {
+ s_logger.error("Unexpected exception", e);
+ return false;
+ }
+ return true;
+ }
@Override
- public <T extends VMInstanceVO> boolean advanceStop(T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
- State state = vm.getState();
- if (state == State.Stopped) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("VM is already stopped: " + vm);
- }
- return true;
- }
+ public <T extends VMInstanceVO> boolean processVmStopWork(T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
+ VmWorkJobVO work = _workJobDao.findById(AsyncJobExecutionContext.getCurrentExecutionContext().getJob().getId());
- if (state == State.Destroyed || state == State.Expunging || state == State.Error) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Stopped called on " + vm + " but the state is " + state);
- }
- return true;
- }
- // grab outstanding work item if any
- ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
- if (work != null) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Found an outstanding work item for this vm " + vm + " with state:" + vm.getState() + ", work id:" + work.getId());
- }
- }
Long hostId = vm.getHostId();
if (hostId == null) {
if (!forced) {
@@@ -1277,7 -1198,7 +1365,7 @@@
try {
if (vm.getHypervisorType() != HypervisorType.BareMetal) {
-- this.volumeMgr.release(profile);
++ volumeMgr.release(profile);
s_logger.debug("Successfully released storage resources for the vm " + vm);
}
} catch (Exception e) {
@@@ -1299,174 -1221,6 +1387,176 @@@
}
}
- /*
- @Override
- public <T extends VMInstanceVO> boolean advanceStop(T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
- State state = vm.getState();
- if (state == State.Stopped) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("VM is already stopped: " + vm);
++ /*
++ @Override
++ public <T extends VMInstanceVO> boolean advanceStop(T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
++ State state = vm.getState();
++ if (state == State.Stopped) {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("VM is already stopped: " + vm);
++ }
++ return true;
+ }
- return true;
- }
+
- if (state == State.Destroyed || state == State.Expunging || state == State.Error) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Stopped called on " + vm + " but the state is " + state);
- }
- return true;
- }
- // grab outstanding work item if any
- ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
- if (work != null) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Found an outstanding work item for this vm " + vm + " with state:" + vm.getState() + ", work id:" + work.getId());
- }
- }
- Long hostId = vm.getHostId();
- if (hostId == null) {
- if (!forced) {
++ if (state == State.Destroyed || state == State.Expunging || state == State.Error) {
+ if (s_logger.isDebugEnabled()) {
- s_logger.debug("HostId is null but this is not a forced stop, cannot stop vm " + vm + " with state:" + vm.getState());
++ s_logger.debug("Stopped called on " + vm + " but the state is " + state);
+ }
- return false;
- }
- try {
- stateTransitTo(vm, Event.AgentReportStopped, null, null);
- } catch (NoTransitionException e) {
- s_logger.warn(e.getMessage());
++ return true;
+ }
- // mark outstanding work item if any as done
++ // grab outstanding work item if any
++ VmWorkJobVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
+ if (work != null) {
+ if (s_logger.isDebugEnabled()) {
- s_logger.debug("Updating work item to Done, id:" + work.getId());
++ s_logger.debug("Found an outstanding work item for this vm " + vm + " with state:" + vm.getState() + ", work id:" + work.getId());
+ }
- work.setStep(Step.Done);
- _workDao.update(work.getId(), work);
- }
- return true;
- }
-
- VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
- VirtualMachineProfile<T> profile = new VirtualMachineProfileImpl<T>(vm);
-
- try {
- if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) {
- throw new ConcurrentOperationException("VM is being operated on.");
- }
- } catch (NoTransitionException e1) {
- if (!forced) {
- throw new CloudRuntimeException("We cannot stop " + vm + " when it is in state " + vm.getState());
- }
- boolean doCleanup = false;
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Unable to transition the state but we're moving on because it's forced stop");
+ }
- if (state == State.Starting || state == State.Migrating) {
++ Long hostId = vm.getHostId();
++ if (hostId == null) {
++ if (!forced) {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("HostId is null but this is not a forced stop, cannot stop vm " + vm + " with state:" + vm.getState());
++ }
++ return false;
++ }
++ try {
++ stateTransitTo(vm, Event.AgentReportStopped, null, null);
++ } catch (NoTransitionException e) {
++ s_logger.warn(e.getMessage());
++ }
++ // mark outstanding work item if any as done
+ if (work != null) {
- doCleanup = true;
- } else {
+ if (s_logger.isDebugEnabled()) {
- s_logger.debug("Unable to cleanup VM: " + vm + " ,since outstanding work item is not found");
++ s_logger.debug("Updating work item to Done, id:" + work.getId());
+ }
- throw new CloudRuntimeException("Work item not found, We cannot stop " + vm + " when it is in state " + vm.getState());
++ work.setStep(Step.Done);
++ _workDao.update(work.getId(), work);
+ }
- } else if (state == State.Stopping) {
- doCleanup = true;
++ return true;
+ }
+
- if (doCleanup) {
- if (cleanup(vmGuru, new VirtualMachineProfileImpl<T>(vm), work, Event.StopRequested, forced, user, account)) {
- try {
++ VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
++ VirtualMachineProfile<T> profile = new VirtualMachineProfileImpl<T>(vm);
++
++ try {
++ if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) {
++ throw new ConcurrentOperationException("VM is being operated on.");
++ }
++ } catch (NoTransitionException e1) {
++ if (!forced) {
++ throw new CloudRuntimeException("We cannot stop " + vm + " when it is in state " + vm.getState());
++ }
++ boolean doCleanup = false;
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("Unable to transition the state but we're moving on because it's forced stop");
++ }
++ if (state == State.Starting || state == State.Migrating) {
++ if (work != null) {
++ doCleanup = true;
++ } else {
+ if (s_logger.isDebugEnabled()) {
- s_logger.debug("Updating work item to Done, id:" + work.getId());
++ s_logger.debug("Unable to cleanup VM: " + vm + " ,since outstanding work item is not found");
+ }
- return changeState(vm, Event.AgentReportStopped, null, work, Step.Done);
- } catch (NoTransitionException e) {
- s_logger.warn("Unable to cleanup " + vm);
- return false;
++ throw new CloudRuntimeException("Work item not found, We cannot stop " + vm + " when it is in state " + vm.getState());
+ }
- } else {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Failed to cleanup VM: " + vm);
++ } else if (state == State.Stopping) {
++ doCleanup = true;
++ }
++
++ if (doCleanup) {
++ if (cleanup(vmGuru, new VirtualMachineProfileImpl<T>(vm), work, Event.StopRequested, forced, user, account)) {
++ try {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("Updating work item to Done, id:" + work.getId());
++ }
++ return changeState(vm, Event.AgentReportStopped, null, work, Step.Done);
++ } catch (NoTransitionException e) {
++ s_logger.warn("Unable to cleanup " + vm);
++ return false;
++ }
++ } else {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("Failed to cleanup VM: " + vm);
++ }
++ throw new CloudRuntimeException("Failed to cleanup " + vm + " , current state " + vm.getState());
+ }
- throw new CloudRuntimeException("Failed to cleanup " + vm + " , current state " + vm.getState());
+ }
+ }
- }
-
- if (vm.getState() != State.Stopping) {
- throw new CloudRuntimeException("We cannot proceed with stop VM " + vm + " since it is not in 'Stopping' state, current state: " + vm.getState());
- }
+
- vmGuru.prepareStop(profile);
-
- StopCommand stop = new StopCommand(vm);
- boolean stopped = false;
- StopAnswer answer = null;
- try {
- 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());
++ if (vm.getState() != State.Stopping) {
++ throw new CloudRuntimeException("We cannot proceed with stop VM " + vm + " since it is not in 'Stopping' state, current state: " + vm.getState());
+ }
- vmGuru.finalizeStop(profile, answer);
+
- } catch (AgentUnavailableException e) {
- } catch (OperationTimedoutException e) {
- } finally {
- if (!stopped) {
- if (!forced) {
- s_logger.warn("Unable to stop vm " + vm);
- try {
- stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
- } catch (NoTransitionException e) {
- s_logger.warn("Unable to transition the state " + vm);
++ vmGuru.prepareStop(profile);
++
++ StopCommand stop = new StopCommand(vm);
++ boolean stopped = false;
++ StopAnswer answer = null;
++ try {
++ 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());
++ }
++ vmGuru.finalizeStop(profile, answer);
++
++ } catch (AgentUnavailableException e) {
++ s_logger.warn("Unable to stop vm, agent unavailable: " + e.toString());
++ } catch (OperationTimedoutException e) {
++ s_logger.warn("Unable to stop vm, operation timed out: " + e.toString());
++ } finally {
++ if (!stopped) {
++ if (!forced) {
++ s_logger.warn("Unable to stop vm " + vm);
++ try {
++ stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
++ } catch (NoTransitionException e) {
++ s_logger.warn("Unable to transition the state " + vm);
++ }
++ return false;
++ } else {
++ s_logger.warn("Unable to actually stop " + vm + " but continue with release because it's a force stop");
++ vmGuru.finalizeStop(profile, answer);
+ }
- return false;
- } else {
- s_logger.warn("Unable to actually stop " + vm + " but continue with release because it's a force stop");
- vmGuru.finalizeStop(profile, answer);
+ }
+ }
- }
+
- if (s_logger.isDebugEnabled()) {
- s_logger.debug(vm + " is stopped on the host. Proceeding to release resource held.");
- }
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug(vm + " is stopped on the host. Proceeding to release resource held.");
++ }
+
- try {
- _networkMgr.release(profile, forced);
- s_logger.debug("Successfully released network resources for the vm " + vm);
- } catch (Exception e) {
- s_logger.warn("Unable to release some network resources.", e);
- }
-
- try {
- if (vm.getHypervisorType() != HypervisorType.BareMetal) {
- this.volumeMgr.release(profile);
- s_logger.debug("Successfully released storage resources for the vm " + vm);
++ try {
++ _networkMgr.release(profile, forced);
++ s_logger.debug("Successfully released network resources for the vm " + vm);
++ } catch (Exception e) {
++ s_logger.warn("Unable to release some network resources.", e);
+ }
- } catch (Exception e) {
- s_logger.warn("Unable to release storage resources.", e);
- }
+
- try {
- if (work != null) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Updating the outstanding work item to Done, id:" + work.getId());
++ try {
++ if (vm.getHypervisorType() != HypervisorType.BareMetal) {
++ this.volumeMgr.release(profile);
++ s_logger.debug("Successfully released storage resources for the vm " + vm);
+ }
- work.setStep(Step.Done);
- _workDao.update(work.getId(), work);
++ } catch (Exception e) {
++ s_logger.warn("Unable to release storage resources.", e);
+ }
+
- return stateTransitTo(vm, Event.OperationSucceeded, null, null);
- } catch (NoTransitionException e) {
- s_logger.warn(e.getMessage());
- return false;
++ try {
++ if (work != null) {
++ if (s_logger.isDebugEnabled()) {
++ s_logger.debug("Updating the outstanding work item to Done, id:" + work.getId());
++ }
++ work.setStep(Step.Done);
++ _workDao.update(work.getId(), work);
++ }
++
++ return stateTransitTo(vm, Event.OperationSucceeded, null);
++ } catch (NoTransitionException e) {
++ s_logger.warn(e.getMessage());
++ return false;
++ }
+ }
- }
- */
++ */
private void setStateMachine() {
_stateMachine = VirtualMachine.State.getStateMachine();
}
@@@ -1478,16 -1232,12 +1568,16 @@@
@Override
public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) throws NoTransitionException {
+
+/*
+ * TODO ???
- *
++ *
// 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;
}
- */
-
++*/
State oldState = vm.getState();
if (oldState == State.Starting) {
if (e == Event.OperationSucceeded) {
@@@ -1567,7 -1317,7 +1657,7 @@@
VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
boolean migrationResult = false;
try {
-- migrationResult = this.volumeMgr.storageMigration(profile, destPool);
++ migrationResult = volumeMgr.storageMigration(profile, destPool);
if (migrationResult) {
//if the vm is migrated to different pod in basic mode, need to reallocate ip
@@@ -1610,40 -1360,267 +1700,271 @@@
@Override
public <T extends VMInstanceVO> T migrate(T vm, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
- VirtualMachineMigrationException {
+ VirtualMachineMigrationException {
s_logger.info("Migrating " + vm + " to " + dest);
+
+ return vm;
+
- /*
- long dstHostId = dest.getHost().getId();
- Host fromHost = _hostDao.findById(srcHostId);
- if (fromHost == null) {
- s_logger.info("Unable to find the host to migrate from: " + srcHostId);
- throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId);
++ /*
++ long dstHostId = dest.getHost().getId();
++ Host fromHost = _hostDao.findById(srcHostId);
++ if (fromHost == null) {
++ s_logger.info("Unable to find the host to migrate from: " + srcHostId);
++ throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId);
++ }
+
- long dstHostId = dest.getHost().getId();
- Host fromHost = _hostDao.findById(srcHostId);
- if (fromHost == null) {
- s_logger.info("Unable to find the host to migrate from: " + srcHostId);
- throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId);
- }
++ if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) {
++ s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
++ throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
++ }
+
- if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) {
- s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
- throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
- }
++ VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
+
- VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
++ long vmId = vm.getId();
++ vm = vmGuru.findById(vmId);
++ 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);
++ }
+
- long vmId = vm.getId();
- vm = vmGuru.findById(vmId);
- 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);
- }
-
- 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());
- }
++ 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());
++ }
+
- short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
- if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
- alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE;
- } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
- alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE;
- }
++ short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
++ if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
++ alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE;
++ } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
++ alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE;
++ }
+
- VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
- _networkMgr.prepareNicForMigration(profile, dest);
- this.volumeMgr.prepareForMigration(profile, dest);
++ VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
++ _networkMgr.prepareNicForMigration(profile, dest);
++ this.volumeMgr.prepareForMigration(profile, dest);
+
- VirtualMachineTO to = toVmTO(profile);
- PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
++ VirtualMachineTO to = toVmTO(profile);
++ PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
+
- ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
- work.setStep(Step.Prepare);
- work.setResourceType(ItWorkVO.ResourceType.Host);
- work.setResourceId(dstHostId);
- work = _workDao.persist(work);
++ VmWorkJobVO work = new VmWorkJobVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
++ work.setStep(Step.Prepare);
++ work.setResourceType(VmWorkJobVO.ResourceType.Host);
++ work.setResourceId(dstHostId);
++ work = _workDao.persist(work);
+
- PrepareForMigrationAnswer pfma = null;
- try {
- pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
- if (!pfma.getResult()) {
- String msg = "Unable to prepare for migration due to " + pfma.getDetails();
- pfma = null;
- throw new AgentUnavailableException(msg, dstHostId);
- }
- } catch (OperationTimedoutException e1) {
- throw new AgentUnavailableException("Operation timed out", dstHostId);
- } finally {
- if (pfma == null) {
- work.setStep(Step.Done);
- _workDao.update(work.getId(), work);
- }
- }
++ PrepareForMigrationAnswer pfma = null;
++ try {
++ pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
++ if (!pfma.getResult()) {
++ String msg = "Unable to prepare for migration due to " + pfma.getDetails();
++ pfma = null;
++ throw new AgentUnavailableException(msg, dstHostId);
++ }
++ } catch (OperationTimedoutException e1) {
++ throw new AgentUnavailableException("Operation timed out", dstHostId);
++ } finally {
++ if (pfma == null) {
++ work.setStep(Step.Done);
++ _workDao.update(work.getId(), work);
++ }
++ }
+
- vm.setLastHostId(srcHostId);
- try {
- if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) {
- s_logger.info("Migration cancelled because state has changed: " + vm);
- throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
- }
- } catch (NoTransitionException e1) {
- s_logger.info("Migration cancelled because " + e1.getMessage());
- throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
- }
++ vm.setLastHostId(srcHostId);
++ try {
++ if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) {
++ s_logger.info("Migration cancelled because state has changed: " + vm);
++ throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
++ }
++ } catch (NoTransitionException e1) {
++ s_logger.info("Migration cancelled because " + e1.getMessage());
++ throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
++ }
+
- boolean migrated = false;
- try {
- boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
- MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows);
- mc.setHostGuid(dest.getHost().getGuid());
++ boolean migrated = false;
++ try {
++ boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
++ MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows);
++ mc.setHostGuid(dest.getHost().getGuid());
+
- try {
- MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
- if (!ma.getResult()) {
- s_logger.error("Unable to migrate due to " + ma.getDetails());
- return null;
- }
- } catch (OperationTimedoutException e) {
- if (e.isActive()) {
- s_logger.warn("Active migration command so scheduling a restart for " + vm);
- _haMgr.scheduleRestart(vm, true);
- }
- throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId);
- }
++ try {
++ MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
++ if (!ma.getResult()) {
++ s_logger.error("Unable to migrate due to " + ma.getDetails());
++ return null;
++ }
++ } catch (OperationTimedoutException e) {
++ if (e.isActive()) {
++ s_logger.warn("Active migration command so scheduling a restart for " + vm);
++ _haMgr.scheduleRestart(vm, true);
++ }
++ throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId);
++ }
+
- try {
- if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
- throw new ConcurrentOperationException("Unable to change the state for " + vm);
- }
- } catch (NoTransitionException e1) {
- throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
- }
++ try {
++ if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
++ throw new ConcurrentOperationException("Unable to change the state for " + vm);
++ }
++ } catch (NoTransitionException e1) {
++ throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
++ }
+
- try {
- if (!checkVmOnHost(vm, dstHostId)) {
- s_logger.error("Unable to complete migration for " + vm);
+ try {
- _agentMgr.send(srcHostId, new Commands(cleanup(vm)), null);
- } catch (AgentUnavailableException e) {
- s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
++ if (!checkVmOnHost(vm, dstHostId)) {
++ s_logger.error("Unable to complete migration for " + vm);
++ try {
++ _agentMgr.send(srcHostId, new Commands(cleanup(vm)), null);
++ } catch (AgentUnavailableException e) {
++ s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
++ }
++ cleanup(vmGuru, new VirtualMachineProfileImpl<T>(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
++ return null;
++ }
++ } catch (OperationTimedoutException e) {
+ }
- cleanup(vmGuru, new VirtualMachineProfileImpl<T>(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
- return null;
- }
- } catch (OperationTimedoutException e) {
- }
+
- migrated = true;
- return vm;
- } finally {
- if (!migrated) {
- s_logger.info("Migration was unsuccessful. Cleaning up: " + vm);
++ migrated = true;
++ return vm;
++ } 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 "
- + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed. Please check logs.");
- try {
- _agentMgr.send(dstHostId, new Commands(cleanup(vm)), null);
- } catch (AgentUnavailableException ae) {
- s_logger.info("Looks like the destination Host is unavailable for cleanup");
- }
++ _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);
++ } catch (AgentUnavailableException ae) {
++ s_logger.info("Looks like the destination Host is unavailable for cleanup");
++ }
+
- try {
- stateTransitTo(vm, Event.OperationFailed, srcHostId);
- } catch (NoTransitionException e) {
- s_logger.warn(e.getMessage());
- }
- }
++ try {
++ stateTransitTo(vm, Event.OperationFailed, srcHostId);
++ } catch (NoTransitionException e) {
++ s_logger.warn(e.getMessage());
++ }
++ }
+
- work.setStep(Step.Done);
- _workDao.update(work.getId(), work);
- }
++ work.setStep(Step.Done);
++ _workDao.update(work.getId(), work);
++ }
++ */
+ }
+
+ private Map<VolumeVO, StoragePoolVO> getPoolListForVolumesForMigration(VirtualMachineProfile<VMInstanceVO> profile,
+ Host host, Map<VolumeVO, StoragePoolVO> volumeToPool) {
+ List<VolumeVO> allVolumes = _volsDao.findUsableVolumesForInstance(profile.getId());
+ for (VolumeVO volume : allVolumes) {
+ StoragePoolVO pool = volumeToPool.get(volume);
+ DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
+ StoragePoolVO currentPool = _storagePoolDao.findById(volume.getPoolId());
+ if (pool != null) {
+ // Check if pool is accessible from the destination host and disk offering with which the volume was
+ // created is compliant with the pool type.
+ if (_poolHostDao.findByPoolHost(pool.getId(), host.getId()) == null ||
+ pool.isLocal() != diskOffering.getUseLocalStorage()) {
+ // Cannot find a pool for the volume. Throw an exception.
+ throw new CloudRuntimeException("Cannot migrate volume " + volume + " to storage pool " + pool +
+ " 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()){
+ // 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);
+ }
+ } else {
+ // Find a suitable pool for the volume. Call the storage pool allocator to find the list of pools.
+ DiskProfile diskProfile = new DiskProfile(volume, diskOffering, profile.getHypervisorType());
+ DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(),
+ host.getClusterId(), host.getId(), null, null);
+ ExcludeList avoid = new ExcludeList();
+ boolean currentPoolAvailable = false;
+
+ for (StoragePoolAllocator allocator : _storagePoolAllocators) {
+ List<StoragePool> poolList = allocator.allocateToPool(diskProfile, profile, plan, avoid,
+ StoragePoolAllocator.RETURN_UPTO_ALL);
+ if (poolList != null && !poolList.isEmpty()) {
+ // Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the
+ // volume to a pool only if it is required; that is the current pool on which the volume resides
+ // is not available on the destination host.
+ if (poolList.contains(currentPool)) {
+ currentPoolAvailable = true;
+ } else {
+ volumeToPool.put(volume, _storagePoolDao.findByUuid(poolList.get(0).getUuid()));
+ }
+
+ break;
+ }
+ }
+
+ if (!currentPoolAvailable && !volumeToPool.containsKey(volume)) {
+ // Cannot find a pool for the volume. Throw an exception.
+ throw new CloudRuntimeException("Cannot find a storage pool which is available for volume " +
+ volume + " while migrating virtual machine " + profile.getVirtualMachine() + " to host " +
+ host);
+ }
+ }
+ }
+
+ return volumeToPool;
+ }
+
- private <T extends VMInstanceVO> void moveVmToMigratingState(T vm, Long hostId, ItWorkVO work)
++ private <T extends VMInstanceVO> void moveVmToMigratingState(T vm, Long hostId, VmWorkJobVO work)
+ throws ConcurrentOperationException {
+ // Put the vm in migrating state.
+ try {
+ if (!changeState(vm, Event.MigrationRequested, hostId, work, Step.Migrating)) {
+ s_logger.info("Migration cancelled because state has changed: " + vm);
+ throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
+ }
+ } catch (NoTransitionException e) {
+ s_logger.info("Migration cancelled because " + e.getMessage());
+ throw new ConcurrentOperationException("Migration cancelled because " + e.getMessage());
}
+ }
- if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) {
- s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
- throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
- private <T extends VMInstanceVO> void moveVmOutofMigratingStateOnSuccess(T vm, Long hostId, ItWorkVO work)
++ private <T extends VMInstanceVO> void moveVmOutofMigratingStateOnSuccess(T vm, Long hostId, VmWorkJobVO work)
+ throws ConcurrentOperationException {
+ // Put the vm in running state.
+ try {
+ if (!changeState(vm, Event.OperationSucceeded, hostId, work, Step.Started)) {
+ s_logger.error("Unable to change the state for " + vm);
+ throw new ConcurrentOperationException("Unable to change the state for " + vm);
+ }
+ } catch (NoTransitionException e) {
+ s_logger.error("Unable to change state due to " + e.getMessage());
+ throw new ConcurrentOperationException("Unable to change state due to " + e.getMessage());
}
+ }
+
+ @Override
+ public <T extends VMInstanceVO> T migrateWithStorage(T vm, long srcHostId, long destHostId,
+ Map<VolumeVO, StoragePoolVO> volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException,
+ ManagementServerException, VirtualMachineMigrationException {
+ HostVO srcHost = _hostDao.findById(srcHostId);
+ HostVO destHost = _hostDao.findById(destHostId);
VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
+ DataCenterVO dc = _dcDao.findById(destHost.getDataCenterId());
+ HostPodVO pod = _podDao.findById(destHost.getPodId());
+ Cluster cluster = _clusterDao.findById(destHost.getClusterId());
+ DeployDestination destination = new DeployDestination(dc, pod, cluster, destHost);
+
+ // Create a map of which volume should go in which storage pool.
long vmId = vm.getId();
vm = vmGuru.findById(vmId);
- 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);
- }
+ VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
+ volumeToPool = getPoolListForVolumesForMigration(profile, destHost, volumeToPool);
- 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());
+ // If none of the volumes have to be migrated, fail the call. Administrator needs to make a call for migrating
+ // a vm and not migrating a vm with storage.
+ if (volumeToPool.isEmpty()) {
+ throw new InvalidParameterValueException("Migration of the vm " + vm + "from host " + srcHost +
+ " to destination host " + destHost + " doesn't involve migrating the volumes.");
}
short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
@@@ -1653,80 -1630,34 +1974,35 @@@
alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE;
}
- VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
- _networkMgr.prepareNicForMigration(profile, dest);
- this.volumeMgr.prepareForMigration(profile, dest);
-
- VirtualMachineTO to = toVmTO(profile);
- PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
+ _networkMgr.prepareNicForMigration(profile, destination);
- this.volumeMgr.prepareForMigration(profile, destination);
++ volumeMgr.prepareForMigration(profile, destination);
+ HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
+ VirtualMachineTO to = hvGuru.implement(profile);
-- ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
-- work.setStep(Step.Prepare);
-- work.setResourceType(ItWorkVO.ResourceType.Host);
- work.setResourceId(dstHostId);
- work = _workDao.persist(work);
-
- PrepareForMigrationAnswer pfma = null;
- try {
- pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
- if (!pfma.getResult()) {
- String msg = "Unable to prepare for migration due to " + pfma.getDetails();
- pfma = null;
- throw new AgentUnavailableException(msg, dstHostId);
- }
- } catch (OperationTimedoutException e1) {
- throw new AgentUnavailableException("Operation timed out", dstHostId);
- } finally {
- if (pfma == null) {
- work.setStep(Step.Done);
- _workDao.update(work.getId(), work);
- }
- }
- work.setResourceId(destHostId);
- work = _workDao.persist(work);
++ VmWorkJobVO work = new VmWorkJobVO();
++// VmWorkJobVO work = new VmWorkJobVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
++// work.setStep(Step.Prepare);
++// work.setResourceType(ItWorkVO.ResourceType.Host);
++// work.setResourceId(destHostId);
++// work = _workDao.persist(work);
+ // Put the vm in migrating state.
vm.setLastHostId(srcHostId);
- try {
- if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) {
- s_logger.info("Migration cancelled because state has changed: " + vm);
- throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
- }
- } catch (NoTransitionException e1) {
- s_logger.info("Migration cancelled because " + e1.getMessage());
- throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
- }
+ moveVmToMigratingState(vm, destHostId, work);
boolean migrated = false;
try {
- boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
- MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows);
- mc.setHostGuid(dest.getHost().getGuid());
+ // Migrate the vm and its volume.
- this.volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool);
++ volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool);
- try {
- MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
- if (!ma.getResult()) {
- s_logger.error("Unable to migrate due to " + ma.getDetails());
- return null;
- }
- } catch (OperationTimedoutException e) {
- if (e.isActive()) {
- s_logger.warn("Active migration command so scheduling a restart for " + vm);
- _haMgr.scheduleRestart(vm, true);
- }
- throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId);
- }
+ // Put the vm back to running state.
+ moveVmOutofMigratingStateOnSuccess(vm, destHost.getId(), work);
try {
- if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
- throw new ConcurrentOperationException("Unable to change the state for " + vm);
- }
- } catch (NoTransitionException e1) {
- throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
- }
-
- try {
- if (!checkVmOnHost(vm, dstHostId)) {
- s_logger.error("Unable to complete migration for " + vm);
+ if (!checkVmOnHost(vm, destHostId)) {
+ s_logger.error("Vm not found on destination host. Unable to complete migration for " + vm);
try {
- _agentMgr.send(srcHostId, new Commands(cleanup(vm)), null);
+ _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null);
} catch (AgentUnavailableException e) {
s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
}
@@@ -1758,9 -1688,8 +2033,8 @@@
}
work.setStep(Step.Done);
-- _workDao.update(work.getId(), work);
++ // FIXME _workDao.update(work.getId(), work);
}
- */
}
@Override
@@@ -1768,47 -1697,45 +2042,47 @@@
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(profile.getVirtualMachine().getHypervisorType());
VirtualMachineTO to = hvGuru.implement(profile);
return to;
- }
+ }
protected void cancelWorkItems(long nodeId) {
- /*
-- GlobalLock scanLock = GlobalLock.getInternLock("vmmgr.cancel.workitem");
++ /*
++ GlobalLock scanLock = GlobalLock.getInternLock("vmmgr.cancel.workitem");
-- try {
-- if (scanLock.lock(3)) {
try {
-- List<ItWorkVO> works = _workDao.listWorkInProgressFor(nodeId);
-- for (ItWorkVO work : works) {
-- s_logger.info("Handling unfinished work item: " + work);
++ if (scanLock.lock(3)) {
try {
-- VMInstanceVO vm = _vmDao.findById(work.getInstanceId());
-- if (vm != null) {
-- if (work.getType() == State.Starting) {
-- _haMgr.scheduleRestart(vm, true);
-- work.setManagementServerId(_nodeId);
-- _workDao.update(work.getId(), work);
-- } else if (work.getType() == State.Stopping) {
-- _haMgr.scheduleStop(vm, vm.getHostId(), WorkType.CheckStop);
-- work.setManagementServerId(_nodeId);
-- _workDao.update(work.getId(), work);
-- } else if (work.getType() == State.Migrating) {
-- _haMgr.scheduleMigration(vm);
-- work.setStep(Step.Done);
-- _workDao.update(work.getId(), work);
++ List<VmWorkJobVO> works = _workDao.listWorkInProgressFor(nodeId);
++ for (VmWorkJobVO work : works) {
++ s_logger.info("Handling unfinished work item: " + work);
++ try {
++ VMInstanceVO vm = _vmDao.findById(work.getInstanceId());
++ if (vm != null) {
++ if (work.getType() == State.Starting) {
++ _haMgr.scheduleRestart(vm, true);
++ work.setManagementServerId(_nodeId);
++ _workDao.update(work.getId(), work);
++ } else if (work.getType() == State.Stopping) {
++ _haMgr.scheduleStop(vm, vm.getHostId(), WorkType.CheckStop);
++ work.setManagementServerId(_nodeId);
++ _workDao.update(work.getId(), work);
++ } else if (work.getType() == State.Migrating) {
++ _haMgr.scheduleMigration(vm);
++ work.setStep(Step.Done);
++ _workDao.update(work.getId(), work);
++ }
++ }
++ } catch (Exception e) {
++ s_logger.error("Error while handling " + work, e);
}
}
-- } catch (Exception e) {
-- s_logger.error("Error while handling " + work, e);
++ } finally {
++ scanLock.unlock();
}
}
} finally {
-- scanLock.unlock();
++ scanLock.releaseRef();
}
-- }
-- } finally {
-- scanLock.releaseRef();
-- }
- */
++ */
}
@Override
@@@ -1836,25 -1763,23 +2110,23 @@@
DeployDestination dest = null;
while (true) {
- for (DeploymentPlanner planner : _planners) {
- if (planner.canHandle(profile, plan, excludes)) {
- dest = planner.plan(profile, plan, excludes);
- } else {
- continue;
+
+ try {
+ dest = _dpMgr.planDeployment(profile, plan, excludes);
+ } catch (AffinityConflictException e2) {
+ s_logger.warn("Unable to create deployment, affinity rules associted to the VM conflict", e2);
+ throw new CloudRuntimeException(
+ "Unable to create deployment, affinity rules associted to the VM conflict");
- }
+ }
- if (dest != null) {
- if (s_logger.isDebugEnabled()) {
+ if (dest != null) {
+ if (s_logger.isDebugEnabled()) {
- s_logger.debug("Planner " + planner + " found " + dest + " for migrating to.");
- }
- break;
+ s_logger.debug("Found destination " + dest + " for migrating to.");
}
+ } else {
if (s_logger.isDebugEnabled()) {
- s_logger.debug("Planner " + planner + " was unable to find anything.");
+ s_logger.debug("Unable to find destination for migrating the vm " + profile);
}
- }
-
- if (dest == null) {
throw new InsufficientServerCapacityException("Unable to find a server to migrate to.", host.getClusterId());
}
@@@ -1899,21 -1823,11 +2171,21 @@@
@Override
public void run() {
s_logger.trace("VM Operation Thread Running");
+
+ try {
+ Date cutDate = DateUtil.currentGMTTime();
+ cutDate = new Date(cutDate.getTime() - 60000);
+ _workJobDao.expungeCompletedWorkJobs(cutDate);
+ } catch(Throwable e) {
+ s_logger.error("Unexpected exception", e);
+ }
- /*
++/*
try {
_workDao.cleanup(_cleanupWait);
} catch (Exception e) {
s_logger.error("VM Operations failed due to ", e);
}
- */
++*/
}
}
@@@ -1987,8 -1901,8 +2259,8 @@@
public Command cleanup(String vmName) {
return new StopCommand(vmName);
}
-
+/*
- public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) {
+ public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) {
Commands commands = new Commands(OnError.Continue);
Map<Long, AgentVmInfo> infos = convertToInfos(startup);
@@@ -2112,132 -2029,138 +2384,132 @@@
}
}
}
-
+*/
public void fullSync(final long clusterId, Map<String, Pair<String, State>> newStates) {
- /*
-- 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());
-- VMInstanceVO castedVm = null;
-
- // sync VM Snapshots related transient states
- List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Cre
<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d4039743/server/test/com/cloud/vm/MockUserVmManagerImpl.java
----------------------------------------------------------------------