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