/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.model;
import java.net.URI;
import java.util.Collection;
import java.util.Iterator;
@Cf("BlockConsistencyGroup")
public class BlockConsistencyGroup extends DataObject implements ProjectResource {
// device native ID for this consistency group
private String _nativeId;
/**
* Storage system where this consistency group is located
*/
private URI _storageController;
/**
* Virtual array where this consistency group exists
*/
private URI _virtualArray;
/**
* Project within this consistency group exists
*/
private NamedURI _project;
/**
* Tenant within this consistency group exists
*/
private NamedURI _tenant;
/**
* Unique name created by the NameGenerator Class
*/
@Deprecated
private String _deviceName;
/**
* SRDF CGs or Local.
*/
@Deprecated
private String type;
/**
* Types that this BlockConsistencyGroup maps to. A single
* BlockConsistencyGroup can map to multiple different consistency
* group types. This set is not filled in until the corresponding provisioning
* for each type has been completed.
*/
private StringSet types;
/**
* Requested types. This is initialized when we are first creating the CG, and
* then used to determine if the CG creation has completed by comparing it
* with types.
*/
private StringSet requestedTypes;
/**
* Alternate label used in SRDF.
*/
private String alternateLabel;
/**
* Maps the StorageSystem (for VPlex, VNX, VMAX) and/or ProtectionSystem (for RP)
* to the corresponding consistency groups that have been created.
*
* Here are the different permutations that can exist based on types:
* RP: [protectionSystem->cg1]
* LOCAL: [storageSystem->cg1]
* SRDF: [storageSystem->cg1]
* VPLEX: [storageSystem->[cluster-1:cg1,cluster-2:cg1]]
* RP,VPLEX: [protectionSystem->cg1,storageSystem->[cluster-1:cg1,cluster-2:cg1]]
*/
private StringSetMap systemConsistencyGroups;
/**
* If adding volumes or VPLEX backend volumes to replication group for each volume created
* in the consistency group.
* By default it is set to true. It would be turned to false if one of the volumes in the CG
* is added to an application (applicable to VPLEX/RP only)
*/
private Boolean arrayConsistency = true;
// Lock to indicate that journal provisioning is actively occurring
// on this CG. Currently used for concurrent RP provisioning requests.
private Long journalProvisioningLock = 0L;
public static enum Types {
/* RecoverPoint consistency group type. */
RP,
/* SRDF consistency group type. */
SRDF,
/* VPlex consistency group type. */
VPLEX,
/* Array-based consistency group type. */
LOCAL
}
@Name("nativeId")
public String getNativeId() {
return _nativeId;
}
public void setNativeId(String nativeId) {
_nativeId = nativeId;
setChanged("nativeId");
}
@RelationIndex(cf = "RelationIndex", type = StorageSystem.class)
@Name("storageDevice")
public URI getStorageController() {
return _storageController;
}
public void setStorageController(URI storageController) {
_storageController = storageController;
setChanged("storageDevice");
}
@Name("varray")
@RelationIndex(cf = "RelationIndex", type = VirtualArray.class)
public URI getVirtualArray() {
return _virtualArray;
}
public void setVirtualArray(URI virtualArray) {
_virtualArray = virtualArray;
setChanged("varray");
}
@Override
@Name("project")
@NamedRelationIndex(cf = "NamedRelation", type = Project.class)
public NamedURI getProject() {
return _project;
}
public void setProject(NamedURI project) {
_project = project;
setChanged("project");
}
@Override
@NamedRelationIndex(cf = "NamedRelation")
@Name("tenant")
public NamedURI getTenant() {
return _tenant;
}
public void setTenant(NamedURI tenant) {
_tenant = tenant;
setChanged("tenant");
}
@Name("deviceName")
@Deprecated
public String getDeviceName() {
return _deviceName;
}
@Deprecated
public void setDeviceName(String deviceName) {
_deviceName = deviceName;
setChanged("deviceName");
}
@AlternateId("AltIdIndex")
@Name("alternateLabel")
public String getAlternateLabel() {
return alternateLabel;
}
public void setAlternateLabel(String alternateLabel) {
this.alternateLabel = alternateLabel;
setChanged("alternateLabel");
}
// alternate label set only for target SRDF Groups
public boolean srdfTarget() {
return null != alternateLabel;
}
@Name("type")
@Deprecated
public String getType() {
return type;
}
@Deprecated
public void setType(String type) {
this.type = type;
setChanged("type");
}
@Name("types")
public StringSet getTypes() {
if (types == null) {
types = new StringSet();
}
return types;
}
public void setTypes(StringSet types) {
this.types = types;
setChanged("types");
}
@Name("requestedTypes")
public StringSet getRequestedTypes() {
// Handle migration case where we did not record requestedTypes by initializing it to Types
if (this.requestedTypes == null && this.types != null && !this.types.isEmpty()) {
requestedTypes = new StringSet();
requestedTypes.addAll(getTypes());
setRequestedTypes(requestedTypes);
return requestedTypes;
}
if (this.requestedTypes == null) {
requestedTypes = new StringSet();
}
return requestedTypes;
}
public boolean isProtectedCG() {
if (requestedTypes == null || requestedTypes.isEmpty()) {
return false;
}
return requestedTypes.contains(Types.RP.toString()) || requestedTypes.contains(Types.VPLEX.toString());
}
public boolean isRPProtectedCG() {
if (requestedTypes == null || requestedTypes.isEmpty()) {
return false;
}
return requestedTypes.contains(Types.RP.toString());
}
public void setRequestedTypes(StringSet requestedTypes) {
this.requestedTypes = requestedTypes;
setChanged("requestedTypes");
}
public void addRequestedTypes(Collection<String> addedTypes) {
if (this.requestedTypes == null) {
setRequestedTypes(new StringSet());
}
for (String type : addedTypes) {
getRequestedTypes().add(type);
}
}
@Name("systemConsistencyGroups")
public StringSetMap getSystemConsistencyGroups() {
return systemConsistencyGroups;
}
public void setSystemConsistencyGroups(
StringSetMap systemConsistencyGroups) {
this.systemConsistencyGroups = systemConsistencyGroups;
setChanged("systemConsistencyGroups");
}
/**
* Check whether this Consistency Group has been created. For each
* of the requested BlockConsistencyGroup types, we must have
* associated consistency groups that have been created,
* which is indicated by the presence in types. If nothing has been
* requested yet, we haven't created the consistencyGroup.
*
* @return true if the ConsistencyGroup has been created, false otherwise.
*/
public boolean created() {
return !getRequestedTypes().isEmpty() && getTypes().containsAll(getRequestedTypes());
}
/**
* Returns true if the given cg name(replicationGroupName) has been created on the given storage array.
*
* @param replicationGroupName Replication name to check on the storage system
* @param systemURI The ID of the storage system
* @return true if the CG is created on the storage system, false otherwise
*/
public boolean created(String replicationGroupName, URI systemURI) {
boolean status = false;
if (getSystemConsistencyGroups() != null && replicationGroupName != null && systemURI != null) {
StringSet replicationNameSet = getSystemConsistencyGroups().get(systemURI.toString());
if (replicationNameSet != null) {
Iterator<String> replicationNameIterator = replicationNameSet.iterator();
while (replicationNameIterator.hasNext()) {
String replicationName = replicationNameIterator.next();
if (replicationGroupName.equals(replicationName)) {
status = true;
break;
}
}
}
}
return status;
}
/**
* Returns true if CG creation has been initiated or even completed
* as given by something was recorded in requestedTypes().
*
* @return true if CG creation has been initiated.
*/
public boolean creationInitiated() {
return !getRequestedTypes().isEmpty();
}
/**
* Check to see if the consistency group has been created for the given
* storage system.
*
* @param storageSystemUri The storage system URI
* @return true if the consistency group has been created, false otherwise.
*/
public boolean created(URI storageSystemUri) {
if (storageSystemUri != null &&
systemConsistencyGroups != null && !systemConsistencyGroups.isEmpty()) {
StringSet cgNames = systemConsistencyGroups.get(storageSystemUri.toString());
if (cgNames != null && !cgNames.isEmpty()) {
return true;
}
}
return false;
}
/**
* Check to see if the consistency group has been created for the given
* storage system, and replication group name
*
* @param storageSystemUri The storage system URI
* @param replicationGroupName the replication group name to check on
* @return true if the consistency group has been created, false otherwise.
*/
public boolean created(URI storageSystemUri, String replicationGroupName) {
if (storageSystemUri != null &&
systemConsistencyGroups != null && !systemConsistencyGroups.isEmpty()) {
StringSet cgNames = systemConsistencyGroups.get(storageSystemUri.toString());
if (cgNames != null && !cgNames.isEmpty()) {
if (replicationGroupName != null && !replicationGroupName.isEmpty()) {
if (cgNames.contains(replicationGroupName)) {
return true;
} else {
return false;
}
} else {
return true;
}
}
}
return false;
}
/**
* Convenience method to add a consistency group type.
*
* @param types The types to add to this consistency group.
*/
public void addConsistencyGroupTypes(String... cgTypes) {
if (types == null) {
setTypes(new StringSet());
}
for (String type : cgTypes) {
types.add(type);
}
}
/**
* Determines if the consistency group has the passed type.
*
* @param type The type to check.
*
* @return true when the consistency group has the type, false otherwise.
*/
public boolean checkForType(Types type) {
if (types == null) {
return false;
} else {
return types.contains(type.toString());
}
}
/**
* Add a mapping of storage systems to consistency group names.
*
* @param systemUri The StorageSystem or ProtectionSystem URI string.
* @param cgName The consistency group name.
*/
public void addSystemConsistencyGroup(String systemUri, String cgName) {
if (systemConsistencyGroups == null) {
setSystemConsistencyGroups(new StringSetMap());
}
if (!systemConsistencyGroups.containsKey(systemUri)) {
systemConsistencyGroups.put(systemUri, new StringSet());
}
StringSet systemCgNames = systemConsistencyGroups.get(systemUri);
systemCgNames.add(cgName);
}
/**
* Remove a mapping of storage system to consistency group name.
*
* @param systemUri The StorageSystem or ProtectionSystem URI string.
* @param cgName The consistency group name.
*/
public void removeSystemConsistencyGroup(String systemUri, String cgName) {
if ((systemConsistencyGroups != null) && (systemConsistencyGroups.containsKey(systemUri))) {
StringSet systemCgNames = systemConsistencyGroups.get(systemUri);
systemCgNames.remove(cgName);
if (systemCgNames.isEmpty()) {
systemConsistencyGroups.remove(systemUri);
}
}
}
/**
* Gets the first CG name that corresponds to the provided storage system URI.
* A BlockConsistencyGroup can only map to a single consistency group on a single
* storage system so that's why we only return the first entry.
*
* @param storageSystemUri Storage System URI to check CG name with
* @return The CG name
*/
public String fetchArrayCgName(URI storageSystemUri) {
if (storageSystemUri == null) {
return null;
}
if (systemConsistencyGroups != null && !systemConsistencyGroups.isEmpty()) {
StringSet cgNames = systemConsistencyGroups.get(storageSystemUri.toString());
if (cgNames != null && cgNames.iterator().hasNext()) {
return cgNames.iterator().next();
}
}
return null;
}
/**
* checks to see if the CG name matches the name ViPR has stored for the storage system
*
* @param cgId id of the CG in the DB
* @param storageSystemId storage system to check the CG name
* @param cgParams cg params with CG name
* @return true if the CG name exists in the ViPR db
*/
public boolean nameExistsForStorageSystem(URI storageSystemId, String cgName) {
return (cgName != null ? cgName.equals(getCgNameOnStorageSystem(storageSystemId))
: false);
}
/**
* Returns the name of the CG on the storage system if ViPR has created this CG on the storage system in the past.
*
* @param cgId id of the CG in the ViPR db
* @param storageSystemId storage system to get the name for
* @return the CG name or null if ViPR has not created the CG on the storage system
*/
public String getCgNameOnStorageSystem(URI storageSystemId) {
String cgName = null;
StringSetMap ssm = this.getSystemConsistencyGroups();
if (ssm != null) {
StringSet ss = ssm.get(storageSystemId.toString());
if (ss != null) {
Iterator<String> itr = ss.iterator();
if (itr.hasNext()) {
cgName = itr.next();
}
}
}
return cgName;
}
@Name("arrayConsistency")
public Boolean getArrayConsistency() {
return arrayConsistency;
}
public void setArrayConsistency(Boolean arrayConsistency) {
this.arrayConsistency = arrayConsistency;
setChanged("arrayConsistency");
}
@Name("journalProvisioningLock")
public Long getJournalProvisioningLock() {
return journalProvisioningLock;
}
public void setJournalProvisioningLock(Long journalProvisioningLock) {
this.journalProvisioningLock = journalProvisioningLock;
setChanged("journalProvisioningLock");
}
}