use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class BlockObjectMultipleConsistencyGroupsMigration method consolidateDuplicates.
/**
* searches for protection sets with duplicate names and consolidates into one protection set
*
* @return
*/
private void consolidateDuplicates() {
Map<String, List<ProtectionSet>> labelURIListMap = new HashMap<String, List<ProtectionSet>>();
List<URI> protectionSetURIs = dbClient.queryByType(ProtectionSet.class, true);
log.info("Scanning ProtectionSets for duplicate names.");
for (URI protectionSetURI : protectionSetURIs) {
ProtectionSet protectionSet = dbClient.queryObject(ProtectionSet.class, protectionSetURI);
if (protectionSet == null || protectionSet.getInactive()) {
log.info("Skipping null or inactive protection set {}", protectionSetURI);
continue;
}
if (!labelURIListMap.containsKey(protectionSet.getLabel())) {
labelURIListMap.put(protectionSet.getLabel(), new ArrayList<ProtectionSet>());
}
labelURIListMap.get(protectionSet.getLabel()).add(protectionSet);
}
List<ProtectionSet> protectionSetsToDelete = new ArrayList<ProtectionSet>();
List<ProtectionSet> protectionSetsToPersist = new ArrayList<ProtectionSet>();
List<Volume> volumesToPersist = new ArrayList<Volume>();
List<BlockSnapshot> snapsToPersist = new ArrayList<BlockSnapshot>();
for (Entry<String, List<ProtectionSet>> entry : labelURIListMap.entrySet()) {
if (entry.getValue().size() > 1) {
log.info("Duplicate protection sets found {} | {}", entry.getKey(), entry.getValue().toArray());
ProtectionSet protectionSet = entry.getValue().iterator().next();
for (ProtectionSet duplicate : entry.getValue()) {
if (duplicate.getId().equals(protectionSet.getId())) {
continue;
}
log.info(String.format("duplicating %s protection set %s to %s)", protectionSet.getLabel(), duplicate.getId(), protectionSet.getId()));
// add the volumes from the duplicate to the original
protectionSet.getVolumes().addAll(duplicate.getVolumes());
// reset the protection set id on the volumes in the duplicate
for (String volid : duplicate.getVolumes()) {
Volume vol = dbClient.queryObject(Volume.class, URI.create(volid));
if (vol == null || vol.getInactive()) {
log.info("Skipping null or inactive volume {}", volid);
continue;
}
log.info(String.format("Changing protection set id on volume %s from %s to %s", vol.getId(), vol.getProtectionSet().getURI(), protectionSet.getId()));
vol.setProtectionSet(new NamedURI(protectionSet.getId(), protectionSet.getLabel()));
volumesToPersist.add(vol);
}
// reset any block snapshot that points to the duplicate protection set
URIQueryResultList blockSnapIds = new URIQueryResultList();
Constraint constraint = ContainmentConstraint.Factory.getProtectionSetBlockSnapshotConstraint(duplicate.getId());
dbClient.queryByConstraint(constraint, blockSnapIds);
Iterator<URI> itr = blockSnapIds.iterator();
while (itr.hasNext()) {
URI snapId = itr.next();
BlockSnapshot snap = dbClient.queryObject(BlockSnapshot.class, snapId);
if (snap == null || snap.getInactive()) {
log.info("Skipping null or inactive volume {}", snapId);
continue;
}
log.info(String.format("Changing protection set id on snapshot %s from %s to %s", snap.getId(), snap.getProtectionSet(), protectionSet.getId()));
snap.setProtectionSet(protectionSet.getId());
snapsToPersist.add(snap);
}
log.info("deleting duplicate protection set {}", duplicate.getId());
protectionSetsToDelete.add(duplicate);
}
protectionSetsToPersist.add(protectionSet);
}
}
dbClient.persistObject(protectionSetsToPersist);
dbClient.persistObject(volumesToPersist);
dbClient.persistObject(snapsToPersist);
dbClient.markForDeletion(protectionSetsToDelete);
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class BlockObjectMultipleConsistencyGroupsMigration method cleanupStaleProtectionSetVolumes.
/**
* Cleans up stale ProtectionSet volume references. Meaning, volumes referenced
* by the ProtectionSet that no longer exist in the DB will be removed. Also,
* if the ProtectionSet ends up containing zero volumes after this operation, the
* ProtectionSet itself will be removed from the DB.
*
* @param protectionSetUri the ProtectionSet to be cleaned-up.
* @return boolean true if the ProtectionSet has been removed from the DB, false otherwise.
*/
private boolean cleanupStaleProtectionSetVolumes(URI protectionSetURI) {
ProtectionSet protectionSet = dbClient.queryObject(ProtectionSet.class, protectionSetURI);
boolean protectionSetRemoved = false;
if (protectionSet != null) {
StringSet protectionSetVolumes = protectionSet.getVolumes();
StringSet volumesToRemove = new StringSet();
if (protectionSetVolumes != null) {
Iterator<String> volumesItr = protectionSetVolumes.iterator();
while (volumesItr.hasNext()) {
String volumeUriStr = volumesItr.next();
Volume volume = dbClient.queryObject(Volume.class, URI.create(volumeUriStr));
if (volume == null) {
volumesToRemove.add(volumeUriStr);
// Volume is referenced by the ProtectionSet but it is not in the database. It should
// be removed from the ProtectionSet.
log.info("Removing stale Volume {} referenced by ProtectionSet {}.", volumeUriStr, protectionSet.getId());
}
}
if (protectionSetVolumes.size() == volumesToRemove.size()) {
// There are no volume references for this ProtectionSet so remove it.
log.info("ProtectionSet {} has no volume references so it is being removed.", protectionSet.getId());
dbClient.markForDeletion(protectionSet);
protectionSetRemoved = true;
} else {
// Stale volume references have been removed.
protectionSetVolumes.removeAll(volumesToRemove);
dbClient.persistObject(protectionSet);
}
}
}
return protectionSetRemoved;
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class BlockObjectMultipleConsistencyGroupsMigration method migrateRpConsistencyGroups.
/**
* Migrates the RP/RP+VPlex BlockConsistencyGroups and BlockObjects.
*/
private void migrateRpConsistencyGroups() {
log.info("Migrating RP+VPlex BlockConsistencyGroup objects and Volume references.");
List<URI> protectionSetURIs = dbClient.queryByType(ProtectionSet.class, true);
log.info("Scanning ProtectionSets for stale Volume references.");
for (URI protectionSetURI : protectionSetURIs) {
// First, cleanup any stale volume references for the ProtectionSet
if (cleanupStaleProtectionSetVolumes(protectionSetURI)) {
log.info("ProtectionSet {} has been removed so continuing to the next one.", protectionSetURI);
}
}
consolidateDuplicates();
protectionSetURIs = dbClient.queryByType(ProtectionSet.class, true);
log.info("Scanning ProtectionSets for RP+VPlex Volume references.");
for (URI protectionSetURI : protectionSetURIs) {
// Lookup the ProtectionSet again after stale volume references have been removed.
ProtectionSet protectionSet = dbClient.queryObject(ProtectionSet.class, protectionSetURI);
log.info("Scanning ProtectionSet {}|{} ", protectionSet.getLabel(), protectionSet.getId());
if (protectionSet != null && protectionSet.getVolumes() != null) {
// are RP+VPlex volumes.
if (protectionSet.getVolumes() != null && !protectionSet.getVolumes().isEmpty()) {
Iterator<String> protectionSetVolumes = protectionSet.getVolumes().iterator();
Volume protectionSetVolume = null;
while (protectionSetVolumes.hasNext()) {
Volume vol = dbClient.queryObject(Volume.class, URI.create(protectionSetVolumes.next()));
if (vol != null) {
log.info("Using ProtectionSet Volume {}|{} to migrate consistency group.", vol.getLabel(), vol.getId());
protectionSetVolume = vol;
break;
}
}
BlockConsistencyGroup primaryCg = null;
// other type of volume will only reference a single BlockConsistencyGroup.
if (protectionSetVolume.getConsistencyGroups() != null && !protectionSetVolume.getConsistencyGroups().isEmpty() && protectionSetVolume.getConsistencyGroups().size() == 2) {
log.info("Found RP+VPlex ProtectionSet {}|{}. Preparing to migrated referenced RP+VPlex " + "volumes and associated BlockConsistencyGroups.", protectionSet.getLabel(), protectionSet.getId());
// There are references to 2 different BlockConsistencyGroup objects,
// so this is an RP+VPlex volume.
Iterator<String> cgUriItr = protectionSetVolume.getConsistencyGroups().iterator();
log.info("Attempting to locate the RP BlockConsistencyGroup for Volume {}|{}", protectionSetVolume.getLabel(), protectionSetVolume.getId());
while (cgUriItr.hasNext()) {
BlockConsistencyGroup cg = dbClient.queryObject(BlockConsistencyGroup.class, URI.create(cgUriItr.next()));
log.info("Found BlockConsistencyGroup {} of type {}", cg.getLabel(), cg.getType());
// will be mapped to this primary BlockConsistencyGroup.
if (cg.getTypes() != null && cg.getType().equals(Types.RP.name())) {
log.info("Primary RP BlockConsistencyGroup {} found for ProtectionSet {}.", cg.getLabel(), protectionSet.getLabel());
primaryCg = cg;
// Add the RP type
primaryCg.addConsistencyGroupTypes(Types.RP.name());
break;
}
}
if (primaryCg == null) {
log.warn("Unable to migration volumes/consistency groups associated with ProtectionSet {}. Could not find an RP associated BlockConsistencyGroup for Volume {}. ", protectionSet.getId(), protectionSetVolume.getId());
continue;
}
// Migrate the protection system/cg entry that replaces the use of the deviceName field.
primaryCg.addSystemConsistencyGroup(protectionSet.getProtectionSystem().toString(), "ViPR-" + primaryCg.getLabel());
Iterator<String> volumeUriItr = protectionSet.getVolumes().iterator();
while (volumeUriItr.hasNext()) {
String volumeUri = volumeUriItr.next();
Volume volume = dbClient.queryObject(Volume.class, URI.create(volumeUri));
if (volume != null) {
log.info("Scanning volume {} for protection set {}.", volume.getLabel(), protectionSet.getLabel());
// Get the volume's VPlex CG, copy the info in the primary CG, and remove
// the VPlex CG from Cassandra.
BlockConsistencyGroup vplexCg = null;
if (volume.getConsistencyGroups() != null && !volume.getConsistencyGroups().isEmpty()) {
cgUriItr = volume.getConsistencyGroups().iterator();
while (cgUriItr.hasNext()) {
BlockConsistencyGroup cg = dbClient.queryObject(BlockConsistencyGroup.class, URI.create(cgUriItr.next()));
if (cg.getType() != null && cg.getType().equals(Types.VPLEX.name())) {
vplexCg = cg;
log.info("Volume {} belongs to VPLEX BlockConsistencyGroup {}.", volume.getLabel(), cg.getLabel());
break;
}
}
}
if (vplexCg != null && volume.getAssociatedVolumes() != null) {
// Copy the VPlex CG info over to the primary CG
StorageSystem vplexStorageSystem = dbClient.queryObject(StorageSystem.class, vplexCg.getStorageController());
String clusterId = getVPlexClusterFromVolume(volume);
primaryCg.addSystemConsistencyGroup(vplexStorageSystem.getId().toString(), BlockConsistencyGroupUtils.buildClusterCgName(clusterId, vplexCg.getLabel()));
if (NullColumnValueGetter.isNullURI(primaryCg.getStorageController())) {
primaryCg.setStorageController(vplexStorageSystem.getId());
}
if (!primaryCg.getTypes().contains(Types.VPLEX.name())) {
// Add the VPlex type
primaryCg.addConsistencyGroupTypes(Types.VPLEX.name());
}
primaryCg.setType(NullColumnValueGetter.getNullStr());
primaryCg.setDeviceName(NullColumnValueGetter.getNullStr());
// Persist the changes to the primary CG, update the volume reference to the single
// primary CG, and remove the VPlex CG.
dbClient.persistObject(primaryCg);
volume.setConsistencyGroup(primaryCg.getId());
StringSet cgs = volume.getConsistencyGroups();
cgs.remove(vplexCg.getId().toString());
volume.setConsistencyGroups(cgs);
dbClient.persistObject(volume);
log.info("Volume {} fields have been migrated.", volume.getLabel());
dbClient.markForDeletion(vplexCg);
log.info("VPlex BlockConsistencyGroup {} has been migrated over to RP BlockConsistencyGroup and has been deleted.", vplexCg.getLabel(), primaryCg.getLabel());
}
}
}
} else if (protectionSetVolume != null && protectionSetVolume.getConsistencyGroups() != null && !protectionSetVolume.getConsistencyGroups().isEmpty() && protectionSetVolume.getConsistencyGroups().size() == 1) {
Iterator<String> cgUriItr = protectionSetVolume.getConsistencyGroups().iterator();
BlockConsistencyGroup cg = dbClient.queryObject(BlockConsistencyGroup.class, URI.create(cgUriItr.next()));
// Migration logic for RP only BlockConsistencyGroup
cg.addConsistencyGroupTypes(cg.getType());
// In ViPR 2.0, the RP deviceName was not being prefixed with 'ViPR-', which is what is used on
// the actual RP appliance for the CG name.
cg.addSystemConsistencyGroup(protectionSet.getProtectionSystem().toString(), "ViPR-" + cg.getLabel());
// Remove type and deviceName fields
cg.setType(NullColumnValueGetter.getNullStr());
cg.setDeviceName(NullColumnValueGetter.getNullStr());
dbClient.persistObject(cg);
}
}
}
}
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class BlockObjectMultipleConsistencyGroupsMigrationTest method prepareRPVplexConsistencyGroupData.
/**
* 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);
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class BlockObjectMultipleConsistencyGroupsMigrationTest method verifyStaleProtectionSet.
/**
* Verifies that ProtectionSets referencing all stale volumes get removed from the DB.
*/
private void verifyStaleProtectionSet() {
ProtectionSet protectionSet = _dbClient.queryObject(ProtectionSet.class, staleProtectionSetURI);
Assert.assertTrue("ProtectionSet " + staleProtectionSetURI + " is stale and should have been removed.", (protectionSet == null || protectionSet.getInactive()));
}
Aggregations