mirror of https://github.com/apache/cloudstack.git
VirtualMachineManager.migrateAway() need to put under management of new sync model
This commit is contained in:
parent
434f8dab72
commit
fa7d9ad1a8
|
|
@ -109,7 +109,7 @@ public interface VirtualMachineManager extends Manager {
|
|||
|
||||
void destroy(String vmUuid) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException;
|
||||
|
||||
void migrateAway(String vmUuid, long hostId, DeploymentPlanner planner) throws InsufficientServerCapacityException;
|
||||
void migrateAway(String vmUuid, long hostId) throws InsufficientServerCapacityException;
|
||||
|
||||
void migrate(String vmUuid, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package com.cloud.ha;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.utils.component.Manager;
|
||||
|
|
@ -103,4 +104,6 @@ public interface HighAvailabilityManager extends Manager {
|
|||
* @return
|
||||
*/
|
||||
String getHaTag();
|
||||
|
||||
DeploymentPlanner getHAPlanner();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1546,7 +1546,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
|
||||
// Disable this hacking thing, VM snapshot task need to be managed by its orchestartion flow istelf instead of
|
||||
// hacking it here at general VM manager
|
||||
/*
|
||||
/*
|
||||
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;
|
||||
|
|
@ -2183,7 +2183,53 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
}
|
||||
|
||||
@Override
|
||||
public void migrateAway(String vmUuid, long srcHostId, DeploymentPlanner planner) throws InsufficientServerCapacityException {
|
||||
public void migrateAway(String vmUuid, long srcHostId) throws InsufficientServerCapacityException {
|
||||
AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
|
||||
if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
|
||||
// avoid re-entrance
|
||||
|
||||
VmWorkJobVO placeHolder = null;
|
||||
if (VmJobEnabled.value()) {
|
||||
VirtualMachine vm = _vmDao.findByUuid(vmUuid);
|
||||
placeHolder = createPlaceHolderWork(vm.getId());
|
||||
}
|
||||
try {
|
||||
try {
|
||||
orchestrateMigrateAway(vmUuid, srcHostId, null);
|
||||
} catch (InsufficientServerCapacityException e) {
|
||||
s_logger.warn("Failed to deploy vm " + vmUuid + " with original planner, sending HAPlanner");
|
||||
orchestrateMigrateAway(vmUuid, srcHostId, _haMgr.getHAPlanner());
|
||||
}
|
||||
} finally {
|
||||
if (VmJobEnabled.value())
|
||||
_workJobDao.expunge(placeHolder.getId());
|
||||
}
|
||||
} else {
|
||||
Outcome<VirtualMachine> outcome = migrateVmAwayThroughJobQueue(vmUuid, srcHostId);
|
||||
|
||||
try {
|
||||
VirtualMachine vm = outcome.get();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Operation is interrupted", e);
|
||||
} catch (java.util.concurrent.ExecutionException e) {
|
||||
throw new RuntimeException("Execution excetion", e);
|
||||
}
|
||||
|
||||
Object jobException = _jobMgr.unmarshallResultObject(outcome.getJob());
|
||||
if (jobException != null) {
|
||||
if (jobException instanceof InsufficientServerCapacityException)
|
||||
throw (InsufficientServerCapacityException)jobException;
|
||||
else if (jobException instanceof ConcurrentOperationException)
|
||||
throw (ConcurrentOperationException)jobException;
|
||||
else if (jobException instanceof RuntimeException)
|
||||
throw (RuntimeException)jobException;
|
||||
else if (jobException instanceof Throwable)
|
||||
throw new RuntimeException("Unexpected exception", (Throwable)jobException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void orchestrateMigrateAway(String vmUuid, long srcHostId, DeploymentPlanner planner) throws InsufficientServerCapacityException {
|
||||
VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
|
||||
if (vm == null) {
|
||||
s_logger.debug("Unable to find a VM for " + vmUuid);
|
||||
|
|
@ -4562,6 +4608,57 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
VirtualMachine.PowerState.PowerOn, vm.getId(), vm.getPowerHostId());
|
||||
}
|
||||
|
||||
public Outcome<VirtualMachine> migrateVmAwayThroughJobQueue(final String vmUuid, final long srcHostId) {
|
||||
final CallContext context = CallContext.current();
|
||||
final User user = context.getCallingUser();
|
||||
final Account account = context.getCallingAccount();
|
||||
|
||||
final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
|
||||
|
||||
Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
|
||||
@Override
|
||||
public Object[] doInTransaction(TransactionStatus status) {
|
||||
|
||||
_vmDao.lockRow(vm.getId(), true);
|
||||
|
||||
List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
|
||||
VirtualMachine.Type.Instance, vm.getId(),
|
||||
VmWorkMigrateAway.class.getName());
|
||||
|
||||
VmWorkJobVO workJob = null;
|
||||
if (pendingWorkJobs != null && pendingWorkJobs.size() > 0) {
|
||||
assert (pendingWorkJobs.size() == 1);
|
||||
workJob = pendingWorkJobs.get(0);
|
||||
} else {
|
||||
|
||||
workJob = new VmWorkJobVO(context.getContextId());
|
||||
|
||||
workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
|
||||
workJob.setCmd(VmWorkMigrateAway.class.getName());
|
||||
|
||||
workJob.setAccountId(account.getId());
|
||||
workJob.setUserId(user.getId());
|
||||
workJob.setVmType(VirtualMachine.Type.Instance);
|
||||
workJob.setVmInstanceId(vm.getId());
|
||||
workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
|
||||
|
||||
// save work context info (there are some duplications)
|
||||
VmWorkMigrateAway workInfo = new VmWorkMigrateAway(user.getId(), account.getId(), vm.getId(), VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, srcHostId);
|
||||
workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
|
||||
|
||||
_jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
|
||||
}
|
||||
return new Object[] {workJob, new Long(workJob.getId())};
|
||||
}
|
||||
});
|
||||
|
||||
final long jobId = (Long)result[1];
|
||||
AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
|
||||
|
||||
return new VmStateSyncOutcome((VmWorkJobVO)result[0],
|
||||
VirtualMachine.PowerState.PowerOn, vm.getId(), vm.getPowerHostId());
|
||||
}
|
||||
|
||||
public Outcome<VirtualMachine> migrateVmWithStorageThroughJobQueue(
|
||||
final String vmUuid, final long srcHostId, final long destHostId,
|
||||
final Map<Volume, StoragePool> volumeToPool) {
|
||||
|
|
@ -4964,6 +5061,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
|
||||
}
|
||||
|
||||
private Pair<JobInfo.Status, String> orchestrateMigrateAway(VmWorkMigrateAway work) throws Exception {
|
||||
VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
|
||||
if (vm == null) {
|
||||
s_logger.info("Unable to find vm " + work.getVmId());
|
||||
}
|
||||
assert (vm != null);
|
||||
|
||||
try {
|
||||
orchestrateMigrateAway(vm.getUuid(), work.getSrcHostId(), null);
|
||||
} catch (InsufficientServerCapacityException e) {
|
||||
s_logger.warn("Failed to deploy vm " + vm.getId() + " with original planner, sending HAPlanner");
|
||||
orchestrateMigrateAway(vm.getUuid(), work.getSrcHostId(), _haMgr.getHAPlanner());
|
||||
}
|
||||
|
||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
|
||||
}
|
||||
|
||||
private Pair<JobInfo.Status, String> orchestrateMigrateWithStorage(VmWorkMigrateWithStorage work) throws Exception {
|
||||
VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
|
||||
if (vm == null) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
// 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.vm;
|
||||
|
||||
public class VmWorkMigrateAway extends VmWork {
|
||||
|
||||
private static final long serialVersionUID = -5917512239025814373L;
|
||||
|
||||
private long srcHostId;
|
||||
|
||||
public VmWorkMigrateAway(long userId, long accountId, long vmId, String handlerName,
|
||||
long srcHostId) {
|
||||
super(userId, accountId, vmId, handlerName);
|
||||
|
||||
this.srcHostId = srcHostId;
|
||||
}
|
||||
|
||||
public long getSrcHostId() {
|
||||
return srcHostId;
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,6 @@ import javax.naming.ConfigurationException;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.NDC;
|
||||
|
||||
import com.cloud.deploy.HAPlanner;
|
||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.managed.context.ManagedContext;
|
||||
|
|
@ -48,6 +47,8 @@ import com.cloud.dc.DataCenterVO;
|
|||
import com.cloud.dc.HostPodVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.deploy.HAPlanner;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
|
|
@ -148,7 +149,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai
|
|||
}
|
||||
|
||||
public void setHaPlanners(List<HAPlanner> haPlanners) {
|
||||
this._haPlanners = haPlanners;
|
||||
_haPlanners = haPlanners;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -611,13 +612,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai
|
|||
|
||||
VMInstanceVO vm = _instanceDao.findById(vmId);
|
||||
// First try starting the vm with its original planner, if it doesn't succeed send HAPlanner as its an emergency.
|
||||
boolean result = false;
|
||||
try {
|
||||
_itMgr.migrateAway(vm.getUuid(), srcHostId, null);
|
||||
}catch (InsufficientServerCapacityException e) {
|
||||
s_logger.warn("Failed to deploy vm " + vmId + " with original planner, sending HAPlanner");
|
||||
_itMgr.migrateAway(vm.getUuid(), srcHostId, _haPlanners.get(0));
|
||||
}
|
||||
_itMgr.migrateAway(vm.getUuid(), srcHostId);
|
||||
return null;
|
||||
} catch (InsufficientServerCapacityException e) {
|
||||
s_logger.warn("Insufficient capacity for migrating a VM.");
|
||||
|
|
@ -935,4 +930,8 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai
|
|||
return _haTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeploymentPlanner getHAPlanner() {
|
||||
return _haPlanners.get(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue