func populateVolumeSMB(confMap conf.ConfMap, volumeSection string, volume *Volume, shareNameSet stringSet) (err error) {
	volume.SMB.AuditLogging, err = confMap.FetchOptionValueBool(volumeSection, "SMBAuditLogging")
	if nil != err {
		return
	}
	volume.SMB.Browseable, err = confMap.FetchOptionValueBool(volumeSection, "SMBBrowseable")
	if nil != err {
		return
	}
	volume.SMB.EncryptionRequired, err = confMap.FetchOptionValueBool(volumeSection, "SMBEncryptionRequired")
	if nil != err {
		return
	}
	volume.SMB.Path = volumeDummyPath
	volume.SMB.ShareName, err = fetchStringSet(confMap, volumeSection, "SMBShareName", shareNameSet)
	if nil != err {
		return
	}
	volume.SMB.StrictSync, err = confMap.FetchOptionValueBool(volumeSection, "SMBStrictSync")
	if nil != err {
		return
	}
	volume.SMB.ValidADGroup, err = confMap.FetchOptionValueStringSlice(volumeSection, "SMBValidADGroupList")
	if nil != err {
		return
	}
	volume.SMB.ValidADUsers, err = confMap.FetchOptionValueStringSlice(volumeSection, "SMBValidADUserList")
	if nil != err {
		return
	}
	volume.SMB.ValidUsers, err = confMap.FetchOptionValueStringSlice(volumeSection, "SMBValidUserList")
	if nil != err {
		return
	}
	return
}
populateVolumeSMB populates the Volume with SMB related info
package confgen
import (
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"strconv"
	"strings"
	"github.com/NVIDIA/proxyfs/conf"
)
type envSettingsStruct struct {
	linuxUserComment          string
	pathToNet                 string
	pathToKRB5ConfDir         string
	pathToPDBEdit             string
	pathToPerVirtualIPAddrDir string
	pathToSMBD                string
	pathToSMBPasswd           string
}
const (
	useraddPath     = "/usr/sbin/useradd"
	userdelPath     = "/usr/sbin/userdel"
	volumeDummyPath = "/opt/ss/var/lib/dummy_path"
)
const (
	exportsFileName       = "exports"               
	fuseSetupFileName     = "fuse_setup.bash"       
	proxyFSConfFileName   = "proxyfs.conf"          
	realmsSourceDirName   = "realms"                
	smbConfFileName       = "smb.conf"              
	smbCommonConfFileName = "smb_common.conf"       
	smbPassdbFileName     = "passdb.tdb"            
	smbUsersSetupFileName = "smb_users_setup.bash"  
	vipsDirName           = "vips"                  
	proxyfsConfDir0       = "/usr/lib/proxyfsd"     
	proxyfsConfDir1       = "/opt/ss/lib/proxyfsd"  
	proxyfsConfDir2       = "./templates"           
)
const (
	confDirPerm     = os.FileMode(0777)  
	confFilePerm    = os.FileMode(0666)  
	exportsFilePerm = os.FileMode(0666)  
	fuseDirPerm     = os.FileMode(0000)  
	scriptPerm      = os.FileMode(0777)  
	smbConfPerm     = os.FileMode(0644)  
)
type smbUserMap map[string]string  
type uint64Set map[uint64]struct{}
type stringSet map[string]struct{}
const (
	nfsSubtreeCheck = "no_subtree_check"  
	nfsSync         = "sync"              
)
type NFSClient struct {
	clientName    string
	ClientPattern string
	AccessMode    string
	RootSquash    string
	Secure        string
}
type NFSClientList []*NFSClient
type NFSClientMap map[string]*NFSClient  
type Volume struct {
	VolumeName         string         
	VolumeGroup        *VolumeGroup   
	FSID               uint64         
	FUSEMountPointName string         
	nfsClientList      NFSClientList  
	nfsClientMap       NFSClientMap   
	AccountName        string         
	SMB                SMBVolume
}
type volumeMap map[string]*Volume  
type SMBVolume struct {
	AuditLogging       bool
	Browseable         bool
	EncryptionRequired bool
	Path               string
	ShareName          string  
	StrictSync         bool
	ValidADGroup       []string
	ValidADUsers       []string
	ValidUsers         []string
}
type SMBVG struct {
	ADBackEnd           string
	ADEnabled           bool
	ADIDMapDefaultMin   int
	ADIDMapDefaultMax   int
	ADIDMapWorkgroupMin int
	ADIDMapWorkgroupMax int
	ADIDMgmt            bool
	ADIDSchema          string
	AuditLogging        bool  
	BrowserAnnounce     string
	FastTCPPort         int
	MapToGuest          string
	ADRealm             string
	RPCServerLSARPC     string
	Security            string
	ServerMinProtocol   string
	TCPPort             int
	WorkGroup           string
}
type VolumeGroup struct {
	PrimaryPeer     string      
	SMB             SMBVG       
	VirtualHostName string      
	VirtualIPAddr   net.IP      
	VirtualIPMask   *net.IPNet  
	VolumeGroupName string      
	VolumeMap       volumeMap   
}
type volumeGroupMap map[string]*VolumeGroup  
func computeInitial(envMap EnvMap, confFilePath string, confOverrides []string, initialDirPath string) (err error) {
	var (
		envSettings                    *envSettingsStruct
		exportsFile                    *os.File
		fuseSetupFile                  *os.File
		initialConfMap                 conf.ConfMap
		localSMBVolumeGroupMap         volumeGroupMap
		localVolumeMap                 volumeMap
		nfsClient                      *NFSClient
		smbUsersSetupFile              *os.File
		toCreateSMBUserMap             smbUserMap
		toCreateSMBUserName            string
		toCreateSMBUserPassword        string
		toCreateSMBUserPasswordEscaped string  
		volume                         *Volume
	)
	envSettings = fetchEnvironSettings(envMap)
	initialConfMap, err = conf.MakeConfMapFromFile(confFilePath)
	if nil != err {
		return
	}
	err = initialConfMap.UpdateFromStrings(confOverrides)
	if nil != err {
		return
	}
	err = os.Mkdir(initialDirPath, confDirPerm)
	if nil != err {
		return
	}
	err = ioutil.WriteFile(initialDirPath+"/"+proxyFSConfFileName, []byte(initialConfMap.Dump()), confFilePerm)
	if nil != err {
		return
	}
	_, localSMBVolumeGroupMap, localVolumeMap, _, _, err = fetchVolumeInfo(initialConfMap)
	if nil != err {
		return
	}
	_, toCreateSMBUserMap, _, _, err = computeSMBUserListChange(make(smbUserMap), initialConfMap)
	if nil != err {
		return
	}
	exportsFile, err = os.OpenFile(initialDirPath+"/"+exportsFileName, os.O_CREATE|os.O_WRONLY, exportsFilePerm)
	if nil != err {
		return
	}
	for _, volume = range localVolumeMap {
		if 0 < len(volume.nfsClientList) {
			_, err = exportsFile.WriteString(fmt.Sprintf("\"%s\"", volume.FUSEMountPointName))
			if nil != err {
				return
			}
			for _, nfsClient = range volume.nfsClientList {
				_, err = exportsFile.WriteString(fmt.Sprintf(" %s(%s,%s,fsid=%d,%s,%s,%s)", nfsClient.ClientPattern, nfsClient.AccessMode, nfsSync, volume.FSID, nfsClient.RootSquash, nfsClient.Secure, nfsSubtreeCheck))
				if nil != err {
					return
				}
			}
			_, err = exportsFile.WriteString("\n")
			if nil != err {
				return
			}
		}
	}
	err = exportsFile.Close()
	if nil != err {
		return
	}
	smbUsersSetupFile, err = os.OpenFile(initialDirPath+"/"+smbUsersSetupFileName, os.O_CREATE|os.O_WRONLY, scriptPerm)
	if nil != err {
		return
	}
	_, err = smbUsersSetupFile.WriteString("#!/bin/bash\n")
	if nil != err {
		return
	}
	_, err = smbUsersSetupFile.WriteString("set -e\n")
	if nil != err {
		return
	}
	for toCreateSMBUserName, toCreateSMBUserPassword = range toCreateSMBUserMap {
		_, err = smbUsersSetupFile.WriteString(fmt.Sprintf("%s --comment %s --no-create-home %s\n", useraddPath, envSettings.linuxUserComment, toCreateSMBUserName))
		if nil != err {
			return
		}
		toCreateSMBUserPasswordEscaped = strings.Replace(toCreateSMBUserPassword, "\\", "\\\\\\", -1)
		_, err = smbUsersSetupFile.WriteString(fmt.Sprintf("echo -e \"%s\\n%s\" | %s -c %s -a %s\n", toCreateSMBUserPasswordEscaped, toCreateSMBUserPasswordEscaped, envSettings.pathToSMBPasswd, smbConfFileName, toCreateSMBUserName))
		if nil != err {
			return
		}
	}
	err = smbUsersSetupFile.Close()
	if nil != err {
		return
	}
	err = os.Mkdir(initialDirPath+"/"+vipsDirName, confDirPerm)
	if nil != err {
		return
	}
	err = createSMBConf(initialDirPath, localSMBVolumeGroupMap)
	if nil != err {
		return
	}
	fuseSetupFile, err = os.OpenFile(initialDirPath+"/"+fuseSetupFileName, os.O_CREATE|os.O_WRONLY, scriptPerm)
	if nil != err {
		return
	}
	_, err = fuseSetupFile.WriteString("#!/bin/bash\n")
	if nil != err {
		return
	}
	_, err = fuseSetupFile.WriteString("set -e\n")
	if nil != err {
		return
	}
	for _, volume = range localVolumeMap {
		if "" != volume.FUSEMountPointName {
			cmdString := ""
			cmdString += fmt.Sprintf("if [ ! -d '%s' ]; then\n", volume.FUSEMountPointName)
			cmdString += fmt.Sprintf("    mkdir -p -m 0%03o '%s' || true\n",
				fuseDirPerm, volume.FUSEMountPointName)
			cmdString += fmt.Sprintf("fi\n")
			_, err = fuseSetupFile.WriteString(cmdString)
			if nil != err {
				return
			}
		}
	}
	err = fuseSetupFile.Close()
	if nil != err {
		return
	}
	return nil  
}
func computePhases(envMap EnvMap, initialDirPath string, confFilePath string, confOverrides []string, phaseOneDirPath string, phaseTwoDirPath string) (err error) {
	var (
		initialConfMap  conf.ConfMap
		phaseOneConfMap conf.ConfMap
		phaseTwoConfMap conf.ConfMap
	)
	initialConfMap, err = conf.MakeConfMapFromFile(initialDirPath + "/" + proxyFSConfFileName)
	if nil != err {
		return
	}
	phaseTwoConfMap, err = conf.MakeConfMapFromFile(confFilePath)
	if nil != err {
		return
	}
	err = phaseTwoConfMap.UpdateFromStrings(confOverrides)
	if nil != err {
		return
	}
	phaseOneConfMap = initialConfMap  
	err = os.Mkdir(phaseOneDirPath, confDirPerm)
	if nil != err {
		return
	}
	err = ioutil.WriteFile(phaseOneDirPath+"/"+proxyFSConfFileName, []byte(phaseOneConfMap.Dump()), confFilePerm)
	if nil != err {
		return
	}
	err = os.Mkdir(phaseTwoDirPath, confDirPerm)
	if nil != err {
		return
	}
	err = ioutil.WriteFile(phaseTwoDirPath+"/"+proxyFSConfFileName, []byte(phaseTwoConfMap.Dump()), confFilePerm)
	if nil != err {
		return
	}
	return nil  
}
func fetchEnvironSettings(envMap EnvMap) (envSettings *envSettingsStruct) {
	var (
		inEnv bool
	)
	envSettings = &envSettingsStruct{}
	envSettings.linuxUserComment, inEnv = envMap[LinuxUserCommentEnv]
	if !inEnv {
		envSettings.linuxUserComment = LinuxUserCommentDefault
	}
	envSettings.pathToNet, inEnv = envMap[PathToNetEnv]
	if !inEnv {
		envSettings.pathToNet = PathToNetDefault
	}
	envSettings.pathToKRB5ConfDir, inEnv = envMap[PathToKRB5ConfDirEnv]
	if !inEnv {
		envSettings.pathToKRB5ConfDir = PathToKRB5ConfDirDefault
	}
	envSettings.pathToPDBEdit, inEnv = envMap[PathToPDBEditEnv]
	if !inEnv {
		envSettings.pathToPDBEdit = PathToPDBEditDefault
	}
	envSettings.pathToPerVirtualIPAddrDir, inEnv = envMap[PathToPerVirtualIPAddrDirEnv]
	if !inEnv {
		envSettings.pathToPerVirtualIPAddrDir = PathToPerVirtualIPAddrDirDefault
	}
	envSettings.pathToSMBD, inEnv = envMap[PathToSMBDEnv]
	if !inEnv {
		envSettings.pathToSMBD = PathToSMBDDefault
	}
	envSettings.pathToSMBPasswd, inEnv = envMap[PathToSMBPasswdEnv]
	if !inEnv {
		envSettings.pathToSMBPasswd = PathToSMBPasswdDefault
	}
	return
}
func computeSMBUserListChange(oldSMBUserMap smbUserMap, newConfMap conf.ConfMap) (newSMBUserMap smbUserMap, toCreateSMBUserMap smbUserMap, toUpdateSMBUserMap smbUserMap, toDeleteSMBUserMap smbUserMap, err error) {
	var (
		inNewSMBUserMap    bool
		inOldSMBUserMap    bool
		newSMBUserName     string
		newSMBUserNameList []string
		newSMBUserPassword string
		oldSMBUserName     string
	)
	newSMBUserMap = make(smbUserMap)
	toCreateSMBUserMap = make(smbUserMap)
	toUpdateSMBUserMap = make(smbUserMap)
	toDeleteSMBUserMap = make(smbUserMap)
	newSMBUserNameList, err = newConfMap.FetchOptionValueStringSlice("FSGlobals", "SMBUserList")
	if nil != err {
		newSMBUserNameList = make([]string, 0)
	}
	for _, newSMBUserName = range newSMBUserNameList {
		newSMBUserPassword, err = newConfMap.FetchOptionValueBase64String("SMBUsers", newSMBUserName)
		if nil != err {
			return
		}
		newSMBUserMap[newSMBUserName] = newSMBUserPassword
		_, inOldSMBUserMap = oldSMBUserMap[newSMBUserName]
		if inOldSMBUserMap {
			toUpdateSMBUserMap[newSMBUserName] = newSMBUserPassword
		} else {
			toCreateSMBUserMap[newSMBUserName] = newSMBUserPassword
		}
	}
	for oldSMBUserName = range oldSMBUserMap {
		_, inNewSMBUserMap = newSMBUserMap[oldSMBUserName]
		if !inNewSMBUserMap {
			toDeleteSMBUserMap[oldSMBUserName] = ""
		}
	}
	return
}
func computeVolumeSetChange(oldConfMap conf.ConfMap, newConfMap conf.ConfMap) (toDeleteVolumeMap volumeMap, toCreateVolumeMap volumeMap, err error) {
	var (
		newLocalVolumeMap volumeMap
		newVolume         *Volume
		ok                bool
		oldLocalVolumeMap volumeMap
		oldVolume         *Volume
		volumeName        string
	)
	_, _, oldLocalVolumeMap, _, _, err = fetchVolumeInfo(oldConfMap)
	if nil != err {
		err = fmt.Errorf("In oldConfMap: %v", err)
		return
	}
	_, _, newLocalVolumeMap, _, _, err = fetchVolumeInfo(newConfMap)
	if nil != err {
		err = fmt.Errorf("In newConfMap: %v", err)
		return
	}
	toDeleteVolumeMap = make(volumeMap)
	for volumeName, oldVolume = range oldLocalVolumeMap {
		newVolume, ok = newLocalVolumeMap[volumeName]
		if !ok || (oldVolume.VolumeGroup.VolumeGroupName != newVolume.VolumeGroup.VolumeGroupName) {
			toDeleteVolumeMap[volumeName] = oldVolume
		}
	}
	toCreateVolumeMap = make(volumeMap)
	for volumeName, newVolume = range newLocalVolumeMap {
		oldVolume, ok = oldLocalVolumeMap[volumeName]
		if !ok || (oldVolume.VolumeGroup.VolumeGroupName != newVolume.VolumeGroup.VolumeGroupName) {
			toCreateVolumeMap[volumeName] = newVolume
		}
	}
	return
}
func fetchStringSet(confMap conf.ConfMap, section string, value string, valueSet stringSet) (data string, err error) {
	var (
		valueAsSlice []string
		ok           bool
	)
	valueAsSlice, err = confMap.FetchOptionValueStringSlice(section, value)
	if err != nil {
		return
	}
	if 0 == len(valueAsSlice) {
		data = ""
		return
	}
	if 1 == len(valueAsSlice) {
		data = valueAsSlice[0]
		if nil != valueSet {
			_, ok = valueSet[data]
			if ok {
				err = fmt.Errorf("Found duplicate [%s]%s (\"%s\")", section, value, data)
				return
			}
			valueSet[data] = struct{}{}
		}
	} else {
		err = fmt.Errorf("Found multiple values for [%s]%s", section, value)
		return
	}
	return
}