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(); | ||||
|                 } | ||||
| 
 | ||||
|                 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