/* * Copyright (c) 2012-2015 iWave Software LLC * All Rights Reserved */ package com.iwave.ext.netapp; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import com.google.common.collect.Lists; import com.iwave.ext.netapp.model.Quota; import com.iwave.ext.netapp.model.QuotaUser; import netapp.manage.NaAPIFailedException; import netapp.manage.NaElement; import netapp.manage.NaErrno; import netapp.manage.NaServer; public class QuotaCommands { public enum QuotaStatus { ON, OFF, RESIZING, INITIALIZING, SHUTTING_DOWN } private Logger log = Logger.getLogger(getClass()); private NaServer server = null; public QuotaCommands(NaServer server) { this.server = server; } public List<Quota> quotaReport(String path, String volume) { NaElement elem = new NaElement("quota-report"); if (StringUtils.isNotBlank(path)) { elem.addNewChild("path", path); } if (StringUtils.isNotBlank(volume)) { elem.addNewChild("volume", volume); } NaElement resultElem = null; try { resultElem = server.invokeElem(elem); } catch (Exception e) { throw createError(elem, e); } List<Quota> quotas = Lists.newArrayList(); for (NaElement e : (List<NaElement>) resultElem.getChildren()) { if ("error".equalsIgnoreCase(e.getName())) { String errno = e.getChildContent("errno"); String reason = e.getChildContent("reason"); String message = String.format("%s: %s", errno, reason); throw new NetAppException(message); } else if ("quotas".equalsIgnoreCase(e.getName())) { for (NaElement quotaElem : (List<NaElement>) e.getChildren()) { Quota quota = new Quota(); quota.setQtree(quotaElem.getChildContent("tree")); quota.setDiskLimit(quotaElem.getChildContent("disk-limit")); quota.setDiskUsed(quotaElem.getChildContent("disk-used")); quota.setFileLimit(quotaElem.getChildContent("file-limit")); quota.setFilesUsed(quotaElem.getChildContent("files-used")); quota.setQuotaTarget(quotaElem.getChildContent("quota-target")); quota.setQuotaType(quotaElem.getChildContent("quota-type")); quota.setSoftDiskLimit(quotaElem.getChildContent("soft-disk-limit")); quota.setSoftFileLimit(quotaElem.getChildContent("soft-file-limit")); quota.setThreshold(quotaElem.getChildContent("threshold")); quota.setVfiler(quotaElem.getChildContent("vfiler")); quota.setVolume(quotaElem.getChildContent("volume")); // users NaElement quotaUsersElem = (NaElement) quotaElem .getChildByName("quota-users"); if (quotaUsersElem != null) { for (NaElement quotaUserElem : (List<NaElement>) quotaUsersElem.getChildren()) { QuotaUser quotaUser = new QuotaUser(); quotaUser.setUserId(quotaUserElem.getChildContent("quota-user-id")); quotaUser.setUserName(quotaUserElem.getChildContent("quota-user-name")); quotaUser.setUserType(quotaUserElem.getChildContent("quota-user-type")); quota.getQuotaUsers().add(quotaUser); } } quotas.add(quota); } } } return quotas; } public Quota getTreeQuota(String volume, String path) { return getQuota(volume, path, "tree", ""); } public Quota getQuota(String volume, String quotaTarget, String quotaType, String qtree) { NaElement elem = new NaElement("quota-get-entry"); elem.addNewChild("volume", volume); elem.addNewChild("quota-target", quotaTarget); elem.addNewChild("quota-type", quotaType); elem.addNewChild("qtree", qtree); try { NaElement result = server.invokeElem(elem); Quota quota = new Quota(); quota.setVolume(volume); quota.setQuotaTarget(quotaTarget); quota.setQuotaType(quotaType); quota.setQtree(qtree); quota.setDiskLimit(result.getChildContent("disk-limit")); quota.setFileLimit(result.getChildContent("file-limit")); quota.setSoftDiskLimit(result.getChildContent("soft-disk-limit")); quota.setSoftFileLimit(result.getChildContent("soft-file-limit")); quota.setThreshold(result.getChildContent("threshold")); return quota; } catch (NaAPIFailedException e) { if (e.getErrno() == NaErrno.EQUOTADOESNOTEXIST) { return null; } throw createError(elem, e); } catch (Exception e) { throw createError(elem, e); } } public List<Quota> getTreeQuotas() { return getQuotas(); } public List<Quota> getQuotas() { NaElement elem = new NaElement("quota-list-entries-iter"); try { List<Quota> quotas = Lists.newArrayList(); NaElement result = server.invokeElem(elem); List<NaElement> quotaElems = new ArrayList<NaElement>(); //Add the Quotas for first call quotaElems.addAll((List<NaElement>)result.getChildByName("attributes-list").getChildren()); //Make further server invokes if more quotas are present while(result.getChildByName("next-tag")!=null){ NaElement tempElem = new NaElement("quota-list-entries-iter"); tempElem.addNewChild("tag", result.getChildContent("next-tag")); result = server.invokeElem(tempElem); quotaElems.addAll((List<NaElement>)result.getChildByName("attributes-list").getChildren()); } for (NaElement quotaElem : quotaElems) { Quota quota = new Quota(); quota.setVolume(quotaElem.getChildContent("volume")); quota.setQuotaTarget(quotaElem.getChildContent("quota-target")); quota.setQuotaType(quotaElem.getChildContent("quota-type")); quota.setQtree(quotaElem.getChildContent("qtree")); quota.setDiskLimit(quotaElem.getChildContent("disk-limit")); quota.setFileLimit(quotaElem.getChildContent("file-limit")); quota.setSoftDiskLimit(quotaElem.getChildContent("soft-disk-limit")); quota.setSoftFileLimit(quotaElem.getChildContent("soft-file-limit")); quota.setThreshold(quotaElem.getChildContent("threshold")); quotas.add(quota); } return quotas; } catch (NaAPIFailedException e) { if (e.getErrno() == NaErrno.EQUOTADOESNOTEXIST) { return null; } throw createError(elem, e); } catch (Exception e) { throw createError(elem, e); } } public void addDiskLimitTreeQuota(String volume, String path, long diskLimitInKB, long thresholdInKB) { addDiskLimitQuota(volume, path, "tree", "", diskLimitInKB, thresholdInKB); } public void modifyDiskLimitTreeQuota(String volume, String path, long diskLimitInKB, long thresholdInKB) { modifyDiskLimitQuota(volume, path, "tree", "", diskLimitInKB, thresholdInKB); } public void addDiskLimitQuota(String volume, String quotaTarget, String quotaType, String qtree, long diskLimitInKB, long thresholdInKB) { NaElement elem = new NaElement("quota-add-entry"); elem.addNewChild("volume", volume); elem.addNewChild("quota-target", quotaTarget); elem.addNewChild("quota-type", quotaType); elem.addNewChild("qtree", qtree); elem.addNewChild("disk-limit", String.valueOf(diskLimitInKB)); if (thresholdInKB > 0) { elem.addNewChild("threshold", String.valueOf(thresholdInKB)); } try { server.invokeElem(elem); } catch (Exception e) { throw createError(elem, e); } } public void setDiskLimitTreeQuota(String volume, String path, long diskLimitInKB, long thresholdInKB) { setDiskLimitQuota(volume, path, "tree", "", diskLimitInKB, thresholdInKB); } public void setDiskLimitQuota(String volume, String quotaTarget, String quotaType, String qtree, long diskLimitInKB, long thresholdInKB) { NaElement elem = new NaElement("quota-set-entry"); elem.addNewChild("volume", volume); elem.addNewChild("quota-target", quotaTarget); elem.addNewChild("quota-type", quotaType); elem.addNewChild("qtree", qtree); elem.addNewChild("disk-limit", String.valueOf(diskLimitInKB)); if (thresholdInKB > 0) { elem.addNewChild("threshold", String.valueOf(thresholdInKB)); } try { server.invokeElem(elem); } catch (Exception e) { throw createError(elem, e); } } public void modifyDiskLimitQuota(String volume, String quotaTarget, String quotaType, String qtree, long diskLimitInKB, long thresholdInKB) { NaElement elem = new NaElement("quota-modify-entry"); elem.addNewChild("volume", volume); elem.addNewChild("quota-target", quotaTarget); elem.addNewChild("quota-type", quotaType); elem.addNewChild("qtree", qtree); elem.addNewChild("disk-limit", String.valueOf(diskLimitInKB)); if (thresholdInKB > 0) { elem.addNewChild("threshold", String.valueOf(thresholdInKB)); } try { server.invokeElem(elem); } catch (Exception e) { throw createError(elem, e); } } public void deleteTreeQuota(String volume, String path) { deleteQuota(volume, path, "tree", ""); } public void deleteQuota(String volume, String quotaTarget, String quotaType, String qtree) { NaElement elem = new NaElement("quota-delete-entry"); elem.addNewChild("volume", volume); elem.addNewChild("quota-target", quotaTarget); elem.addNewChild("quota-type", quotaType); elem.addNewChild("qtree", qtree); try { server.invokeElem(elem); } catch (Exception e) { throw createError(elem, e); } } /** * Starts to turn quotas on for a volume. A successful return from this API does not mean that quotas are on, * merely that an attempt to start it has been triggered */ public void turnQuotaOn(String volume) { NaElement elem = new NaElement("quota-on"); elem.addNewChild("volume", volume); try { server.invokeElem(elem); } catch (Exception e) { throw createError(elem, e); } } /** * Turns the quota subsystem off for a volume */ public void turnQuotaOff(String volume) { NaElement elem = new NaElement("quota-off"); elem.addNewChild("volume", volume); try { server.invokeElem(elem); } catch (Exception e) { throw createError(elem, e); } } public void startQuotaResize(String volumeName) { NaElement elem = new NaElement("quota-resize"); elem.addNewChild("volume", volumeName); try { server.invokeElem(elem); } catch (Exception e) { String msg = "Failed to start quota resizing on volume: " + volumeName; log.error(msg, e); throw new NetAppException(msg, e); } } /** * Returns the current status of Quotas on the specified volume */ public QuotaStatus getQuotaStatus(String volumeName) { NaElement elem = new NaElement("quota-status"); elem.addNewChild("volume", volumeName); try { NaElement result = server.invokeElem(elem); String status = result.getChildContent("status"); if (status.equals("on")) { return QuotaStatus.ON; } else if (status.equals("off")) { return QuotaStatus.OFF; } else if (status.equals("resizing")) { return QuotaStatus.RESIZING; } else if (status.equals("shutting down")) { return QuotaStatus.SHUTTING_DOWN; } else { throw new NetAppException("Unknown quota status value " + status); } } catch (Exception e) { String msg = "Failed to get quota status: " + volumeName; log.error(msg, e); throw new NetAppException(msg, e); } } /** * Starts a Resize Quota operation on the specified volume. * * This only starts the resize operation and returns immediately, {@link #getQuotaStatus(String)} should be used * to find out when the current status of the operation */ public void startResize(String volumeName) { NaElement elem = new NaElement("quota-resize"); elem.addNewChild("volume", volumeName); try { server.invokeElem(elem); } catch (Exception e) { String msg = "Failed to start quota resizing on volume: " + volumeName; log.error(msg, e); throw new NetAppException(msg, e); } } protected NetAppException createError(NaElement elem, Exception e) { String message = "Failed to run " + elem.getName(); log.error(message, e); return new NetAppException(message, e); } }