Skip to content

Commit

Permalink
Create snapshot from VM snapshot for NFS/Local storage
Browse files Browse the repository at this point in the history
  • Loading branch information
slavkap authored and rohityadavcloud committed Oct 25, 2023
1 parent 7ffdb9f commit d28366e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 22 deletions.
2 changes: 1 addition & 1 deletion api/src/main/java/com/cloud/storage/Snapshot.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,13 @@
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;
Expand Down Expand Up @@ -97,6 +100,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {

@Inject
StorageManager storageManager;
@Inject
SnapshotDao snapshotDao;

@Override
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
Expand Down Expand Up @@ -583,8 +588,8 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
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;
Expand Down Expand Up @@ -631,6 +636,15 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {

}

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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1014,9 +1014,9 @@ public Answer backupSnapshot(final CopyCommand cmd) {
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) {
Expand All @@ -1041,18 +1041,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
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 {
Expand All @@ -1064,6 +1053,27 @@ public Answer backupSnapshot(final CopyCommand cmd) {
}
}
}

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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
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;
Expand Down Expand Up @@ -150,8 +151,10 @@
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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -497,12 +504,12 @@ public Snapshot backupSnapshotFromVmSnapshot(Long snapshotId, Long vmId, Long vo
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();
Expand All @@ -519,10 +526,35 @@ public Snapshot backupSnapshotFromVmSnapshot(Long snapshotId, Long vmId, Long vo
_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);
Expand Down

0 comments on commit d28366e

Please sign in to comment.