@Override
 public void process() {
   DbClient dbClient = getDbClient();
   List<URI> volumeURIs = dbClient.queryByType(Volume.class, false);
   Iterator<Volume> volumesIter = dbClient.queryIterativeObjects(Volume.class, volumeURIs);
   while (volumesIter.hasNext()) {
     Volume volume = volumesIter.next();
     URI systemURI = volume.getStorageController();
     if (!NullColumnValueGetter.isNullURI(systemURI)) {
       StorageSystem system = dbClient.queryObject(StorageSystem.class, systemURI);
       if ((system != null)
           && (DiscoveredDataObject.Type.vplex.name().equals(system.getSystemType()))) {
         // This is a VPLEX volume. If not already set,
         // set the protocols to FC.
         StringSet protocols = volume.getProtocol();
         if (protocols == null) {
           protocols = new StringSet();
           protocols.add(StorageProtocol.Block.FC.name());
           volume.setProtocol(protocols);
           dbClient.persistObject(volume);
         }
       }
     }
   }
 }
 @Override
 protected void setProtocol(StoragePool pool, Volume volume, VirtualPool vPool) {
   if (null == volume.getProtocol()) {
     volume.setProtocol(new StringSet());
   }
   volume.getProtocol().addAll(vPool.getProtocols());
 }
  /** {@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();
          }
        }
      }
    }
  }
 /**
  * Validate the Target Volume VirtualArray with the Source Volume VPool VirtualArray.
  *
  * @param type
  * @param unManagedVolume
  * @param virtualArray
  */
 private void validateTargetVolumeVpoolWithSourceVolume(
     UnManagedVolume unManagedVolume, VirtualArray virtualArray) {
   String sourceUnManagedVolumeId =
       PropertySetterUtil.extractValueFromStringSet(
           SupportedVolumeInformation.REMOTE_MIRROR_SOURCE_VOLUME.toString(),
           unManagedVolume.getVolumeInformation());
   String sourceVolumeId =
       sourceUnManagedVolumeId.replace(
           VolumeIngestionUtil.UNMANAGEDVOLUME, VolumeIngestionUtil.VOLUME);
   List<URI> sourceUris =
       _dbClient.queryByConstraint(
           AlternateIdConstraint.Factory.getVolumeNativeGuidConstraint(sourceVolumeId));
   if (sourceUris.isEmpty()) {
     _logger.info(
         "Source {} Not found for target {}", sourceVolumeId, unManagedVolume.getNativeGuid());
   } else {
     // if source volume is ingested, then
     Volume sourceVolume = _dbClient.queryObject(Volume.class, sourceUris.get(0));
     // check whether the source Volume's VPool is actually having this
     // target Volume's varray
     // specified as remote
     VirtualPool sourceVPool =
         _dbClient.queryObject(VirtualPool.class, sourceVolume.getVirtualPool());
     Map<URI, VpoolRemoteCopyProtectionSettings> settings =
         sourceVPool.getRemoteProtectionSettings(sourceVPool, _dbClient);
     if (null == settings || settings.isEmpty() || !settings.containsKey(virtualArray.getId())) {
       _logger.info(
           "Target Volume's VArray {} is not matching already ingested source volume virtual pool's remote VArray ",
           virtualArray.getId());
       throw IngestionException.exceptions.unmanagedSRDFTargetVolumeVArrayMismatch(
           unManagedVolume.getLabel(), sourceVolume.getVirtualArray().toString());
     }
   }
 }
 /**
  * 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;
 }
 /**
  * Validate the SourceVolume VArray details with ingested target volumes VArray.
  *
  * @param unManagedVolume
  * @param VirtualPool
  * @return
  */
 private void validateSourceVolumeVarrayWithTargetVPool(
     UnManagedVolume unManagedVolume, VirtualPool sourceVPool) {
   StringSetMap unManagedVolumeInformation = unManagedVolume.getVolumeInformation();
   // find whether all targets are ingested
   StringSet targetUnManagedVolumeGuids =
       unManagedVolumeInformation.get(SupportedVolumeInformation.REMOTE_MIRRORS.toString());
   if (null != targetUnManagedVolumeGuids && !targetUnManagedVolumeGuids.isEmpty()) {
     StringSet targetVolumeNativeGuids =
         VolumeIngestionUtil.getListofVolumeIds(targetUnManagedVolumeGuids);
     // check whether target exists
     List<URI> targetUris = VolumeIngestionUtil.getVolumeUris(targetVolumeNativeGuids, _dbClient);
     if (null == targetUris || targetUris.isEmpty()) {
       _logger.info(
           "None of the targets ingested for source volume: {}", unManagedVolume.getNativeGuid());
     } else {
       List<Volume> targetVolumes = _dbClient.queryObject(Volume.class, targetUris);
       for (Volume targetVolume : targetVolumes) {
         Map<URI, VpoolRemoteCopyProtectionSettings> settings =
             sourceVPool.getRemoteProtectionSettings(sourceVPool, _dbClient);
         if (null == settings
             || settings.size() == 0
             || !settings.containsKey(targetVolume.getVirtualArray())) {
           _logger.info(
               "Target Volume's VArray {} is not matching already ingested source volume virtual pool's remote VArray {}",
               targetVolume.getVirtualArray(),
               Joiner.on(",").join(settings.keySet()));
           throw IngestionException.exceptions.unmanagedSRDFSourceVolumeVArrayMismatch(
               unManagedVolume.getLabel(), targetVolume.getVirtualArray().toString());
         }
       }
     }
   }
 }
  /**
   * Verify the RP+VPlex consistency group and its volumes have been properly migrated.
   *
   * @throws Exception
   */
  private void verifyRpVplexConsistencyGroupMigration() throws Exception {
    log.info("Verifying RP+VPlex BlockConsistencyGroup and associated volume migration.");
    List<BlockObject> blockObjects = new ArrayList<BlockObject>();

    BlockConsistencyGroup rpVplexPrimaryCg =
        _dbClient.queryObject(BlockConsistencyGroup.class, rpVplexPrimaryConsistencyGroupURI);

    // Verify the RP+VPLEX consistency group was properly migrated
    verifyConsistencyGroupMigration(rpVplexPrimaryCg, Types.RP.name(), Types.VPLEX.name());

    Assert.assertNotNull(
        "The RP+VPlex BlockConsistencyGroup.systemConsistencyGroups field should be populated.",
        rpVplexPrimaryCg.getSystemConsistencyGroups());
    Assert.assertNotNull(
        "The RP+VPlex BlockConsistencyGroup.systemConsistencyGroups field should contain an entry for "
            + protectionSystemURI.toString(),
        rpVplexPrimaryCg.getSystemConsistencyGroups().get(protectionSystemURI.toString()));
    Assert.assertTrue(
        "The RP+VPlex BlockConsistencyGroup.systemConsistencyGroups field should contain a mapping for "
            + protectionSystemURI.toString()
            + "-> ViPR-"
            + rpVplexPrimaryCg.getLabel(),
        rpVplexPrimaryCg
            .getSystemConsistencyGroups()
            .get(protectionSystemURI.toString())
            .contains("ViPR-" + rpVplexPrimaryCg.getLabel()));

    // Verify that primary CG has a mapping reference for each of the VPlex storage system/cg name.
    for (URI rpVplexVolumeId : rpVplexVolumeToCgMapping.keySet()) {
      Volume rpVplexVolume = _dbClient.queryObject(Volume.class, rpVplexVolumeId);
      blockObjects.add(rpVplexVolume);

      // Get the VPlex consistency group
      URI cgUri = rpVplexVolumeToCgMapping.get(rpVplexVolumeId);
      BlockConsistencyGroup vplexCg = _dbClient.queryObject(BlockConsistencyGroup.class, cgUri);

      String cgName = vplexCg.getLabel();
      String clusterName = getVPlexClusterFromVolume(rpVplexVolume);
      String storageSystem = rpVplexVolume.getStorageController().toString();
      String clusterCgName = BlockConsistencyGroupUtils.buildClusterCgName(clusterName, cgName);

      // Verify that primary CG contains the correct mapping
      Assert.assertTrue(
          "The RP+VPlex BlockConsistencyGroup.systemConsistencyGroups field should contain a mapping for "
              + storageSystem
              + "->"
              + clusterCgName,
          rpVplexPrimaryCg.getSystemConsistencyGroups().get(storageSystem).contains(clusterCgName));

      // Verify that the VPlex CG has been marked for deletion
      Assert.assertTrue(
          "The VPlex BlockConsistencyGroup " + vplexCg.getLabel() + "should be inactive.",
          vplexCg.getInactive());
    }

    // Verify the volume migration took place correctly
    verifyBlockObjects(blockObjects);
  }
 /**
  * Remove application from the volume applicationIds attribute
  *
  * @param voluri The volumes that will be updated
  * @param dbClient
  */
 protected void removeApplicationFromVolume(URI voluri, DbClient dbClient) {
   Volume volume = dbClient.queryObject(Volume.class, voluri);
   String appId = getId().toString();
   StringSet appIds = volume.getVolumeGroupIds();
   if (appIds != null) {
     appIds.remove(appId);
   }
   dbClient.updateObject(volume);
 }
 /**
  * Convenience method that adds volumes to a protection set.
  *
  * @param protectionSetURI
  * @param volumes
  */
 private void addVolumesToProtectionSet(URI protectionSetURI, List<Volume> volumes) {
   ProtectionSet protectionSet = _dbClient.queryObject(ProtectionSet.class, protectionSetURI);
   StringSet vols = new StringSet();
   for (Volume volume : volumes) {
     vols.add(volume.getId().toString());
   }
   protectionSet.setVolumes(vols);
   _dbClient.persistObject(protectionSet);
 }
  /**
   * Gets the VPlex cluster Id for a given VPlex virtual volume.
   *
   * @param virtualVolume
   * @return
   */
  private String getVPlexClusterFromVolume(Volume virtualVolume) {
    String clusterId = null;

    if (virtualVolume != null && virtualVolume.getNativeId() != null) {
      String[] nativeIdSplit = virtualVolume.getNativeId().split("/");
      clusterId = nativeIdSplit[2];
    }

    return clusterId;
  }
 /*
  * (non-Javadoc)
  *
  * @see com.emc.storageos.volumecontroller.CloneOperations#detachSingleClone(
  * com.emc.storageos.db.client.model.StorageSystem,
  * java.net.URI,
  * com.emc.storageos.volumecontroller.TaskCompleter)
  */
 @Override
 public void detachSingleClone(
     StorageSystem storageSystem, URI cloneVolume, TaskCompleter taskCompleter) {
   // Not Supported
   Volume clone = dbClient.queryObject(Volume.class, cloneVolume);
   clone.setAssociatedSourceVolume(NullColumnValueGetter.getNullURI());
   clone.setReplicaState(ReplicationState.DETACHED.name());
   dbClient.persistObject(clone);
   taskCompleter.ready(dbClient);
 }
  /*
   * (non-Javadoc)
   *
   * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExpandVolume(com.emc.storageos.db.client.model.StorageSystem,
   * com.emc.storageos.db.client.model.StoragePool, com.emc.storageos.db.client.model.Volume, java.lang.Long,
   * com.emc.storageos.volumecontroller.TaskCompleter)
   */
  @Override
  public void doExpandVolume(
      StorageSystem storageSystem,
      StoragePool storagePool,
      Volume volume,
      Long size,
      TaskCompleter taskCompleter)
      throws DeviceControllerException {

    log.info(
        String.format(
            "Expand Volume Start - Array: %s, Pool: %s, Volume: %s, New size: %d",
            storageSystem.getSerialNumber(), storagePool.getNativeGuid(), volume.getLabel(), size));
    try {
      HDSApiClient hdsApiClient =
          hdsApiFactory.getClient(
              HDSUtils.getHDSServerManagementServerInfo(storageSystem),
              storageSystem.getSmisUserName(),
              storageSystem.getSmisPassword());
      String systemObjectID = HDSUtils.getSystemObjectID(storageSystem);
      String asyncTaskMessageId = null;

      if (volume.getThinlyProvisioned()) {
        asyncTaskMessageId =
            hdsApiClient.modifyThinVolume(
                systemObjectID,
                HDSUtils.getLogicalUnitObjectId(volume.getNativeId(), storageSystem),
                size);
      }

      if (null != asyncTaskMessageId) {
        HDSJob expandVolumeJob =
            new HDSVolumeExpandJob(
                asyncTaskMessageId,
                storageSystem.getId(),
                storagePool.getId(),
                taskCompleter,
                "ExpandVolume");
        ControllerServiceImpl.enqueueJob(new QueueJob(expandVolumeJob));
      }
    } catch (final InternalException e) {
      log.error("Problem in doExpandVolume: ", e);
      taskCompleter.error(dbClient, e);
    } catch (final Exception e) {
      log.error("Problem in doExpandVolume: ", e);
      ServiceError serviceError =
          DeviceControllerErrors.hds.methodFailed("doExpandVolume", e.getMessage());
      taskCompleter.error(dbClient, serviceError);
    }
    log.info(
        String.format(
            "Expand Volume End - Array: %s, Pool: %s, Volume: %s",
            storageSystem.getSerialNumber(), storagePool.getNativeGuid(), volume.getLabel()));
  }
 @Override
 protected Volume.VolumeAccessState getVolumeAccessStateForSuccess(Volume v) {
   if (!NullColumnValueGetter.isNullValue(v.getSrdfCopyMode())
       && Mode.ACTIVE.equals(Mode.valueOf(v.getSrdfCopyMode()))
       && v.getPersonality().equals(Volume.PersonalityTypes.TARGET.toString())) {
     // For Active mode target access state is always updated from the provider
     // after each operation so just use that.
     return Volume.VolumeAccessState.getVolumeAccessState(v.getAccessState());
   } else {
     return Volume.VolumeAccessState.READWRITE;
   }
 }
  private void handleBlockVolumeErrors(DbClient dbClient) {
    for (VolumeDescriptor volumeDescriptor :
        VolumeDescriptor.getDescriptors(_volumeDescriptors, VolumeDescriptor.Type.BLOCK_DATA)) {

      Volume volume = dbClient.queryObject(Volume.class, volumeDescriptor.getVolumeURI());

      if (volume != null && (volume.getNativeId() == null || volume.getNativeId().equals(""))) {
        _log.info("No native id was present on volume {}, marking inactive", volume.getLabel());
        dbClient.markForDeletion(volume);
      }
    }
  }
  /*
   * (non-Javadoc)
   *
   * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExpandAsMetaVolume(com.emc.storageos.db.client.model.StorageSystem,
   * com.emc.storageos.db.client.model.StoragePool, com.emc.storageos.db.client.model.Volume, long,
   * com.emc.storageos.volumecontroller.impl.smis.MetaVolumeRecommendation, com.emc.storageos.volumecontroller.TaskCompleter)
   */
  @Override
  public void doExpandAsMetaVolume(
      StorageSystem storageSystem,
      StoragePool storagePool,
      Volume metaHead,
      long size,
      MetaVolumeRecommendation recommendation,
      VolumeExpandCompleter volumeCompleter)
      throws DeviceControllerException {
    StringBuilder logMsgBuilder =
        new StringBuilder(
            String.format(
                "Expand Meta Volume Start - Array:%s, Pool:%s %n Volume: %s, id: %s",
                storageSystem.getSerialNumber(),
                storagePool.getNativeId(),
                metaHead.getLabel(),
                metaHead.getId()));
    log.info(logMsgBuilder.toString());
    long metaMemberCapacity = recommendation.getMetaMemberSize();
    int metaMemberCount = (int) recommendation.getMetaMemberCount();
    MetaVolumeTaskCompleter metaVolumeTaskCompleter = new MetaVolumeTaskCompleter(volumeCompleter);
    try {
      // Step 1: create meta members.
      List<String> newMetaMembers =
          metaVolumeOperations.createMetaVolumeMembers(
              storageSystem,
              storagePool,
              metaHead,
              metaMemberCount,
              metaMemberCapacity,
              metaVolumeTaskCompleter);
      log.info("ldevMetaMembers created successfully: {}", newMetaMembers);

      if (metaVolumeTaskCompleter.getLastStepStatus() == Job.JobStatus.SUCCESS) {
        metaVolumeOperations.expandMetaVolume(
            storageSystem, storagePool, metaHead, newMetaMembers, metaVolumeTaskCompleter);
      } else {
        ServiceError serviceError =
            DeviceControllerErrors.hds.jobFailed("LDEV Meta Member creation failed");
        volumeCompleter.error(dbClient, serviceError);
      }

    } catch (final InternalException e) {
      log.error("Problem in doExpandAsMetaVolume: ", e);
      volumeCompleter.error(dbClient, e);
    } catch (final Exception e) {
      log.error("Problem in doExpandAsMetaVolume: ", e);
      ServiceError serviceError =
          DeviceControllerErrors.hds.methodFailed("doExpandAsMetaVolume", e.getMessage());
      volumeCompleter.error(dbClient, serviceError);
    }
  }
  /**
   * Detaches volumes from initiators.
   *
   * @param storage the storage
   * @param volumes the volumes
   * @param initiators the initiators
   * @throws Exception the exception
   */
  private void detachVolumesFromInitiators(
      StorageSystem storage, List<Volume> volumes, List<Initiator> initiators) throws Exception {
    CinderEndPointInfo ep = CinderUtils.getCinderEndPoint(storage.getActiveProviderURI(), dbClient);
    log.debug("Getting the cinder APi for the provider with id {}", storage.getActiveProviderURI());
    CinderApi cinderApi = cinderApiFactory.getApi(storage.getActiveProviderURI(), ep);

    List<Initiator> iSCSIInitiators = new ArrayList<Initiator>();
    List<Initiator> fcInitiators = new ArrayList<Initiator>();
    splitInitiatorsByProtocol(initiators, iSCSIInitiators, fcInitiators);
    String host = getHostNameFromInitiators(initiators);

    Map<String, String[]> mapSettingVsValues = getFCInitiatorsArray(fcInitiators);
    String[] fcInitiatorsWwpns = mapSettingVsValues.get(WWPNS);
    String[] fcInitiatorsWwnns = mapSettingVsValues.get(WWNNS);

    for (Volume volume : volumes) {
      // cinder generated volume ID
      String volumeId = volume.getNativeId();

      // for iSCSI
      for (Initiator initiator : iSCSIInitiators) {
        String initiatorPort = initiator.getInitiatorPort();
        log.debug(
            String.format(
                "Detaching volume %s ( %s ) from initiator %s on Openstack cinder node",
                volumeId, volume.getId(), initiatorPort));
        cinderApi.detachVolume(volumeId, initiatorPort, null, null, host);

        // TODO : Do not use Job to poll status till we figure out how
        // to get detach status.
        /*
         * CinderJob detachJob = new CinderDetachVolumeJob(volumeId,
         * volume.getLabel(), storage.getId(),
         * CinderConstants.ComponentType.volume.name(), ep,
         * taskCompleter); ControllerServiceImpl.enqueueJob(new
         * QueueJob(detachJob));
         */
      }

      // for FC
      if (fcInitiatorsWwpns.length > 0) {
        log.debug(
            String.format(
                "Detaching volume %s ( %s ) from initiator %s on Openstack cinder node",
                volumeId, volume.getId(), fcInitiatorsWwpns));
        cinderApi.detachVolume(volumeId, null, fcInitiatorsWwpns, fcInitiatorsWwnns, host);
      }

      // If ITLs are added, remove them
      removeITLsFromVolume(volume);
    }
  }
  /**
   * Return the rdfGroupId based on the personality. For source volume, we will not have RDFGroup
   * hence we should get it from its targets.
   *
   * @param unManagedVolumeInformation
   * @return
   */
  private URI getRDFGroupBasedOnPersonality(StringSetMap unManagedVolumeInformation) {
    String type =
        PropertySetterUtil.extractValueFromStringSet(
            SupportedVolumeInformation.REMOTE_VOLUME_TYPE.toString(), unManagedVolumeInformation);
    URI rdfGroupId = null;
    if (RemoteMirrorObject.Types.SOURCE.toString().equalsIgnoreCase(type)) {
      StringSet targetUnManagedVolumeGuids =
          unManagedVolumeInformation.get(SupportedVolumeInformation.REMOTE_MIRRORS.toString());
      if (null != targetUnManagedVolumeGuids && !targetUnManagedVolumeGuids.isEmpty()) {
        StringSet targetVolumeNativeGuids =
            VolumeIngestionUtil.getListofVolumeIds(targetUnManagedVolumeGuids);
        List<URI> targetUris =
            VolumeIngestionUtil.getVolumeUris(targetVolumeNativeGuids, _dbClient);
        if (null == targetUris || targetUris.isEmpty()) {
          List<URI> unmanagedTargetVolumes =
              VolumeIngestionUtil.getUnManagedVolumeUris(targetUnManagedVolumeGuids, _dbClient);
          for (URI targetUmv : unmanagedTargetVolumes) {
            _logger.info("RDFGroup Found using unmanaged Target volume {}", targetUmv);
            UnManagedVolume umv = _dbClient.queryObject(UnManagedVolume.class, targetUmv);
            rdfGroupId =
                URI.create(
                    PropertySetterUtil.extractValueFromStringSet(
                        SupportedVolumeInformation.REMOTE_MIRROR_RDF_GROUP.toString(),
                        umv.getVolumeInformation()));
            break;
          }
        } else {
          // If targets are already ingested.
          List<Volume> targetVolumes = _dbClient.queryObject(Volume.class, targetUris);
          if (null != targetVolumes && !targetVolumes.isEmpty()) {
            for (Volume targetVolume : targetVolumes) {
              _logger.info(
                  "RDFGroup Found for using ingested Target volumes {}.",
                  targetVolume.getNativeGuid());
              rdfGroupId = targetVolume.getSrdfGroup();
              break;
            }
          }
        }
      }

    } else if (RemoteMirrorObject.Types.TARGET.toString().equalsIgnoreCase(type)) {
      rdfGroupId =
          URI.create(
              PropertySetterUtil.extractValueFromStringSet(
                  SupportedVolumeInformation.REMOTE_MIRROR_RDF_GROUP.toString(),
                  unManagedVolumeInformation));
    }

    return rdfGroupId;
  }
  /**
   * Add the application to the volume applicationIds attribute
   *
   * @param voluri The volume that will be updated
   * @param dbClient
   */
  protected void addApplicationToVolume(URI voluri, DbClient dbClient) {
    Volume volume = dbClient.queryObject(Volume.class, voluri);
    StringSet applications = volume.getVolumeGroupIds();
    if (applications == null) {
      applications = new StringSet();
    }
    applications.add(getId().toString());
    volume.setVolumeGroupIds(applications);
    dbClient.updateObject(volume);

    // handle clones
    StringSet fullCopies = volume.getFullCopies();
    List<Volume> fullCopiesToUpdate = new ArrayList<Volume>();
    if (fullCopies != null && !fullCopies.isEmpty()) {
      for (String fullCopyId : fullCopies) {
        Volume fullCopy = dbClient.queryObject(Volume.class, URI.create(fullCopyId));
        if (fullCopy != null && NullColumnValueGetter.isNullValue(fullCopy.getFullCopySetName())) {
          fullCopy.setFullCopySetName(fullCopy.getReplicationGroupInstance());
          fullCopiesToUpdate.add(fullCopy);
        }
      }
    }

    if (!fullCopiesToUpdate.isEmpty()) {
      dbClient.updateObject(fullCopiesToUpdate);
    }
  }
  /**
   * Create Initiator Target LUN Mapping as an extension in volume object
   *
   * @param volume - volume in which ITL to be added
   * @param exportMask - exportMask in which the volume is to be added
   * @param targetLunId - integer value of host LUN id on which volume is accessible.
   */
  private void storeITLMappingInVolume(
      Map<URI, Integer> volumeToTargetLunMap, ExportMask exportMask) {
    log.debug("START - createITLMappingInVolume");
    for (URI volumeURI : volumeToTargetLunMap.keySet()) {
      Integer targetLunId = volumeToTargetLunMap.get(volumeURI);
      Volume volume = dbClient.queryObject(Volume.class, volumeURI);

      StringSetMap zoningMap = exportMask.getZoningMap();
      Set<String> zoningMapKeys = zoningMap.keySet();
      int initiatorIndex = 0;
      for (String initiator : zoningMapKeys) {
        Initiator initiatorObj = dbClient.queryObject(Initiator.class, URI.create(initiator));
        String initiatorWWPN =
            initiatorObj.getInitiatorPort().replaceAll(CinderConstants.COLON, "");
        StringSet targetPorts = zoningMap.get(initiator);
        int targetIndex = 0;
        for (String target : targetPorts) {
          StoragePort targetPort = dbClient.queryObject(StoragePort.class, URI.create(target));
          String targetPortWWN =
              targetPort.getPortNetworkId().replaceAll(CinderConstants.COLON, "");

          // Format is - <InitiatorWWPN>-<TargetWWPN>-<LunId>
          String itl = initiatorWWPN + "-" + targetPortWWN + "-" + String.valueOf(targetLunId);

          // ITL keys will be formed as ITL-00, ITL-01, ITL-10, ITL-11 so on
          String itlKey =
              CinderConstants.PREFIX_ITL
                  + String.valueOf(initiatorIndex)
                  + String.valueOf(targetIndex);
          log.info(String.format("Adding ITL %s with key %s", itl, itlKey));
          StringMap extensionsMap = volume.getExtensions();
          if (null == extensionsMap) {
            extensionsMap = new StringMap();
            extensionsMap.put(itlKey, itl);
            volume.setExtensions(extensionsMap);
          } else {
            volume.getExtensions().put(itlKey, itl);
          }

          targetIndex++;
        }

        initiatorIndex++;
      }

      dbClient.updateAndReindexObject(volume);
    }

    log.debug("END - createITLMappingInVolume");
  }
  /**
   * Convenience method that creates the BlockObject Volume data.
   *
   * @param volumeName
   * @param numTargets
   */
  private List<Volume> createBlockVolumes(String volumeName, int numVolumes, URI storageSystem) {
    List<Volume> volumes = new ArrayList<Volume>();
    for (int i = 1; i <= numVolumes; i++) {
      Volume volume = new Volume();
      URI volumeURI = URIUtil.createId(Volume.class);
      blockVolumeURIs.add(volumeURI);
      volume.setId(volumeURI);
      volume.setLabel(volumeName + i);
      volume.setStorageController(storageSystem);
      _dbClient.createObject(volume);
      volumes.add(volume);
    }

    return volumes;
  }
  public void vcenterClusterCreateDatastoreOperation(
      URI vcenterId,
      URI vcenterDataCenterId,
      URI clusterId,
      URI volumeId,
      String selectHostStepId,
      String stepId) {
    VcenterApiClient vcenterApiClient = null;
    try {
      WorkflowStepCompleter.stepExecuting(stepId);

      URI hostId = (URI) _workflowService.loadStepData(selectHostStepId);
      if (hostId == null) {
        _log.error("Workflow loadStepData on " + selectHostStepId + " is null");
        throw new Exception("Workflow loadStepData on " + selectHostStepId + " is null");
      }

      VcenterDataCenter vcenterDataCenter =
          _dbClient.queryObject(VcenterDataCenter.class, vcenterDataCenterId);
      Cluster cluster = _dbClient.queryObject(Cluster.class, clusterId);
      Vcenter vcenter = _dbClient.queryObject(Vcenter.class, vcenterId);
      Host host = _dbClient.queryObject(Host.class, hostId);
      Volume volume = _dbClient.queryObject(Volume.class, volumeId);

      vcenterApiClient = new VcenterApiClient(_coordinator.getPropertyInfo());
      vcenterApiClient.setup(vcenter.getIpAddress(), vcenter.getUsername(), vcenter.getPassword());
      String key =
          vcenterApiClient.createDatastore(
              vcenterDataCenter.getLabel(),
              cluster.getExternalId(),
              host.getHostName(),
              volume.getWWN(),
              volume.getLabel());
      _log.info("Successfully created or located datastore " + volume.getLabel() + " " + key);

      host.setVcenterDataCenter(vcenterDataCenter.getId());
      _dbClient.updateAndReindexObject(host);

      WorkflowStepCompleter.stepSucceded(stepId);
    } catch (Exception e) {
      _log.error("vcenterClusterCreateDatastoreOperation exception " + e);
      WorkflowStepCompleter.stepFailed(
          stepId, VcenterControllerException.exceptions.hostException(e.getLocalizedMessage(), e));
    } finally {
      if (vcenterApiClient != null) vcenterApiClient.destroy();
    }
  }
  /** {@inheritDoc} */
  @Override
  public VolumeRestRep checkProgress(URI sourceURI, Volume fullCopyVolume) {
    // Get the native backend full copy volume for this VPLEX
    // full copy volume.
    Volume nativeFullCopyVolume = VPlexUtil.getVPLEXBackendVolume(fullCopyVolume, true, _dbClient);

    // Call super to check the progress of the backend full
    // copy volume.
    Integer percentSynced =
        getSyncPercentage(nativeFullCopyVolume.getAssociatedSourceVolume(), nativeFullCopyVolume);

    // The synchronization progress of the VPLEX full copy is that
    // of the backend full copy.
    VolumeRestRep volumeRestRep = BlockMapper.map(_dbClient, fullCopyVolume);
    volumeRestRep.getProtection().getFullCopyRep().setPercentSynced(percentSynced);
    return volumeRestRep;
  }
  private void updateStorageVolume(
      CIMInstance volumeInstance, Volume storageVolume, Map<String, Object> keyMap)
      throws IOException {
    storageVolume.setAllocatedCapacity(
        Long.parseLong(getCIMPropertyValue(volumeInstance, EMC_ALLOCATED_CAPACITY)));
    storageVolume.setProvisionedCapacity(returnProvisionedCapacity(volumeInstance, keyMap));

    // If meta volume was ingested prior to upgrade to 2.2 it won't have
    // 'isComposite' set. We need to check
    // cim instance here to see if the volume is meta volume and set it in
    // the volume instance.
    if (isComposite(volumeInstance) && !storageVolume.getIsComposite()) {
      storageVolume.setIsComposite(true);
      _logger.info("Set volume {} to composite (meta volume)", storageVolume.getId());
    }
    _updateVolumes.add(storageVolume);
  }
  /** {@inheritDoc} */
  @Override
  public void validateFullCopyCreateRequest(List<BlockObject> fcSourceObjList, int count) {
    if (fcSourceObjList.size() > 0) {
      URI fcSourceObjURI = fcSourceObjList.get(0).getId();
      if (URIUtil.isType(fcSourceObjURI, BlockSnapshot.class)) {
        // Currently you cannot create a full copy of a VPLEX snapshot.
        throw APIException.badRequests.cantCreateFullCopyForVPlexSnapshot();
      } else {
        // Call super first.
        super.validateFullCopyCreateRequest(fcSourceObjList, count);

        // Platform specific checks.
        for (BlockObject fcSourceObj : fcSourceObjList) {
          Volume fcSourceVolume = (Volume) fcSourceObj;
          StorageSystem system =
              _dbClient.queryObject(StorageSystem.class, fcSourceVolume.getStorageController());
          if (DiscoveredDataObject.Type.vplex.name().equals(system.getSystemType())) {
            // If the volume is a VPLEX volume, then we need to be sure that
            // storage pool of the source backend volume of the VPLEX volume,
            // which is volume used to create the native full copy, supports
            // full copy.
            Volume srcBackendVolume =
                VPlexUtil.getVPLEXBackendVolume(fcSourceVolume, true, _dbClient, true);
            StoragePool storagePool =
                _dbClient.queryObject(StoragePool.class, srcBackendVolume.getPool());
            verifyFullCopySupportedForStoragePool(storagePool);

            // If the full copy source is itself a full copy, it is not
            // detached, and the native full copy i.e., the source side
            // backend volume, is VNX, then creating a full copy of the
            // volume will fail. As such, we prevent it.
            if ((BlockFullCopyUtils.isVolumeFullCopy(fcSourceVolume, _dbClient))
                && (!BlockFullCopyUtils.isFullCopyDetached(fcSourceVolume, _dbClient))) {
              URI backendSystemURI = srcBackendVolume.getStorageController();
              StorageSystem backendSystem =
                  _dbClient.queryObject(StorageSystem.class, backendSystemURI);
              if (DiscoveredDataObject.Type.vnxblock.name().equals(backendSystem.getSystemType())) {
                throw APIException.badRequests.cantCreateFullCopyOfVPlexFullCopyUsingVNX();
              }
            }
          }
        }
      }
    }
  }
 @Override
 public void injectColumnsDetails(Stat statObj, DbClient client) throws Exception {
   ProtectionSystem protectionObj =
       client.queryObject(ProtectionSystem.class, statObj.getResourceId());
   // Given a protection system, find a volume protected by this protection system,
   // and then extract the project and vpool
   Volume protectedVolume = null;
   URIQueryResultList resultList = new URIQueryResultList();
   client.queryByConstraint(
       ContainmentConstraint.Factory.getProtectionSystemVolumesConstraint(protectionObj.getId()),
       resultList);
   for (Iterator<URI> volumeItr = resultList.iterator(); volumeItr.hasNext(); ) {
     Volume volume = client.queryObject(Volume.class, volumeItr.next());
     if (volume.getProtectionController().equals(protectionObj.getId())) {
       protectedVolume = volume;
       break;
     }
   }
   if (protectedVolume != null) {
     _logger.info(
         "Found volume "
             + protectedVolume.getWWN()
             + " protected by this protection controller.  Get the Cos/Project/Tenant.");
     statObj.setProject(protectedVolume.getProject().getURI());
     statObj.setVirtualPool(protectedVolume.getVirtualPool());
     statObj.setTenant(protectedVolume.getTenant().getURI());
   } else {
     statObj.setProject(null);
     statObj.setVirtualPool(null);
     statObj.setTenant(null);
     throw new SMIPluginException(
         "Cassandra Database Insertion Error.  Cannot identify Project/CoS/Tenant for ProtectionSystem",
         -1);
   }
 }
 /**
  * Remove the list of ITLs from the volume extensions
  *
  * @param volume
  * @return
  */
 private void removeITLsFromVolume(Volume volume) {
   StringMap extensions = volume.getExtensions();
   Set<Map.Entry<String, String>> mapEntries = extensions.entrySet();
   for (Iterator<Map.Entry<String, String>> it = mapEntries.iterator(); it.hasNext(); ) {
     Map.Entry<String, String> entry = it.next();
     if (entry.getKey().startsWith(CinderConstants.PREFIX_ITL)) {
       it.remove();
     }
   }
 }
  @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);
    }
  }
  /**
   * Verify the VPlex consistency group and its volumes have been properly migrated.
   *
   * @throws Exception
   */
  private void verifyVplexConsistencyGroupMigration() throws Exception {
    log.info("Verifying VPlex BlockConsistencyGroup and associated volume migration.");

    BlockConsistencyGroup vplexCg =
        _dbClient.queryObject(BlockConsistencyGroup.class, vplexConsistencyGroupURI);
    Iterator<Volume> vplexVolumeItr =
        _dbClient.queryIterativeObjects(Volume.class, vplexVolumeURIs);

    // Verify the VPLEX consistency group was properly migrated
    verifyConsistencyGroupMigration(vplexCg, Types.VPLEX.name());

    while (vplexVolumeItr.hasNext()) {
      Volume vplexVolume = vplexVolumeItr.next();
      // Get the VPlex consistency group
      String cgName = vplexCg.getLabel();
      String clusterName = getVPlexClusterFromVolume(vplexVolume);
      String storageSystem = vplexVolume.getStorageController().toString();
      String clusterCgName = BlockConsistencyGroupUtils.buildClusterCgName(clusterName, cgName);

      // Verify that primary CG contains the correct mapping
      Assert.assertNotNull(
          "The VPlex BlockConsistencyGroup.vplexStorageSystemToCg field should be populated.",
          vplexCg.getSystemConsistencyGroups());
      Assert.assertTrue(
          "The VPlex BlockConsistencyGroup.vplexStorageSystemToCg should contain a key for storage system "
              + storageSystem,
          vplexCg.getSystemConsistencyGroups().containsKey(storageSystem));
      Assert.assertTrue(
          "The VPlex BlockConsistencyGroup.vplexStorageSystemToCg field should contain a mapping for "
              + storageSystem
              + "->"
              + clusterCgName,
          vplexCg.getSystemConsistencyGroups().get(storageSystem).contains(clusterCgName));
    }

    // Verify the volume migration took place correctly
    List<BlockObject> blockObjects = new ArrayList<BlockObject>();
    while (vplexVolumeItr.hasNext()) {
      blockObjects.add(vplexVolumeItr.next());
    }

    verifyBlockObjects(blockObjects);
  }
  /*
   * (non-Javadoc)
   *
   * @see
   * com.emc.storageos.volumecontroller.BlockStorageDevice#doWaitForSynchronized
   * (java.lang.Class, com.emc.storageos.db.client.model.StorageSystem,
   * java.net.URI, com.emc.storageos.volumecontroller.TaskCompleter)
   */
  @Override
  public void doWaitForSynchronized(
      Class<? extends BlockObject> clazz,
      StorageSystem storageObj,
      URI target,
      TaskCompleter completer) {
    log.info("START waitForSynchronized for {}", target);

    try {
      Volume targetObj = dbClient.queryObject(Volume.class, target);
      // Source could be either Volume or BlockSnapshot
      BlockObject sourceObj = BlockObject.fetch(dbClient, targetObj.getAssociatedSourceVolume());

      // We split the pair which causes the data to be synchronized.
      // When the split is complete that data is synchronized.
      HDSApiClient hdsApiClient =
          hdsApiFactory.getClient(
              HDSUtils.getHDSServerManagementServerInfo(storageObj),
              storageObj.getSmisUserName(),
              storageObj.getSmisPassword());
      HDSApiProtectionManager hdsApiProtectionManager = hdsApiClient.getHdsApiProtectionManager();
      String replicationGroupObjectID = hdsApiProtectionManager.getReplicationGroupObjectId();
      ReplicationInfo replicationInfo =
          hdsApiProtectionManager.getReplicationInfoFromSystem(
                  sourceObj.getNativeId(), targetObj.getNativeId())
              .first;
      hdsApiProtectionManager.modifyShadowImagePair(
          replicationGroupObjectID,
          replicationInfo.getObjectID(),
          HDSApiProtectionManager.ShadowImageOperationType.split);

      // Update state in case we are waiting for synchronization
      // after creation of a new full copy that was not created
      // inactive.
      String state = targetObj.getReplicaState();
      if (!ReplicationState.SYNCHRONIZED.name().equals(state)) {
        targetObj.setSyncActive(true);
        targetObj.setReplicaState(ReplicationState.SYNCHRONIZED.name());
        dbClient.persistObject(targetObj);
      }

      // Queue job to wait for replication status to move to split.
      ControllerServiceImpl.enqueueJob(
          new QueueJob(
              new HDSReplicationSyncJob(
                  storageObj.getId(),
                  sourceObj.getNativeId(),
                  targetObj.getNativeId(),
                  ReplicationStatus.SPLIT,
                  completer)));
    } catch (Exception e) {
      log.error("Exception occurred while waiting for synchronization", e);
      ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
      completer.error(dbClient, serviceError);
    }
    log.info("completed doWaitForSynchronized");
  }
  /** Create RP BlockConsistencyGroup objects for each ProtectionSet. */
  private void createRpBlockConsistencyGroups() {
    DbClient dbClient = this.getDbClient();
    List<URI> protectionSetURIs = dbClient.queryByType(ProtectionSet.class, false);

    Iterator<ProtectionSet> protectionSets =
        dbClient.queryIterativeObjects(ProtectionSet.class, protectionSetURIs);

    while (protectionSets.hasNext()) {
      ProtectionSet ps = protectionSets.next();
      Project project = dbClient.queryObject(Project.class, ps.getProject());

      BlockConsistencyGroup cg = new BlockConsistencyGroup();
      cg.setId(URIUtil.createId(BlockConsistencyGroup.class));
      cg.setLabel(ps.getLabel());
      cg.setDeviceName(ps.getLabel());
      cg.setType(BlockConsistencyGroup.Types.RP.toString());
      cg.setProject(new NamedURI(project.getId(), ps.getLabel()));
      cg.setTenant(new NamedURI(project.getTenantOrg().getURI(), ps.getLabel()));

      dbClient.createObject(cg);

      log.debug(
          "Created ConsistencyGroup (id={}) based on ProtectionSet (id={})",
          cg.getId().toString(),
          ps.getId().toString());

      // Organize the volumes by replication set
      for (String protectionVolumeID : ps.getVolumes()) {
        URI uri = URI.create(protectionVolumeID);
        Volume protectionVolume = dbClient.queryObject(Volume.class, uri);
        protectionVolume.addConsistencyGroup(cg.getId().toString());

        dbClient.persistObject(protectionVolume);

        log.debug(
            "Volume (id={}) added to ConsistencyGroup (id={})",
            protectionVolume.getId().toString(),
            cg.getId().toString());
      }
    }
  }