/** {@inheritDoc} */ @Override public void validateSnapshotCreateRequest(Volume requestedVolume, List<Volume> volumesToSnap) { // For VMAX3 you cannot have active snap and full copy sessions, // so verify there are no active full copies for the volume. for (Volume volumeToSnap : volumesToSnap) { // Check if the volume to snap is an active full copy. if ((BlockFullCopyUtils.isVolumeFullCopy(volumeToSnap, _dbClient)) && (!BlockFullCopyUtils.isFullCopyDetached(volumeToSnap, _dbClient)) && (!BlockFullCopyUtils.isFullCopyInactive(volumeToSnap, _dbClient))) { throw APIException.badRequests.noSnapshotsForVMAX3VolumeWithActiveFullCopy(); } // Now check if the volume to be snapped is a full copy source // that has active full copies. StringSet fullCopyIds = volumeToSnap.getFullCopies(); if ((fullCopyIds != null) && (!fullCopyIds.isEmpty())) { Iterator<String> fullCopyIdsIter = fullCopyIds.iterator(); while (fullCopyIdsIter.hasNext()) { URI fullCopyURI = URI.create(fullCopyIdsIter.next()); Volume fullCopyVolume = _dbClient.queryObject(Volume.class, fullCopyURI); if ((fullCopyVolume != null) && (!fullCopyVolume.getInactive()) && (!BlockFullCopyUtils.isFullCopyDetached(fullCopyVolume, _dbClient)) && (!BlockFullCopyUtils.isFullCopyInactive(fullCopyVolume, _dbClient))) { throw APIException.badRequests.noSnapshotsForVMAX3VolumeWithActiveFullCopy(); } } } } }
private void handleVplexVolumeErrors(DbClient dbClient) { List<String> finalMessages = new ArrayList<String>(); for (VolumeDescriptor volumeDescriptor : VolumeDescriptor.getDescriptors( _volumeDescriptors, VolumeDescriptor.Type.VPLEX_VIRT_VOLUME)) { Volume volume = dbClient.queryObject(Volume.class, volumeDescriptor.getVolumeURI()); _log.info("Looking at VPLEX virtual volume {}", volume.getLabel()); boolean deactivateVirtualVolume = true; List<String> livingVolumeNames = new ArrayList<String>(); _log.info("Its associated volumes are: " + volume.getAssociatedVolumes()); for (String associatedVolumeUri : volume.getAssociatedVolumes()) { Volume associatedVolume = dbClient.queryObject(Volume.class, URI.create(associatedVolumeUri)); if (associatedVolume != null && !associatedVolume.getInactive()) { _log.warn( "VPLEX virtual volume {} has active associated volume {}", volume.getLabel(), associatedVolume.getLabel()); livingVolumeNames.add(associatedVolume.getLabel()); deactivateVirtualVolume = false; } } if (deactivateVirtualVolume) { _log.info( "VPLEX virtual volume {} has no active associated volumes, marking for deletion", volume.getLabel()); dbClient.markForDeletion(volume); } else { String message = "VPLEX virtual volume " + volume.getLabel() + " will not be marked for deletion " + "because it still has active associated volumes ("; message += Joiner.on(",").join(livingVolumeNames) + ")"; finalMessages.add(message); _log.warn(message); } } if (!finalMessages.isEmpty()) { String finalMessage = Joiner.on("; ").join(finalMessages) + "."; _log.error(finalMessage); } }
/** * Verify the RP consistency group and its volumes have been properly migrated. * * @throws Exception */ private void verifyRpConsistencyGroupWithDuplicatesMigration() throws Exception { log.info("Verifying duplicate protection sets were cleaned up."); List<URI> protSetIds = _dbClient.queryByType(ProtectionSet.class, true); List<String> protSetNames = new ArrayList<String>(); for (URI id : protSetIds) { ProtectionSet protSet = _dbClient.queryObject(ProtectionSet.class, id); if (protSet == null || protSet.getInactive()) { continue; } if (protSetNames.contains(protSet.getLabel())) { // fail duplicate protection set Assert.fail("Duplicate protection sets exist after migration " + protSet.getLabel()); } else { protSetNames.add(protSet.getLabel()); // verify that there are no duplicates or stale volumes on the volume list List<String> volumeIds = new ArrayList<String>(); for (String volId : protSet.getVolumes()) { Volume vol = _dbClient.queryObject(Volume.class, URI.create(volId)); if (vol == null || vol.getInactive()) { // fail stale volume on protection set Assert.fail( String.format( "Stale volume %s exists on protection set %s exist after migration", volId, protSet.getLabel())); } else if (volumeIds.contains(volId)) { // fail duplicate volume on protection set Assert.fail( String.format( "Duplicate volume %s exists on protection set %s exist after migration", volId, protSet.getLabel())); } else if (vol.getProtectionSet() == null || vol.getProtectionSet().getURI() == null || !vol.getProtectionSet().getURI().equals(protSet.getId())) { // fail volume does not point back to protection set Assert.fail( String.format( "Volume %s does not point back to protection set %s exist after migration", volId, protSet.getLabel())); } else { volumeIds.add(volId); } } } } // make sure there are no dangling protection sets on volumes List<URI> volumes = _dbClient.queryByType(Volume.class, true); for (URI id : volumes) { Volume vol = _dbClient.queryObject(Volume.class, id); if (vol.getProtectionSet() != null && vol.getProtectionSet().getURI() != null) { ProtectionSet protSet = _dbClient.queryObject(ProtectionSet.class, vol.getProtectionSet().getURI()); if (protSet == null || protSet.getInactive()) { // fail dangling protection set Assert.fail( String.format( "Stale protection set %s on volume %s exists after migration", vol.getProtectionSet().getURI(), id)); } } } // make sure there are no dangling protection sets on snapshots List<URI> snapshots = _dbClient.queryByType(BlockSnapshot.class, true); for (URI id : snapshots) { BlockSnapshot snapshot = _dbClient.queryObject(BlockSnapshot.class, id); if (snapshot.getProtectionSet() != null) { ProtectionSet protSet = _dbClient.queryObject(ProtectionSet.class, snapshot.getProtectionSet()); if (protSet == null || protSet.getInactive()) { // fail dangling protection set Assert.fail( String.format( "Stale protection set %s on snapshot %s exists after migration", snapshot.getProtectionSet(), id)); } } } }
private void processVolumes( CloseableIterator<CIMInstance> volumeInstances, Map<String, Object> keyMap) throws IOException { List<CIMObjectPath> metaVolumes = new ArrayList<>(); while (volumeInstances.hasNext()) { CIMInstance volumeViewInstance = volumeInstances.next(); String nativeGuid = getVolumeViewNativeGuid(volumeViewInstance.getObjectPath(), keyMap); if (isSnapShot(volumeViewInstance)) { BlockSnapshot snapShot = checkSnapShotExistsInDB(nativeGuid, _dbClient); if (null == snapShot || snapShot.getInactive()) { _logger.debug("Skipping Snapshot, as its not being managed in Bourne"); continue; } updateBlockSnapShot(volumeViewInstance, snapShot, keyMap); if (_updateSnapShots.size() > BATCH_SIZE) { _partitionManager.updateInBatches( _updateSnapShots, getPartitionSize(keyMap), _dbClient, BLOCK_SNAPSHOT); _updateSnapShots.clear(); } } else if (isMirror(volumeViewInstance)) { BlockMirror mirror = checkBlockMirrorExistsInDB(nativeGuid, _dbClient); if (null == mirror || mirror.getInactive()) { _logger.debug("Skipping Mirror, as its not being managed in Bourne"); continue; } updateBlockMirror(volumeViewInstance, mirror, keyMap); if (_updateMirrors.size() > BATCH_SIZE) { _partitionManager.updateInBatches( _updateMirrors, getPartitionSize(keyMap), _dbClient, BLOCK_MIRROR); _updateMirrors.clear(); } } else { Volume storageVolume = checkStorageVolumeExistsInDB(nativeGuid, _dbClient); if (null == storageVolume || storageVolume.getInactive()) { continue; } _logger.debug("Volume managed by Bourne :" + storageVolume.getNativeGuid()); updateStorageVolume(volumeViewInstance, storageVolume, keyMap); // Check if this is a meta volume and if we need to set missing meta volume related // properties. // This is applicable for meta volumes discovered as unmanaged volumes and ingested prior to // vipr controller 2.2 . if (storageVolume.getIsComposite() && (storageVolume.getCompositionType() == null || storageVolume.getCompositionType().isEmpty())) { // meta volume is missing meta related data. Need to discover this data and set in the // volume. metaVolumes.add(volumeViewInstance.getObjectPath()); _logger.info( "Found meta volume in vipr with missing data: {}, name: {}", volumeViewInstance.getObjectPath(), storageVolume.getLabel()); } } if (_updateVolumes.size() > BATCH_SIZE) { _partitionManager.updateInBatches( _updateVolumes, getPartitionSize(keyMap), _dbClient, VOLUME); _updateVolumes.clear(); } } // Add meta volumes to the keyMap try { if (metaVolumes != null && !metaVolumes.isEmpty()) { _metaVolumeViewPaths.addAll(metaVolumes); _logger.info("Added {} meta volumes.", metaVolumes.size()); } } catch (Exception ex) { _logger.error("Processing meta volumes.", ex); } }