Skip to content

Commit d28366e

Browse files
slavkaprohityadavcloud
authored andcommitted
Create snapshot from VM snapshot for NFS/Local storage
1 parent 7ffdb9f commit d28366e

File tree

4 files changed

+78
-22
lines changed

4 files changed

+78
-22
lines changed

api/src/main/java/com/cloud/storage/Snapshot.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, StateObject<Snapshot.State> {
2828
public enum Type {
29-
MANUAL, RECURRING, TEMPLATE, HOURLY, DAILY, WEEKLY, MONTHLY, GROUP;
29+
MANUAL, RECURRING, TEMPLATE, HOURLY, DAILY, WEEKLY, MONTHLY, GROUP, FROM_GROUP;
3030
private int max = 8;
3131

3232
public void setMax(int max) {

engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,13 @@
6666
import com.cloud.host.Host;
6767
import com.cloud.hypervisor.Hypervisor;
6868
import com.cloud.storage.DataStoreRole;
69+
import com.cloud.storage.Snapshot.Type;
70+
import com.cloud.storage.SnapshotVO;
6971
import com.cloud.storage.StorageManager;
7072
import com.cloud.storage.Storage.StoragePoolType;
7173
import com.cloud.storage.StoragePool;
7274
import com.cloud.storage.VolumeVO;
75+
import com.cloud.storage.dao.SnapshotDao;
7376
import com.cloud.storage.dao.VolumeDao;
7477
import com.cloud.utils.NumbersUtil;
7578
import com.cloud.utils.db.DB;
@@ -97,6 +100,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
97100

98101
@Inject
99102
StorageManager storageManager;
103+
@Inject
104+
SnapshotDao snapshotDao;
100105

101106
@Override
102107
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
@@ -583,8 +588,8 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
583588
fullSnapshot = snapshotFullBackup;
584589
}
585590
Map<String, String> options = new HashMap<String, String>();
586-
options.put("fullSnapshot", fullSnapshot.toString());
587-
options.put(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key(), String.valueOf(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()));
591+
592+
addCommandOptions(snapshotInfo, fullSnapshot, options);
588593
boolean encryptionRequired = anyVolumeRequiresEncryption(srcData, destData);
589594

590595
Answer answer = null;
@@ -631,6 +636,15 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
631636

632637
}
633638

639+
private void addCommandOptions(SnapshotInfo snapshotInfo, Boolean fullSnapshot, Map<String, String> options) {
640+
SnapshotVO snap = snapshotDao.findById(snapshotInfo.getSnapshotId());
641+
if (snap != null && Type.FROM_GROUP.name().equals(snap.getTypeDescription())) {
642+
options.put("typeDescription", snap.getTypeDescription());
643+
}
644+
options.put("fullSnapshot", fullSnapshot.toString());
645+
options.put(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key(), String.valueOf(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()));
646+
}
647+
634648
@Override
635649
public void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
636650
CopyCommandResult result = new CopyCommandResult(null, null);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,9 +1014,9 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10141014
command.add("-b", isCreatedFromVmSnapshot ? snapshotDisk.getPath() : snapshot.getPath());
10151015
command.add(NAME_OPTION, snapshotName);
10161016
command.add("-p", snapshotDestPath);
1017-
if (isCreatedFromVmSnapshot) {
1018-
descName = UUID.randomUUID().toString();
1019-
}
1017+
1018+
descName = UUID.randomUUID().toString();
1019+
10201020
command.add("-t", descName);
10211021
final String result = command.execute();
10221022
if (result != null) {
@@ -1041,18 +1041,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10411041
if (isCreatedFromVmSnapshot) {
10421042
s_logger.debug("Ignoring removal of vm snapshot on primary as this snapshot is created from vm snapshot");
10431043
} else if (primaryPool.getType() != StoragePoolType.RBD) {
1044-
String snapshotPath = snapshot.getPath();
1045-
String backupSnapshotAfterTakingSnapshot = cmd.getOptions() == null ? null : cmd.getOptions().get(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key());
1046-
1047-
if (backupSnapshotAfterTakingSnapshot == null || BooleanUtils.toBoolean(backupSnapshotAfterTakingSnapshot)) {
1048-
try {
1049-
Files.deleteIfExists(Paths.get(snapshotPath));
1050-
} catch (IOException ex) {
1051-
s_logger.error(String.format("Failed to delete snapshot [%s] on primary storage [%s].", snapshotPath, primaryPool.getUuid()), ex);
1052-
}
1053-
} else {
1054-
s_logger.debug(String.format("This backup is temporary, not deleting snapshot [%s] on primary storage [%s]", snapshotPath, primaryPool.getUuid()));
1055-
}
1044+
deleteSnapshotOnPrimary(cmd, snapshot, primaryPool);
10561045
}
10571046

10581047
try {
@@ -1064,6 +1053,27 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10641053
}
10651054
}
10661055
}
1056+
1057+
private void deleteSnapshotOnPrimary(final CopyCommand cmd, final SnapshotObjectTO snapshot,
1058+
KVMStoragePool primaryPool) {
1059+
String snapshotPath = snapshot.getPath();
1060+
String backupSnapshotAfterTakingSnapshot = null;
1061+
boolean deleteSnapshotOnPrimary = true;
1062+
if (cmd.getOptions() != null) {
1063+
backupSnapshotAfterTakingSnapshot = cmd.getOptions().get(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key());
1064+
deleteSnapshotOnPrimary = cmd.getOptions().get("typeDescription") == null;
1065+
}
1066+
1067+
if ((backupSnapshotAfterTakingSnapshot == null || BooleanUtils.toBoolean(backupSnapshotAfterTakingSnapshot)) && deleteSnapshotOnPrimary) {
1068+
try {
1069+
Files.deleteIfExists(Paths.get(snapshotPath));
1070+
} catch (IOException ex) {
1071+
s_logger.error(String.format("Failed to delete snapshot [%s] on primary storage [%s].", snapshotPath, primaryPool.getUuid()), ex);
1072+
}
1073+
} else {
1074+
s_logger.debug(String.format("This backup is temporary, not deleting snapshot [%s] on primary storage [%s]", snapshotPath, primaryPool.getUuid()));
1075+
}
1076+
}
10671077
protected synchronized void attachOrDetachISO(final Connect conn, final String vmName, String isoPath, final boolean isAttach, Map<String, String> params) throws
10681078
LibvirtException, InternalErrorException {
10691079
DiskDef iso = new DiskDef();

server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
import com.cloud.storage.SnapshotVO;
110110
import com.cloud.storage.Storage;
111111
import com.cloud.storage.Storage.ImageFormat;
112+
import com.cloud.storage.Storage.StoragePoolType;
112113
import com.cloud.storage.StorageManager;
113114
import com.cloud.storage.StoragePool;
114115
import com.cloud.storage.VMTemplateVO;
@@ -150,8 +151,10 @@
150151
import com.cloud.vm.VirtualMachine.State;
151152
import com.cloud.vm.dao.UserVmDao;
152153
import com.cloud.vm.snapshot.VMSnapshot;
154+
import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
153155
import com.cloud.vm.snapshot.VMSnapshotVO;
154156
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
157+
import com.cloud.vm.snapshot.dao.VMSnapshotDetailsDao;
155158

156159
@Component
157160
public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implements SnapshotManager, SnapshotApiService, Configurable {
@@ -221,6 +224,10 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
221224
protected SnapshotHelper snapshotHelper;
222225
@Inject
223226
DataCenterDao dataCenterDao;
227+
@Inject
228+
VMSnapshotDetailsDao vmSnapshotDetailsDao;
229+
@Inject
230+
SnapshotDataFactory snapshotDataFactory;
224231

225232
private int _totalRetries;
226233
private int _pauseInterval;
@@ -497,12 +504,12 @@ public Snapshot backupSnapshotFromVmSnapshot(Long snapshotId, Long vmId, Long vo
497504
SnapshotInfo snapshotInfo = this.snapshotFactory.getSnapshot(snapshotId, store);
498505
snapshotInfo = (SnapshotInfo)store.create(snapshotInfo);
499506
SnapshotDataStoreVO snapshotOnPrimaryStore = this._snapshotStoreDao.findByStoreSnapshot(store.getRole(), store.getId(), snapshot.getId());
500-
snapshotOnPrimaryStore.setState(ObjectInDataStoreStateMachine.State.Ready);
501-
snapshotOnPrimaryStore.setInstallPath(vmSnapshot.getName());
502-
_snapshotStoreDao.update(snapshotOnPrimaryStore.getId(), snapshotOnPrimaryStore);
507+
508+
StoragePoolVO storagePool = _storagePoolDao.findById(store.getId());
509+
updateSnapshotInfo(volumeId, vmSnapshotId, vmSnapshot, snapshot, snapshotOnPrimaryStore, storagePool);
510+
503511
snapshot.setState(Snapshot.State.CreatedOnPrimary);
504512
_snapshotDao.update(snapshot.getId(), snapshot);
505-
506513
snapshotInfo = this.snapshotFactory.getSnapshot(snapshotId, store);
507514

508515
Long snapshotOwnerId = vm.getAccountId();
@@ -519,10 +526,35 @@ public Snapshot backupSnapshotFromVmSnapshot(Long snapshotId, Long vmId, Long vo
519526
_resourceLimitMgr.decrementResourceCount(snapshotOwnerId, ResourceType.snapshot);
520527
_resourceLimitMgr.decrementResourceCount(snapshotOwnerId, ResourceType.secondary_storage, new Long(volume.getSize()));
521528
throw new CloudRuntimeException("Failed to backup snapshot from vm snapshot", e);
529+
} finally {
530+
if (snapshotOnPrimaryStore != null) {
531+
_snapshotStoreDao.remove(snapshotOnPrimaryStore.getId());
532+
}
522533
}
523534
return snapshotInfo;
524535
}
525536

537+
private void updateSnapshotInfo(Long volumeId, Long vmSnapshotId, VMSnapshotVO vmSnapshot, SnapshotVO snapshot,
538+
SnapshotDataStoreVO snapshotOnPrimaryStore, StoragePoolVO storagePool) {
539+
if ((storagePool.getPoolType() == StoragePoolType.NetworkFilesystem || storagePool.getPoolType() == StoragePoolType.Filesystem) && vmSnapshot.getType() == VMSnapshot.Type.Disk) {
540+
List<VMSnapshotDetailsVO> vmSnapshotDetails = vmSnapshotDetailsDao.findDetails(vmSnapshotId, "kvmStorageSnapshot");
541+
for (VMSnapshotDetailsVO vmSnapshotDetailsVO : vmSnapshotDetails) {
542+
SnapshotInfo sInfo = snapshotDataFactory.getSnapshot(Long.parseLong(vmSnapshotDetailsVO.getValue()), DataStoreRole.Primary);
543+
if (sInfo.getVolumeId() == volumeId) {
544+
snapshotOnPrimaryStore.setState(ObjectInDataStoreStateMachine.State.Ready);
545+
snapshotOnPrimaryStore.setInstallPath(sInfo.getPath());
546+
_snapshotStoreDao.update(snapshotOnPrimaryStore.getId(), snapshotOnPrimaryStore);
547+
snapshot.setTypeDescription(Type.FROM_GROUP.name());
548+
snapshot.setSnapshotType((short)Type.FROM_GROUP.ordinal());
549+
}
550+
}
551+
} else {
552+
snapshotOnPrimaryStore.setState(ObjectInDataStoreStateMachine.State.Ready);
553+
snapshotOnPrimaryStore.setInstallPath(vmSnapshot.getName());
554+
_snapshotStoreDao.update(snapshotOnPrimaryStore.getId(), snapshotOnPrimaryStore);
555+
}
556+
}
557+
526558
@Override
527559
public SnapshotVO getParentSnapshot(VolumeInfo volume) {
528560
long preId = _snapshotDao.getLastSnapshot(volume.getId(), DataStoreRole.Primary);

0 commit comments

Comments
 (0)