/**
   * 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);
    }
  }
  /**
   * Prepare the RecoverPoint only volumes and associated consistency group data.
   *
   * @throws Exception
   */
  private void prepareRPConsistencyGroupDataWithStaleVolumes() throws Exception {
    String cg2Name = "rpCg2";
    // Create the RecoverPoint BlockConsistencyGroup that will be shared by all the
    // RP volumes.
    BlockConsistencyGroup rpCg = createBlockConsistencyGroup(cg2Name, null, Types.RP.name(), true);
    // Save the CG references for migration verification.
    rpConsistencyGroupURI2 = rpCg.getId();

    // Create the ProtectionSet that the RP volumes will belong to.
    ProtectionSet cg2ps = createProtectionSet("rpCg2ProtectionSet", projectURI);

    // Create all the RP volumes
    List<Volume> rpCg2Volumes = createRpVolumes("rpCg2VolumeA", 2, cg2ps, false);
    rpCg2Volumes.addAll(createRpVolumes("rpCg2VolumeB", 2, cg2ps, false));

    // Add the RP volumes to the RP consistency group
    addVolumesToBlockConsistencyGroup(rpCg.getId(), rpCg2Volumes);
    // Add the RP volumes to the protection set
    addVolumesToProtectionSet(cg2ps.getId(), rpCg2Volumes);

    // Add stale volume references
    URI staleVolumeURI1 = URIUtil.createId(Volume.class);
    URI staleVolumeURI2 = URIUtil.createId(Volume.class);

    ProtectionSet ps = _dbClient.queryObject(ProtectionSet.class, cg2ps.getId());
    StringSet vols = ps.getVolumes();
    vols.add(staleVolumeURI1.toString());
    vols.add(staleVolumeURI2.toString());

    staleProtectionSetURI2 = cg2ps.getId();
    staleProtectionSetVolumeURIs.add(staleVolumeURI1.toString());
    staleProtectionSetVolumeURIs.add(staleVolumeURI2.toString());

    _dbClient.persistObject(ps);
  }
  @Test
  public void testPersistObject() throws Exception {
    _logger.info("Starting persist CatalogService test");

    CatalogService model = new CatalogService();
    model.setId(URIUtil.createId(CatalogService.class));
    model.setLabel("foo");
    model.setApprovalRequired(true);
    model.setBaseService("my service");
    URI ewUri = URIUtil.createId(ExecutionWindow.class);
    NamedURI ewId = new NamedURI(ewUri, "ewId");
    model.setDefaultExecutionWindowId(ewId);
    model.setDescription("my desc");
    model.setExecutionWindowRequired(true);
    model.setImage("my image");
    model.setMaxSize(42);
    model.setTitle("my title");

    save(model);
    model = findById(model.getId());

    Assert.assertNotNull(model);
    Assert.assertEquals("foo", model.getLabel());
    Assert.assertEquals(true, model.getApprovalRequired());
    Assert.assertEquals("my service", model.getBaseService());
    Assert.assertEquals(ewId, model.getDefaultExecutionWindowId());
    Assert.assertEquals("my desc", model.getDescription());
    Assert.assertEquals(true, model.getExecutionWindowRequired());
    Assert.assertEquals("my image", model.getImage());
    Assert.assertEquals(new Integer(42), model.getMaxSize());
    Assert.assertEquals("my title", model.getTitle());
  }
 @Before
 public void setup() {
   _context = new ClassPathXmlApplicationContext("metering-vnxfile-context.xml");
   try {
     ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/dbutils-conf.xml");
     _dbClient = (DbClientImpl) ctx.getBean("dbclient");
     _dbClient = Cassandraforplugin.returnDBClient();
     final TenantOrg tenantorg = new TenantOrg();
     tenantorg.setId(URIUtil.createId(TenantOrg.class));
     tenantorg.setLabel("some org");
     tenantorg.setParentTenant(
         new NamedURI(URIUtil.createId(TenantOrg.class), tenantorg.getLabel()));
     _logger.info("TenantOrg :" + tenantorg.getId());
     _dbClient.persistObject(tenantorg);
     final Project proj = new Project();
     proj.setId(URIUtil.createId(Project.class));
     proj.setLabel("some name");
     proj.setTenantOrg(new NamedURI(tenantorg.getId(), proj.getLabel()));
     _logger.info("Project :" + proj.getId());
     _logger.info("TenantOrg-Proj :" + proj.getTenantOrg());
     _dbClient.persistObject(proj);
     final FileShare fileShare = new FileShare();
     fileShare.setId(URIUtil.createId(FileShare.class));
     fileShare.setLabel("some fileshare");
     fileShare.setNativeGuid("CELERRA+" + serialNumber);
     fileShare.setVirtualPool(URIUtil.createId(VirtualPool.class));
     fileShare.setProject(new NamedURI(proj.getId(), fileShare.getLabel()));
     fileShare.setCapacity(12500L);
     _dbClient.persistObject(fileShare);
   } catch (final Exception ioEx) {
     _logger.error("Exception occurred while persisting objects in db {}", ioEx.getMessage());
     _logger.error(ioEx.getMessage(), ioEx);
   }
 }
  /**
   * Prepares and persists the Project/Tenant data.
   *
   * @throws Exception
   */
  private void prepareProjectData() throws Exception {
    TenantOrg tenantOrg = new TenantOrg();
    URI tenantOrgURI = URIUtil.createId(TenantOrg.class);
    tenantOrg.setId(tenantOrgURI);
    _dbClient.createObject(tenantOrg);

    Project proj = new Project();
    projectURI = URIUtil.createId(Project.class);
    String projectLabel = "project";
    proj.setId(projectURI);
    proj.setLabel(projectLabel);
    proj.setTenantOrg(new NamedURI(tenantOrgURI, projectLabel));
    _dbClient.createObject(proj);
  }
  /**
   * Creates the consistency group used by the BlockObjects.
   *
   * @param name
   * @return
   */
  private BlockConsistencyGroup createBlockConsistencyGroup(
      String name, URI storageSystem, String type, boolean setType) {
    BlockConsistencyGroup cg = new BlockConsistencyGroup();
    URI cgURI = URIUtil.createId(BlockConsistencyGroup.class);
    cg.setId(cgURI);
    cg.setLabel(name);
    cg.setStorageController(storageSystem);

    if (type.equals(Types.LOCAL.name())) {
      // Set the 'old' field value so it can be migrated
      cg.setDeviceName("localArrayDeviceName");
    } else if (type.equals(Types.VPLEX.name())) {
      // Set the 'old' field value so it can be migrated
      cg.setDeviceName("vplexDeviceName");
    } else if (type.equals(Types.RP.name())) {
      // Set the 'old' field value so it can be migrated.
      cg.setDeviceName("rpDeviceName");
    } else if (type.equals(Types.SRDF.name())) {
      // Set the 'old' field value so it can be migrated
      cg.setDeviceName("srdfDeviceName");
    }

    if (setType) {
      cg.setType(type);
    }

    // Set the 'old' field value so it can be migrated
    _dbClient.createObject(cg);
    return cg;
  }
  @Override
  protected void prepareData() throws Exception {
    DbClient dbClient = getDbClient();

    ComputeImage image1 = new ComputeImage();
    image1.setId(URIUtil.createId(ComputeImage.class));
    image1.setLabel(IMAGE_NAME_WITH_PWD);
    image1.setImageUrl(urlWithPwd);
    dbClient.createObject(image1);

    ComputeImage image2 = new ComputeImage();
    image2.setId(URIUtil.createId(ComputeImage.class));
    image2.setLabel(IMAGE_NAME_WITHOUT_PWD);
    image2.setImageUrl(urlWithoutPwd);
    dbClient.createObject(image2);
  }
  /**
   * Allocate, initialize and persist state of the Bucket being created.
   *
   * @param param
   * @param project
   * @param tenantOrg
   * @param neighborhood
   * @param vpool
   * @param flags
   * @param placement
   * @return
   */
  private Bucket prepareBucket(
      BucketParam param,
      Project project,
      TenantOrg tenantOrg,
      VirtualArray neighborhood,
      VirtualPool vpool,
      DataObject.Flag[] flags,
      BucketRecommendation placement) {
    _log.debug("Preparing Bucket creation for Param : {}", param);
    StoragePool pool = null;
    Bucket bucket = new Bucket();
    bucket.setId(URIUtil.createId(Bucket.class));
    bucket.setLabel(param.getLabel().replaceAll(SPECIAL_CHAR_REGEX, ""));
    bucket.setHardQuota(SizeUtil.translateSize(param.getHardQuota()));
    bucket.setSoftQuota(SizeUtil.translateSize(param.getSoftQuota()));
    bucket.setRetention(Integer.valueOf(param.getRetention()));
    bucket.setOwner(getOwner(param.getOwner()));
    bucket.setNamespace(tenantOrg.getNamespace());
    bucket.setVirtualPool(param.getVpool());
    if (project != null) {
      bucket.setProject(new NamedURI(project.getId(), bucket.getLabel()));
    }
    bucket.setTenant(new NamedURI(tenantOrg.getId(), param.getLabel()));
    bucket.setVirtualArray(neighborhood.getId());

    if (null != placement.getSourceStoragePool()) {
      pool = _dbClient.queryObject(StoragePool.class, placement.getSourceStoragePool());
      if (null != pool) {
        bucket.setProtocol(new StringSet());
        bucket
            .getProtocol()
            .addAll(
                VirtualPoolUtil.getMatchingProtocols(vpool.getProtocols(), pool.getProtocols()));
      }
    }

    bucket.setStorageDevice(placement.getSourceStorageSystem());
    bucket.setPool(placement.getSourceStoragePool());
    bucket.setOpStatus(new OpStatusMap());

    // Bucket name to be used at Storage System
    String bucketName = project.getLabel() + UNDER_SCORE + param.getLabel();
    bucket.setName(bucketName.replaceAll(SPECIAL_CHAR_REGEX, ""));

    // Update Bucket path
    StringBuilder bucketPath = new StringBuilder();
    bucketPath
        .append(tenantOrg.getNamespace())
        .append(SLASH)
        .append(project.getLabel())
        .append(SLASH)
        .append(param.getLabel());
    bucket.setPath(bucketPath.toString());

    if (flags != null) {
      bucket.addInternalFlags(flags);
    }
    _dbClient.createObject(bucket);
    return bucket;
  }
 /**
  * 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;
 }
 /**
  * Creates a new vCenter data center.
  *
  * @param id the URN of the parent vCenter
  * @param createParam the details of the data center
  * @prereq none
  * @brief Create vCenter data center
  * @return the details of the vCenter data center, including its id and link, when creation
  *     completes successfully.
  * @throws DatabaseException when a database error occurs.
  */
 @POST
 @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 @CheckPermission(roles = {Role.SYSTEM_ADMIN, Role.TENANT_ADMIN})
 @Path("/{id}/vcenter-data-centers")
 public VcenterDataCenterRestRep createVcenterDataCenter(
     @PathParam("id") URI id, VcenterDataCenterCreate createParam) throws DatabaseException {
   Vcenter vcenter = queryObject(Vcenter.class, id, false);
   checkDuplicateChildName(
       id,
       VcenterDataCenter.class,
       DATAOBJECT_NAME_FIELD,
       "vcenter",
       createParam.getName(),
       _dbClient);
   VcenterDataCenter datacenter = new VcenterDataCenter();
   datacenter.setId(URIUtil.createId(VcenterDataCenter.class));
   datacenter.setLabel(createParam.getName());
   datacenter.setVcenter(id);
   if (vcenter.getTenantCreated()) {
     datacenter.setTenant(_permissionsHelper.getTenant(vcenter.getAcls()));
   } else {
     datacenter.setTenant(NullColumnValueGetter.getNullURI());
   }
   _dbClient.createObject(datacenter);
   auditOp(OperationTypeEnum.CREATE_VCENTER_DATACENTER, true, null, datacenter.auditParameters());
   return map(datacenter);
 }
  /**
   * Prepares a ProtectionSet with volume references to volumes that do not exist in the DB.
   *
   * @throws Exception
   */
  private void prepareProtectionSetWithAllStaleVolumes() throws Exception {
    String cgName = "staleVolumeTest";
    ProtectionSet protectionSet = createProtectionSet(cgName, projectURI);
    staleProtectionSetURI = protectionSet.getId();

    URI volumeURI1 = URIUtil.createId(Volume.class);
    URI volumeURI2 = URIUtil.createId(Volume.class);
    URI volumeURI3 = URIUtil.createId(Volume.class);

    StringSet volumes = new StringSet();
    volumes.add(volumeURI1.toString());
    volumes.add(volumeURI2.toString());
    volumes.add(volumeURI3.toString());

    protectionSet.setVolumes(volumes);
    _dbClient.persistObject(protectionSet);
  }
 /**
  * Creates the consistency group used by the BlockObjects.
  *
  * @param name
  * @return
  */
 private BlockConsistencyGroup createBareBlockConsistencyGroup(String name) {
   BlockConsistencyGroup cg = new BlockConsistencyGroup();
   URI cgURI = URIUtil.createId(BlockConsistencyGroup.class);
   emptyCgURI = cgURI;
   cg.setId(cgURI);
   cg.setLabel(name);
   _dbClient.createObject(cg);
   return cg;
 }
  private void createFileShare() {
    // prepare FileShare objects for migration
    FileShare fs = new FileShare();

    fs.setId(URIUtil.createId(FileShare.class));
    fs.setLabel("fileshare test");

    dbClient.createObject(fs);
  }
  /**
   * Convenience method to create a ProtectionSet.
   *
   * @param cgName
   * @param projectURI
   * @return
   * @throws Exception
   */
  private ProtectionSet createProtectionSet(String cgName, URI projectURI) throws Exception {
    ProtectionSet protectionSet = new ProtectionSet();
    URI protectionSetURI = URIUtil.createId(ProtectionSet.class);
    protectionSet.setId(protectionSetURI);
    protectionSet.setLabel("ViPR-" + cgName);
    protectionSet.setProtectionId("790520997");
    protectionSet.setProtectionStatus("ENABLED");
    protectionSet.setProject(projectURI);
    protectionSet.setProtectionSystem(protectionSystemURI);
    _dbClient.createObject(protectionSet);

    return protectionSet;
  }
  @SuppressWarnings("deprecation")
  @Override
  protected void prepareData() throws Exception {

    // Create a virtual array.
    VirtualArray varray = new VirtualArray();
    varrayURI = URIUtil.createId(VirtualArray.class);
    varray.setId(varrayURI);
    _dbClient.createObject(varray);

    // Create a network and set the virtual array.
    Network network = new Network();
    network.setId(URIUtil.createId(Network.class));
    network.setLabel("NetworkWithVarray");
    network.setVirtualArray(varrayURI);
    _dbClient.createObject(network);

    // Create another network without a virtual array.
    network = new Network();
    network.setId(URIUtil.createId(Network.class));
    network.setLabel("NetworkWithoutVArray");
    _dbClient.createObject(network);
  }
 /**
  * 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);
   }
 }
  /**
   * Creates the BlockObject BlockMirror data.
   *
   * @param name
   * @param numBlockMirrors
   * @throws Exception
   */
  private void prepareBlockMirrorData(String name, int numBlockMirrors) throws Exception {
    BlockConsistencyGroup cg =
        createBlockConsistencyGroup("blockMirrorConsistencyGroup", null, Types.LOCAL.name(), true);

    for (int i = 1; i <= numBlockMirrors; i++) {
      BlockMirror blockMirror = new BlockMirror();
      URI blockMirrorURI = URIUtil.createId(BlockMirror.class);
      blockMirrorURIs.add(blockMirrorURI);
      blockMirror.setId(blockMirrorURI);
      blockMirror.setLabel(name + i);
      // Set the 'old' field value so it can be migrated
      blockMirror.addConsistencyGroup(cg.getId().toString());
      _dbClient.createObject(blockMirror);
    }
  }
 private CatalogService createWithLabel(String label) {
   CatalogService model = new CatalogService();
   model.setLabel(label);
   model.setApprovalRequired(true);
   model.setBaseService("my service");
   URI ewUri = URIUtil.createId(ExecutionWindow.class);
   NamedURI ewId = new NamedURI(ewUri, "ewId");
   model.setDefaultExecutionWindowId(ewId);
   model.setDescription("my desc");
   model.setExecutionWindowRequired(true);
   model.setImage("my image");
   model.setMaxSize(42);
   model.setTitle("my title");
   return model;
 }
  /**
   * 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;
  }
  /**
   * Convenience method that creates a StorageSystem.
   *
   * @param isVplex true if a VPlex storage system is to be created, false otherwise.
   * @return
   */
  private StorageSystem createStorageSystem(boolean isVplex) {
    StorageSystem ss = new StorageSystem();
    URI storageSystemId = URIUtil.createId(StorageSystem.class);
    ss.setId(storageSystemId);
    if (isVplex) {
      ss.setLabel("VPLEX+FNM00114300288:FNM00114600001");
      ss.setNativeGuid("VPLEX+FNM00114300288:FNM00114600001");
      ss.setSystemType("vplex");
    } else {
      ss.setLabel("SYMMETRIX+000195701573");
      ss.setNativeGuid("SYMMETRIX+000195701573");
      ss.setSystemType("vmax");
    }

    _dbClient.createObject(ss);

    return ss;
  }
 /**
  * Creates a new instance of vcenter.
  *
  * @param tenant the vcenter parent tenant organization
  * @param param the input parameter containing the vcenter attributes
  * @return an instance of {@link Vcenter}
  */
 protected Vcenter createNewVcenter(TenantOrg tenant, VcenterParam param) {
   Vcenter vcenter = new Vcenter();
   vcenter.setId(URIUtil.createId(Vcenter.class));
   addVcenterAclIfTenantAdmin(tenant, vcenter);
   populateVcenterData(vcenter, param);
   if (isSystemAdmin()) {
     // Since, the creating user is either SysAdmin make the tenantCreated
     // flag to false.
     vcenter.setTenantCreated(Boolean.FALSE);
   } else {
     // Since the creating user is a TenantAdmin, just make the vCenter
     // as a tenant created resource by default. When the SecAdmin or
     // SysAdmin adds any new tenant then the vCenter will be shared
     // across those tenants.
     _log.debug("Tenant admin creates the vCenter {}", param.getName());
     vcenter.setTenantCreated(Boolean.TRUE);
   }
   return vcenter;
 }
  /**
   * Creates an instance of new storage port and associates it with the storage system.
   *
   * @param portNetworkId
   * @param transportType
   */
  private void create(String portNetworkId, String transportType) {
    logger.info(
        "Start create storage port for portNetworkId={}" + " and transportType={}",
        portNetworkId,
        transportType);

    StorageHADomain adapter = CinderUtils.getStorageAdapter(storageSystem, dbClient);

    StoragePort port = new StoragePort();
    port.setId(URIUtil.createId(StoragePort.class));
    port.setStorageDevice(storageSystem.getId());
    String portName = generatePortName();
    logger.debug("New storage port name is = {}", portName);
    String nativeGuid =
        NativeGUIDGenerator.generateNativeGuid(storageSystem, portName, NativeGUIDGenerator.PORT);
    port.setNativeGuid(nativeGuid);
    port.setPortNetworkId(portNetworkId);
    port.setStorageHADomain(adapter.getId());

    port.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.REGISTERED.toString());
    // always treat it as a frontend port
    port.setPortType(PortType.frontend.name());
    port.setOperationalStatus(OperationalStatus.OK.toString());
    port.setTransportType(transportType);
    port.setLabel(portName);
    port.setPortName(portName);
    port.setPortGroup("Cinder-PortGroup");
    port.setCompatibilityStatus(CompatibilityStatus.COMPATIBLE.name());
    port.setDiscoveryStatus(DiscoveryStatus.VISIBLE.name());
    dbClient.createObject(port);

    // Add it to the new ports list
    newStoragePortsList.add(port);

    // Add it to the local list
    allStoragePortsList.add(port);

    logger.info(
        "End create storage port for portNetworkId={}" + " and transportType={}",
        portNetworkId,
        transportType);
  }
  /** 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());
      }
    }
  }
  /**
   * Convenience method that creates VPlex volumes.
   *
   * @param name
   * @param numberOfVols
   * @param storageSystem
   * @return
   */
  private List<Volume> createVPlexVolumes(String name, int numberOfVols, URI storageSystem) {
    List<Volume> volumes = new ArrayList<Volume>();

    for (int i = 1; i <= numberOfVols; i++) {
      Volume vplexVolume = new Volume();
      URI vplexVolumeUri = URIUtil.createId(Volume.class);
      vplexVolumeURIs.add(vplexVolumeUri);
      vplexVolume.setId(vplexVolumeUri);
      vplexVolume.setLabel(name + i);
      vplexVolume.setNativeId(
          "/clusters/cluster-1/virtual-volumes/device_V000195701573-01E7F_vol" + i);
      vplexVolume.setStorageController(storageSystem);

      StringSet associatedVolumes = new StringSet();
      associatedVolumes.add("associatedVol1");
      vplexVolume.setAssociatedVolumes(associatedVolumes);

      volumes.add(vplexVolume);
    }

    return volumes;
  }
  /**
   * create StoragePort Record, if not present already, else update only the properties.
   *
   * @param port
   * @param portInstance
   * @throws URISyntaxException
   * @throws IOException
   */
  private StoragePort createStoragePort(
      StoragePort port,
      CIMInstance portInstance,
      AccessProfile profile,
      StorageHADomain haDomain,
      boolean flag,
      String transportType,
      StorageSystem device)
      throws URISyntaxException, IOException {
    boolean newPort = false;
    if (null == port) {
      newPort = true;
      port = new StoragePort();
      port.setId(URIUtil.createId(StoragePort.class));
      // if true, then its FC Port or else its Ethernet, PORTID
      // or ethernet will be updated later in ProtocolEndPoint Processor
      if (flag) {
        port.setPortNetworkId(
            WWNUtility.getWWNWithColons(getCIMPropertyValue(portInstance, PORTID)));
      }
      port.setStorageDevice(profile.getSystemId());
      String portNativeGuid = NativeGUIDGenerator.generateNativeGuid(_dbClient, port);
      port.setNativeGuid(portNativeGuid);
      port.setLabel(portNativeGuid);
      port.setPortGroup(haDomain.getAdapterName());
      port.setStorageHADomain(haDomain.getId());
    }
    setPortType(port, portInstance);
    port.setTransportType(transportType);
    port.setPortName(getCIMPropertyValue(portInstance, PORTNAME));
    port.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.COMPATIBLE.name());
    port.setDiscoveryStatus(DiscoveredDataObject.DiscoveryStatus.VISIBLE.name());

    UnsignedInteger16[] operationalStatusCodes =
        (UnsignedInteger16[]) portInstance.getPropertyValue(OPERATIONALSTATUS);
    OperationalStatus operationalStatus = getPortOperationalStatus(operationalStatusCodes);
    if (OperationalStatus.NOT_OK.equals(operationalStatus)) {
      _logger.info(
          "StoragePort {} operationalStatus is NOT_OK. operationalStatusCodes collected from SMI-S :{}",
          port.getId(),
          operationalStatusCodes);
    } else {
      _logger.debug("operationalStatusCodes :{}", operationalStatusCodes);

      // there can be multiple statuses. {OK, Online}, {OK, Stopped}
      if (operationalStatusCodes != null
          && operationalStatusCodes.length > 1
          && Arrays.asList(operationalStatusCodes).contains(stopped_code)) {
        _logger.info(
            "StoragePort {} operational status is {OK, Stopped}. operationalStatusCodes :{}",
            port.getId(),
            operationalStatusCodes);
      }
    }
    port.setOperationalStatus(operationalStatus.name());
    String portSpeed = getCIMPropertyValue(portInstance, SPEED);
    if (null != portSpeed) {
      // SMI returns port speed in bits per sec ?? Is this always true?
      Long portSpeedInBitsPerSec = Long.parseLong(portSpeed);
      Long portSpeedInGbps = portSpeedInBitsPerSec / GB;
      port.setPortSpeed(portSpeedInGbps);
    }
    setCompatibilityByACLXFlag(device, portInstance, port);
    if (flag) {
      if (newPort) {
        _logger.info("Creating port - {}:{}", port.getLabel(), port.getNativeGuid());
        _newPortList.add(port);
      } else {
        _logger.info("Updating port - {}:{}", port.getLabel(), port.getNativeGuid());
        _updatePortList.add(port);
      }
    }
    ;
    return port;
  }
  /**
   * create StorageVolume Info Object
   *
   * @param unManagedVolume
   * @param volumeInstance
   * @param unManagedVolumeNativeGuid
   * @param pool
   * @return
   */
  private UnManagedVolume createUnManagedVolume(
      UnManagedVolume unManagedVolume,
      CIMInstance volumeInstance,
      String unManagedVolumeNativeGuid,
      StoragePool pool,
      StorageSystem system,
      String volumeNativeGuid,
      // to make the code uniform, passed in all the below sets as
      // arguments
      Map<String, VolHostIOObject> exportedVolumes,
      Set<String> existingVolumesInCG,
      Map<String, RemoteMirrorObject> volumeToRAGroupMap,
      Map<String, LocalReplicaObject> volumeToLocalReplicaMap,
      Set<String> poolSupportedSLONames,
      Map<String, Object> keyMap) {
    _logger.info("Process UnManagedVolume {}", unManagedVolumeNativeGuid);
    try {
      boolean created = false;
      if (null == unManagedVolume) {
        unManagedVolume = new UnManagedVolume();
        unManagedVolume.setId(URIUtil.createId(UnManagedVolume.class));
        unManagedVolume.setNativeGuid(unManagedVolumeNativeGuid);
        unManagedVolume.setStorageSystemUri(system.getId());
        created = true;
      }

      // reset the auto-tiering info for unmanaged volumes already present
      // in db
      // so that the tiering info is updated correctly later
      if (!created) {
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.AUTO_TIERING_POLICIES.toString(), "");
        unManagedVolume.putVolumeCharacterstics(
            SupportedVolumeCharacterstics.IS_AUTO_TIERING_ENABLED.toString(), "false");

        // reset local replica info
        unManagedVolume.putVolumeCharacterstics(
            SupportedVolumeCharacterstics.IS_FULL_COPY.name(), FALSE);
        unManagedVolume.putVolumeCharacterstics(
            SupportedVolumeCharacterstics.IS_LOCAL_MIRROR.name(), FALSE);
        unManagedVolume.putVolumeCharacterstics(
            SupportedVolumeCharacterstics.IS_SNAP_SHOT.name(), FALSE);
        unManagedVolume.putVolumeCharacterstics(
            SupportedVolumeCharacterstics.HAS_REPLICAS.name(), FALSE);

        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.REPLICA_STATE.name(), new StringSet());

        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.LOCAL_REPLICA_SOURCE_VOLUME.name(), new StringSet());
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.SYNC_STATE.name(), new StringSet());
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.SYNC_TYPE.name(), new StringSet());
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.SYNCHRONIZED_INSTANCE.name(), new StringSet());

        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.IS_SYNC_ACTIVE.name(), new StringSet());
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.NEEDS_COPY_TO_TARGET.name(), new StringSet());
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.TECHNOLOGY_TYPE.name(), new StringSet());
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.SETTINGS_INSTANCE.name(), new StringSet());

        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.FULL_COPIES.name(), new StringSet());
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.MIRRORS.name(), new StringSet());
        unManagedVolume
            .getVolumeInformation()
            .put(SupportedVolumeInformation.SNAPSHOTS.name(), new StringSet());
      }

      Map<String, StringSet> unManagedVolumeInformation = new HashMap<String, StringSet>();
      Map<String, String> unManagedVolumeCharacteristics = new HashMap<String, String>();

      if (null != system) {
        StringSet systemTypes = new StringSet();
        systemTypes.add(system.getSystemType());
        unManagedVolumeInformation.put(
            SupportedVolumeInformation.SYSTEM_TYPE.toString(), systemTypes);
      }

      if (exportedVolumes != null && exportedVolumes.containsKey(volumeNativeGuid)) {
        VolHostIOObject obj = exportedVolumes.get(volumeNativeGuid);
        if (null != obj) {
          StringSet bwValues = new StringSet();
          bwValues.add(obj.getHostIoBw());
          if (unManagedVolumeInformation.get(
                  SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString())
              == null) {
            unManagedVolumeInformation.put(
                SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString(), bwValues);
          } else {
            unManagedVolumeInformation
                .get(SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString())
                .replace(bwValues);
          }

          StringSet iopsVal = new StringSet();
          iopsVal.add(obj.getHostIops());

          if (unManagedVolumeInformation.get(SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString())
              == null) {
            unManagedVolumeInformation.put(
                SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString(), iopsVal);
          } else {
            unManagedVolumeInformation
                .get(SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString())
                .replace(iopsVal);
          }
        }
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_VOLUME_EXPORTED.toString(), TRUE);

      } else {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_VOLUME_EXPORTED.toString(), FALSE);
        StringSet bwValues = new StringSet();
        bwValues.add("0");

        if (unManagedVolumeInformation.get(
                SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString())
            == null) {
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString(), bwValues);
        } else {
          unManagedVolumeInformation
              .get(SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString())
              .replace(bwValues);
        }

        StringSet iopsVal = new StringSet();
        iopsVal.add("0");

        if (unManagedVolumeInformation.get(SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString())
            == null) {
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString(), iopsVal);
        } else {
          unManagedVolumeInformation
              .get(SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString())
              .replace(iopsVal);
        }
      }

      // Set SLOName only for VMAX3 exported volumes
      if (system.checkIfVmax3()) {
        // If there are no slonames defined for a pool or no slo
        // set for a volume, update the tiering_enabled to false.
        if (poolSupportedSLONames.isEmpty() || !keyMap.containsKey(Constants.VOLUMES_WITH_SLOS)) {
          unManagedVolumeCharacteristics.put(
              SupportedVolumeCharacterstics.IS_AUTO_TIERING_ENABLED.toString(),
              Boolean.FALSE.toString());
        } else {
          Map<String, String> volumesWithSLO =
              (Map<String, String>) keyMap.get(Constants.VOLUMES_WITH_SLOS);
          if (volumesWithSLO.containsKey(volumeNativeGuid)) {
            String sloName = volumesWithSLO.get(volumeNativeGuid);
            _logger.debug("formattedSLOName: {}", sloName);
            updateSLOPolicies(
                poolSupportedSLONames,
                unManagedVolumeInformation,
                unManagedVolumeCharacteristics,
                sloName);
          } else {
            unManagedVolumeCharacteristics.put(
                SupportedVolumeCharacterstics.IS_AUTO_TIERING_ENABLED.toString(),
                Boolean.FALSE.toString());
          }
        }
      }

      if (existingVolumesInCG != null && existingVolumesInCG.contains(volumeNativeGuid)) {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_VOLUME_ADDED_TO_CONSISTENCYGROUP.toString(), TRUE);
      } else {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_VOLUME_ADDED_TO_CONSISTENCYGROUP.toString(), FALSE);
      }

      Object raidLevelObj;
      boolean isIngestable;
      String isBound;
      String isThinlyProvisioned;
      String isMetaVolume;
      String allocCapacity;
      // Set the attributes for new smis version.
      if (keyMap.containsKey(Constants.IS_NEW_SMIS_PROVIDER)
          && Boolean.valueOf(keyMap.get(Constants.IS_NEW_SMIS_PROVIDER).toString())) {
        unManagedVolume.setLabel(getCIMPropertyValue(volumeInstance, NAME));
        raidLevelObj =
            volumeInstance.getPropertyValue(
                SupportedVolumeInformation.RAID_LEVEL.getAlternateKey());
        isBound =
            getCIMPropertyValue(
                volumeInstance, SupportedVolumeCharacterstics.IS_BOUND.getAlterCharacterstic());
        isIngestable = isVolumeIngestable(volumeInstance, isBound, USAGE);
        isThinlyProvisioned = getCIMPropertyValue(volumeInstance, THINLY_PROVISIONED);
        isMetaVolume =
            getCIMPropertyValue(
                volumeInstance,
                SupportedVolumeCharacterstics.IS_METAVOLUME.getAlterCharacterstic());
        allocCapacity =
            getAllocatedCapacity(volumeInstance, _volumeToSpaceConsumedMap, system.checkIfVmax3());
      } else {
        unManagedVolume.setLabel(getCIMPropertyValue(volumeInstance, SVELEMENT_NAME));
        isBound =
            getCIMPropertyValue(
                volumeInstance, SupportedVolumeCharacterstics.IS_BOUND.getCharacterstic());
        raidLevelObj =
            volumeInstance.getPropertyValue(SupportedVolumeInformation.RAID_LEVEL.getInfoKey());
        isIngestable = isVolumeIngestable(volumeInstance, isBound, SVUSAGE);
        isThinlyProvisioned = getCIMPropertyValue(volumeInstance, EMC_THINLY_PROVISIONED);
        isMetaVolume =
            getCIMPropertyValue(
                volumeInstance, SupportedVolumeCharacterstics.IS_METAVOLUME.getCharacterstic());
        allocCapacity = getCIMPropertyValue(volumeInstance, EMC_ALLOCATED_CAPACITY);
      }

      if (null != raidLevelObj) {
        StringSet raidLevels = new StringSet();
        raidLevels.add(raidLevelObj.toString());
        unManagedVolumeInformation.put(
            SupportedVolumeInformation.RAID_LEVEL.toString(), raidLevels);
      }

      if (null != isBound) {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_BOUND.toString(), isBound);
      }
      if (null != isThinlyProvisioned) {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_THINLY_PROVISIONED.toString(), isThinlyProvisioned);
      }

      if (null != isMetaVolume) {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_METAVOLUME.toString(), isMetaVolume);
      }

      // only Volumes with Usage 2 can be ingestable, other volumes
      // [SAVE,VAULT...] apart from replicas have usage other than 2
      // Volumes which are set EMCIsBound as false cannot be ingested
      if (isIngestable) {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_INGESTABLE.toString(), TRUE);
      } else {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.IS_INGESTABLE.toString(), FALSE);
      }

      if (volumeToRAGroupMap.containsKey(unManagedVolume.getNativeGuid())) {
        RemoteMirrorObject rmObj = volumeToRAGroupMap.get(unManagedVolume.getNativeGuid());
        _logger.info("Found RA Object {}", rmObj.toString());
        if (RemoteMirrorObject.Types.SOURCE.toString().equalsIgnoreCase(rmObj.getType())) {
          _logger.info("Found Source, updating targets {}", rmObj.getTargetVolumenativeGuids());
          // setting target Volumes
          if (unManagedVolumeInformation.get(SupportedVolumeInformation.REMOTE_MIRRORS.toString())
              == null) {
            unManagedVolumeInformation.put(
                SupportedVolumeInformation.REMOTE_MIRRORS.toString(),
                rmObj.getTargetVolumenativeGuids());
          } else {
            if (null == rmObj.getTargetVolumenativeGuids()
                || rmObj.getTargetVolumenativeGuids().size() == 0) {
              unManagedVolumeInformation
                  .get(SupportedVolumeInformation.REMOTE_MIRRORS.toString())
                  .clear();
            } else {
              unManagedVolumeInformation
                  .get(SupportedVolumeInformation.REMOTE_MIRRORS.toString())
                  .replace(rmObj.getTargetVolumenativeGuids());
            }
          }
        } else if (RemoteMirrorObject.Types.TARGET.toString().equalsIgnoreCase(rmObj.getType())) {

          _logger.info(
              "Found Target {}, updating copyMode {}, RA Group",
              unManagedVolume.getNativeGuid(),
              rmObj.getCopyMode());
          // setting srdfParent
          StringSet parentVolume = new StringSet();
          parentVolume.add(rmObj.getSourceVolumeNativeGuid());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.REMOTE_MIRROR_SOURCE_VOLUME.toString(), parentVolume);

          // setting RAGroup
          StringSet raGroup = new StringSet();
          raGroup.add(rmObj.getRaGroupUri().toString());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.REMOTE_MIRROR_RDF_GROUP.toString(), raGroup);
        }
        // setting Copy Modes
        StringSet copyModes = new StringSet();
        copyModes.add(rmObj.getCopyMode());
        if (unManagedVolumeInformation.get(SupportedVolumeInformation.REMOTE_COPY_MODE.toString())
            == null) {
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.REMOTE_COPY_MODE.toString(), copyModes);
        } else {
          unManagedVolumeInformation
              .get(SupportedVolumeInformation.REMOTE_COPY_MODE.toString())
              .replace(copyModes);
        }
        // setting Volume Type

        StringSet volumeType = new StringSet();
        volumeType.add(rmObj.getType());
        unManagedVolumeInformation.put(
            SupportedVolumeInformation.REMOTE_VOLUME_TYPE.toString(), volumeType);

        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.REMOTE_MIRRORING.toString(), TRUE);
      } else {
        unManagedVolumeCharacteristics.put(
            SupportedVolumeCharacterstics.REMOTE_MIRRORING.toString(), FALSE);
      }

      // handle clones, local mirrors and snapshots
      boolean isLocalReplica = false;
      if (volumeToLocalReplicaMap.containsKey(unManagedVolume.getNativeGuid())) {
        _logger.info("Found in localReplicaMap {}", unManagedVolume.getNativeGuid());
        LocalReplicaObject lrObj = volumeToLocalReplicaMap.get(unManagedVolume.getNativeGuid());
        isLocalReplica = lrObj.isReplica();

        // setting targets
        StringSet fullCopies = lrObj.getFullCopies();
        if (fullCopies != null && !fullCopies.isEmpty()) {
          unManagedVolumeInformation.put(SupportedVolumeInformation.FULL_COPIES.name(), fullCopies);
        }

        StringSet mirrors = lrObj.getMirrors();
        if (mirrors != null && !mirrors.isEmpty()) {
          unManagedVolumeInformation.put(SupportedVolumeInformation.MIRRORS.name(), mirrors);
        }

        StringSet snapshots = lrObj.getSnapshots();
        if (snapshots != null && !snapshots.isEmpty()) {
          unManagedVolumeInformation.put(SupportedVolumeInformation.SNAPSHOTS.name(), snapshots);
        }

        if (lrObj.hasReplica()) {
          // set the HAS_REPLICAS property
          unManagedVolumeCharacteristics.put(
              SupportedVolumeCharacterstics.HAS_REPLICAS.name(), TRUE);
        }

        if (LocalReplicaObject.Types.FullCopy.equals(lrObj.getType())) {
          _logger.info("Found Clone {}", unManagedVolume.getNativeGuid());
          // setting clone specific info
          unManagedVolumeCharacteristics.put(
              SupportedVolumeCharacterstics.IS_FULL_COPY.name(), TRUE);
          StringSet sourceVolume = new StringSet();
          sourceVolume.add(lrObj.getSourceNativeGuid());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.LOCAL_REPLICA_SOURCE_VOLUME.name(), sourceVolume);

          StringSet isSyncActive = new StringSet();
          isSyncActive.add(new Boolean(lrObj.isSyncActive()).toString());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.IS_SYNC_ACTIVE.name(), isSyncActive);

          StringSet replicaState = new StringSet();
          replicaState.add(lrObj.getReplicaState());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.REPLICA_STATE.name(), replicaState);
        } else if (LocalReplicaObject.Types.BlockMirror.equals(lrObj.getType())) {
          _logger.info("Found Local Mirror {}", unManagedVolume.getNativeGuid());
          // setting local mirror specific info
          unManagedVolumeCharacteristics.put(
              SupportedVolumeCharacterstics.IS_LOCAL_MIRROR.name(), TRUE);
          StringSet sourceVolume = new StringSet();
          sourceVolume.add(lrObj.getSourceNativeGuid());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.LOCAL_REPLICA_SOURCE_VOLUME.name(), sourceVolume);

          StringSet syncState = new StringSet();
          syncState.add(lrObj.getSyncState());
          unManagedVolumeInformation.put(SupportedVolumeInformation.SYNC_STATE.name(), syncState);

          StringSet syncType = new StringSet();
          syncType.add(lrObj.getSyncType());
          unManagedVolumeInformation.put(SupportedVolumeInformation.SYNC_TYPE.name(), syncType);

          String syncedInst = lrObj.getSynchronizedInstance();
          if (syncedInst != null) {
            StringSet synchronizedInstance = new StringSet();
            synchronizedInstance.add(syncedInst);
            unManagedVolumeInformation.put(
                SupportedVolumeInformation.SYNCHRONIZED_INSTANCE.name(), synchronizedInstance);
          }
        } else if (LocalReplicaObject.Types.BlockSnapshot.equals(lrObj.getType())) {
          _logger.info("Found Snapshot {}", unManagedVolume.getNativeGuid());
          // setting snapshot specific info
          unManagedVolumeCharacteristics.put(
              SupportedVolumeCharacterstics.IS_SNAP_SHOT.name(), TRUE);
          StringSet sourceVolume = new StringSet();
          sourceVolume.add(lrObj.getSourceNativeGuid());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.LOCAL_REPLICA_SOURCE_VOLUME.name(), sourceVolume);

          StringSet isSyncActive = new StringSet();
          isSyncActive.add(new Boolean(lrObj.isSyncActive()).toString());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.IS_SYNC_ACTIVE.name(), isSyncActive);

          StringSet needsCopyToTarget = new StringSet();
          needsCopyToTarget.add(new Boolean(lrObj.isNeedsCopyToTarget()).toString());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.NEEDS_COPY_TO_TARGET.name(), needsCopyToTarget);

          StringSet technologyType = new StringSet();
          technologyType.add(lrObj.getTechnologyType());
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.TECHNOLOGY_TYPE.name(), technologyType);

          String settingsInst = lrObj.getSettingsInstance();
          if (settingsInst != null) {
            StringSet settingsInstance = new StringSet();
            settingsInstance.add(settingsInst);
            unManagedVolumeInformation.put(
                SupportedVolumeInformation.SETTINGS_INSTANCE.name(), settingsInstance);
          }
        }
      }

      // set volume's isSyncActive
      if (!isLocalReplica) {
        StringSet isSyncActive = new StringSet();
        isSyncActive.add(TRUE);
        unManagedVolumeInformation.put(
            SupportedVolumeInformation.IS_SYNC_ACTIVE.name(), isSyncActive);
      }

      if (null != pool) {
        unManagedVolume.setStoragePoolUri(pool.getId());
        StringSet pools = new StringSet();
        pools.add(pool.getId().toString());
        unManagedVolumeInformation.put(SupportedVolumeInformation.STORAGE_POOL.toString(), pools);
        StringSet driveTypes = pool.getSupportedDriveTypes();
        if (null != driveTypes) {
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.DISK_TECHNOLOGY.toString(), driveTypes);
        }
        StringSet matchedVPools =
            DiscoveryUtils.getMatchedVirtualPoolsForPool(
                _dbClient,
                pool.getId(),
                unManagedVolumeCharacteristics.get(
                    SupportedVolumeCharacterstics.IS_THINLY_PROVISIONED.toString()));
        if (unManagedVolumeInformation.containsKey(
            SupportedVolumeInformation.SUPPORTED_VPOOL_LIST.toString())) {

          _logger.debug("Matched Pools :" + Joiner.on("\t").join(matchedVPools));
          if (null != matchedVPools && matchedVPools.size() == 0) {
            // replace with empty string set doesn't work, hence
            // added explicit code to remove all
            unManagedVolumeInformation
                .get(SupportedVolumeInformation.SUPPORTED_VPOOL_LIST.toString())
                .clear();
          } else {
            // replace with new StringSet
            unManagedVolumeInformation
                .get(SupportedVolumeInformation.SUPPORTED_VPOOL_LIST.toString())
                .replace(matchedVPools);
            _logger.info(
                "Replaced Pools :"
                    + Joiner.on("\t")
                        .join(
                            unManagedVolumeInformation.get(
                                SupportedVolumeInformation.SUPPORTED_VPOOL_LIST.toString())));
          }
        } else {
          unManagedVolumeInformation.put(
              SupportedVolumeInformation.SUPPORTED_VPOOL_LIST.toString(), matchedVPools);
        }
      }

      // set allocated capacity
      if (allocCapacity != null) {
        StringSet allocCapacitySet = new StringSet();
        allocCapacitySet.add(allocCapacity);
        unManagedVolumeInformation.put(
            SupportedVolumeInformation.ALLOCATED_CAPACITY.toString(), allocCapacitySet);
      }

      StringSet provCapacity = new StringSet();
      provCapacity.add(String.valueOf(returnProvisionedCapacity(volumeInstance, keyMap)));
      unManagedVolumeInformation.put(
          SupportedVolumeInformation.PROVISIONED_CAPACITY.toString(), provCapacity);
      injectVolumeInformation(unManagedVolume, volumeInstance, unManagedVolumeInformation);
      injectVolumeCharacterstics(unManagedVolume, volumeInstance, unManagedVolumeCharacteristics);
      unManagedVolume.getUnmanagedExportMasks().clear();
      unManagedVolume.getInitiatorUris().clear();
      unManagedVolume.getInitiatorNetworkIds().clear();
      if (created) {
        _unManagedVolumesInsert.add(unManagedVolume);
      } else {
        _unManagedVolumesUpdate.add(unManagedVolume);
      }

    } catch (Exception e) {
      _logger.error("Exception: ", e);
    }
    return unManagedVolume;
  }
  /**
   * Creates the RP source volume/journal and the specified number of target/journal volumes.
   *
   * @param volumeName
   * @param numTargets
   */
  private List<Volume> createRpVolumes(
      String volumeName, int numTargets, ProtectionSet protectionSet, boolean isRpVPlex) {
    List<Volume> volumes = new ArrayList<Volume>();

    StringSet associatedVolumes = new StringSet();
    associatedVolumes.add("associatedVol1");

    StorageSystem storageSystem = null;
    if (isRpVPlex) {
      storageSystem = createStorageSystem(true);
    } else {
      storageSystem = createStorageSystem(false);
    }

    String rsetName = "RSet-" + volumeName;

    Volume sourceVolume = new Volume();
    URI sourceVolumeURI = URIUtil.createId(Volume.class);
    volumes.add(sourceVolume);
    sourceVolume.setId(sourceVolumeURI);
    sourceVolume.setLabel(volumeName);
    sourceVolume.setPersonality(Volume.PersonalityTypes.SOURCE.toString());
    sourceVolume.setRSetName(rsetName);
    sourceVolume.setProtectionSet(new NamedURI(protectionSet.getId(), sourceVolume.getLabel()));
    sourceVolume.setStorageController(storageSystem.getId());
    if (isRpVPlex) {
      sourceVolume.setAssociatedVolumes(associatedVolumes);
      sourceVolume.setNativeId(
          "/clusters/cluster-1/virtual-volumes/device_V000195701573-01E7A_vol");
      // Create a VPLEX ViPR BlockConsistencyGroup for the source volume
      BlockConsistencyGroup sourceVolumeCg =
          createBlockConsistencyGroup(
              sourceVolume.getLabel() + "-CG", storageSystem.getId(), Types.VPLEX.name(), true);
      addVolumeToBlockConsistencyGroup(sourceVolumeCg.getId(), sourceVolume);
      rpVplexVolumeToCgMapping.put(sourceVolumeURI, sourceVolumeCg.getId());
    } else {
      rpVolumeURIs.add(sourceVolumeURI);
    }
    _dbClient.createObject(sourceVolume);

    Volume sourceVolumeJournal = new Volume();
    URI sourceVolumeJournalURI = URIUtil.createId(Volume.class);
    volumes.add(sourceVolumeJournal);
    sourceVolumeJournal.setId(sourceVolumeJournalURI);
    sourceVolumeJournal.setLabel(volumeName + RP_SRC_JOURNAL_APPEND);
    sourceVolumeJournal.setPersonality(Volume.PersonalityTypes.METADATA.toString());
    sourceVolumeJournal.setProtectionSet(
        new NamedURI(protectionSet.getId(), sourceVolumeJournal.getLabel()));
    sourceVolumeJournal.setStorageController(storageSystem.getId());
    if (isRpVPlex) {
      sourceVolumeJournal.setAssociatedVolumes(associatedVolumes);
      sourceVolumeJournal.setNativeId(
          "/clusters/cluster-1/virtual-volumes/device_V000195701573-01E7B_vol");
      // Create a VPLEX ViPR BlockConsistencyGroup for the source journal volume
      BlockConsistencyGroup sourceVolumeJournalCg =
          createBlockConsistencyGroup(
              sourceVolumeJournal.getLabel() + "-CG",
              storageSystem.getId(),
              Types.VPLEX.name(),
              true);
      addVolumeToBlockConsistencyGroup(sourceVolumeJournalCg.getId(), sourceVolumeJournal);
      rpVplexVolumeToCgMapping.put(sourceVolumeJournalURI, sourceVolumeJournalCg.getId());
    } else {
      rpVolumeURIs.add(sourceVolumeJournalURI);
    }
    _dbClient.createObject(sourceVolumeJournal);

    for (int i = 1; i <= numTargets; i++) {
      Volume sourceVolumeTarget = new Volume();
      URI sourceVolumeTargetURI = URIUtil.createId(Volume.class);
      volumes.add(sourceVolumeTarget);
      sourceVolumeTarget.setId(sourceVolumeTargetURI);
      sourceVolumeTarget.setLabel(volumeName + RP_TGT_APPEND + "vArray" + i);
      sourceVolumeTarget.setPersonality(Volume.PersonalityTypes.TARGET.toString());
      sourceVolumeTarget.setRSetName(rsetName);
      sourceVolumeTarget.setProtectionSet(
          new NamedURI(protectionSet.getId(), sourceVolumeTarget.getLabel()));
      sourceVolumeTarget.setStorageController(storageSystem.getId());
      if (isRpVPlex) {
        sourceVolumeTarget.setAssociatedVolumes(associatedVolumes);
        sourceVolumeTarget.setNativeId(
            "/clusters/cluster-2/virtual-volumes/device_V000195701573-01E7C_vol" + i);
        // Create a VPLEX ViPR BlockConsistencyGroup for the target volume
        BlockConsistencyGroup sourceVolumeTargetCg =
            createBlockConsistencyGroup(
                sourceVolumeTarget.getLabel() + "-CG",
                storageSystem.getId(),
                Types.VPLEX.name(),
                true);
        addVolumeToBlockConsistencyGroup(sourceVolumeTargetCg.getId(), sourceVolumeTarget);
        rpVplexVolumeToCgMapping.put(sourceVolumeTargetURI, sourceVolumeTargetCg.getId());
      } else {
        rpVolumeURIs.add(sourceVolumeTargetURI);
      }

      _dbClient.createObject(sourceVolumeTarget);

      Volume sourceVolumeTargetJournal = new Volume();
      URI sourceVolumeTargetJournalURI = URIUtil.createId(Volume.class);
      volumes.add(sourceVolumeTargetJournal);
      sourceVolumeTargetJournal.setId(sourceVolumeTargetJournalURI);
      sourceVolumeTargetJournal.setLabel(volumeName + RP_TGT_JOURNAL_APPEND + "vArray" + i);
      sourceVolumeTargetJournal.setPersonality(Volume.PersonalityTypes.METADATA.toString());
      sourceVolumeTargetJournal.setProtectionSet(
          new NamedURI(protectionSet.getId(), sourceVolumeTargetJournal.getLabel()));
      sourceVolumeTargetJournal.setStorageController(storageSystem.getId());
      if (isRpVPlex) {
        sourceVolumeTargetJournal.setAssociatedVolumes(associatedVolumes);
        sourceVolumeTargetJournal.setNativeId(
            "/clusters/cluster-2/virtual-volumes/device_V000195701573-01ED_vol" + i);
        // Create a VPLEX ViPR BlockConsistencyGroup for the source target journal volume
        BlockConsistencyGroup sourceVolumeTargetJournalCg =
            createBlockConsistencyGroup(
                sourceVolumeTargetJournal.getLabel() + "-CG",
                storageSystem.getId(),
                Types.VPLEX.name(),
                true);
        addVolumeToBlockConsistencyGroup(
            sourceVolumeTargetJournalCg.getId(), sourceVolumeTargetJournal);
        rpVplexVolumeToCgMapping.put(
            sourceVolumeTargetJournalURI, sourceVolumeTargetJournalCg.getId());
      } else {
        rpVolumeURIs.add(sourceVolumeTargetJournalURI);
      }
      _dbClient.createObject(sourceVolumeTargetJournal);
    }

    return volumes;
  }
  @POST
  @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @CheckPermission(roles = {Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN})
  public TaskResourceRep registerStorageProvider(StorageProviderCreateParam param)
      throws ControllerException {
    ArgValidator.checkFieldNotEmpty(param.getName(), "name");
    checkForDuplicateName(param.getName(), StorageProvider.class);

    ArgValidator.checkFieldNotEmpty(param.getIpAddress(), "ip_address");
    ArgValidator.checkFieldNotNull(param.getPortNumber(), "port_number");
    ArgValidator.checkFieldNotEmpty(param.getUserName(), "user_name");
    ArgValidator.checkFieldNotEmpty(param.getPassword(), "password");
    ArgValidator.checkFieldRange(param.getPortNumber(), 1, 65535, "port_number");
    ArgValidator.checkFieldValueFromEnum(
        param.getInterfaceType(), "interface_type", StorageProvider.InterfaceType.class);
    String providerKey = param.getIpAddress() + "-" + param.getPortNumber();
    List<StorageProvider> providers =
        CustomQueryUtility.getActiveStorageProvidersByProviderId(_dbClient, providerKey);
    if (providers != null && !providers.isEmpty()) {
      throw APIException.badRequests.invalidParameterStorageProviderAlreadyRegistered(providerKey);
    }

    // Set the SSL parameter
    Boolean useSSL = param.getUseSSL();
    if (useSSL == null) {
      useSSL = StorageProviderCreateParam.USE_SSL_DEFAULT;
    }

    StorageProvider provider = new StorageProvider();
    provider.setId(URIUtil.createId(StorageProvider.class));
    provider.setLabel(param.getName());
    provider.setIPAddress(param.getIpAddress());
    provider.setPortNumber(param.getPortNumber());
    provider.setUserName(param.getUserName());
    provider.setPassword(param.getPassword());
    provider.setUseSSL(useSSL);
    provider.setInterfaceType(param.getInterfaceType());
    provider.setRegistrationStatus(RegistrationStatus.REGISTERED.toString());
    provider.setConnectionStatus(ConnectionStatus.INITIALIZING.name());
    provider.setSecondaryUsername(param.getSecondaryUsername());
    provider.setSecondaryPassword(param.getSecondaryPassword());
    provider.setElementManagerURL(param.getElementManagerURL());
    if (param.getSioCLI() != null) {
      // TODO: Validate the input?
      provider.addKey(StorageProvider.GlobalKeys.SIO_CLI.name(), param.getSioCLI());
    }

    if (StorageProvider.InterfaceType.ibmxiv.name().equalsIgnoreCase(provider.getInterfaceType())) {
      provider.setManufacturer("IBM");
    }

    _dbClient.createObject(provider);

    auditOp(
        OperationTypeEnum.REGISTER_STORAGEPROVIDER,
        true,
        null,
        provider.getLabel(),
        provider.getId().toString(),
        provider.getIPAddress(),
        provider.getPortNumber(),
        provider.getUserName(),
        provider.getInterfaceType());

    ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1);
    String taskId = UUID.randomUUID().toString();
    tasks.add(new AsyncTask(StorageProvider.class, provider.getId(), taskId));

    BlockController controller = getController(BlockController.class, provider.getInterfaceType());
    log.debug("controller.getClass().getName() :{}", controller.getClass().getName());
    log.debug("controller.getClass().getSimpleName() :{}", controller.getClass().getSimpleName());
    /**
     * Creates MonitoringJob token for vnxblock/vmax, hds, cinder and IBM XIV device on zooKeeper
     * queue
     */
    // TODO : If all interface types have monitoring impl class added (scaleIO is missing),
    // this check can be removed.
    String interfaceType = provider.getInterfaceType();
    if (StorageProvider.InterfaceType.hicommand.name().equalsIgnoreCase(interfaceType)
        || StorageProvider.InterfaceType.smis.name().equalsIgnoreCase(interfaceType)
        || StorageProvider.InterfaceType.cinder.name().equalsIgnoreCase(interfaceType)
        || StorageProvider.InterfaceType.ibmxiv.name().equalsIgnoreCase(interfaceType)) {
      controller.startMonitoring(
          new AsyncTask(StorageProvider.class, provider.getId(), taskId),
          getSystemTypeByInterface(interfaceType));
    }

    DiscoveredObjectTaskScheduler scheduler =
        new DiscoveredObjectTaskScheduler(_dbClient, new ScanJobExec(controller));
    TaskList taskList = scheduler.scheduleAsyncTasks(tasks);
    return taskList.getTaskList().listIterator().next();
  }
  /**
   * Reconciles the current set of a Device's endpoints with what is persisted. Updates the database
   * accordingly.
   *
   * @param dev
   * @param currentConnections
   * @throws IOException
   */
  private void reconcileFCEndpoints(NetworkSystem dev, List<FCEndpoint> currentConnections)
      throws IOException {
    // First, read all the existing connections from the device, and put them into a map
    // keyed by remote wwpn.
    URIQueryResultList uriList = new URIQueryResultList();
    dbClient.queryByConstraint(
        ContainmentConstraint.Factory.getNetworkSystemFCPortConnectionConstraint(dev.getId()),
        uriList);
    Map<String, FCEndpoint> existingEndpoints = new HashMap<String, FCEndpoint>();
    for (URI uriold : uriList) {
      FCEndpoint connection = dbClient.queryObject(FCEndpoint.class, uriold);
      if (connection != null) {
        existingEndpoints.put(connection.getRemotePortName().toUpperCase(), connection);
      }
    }
    // Now, scan the new endpoints, looking for added or updated records by
    // comparing them with the existing endpoints. Keep track of what was processed
    // so can do deletions on anything not seen in the currentConnections.
    List<FCEndpoint> updated = new ArrayList<FCEndpoint>();
    List<FCEndpoint> created = new ArrayList<FCEndpoint>();
    Set<String> processedWwpns = new HashSet<String>();
    int conflictingEndpoints = 0;
    for (FCEndpoint current : currentConnections) {
      String key = current.getRemotePortName().toUpperCase();
      processedWwpns.add(key);
      FCEndpoint existing = existingEndpoints.get(key);
      if (existing == null) {
        current.setNetworkDevice(dev.getId());
        current.setId(URIUtil.createId(FCEndpoint.class));
        created.add(current);
        conflictingEndpoints +=
            removeConflictingEndpoints(key, current.getFabricWwn(), dev.getId());
      } else {
        boolean modified = checkUpdated(existing, current);
        if (existing.getAwolCount() > 0) {
          modified = true;
          existing.setAwolCount(0);
          existing.setAwolTime(null);
        }
        if (modified) {
          updated.add(existing);
          conflictingEndpoints +=
              removeConflictingEndpoints(key, current.getFabricWwn(), dev.getId());
        }
      }
    }

    // Determine those to be deleted. Remove all the processed records from the existing set.
    // What was left were not seen this time.
    for (String key : processedWwpns) {
      existingEndpoints.remove(key);
    }
    // The remaining existingEndpoints can be processed for removal.
    // They are removed after a minimum number of samples and minimum amount of time has transpired.
    Integer removedCount = 0;
    for (FCEndpoint entry : existingEndpoints.values()) {
      int count = entry.getAwolCount();
      if (count == 0) {
        entry.setAwolTime(System.currentTimeMillis());
      }
      entry.setAwolCount(++count);
      if (count >= _minAwolSamples
          && (System.currentTimeMillis() - entry.getAwolTime()) > _minAwolTime) {
        removedCount++;
        dbClient.removeObject(entry);
      } else {
        updated.add(entry); // update counters
      }
    }
    // Persist created, modified.
    dbClient.createObject(created);
    dbClient.updateAndReindexObject(updated);
    _log.info(MessageFormat.format("{0} new connections persisted", created.size()).toString());
    _log.info(MessageFormat.format("{0} updated connections persisted", updated.size()).toString());
    _log.info(
        MessageFormat.format("{0} missing connections", existingEndpoints.values().size())
            .toString());
    _log.info(MessageFormat.format("{0} removed connections", removedCount.toString()));
    _log.info(MessageFormat.format("{0} conflicting connections (removed)", conflictingEndpoints));
  }
 /**
  * Prepares the ProtectionSystem data.
  *
  * @throws Exception
  */
 private void prepareProtectionSystemData() throws Exception {
   ProtectionSystem protectionSystem = new ProtectionSystem();
   protectionSystemURI = URIUtil.createId(ProtectionSystem.class);
   protectionSystem.setId(protectionSystemURI);
   _dbClient.createObject(protectionSystem);
 }