mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Create snapshot from VM snapshot without memory for NFS/Local storage (#8117)
This commit is contained in:
parent
ae724b9d4c
commit
6ae3b73ca2
@ -26,7 +26,7 @@ import java.util.Date;
|
||||
|
||||
public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, StateObject<Snapshot.State> {
|
||||
public enum Type {
|
||||
MANUAL, RECURRING, TEMPLATE, HOURLY, DAILY, WEEKLY, MONTHLY, GROUP;
|
||||
MANUAL, RECURRING, TEMPLATE, HOURLY, DAILY, WEEKLY, MONTHLY, GROUP, FROM_GROUP;
|
||||
private int max = 8;
|
||||
|
||||
public void setMax(int max) {
|
||||
|
||||
@ -66,10 +66,13 @@ import com.cloud.configuration.Config;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Snapshot.Type;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.db.DB;
|
||||
@ -97,6 +100,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
@Inject
|
||||
StorageManager storageManager;
|
||||
@Inject
|
||||
SnapshotDao snapshotDao;
|
||||
|
||||
@Override
|
||||
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
|
||||
@ -583,8 +588,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
||||
fullSnapshot = snapshotFullBackup;
|
||||
}
|
||||
Map<String, String> options = new HashMap<String, String>();
|
||||
options.put("fullSnapshot", fullSnapshot.toString());
|
||||
options.put(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key(), String.valueOf(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()));
|
||||
|
||||
addCommandOptions(snapshotInfo, fullSnapshot, options);
|
||||
boolean encryptionRequired = anyVolumeRequiresEncryption(srcData, destData);
|
||||
|
||||
Answer answer = null;
|
||||
@ -631,6 +636,15 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
}
|
||||
|
||||
private void addCommandOptions(SnapshotInfo snapshotInfo, Boolean fullSnapshot, Map<String, String> options) {
|
||||
SnapshotVO snap = snapshotDao.findById(snapshotInfo.getSnapshotId());
|
||||
if (snap != null && Type.FROM_GROUP.name().equals(snap.getTypeDescription())) {
|
||||
options.put("typeDescription", snap.getTypeDescription());
|
||||
}
|
||||
options.put("fullSnapshot", fullSnapshot.toString());
|
||||
options.put(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key(), String.valueOf(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||
CopyCommandResult result = new CopyCommandResult(null, null);
|
||||
|
||||
@ -1014,9 +1014,9 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
command.add("-b", isCreatedFromVmSnapshot ? snapshotDisk.getPath() : snapshot.getPath());
|
||||
command.add(NAME_OPTION, snapshotName);
|
||||
command.add("-p", snapshotDestPath);
|
||||
if (isCreatedFromVmSnapshot) {
|
||||
descName = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
descName = UUID.randomUUID().toString();
|
||||
|
||||
command.add("-t", descName);
|
||||
final String result = command.execute();
|
||||
if (result != null) {
|
||||
@ -1041,18 +1041,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
if (isCreatedFromVmSnapshot) {
|
||||
s_logger.debug("Ignoring removal of vm snapshot on primary as this snapshot is created from vm snapshot");
|
||||
} else if (primaryPool.getType() != StoragePoolType.RBD) {
|
||||
String snapshotPath = snapshot.getPath();
|
||||
String backupSnapshotAfterTakingSnapshot = cmd.getOptions() == null ? null : cmd.getOptions().get(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key());
|
||||
|
||||
if (backupSnapshotAfterTakingSnapshot == null || BooleanUtils.toBoolean(backupSnapshotAfterTakingSnapshot)) {
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(snapshotPath));
|
||||
} catch (IOException ex) {
|
||||
s_logger.error(String.format("Failed to delete snapshot [%s] on primary storage [%s].", snapshotPath, primaryPool.getUuid()), ex);
|
||||
}
|
||||
} else {
|
||||
s_logger.debug(String.format("This backup is temporary, not deleting snapshot [%s] on primary storage [%s]", snapshotPath, primaryPool.getUuid()));
|
||||
}
|
||||
deleteSnapshotOnPrimary(cmd, snapshot, primaryPool);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -1064,6 +1053,27 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteSnapshotOnPrimary(final CopyCommand cmd, final SnapshotObjectTO snapshot,
|
||||
KVMStoragePool primaryPool) {
|
||||
String snapshotPath = snapshot.getPath();
|
||||
String backupSnapshotAfterTakingSnapshot = null;
|
||||
boolean deleteSnapshotOnPrimary = true;
|
||||
if (cmd.getOptions() != null) {
|
||||
backupSnapshotAfterTakingSnapshot = cmd.getOptions().get(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key());
|
||||
deleteSnapshotOnPrimary = cmd.getOptions().get("typeDescription") == null;
|
||||
}
|
||||
|
||||
if ((backupSnapshotAfterTakingSnapshot == null || BooleanUtils.toBoolean(backupSnapshotAfterTakingSnapshot)) && deleteSnapshotOnPrimary) {
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(snapshotPath));
|
||||
} catch (IOException ex) {
|
||||
s_logger.error(String.format("Failed to delete snapshot [%s] on primary storage [%s].", snapshotPath, primaryPool.getUuid()), ex);
|
||||
}
|
||||
} else {
|
||||
s_logger.debug(String.format("This backup is temporary, not deleting snapshot [%s] on primary storage [%s]", snapshotPath, primaryPool.getUuid()));
|
||||
}
|
||||
}
|
||||
protected synchronized void attachOrDetachISO(final Connect conn, final String vmName, String isoPath, final boolean isAttach, Map<String, String> params) throws
|
||||
LibvirtException, InternalErrorException {
|
||||
DiskDef iso = new DiskDef();
|
||||
|
||||
@ -109,6 +109,7 @@ import com.cloud.storage.SnapshotScheduleVO;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
@ -150,8 +151,10 @@ import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
|
||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDetailsDao;
|
||||
|
||||
@Component
|
||||
public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implements SnapshotManager, SnapshotApiService, Configurable {
|
||||
@ -221,6 +224,10 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
||||
protected SnapshotHelper snapshotHelper;
|
||||
@Inject
|
||||
DataCenterDao dataCenterDao;
|
||||
@Inject
|
||||
VMSnapshotDetailsDao vmSnapshotDetailsDao;
|
||||
@Inject
|
||||
SnapshotDataFactory snapshotDataFactory;
|
||||
|
||||
private int _totalRetries;
|
||||
private int _pauseInterval;
|
||||
@ -497,12 +504,12 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
||||
SnapshotInfo snapshotInfo = this.snapshotFactory.getSnapshot(snapshotId, store);
|
||||
snapshotInfo = (SnapshotInfo)store.create(snapshotInfo);
|
||||
SnapshotDataStoreVO snapshotOnPrimaryStore = this._snapshotStoreDao.findByStoreSnapshot(store.getRole(), store.getId(), snapshot.getId());
|
||||
snapshotOnPrimaryStore.setState(ObjectInDataStoreStateMachine.State.Ready);
|
||||
snapshotOnPrimaryStore.setInstallPath(vmSnapshot.getName());
|
||||
_snapshotStoreDao.update(snapshotOnPrimaryStore.getId(), snapshotOnPrimaryStore);
|
||||
|
||||
StoragePoolVO storagePool = _storagePoolDao.findById(store.getId());
|
||||
updateSnapshotInfo(volumeId, vmSnapshotId, vmSnapshot, snapshot, snapshotOnPrimaryStore, storagePool);
|
||||
|
||||
snapshot.setState(Snapshot.State.CreatedOnPrimary);
|
||||
_snapshotDao.update(snapshot.getId(), snapshot);
|
||||
|
||||
snapshotInfo = this.snapshotFactory.getSnapshot(snapshotId, store);
|
||||
|
||||
Long snapshotOwnerId = vm.getAccountId();
|
||||
@ -519,10 +526,35 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwnerId, ResourceType.snapshot);
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwnerId, ResourceType.secondary_storage, new Long(volume.getSize()));
|
||||
throw new CloudRuntimeException("Failed to backup snapshot from vm snapshot", e);
|
||||
} finally {
|
||||
if (snapshotOnPrimaryStore != null) {
|
||||
_snapshotStoreDao.remove(snapshotOnPrimaryStore.getId());
|
||||
}
|
||||
}
|
||||
return snapshotInfo;
|
||||
}
|
||||
|
||||
private void updateSnapshotInfo(Long volumeId, Long vmSnapshotId, VMSnapshotVO vmSnapshot, SnapshotVO snapshot,
|
||||
SnapshotDataStoreVO snapshotOnPrimaryStore, StoragePoolVO storagePool) {
|
||||
if ((storagePool.getPoolType() == StoragePoolType.NetworkFilesystem || storagePool.getPoolType() == StoragePoolType.Filesystem) && vmSnapshot.getType() == VMSnapshot.Type.Disk) {
|
||||
List<VMSnapshotDetailsVO> vmSnapshotDetails = vmSnapshotDetailsDao.findDetails(vmSnapshotId, "kvmStorageSnapshot");
|
||||
for (VMSnapshotDetailsVO vmSnapshotDetailsVO : vmSnapshotDetails) {
|
||||
SnapshotInfo sInfo = snapshotDataFactory.getSnapshot(Long.parseLong(vmSnapshotDetailsVO.getValue()), DataStoreRole.Primary);
|
||||
if (sInfo.getVolumeId() == volumeId) {
|
||||
snapshotOnPrimaryStore.setState(ObjectInDataStoreStateMachine.State.Ready);
|
||||
snapshotOnPrimaryStore.setInstallPath(sInfo.getPath());
|
||||
_snapshotStoreDao.update(snapshotOnPrimaryStore.getId(), snapshotOnPrimaryStore);
|
||||
snapshot.setTypeDescription(Type.FROM_GROUP.name());
|
||||
snapshot.setSnapshotType((short)Type.FROM_GROUP.ordinal());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
snapshotOnPrimaryStore.setState(ObjectInDataStoreStateMachine.State.Ready);
|
||||
snapshotOnPrimaryStore.setInstallPath(vmSnapshot.getName());
|
||||
_snapshotStoreDao.update(snapshotOnPrimaryStore.getId(), snapshotOnPrimaryStore);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotVO getParentSnapshot(VolumeInfo volume) {
|
||||
long preId = _snapshotDao.getLastSnapshot(volume.getId(), DataStoreRole.Primary);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user