@Override public void deleteSingleVolumeSnapshot( StorageSystem storage, URI snapshot, TaskCompleter taskCompleter) throws DeviceControllerException { try { BlockSnapshot snap = _dbClient.queryObject(BlockSnapshot.class, snapshot); VNXeApiClient apiClient = getVnxeClient(storage); VNXeLunSnap lunSnap = apiClient.getLunSnapshot(snap.getNativeId()); if (lunSnap != null) { VNXeCommandJob job = apiClient.deleteLunSnap(lunSnap.getId()); if (job != null) { ControllerServiceImpl.enqueueJob( new QueueJob( new VNXeBlockDeleteSnapshotJob(job.getId(), storage.getId(), taskCompleter))); } } else { // Perhaps, it's already been deleted or was deleted on the array. // In that case, we'll just say all is well, so that this operation // is idempotent. snap.setInactive(true); snap.setIsSyncActive(false); _dbClient.updateObject(snap); taskCompleter.ready(_dbClient); } } catch (VNXeException e) { _log.error("Delete volume snapshot got the exception", e); taskCompleter.error(_dbClient, e); } catch (Exception ex) { _log.error("Delete volume snapshot got the exception", ex); ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteSnapshot", ex.getMessage()); taskCompleter.error(_dbClient, error); } }
/** * Prepare the ViPR BlockSnapshotSession instance for the pass BlockSnapshot instance. * * @param snapshot A reference to the snapshot. * @return A reference to the newly created snapshot session. */ private BlockSnapshotSession prepareSnapshotSession(BlockSnapshot snapshot) { s_logger.info("Prepare BlockSnapshotSession for snapshot {}", snapshot.getId()); BlockSnapshotSession snapshotSession = new BlockSnapshotSession(); URI snapSessionURI = URIUtil.createId(BlockSnapshotSession.class); snapshotSession.setId(snapSessionURI); snapshotSession.setSessionLabel(getSessionLabelFromSettingsInstance(snapshot)); URI cgURI = snapshot.getConsistencyGroup(); if (NullColumnValueGetter.isNullURI(cgURI)) { snapshotSession.setParent(snapshot.getParent()); snapshotSession.setLabel(snapshot.getLabel()); } else { snapshotSession.setConsistencyGroup(cgURI); snapshotSession.setLabel(snapshot.getSnapsetLabel()); Volume parent = getDbClient().queryObject(Volume.class, snapshot.getParent()); if (parent != null) { snapshotSession.setReplicationGroupInstance(parent.getReplicationGroupInstance()); snapshotSession.setSessionSetName(parent.getReplicationGroupInstance()); } } snapshotSession.setProject(snapshot.getProject()); snapshotSession.setStorageController(snapshot.getStorageController()); snapshotSession.setSessionInstance(snapshot.getSettingsInstance()); StringSet linkedTargets = new StringSet(); linkedTargets.add(snapshot.getId().toString()); snapshotSession.setLinkedTargets(linkedTargets); return snapshotSession; }
private void updateBlockSnapShot( CIMInstance volumeInstance, BlockSnapshot snapShot, Map<String, Object> keyMap) { snapShot.setAllocatedCapacity( Long.parseLong(getCIMPropertyValue(volumeInstance, EMC_ALLOCATED_CAPACITY))); snapShot.setProvisionedCapacity(returnProvisionedCapacity(volumeInstance, keyMap)); _updateSnapShots.add(snapShot); }
/** {@inheritDoc} */ @Override public void process() throws MigrationCallbackException { s_logger.info("Executing BlockSnapshotSession migration callback."); try { DbClient dbClient = getDbClient(); List<BlockSnapshotSession> snapshotSessions = new ArrayList<BlockSnapshotSession>(); Map<URI, Map<String, BlockSnapshotSession>> groupSessionMap = new HashMap<>(); List<URI> snapshotURIs = dbClient.queryByType(BlockSnapshot.class, true); Iterator<BlockSnapshot> snapshotsIter = dbClient.queryIterativeObjects(BlockSnapshot.class, snapshotURIs, true); while (snapshotsIter.hasNext()) { BlockSnapshot snapshot = snapshotsIter.next(); if (isSnapshotSessionSupported(snapshot)) { // Check if this is a group snapshot. URI cgURI = snapshot.getConsistencyGroup(); if (NullColumnValueGetter.isNullURI(cgURI)) { // The storage system for the single volume snapshot supports // snapshot sessions, then we need to prepare and create a // snapshot session for that snapshot and add the snapshot as // a linked target for the session. BlockSnapshotSession snapshotSession = prepareSnapshotSession(snapshot); snapshotSessions.add(snapshotSession); } else { // Create the group session if necessary and add the snapshot as a // linked target for that group session. String settingsInstance = snapshot.getSettingsInstance(); Map<String, BlockSnapshotSession> grpSnapshotSessions = groupSessionMap.get(cgURI); if (grpSnapshotSessions != null) { BlockSnapshotSession snapshotSession = grpSnapshotSessions.get(settingsInstance); if (snapshotSession == null) { snapshotSession = prepareSnapshotSession(snapshot); grpSnapshotSessions.put(settingsInstance, snapshotSession); snapshotSessions.add(snapshotSession); } else { StringSet linkedTargets = snapshotSession.getLinkedTargets(); linkedTargets.add(snapshot.getId().toString()); } } else { grpSnapshotSessions = new HashMap<String, BlockSnapshotSession>(); groupSessionMap.put(cgURI, grpSnapshotSessions); BlockSnapshotSession snapshotSession = prepareSnapshotSession(snapshot); grpSnapshotSessions.put(settingsInstance, snapshotSession); snapshotSessions.add(snapshotSession); } } } } if (!snapshotSessions.isEmpty()) { dbClient.createObject(snapshotSessions); } } catch (Exception e) { s_logger.error("Caught exception during BlockSnapshotSession migration", e); } }
/** * Determines if the storage system for the passed BlockSnapshot instance supports snapshot * sessions. * * @param snapshot A reference to the snapshot. * @return true if the system for the passed snapshot supports snapshot sessions, false otherwise. */ private boolean isSnapshotSessionSupported(BlockSnapshot snapshot) { boolean isSupported = false; URI systemURI = snapshot.getStorageController(); StorageSystem system = dbClient.queryObject(StorageSystem.class, systemURI); if ((system != null) && (system.checkIfVmax3())) { s_logger.info( "BlockSnapshotSession supported for snapshot {}:{}", snapshot.getId(), snapshot.getLabel()); isSupported = true; } return isSupported; }
/** * Gets the session label from settings instance. * * @param snapshot the snapshot * @return the session label from settings instance */ private String getSessionLabelFromSettingsInstance(BlockSnapshot snapshot) { String sessionLabel = null; String settingsInstance = snapshot.getSettingsInstance(); if (settingsInstance != null && !settingsInstance.isEmpty()) { String[] instanceArray = settingsInstance.split(SMIS80_DELIMITER_REGEX); sessionLabel = instanceArray[3]; } return sessionLabel; }
@Override public void createGroupSnapshots( StorageSystem storage, List<URI> snapshotList, Boolean createInactive, Boolean readOnly, TaskCompleter taskCompleter) throws DeviceControllerException { try { URI snapshot = snapshotList.get(0); BlockSnapshot snapshotObj = _dbClient.queryObject(BlockSnapshot.class, snapshot); Volume volume = _dbClient.queryObject(Volume.class, snapshotObj.getParent()); TenantOrg tenant = _dbClient.queryObject(TenantOrg.class, volume.getTenant().getURI()); String tenantName = tenant.getLabel(); String snapLabelToUse = _nameGenerator.generate( tenantName, snapshotObj.getLabel(), snapshot.toString(), '-', SmisConstants.MAX_SNAPSHOT_NAME_LENGTH); String groupName = getConsistencyGroupName(snapshotObj); VNXeApiClient apiClient = getVnxeClient(storage); VNXeCommandJob job = apiClient.createLunGroupSnap(groupName, snapLabelToUse); if (job != null) { ControllerServiceImpl.enqueueJob( new QueueJob( new VNXeBlockCreateCGSnapshotJob( job.getId(), storage.getId(), !createInactive, taskCompleter))); } } catch (VNXeException e) { _log.error("Create volume snapshot got the exception", e); taskCompleter.error(_dbClient, e); } catch (Exception ex) { _log.error("Create volume snapshot got the exception", ex); ServiceError error = DeviceControllerErrors.vnxe.jobFailed("CreateCGSnapshot", ex.getMessage()); taskCompleter.error(_dbClient, error); } }
/** * Cleans up instances of {@link BlockSnapshot} that failed to be created. Also, any stale entries * in {@link BlockSnapshotSession#getLinkedTargets()} will be cleaned up. * * @param volume Volume URI to process. * @param itemsToUpdate Items to be updated. * @param itemsToDelete Items to be deleted. */ @Override public void process( URI volume, Collection<DataObject> itemsToUpdate, Collection<DataObject> itemsToDelete) { List<BlockSnapshot> snapshots = CustomQueryUtility.queryActiveResourcesByConstraint( getDbClient(), BlockSnapshot.class, ContainmentConstraint.Factory.getVolumeSnapshotConstraint(volume)); List<BlockSnapshot> failedSnapshots = new ArrayList<>(); List<BlockSnapshotSession> updateSessions = new ArrayList<>(); failedSnapshots.addAll( Collections2.filter( snapshots, new Predicate<BlockSnapshot>() { @Override public boolean apply(BlockSnapshot snapshot) { return Strings.isNullOrEmpty(snapshot.getNativeId()); } })); // Removed failed snapshots from any existing sessions for (BlockSnapshot failedSnapshot : failedSnapshots) { log.info("Removing failed snapshot: {}", failedSnapshot.getLabel()); List<BlockSnapshotSession> sessions = CustomQueryUtility.queryActiveResourcesByConstraint( getDbClient(), BlockSnapshotSession.class, ContainmentConstraint.Factory.getLinkedTargetSnapshotSessionConstraint( failedSnapshot.getId())); for (BlockSnapshotSession session : sessions) { log.info("Updating existing session: {}", session.getSessionLabel()); StringSet linkedTargets = session.getLinkedTargets(); linkedTargets.remove(failedSnapshot.getId().toString()); updateSessions.add(session); } } itemsToUpdate.addAll(updateSessions); itemsToDelete.addAll(failedSnapshots); }
/** * Creates the BlockObject BlockSnapshot data. * * @param name * @param numSnapshots * @throws Exception */ private void prepareBlockSnapshotData(String name, int numSnapshots) throws Exception { // Create the volume for the snapshots Volume volume = new Volume(); URI volumeURI = URIUtil.createId(Volume.class); StorageSystem storageSystem = createStorageSystem(false); volume.setId(volumeURI); volume.setStorageController(storageSystem.getId()); String volName = "blockSnapshotVolume"; volume.setLabel(volName); BlockConsistencyGroup cg = createBlockConsistencyGroup( "blockSnapshotConsistencyGroup", storageSystem.getId(), Types.LOCAL.name(), true); volume.setConsistencyGroup(cg.getId()); _dbClient.createObject(volume); for (int i = 1; i <= numSnapshots; i++) { BlockSnapshot blockSnapshot = new BlockSnapshot(); URI blockSnapshotURI = URIUtil.createId(BlockSnapshot.class); blockSnapshotURIs.add(blockSnapshotURI); blockSnapshot.setId(blockSnapshotURI); blockSnapshot.setLabel(name + i); blockSnapshot.setSnapsetLabel(name + i); blockSnapshot.setParent(new NamedURI(volume.getId(), name + i)); blockSnapshot.addConsistencyGroup(cg.getId().toString()); _dbClient.createObject(blockSnapshot); } }
@Override public void restoreGroupSnapshots( StorageSystem storage, URI volume, URI snapshot, TaskCompleter taskCompleter) throws DeviceControllerException { try { BlockSnapshot snapshotObj = _dbClient.queryObject(BlockSnapshot.class, snapshot); VNXeApiClient apiClient = getVnxeClient(storage); VNXeLunGroupSnap lunGroupSnap = apiClient.getLunGroupSnapshot(snapshotObj.getReplicationGroupInstance()); // Error out if the snapshot is attached if (lunGroupSnap.getIsAttached()) { _log.error( "Snapshot {})is attached and cannot be used for restore", snapshotObj.getLabel()); ServiceError error = DeviceControllerErrors.vnxe.cannotRestoreAttachedSnapshot(snapshot.toString()); taskCompleter.error(_dbClient, error); } VNXeCommandJob job = apiClient.restoreLunGroupSnap(lunGroupSnap.getId()); if (job != null) { ControllerServiceImpl.enqueueJob( new QueueJob( new VNXeBlockRestoreSnapshotJob(job.getId(), storage.getId(), taskCompleter))); } } catch (VNXeException e) { _log.error("Restore group snapshot got the exception", e); taskCompleter.error(_dbClient, e); } catch (Exception ex) { _log.error("Restore group snapshot got the exception", ex); ServiceError error = DeviceControllerErrors.vnxe.jobFailed("RestoreSnapshotJob", ex.getMessage()); taskCompleter.error(_dbClient, error); } }
/** * creates snapshot objects * * @param numSnapshots * @param volume * @param name snapshot name */ public void addSnapshots( int numSnapshots, Volume volume, BlockConsistencyGroup cg, ProtectionSet ps, String name) { for (int i = 1; i <= numSnapshots; i++) { BlockSnapshot blockSnapshot = new BlockSnapshot(); URI blockSnapshotURI = URIUtil.createId(BlockSnapshot.class); blockSnapshotURIs.add(blockSnapshotURI); blockSnapshot.setId(blockSnapshotURI); blockSnapshot.setLabel(name + i); blockSnapshot.setSnapsetLabel(name + i); blockSnapshot.setParent(new NamedURI(volume.getId(), name + i)); blockSnapshot.addConsistencyGroup(cg.getId().toString()); blockSnapshot.setProtectionSet(ps.getId()); _dbClient.createObject(blockSnapshot); } }
@Override public void deleteGroupSnapshots(StorageSystem storage, URI snapshot, TaskCompleter taskCompleter) throws DeviceControllerException { try { List<BlockSnapshot> snapshots = _dbClient.queryObject(BlockSnapshot.class, Arrays.asList(snapshot)); BlockSnapshot snapshotObj = snapshots.get(0); VNXeApiClient apiClient = getVnxeClient(storage); VNXeLunGroupSnap lunGroupSnap = apiClient.getLunGroupSnapshot(snapshotObj.getReplicationGroupInstance()); if (lunGroupSnap != null) { VNXeCommandJob job = apiClient.deleteLunGroupSnap(lunGroupSnap.getId()); if (job != null) { ControllerServiceImpl.enqueueJob( new QueueJob( new VNXeBlockDeleteSnapshotJob(job.getId(), storage.getId(), taskCompleter))); } else { // Should not take this path, but treat as an error if we do // happen to get a null job due to some error in the client. _log.error("Unexpected null job from VNXe client call to delete group snapshot."); ServiceCoded sc = DeviceControllerExceptions.vnxe.nullJobForDeleteGroupSnapshot( snapshotObj.forDisplay(), snapshotObj.getReplicationGroupInstance()); taskCompleter.error(_dbClient, sc); } } else { // Treat as in the single volume snapshot case and presume // the group snapshot has already been deleted. List<BlockSnapshot> grpSnapshots = ControllerUtils.getSnapshotsPartOfReplicationGroup(snapshotObj, _dbClient); for (BlockSnapshot grpSnapshot : grpSnapshots) { grpSnapshot.setInactive(true); grpSnapshot.setIsSyncActive(false); } _dbClient.updateObject(grpSnapshots); taskCompleter.ready(_dbClient); } } catch (VNXeException e) { _log.error("Delete group snapshot got the exception", e); taskCompleter.error(_dbClient, e); } catch (Exception ex) { _log.error("Delete group snapshot got the exception", ex); ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeletGroupSnapshot", ex.getMessage()); taskCompleter.error(_dbClient, error); } }
/** {@inheritDoc} */ @Override public void updateStatus(JobContext jobContext) throws Exception { JobStatus jobStatus = getJobStatus(); CloseableIterator<CIMObjectPath> volumeIter = null; try { DbClient dbClient = jobContext.getDbClient(); TaskCompleter completer = getTaskCompleter(); BlockSnapshot snapshot = dbClient.queryObject(BlockSnapshot.class, _snapshotURI); if (jobStatus == JobStatus.IN_PROGRESS) { return; } if (jobStatus == JobStatus.SUCCESS) { s_logger.info( "Post-processing successful link snapshot session target {} for task {}", snapshot.getId(), completer.getOpId()); // Get the snapshot session to which the target is being linked. BlockSnapshotSession snapSession = dbClient.queryObject(BlockSnapshotSession.class, completer.getId()); // Get the snapshot device ID and set it against the BlockSnapshot object. BlockObject sourceObj = BlockObject.fetch(dbClient, snapshot.getParent().getURI()); CIMConnectionFactory cimConnectionFactory = jobContext.getCimConnectionFactory(); WBEMClient client = getWBEMClient(dbClient, cimConnectionFactory); volumeIter = client.associatorNames(getCimJob(), null, SmisConstants.CIM_STORAGE_VOLUME, null, null); while (volumeIter.hasNext()) { // Get the sync volume native device id CIMObjectPath volumePath = volumeIter.next(); s_logger.info("volumePath: {}", volumePath.toString()); CIMInstance volume = client.getInstance(volumePath, false, false, null); String volumeDeviceId = volumePath.getKey(SmisConstants.CP_DEVICE_ID).getValue().toString(); s_logger.info("volumeDeviceId: {}", volumeDeviceId); if (volumeDeviceId.equals(sourceObj.getNativeId())) { // Don't want the source, we want the linked target. continue; } String volumeElementName = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_ELEMENT_NAME); s_logger.info("volumeElementName: {}", volumeElementName); String volumeWWN = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_WWN_NAME); s_logger.info("volumeWWN: {}", volumeWWN); String volumeAltName = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_NAME); s_logger.info("volumeAltName: {}", volumeAltName); StorageSystem system = dbClient.queryObject(StorageSystem.class, getStorageSystemURI()); snapshot.setNativeId(volumeDeviceId); snapshot.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(system, snapshot)); snapshot.setDeviceLabel(volumeElementName); snapshot.setInactive(false); snapshot.setIsSyncActive(Boolean.TRUE); snapshot.setCreationTime(Calendar.getInstance()); snapshot.setWWN(volumeWWN.toUpperCase()); snapshot.setAlternateName(volumeAltName); snapshot.setSettingsInstance(snapSession.getSessionInstance()); commonSnapshotUpdate( snapshot, volume, client, system, sourceObj.getNativeId(), volumeDeviceId, false, dbClient); s_logger.info( String.format( "For target volume path %1$s, going to set blocksnapshot %2$s nativeId to %3$s (%4$s). Associated volume is %5$s (%6$s)", volumePath.toString(), snapshot.getId().toString(), volumeDeviceId, volumeElementName, sourceObj.getNativeId(), sourceObj.getDeviceLabel())); dbClient.updateObject(snapshot); } } else if (jobStatus == JobStatus.FAILED || jobStatus == JobStatus.FATAL_ERROR) { s_logger.info( "Failed to link snapshot session target {} for task {}", snapshot.getId(), completer.getOpId()); snapshot.setInactive(true); dbClient.updateObject(snapshot); } } catch (Exception e) { setPostProcessingErrorStatus( "Encountered an internal error in link snapshot session target job status processing: " + e.getMessage()); s_logger.error( "Encountered an internal error in link snapshot session target job status processing", e); } finally { if (volumeIter != null) { volumeIter.close(); } super.updateStatus(jobContext); } }
/** * 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); } }