/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller; import java.net.URI; import java.util.ArrayList; import java.util.List; import org.apache.commons.collections.CollectionUtils; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.ProtectionSystem; import com.emc.storageos.db.client.model.VirtualPool; /** * Top level recommendation for RP protection placement */ @SuppressWarnings("serial") public class RPProtectionRecommendation extends Recommendation { private URI protectionDevice; //RP source recommendation List<RPRecommendation> sourceRecommendations; //Journal recommendations private RPRecommendation sourceJournalRecommendation; private RPRecommendation standbyJournalRecommendation; private List<RPRecommendation> targetJournalRecommendations; private URI vpoolChangeVolume; private URI vpoolChangeNewVpool; private boolean vpoolChangeProtectionAlreadyExists; //Placement status private PlacementProgress placementStepsCompleted; private String protectionSystemCriteriaError; public static enum PlacementProgress { NONE, IDENTIFIED_SOLUTION_FOR_SOURCE, IDENTIFIED_SOLUTION_FOR_SUBSET_OF_TARGETS, IDENTIFIED_SOLUTION_FOR_ALL_TARGETS, PROTECTION_SYSTEM_CANNOT_FULFILL_REQUEST } public RPProtectionRecommendation() { this.sourceRecommendations = new ArrayList<RPRecommendation>(); this.targetJournalRecommendations = new ArrayList<RPRecommendation>(); placementStepsCompleted = PlacementProgress.NONE; } public RPProtectionRecommendation(RPProtectionRecommendation copy) { this.setSourceStoragePool(copy.getSourceStoragePool()); this.setSourceStorageSystem(copy.getSourceStorageSystem()); this.setDeviceType(copy.getDeviceType()); this.setResourceCount(copy.getResourceCount()); this.placementStepsCompleted = copy.getPlacementStepsCompleted(); this.protectionDevice = copy.getProtectionDevice(); this.sourceJournalRecommendation = copy.getSourceJournalRecommendation(); this.setStandbyJournalRecommendation(copy.getStandbyJournalRecommendation()); this.vpoolChangeVolume = copy.getVpoolChangeVolume(); this.vpoolChangeNewVpool = copy.getVpoolChangeNewVpool(); this.sourceRecommendations = new ArrayList<RPRecommendation>(); this.getSourceRecommendations().addAll(copy.getSourceRecommendations()); this.targetJournalRecommendations = new ArrayList<RPRecommendation>(); this.getTargetJournalRecommendations().addAll(copy.getTargetJournalRecommendations()); } public RPRecommendation getSourceJournalRecommendation() { return sourceJournalRecommendation; } public void setSourceJournalRecommendation( RPRecommendation sourceJournalRecommendation) { this.sourceJournalRecommendation = sourceJournalRecommendation; } public List<RPRecommendation> getSourceRecommendations() { return sourceRecommendations; } public void setSourceRecommendations(List<RPRecommendation> sourceRecommendations) { this.sourceRecommendations = sourceRecommendations; } public List<RPRecommendation> getTargetJournalRecommendations() { return targetJournalRecommendations; } public void setTargetJournalRecommendations( List<RPRecommendation> targetJournalRecommendations) { this.targetJournalRecommendations = targetJournalRecommendations; } public RPRecommendation getStandbyJournalRecommendation() { return standbyJournalRecommendation; } public void setStandbyJournalRecommendation( RPRecommendation standbyJournalRecommendation) { this.standbyJournalRecommendation = standbyJournalRecommendation; } public URI getProtectionDevice() { return protectionDevice; } public void setProtectionDevice(URI protectionDevice) { this.protectionDevice = protectionDevice; } public void setVpoolChangeVolume(URI id) { vpoolChangeVolume = id; } public URI getVpoolChangeVolume() { return vpoolChangeVolume; } public void setVpoolChangeNewVpool(URI id) { vpoolChangeNewVpool = id; } public URI getVpoolChangeNewVpool() { return vpoolChangeNewVpool; } public boolean isVpoolChangeProtectionAlreadyExists() { return vpoolChangeProtectionAlreadyExists; } public void setVpoolChangeProtectionAlreadyExists( boolean vpoolChangeProtectionAlreadyExists) { this.vpoolChangeProtectionAlreadyExists = vpoolChangeProtectionAlreadyExists; } public PlacementProgress getPlacementStepsCompleted() { return placementStepsCompleted; } public void setPlacementStepsCompleted(PlacementProgress identifiedProtectionSolution) { this.placementStepsCompleted = identifiedProtectionSolution; } public String getProtectionSystemCriteriaError() { return protectionSystemCriteriaError; } public void setProtectionSystemCriteriaError(String protectionSystemCriteriaError) { this.protectionSystemCriteriaError = protectionSystemCriteriaError; } /** * @param internalSiteName * @return */ public int getNumberOfVolumes(String internalSiteName) { int count=0; for (RPRecommendation rpSourceRecommendation: getSourceRecommendations()) { if (rpSourceRecommendation.getInternalSiteName().equals(internalSiteName)) { count += rpSourceRecommendation.getResourceCount(); continue; } for(RPRecommendation targetRec : rpSourceRecommendation.getTargetRecommendations()) { if (targetRec.getInternalSiteName().equals(internalSiteName)) { count += targetRec.getResourceCount(); } } } if (getSourceJournalRecommendation() != null && getSourceJournalRecommendation().getInternalSiteName().equals(internalSiteName)) { count += getSourceJournalRecommendation().getResourceCount(); } if (getStandbyJournalRecommendation() != null && getStandbyJournalRecommendation().getInternalSiteName().equals(internalSiteName)) { count += getStandbyJournalRecommendation().getResourceCount(); } for(RPRecommendation targetJournalRecommendation : getTargetJournalRecommendations()) if ( targetJournalRecommendation != null && targetJournalRecommendation.getInternalSiteName().equals(internalSiteName)) { count += targetJournalRecommendation.getResourceCount(); } return count; } /** Returns list of already determined recommendations. * @return - List of recommendations */ public List<RPRecommendation> getPoolsInAllRecommendations() { List<RPRecommendation> poolsAlreadyInRecommendation = new ArrayList<RPRecommendation>(); poolsAlreadyInRecommendation.addAll(getJournalPoolsInRecommendation()); List<RPRecommendation> sourcePoolsInRecommendation = getSourcePoolsInRecommendation(); if (!sourcePoolsInRecommendation.isEmpty()) { poolsAlreadyInRecommendation.addAll(getSourcePoolsInRecommendation()); } List<RPRecommendation> targetPoolsInRecommendation = getTargetPoolsInRecommendation(); if (!targetPoolsInRecommendation.isEmpty()) { poolsAlreadyInRecommendation.addAll(targetPoolsInRecommendation); } return poolsAlreadyInRecommendation; } /** * Returns all recommendations corresponding to RP journals. * @return - List of recommendations */ public List<RPRecommendation> getJournalPoolsInRecommendation() { List<RPRecommendation> journalRecs = new ArrayList<RPRecommendation>(); if (getSourceJournalPoolsInRecommendation() != null) { journalRecs.add(getSourceJournalPoolsInRecommendation()); } if (getStandbyJournalPoolsInRecommendation() != null) { journalRecs.add(getStandbyJournalPoolsInRecommendation()); } List<RPRecommendation> targetJournalRecs = getTargetJournalPoolsInRecommendation(); if (null != targetJournalRecs && !targetJournalRecs.isEmpty()) { journalRecs.addAll(targetJournalRecs); } return journalRecs; } /** * Returns all recommendations corresponding to RP source journals. * @return - List of recommendations */ public RPRecommendation getSourceJournalPoolsInRecommendation() { if (this.getSourceJournalRecommendation() != null) { return this.getSourceJournalRecommendation(); } return null; } /** * Returns all recommendations corresponding to RP stand-by journals, applies to only Metropoint. * @return - List of recommendations */ public RPRecommendation getStandbyJournalPoolsInRecommendation() { if (this.getStandbyJournalRecommendation() != null) { return this.getStandbyJournalRecommendation(); } return null; } /** * Returns all recommendations corresponding to RP source. * @return - List of recommendations */ public List<RPRecommendation> getSourcePoolsInRecommendation() { List<RPRecommendation> sourcePoolsInRecommendation = new ArrayList<RPRecommendation>(); if (this.getSourceRecommendations() != null) { for(RPRecommendation srcRec : this.getSourceRecommendations()){ sourcePoolsInRecommendation.add(srcRec); if (srcRec.getHaRecommendation() != null) { sourcePoolsInRecommendation.add(srcRec.getHaRecommendation()); } } } return sourcePoolsInRecommendation; } /** * Returns all recommendations corresponding to RP target journals. * @return - List of recommendations */ public List<RPRecommendation> getTargetJournalPoolsInRecommendation() { List<RPRecommendation> tgtJrnlPoolsInRecommendation = new ArrayList<RPRecommendation>(); if (this.getTargetJournalRecommendations() != null) { for(RPRecommendation tgtJrnlRec : this.getTargetJournalRecommendations()){ tgtJrnlPoolsInRecommendation.add(tgtJrnlRec); } } return tgtJrnlPoolsInRecommendation; } /** * Returns all recommendations corresponding to RP targets. * @return - List of recommendations */ public List<RPRecommendation> getTargetPoolsInRecommendation() { List<RPRecommendation> targetPoolsInRecommendation = new ArrayList<RPRecommendation>(); if (this.getSourceRecommendations() != null) { for(RPRecommendation srcRec : this.getSourceRecommendations()){ if (srcRec.getTargetRecommendations() != null) { for(RPRecommendation tgtRec : srcRec.getTargetRecommendations()) { targetPoolsInRecommendation.add(tgtRec); } } } } return targetPoolsInRecommendation; } /** * @param dbClient * @return */ public String toString(DbClient dbClient) { StringBuffer buff = new StringBuffer(String.format("%nRecoverPoint Placement Results : %n")); buff.append(String.format("--------------------------------------%n")); RPRecommendation rpRecommendation = this.getSourceRecommendations().get(0); String protectionType = "Regular RP recommendation"; if (VirtualPool.vPoolSpecifiesMetroPoint(rpRecommendation.getVirtualPool())) { protectionType = "Metropoint RP recommendation"; } else if(VirtualPool.vPoolSpecifiesRPVPlex(rpRecommendation.getVirtualPool())) { protectionType = "RP/VPLEX recommendation"; } buff.append(String.format(protectionType + "%n")); ProtectionSystem ps = dbClient.queryObject(ProtectionSystem.class, getProtectionDevice()); buff.append(String.format("Total volumes placed : %s %n", + this.getResourceCount())); buff.append(String.format("Protection System : %s %n%n", ps.getLabel())); for (RPRecommendation sourceRecommendation : this.getSourceRecommendations()) { buff.append(String.format("Source Recommendation : %n")); buff.append(String.format("%s %n",sourceRecommendation.toString(dbClient, ps))); for (RPRecommendation targetRecommendation : sourceRecommendation.getTargetRecommendations()) { buff.append(String.format("Target Recommendation : %n")); buff.append(String.format("%s %n", targetRecommendation.toString(dbClient, ps))); } } buff.append("Journal Recommendation : "); String sourceJournalString = "Source"; if (standbyJournalRecommendation != null) { sourceJournalString = "Metropoint Active Source "; } buff.append(String.format("%s %n", sourceJournalString )); if (sourceJournalRecommendation != null) { buff.append(String.format("%s %n", sourceJournalRecommendation.toString(dbClient, ps))); } else { buff.append("\tNo Source Journal Recommedation required. Re-use existing Journal(s).\n\n"); } if (standbyJournalRecommendation != null) { buff.append(String.format("Journal Recommendation : Metropoint Standby Source %n")); buff.append(String.format("%s %n", standbyJournalRecommendation.toString(dbClient, ps))); } buff.append(String.format("Journal Recommendation : Target(s) %n")); if (!CollectionUtils.isEmpty(this.getTargetJournalRecommendations())) { for (RPRecommendation targetJournalRecommendation : getTargetJournalRecommendations()) { buff.append(String.format("%s", targetJournalRecommendation.toString(dbClient, ps))); } } else { buff.append("\tNo Target Journal Recommedation(s) required. Re-use existing Journal(s).\n\n"); } buff.append(String.format("--------------------------------------%n")); return buff.toString(); } }