/*
* Copyright (c) 2012-2015 iWave Software LLC
* All Rights Reserved
*/
package com.iwave.ext.netappc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import netapp.manage.NaElement;
import netapp.manage.NaServer;
import org.apache.log4j.Logger;
public class FlexVolume {
private Logger log = Logger.getLogger(getClass());
private String name = "";
private NaServer server = null;
public FlexVolume(NaServer server, String volumeName)
{
this.server = server;
name = volumeName;
}
/**
* Takes a volume offline
*
* @param delayInMinutes - number of minutes to wait before the volume goes offline.
* Use zero to take offline immediately.
*/
public void setVolumeOffline(int delayInMinutes)
{
if (!isOnline()) {
log.info("volume " + name + " is already offline.");
return;
}
NaElement elem = new NaElement("volume-offline");
elem.addNewChild("name", name);
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to volume off line: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
boolean isOnline() {
return "online".equals(getVolumeInfo().get("state"));
}
/**
* Creates a new flexible volume. Only parameters for flexible volumes are provided.
* Note the volume may not be operational immediately after this method returns. Use
* getVolumeInfo() to query the status of the new volume.
*
* @param containingAggrName - Optional. Name of the aggregate in which to create the volume. Must
* be used in conjunction with the size parameter.
* @param path - Optional. The junction path where the volume is to be mounted.
* @param size - Optional. Size (with unit) of the new volume. Ex: 10g, 2000m, 1t. Must be used
* in conjunction with containingAggrName.
* @param spaceReserve - Optional. Type of volume guarantee new volume will use. Valid
* values are "none", "file", "volume".
* @param permission - Optional. Unix permission bits in octal string format.
* @return
*/
public boolean createFlexibleVolume(String containingAggrName,
String path, String size, String spaceReserve, String permission)
{
NaElement elem = new NaElement("volume-create");
elem.addNewChild("volume", name);
// Remaining params are optional
if (containingAggrName != null && !containingAggrName.isEmpty()) {
elem.addNewChild("containing-aggr-name", containingAggrName);
}
if (size != null && !size.isEmpty()) {
elem.addNewChild("size", size);
}
if (path != null && !path.isEmpty()) {
elem.addNewChild("junction-path", path);
}
if (spaceReserve != null && !spaceReserve.isEmpty()) {
elem.addNewChild("space-reserve", spaceReserve);
}
if (permission != null && !permission.isEmpty()) {
elem.addNewChild("unix-permissions", permission);
}
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to create new volume: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return true;
}
/**
* Destroys a volume, releasing all storage blocks assigned to it.
*
* @param force - force destroy. Set to false if unsure.
* @return - true if successful, false if the operation failed
*/
public boolean destroyVolume(boolean force)
{
NaElement elem = new NaElement("volume-destroy");
elem.addNewChild("name", name);
try {
server.invokeElem(elem);
return true;
} catch (Exception e) {
String msg = "Failed to destroy volume: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
/**
* Unmounts a volume
*
* @param force - force unmount. Set to false if unsure.
* @return - true if successful, false if the operation failed
*/
public boolean unmountVolume(boolean force)
{
NaElement elem = new NaElement("volume-unmount");
elem.addNewChild("force", Boolean.toString(force));
elem.addNewChild("volume-name", name);
try {
server.invokeElem(elem);
return true;
} catch (Exception e) {
String msg = "Failed to unmount volume: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
/**
* Returns a name-value pair map of the volume settings.
*
* @param verbose - set to true for all settings
* @return - map of volume setting name/value.
*/
public Map<String, String> getVolumeInfo()
{
Map<String, String> result = null;
NaElement elem = new NaElement("volume-get-iter");
if (name != null && !name.isEmpty()) {
NaElement volumeIdAttrs = new NaElement("volume-id-attributes");
volumeIdAttrs.addNewChild("name", name);
NaElement volumeAttrs = new NaElement("volume-attributes");
volumeAttrs.addChildElem(volumeIdAttrs);
NaElement query = new NaElement("query");
query.addChildElem(volumeAttrs);
elem.addChildElem(query);
}
NaElement resultElem = null;
String tag = null;
try {
do {
NaElement results = server.invokeElem(elem);
tag = results.getChildContent("next-tag");
resultElem = results.getChildByName("attributes-list");
if (resultElem != null) {
for (NaElement volInfo : (List<NaElement>) resultElem.getChildren()) {
result = new HashMap<String, String>();
NaElement volIdAttrs = volInfo.getChildByName("volume-id-attributes");
if (volIdAttrs != null) {
for (NaElement info : (List<NaElement>) volIdAttrs.getChildren()) {
result.put(info.getName(), info.getContent());
}
}
NaElement volStateAttrs = volInfo.getChildByName("volume-state-attributes");
if (volStateAttrs != null) {
for (NaElement info : (List<NaElement>) volStateAttrs.getChildren()) {
result.put(info.getName(), info.getContent());
}
}
}
}
if (tag != null && !tag.isEmpty()) {
elem = new NaElement("volume-get-iter");
elem.addNewChild("tag", tag);
}
} while (tag != null && !tag.isEmpty());
} catch (Exception e) {
String msg = "Failed to get volume info: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return result;
}
/**
* Returns the size of the volume
*
* @return
*/
String getVolumeSize()
{
String size = "";
NaElement elem = new NaElement("volume-size");
elem.addNewChild("volume", name);
NaElement result = null;
try {
result = server.invokeElem(elem);
size = result.getChildContent("volume-size");
} catch (Exception e) {
String msg = "Failed to retrieve size of volume: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return size;
}
/**
* Sets a new size of a volume.
*
* @param newSize - Size (with unit) of the new volume. Ex: 10g, 2000m, 1t.
* @return - The new size of the volume.
*/
public String setVolumeSize(String newSize)
{
String size = "";
NaElement elem = new NaElement("volume-size");
elem.addNewChild("volume", name);
elem.addNewChild("new-size", newSize);
NaElement result = null;
try {
result = server.invokeElem(elem);
size = result.getChildContent("volume-size");
} catch (Exception e) {
String msg = "Failed to set size of volume: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return size;
}
public List<String> listVolumes()
{
NaElement elem = new NaElement("volume-get-iter");
NaElement resultElem = null;
String tag = null;
ArrayList<String> volumes = new ArrayList<String>();
try {
do {
NaElement result = server.invokeElem(elem);
tag = result.getChildContent("next-tag");
resultElem = result.getChildByName("attributes-list");
if (resultElem != null) {
for (NaElement volInfo : (List<NaElement>) resultElem.getChildren()) {
NaElement volAttrs = volInfo.getChildByName("volume-id-attributes");
if (volAttrs != null) {
volumes.add(volAttrs.getChildContent("name"));
}
}
}
if (tag != null && !tag.isEmpty()) {
elem = new NaElement("volume-get-iter");
elem.addNewChild("tag", tag);
}
} while (tag != null && !tag.isEmpty());
} catch (Exception e) {
String msg = "Failed to get list of Volumes.";
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return volumes;
}
public List<Map<String, String>> listVolumeInfo(Collection<String> attrs)
{
NaElement elem = new NaElement("volume-get-iter");
ArrayList<Map<String, String>> volumes = new ArrayList<Map<String, String>>();
if (name != null && !name.isEmpty()) {
NaElement volumeIdAttrs = new NaElement("volume-id-attributes");
volumeIdAttrs.addNewChild("name", name);
NaElement volumeAttrs = new NaElement("volume-attributes");
volumeAttrs.addChildElem(volumeIdAttrs);
NaElement query = new NaElement("query");
query.addChildElem(volumeAttrs);
elem.addChildElem(query);
}
NaElement resultElem = null;
String tag = null;
try {
do {
NaElement result = server.invokeElem(elem);
tag = result.getChildContent("next-tag");
resultElem = result.getChildByName("attributes-list");
if (resultElem != null) {
for (NaElement volInfo : (List<NaElement>) resultElem.getChildren()) {
Map<String, String> infos = new HashMap<String, String>();
NaElement volAttrs = volInfo.getChildByName("volume-id-attributes");
if (volAttrs != null) {
for (NaElement info : (List<NaElement>) volAttrs.getChildren()) {
String name = info.getName();
if (attrs == null || attrs.contains(name) || name.equals("name")) {
infos.put(name, info.getContent());
}
}
}
NaElement volSpaceAttrs = volInfo.getChildByName("volume-space-attributes");
if (volSpaceAttrs != null) {
for (NaElement info : (List<NaElement>) volSpaceAttrs.getChildren()) {
String name = info.getName();
if (attrs == null || attrs.contains(name)) {
infos.put(name, info.getContent());
}
}
}
NaElement volStateAttrs = volInfo.getChildByName("volume-state-attributes");
if (volStateAttrs != null) {
for (NaElement info : (List<NaElement>) volStateAttrs.getChildren()) {
String name = info.getName();
if (attrs == null || attrs.contains(name)) {
infos.put(name, info.getContent());
}
}
}
volumes.add(infos);
}
}
if (tag != null && !tag.isEmpty()) {
elem = new NaElement("volume-get-iter");
elem.addNewChild("tag", tag);
}
} while (tag != null && !tag.isEmpty());
} catch (Exception e) {
String msg = "Failed to get list of Volumes.";
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return volumes;
}
/**
* Creates a new snapshot of the volume.
*
* @param snapshotName - Required. Name of the snapshot.
* @param async - Optional. Default is false. True indicates created asynchronously.
* @return - true/false if operation succeeded.
*/
boolean createSnapshot(String snapshotName, boolean async)
{
NaElement elem = new NaElement("snapshot-create");
elem.addNewChild("volume", name);
elem.addNewChild("snapshot", snapshotName);
elem.addNewChild("async", Boolean.toString(async));
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to create snapshot on volume: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return true;
}
/**
* Deletes a snapshot given the snapshot name.
*
* @param snapshotName - name of the snapshot to delete.
* @return - true/false if operation succeeded.
*/
boolean deleteSnapshot(String snapshotName)
{
NaElement elem = new NaElement("snapshot-delete");
elem.addNewChild("volume", name);
elem.addNewChild("snapshot", snapshotName);
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to delete snapshot: " + snapshotName;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return true;
}
/**
* Restores a volume to a specified snapshot.
*
* @param snapshotName - Name of the snapshot to restore from.
* @return - true/false if operation succeeded.
*/
boolean restoreVolumeFromSnapshot(String snapshotName)
{
NaElement elem = new NaElement("snapshot-restore-volume");
elem.addNewChild("volume", name);
elem.addNewChild("snapshot", snapshotName);
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to restore volume to specified snapshot: " + snapshotName;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return true;
}
/**
* Deletes a snapshot given the snapshot name.
*
* @param snapshotName - name of the snapshot to delete.
* @return - List<String> list of snapsshots for .
*/
List<String> listSnapshots(Collection<String> attrs)
{
NaElement elem = new NaElement("snapshot-get-iter");
NaElement resultElem = null;
String tag = null;
NaElement volumeElem = new NaElement("volume-get-iter");
if (name != null && !name.isEmpty()) {
NaElement volumeIdAttrs = new NaElement("volume-id-attributes");
volumeIdAttrs.addNewChild("name", name);
NaElement volumeAttrs = new NaElement("volume-attributes");
volumeAttrs.addChildElem(volumeIdAttrs);
NaElement query = new NaElement("query");
query.addChildElem(volumeAttrs);
volumeElem.addChildElem(query);
}
try {
do {
NaElement result = server.invokeElem(volumeElem);
tag = result.getChildContent("next-tag");
resultElem = result.getChildByName("attributes-list");
if (resultElem != null) {
for (NaElement volInfo : (List<NaElement>) resultElem.getChildren()) {
NaElement volAttrs = volInfo.getChildByName("volume-id-attributes");
if (volAttrs != null) {
String volumeName = volAttrs.getChildContent("name");
if (volumeName.equalsIgnoreCase(name)) {
NaElement snapshotInfo = new NaElement("snapshot-info");
snapshotInfo.addNewChild("volume-provenance-uuid", volAttrs.getChildContent("provenance-uuid"));
NaElement query = new NaElement("query");
query.addChildElem(snapshotInfo);
elem.addChildElem(query);
break;
}
}
}
}
if (tag != null && !tag.isEmpty()) {
volumeElem = new NaElement("volume-get-iter");
volumeElem.addNewChild("tag", tag);
}
} while (tag != null && !tag.isEmpty());
} catch (Exception e) {
String msg = "Failed to list volumes: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
ArrayList<String> snaps = new ArrayList<String>();
try {
do {
resultElem = server.invokeElem(elem);
tag = resultElem.getChildContent("next-tag");
if (resultElem != null) {
for (NaElement e : (List<NaElement>) resultElem.getChildren()) {
for (NaElement info : (List<NaElement>) e.getChildren()) {
for (NaElement info2 : ((List<NaElement>) info.getChildren())) {
String name = info2.getName();
if (attrs == null || attrs.contains(name) || name.equals("name")) {
snaps.add(info2.getContent());
}
}
}
}
}
if (tag != null && !tag.isEmpty()) {
elem = new NaElement("snapshot-get-iter");
elem.addNewChild("tag", tag);
}
} while (tag != null && !tag.isEmpty());
} catch (Exception e) {
String msg = "Failed to list snapshot for volume: " + name;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return snaps;
}
}