@Override
  public void createOrAddVolumesToExportMask(
      URI arrayURI,
      URI exportGroupURI,
      URI exportMaskURI,
      Map<URI, Integer> volumeMap,
      List<URI> initiatorURIs2,
      TaskCompleter completer,
      String stepId) {
    try {
      StorageSystem array = _dbClient.queryObject(StorageSystem.class, arrayURI);
      ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
      WorkflowStepCompleter.stepExecuting(stepId);

      // If the exportMask isn't found, or has been deleted, fail, ask user to retry.
      if (exportMask == null || exportMask.getInactive()) {
        _log.info(String.format("ExportMask %s deleted or inactive, failing", exportMaskURI));
        ServiceError svcerr =
            VPlexApiException.errors.createBackendExportMaskDeleted(
                exportMaskURI.toString(), arrayURI.toString());
        WorkflowStepCompleter.stepFailed(stepId, svcerr);
        return;
      }

      // Protect concurrent operations by locking {host, array} dupple.
      // Lock will be released when workflow step completes.
      List<String> lockKeys =
          ControllerLockingUtil.getHostStorageLockKeys(
              _dbClient,
              ExportGroupType.Host,
              StringSetUtil.stringSetToUriList(exportMask.getInitiators()),
              arrayURI);
      getWorkflowService()
          .acquireWorkflowStepLocks(
              stepId, lockKeys, LockTimeoutValue.get(LockType.VPLEX_BACKEND_EXPORT));

      // Fetch the Initiators
      List<URI> initiatorURIs = new ArrayList<URI>();
      List<Initiator> initiators = new ArrayList<Initiator>();
      for (String initiatorId : exportMask.getInitiators()) {
        Initiator initiator = _dbClient.queryObject(Initiator.class, URI.create(initiatorId));
        if (initiator != null) {
          initiators.add(initiator);
          initiatorURIs.add(initiator.getId());
        }
      }

      // We do not refresh here, as the VNXExportOperations code will throw an exception
      // if the StorageGroup was not found.
      BlockStorageDevice device = _blockController.getDevice(array.getSystemType());
      if (!exportMask.hasAnyVolumes() && exportMask.getCreatedBySystem()) {
        // We are creating this ExportMask on the hardware! (Maybe not the first time though...)

        // Fetch the targets
        List<URI> targets = new ArrayList<URI>();
        for (String targetId : exportMask.getStoragePorts()) {
          targets.add(URI.create(targetId));
        }

        // Clear the export_mask nativeId; otherwise the VnxExportOps will attempt to look it
        // up and fail. An empty String will suffice as having no nativeId.
        if (exportMask.getNativeId() != null) {
          exportMask.setNativeId("");
          _dbClient.updateAndReindexObject(exportMask);
        }
        // The default completer passed in is for add volume, create correct one
        completer =
            new ExportMaskCreateCompleter(
                exportGroupURI, exportMaskURI, initiatorURIs, volumeMap, stepId);
        device.doExportCreate(array, exportMask, volumeMap, initiators, targets, completer);
      } else {
        device.doExportAddVolumes(array, exportMask, initiators, volumeMap, completer);
      }
    } catch (Exception ex) {
      _log.error("Failed to create or add volumes to export mask for vnx: ", ex);
      VPlexApiException vplexex =
          DeviceControllerExceptions.vplex.addStepsForCreateVolumesFailed(ex);
      WorkflowStepCompleter.stepFailed(stepId, vplexex);
    }
  }
  @Override
  public void createOrAddVolumesToExportMask(
      URI arrayURI,
      URI exportGroupURI,
      URI exportMaskURI,
      Map<URI, Integer> volumeMap,
      TaskCompleter completer,
      String stepId) {
    _log.debug("START - createOrAddVolumesToExportMask");
    try {
      WorkflowStepCompleter.stepExecuting(stepId);
      StorageSystem array = _dbClient.queryObject(StorageSystem.class, arrayURI);
      ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);

      // If the exportMask isn't found, or has been deleted, fail, ask user to retry.
      if (exportMask == null || exportMask.getInactive()) {
        _log.info(String.format("ExportMask %s deleted or inactive, failing", exportMaskURI));
        ServiceError svcerr =
            VPlexApiException.errors.createBackendExportMaskDeleted(
                exportMaskURI.toString(), arrayURI.toString());
        WorkflowStepCompleter.stepFailed(stepId, svcerr);
        return;
      }

      // Protect concurrent operations by locking {host, array} dupple.
      // Lock will be released when work flow step completes.
      List<String> lockKeys =
          ControllerLockingUtil.getHostStorageLockKeys(
              _dbClient,
              ExportGroupType.Host,
              StringSetUtil.stringSetToUriList(exportMask.getInitiators()),
              arrayURI);
      getWorkflowService()
          .acquireWorkflowStepLocks(
              stepId, lockKeys, LockTimeoutValue.get(LockType.VPLEX_BACKEND_EXPORT));

      // Refresh the ExportMask
      BlockStorageDevice device = _blockController.getDevice(array.getSystemType());

      if (!exportMask.hasAnyVolumes()) {
        /*
         * We are creating this ExportMask on the hardware! (Maybe not
         * the first time though...)
         *
         * Fetch the Initiators
         */
        List<Initiator> initiators = new ArrayList<Initiator>();
        for (String initiatorId : exportMask.getInitiators()) {
          Initiator initiator = _dbClient.queryObject(Initiator.class, URI.create(initiatorId));
          if (initiator != null) {
            initiators.add(initiator);
          }
        }

        // Fetch the targets
        List<URI> targets = new ArrayList<URI>();
        for (String targetId : exportMask.getStoragePorts()) {
          targets.add(URI.create(targetId));
        }

        if (volumeMap != null) {
          for (URI volume : volumeMap.keySet()) {
            exportMask.addVolume(volume, volumeMap.get(volume));
          }
        }

        _dbClient.persistObject(exportMask);

        _log.debug(
            String.format(
                "Calling doExportGroupCreate on the device %s", array.getId().toString()));
        device.doExportGroupCreate(array, exportMask, volumeMap, initiators, targets, completer);
      } else {
        _log.debug(
            String.format("Calling doExportAddVolumes on the device %s", array.getId().toString()));
        device.doExportAddVolumes(array, exportMask, volumeMap, completer);
      }

    } catch (Exception ex) {
      _log.error("Failed to create or add volumes to export mask for cinder: ", ex);
      VPlexApiException vplexex =
          DeviceControllerExceptions.vplex.addStepsForCreateVolumesFailed(ex);
      WorkflowStepCompleter.stepFailed(stepId, vplexex);
    }

    _log.debug("END - createOrAddVolumesToExportMask");
  }