/*
* Copyright (c) 2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.vplex.api;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Info for a VPlex virtual volume.
*/
public class VPlexVirtualVolumeInfo extends VPlexResourceInfo {
// Values for rebuild completion status
public enum WaitOnRebuildResult {
SUCCESS,
FAILED,
TIMED_OUT,
INVALID_REQUEST
}
// Values for expansion status
public enum ExpansionStatus {
INPROGRESS("in-progress"),
FAILED("failed"),
UNKNOWN("unknown");
// The VPlex expansion status value.
private String _status;
/**
* Constructor.
*
* @param status The VPlex expansion status value
*/
ExpansionStatus(String status) {
_status = status;
}
/**
* Getter for the VPlex expansion status value.
*
* @return The VPlex expansion status value.
*/
public String getStatus() {
return _status;
}
}
// Values for service status
public enum ServiceStatus {
unexported;
}
// Values for service status
public enum Locality {
local,
distributed;
}
// Enumerates the virtual volume attributes we are interested in and
// parse from the VPlex virtual volume response. There must be a setter
// method for each attribute specified. The format of the setter
// method must be as specified by the base class method
// getAttributeSetterMethodName.
public static enum VirtualVolumeAttribute {
BLOCK_COUNT("block-count"),
BLOCK_SIZE("block-size"),
EXPANSION_STATUS("expansion-status"),
SUPPORTING_DEVICE("supporting-device"),
SERVICE_STATUS("service-status"),
THIN_CAPABLE("thin-capable"),
THIN_ENABLED("thin-enabled"),
LOCALITY("locality"),
VPD_ID("vpd-id"),
EXPANDABLE_CAPACITY("expandable-capacity");
// The VPlex name for the attribute.
private String _name;
/**
* Constructor.
*
* @param name The VPlex attribute name.
*/
VirtualVolumeAttribute(String name) {
_name = name;
}
/**
* Getter for the VPlex name for the attribute.
*
* @return The VPlex name for the attribute.
*/
public String getAttributeName() {
return _name;
}
/**
* Returns the enum whose name matches the passed name, else null when
* not found.
*
* @param name The name to match.
*
* @return The enum whose name matches the passed name, else null when
* not found.
*/
public static VirtualVolumeAttribute valueOfAttribute(String name) {
VirtualVolumeAttribute[] volumeAtts = values();
for (int i = 0; i < volumeAtts.length; i++) {
if (volumeAtts[i].getAttributeName().equals(name)) {
return volumeAtts[i];
}
}
return null;
}
};
// The block count.
private String blockCount;
// The block size in Bytes.
private String blockSize;
// The expansion status
private String expansionStatus;
// The name of the local or distributed device supporting
// this virtual volume.
private String supportingDevice;
// A reference to the supporting device info, which could be
// a VPlexDeviceInfo or VPlexDistributedDeviceInfo depending
// upon the locality of the volume.
private VPlexResourceInfo supportingDeviceInfo;
// The service status
private String serviceStatus;
// The thin-capable status
private String thinCapable;
// The thin-enabled status
private String thinEnabled;
// The locality of the virtual volume.
private String locality;
// The clusters for the virtual volume.
private List<String> clusters = new ArrayList<String>();
// The volume id containing the WWN.
private String vpdId;
// The expandable capacity for the volume.
private String expandableCapacity;
/**
* Getter for the volume block count.
*
* @return The volume block count.
*/
public String getBlockCount() {
return blockCount;
}
/**
* Setter for the volume block count.
*
* @param strVal The volume block count.
*/
public void setBlockCount(String strVal) {
blockCount = strVal;
}
/**
* Getter for the volume block size.
*
* @return The volume block size.
*/
public String getBlockSize() {
return blockSize;
}
/**
* Setter for the volume block size.
*
* @param strVal The volume block size.
*/
public void setBlockSize(String strVal) {
blockSize = strVal;
}
/**
* Getter for the volume expansion status.
*
* @return The volume expansion status.
*/
public String getExpansionStatus() {
return expansionStatus;
}
/**
* Setter for the volume expansion status.
*
* @param strVal The volume expansion status.
*/
public void setExpansionStatus(String strVal) {
expansionStatus = strVal;
}
/**
* Getter for the supporting device name.
*
* @return The supporting device name.
*/
public String getSupportingDevice() {
return supportingDevice;
}
/**
* Setter for the supporting device name.
*
* @param strVal The supporting device name.
*/
public void setSupportingDevice(String strVal) {
supportingDevice = strVal;
}
/**
* Getter for the supporting device information.
*
* @return The supporting device information.
*/
public VPlexResourceInfo getSupportingDeviceInfo() {
return supportingDeviceInfo;
}
/**
* Setter for the supporting device information.
*
* @param resourceInfo The supporting device information.
*/
public void setSupportingDeviceInfo(VPlexResourceInfo resourceInfo) {
supportingDeviceInfo = resourceInfo;
}
/**
* Getter for the volume service status.
*
* @return The volume service status.
*/
public String getServiceStatus() {
return serviceStatus;
}
/**
* Setter for the volume service status.
*
* @param strVal The volume service status.
*/
public void setServiceStatus(String strVal) {
serviceStatus = strVal;
}
/**
* Getter for the volume thin-capable status.
*
* @return The volume thin-capable status.
*/
public String getThinCapable() {
return thinCapable;
}
/**
* Setter for the volume thin-capable status.
*
* @param strVal The volume thin-capable status.
*/
public void setThinCapable(String strVal) {
thinCapable = strVal;
}
/**
* Getter for the volume thin-enabled status.
*
* @return The volume thin-enabled status.
*/
public String getThinEnabled() {
return thinEnabled;
}
/**
* Setter for the volume thin-enabled status.
*
* @param strVal The volume thin-enabled status.
*/
public void setThinEnabled(String strVal) {
thinEnabled = strVal;
}
/**
* Getter for the volume locality.
*
* @return The volume locality.
*/
public String getLocality() {
return locality;
}
/**
* Setter for the volume locality.
*
* @param strVal The volume locality.
*/
public void setLocality(String strVal) {
locality = strVal;
}
/**
* Getter for the volume clusters.
*
* @return The volume clusters.
*/
public List<String> getClusters() {
return clusters;
}
/**
* Adds the passed cluster to the list of clusters for the volume.
*
* @param clusterId The clusterId.
*/
public void addCluster(String clusterId) {
if (!clusters.contains(clusterId)) {
clusters.add(clusterId);
}
}
/**
* Getter for the volume vpd-id.
*
* @return The volume vpd-id.
*/
public String getVpdId() {
return vpdId;
}
/**
* Setter for the volume vpd-id.
*
* @param strVal The volume vpd-id.
*/
public void setVpdId(String strVal) {
vpdId = strVal;
}
/**
* Getter for the volume expandable-capacity.
*
* @return The volume expandable-capacity.
*/
public String getExpandableCapacity() {
return expandableCapacity;
}
/**
* Setter for the volume expandable-capacity.
*
* @param strVal The volume expandable-capacity.
*/
public void setExpandableCapacity(String strVal) {
expandableCapacity = strVal;
}
/**
* Getter for the volume WWN, parsed
* from the vpd-id value.
*
* @return the volume's WWN or null if none
*/
public String getWwn() {
if (null != vpdId) {
if (vpdId.startsWith(VPlexApiConstants.VOLUME_WWN_PREFIX)) {
return vpdId.substring(VPlexApiConstants.VOLUME_WWN_PREFIX.length());
} else if (vpdId.startsWith(VPlexApiConstants.VOLUME_WWN_PREFIX_T2)) {
return vpdId.substring(VPlexApiConstants.VOLUME_WWN_PREFIX_T2.length());
}
}
return null;
}
/**
* Return the virtual volume capacity in bytes.
*
* @return The virtual volume capacity in bytes.
*
* @throws VPlexApiException For an invalid formatted capacity.
*/
public Long getCapacityBytes() throws VPlexApiException {
if ((blockCount == null) || (VPlexApiConstants.NULL_ATT_VAL.equals(blockCount)) ||
(blockSize == null) || (VPlexApiConstants.NULL_ATT_VAL.equals(blockSize))) {
return null;
}
// Note block size is assumed to be in Bytes, which is what the
// VPlex returns.
Pattern p = Pattern.compile("(\\d+)");
Matcher m = p.matcher(blockSize);
if (m.find()) {
Long blockSizeBytes = Long.valueOf(m.group(1));
m = p.matcher(blockCount);
if (m.find()) {
return Long.valueOf(m.group(1)) * blockSizeBytes;
} else {
throw VPlexApiException.exceptions.unexpectedBlockCountFormat(blockCount);
}
} else {
throw VPlexApiException.exceptions.unexpectedBlockSizeFormat(blockSize);
}
}
/**
* Update the virtual volume name after path of the virtual volume
* when a migration associated with the virtual volume is committed.
*
* @param updatedName The new name.
*/
public void updateNameOnMigrationCommit(String updatedName) {
// When a migration for the virtual volume is committed, we
// update the name and path to reflect the new underlying
// volume, which is the migration target.
String currentPath = getPath();
setPath(currentPath.replace(getName(), updatedName));
setName(updatedName);
}
/**
* Returns whether or not the volume is exported.
*
* @return true if the volume is exported, false otherwise.
*/
public boolean isExported() {
return (!ServiceStatus.unexported.name().equals(serviceStatus));
}
/**
* Returns whether or not the volume is thin-enabled.
*
* @return true if the volume is thin enabled, false otherwise.
*/
public boolean isThinEnabled() {
// need to check both thin-capable=true && thin-enabled=true|enabled
return VPlexApiConstants.TRUE.equalsIgnoreCase(getThinCapable()) &&
(VPlexApiConstants.TRUE.equalsIgnoreCase(getThinEnabled())
|| VPlexApiConstants.ENABLED.equalsIgnoreCase(getThinEnabled()));
}
/**
* {@inheritDoc}
*/
@Override
public List<String> getAttributeFilters() {
List<String> attFilters = new ArrayList<String>();
for (VirtualVolumeAttribute att : VirtualVolumeAttribute.values()) {
attFilters.add(att.getAttributeName());
}
return attFilters;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder str = new StringBuilder();
str.append("VirtualVolumeInfo ( ");
str.append(super.toString());
str.append(", blockCount: ").append(blockCount);
str.append(", blockSize: ").append(blockSize);
str.append(", expansionStatus: ").append(expansionStatus);
str.append(", supportingDevice: ").append(supportingDevice);
if (supportingDeviceInfo != null) {
str.append(", supportingDeviceInfo: ").append(supportingDeviceInfo.toString());
}
str.append(", serviceStatus: ").append(serviceStatus);
str.append(", thinCapable: ").append(thinCapable);
str.append(", thinEnabled: ").append(thinEnabled);
str.append(", locality: ").append(locality);
str.append(", clusters: ").append(clusters);
str.append(", vpdId: ").append(vpdId);
str.append(", expandableCapacity: ").append(expandableCapacity);
str.append(" )");
return str.toString();
}
}