private Map<String, String> getSnapshotAttributes(SnapshotInfo snapshotInfo) { Map<String, String> mapAttributes = new HashMap<>(); mapAttributes.put(SolidFireUtil.CloudStackSnapshotId, String.valueOf(snapshotInfo.getId())); mapAttributes.put(SolidFireUtil.CloudStackSnapshotSize, NumberFormat.getInstance().format(snapshotInfo.getSize())); return mapAttributes; }
private boolean usingBackendSnapshotFor(SnapshotInfo snapshotInfo) { String property = getSnapshotProperty(snapshotInfo.getId(), "takeSnapshot"); return Boolean.parseBoolean(property); }
@Override public void postSnapshotCreation(SnapshotInfo snapshot) { updateLocationTypeInDb(snapshot); if (snapshot.getLocationType() == Snapshot.LocationType.SECONDARY) { // remove the snapshot on primary storage try { snapshotSvr.deleteSnapshot(snapshot); } catch (Exception e) { s_logger.warn("Failed to clean up snapshot '" + snapshot.getId() + "' on primary storage: " + e.getMessage()); } } }
private Map<String, String> getDestDetails(StoragePoolVO storagePoolVO, SnapshotInfo snapshotInfo) { Map<String, String> destDetails = new HashMap<>(); destDetails.put(DiskTO.STORAGE_HOST, storagePoolVO.getHostAddress()); destDetails.put(DiskTO.STORAGE_PORT, String.valueOf(storagePoolVO.getPort())); long snapshotId = snapshotInfo.getId(); destDetails.put(DiskTO.IQN, getProperty(snapshotId, DiskTO.IQN)); destDetails.put(DiskTO.CHAP_INITIATOR_USERNAME, getProperty(snapshotId, DiskTO.CHAP_INITIATOR_USERNAME)); destDetails.put(DiskTO.CHAP_INITIATOR_SECRET, getProperty(snapshotId, DiskTO.CHAP_INITIATOR_SECRET)); destDetails.put(DiskTO.CHAP_TARGET_USERNAME, getProperty(snapshotId, DiskTO.CHAP_TARGET_USERNAME)); destDetails.put(DiskTO.CHAP_TARGET_SECRET, getProperty(snapshotId, DiskTO.CHAP_TARGET_SECRET)); return destDetails; }
private void setVmdk(SnapshotInfo snapshotInfo, VolumeInfo volumeInfo) { if (!ImageFormat.OVA.equals(volumeInfo.getFormat())) { return; } String search = "]"; String path = volumeInfo.getPath(); int startIndex = path.indexOf(search); SnapshotDetailsVO snapshotDetail = new SnapshotDetailsVO(snapshotInfo.getId(), DiskTO.VMDK, path.substring(startIndex + search.length()).trim(), false); snapshotDetailsDao.persist(snapshotDetail); }
private void updateLocationTypeInDb(SnapshotInfo snapshotInfo) { Object objPayload = snapshotInfo.getPayload(); if (objPayload instanceof CreateSnapshotPayload) { CreateSnapshotPayload payload = (CreateSnapshotPayload)objPayload; SnapshotVO snapshot = snapshotDao.findById(snapshotInfo.getId()); snapshot.setLocationType(payload.getLocationType()); snapshotDao.update(snapshotInfo.getId(), snapshot); } }
private Map<String, String> getSnapshotDetails(SnapshotInfo snapshotInfo) { Map<String, String> snapshotDetails = new HashMap<>(); long storagePoolId = snapshotInfo.getDataStore().getId(); StoragePoolVO storagePoolVO = _storagePoolDao.findById(storagePoolId); snapshotDetails.put(DiskTO.STORAGE_HOST, storagePoolVO.getHostAddress()); snapshotDetails.put(DiskTO.STORAGE_PORT, String.valueOf(storagePoolVO.getPort())); long snapshotId = snapshotInfo.getId(); snapshotDetails.put(DiskTO.IQN, getSnapshotProperty(snapshotId, DiskTO.IQN)); snapshotDetails.put(DiskTO.VOLUME_SIZE, String.valueOf(snapshotInfo.getSize())); snapshotDetails.put(DiskTO.SCSI_NAA_DEVICE_ID, getSnapshotProperty(snapshotId, DiskTO.SCSI_NAA_DEVICE_ID)); snapshotDetails.put(DiskTO.CHAP_INITIATOR_USERNAME, getSnapshotProperty(snapshotId, DiskTO.CHAP_INITIATOR_USERNAME)); snapshotDetails.put(DiskTO.CHAP_INITIATOR_SECRET, getSnapshotProperty(snapshotId, DiskTO.CHAP_INITIATOR_SECRET)); snapshotDetails.put(DiskTO.CHAP_TARGET_USERNAME, getSnapshotProperty(snapshotId, DiskTO.CHAP_TARGET_USERNAME)); snapshotDetails.put(DiskTO.CHAP_TARGET_SECRET, getSnapshotProperty(snapshotId, DiskTO.CHAP_TARGET_SECRET)); return snapshotDetails; }
@Override public void revertSnapshot(SnapshotInfo snapshot, SnapshotInfo snapshotOnPrimaryStore, AsyncCompletionCallback<CommandResult> callback) { SnapshotObjectTO snapshotTO = (SnapshotObjectTO)snapshot.getTO(); RevertSnapshotCommand cmd = new RevertSnapshotCommand(snapshotTO); CommandResult result = new CommandResult(); try { EndPoint ep = epSelector.select(snapshotOnPrimaryStore); if ( ep == null ){ String errMsg = "No remote endpoint to send RevertSnapshotCommand, check if host or ssvm is down?"; s_logger.error(errMsg); result.setResult(errMsg); } else { Answer answer = ep.sendMessage(cmd); if (answer != null && !answer.getResult()) { result.setResult(answer.getDetails()); } } } catch (Exception ex) { s_logger.debug("Unable to revert snapshot " + snapshot.getId(), ex); result.setResult(ex.toString()); } callback.complete(result); }
@Override public void doInTransactionWithoutResult(TransactionStatus status) { try { SnapshotObject srcSnapshot = (SnapshotObject)snapshot; srcSnapshot.processEvent(Event.DestroyRequested); srcSnapshot.processEvent(Event.OperationSuccessed); srcSnapshot.processEvent(Snapshot.Event.OperationFailed); _snapshotDetailsDao.removeDetail(srcSnapshot.getId(), AsyncJob.Constants.MS_ID); _snapshotDao.remove(srcSnapshot.getId()); } catch (NoTransitionException ex) { s_logger.debug("Failed to create backup " + ex.toString()); throw new CloudRuntimeException("Failed to backup snapshot" + snapshot.getId()); } } });
/** * If the underlying storage system needed to create a volume from a snapshot for createVolumeFromSnapshot(SnapshotInfo), then * this is its opportunity to delete that temporary volume and restore properties in snapshot_details to the way they were before the * invocation of createVolumeFromSnapshot(SnapshotInfo). */ private void deleteVolumeFromSnapshot(SnapshotInfo snapshotInfo) { SnapshotDetailsVO snapshotDetails = handleSnapshotDetails(snapshotInfo.getId(), "delete"); try { snapshotInfo.getDataStore().getDriver().createAsync(snapshotInfo.getDataStore(), snapshotInfo, null); } finally { _snapshotDetailsDao.remove(snapshotDetails.getId()); } }
@Override public boolean revertSnapshot(SnapshotInfo snapshot) { SnapshotInfo snapshotOnPrimaryStore = _snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Primary); if (snapshotOnPrimaryStore == null) { throw new CloudRuntimeException("Cannot find an entry for snapshot " + snapshot.getId() + " on primary storage pools"); } PrimaryDataStore store = (PrimaryDataStore)snapshotOnPrimaryStore.getDataStore(); AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>(); RevertSnapshotContext<CommandResult> context = new RevertSnapshotContext<CommandResult>(null, snapshot, future); AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().revertSnapshotCallback(null, null)).setContext(context); ((PrimaryDataStoreDriver)store.getDriver()).revertSnapshot(snapshot, snapshotOnPrimaryStore, caller); SnapshotResult result = null; try { result = future.get(); if (result.isFailed()) { throw new CloudRuntimeException(result.getResult()); } return true; } catch (InterruptedException e) { s_logger.debug("revert snapshot is failed: " + e.toString()); } catch (ExecutionException e) { s_logger.debug("revert snapshot is failed: " + e.toString()); } return false; }
@Override public AsyncCallFuture<VolumeApiResult> createVolumeFromSnapshot(VolumeInfo volume, DataStore store, SnapshotInfo snapshot) { AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>(); try { DataObject volumeOnStore = store.create(volume); volumeOnStore.processEvent(Event.CreateOnlyRequested); _volumeDetailsDao.addDetail(volume.getId(), SNAPSHOT_ID, Long.toString(snapshot.getId()), false); CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, volume, store, volumeOnStore, future, snapshot); AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().createVolumeFromSnapshotCallback(null, null)).setContext(context); motionSrv.copyAsync(snapshot, volumeOnStore, caller); } catch (Exception e) { s_logger.debug("create volume from snapshot failed", e); VolumeApiResult result = new VolumeApiResult(volume); result.setResult(e.toString()); future.complete(result); } return future; }
public SnapshotObjectTO(SnapshotInfo snapshot) { this.path = snapshot.getPath(); this.setId(snapshot.getId()); VolumeInfo vol = snapshot.getBaseVolume(); if (vol != null) { this.volume = (VolumeObjectTO)vol.getTO(); this.setVmName(vol.getAttachedVmName()); } SnapshotInfo parentSnapshot = snapshot.getParent(); ArrayList<String> parentsArry = new ArrayList<String>(); if (parentSnapshot != null) { this.parentSnapshotPath = parentSnapshot.getPath(); while(parentSnapshot != null) { parentsArry.add(parentSnapshot.getPath()); parentSnapshot = parentSnapshot.getParent(); } parents = parentsArry.toArray(new String[parentsArry.size()]); ArrayUtils.reverse(parents); } this.dataStore = snapshot.getDataStore().getTO(); this.setName(snapshot.getName()); this.hypervisorType = snapshot.getHypervisorType(); this.quiescevm = false; }
/** * If the underlying storage system is making use of read-only snapshots, this gives the storage system the opportunity to * create a volume from the snapshot so that we can copy the VHD file that should be inside of the snapshot to secondary storage. * * The resultant volume must be writable because we need to resign the SR and the VDI that should be inside of it before we copy * the VHD file to secondary storage. * * If the storage system is using writable snapshots, then nothing need be done by that storage system here because we can just * resign the SR and the VDI that should be inside of the snapshot before copying the VHD file to secondary storage. */ private void createVolumeFromSnapshot(SnapshotInfo snapshotInfo) { SnapshotDetailsVO snapshotDetails = handleSnapshotDetails(snapshotInfo.getId(), "create"); try { snapshotInfo.getDataStore().getDriver().createAsync(snapshotInfo.getDataStore(), snapshotInfo, null); } finally { _snapshotDetailsDao.remove(snapshotDetails.getId()); } }
private void deleteSnapshot(SnapshotInfo snapshotInfo, long storagePoolId) { long csSnapshotId = snapshotInfo.getId(); try { SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, storagePoolDetailsDao); SnapshotDetailsVO snapshotDetails = snapshotDetailsDao.findDetail(csSnapshotId, SolidFireUtil.SNAPSHOT_ID); if (snapshotDetails != null && snapshotDetails.getValue() != null) { // A SolidFire snapshot is being used to support the CloudStack volume snapshot. long sfSnapshotId = Long.parseLong(snapshotDetails.getValue()); deleteSolidFireSnapshot(sfConnection, csSnapshotId, sfSnapshotId); } else { // A SolidFire volume is being used to support the CloudStack volume snapshot. snapshotDetails = snapshotDetailsDao.findDetail(csSnapshotId, SolidFireUtil.VOLUME_ID); long sfVolumeId = Long.parseLong(snapshotDetails.getValue()); SolidFireUtil.deleteVolume(sfConnection, sfVolumeId); } snapshotDetailsDao.removeDetails(csSnapshotId); StoragePoolVO storagePool = storagePoolDao.findById(storagePoolId); // getUsedBytes(StoragePool) will not include the snapshot to delete because it has already been deleted by this point long usedBytes = getUsedBytes(storagePool); storagePool.setUsedBytes(usedBytes < 0 ? 0 : usedBytes); storagePoolDao.update(storagePoolId, storagePool); } catch (Exception ex) { LOGGER.debug(SolidFireUtil.LOG_PREFIX + "Issue in 'deleteSnapshot(SnapshotInfo, long)'. CloudStack snapshot ID: " + csSnapshotId, ex); throw ex; } }
return; } catch (Exception e) { s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e); result = new CreateCmdResult(null, null); result.setResult(e.toString());
@Override public Snapshot archiveSnapshot(Long snapshotId) { SnapshotInfo snapshotOnPrimary = snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Primary); if (snapshotOnPrimary == null || !snapshotOnPrimary.getStatus().equals(ObjectInDataStoreStateMachine.State.Ready)) { throw new CloudRuntimeException("Can only archive snapshots present on primary storage. " + "Cannot find snapshot " + snapshotId + " on primary storage"); } SnapshotInfo snapshotOnSecondary = snapshotSrv.backupSnapshot(snapshotOnPrimary); SnapshotVO snapshotVO = _snapshotDao.findById(snapshotOnSecondary.getId()); snapshotVO.setLocationType(Snapshot.LocationType.SECONDARY); _snapshotDao.persist(snapshotVO); try { snapshotSrv.deleteSnapshot(snapshotOnPrimary); } catch (Exception e) { throw new CloudRuntimeException("Snapshot archived to Secondary Storage but there was an error deleting " + " the snapshot on Primary Storage. Please manually delete the primary snapshot " + snapshotId, e); } return snapshotOnSecondary; }
private DataStore findSnapshotImageStore(SnapshotInfo snapshot) { Boolean fullSnapshot = true; Boolean snapshotFullBackup = snapshot.getFullBackup(); if (snapshotFullBackup != null) { fullSnapshot = snapshotFullBackup; } if (fullSnapshot) { return dataStoreMgr.getImageStore(snapshot.getDataCenterId()); } else { SnapshotInfo parentSnapshot = snapshot.getParent(); // Note that DataStore information in parentSnapshot is for primary // data store here, we need to // find the image store where the parent snapshot backup is located SnapshotDataStoreVO parentSnapshotOnBackupStore = null; if (parentSnapshot != null) { parentSnapshotOnBackupStore = _snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), DataStoreRole.Image); } if (parentSnapshotOnBackupStore == null) { return dataStoreMgr.getImageStore(snapshot.getDataCenterId()); } return dataStoreMgr.getDataStore(parentSnapshotOnBackupStore.getDataStoreId(), parentSnapshotOnBackupStore.getRole()); } }
@Override public void revertSnapshot(SnapshotInfo snapshot, SnapshotInfo snapshot2, AsyncCompletionCallback<CommandResult> callback) { VolumeInfo volumeInfo = snapshot.getBaseVolume(); VolumeVO volumeVO = volumeDao.findById(volumeInfo.getId()); if (volumeVO == null || volumeVO.getRemoved() != null) { String errMsg = "The volume that the snapshot belongs to no longer exists."; CommandResult commandResult = new CommandResult(); commandResult.setResult(errMsg); callback.complete(commandResult); return; } SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(volumeVO.getPoolId(), storagePoolDetailsDao); long sfVolumeId = Long.parseLong(volumeInfo.getFolder()); SnapshotDetailsVO snapshotDetails = snapshotDetailsDao.findDetail(snapshot.getId(), SolidFireUtil.SNAPSHOT_ID); long sfSnapshotId = Long.parseLong(snapshotDetails.getValue()); SolidFireUtil.rollBackVolumeToSnapshot(sfConnection, sfVolumeId, sfSnapshotId); SolidFireUtil.SolidFireVolume sfVolume = SolidFireUtil.getVolume(sfConnection, sfVolumeId); updateVolumeDetails(volumeVO.getId(), sfVolume.getTotalSize(), sfVolume.getScsiNaaDeviceId()); CommandResult commandResult = new CommandResult(); callback.complete(commandResult); }
private void createTempVolume(SnapshotInfo snapshotInfo, long storagePoolId) { long csSnapshotId = snapshotInfo.getId(); SnapshotDetailsVO snapshotDetails = snapshotDetailsDao.findDetail(csSnapshotId, SolidFireUtil.SNAPSHOT_ID); if (snapshotDetails == null || snapshotDetails.getValue() == null) { throw new CloudRuntimeException("'createTempVolume(SnapshotInfo, long)' should not be invoked unless " + SolidFireUtil.SNAPSHOT_ID + " exists."); } SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, storagePoolDetailsDao); snapshotDetails = snapshotDetailsDao.findDetail(csSnapshotId, "tempVolume"); if (snapshotDetails != null && snapshotDetails.getValue() != null && snapshotDetails.getValue().equalsIgnoreCase("create")) { long sfAccountId = getCreateSolidFireAccountId(sfConnection, snapshotInfo.getAccountId(), storagePoolId); SolidFireUtil.SolidFireVolume sfVolume = createCloneFromSnapshot(sfConnection, csSnapshotId, sfAccountId); addTempVolumeId(csSnapshotId, String.valueOf(sfVolume.getId())); handleSnapshotDetails(csSnapshotId, DiskTO.IQN, sfVolume.getIqn()); handleSnapshotDetails(csSnapshotId, DiskTO.SCSI_NAA_DEVICE_ID, sfVolume.getScsiNaaDeviceId()); } else if (snapshotDetails != null && snapshotDetails.getValue() != null && snapshotDetails.getValue().equalsIgnoreCase("delete")) { snapshotDetails = snapshotDetailsDao.findDetail(csSnapshotId, SolidFireUtil.VOLUME_ID); SolidFireUtil.deleteVolume(sfConnection, Long.parseLong(snapshotDetails.getValue())); removeTempVolumeId(csSnapshotId); snapshotDetails = snapshotDetailsDao.findDetail(csSnapshotId, DiskTO.IQN); snapshotDetailsDao.remove(snapshotDetails.getId()); snapshotDetails = snapshotDetailsDao.findDetail(csSnapshotId, DiskTO.SCSI_NAA_DEVICE_ID); snapshotDetailsDao.remove(snapshotDetails.getId()); } else { throw new CloudRuntimeException("Invalid state in 'createTempVolume(SnapshotInfo, long)'"); } }