mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
bug 12148: add checkpoint for storage migration
status 12148: resolved fixed
This commit is contained in:
parent
1a3a3f8e0d
commit
1d352f1e2c
@ -2340,13 +2340,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attach each data volume to the VM, if there is a deferred attached disk
|
||||
for (DiskDef disk : vm.getDevices().getDisks()) {
|
||||
if (disk.isAttachDeferred()) {
|
||||
attachOrDetachDevice(conn, true, vmName, disk.toString());
|
||||
}
|
||||
}
|
||||
|
||||
state = State.Running;
|
||||
return new StartAnswer(cmd);
|
||||
@ -2416,18 +2409,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
if (pool.getType() == StoragePoolType.CLVM) {
|
||||
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusType);
|
||||
} else {
|
||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.diskFmtType.QCOW2);
|
||||
if (volume.getType() == Volume.Type.DATADISK) {
|
||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2);
|
||||
} else {
|
||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.diskFmtType.QCOW2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Centos doesn't support scsi hotplug. For other host OSes, we attach the disk after the vm is running, so that we can hotplug it.
|
||||
if (volume.getType() == Volume.Type.DATADISK && diskBusType != DiskDef.diskBus.VIRTIO) {
|
||||
disk.setAttachDeferred(true);
|
||||
}
|
||||
|
||||
if (!disk.isAttachDeferred()) {
|
||||
vm.getDevices().addDevice(disk);
|
||||
}
|
||||
vm.getDevices().addDevice(disk);
|
||||
|
||||
}
|
||||
|
||||
if (vmSpec.getType() != VirtualMachine.Type.User) {
|
||||
|
||||
@ -206,14 +206,16 @@ public class CheckPointManagerImpl implements CheckPointManager, Manager, Cluste
|
||||
}
|
||||
|
||||
class CleanupTask implements Runnable {
|
||||
|
||||
public CleanupTask() {
|
||||
private Date _curDate;
|
||||
public CleanupTask() {
|
||||
_curDate = new Date();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
List<CheckPointVO> tasks = _maidDao.listCleanupTasks(_msId);
|
||||
try {
|
||||
List<CheckPointVO> tasks = _maidDao.listLeftoversByCutTime(_curDate, _msId);
|
||||
tasks.addAll(_maidDao.listCleanupTasks(_msId));
|
||||
|
||||
List<CheckPointVO> retries = new ArrayList<CheckPointVO>();
|
||||
|
||||
|
||||
@ -44,5 +44,6 @@ public interface StackMaidDao extends GenericDao<CheckPointVO, Long> {
|
||||
*/
|
||||
boolean takeover(long takeOverMsid, long selfId);
|
||||
|
||||
List<CheckPointVO> listCleanupTasks(long selfId);
|
||||
List<CheckPointVO> listCleanupTasks(long selfId);
|
||||
List<CheckPointVO> listLeftoversByCutTime(Date cutTime, long msid);
|
||||
}
|
||||
|
||||
@ -174,6 +174,35 @@ public class StackMaidDaoImpl extends GenericDaoBase<CheckPointVO, Long> impleme
|
||||
txn.close();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public List<CheckPointVO> listLeftoversByCutTime(Date cutTime, long msid) {
|
||||
|
||||
List<CheckPointVO> l = new ArrayList<CheckPointVO>();
|
||||
String sql = "select * from stack_maid where created < ? and msid = ? order by msid asc, thread_id asc, seq desc";
|
||||
|
||||
Transaction txn = Transaction.open(Transaction.CLOUD_DB);
|
||||
PreparedStatement pstmt = null;
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
String gmtCutTime = DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutTime);
|
||||
pstmt.setString(1, gmtCutTime);
|
||||
pstmt.setLong(2, msid);
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while(rs.next()) {
|
||||
l.add(toEntityBean(rs, false));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
s_logger.error("unexcpected exception " + e.getMessage(), e);
|
||||
} catch (Throwable e) {
|
||||
s_logger.error("unexcpected exception " + e.getMessage(), e);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -75,6 +75,7 @@ import com.cloud.async.AsyncJobManager;
|
||||
import com.cloud.capacity.Capacity;
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.capacity.dao.CapacityDao;
|
||||
import com.cloud.cluster.CheckPointManager;
|
||||
import com.cloud.cluster.ClusterManagerListener;
|
||||
import com.cloud.cluster.ManagementServerHostVO;
|
||||
import com.cloud.configuration.Config;
|
||||
@ -299,6 +300,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
protected SecondaryStorageVmManager _ssvmMgr;
|
||||
@Inject
|
||||
protected ResourceManager _resourceMgr;
|
||||
@Inject
|
||||
protected CheckPointManager _checkPointMgr;
|
||||
|
||||
@Inject(adapter = StoragePoolAllocator.class)
|
||||
protected Adapters<StoragePoolAllocator> _storagePoolAllocators;
|
||||
@ -2636,7 +2639,9 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
txn.start();
|
||||
|
||||
boolean transitResult = false;
|
||||
long checkPointTaskId = -1;
|
||||
try {
|
||||
List<Long> volIds = new ArrayList<Long>();
|
||||
for (Volume volume : volumes) {
|
||||
if (!_snapshotMgr.canOperateOnVolume((VolumeVO)volume)) {
|
||||
throw new CloudRuntimeException("There are snapshots creating on this volume, can not move this volume");
|
||||
@ -2650,8 +2655,10 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
s_logger.debug("Failed to set state into migrate: " + e.toString());
|
||||
throw new CloudRuntimeException("Failed to set state into migrate: " + e.toString());
|
||||
}
|
||||
volIds.add(volume.getId());
|
||||
}
|
||||
|
||||
checkPointTaskId = _checkPointMgr.pushCheckPoint(new StorageMigrationCleanupMaid(StorageMigrationCleanupMaid.StorageMigrationState.MIGRATING, volIds));
|
||||
transitResult = true;
|
||||
} finally {
|
||||
if (!transitResult) {
|
||||
@ -2708,6 +2715,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
s_logger.debug("Failed to change volume state: " + e.toString());
|
||||
}
|
||||
}
|
||||
_checkPointMgr.popCheckPoint(checkPointTaskId);
|
||||
} else {
|
||||
//Need a transaction, make sure all the volumes get migrated to new storage pool
|
||||
txn = Transaction.currentTxn();
|
||||
@ -2732,8 +2740,12 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
throw new CloudRuntimeException("Failed to change volume state: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
transitResult = true;
|
||||
try {
|
||||
_checkPointMgr.popCheckPoint(checkPointTaskId);
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
} finally {
|
||||
if (!transitResult) {
|
||||
txn.rollback();
|
||||
|
||||
105
server/src/com/cloud/storage/StorageMigrationCleanupMaid.java
Normal file
105
server/src/com/cloud/storage/StorageMigrationCleanupMaid.java
Normal file
@ -0,0 +1,105 @@
|
||||
package com.cloud.storage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.cluster.CheckPointManager;
|
||||
import com.cloud.cluster.CleanupMaid;
|
||||
import com.cloud.server.ManagementServer;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import com.cloud.utils.fsm.StateMachine2;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
public class StorageMigrationCleanupMaid implements CleanupMaid {
|
||||
private static final Logger s_logger = Logger.getLogger(StorageMigrationCleanupMaid.class);
|
||||
public static enum StorageMigrationState {
|
||||
MIGRATING,
|
||||
MIGRATINGFAILED,
|
||||
MIGRATINGSUCCESS;
|
||||
}
|
||||
|
||||
private List<Long> _volumesIds = new ArrayList<Long>();
|
||||
private StorageMigrationState _migrateState;
|
||||
|
||||
public StorageMigrationCleanupMaid() {
|
||||
|
||||
}
|
||||
|
||||
public StorageMigrationCleanupMaid(StorageMigrationState state, List<Long> volumes) {
|
||||
_migrateState = state;
|
||||
_volumesIds = volumes;
|
||||
}
|
||||
|
||||
public void updateStaste(StorageMigrationState state) {
|
||||
_migrateState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int cleanup(CheckPointManager checkPointMgr) {
|
||||
StateMachine2<Volume.State, Volume.Event, Volume> _stateMachine = Volume.State.getStateMachine();
|
||||
|
||||
ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
|
||||
VolumeDao volDao = locator.getDao(VolumeDao.class);
|
||||
VMInstanceDao vmDao = locator.getDao(VMInstanceDao.class);
|
||||
VirtualMachineManager vmMgr = locator.getManager(VirtualMachineManager.class);
|
||||
Long vmInstanceId = null;
|
||||
boolean success = true;
|
||||
Transaction txn = Transaction.open(Transaction.CLOUD_DB);
|
||||
|
||||
try {
|
||||
txn.start();
|
||||
for (Long volumeId : _volumesIds) {
|
||||
VolumeVO volume = volDao.findById(volumeId);
|
||||
if (volume == null) {
|
||||
continue;
|
||||
}
|
||||
vmInstanceId = volume.getInstanceId();
|
||||
if (_migrateState == StorageMigrationState.MIGRATING && volume.getState() == Volume.State.Migrating) {
|
||||
try {
|
||||
_stateMachine.transitTo(volume, Volume.Event.OperationFailed, null, volDao);
|
||||
} catch (NoTransitionException e) {
|
||||
s_logger.debug("Failed to transit volume state: " + e.toString());
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vmInstanceId != null) {
|
||||
VMInstanceVO vm = vmDao.findById(vmInstanceId);
|
||||
if (vm != null && vm.getState() == VirtualMachine.State.Migrating) {
|
||||
try {
|
||||
vmMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportStopped, null);
|
||||
} catch (NoTransitionException e) {
|
||||
s_logger.debug("Failed to transit vm state");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
txn.commit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("storage migration cleanup failed:" + e.toString());
|
||||
txn.rollback();
|
||||
}finally {
|
||||
txn.close();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCleanupProcedure() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user