/* * Copyright (c) 2012-2015 iWave Software LLC * All Rights Reserved */ /** * */ package com.iwave.ext.netapp; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; 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.netapp.model.CifsAccess; import com.iwave.ext.netapp.model.CifsAcl; import com.iwave.ext.netapp.model.ExportsHostnameInfo; import com.iwave.ext.netapp.model.ExportsRuleInfo; import com.iwave.ext.netapp.model.SecurityRuleInfo; import com.iwave.ext.netapp.utils.ExportRule; /** * @author sdorcas * */ @SuppressWarnings({ "findbugs:WMI_WRONG_MAP_ITERATOR" }) /* * Code change for iterator will be made in future release */ public class FileShare { private Logger log = Logger.getLogger(getClass()); /** maximum number of shares that will be listed */ private static final int MAX_LIST = 1024; private static final String ROOT_USER = "root"; private static final String NO_ROOT_USERS = "nobody"; 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 FileShare(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-add"); elem.addNewChild("path", mountPath); elem.addNewChild("share-name", shareName); 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 NetAppException(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 NetAppException(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)); } try { server.invokeElem(elem); } catch (Exception e) { String msg = "Failed to change CIFS share: " + shareName + " attrs: " + attrs; log.error(msg, e); throw new NetAppException(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-list-iter-start"); if (shareName != null && !shareName.isEmpty()) { elem.addNewChild("share-name", shareName); // shareName can contain wildcards * or ? } try { NaElement result = server.invokeElem(elem); String tag = result.getChildContent("tag"); elem = new NaElement("cifs-share-list-iter-next"); elem.addNewChild("tag", tag); elem.addNewChild("maximum", MAX_LIST + ""); List<NaElement> shareElems = server.invokeElem(elem).getChildByName("cifs-shares").getChildren(); for (NaElement shareElem : shareElems) { // {description=Testing, maxusers=5, 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); } elem = new NaElement("cifs-share-list-iter-end"); elem.addNewChild("tag", tag); server.invokeElem(elem); return shares; } catch (Exception e) { String msg = "Failed to list CIFS shares."; log.error(msg, e); throw new NetAppException(msg, e); } } public void setCIFSAcl(CifsAcl acl) { NaElement elem = new NaElement("cifs-share-ace-set"); elem.addNewChild("share-name", acl.getShareName()); elem.addNewChild("access-rights", acl.getAccess().access()); if (acl.getUserName() != null) { elem.addNewChild("user-name", acl.getUserName()); } if (acl.getGroupName() != null) { elem.addNewChild("unix-group-name", acl.getGroupName()); elem.addNewChild("is-unixgroup", "true"); } try { server.invokeElem(elem); } catch (NaAPIFailedException e) { String msg = "Failed to set CIFS Acl: " + acl; log.error(msg, e); throw new NetAppException(msg, e, e.getErrno()); } catch (Exception e) { String msg = "Failed to set CIFS Acl: " + acl; log.error(msg, e); throw new NetAppException(msg, e); } } public void deleteCIFSAcl(CifsAcl acl) { NaElement elem = new NaElement("cifs-share-ace-delete"); elem.addNewChild("share-name", acl.getShareName()); if (acl.getUserName() != null) { elem.addNewChild("user-name", acl.getUserName()); } if (acl.getGroupName() != null) { elem.addNewChild("unix-group-name", acl.getGroupName()); elem.addNewChild("is-unixgroup", "true"); } try { server.invokeElem(elem); } catch (Exception e) { String msg = "Failed to delete CIFS Acl: " + acl; log.error(msg, e); throw new NetAppException(msg, e); } } public List<CifsAcl> listCIFSAcls(String shareName) { List<CifsAcl> acls = new ArrayList<CifsAcl>(); NaElement elem = new NaElement("cifs-share-acl-list-iter-start"); if (shareName != null && !shareName.isEmpty()) { elem.addNewChild("share-name", shareName); // shareName can contain wildcards * or ? } try { NaElement result = server.invokeElem(elem); String tag = result.getChildContent("tag"); elem = new NaElement("cifs-share-acl-list-iter-next"); elem.addNewChild("tag", tag); elem.addNewChild("maximum", MAX_LIST + ""); List<NaElement> shareElems = server.invokeElem(elem).getChildByName("cifs-share-acls").getChildren(); for (NaElement shareElem : shareElems) { String name = shareElem.getChildContent("share-name"); shareElem = shareElem.getChildByName("user-acl-info"); // Note: can't use shareElem.getChildByName("access-rights-info"); // as this only gets the first element List<NaElement> infos = shareElem.getChildren(); for (NaElement info : infos) { CifsAcl acl = new CifsAcl(); acl.setShareName(name); String access = info.getChildContent("access-rights"); try { acl.setAccess(CifsAccess.valueOfAccess(access)); } catch (IllegalArgumentException e) { log.warn("Invalid permission for a CIFS share: " + name, e); log.info("Continue with next acl"); continue; } String user = info.getChildContent("user-name"); String group = info.getChildContent("unix-group-name"); /* * numeric groups are returned as users like: {gid:0} */ if (user != null && user.startsWith("{gid:")) { int brace = user.indexOf('}'); group = user.substring(5, brace); user = null; } acl.setUserName(user); acl.setGroupName(group); acls.add(acl); } } elem = new NaElement("cifs-share-list-iter-end"); elem.addNewChild("tag", tag); server.invokeElem(elem); return acls; } catch (Exception e) { String msg = "Failed to list CIFS ACLs."; log.error(msg, e); throw new NetAppException(msg, e); } } @SuppressWarnings("unchecked") List<Map<String, String>> listNFSInfo(String pathName) { ArrayList<Map<String, String>> exports = new ArrayList<Map<String, String>>(); NaElement elem = new NaElement("nfs-exportfs-list-rules"); // if true, returns entries from exports file; else from memory elem.addNewChild("persistent", String.valueOf(true)); if (pathName != null && !pathName.isEmpty()) { elem.addNewChild("pathname", pathName); } try { List<NaElement> ruleElems = server.invokeElem(elem).getChildByName("rules").getChildren(); for (NaElement ruleElem : ruleElems) { Map<String, String> export = new HashMap<String, String>(); for (NaElement info : (List<NaElement>) ruleElem.getChildren()) { String name = info.getName(); String value = info.getContent(); List<NaElement> children = (List<NaElement>) info.getChildren(); if (!children.isEmpty()) { StringBuilder buf = new StringBuilder(); for (NaElement child : children) { List<NaElement> grandchildren = (List<NaElement>) child.getChildren(); if (!grandchildren.isEmpty()) { for (NaElement grandchild : grandchildren) { if (buf.length() > 0) { buf.append(","); } buf.append(grandchild.getContent()); } } } value = buf.toString(); if (value.equals("true")) { value = "All Hosts"; } } export.put(name, value); } exports.add(export); } return exports; } catch (Exception e) { String msg = "Failed to list NFS exports."; log.error(msg, e); throw new NetAppException(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 elem.addNewChild("persistent", String.valueOf(false)); 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 NetAppException(msg, e); } } 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; } @SuppressWarnings("unchecked") List<Map<String, String>> listNFSExports(String pathName) { ArrayList<Map<String, String>> exports = new ArrayList<Map<String, String>>(); NaElement elem = new NaElement("nfs-exportfs-list-rules-2"); // if true, returns entries from exports file; else from memory elem.addNewChild("persistent", String.valueOf(true)); if (pathName != null && !pathName.isEmpty()) { elem.addNewChild("pathname", pathName); } try { List<NaElement> ruleElems = server.invokeElem(elem).getChildByName("rules").getChildren(); for (NaElement ruleElem : ruleElems) { Map<String, String> export = new HashMap<String, String>(); for (NaElement info : (List<NaElement>) ruleElem.getChildren()) { String name = info.getName(); String value = info.getContent(); if ("security-rules".equalsIgnoreCase(name)) { // Ignore, use another method call } else { export.put(name, value); } } exports.add(export); } return exports; } catch (Exception e) { String msg = "Failed to list NFS exports."; log.error(msg, e); throw new NetAppException(msg, e); } } List<String> addNFSShare(String exportPath, int anonymousUid, List<String> roHosts, boolean roAddAll, List<String> rwHosts, boolean rwAddAll, List<String> rootHosts, boolean rootAddAll, List<NFSSecurityStyle> securityStyle) { NaElement elem = new NaElement("nfs-exportfs-append-rules"); elem.addNewChild("persistent", String.valueOf(true)); elem.addNewChild("verbose", String.valueOf(true)); NaElement rules = new NaElement("rules"); NaElement exportRule = new NaElement("exports-rule-info"); exportRule.addNewChild("pathname", exportPath); if (mountPath != null) { exportRule.addNewChild("actual-pathname", mountPath); } if (anonymousUid > -1) { exportRule.addNewChild("anon", String.valueOf(anonymousUid)); } // Add the host list if hosts are defined or addAll is true if (roAddAll || (roHosts != null && !roHosts.isEmpty())) { NaElement readOnly = new NaElement("read-only"); addHosts(readOnly, roHosts, roAddAll); exportRule.addChildElem(readOnly); } if (rwAddAll || (rwHosts != null && !rwHosts.isEmpty())) { NaElement readWrite = new NaElement("read-write"); addHosts(readWrite, rwHosts, rwAddAll); exportRule.addChildElem(readWrite); } if (rootAddAll || (rootHosts != null && !rootHosts.isEmpty())) { NaElement root = new NaElement("root"); addHosts(root, rootHosts, rootAddAll); exportRule.addChildElem(root); } // Add security style if (securityStyle != null && !securityStyle.isEmpty()) { NaElement secStyle = new NaElement("sec-flavor"); addSecurityStyles(securityStyle, secStyle); exportRule.addChildElem(secStyle); } // Add the export rule rules.addChildElem(exportRule); elem.addChildElem(rules); NaElement result = null; try { result = server.invokeElem(elem).getChildByName("loaded-pathnames"); } catch (Exception e) { String msg = "Failed to create NFS share on path: " + (mountPath != null ? mountPath : exportPath); log.error(msg, e); throw new NetAppException(msg, e); } // build the result ArrayList<String> pathnames = new ArrayList<String>(); for (NaElement pathInfo : (List<NaElement>) result.getChildren()) { pathnames.add(pathInfo.getChildContent("name")); // API doc is wrong here } if (!pathnames.contains(exportPath)) { String msg = "Failed to create NFS share on path: " + (mountPath != null ? mountPath : exportPath); msg += ". Check directory exists in volume."; log.error(msg); throw new NetAppException(msg); } return pathnames; } 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("pathname", mountPath); - API doc is wrong here 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 NetAppException(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); } } static private void addSecurityStyles(List<NFSSecurityStyle> securityStyle, NaElement secStyle) { for (NFSSecurityStyle s : securityStyle) { NaElement secInfo = new NaElement("sec-flavor-info"); secInfo.addNewChild("flavor", s.name()); secStyle.addChildElem(secInfo); } } static private void addHosts(NaElement elem, List<String> hosts, boolean addAll) { // To add all hosts, NetApp API requires you to create a single // 'exports-hostname-info' element with a child element 'all-hosts' // with value of true. if (addAll) { NaElement exportHost = new NaElement("exports-hostname-info"); exportHost.addNewChild("all-hosts", String.valueOf(true)); elem.addChildElem(exportHost); } // Otherwise add each host explicitly else { for (String name : hosts) { NaElement exportHost = new NaElement("exports-hostname-info"); exportHost.addNewChild("name", name); elem.addChildElem(exportHost); } } } List<String> modifyNFSShare(String exportPath, List<ExportRule> exportRules) { log.info("modifyNFSShare" + exportPath); NaElement elem = new NaElement("nfs-exportfs-modify-rule-2"); elem.addNewChild("persistent", String.valueOf(true)); // elem.addNewChild("verbose", String.valueOf(true)); NaElement rules = new NaElement("rule"); NaElement exportRules2 = new NaElement("exports-rule-info-2"); exportRules2.addNewChild("pathname", exportPath); NaElement naSecurityRules = new NaElement("security-rules"); for (ExportRule expRule : exportRules) { int rootMappingUid = 0; String anon = expRule.getAnon(); 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; } NaElement naExportRule = new NaElement("security-rule-info"); naExportRule.addNewChild("anon", String.valueOf(rootMappingUid)); /* * if (!(expRule.getAnon().equals("-1"))) { * naExportRule.addNewChild("anon", String.valueOf(rootMappingUid)); * } */ // TODO: Account for AddAll hosts. // Add read-only hosts if ((expRule.getReadOnlyHosts() != null) && (!expRule.getReadOnlyHosts().isEmpty())) { NaElement readOnly = new NaElement("read-only"); addHosts(readOnly, expRule.getReadOnlyHosts(), false); naExportRule.addChildElem(readOnly); } // Add read-write hosts if ((expRule.getReadWriteHosts() != null) && (!expRule.getReadWriteHosts().isEmpty())) { NaElement readWriteHosts = new NaElement("read-write"); addHosts(readWriteHosts, expRule.getReadWriteHosts(), false); naExportRule.addChildElem(readWriteHosts); } // Add root hosts if ((expRule.getRootHosts() != null) && (!expRule.getRootHosts().isEmpty())) { NaElement rootHosts = new NaElement("root"); addHosts(rootHosts, expRule.getRootHosts(), false); naExportRule.addChildElem(rootHosts); } // Add security style if (expRule.getSecFlavor() != null) { NaElement secStyle = new NaElement("sec-flavor"); List<NFSSecurityStyle> secruityStyleList = new ArrayList<NFSSecurityStyle>(); secruityStyleList.add(NFSSecurityStyle.valueOfName(expRule.getSecFlavor())); addSecurityStyles(secruityStyleList, secStyle); naExportRule.addChildElem(secStyle); } naSecurityRules.addChildElem(naExportRule); } // Add the export rule exportRules2.addChildElem(naSecurityRules); rules.addChildElem(exportRules2); elem.addChildElem(rules); NaElement result = null; try { log.info(elem); result = server.invokeElem(elem).getChildByName("loaded-pathnames"); } catch (Exception e) { String msg = "Failed to create NFS share on path: " + (mountPath != null ? mountPath : exportPath); log.error(msg, e); throw new NetAppException(msg, e); } // build the result ArrayList<String> pathnames = new ArrayList<String>(); // for (NaElement pathInfo : (List<NaElement>)result.getChildren()) { // pathnames.add(pathInfo.getChildContent("name")); // API doc is wrong here // } // // if (!pathnames.contains(exportPath)) { // String msg = "Failed to create NFS share on path: " + (mountPath != null ? mountPath : exportPath); // msg += ". Check directory exists in volume."; // log.error(msg); // throw new NetAppException(msg); // } return pathnames; } List<String> addNewNFSShare(String exportPath, List<ExportRule> exportRules) { log.info("addNewNFSShare" + exportPath); NaElement elem = new NaElement("nfs-exportfs-append-rules-2"); elem.addNewChild("persistent", String.valueOf(true)); elem.addNewChild("verbose", String.valueOf(true)); NaElement rules = new NaElement("rules"); NaElement exportRules2 = new NaElement("exports-rule-info-2"); exportRules2.addNewChild("pathname", exportPath); NaElement naSecurityRules = new NaElement("security-rules"); for (ExportRule expRule : exportRules) { int rootMappingUid = 0; String anon = expRule.getAnon(); 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; } NaElement naExportRule = new NaElement("security-rule-info"); naExportRule.addNewChild("anon", String.valueOf(rootMappingUid)); /* * if (!(expRule.getAnon().equals("-1"))) { * naExportRule.addNewChild("anon", String.valueOf(rootMappingUid)); * } */ // TODO: Account for AddAll hosts. // Add read-only hosts if ((expRule.getReadOnlyHosts() != null) && (!expRule.getReadOnlyHosts().isEmpty())) { NaElement readOnly = new NaElement("read-only"); addHosts(readOnly, expRule.getReadOnlyHosts(), false); naExportRule.addChildElem(readOnly); } // Add read-write hosts if ((expRule.getReadWriteHosts() != null) && (!expRule.getReadWriteHosts().isEmpty())) { NaElement readWriteHosts = new NaElement("read-write"); addHosts(readWriteHosts, expRule.getReadWriteHosts(), false); naExportRule.addChildElem(readWriteHosts); } // Add root hosts if ((expRule.getRootHosts() != null) && (!expRule.getRootHosts().isEmpty())) { NaElement rootHosts = new NaElement("root"); addHosts(rootHosts, expRule.getRootHosts(), false); naExportRule.addChildElem(rootHosts); } // Add security style if (expRule.getSecFlavor() != null) { NaElement secStyle = new NaElement("sec-flavor"); List<NFSSecurityStyle> secruityStyleList = new ArrayList<NFSSecurityStyle>(); secruityStyleList.add(NFSSecurityStyle.valueOfName(expRule.getSecFlavor())); addSecurityStyles(secruityStyleList, secStyle); naExportRule.addChildElem(secStyle); } naSecurityRules.addChildElem(naExportRule); } // Add the export rule exportRules2.addChildElem(naSecurityRules); rules.addChildElem(exportRules2); elem.addChildElem(rules); NaElement result = null; try { log.info(elem); result = server.invokeElem(elem).getChildByName("loaded-pathnames"); } catch (Exception e) { String msg = "Failed to create NFS share on path: " + (mountPath != null ? mountPath : exportPath); log.error(msg, e); throw new NetAppException(msg, e); } // build the result ArrayList<String> pathnames = new ArrayList<String>(); for (NaElement pathInfo : (List<NaElement>) result.getChildren()) { pathnames.add(pathInfo.getChildContent("name")); // API doc is wrong here } if (!pathnames.contains(exportPath)) { String msg = "Failed to create NFS share on path: " + (mountPath != null ? mountPath : exportPath); msg += ". Check directory exists in volume."; log.error(msg); throw new NetAppException(msg); } return pathnames; } static private void addHosts(NaElement elem, Set<String> hosts, boolean addAll) { // To add all hosts, NetApp API requires you to create a single // 'exports-hostname-info' element with a child element 'all-hosts' // with value of true. if (addAll) { NaElement exportHost = new NaElement("exports-hostname-info"); exportHost.addNewChild("all-hosts", String.valueOf(true)); elem.addChildElem(exportHost); } // Otherwise add each host explicitly else { for (String name : hosts) { NaElement exportHost = new NaElement("exports-hostname-info"); exportHost.addNewChild("name", name); elem.addChildElem(exportHost); } } } }