/**
   * 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;
  }
  /**
   * Verify the RP consistency group and its volumes have been properly migrated.
   *
   * @throws Exception
   */
  private void verifyRpConsistencyGroupMigration() throws Exception {
    log.info("Verifying RP BlockConsistencyGroup and associated volume migration.");

    BlockConsistencyGroup rpCg =
        _dbClient.queryObject(BlockConsistencyGroup.class, rpConsistencyGroupURI);

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

    Iterator<Volume> rpVolumeItr = _dbClient.queryIterativeObjects(Volume.class, rpVolumeURIs);

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

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

    verifyBlockObjects(blockObjects);
  }
  /**
   * 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);
  }
  /**
   * Prepare the RecoverPoint only volumes and associated consistency group data.
   *
   * @throws Exception
   */
  private void prepareRPConsistencyGroupDataWithDuplicates() throws Exception {
    String cg2Name = "rpCg3";
    // 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.
    rpConsistencyGroupURI3 = rpCg.getId();

    // create a protection set and volumes and add them to the CG
    addProtectionSetAndVolumes(rpCg, "ps-dup", 3);

    // create a protection set and volumes and add them to the CG
    addProtectionSetAndVolumes(rpCg, "ps-dup", 3);

    // same volume in two protection sets
    // Create the ProtectionSet that the RP volumes will belong to.
    String prefix = "ps-dup2-";
    ProtectionSet cg2ps1 = createProtectionSet(prefix + "ProtectionSet", projectURI);
    ProtectionSet cg2ps2 = createProtectionSet(prefix + "ProtectionSet", projectURI);

    // Create all the RP volumes
    List<Volume> rpCgVolumes = createRpVolumes(prefix + "VolumeA", 1, cg2ps1, false);

    // Add the RP volumes to the RP consistency group
    addVolumesToBlockConsistencyGroup(rpCg.getId(), rpCgVolumes);
    // Add the RP volumes to the protection set
    addVolumesToProtectionSet(cg2ps1.getId(), rpCgVolumes);
    addVolumesToProtectionSet(cg2ps2.getId(), rpCgVolumes);
  }
  /**
   * 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);
  }
  /**
   * Prepare the RecoverPoint only volumes and associated consistency group data.
   *
   * @throws Exception
   */
  private void prepareRPConsistencyGroupData() throws Exception {
    String cg2Name = "rpCg";
    // 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.
    rpConsistencyGroupURI = rpCg.getId();

    // create a protection set and volumes and add them to the CG
    addProtectionSetAndVolumes(rpCg, "rpCg", 0);
  }
  /**
   * Prepares the RP + VPlex consistency group test data.
   *
   * @throws Exception
   */
  private void prepareRPVplexConsistencyGroupData() throws Exception {
    String cg1Name = "rpVplexCg";
    // Create the primary RecoverPoint BlockConsistencyGroup that will be shared by all the
    // RP+VPlex volumes.
    BlockConsistencyGroup rpVplexCg =
        createBlockConsistencyGroup(cg1Name, null, Types.RP.name(), true);
    // Save the CG references for migration verification.
    rpVplexPrimaryConsistencyGroupURI = rpVplexCg.getId();

    // Create the ProtectionSet that the RP + VPlex volumes will belong to.
    ProtectionSet rpVplexProtectionSet = createProtectionSet(cg1Name, projectURI);

    // Create all the RP+VPlex volumes
    List<Volume> rpVplexVolumes =
        createRpVolumes("rpVplexCgVolume1", 1, rpVplexProtectionSet, true);
    rpVplexVolumes.addAll(createRpVolumes("rpVplexCgVolume2", 1, rpVplexProtectionSet, true));

    // Add the RP + VPlex volumes to the RP consistency group
    addVolumesToBlockConsistencyGroup(rpVplexCg.getId(), rpVplexVolumes);
    // Add the RP+VPlex volumes to the protection set.
    addVolumesToProtectionSet(rpVplexProtectionSet.getId(), rpVplexVolumes);
  }