/*
* Copyright (c) 2012-2015 iWave Software LLC
* All Rights Reserved
*/
/**
*
*/
package com.iwave.ext.netappc;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashMap;
import netapp.manage.NaAPIFailedException;
import netapp.manage.NaElement;
import netapp.manage.NaServer;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.google.common.collect.Lists;
import com.iwave.ext.netappc.NFSSecurityStyle;
import com.iwave.ext.netappc.model.CifsAcl;
import com.iwave.ext.netappc.model.CifsAccess;
import com.iwave.ext.netapp.model.ExportsHostnameInfo;
import com.iwave.ext.netapp.model.ExportsRuleInfo;
import com.iwave.ext.netapp.model.Qtree;
import com.iwave.ext.netapp.model.SecurityRuleInfo;
import com.iwave.ext.netapp.utils.ExportRule;
public class FlexFileShare {
private Logger log = Logger.getLogger(getClass());
private static final String ROOT_USER = "root";
private static final String NO_ROOT_USERS = "nobody";
private static final String SEC_FLAVOR_NEVER = "never";
private static final String SEC_FLAVOR_NONE = "none";
private static final String RO_PERMISSION = "ro";
private static final String RW_PERMISSION = "rw";
private static final String ROOT_PERMISSION = "root";
private static final String DEFAULT_EXPORT_POLICY = "default";
private static final String UNEXPORTED_EXPORT_POLICY = "unexport_policy";
private static final int DISABLE_ROOT_ACCESS_CODE = 65535;
private static final int DEFAULT_ANONMOUS_ROOT_ACCESS = 65534;
private String mountPath = "";
private NaServer server = null;
public FlexFileShare(NaServer server, String mountPath)
{
this.server = server;
this.mountPath = mountPath;
}
boolean addCIFSShare(String shareName, String comment, int maxusers, String forcegroup)
{
NaElement elem = new NaElement("cifs-share-create");
elem.addNewChild("path", mountPath);
elem.addNewChild("share-name", shareName);
if (comment != null && !comment.isEmpty()) {
elem.addNewChild("comment", comment);
}
if (maxusers > 0) {
elem.addNewChild("maxusers", String.valueOf(maxusers));
}
if (forcegroup != null && !forcegroup.isEmpty()) {
elem.addNewChild("forcegroup", forcegroup);
}
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to create CIFS share on path: " + mountPath;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return true;
}
void deleteCIFSShare(String shareName)
{
NaElement elem = new NaElement("cifs-share-delete");
elem.addNewChild("share-name", shareName);
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to delete CIFS share: " + shareName;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
void changeCIFSShare(String shareName, Map<String, String> attrs)
{
NaElement elem = new NaElement("cifs-share-change");
elem.addNewChild("share-name", shareName);
for (String key : attrs.keySet()) {
elem.addNewChild(key, attrs.get(key)); // NOSONAR("Fix this in future release to avoid regression")
}
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to change CIFS share: " + shareName + " attrs: " + attrs;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
public void setCIFSAcl(CifsAcl acl)
{
NaElement elem = new NaElement("cifs-share-access-control-modify");
elem.addNewChild("share", acl.getShareName());
elem.addNewChild("permission", acl.getAccess().access());
if (acl.getUserName() != null) {
elem.addNewChild("user-or-group", acl.getUserName());
}
if (acl.getGroupName() != null) {
elem.addNewChild("user-or-group", acl.getGroupName());
}
try {
server.invokeElem(elem);
} catch (NaAPIFailedException e) {
String msg = "Failed to set CIFS Acl: " + acl;
log.error(msg, e);
throw new NetAppCException(msg, e, e.getErrno());
} catch (Exception e) {
String msg = "Failed to set CIFS Acl: " + acl;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
/**
* this function add new acl
*
* @param acl
*/
public void addCIFSAcl(CifsAcl acl)
{
NaElement elem = new NaElement("cifs-share-access-control-create");
elem.addNewChild("share", acl.getShareName());
elem.addNewChild("permission", acl.getAccess().access());
if (acl.getUserName() != null) {
elem.addNewChild("user-or-group", acl.getUserName());
}
if (acl.getGroupName() != null) {
elem.addNewChild("user-or-group", acl.getGroupName());
}
try {
server.invokeElem(elem);
} catch (NaAPIFailedException e) {
String msg = "Failed to create CIFS Acl: " + acl;
log.error(msg, e);
throw new NetAppCException(msg, e, e.getErrno());
} catch (Exception e) {
String msg = "Failed to create CIFS Acl: " + acl;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
@SuppressWarnings("unchecked")
List<Map<String, String>> listCIFSInfo(String shareName)
{
ArrayList<Map<String, String>> shares = new ArrayList<Map<String, String>>();
NaElement elem = new NaElement("cifs-share-get-iter");
if (shareName != null && !shareName.isEmpty()) {
NaElement accessAttr = new NaElement("cifs-share");
accessAttr.addNewChild("share-name", shareName);// shareName can contain wildcards * or ?
NaElement query = new NaElement("query");
query.addChildElem(accessAttr);
elem.addChildElem(query);
}
String tag = null;
try {
do {
NaElement result = server.invokeElem(elem);
tag = result.getChildContent("next-tag");
NaElement naElement = result.getChildByName("attributes-list");
if (naElement != null) {
List<NaElement> shareElems = naElement.getChildren();
if (shareElems != null && !shareElems.isEmpty()) {
for (NaElement shareElem : shareElems) {
// {description=Testing, share-name=demotest, mount-point=/vol/volscott}
Map<String, String> share = new HashMap<String, String>();
for (NaElement info : (List<NaElement>) shareElem.getChildren()) {
share.put(info.getName(), info.getContent());
}
shares.add(share);
}
}
}
if (tag != null && !tag.isEmpty()) {
elem = new NaElement("cifs-share-get-iter");
elem.addNewChild("tag", tag);
}
} while (tag != null && !tag.isEmpty());
return shares;
} catch (Exception e) {
String msg = "Failed to list CIFS shares.";
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
public void deleteCIFSAcl(CifsAcl acl)
{
NaElement elem = new NaElement("cifs-share-access-control-delete");
elem.addNewChild("share", acl.getShareName());
if (acl.getUserName() != null) {
elem.addNewChild("user-or-group", acl.getUserName());
}
if (acl.getGroupName() != null) {
elem.addNewChild("user-or-group", acl.getGroupName());
}
try {
server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to delete CIFS Acl: " + acl;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
public List<CifsAcl> listCIFSAcls(String shareName) {
List<CifsAcl> acls = new ArrayList<CifsAcl>();
String tagNext = null;
NaElement elem = new NaElement("cifs-share-access-control-get-iter");
if (shareName != null && !shareName.isEmpty()) {
NaElement accessAttr = new NaElement("cifs-share-access-control");
accessAttr.addNewChild("share", shareName);
NaElement query = new NaElement("query");
query.addChildElem(accessAttr);
elem.addChildElem(query);
}
try {
do {
NaElement result = server.invokeElem(elem);
tagNext = result.getChildContent("next-tag");
NaElement cifsAcl = result.getChildByName("attributes-list");
if (cifsAcl != null) {
List<NaElement> cifacls = cifsAcl.getChildren();
for (NaElement shareElem : cifacls) {
NaElement permission = shareElem.getChildByName("permission");
String name = shareElem.getChildContent("share");
CifsAcl acl = new CifsAcl();
try {
acl.setAccess(CifsAccess.valueOfAccess(permission.getContent()));
} catch (IllegalArgumentException e) {
log.warn("Invalid permission for a CIFS share: " + name, e);
log.info("Continue with next acl");
continue;
}
acl.setShareName(name);
String userorgroup = shareElem.getChildContent("user-or-group");
acl.setUserName(userorgroup);
acls.add(acl);
}
} else {
return acls;
}
if (tagNext != null && !tagNext.isEmpty()) {
elem = new NaElement("cifs-share-access-control-get-iter");
if (shareName != null && !shareName.isEmpty()) {
NaElement accessAttr = new NaElement("cifs-share-access-control");
accessAttr.addNewChild("share", shareName);
NaElement query = new NaElement("query");
query.addChildElem(accessAttr);
elem.addChildElem(query);
}
elem.addNewChild("tag-next", tagNext);
}
} while (tagNext != null && !tagNext.isEmpty());
return acls;
} catch (Exception e) {
String msg = "Failed to list CIFS ACLs.";
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
@SuppressWarnings("unchecked")
List<ExportsRuleInfo> listNFSExportRules(String pathName)
{
List<ExportsRuleInfo> exports = Lists.newArrayList();
NaElement elem = new NaElement("nfs-exportfs-list-rules-2");
// if true, returns entries from exports file; else from memory. For Cluster mode, it is always true.
elem.addNewChild("persistent", String.valueOf(true));
if (StringUtils.isNotBlank(pathName)) {
elem.addNewChild("pathname", pathName);
}
try {
NaElement results = server.invokeElem(elem);
List<NaElement> rules = results.getChildByName("rules").getChildren();
for (NaElement rule : rules) {
ExportsRuleInfo exportsRuleInfo = new ExportsRuleInfo();
exportsRuleInfo.setActualPathname(rule.getChildContent("actual-pathname"));
exportsRuleInfo.setPathname(rule.getChildContent("pathname"));
for (NaElement securityRule : (List<NaElement>) rule.getChildByName("security-rules").getChildren()) {
SecurityRuleInfo securityRuleInfo = new SecurityRuleInfo();
securityRuleInfo.setAnon(securityRule.getChildContent("anon"));
// String nonsuid = securityRule.getChildContent("nonsuid"); // This is not correct.. Modified by [Gopi] as per API.
String nonsuid = securityRule.getChildContent("nosuid");
if (StringUtils.isNotBlank(nonsuid)) {
securityRuleInfo.setNosuid(Boolean.parseBoolean(nonsuid));
}
List<NaElement> secFlavors = (List<NaElement>) securityRule.getChildByName("sec-flavor").getChildren();
for (NaElement secFlavor : secFlavors) {
if (secFlavor != null) {
if (securityRuleInfo.getSecFlavor() != null) {
securityRuleInfo.setSecFlavor(securityRuleInfo.getSecFlavor() + ","
+ secFlavor
.getChildContent("flavor"));
} else {
securityRuleInfo.setSecFlavor(secFlavor
.getChildContent("flavor"));
}
}
}
List<ExportsHostnameInfo> readOnly = extractExportsHostnameInfos(securityRule.getChildByName("read-only"));
securityRuleInfo.getReadOnly().addAll(readOnly);
List<ExportsHostnameInfo> readWrite = extractExportsHostnameInfos(securityRule.getChildByName("read-write"));
securityRuleInfo.getReadWrite().addAll(readWrite);
List<ExportsHostnameInfo> root = extractExportsHostnameInfos(securityRule.getChildByName("root"));
securityRuleInfo.getRoot().addAll(root);
exportsRuleInfo.getSecurityRuleInfos().add(securityRuleInfo);
}
exports.add(exportsRuleInfo);
}
return exports;
} catch (Exception e) {
String msg = "Failed to list NFS exports.";
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
public String getExportPolicyOfVolume(String exportPath, String volume) {
NaElement elem = new NaElement("volume-get-iter");
String policyName = null;
if (volume != null && !volume.isEmpty()) {
NaElement volumeIdAttrs = new NaElement("volume-id-attributes");
volumeIdAttrs.addNewChild("name", volume);
NaElement volumeAttrs = new NaElement("volume-attributes");
volumeAttrs.addChildElem(volumeIdAttrs);
NaElement query = new NaElement("query");
query.addChildElem(volumeAttrs);
elem.addChildElem(query);
}
NaElement resultElem = null;
try {
NaElement result = server.invokeElem(elem);
resultElem = result.getChildByName("attributes-list");
if (resultElem != null) {
for (NaElement volInfo : (List<NaElement>) resultElem.getChildren()) {
NaElement volExportAttrs = volInfo.getChildByName("volume-export-attributes");
if (volExportAttrs != null) {
policyName = volExportAttrs.getChildContent("policy");
}
}
}
} catch (Exception e) {
String msg = "Failed to get export policy of Volume " + volume;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return policyName;
}
public String getExportPolicyOfQtree(String exportPath, String volume, String qtree) {
NaElement elem = new NaElement("qtree-list-iter");
String policyName = null;
if ((volume != null && !volume.isEmpty()) && (qtree != null && !qtree.isEmpty())) {
NaElement qtreeAttrs = new NaElement("qtree-info");
qtreeAttrs.addNewChild("volume", volume);
qtreeAttrs.addNewChild("qtree", qtree);
NaElement query = new NaElement("query");
query.addChildElem(qtreeAttrs);
elem.addChildElem(query);
}
NaElement resultElem = null;
String tag = null;
List<Qtree> qtrees = Lists.newArrayList();
try {
do {
NaElement results = server.invokeElem(elem);
tag = results.getChildContent("next-tag");
resultElem = results.getChildByName("attributes-list");
if (resultElem != null) {
// Get the number of records returned by API.
for (NaElement qtreeElem : (List<NaElement>) resultElem.getChildren()) {
if (qtreeElem != null) {
policyName = qtreeElem.getChildContent("export-policy");
}
}
}
if (tag != null && !tag.isEmpty()) {
elem = new NaElement("qtree-list-iter");
elem.addNewChild("tag", tag);
}
} while (tag != null && !tag.isEmpty());
} catch (IllegalArgumentException e) {
String msg = "Failed to get export policy on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
String msg = "Failed to get export policy on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return policyName;
}
public void addNFSShare(String fsName, String qtreeName, String exportPath,
int anonymousUid, List<String> roHosts, List<String> rwHosts,
List<String> rootHosts, List<NFSSecurityStyle> securityStyle) {
String policyName = "";
String qtreePolicyName = "";
boolean isExported = true;
String volumePolicyName = getExportPolicyOfVolume(exportPath, fsName);
policyName = volumePolicyName;
if (qtreeName == null || qtreeName.isEmpty()) {
if (policyName.equalsIgnoreCase(DEFAULT_EXPORT_POLICY) || policyName.equalsIgnoreCase(UNEXPORTED_EXPORT_POLICY)) {
isExported = false;
}
} else {
qtreePolicyName = fsName + "_" + qtreeName;
policyName = getExportPolicyOfQtree(exportPath, fsName, qtreeName);
if (policyName.equalsIgnoreCase(volumePolicyName) || policyName.equalsIgnoreCase(DEFAULT_EXPORT_POLICY) ||
policyName.equalsIgnoreCase(UNEXPORTED_EXPORT_POLICY)) {
isExported = false;
}
}
if (!isExported) {
createExportPolicy(qtreeName, fsName, exportPath);
try {
NaElement result = null;
Set<String> hosts = new HashSet<String>();
hosts.addAll(roHosts);
hosts.addAll(rwHosts);
hosts.addAll(roHosts);
for (String host : hosts) {
NaElement ruleElem = new NaElement("export-rule-create");
if (qtreeName != null && !qtreeName.isEmpty()) {
ruleElem.addNewChild("policy-name", qtreePolicyName);
} else {
ruleElem.addNewChild("policy-name", fsName);
}
ruleElem.addNewChild("client-match", host);
if (anonymousUid > -1) {
ruleElem.addNewChild("anonymous-user-id", String.valueOf(anonymousUid));
}
setSecurityStyle(host, securityStyle, roHosts, rwHosts, rootHosts, ruleElem);
result = server.invokeElem(ruleElem);
}
} catch (IllegalArgumentException e) {
// Rollback - Delete export policy if creation of export rules fail
deleteExportPolicy(policyName, fsName);
String msg = "Failed to create export rule on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
// Rollback - Delete export policy if creation of export rules fail
deleteExportPolicy(policyName, fsName);
String msg = "Failed to create export rule on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
}
if (qtreeName != null && !qtreeName.isEmpty()) {
assignExportPolicyToQtree(qtreeName, fsName, exportPath);
} else {
assignExportPolicyToVolume(fsName, policyName, exportPath);
}
} else {
String msg = "Export already exists. Failed to export path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg);
throw new NetAppCException(msg);
}
}
public void changeNFSShare(String fsName, String qtreeName, ExportRule oldRule,
ExportRule newRule, String exportPath) {
String policyName = "";
if (qtreeName == null || qtreeName.isEmpty()) {
policyName = getExportPolicyOfVolume(exportPath, fsName);
} else {
policyName = getExportPolicyOfQtree(exportPath, fsName, qtreeName);
}
NaElement result = null;
try {
List<String> rootHosts = new ArrayList<String>();
List<String> rwHosts = new ArrayList<String>();
List<String> roHosts = new ArrayList<String>();
int rootMappingUid = getAnonId(newRule.getAnon());
List<NFSSecurityStyle> securityStyleList = new ArrayList<NFSSecurityStyle>();
securityStyleList.add(NFSSecurityStyle.valueOfName(newRule.getSecFlavor()));
// Collects all the hosts from export rule after modification
Set<String> hosts = new HashSet<String>();
if (newRule.getReadOnlyHosts() != null) {
hosts.addAll(newRule.getReadOnlyHosts());
roHosts.addAll(newRule.getReadOnlyHosts());
}
if (newRule.getReadWriteHosts() != null) {
hosts.addAll(newRule.getReadWriteHosts());
rwHosts.addAll(newRule.getReadWriteHosts());
}
if (newRule.getRootHosts() != null) {
hosts.addAll(newRule.getRootHosts());
rootHosts.addAll(newRule.getRootHosts());
}
if (oldRule != null) {
// Collects all the hosts from export rule before modification
Set<String> oldHosts = new HashSet<String>();
if (oldRule.getReadOnlyHosts() != null) {
oldHosts.addAll(oldRule.getReadOnlyHosts());
}
if (oldRule.getReadWriteHosts() != null) {
oldHosts.addAll(oldRule.getReadWriteHosts());
}
if (oldRule.getRootHosts() != null) {
oldHosts.addAll(oldRule.getRootHosts());
}
// Handles removing endpoint from export rule during modify.
Set<String> hostsToRemove = com.google.common.collect.Sets.difference(oldHosts, hosts);
for (String host : hostsToRemove) {
List<String> permission = new ArrayList<String>();
if (oldRule.getReadOnlyHosts() != null && oldRule.getReadOnlyHosts().contains(host)) {
permission.add(RO_PERMISSION);
}
if (oldRule.getReadWriteHosts() != null && oldRule.getReadWriteHosts().contains(host)) {
permission.add(RW_PERMISSION);
}
if (oldRule.getRootHosts() != null && oldRule.getRootHosts().contains(host)) {
permission.add(ROOT_PERMISSION);
}
String ruleIndex = getMatchingRule(host, policyName, permission, oldRule.getSecFlavor(), exportPath);
NaElement ruleElem = null;
if (!ruleIndex.isEmpty()) {
deleteExportRule(ruleIndex, policyName, fsName);
}
}
}
for (String host : hosts) {
String ruleIndex = "";
if (oldRule != null) {
List<String> permission = new ArrayList<String>();
if (oldRule.getReadOnlyHosts() != null && oldRule.getReadOnlyHosts().contains(host)) {
permission.add(RO_PERMISSION);
}
if (oldRule.getReadWriteHosts() != null && oldRule.getReadWriteHosts().contains(host)) {
permission.add(RW_PERMISSION);
}
if (oldRule.getRootHosts() != null && oldRule.getRootHosts().contains(host)) {
permission.add(ROOT_PERMISSION);
}
ruleIndex = getMatchingRule(host, policyName, permission, oldRule.getSecFlavor(), exportPath);
} else {
ruleIndex = getMatchingRule(host, policyName, null, null, exportPath);
}
NaElement ruleElem = null;
if (!ruleIndex.isEmpty()) {
ruleElem = new NaElement("export-rule-modify");
ruleElem.addNewChild("rule-index", ruleIndex);
} else {
ruleElem = new NaElement("export-rule-create");
}
ruleElem.addNewChild("anonymous-user-id", String.valueOf(rootMappingUid));
ruleElem.addNewChild("policy-name", policyName);
ruleElem.addNewChild("client-match", host);
setSecurityStyle(host, securityStyleList, roHosts, rwHosts, rootHosts, ruleElem);
result = server.invokeElem(ruleElem);
}
} catch (IllegalArgumentException e) {
String msg = "Failed to create export rule for file system: " + fsName;
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
String msg = "Failed to create export rule for file system: " + fsName;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
public void deleteNFSShare(String fsName, String qtreeName, ExportRule oldRule,
String exportPath) {
String policyName = "";
if (qtreeName == null || qtreeName.isEmpty()) {
policyName = getExportPolicyOfVolume(exportPath, fsName);
} else {
policyName = getExportPolicyOfQtree(exportPath, fsName, qtreeName);
}
NaElement result = null;
try {
List<String> rootHosts = new ArrayList<String>();
List<String> rwHosts = new ArrayList<String>();
List<String> roHosts = new ArrayList<String>();
List<NFSSecurityStyle> secruityStyleList = new ArrayList<NFSSecurityStyle>();
secruityStyleList.add(NFSSecurityStyle.valueOfName(oldRule.getSecFlavor()));
// Collects all the hosts from export rule before modification
Set<String> hosts = new HashSet<String>();
if (oldRule.getReadOnlyHosts() != null) {
hosts.addAll(oldRule.getReadOnlyHosts());
roHosts.addAll(oldRule.getReadOnlyHosts());
}
if (oldRule.getReadWriteHosts() != null) {
hosts.addAll(oldRule.getReadWriteHosts());
rwHosts.addAll(oldRule.getReadWriteHosts());
}
if (oldRule.getRootHosts() != null) {
hosts.addAll(oldRule.getRootHosts());
rootHosts.addAll(oldRule.getRootHosts());
}
for (String host : hosts) {
List<String> permission = new ArrayList<String>();
if (oldRule.getReadOnlyHosts() != null && oldRule.getReadOnlyHosts().contains(host)) {
permission.add(RO_PERMISSION);
}
if (oldRule.getReadWriteHosts() != null && oldRule.getReadWriteHosts().contains(host)) {
permission.add(RW_PERMISSION);
}
if (oldRule.getRootHosts() != null && oldRule.getRootHosts().contains(host)) {
permission.add(ROOT_PERMISSION);
}
String ruleIndex = getMatchingRule(host, policyName, permission, oldRule.getSecFlavor(), exportPath);
NaElement ruleElem = null;
if (!ruleIndex.isEmpty()) {
deleteExportRule(ruleIndex, policyName, fsName);
}
}
} catch (IllegalArgumentException e) {
String msg = "Failed to create export rule for file system: " + fsName;
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
String msg = "Failed to create export rule for file system: " + fsName;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
public int getAnonId(String anon) {
int rootMappingUid = 0;
if (anon != null) {
if (anon.equals(ROOT_USER)) {
rootMappingUid = 0;
}
else if (anon.equals(NO_ROOT_USERS)) {
rootMappingUid = DISABLE_ROOT_ACCESS_CODE;
}
} else {
// If UID is specified other than root or nobody default it
// to this value.
rootMappingUid = DEFAULT_ANONMOUS_ROOT_ACCESS;
}
return rootMappingUid;
}
/**
* Gets the index of export rule to be modified by matching the properties
* of export rule before modification
*/
public String getMatchingRule(String host, String fsName,
List<String> permission, String secFlavor, String exportPath) {
String ruleIndex = "";
try {
NaElement expRuleElem = new NaElement("export-rule-get-iter");
NaElement expRuleInfo = new NaElement("export-rule-info");
NaElement result = null;
expRuleInfo.addNewChild("policy-name", fsName);
expRuleInfo.addNewChild("client-match", host);
expRuleInfo.addNewChild("vserver-name", server.getVserver());
if (permission != null && !permission.isEmpty() && secFlavor != null) {
NaElement roRule = new NaElement("ro-rule");
NaElement rwRule = new NaElement("rw-rule");
NaElement rootRule = new NaElement("super-user-security");
if (permission.contains(ROOT_PERMISSION)) {
rootRule.addNewChild("security-flavor", secFlavor);
rwRule.addNewChild("security-flavor", secFlavor);
roRule.addNewChild("security-flavor", secFlavor);
} else if (permission.contains(RW_PERMISSION)) {
rootRule.addNewChild("security-flavor", SEC_FLAVOR_NONE);
rwRule.addNewChild("security-flavor", secFlavor);
roRule.addNewChild("security-flavor", secFlavor);
} else if (permission.contains(RO_PERMISSION)) {
rootRule.addNewChild("security-flavor", SEC_FLAVOR_NONE);
rwRule.addNewChild("security-flavor", SEC_FLAVOR_NEVER);
roRule.addNewChild("security-flavor", secFlavor);
}
expRuleInfo.addChildElem(rwRule);
expRuleInfo.addChildElem(roRule);
expRuleInfo.addChildElem(rootRule);
}
if ((permission == null) || (permission != null && permission.isEmpty())) { // NOSONAR("Null check required")
NaElement roRule = new NaElement("ro-rule");
NaElement rwRule = new NaElement("rw-rule");
NaElement rootRule = new NaElement("super-user-security");
rootRule.addNewChild("security-flavor", SEC_FLAVOR_NONE);
rootRule.addNewChild("security-flavor", SEC_FLAVOR_NEVER);
rwRule.addNewChild("security-flavor", SEC_FLAVOR_NEVER);
expRuleInfo.addChildElem(rwRule);
expRuleInfo.addChildElem(roRule);
expRuleInfo.addChildElem(rootRule);
}
NaElement query = new NaElement("query");
query.addChildElem(expRuleInfo);
expRuleElem.addChildElem(query);
NaElement resultElem = null;
result = server.invokeElem(expRuleElem);
resultElem = result.getChildByName("attributes-list");
if (resultElem != null) {
for (NaElement exportRule : (List<NaElement>) resultElem.getChildren()) {
ruleIndex = exportRule.getChildContent("rule-index");
break;
}
}
} catch (IllegalArgumentException e) {
String msg = "Failed to match export rule on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
String msg = "Failed to match export rule on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
}
return ruleIndex;
}
/**
* Deletes export rule based on rule index
*/
public void deleteExportRule(String ruleIndex, String policyName, String fsName) {
NaElement ruleElem = null;
NaElement result = null;
try {
ruleElem = new NaElement("export-rule-destroy");
ruleElem.addNewChild("rule-index", ruleIndex);
ruleElem.addNewChild("policy-name", policyName);
result = server.invokeElem(ruleElem);
} catch (IllegalArgumentException e) {
String msg = "Failed to delete export rule index " + ruleIndex + " for file system: " + fsName;
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
String msg = "Failed to delete export rule index " + ruleIndex + " for file system: " + fsName;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
/**
* Deletes export policy based on policy name
*/
public void deleteExportPolicy(String policyName, String fsName) {
NaElement ruleElem = null;
NaElement result = null;
try {
ruleElem = new NaElement("export-policy-destroy");
ruleElem.addNewChild("policy-name", policyName);
result = server.invokeElem(ruleElem);
} catch (IllegalArgumentException e) {
String msg = "Failed to delete export policy for file system: " + fsName;
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
String msg = "Failed to create export policy for file system: " + fsName;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
/**
* Creates export policy
*/
public void createExportPolicy(String qtreeName, String fsName, String exportPath) {
NaElement result = null;
try {
NaElement policyElem = new NaElement("export-policy-create");
if (qtreeName != null && !qtreeName.isEmpty()) {
String qtreePolicyName = fsName + "_" + qtreeName;
policyElem.addNewChild("policy-name", qtreePolicyName);
} else {
policyElem.addNewChild("policy-name", fsName);
}
result = server.invokeElem(policyElem);
} catch (IllegalArgumentException e) {
String msg = "Failed to create export policy on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
String msg = "Failed to create export policy on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
/**
* Assigns export policy name to qtree after export policy and rules are created
*/
public void assignExportPolicyToQtree(String qtreeName, String fsName, String exportPath) {
try {
NaElement result = null;
String qtreePolicyName = fsName + "_" + qtreeName;
NaElement qtreeElem = new NaElement("qtree-modify");
qtreeElem.addNewChild("export-policy", qtreePolicyName);
qtreeElem.addNewChild("volume", fsName);
qtreeElem.addNewChild("qtree", qtreeName);
result = server.invokeElem(qtreeElem);
} catch (IllegalArgumentException e) {
String msg = "Failed to modify volume on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
String msg = "Failed to modify volume on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
/**
* Assigns export policy name to volume after export policy and rules are created
*/
public void assignExportPolicyToVolume(String fsName, String policyName, String exportPath) {
try {
NaElement result = null;
NaElement volumeElem = new NaElement("volume-modify-iter");
NaElement volumeIdAttrs = new NaElement("volume-id-attributes");
volumeIdAttrs.addNewChild("name", fsName);
NaElement query = new NaElement("query");
NaElement volumeAttr = new NaElement("volume-attributes");
volumeAttr.addChildElem(volumeIdAttrs);
query.addChildElem(volumeAttr);
volumeElem.addChildElem(query);
NaElement attrs = new NaElement("attributes");
NaElement volumeAttrs = new NaElement("volume-attributes");
NaElement volumeExportAttrs = new NaElement("volume-export-attributes");
volumeExportAttrs.addNewChild("policy", fsName);
volumeAttrs.addChildElem(volumeExportAttrs);
attrs.addChildElem(volumeAttrs);
volumeElem.addChildElem(attrs);
volumeElem.addNewChild("return-failure-list", String.valueOf(true));
result = server.invokeElem(volumeElem);
log.info("Failure list size " + result.getChildByName("failure-list").getChildren().size());
if (!result.getChildByName("failure-list").getChildren().isEmpty()) {
log.error("Failed to modify Export Policy of File System : " + fsName);
}
} catch (IllegalArgumentException e) {
// Rollback - Delete export policy if assigning export policy to volume fails
deleteExportPolicy(policyName, fsName);
String msg = "Failed to modify volume on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
} catch (Exception e) {
// Rollback - Delete export policy if assigning export policy to volume fails
deleteExportPolicy(policyName, fsName);
String msg = "Failed to modify volume on path: " + (mountPath != null ? mountPath : exportPath);
log.error(msg, e);
throw new NetAppCException(msg, e);
}
}
private void setSecurityStyle(String host, List<NFSSecurityStyle> securityStyleList,
List<String> roHosts, List<String> rwHosts, List<String> rootHosts, NaElement ruleElem) {
NaElement roRule = new NaElement("ro-rule");
NaElement rwRule = new NaElement("rw-rule");
NaElement rootRule = new NaElement("super-user-security");
boolean hasRootPermission = false;
boolean hasRWPermission = false;
boolean hasROPermission = false;
if (roHosts.contains(host)) {
hasROPermission = true;
}
if (rwHosts.contains(host)) {
hasRWPermission = true;
hasROPermission = true;
}
if (rootHosts.contains(host)) {
hasRootPermission = true;
hasRWPermission = true;
hasROPermission = true;
}
if (hasRootPermission) {
// Add security style
for (NFSSecurityStyle s : securityStyleList) {
rootRule.addNewChild("security-flavor", s.name());
rwRule.addNewChild("security-flavor", s.name());
roRule.addNewChild("security-flavor", s.name());
}
} else {
if (hasRWPermission) {
rootRule.addNewChild("security-flavor", SEC_FLAVOR_NONE);
// Add security style
for (NFSSecurityStyle s : securityStyleList) {
rwRule.addNewChild("security-flavor", s.name());
roRule.addNewChild("security-flavor", s.name());
}
} else {
rootRule.addNewChild("security-flavor", SEC_FLAVOR_NONE);
rwRule.addNewChild("security-flavor", SEC_FLAVOR_NEVER);
if (hasROPermission) {
// Add security style
for (NFSSecurityStyle s : securityStyleList) {
roRule.addNewChild("security-flavor", s.name());
}
} else {
roRule.addNewChild("security-flavor", SEC_FLAVOR_NEVER);
}
}
}
ruleElem.addChildElem(rootRule);
ruleElem.addChildElem(rwRule);
ruleElem.addChildElem(roRule);
}
public List<String> deleteNFSShare(boolean deleteAll)
{
NaElement elem = new NaElement("nfs-exportfs-delete-rules");
elem.addNewChild("persistent", String.valueOf(true));
elem.addNewChild("verbose", String.valueOf(true));
// Delete all NFS Shares
if (deleteAll) {
elem.addNewChild("all-pathnames", String.valueOf(true));
}
else {
NaElement pathnames = new NaElement("pathnames");
NaElement pathInfo = new NaElement("pathname-info");
pathInfo.addNewChild("name", mountPath);
pathnames.addChildElem(pathInfo);
elem.addChildElem(pathnames);
}
NaElement result = null;
try {
result = server.invokeElem(elem);
} catch (Exception e) {
String msg = "Failed to delete NFS share on path: " + mountPath;
log.error(msg, e);
throw new NetAppCException(msg, e);
}
// build the result
if (result.hasChildren()) {
ArrayList<String> pathnames = new ArrayList<String>();
for (NaElement pathInfo : (List<NaElement>) result.getChildren()) {
pathnames.add(pathInfo.getChildContent("pathname"));
}
return pathnames;
} else {
return Lists.newArrayList(mountPath);
}
}
private List<ExportsHostnameInfo> extractExportsHostnameInfos(NaElement elem) {
List<ExportsHostnameInfo> exportsHostnameInfos = Lists.newArrayList();
if (elem != null && elem.getChildren() != null) {
for (NaElement exportsHostname : (List<NaElement>) elem.getChildren()) {
ExportsHostnameInfo exportsHostnameInfo = new ExportsHostnameInfo();
String allHosts = exportsHostname.getChildContent("all-hosts");
if (StringUtils.isNotBlank(allHosts)) {
exportsHostnameInfo.setAllHosts(Boolean.parseBoolean(allHosts));
}
exportsHostnameInfo.setName(exportsHostname.getChildContent("name"));
String negate = exportsHostname.getChildContent("negate");
if (StringUtils.isNotBlank(negate)) {
exportsHostnameInfo.setNegate(Boolean.parseBoolean(negate));
}
exportsHostnameInfos.add(exportsHostnameInfo);
}
}
return exportsHostnameInfos;
}
}