Add `auto_unmount` mount option for glusterfs fuse mount.

libfuse has an auto_unmount option which, if enabled, ensures that
the file system is unmounted at FUSE server termination by running a
separate monitor process that performs the unmount when that occurs.
(This feature would probably better be called "robust auto-unmount",
as FUSE servers usually do try to unmount their file systems upon
termination, it's just this mechanism is not crash resilient.)
This change implements that option and behavior for glusterfs.

This option will be only supported for clients with version >3.11.

Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
pull/6/head
Humble Chirammal 2017-05-18 00:57:03 +05:30
parent ac62748480
commit 04bf95a5d1
1 changed files with 66 additions and 18 deletions

View File

@ -71,7 +71,7 @@ const (
replicaCount = 3 replicaCount = 3
durabilityType = "replicate" durabilityType = "replicate"
secretKeyName = "key" // key name used in secret secretKeyName = "key" // key name used in secret
gciGlusterMountBinariesPath = "/sbin/mount.glusterfs" gciLinuxGlusterMountBinaryPath = "/sbin/mount.glusterfs"
defaultGidMin = 2000 defaultGidMin = 2000
defaultGidMax = math.MaxInt32 defaultGidMax = math.MaxInt32
// absoluteGidMin/Max are currently the same as the // absoluteGidMin/Max are currently the same as the
@ -83,6 +83,8 @@ const (
heketiAnn = "heketi-dynamic-provisioner" heketiAnn = "heketi-dynamic-provisioner"
glusterTypeAnn = "gluster.org/type" glusterTypeAnn = "gluster.org/type"
glusterDescAnn = "Gluster: Dynamically provisioned PV" glusterDescAnn = "Gluster: Dynamically provisioned PV"
linuxGlusterMountBinary = "mount.glusterfs"
autoUnmountBinaryVer = "3.11"
) )
func (plugin *glusterfsPlugin) Init(host volume.VolumeHost) error { func (plugin *glusterfsPlugin) Init(host volume.VolumeHost) error {
@ -290,8 +292,8 @@ func (b *glusterfsMounter) CanMount() error {
exe := exec.New() exe := exec.New()
switch runtime.GOOS { switch runtime.GOOS {
case "linux": case "linux":
if _, err := exe.Command("/bin/ls", gciGlusterMountBinariesPath).CombinedOutput(); err != nil { if _, err := exe.Command("/bin/ls", gciLinuxGlusterMountBinaryPath).CombinedOutput(); err != nil {
return fmt.Errorf("Required binary %s is missing", gciGlusterMountBinariesPath) return fmt.Errorf("Required binary %s is missing", gciLinuxGlusterMountBinaryPath)
} }
} }
return nil return nil
@ -376,13 +378,58 @@ func (b *glusterfsMounter) setUpAtInternal(dir string) error {
} }
} }
options = append(options, "backup-volfile-servers="+dstrings.Join(addrlist[:], ":")) options = append(options, "backup-volfile-servers="+dstrings.Join(addrlist[:], ":"))
//fetch client version.
mountBinaryVerStr := ""
mountStr := ""
cmdOut, err := b.exe.Command(linuxGlusterMountBinary, "-V").CombinedOutput()
if err != nil {
return fmt.Errorf("Failed to get binary %s version", linuxGlusterMountBinary)
}
//cmdOut will be filled as shown below.
/*
[root@]# mount.glusterfs -V
glusterfs 3.10.1
Repository revision: git://git.gluster.org/glusterfs.git
Copyright (c) 2006-2016 Red Hat, Inc. <https://www.gluster.org/>
GlusterFS comes with ABSOLUTELY NO WARRANTY.
.........
*/
parseStr := string(cmdOut)
if parseStr != "" {
//Store the version line from parseStr
mountStrSlice := dstrings.Split(parseStr, "\n")
if len(mountStrSlice) > 0 {
mountStr = mountStrSlice[0]
}
if mountStr != "" {
// Get the [binary, version] slice.
mountBinaryVerSlice := dstrings.Split(mountStr, " ")
if len(mountBinaryVerSlice) >= 2 {
// Get the 'version' string in mountBinaryVerStr
mountBinaryVerStr = mountBinaryVerSlice[1]
}
}
}
mountOptions := volume.JoinMountOptions(b.mountOptions, options)
for i := len(mountOptions) - 1; i >= 0; i-- {
if mountOptions[i] == "auto_unmount" && mountBinaryVerStr != "" && mountBinaryVerStr < autoUnmountBinaryVer {
mountOptions = append(mountOptions[:i], mountOptions[i+1:]...)
}
}
// Avoid mount storm, pick a host randomly. // Avoid mount storm, pick a host randomly.
// Iterate all hosts until mount succeeds. // Iterate all hosts until mount succeeds.
for _, ip := range addrlist { for _, ip := range addrlist {
mountOptions := volume.JoinMountOptions(b.mountOptions, options)
errs = b.mounter.Mount(ip+":"+b.path, dir, "glusterfs", mountOptions) errs = b.mounter.Mount(ip+":"+b.path, dir, "glusterfs", mountOptions)
if errs == nil { if errs == nil {
glog.Infof("glusterfs: successfully mounted %s", dir) glog.Infof("glusterfs: successfully mounted %s", dir)
@ -819,6 +866,7 @@ func (p *glusterfsVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
"kubernetes.io/createdby": heketiAnn, "kubernetes.io/createdby": heketiAnn,
glusterTypeAnn: "file", glusterTypeAnn: "file",
"Description": glusterDescAnn, "Description": glusterDescAnn,
v1.MountOptionAnnotation: "auto_unmount",
} }
pv.Spec.Capacity = v1.ResourceList{ pv.Spec.Capacity = v1.ResourceList{