2015-03-26 18:53:21 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2015 The Kubernetes Authors All rights reserved .
2015-03-26 18:53:21 +00:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package glusterfs
import (
2015-10-07 16:47:11 +00:00
"fmt"
2015-03-26 18:53:21 +00:00
"os"
2015-09-11 13:23:19 +00:00
"path"
2015-03-26 18:53:21 +00:00
2015-08-05 22:05:17 +00:00
"github.com/golang/glog"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util/exec"
"k8s.io/kubernetes/pkg/util/mount"
2016-01-11 07:55:51 +00:00
"k8s.io/kubernetes/pkg/util/strings"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/volume"
2015-03-26 18:53:21 +00:00
)
// This is the primary entrypoint for volume plugins.
func ProbeVolumePlugins ( ) [ ] volume . VolumePlugin {
2015-10-07 16:47:11 +00:00
return [ ] volume . VolumePlugin { & glusterfsPlugin { nil , exec . New ( ) } }
2015-03-26 18:53:21 +00:00
}
type glusterfsPlugin struct {
host volume . VolumeHost
2015-10-07 16:47:11 +00:00
exe exec . Interface
2015-03-26 18:53:21 +00:00
}
var _ volume . VolumePlugin = & glusterfsPlugin { }
2015-06-26 20:37:11 +00:00
var _ volume . PersistentVolumePlugin = & glusterfsPlugin { }
2015-03-26 18:53:21 +00:00
const (
glusterfsPluginName = "kubernetes.io/glusterfs"
)
2015-09-30 18:31:53 +00:00
func ( plugin * glusterfsPlugin ) Init ( host volume . VolumeHost ) error {
2015-03-26 18:53:21 +00:00
plugin . host = host
2015-09-30 18:31:53 +00:00
return nil
2015-03-26 18:53:21 +00:00
}
func ( plugin * glusterfsPlugin ) Name ( ) string {
return glusterfsPluginName
}
2015-04-14 16:29:33 +00:00
func ( plugin * glusterfsPlugin ) CanSupport ( spec * volume . Spec ) bool {
2015-10-07 16:47:11 +00:00
if ( spec . PersistentVolume != nil && spec . PersistentVolume . Spec . Glusterfs == nil ) ||
( spec . Volume != nil && spec . Volume . Glusterfs == nil ) {
return false
}
2016-02-25 19:00:12 +00:00
2016-02-23 15:40:35 +00:00
return true
2015-10-07 16:47:11 +00:00
2015-03-26 18:53:21 +00:00
}
2015-05-18 20:22:30 +00:00
func ( plugin * glusterfsPlugin ) GetAccessModes ( ) [ ] api . PersistentVolumeAccessMode {
return [ ] api . PersistentVolumeAccessMode {
2015-03-26 18:53:21 +00:00
api . ReadWriteOnce ,
api . ReadOnlyMany ,
api . ReadWriteMany ,
}
}
2016-03-23 05:12:21 +00:00
func ( plugin * glusterfsPlugin ) NewMounter ( spec * volume . Spec , pod * api . Pod , _ volume . VolumeOptions ) ( volume . Mounter , error ) {
2015-06-26 20:37:11 +00:00
source , _ := plugin . getGlusterVolumeSource ( spec )
2015-06-01 14:34:40 +00:00
ep_name := source . EndpointsName
2015-05-11 00:12:57 +00:00
ns := pod . Namespace
2016-02-03 21:21:05 +00:00
ep , err := plugin . host . GetKubeClient ( ) . Core ( ) . Endpoints ( ns ) . Get ( ep_name )
2015-03-26 18:53:21 +00:00
if err != nil {
2015-10-07 16:47:11 +00:00
glog . Errorf ( "glusterfs: failed to get endpoints %s[%v]" , ep_name , err )
2015-03-26 18:53:21 +00:00
return nil , err
}
2015-10-07 16:47:11 +00:00
glog . V ( 1 ) . Infof ( "glusterfs: endpoints %v" , ep )
2016-03-23 05:12:21 +00:00
return plugin . newMounterInternal ( spec , ep , pod , plugin . host . GetMounter ( ) , exec . New ( ) )
2015-03-26 18:53:21 +00:00
}
2015-06-26 20:37:11 +00:00
func ( plugin * glusterfsPlugin ) getGlusterVolumeSource ( spec * volume . Spec ) ( * api . GlusterfsVolumeSource , bool ) {
// Glusterfs volumes used directly in a pod have a ReadOnly flag set by the pod author.
// Glusterfs volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
2015-08-12 19:11:03 +00:00
if spec . Volume != nil && spec . Volume . Glusterfs != nil {
return spec . Volume . Glusterfs , spec . Volume . Glusterfs . ReadOnly
2015-06-01 14:34:40 +00:00
} else {
2015-08-12 19:11:03 +00:00
return spec . PersistentVolume . Spec . Glusterfs , spec . ReadOnly
2015-06-01 14:34:40 +00:00
}
}
2016-03-23 05:12:21 +00:00
func ( plugin * glusterfsPlugin ) newMounterInternal ( spec * volume . Spec , ep * api . Endpoints , pod * api . Pod , mounter mount . Interface , exe exec . Interface ) ( volume . Mounter , error ) {
2015-06-26 20:37:11 +00:00
source , readOnly := plugin . getGlusterVolumeSource ( spec )
2016-03-23 05:12:21 +00:00
return & glusterfsMounter {
2015-07-23 07:07:40 +00:00
glusterfs : & glusterfs {
2015-08-12 19:11:03 +00:00
volName : spec . Name ( ) ,
2015-07-23 07:07:40 +00:00
mounter : mounter ,
pod : pod ,
plugin : plugin ,
} ,
2015-03-26 18:53:21 +00:00
hosts : ep ,
2015-06-01 14:34:40 +00:00
path : source . Path ,
2015-06-29 16:54:43 +00:00
readOnly : readOnly ,
2015-07-23 07:07:40 +00:00
exe : exe } , nil
2015-03-26 18:53:21 +00:00
}
2016-03-23 05:12:21 +00:00
func ( plugin * glusterfsPlugin ) NewUnmounter ( volName string , podUID types . UID ) ( volume . Unmounter , error ) {
return plugin . newUnmounterInternal ( volName , podUID , plugin . host . GetMounter ( ) )
2015-03-26 18:53:21 +00:00
}
2016-03-23 05:12:21 +00:00
func ( plugin * glusterfsPlugin ) newUnmounterInternal ( volName string , podUID types . UID , mounter mount . Interface ) ( volume . Unmounter , error ) {
return & glusterfsUnmounter { & glusterfs {
2015-03-26 18:53:21 +00:00
volName : volName ,
mounter : mounter ,
2015-05-11 00:12:57 +00:00
pod : & api . Pod { ObjectMeta : api . ObjectMeta { UID : podUID } } ,
2015-03-26 18:53:21 +00:00
plugin : plugin ,
2015-07-23 07:07:40 +00:00
} } , nil
2015-03-26 18:53:21 +00:00
}
2015-10-07 16:47:11 +00:00
func ( plugin * glusterfsPlugin ) execCommand ( command string , args [ ] string ) ( [ ] byte , error ) {
cmd := plugin . exe . Command ( command , args ... )
return cmd . CombinedOutput ( )
}
2015-03-26 18:53:21 +00:00
// Glusterfs volumes represent a bare host file or directory mount of an Glusterfs export.
type glusterfs struct {
2015-07-23 07:07:40 +00:00
volName string
pod * api . Pod
mounter mount . Interface
plugin * glusterfsPlugin
2015-12-04 20:40:01 +00:00
volume . MetricsNil
2015-07-23 07:07:40 +00:00
}
2016-03-23 05:12:21 +00:00
type glusterfsMounter struct {
2015-07-23 07:07:40 +00:00
* glusterfs
2015-03-26 18:53:21 +00:00
hosts * api . Endpoints
path string
2015-06-29 16:54:43 +00:00
readOnly bool
2015-03-26 18:53:21 +00:00
exe exec . Interface
}
2016-03-23 05:12:21 +00:00
var _ volume . Mounter = & glusterfsMounter { }
2015-07-23 07:07:40 +00:00
2016-03-23 05:12:21 +00:00
func ( b * glusterfsMounter ) GetAttributes ( ) volume . Attributes {
2015-10-30 20:25:36 +00:00
return volume . Attributes {
2016-01-11 16:10:55 +00:00
ReadOnly : b . readOnly ,
Managed : false ,
SupportsSELinux : false ,
2015-10-30 20:25:36 +00:00
}
2015-10-20 18:49:39 +00:00
}
2015-03-26 18:53:21 +00:00
// SetUp attaches the disk and bind mounts to the volume path.
2016-03-23 05:12:21 +00:00
func ( b * glusterfsMounter ) SetUp ( fsGroup * int64 ) error {
2015-12-18 15:55:11 +00:00
return b . SetUpAt ( b . GetPath ( ) , fsGroup )
2015-03-26 18:53:21 +00:00
}
2016-03-23 05:12:21 +00:00
func ( b * glusterfsMounter ) SetUpAt ( dir string , fsGroup * int64 ) error {
2015-04-16 23:49:53 +00:00
notMnt , err := b . mounter . IsLikelyNotMountPoint ( dir )
2015-10-07 16:47:11 +00:00
glog . V ( 4 ) . Infof ( "glusterfs: mount set up: %s %v %v" , dir , ! notMnt , err )
2015-03-26 18:53:21 +00:00
if err != nil && ! os . IsNotExist ( err ) {
return err
}
2015-04-16 23:49:53 +00:00
if ! notMnt {
2015-03-26 18:53:21 +00:00
return nil
}
2015-04-03 01:08:04 +00:00
2015-03-26 18:53:21 +00:00
os . MkdirAll ( dir , 0750 )
2015-07-23 07:07:40 +00:00
err = b . setUpAtInternal ( dir )
2015-03-26 18:53:21 +00:00
if err == nil {
return nil
}
2015-04-03 01:08:04 +00:00
// Cleanup upon failure.
2016-03-23 05:12:21 +00:00
c := & glusterfsUnmounter { b . glusterfs }
2015-07-23 07:07:40 +00:00
c . cleanup ( dir )
2015-03-26 18:53:21 +00:00
return err
}
func ( glusterfsVolume * glusterfs ) GetPath ( ) string {
name := glusterfsPluginName
2016-01-11 07:55:51 +00:00
return glusterfsVolume . plugin . host . GetPodVolumeDir ( glusterfsVolume . pod . UID , strings . EscapeQualifiedNameForDisk ( name ) , glusterfsVolume . volName )
2015-03-26 18:53:21 +00:00
}
2016-03-23 05:12:21 +00:00
type glusterfsUnmounter struct {
2015-07-23 07:07:40 +00:00
* glusterfs
}
2016-03-23 05:12:21 +00:00
var _ volume . Unmounter = & glusterfsUnmounter { }
2015-07-23 07:07:40 +00:00
2016-03-23 05:12:21 +00:00
func ( c * glusterfsUnmounter ) TearDown ( ) error {
2015-07-23 07:07:40 +00:00
return c . TearDownAt ( c . GetPath ( ) )
2015-03-26 18:53:21 +00:00
}
2016-03-23 05:12:21 +00:00
func ( c * glusterfsUnmounter ) TearDownAt ( dir string ) error {
2015-07-23 07:07:40 +00:00
return c . cleanup ( dir )
2015-03-26 18:53:21 +00:00
}
2016-03-23 05:12:21 +00:00
func ( c * glusterfsUnmounter ) cleanup ( dir string ) error {
2015-04-16 23:49:53 +00:00
notMnt , err := c . mounter . IsLikelyNotMountPoint ( dir )
2015-03-26 18:53:21 +00:00
if err != nil {
2015-10-07 16:47:11 +00:00
return fmt . Errorf ( "glusterfs: Error checking IsLikelyNotMountPoint: %v" , err )
2015-03-26 18:53:21 +00:00
}
2015-04-16 23:49:53 +00:00
if notMnt {
2015-03-26 18:53:21 +00:00
return os . RemoveAll ( dir )
}
2015-07-23 07:07:40 +00:00
if err := c . mounter . Unmount ( dir ) ; err != nil {
2015-10-07 16:47:11 +00:00
return fmt . Errorf ( "glusterfs: Unmounting failed: %v" , err )
2015-03-26 18:53:21 +00:00
}
2015-04-16 23:49:53 +00:00
notMnt , mntErr := c . mounter . IsLikelyNotMountPoint ( dir )
2015-03-26 18:53:21 +00:00
if mntErr != nil {
2015-10-07 16:47:11 +00:00
return fmt . Errorf ( "glusterfs: IsLikelyNotMountPoint check failed: %v" , mntErr )
2015-03-26 18:53:21 +00:00
}
2015-04-16 23:49:53 +00:00
if notMnt {
2015-03-26 18:53:21 +00:00
if err := os . RemoveAll ( dir ) ; err != nil {
2015-10-07 16:47:11 +00:00
return fmt . Errorf ( "glusterfs: RemoveAll failed: %v" , err )
2015-03-26 18:53:21 +00:00
}
}
return nil
}
2016-03-23 05:12:21 +00:00
func ( b * glusterfsMounter ) setUpAtInternal ( dir string ) error {
2015-03-26 18:53:21 +00:00
var errs error
2015-04-03 01:08:04 +00:00
options := [ ] string { }
2015-07-24 19:04:03 +00:00
if b . readOnly {
2015-04-03 01:08:04 +00:00
options = append ( options , "ro" )
2015-03-26 18:53:21 +00:00
}
2015-09-11 13:23:19 +00:00
p := path . Join ( b . glusterfs . plugin . host . GetPluginDir ( glusterfsPluginName ) , b . glusterfs . volName )
if err := os . MkdirAll ( p , 0750 ) ; err != nil {
2015-10-07 16:47:11 +00:00
return fmt . Errorf ( "glusterfs: mkdir failed: %v" , err )
2015-09-11 13:23:19 +00:00
}
2016-04-26 17:06:30 +00:00
// adding log-level ERROR to remove noise
// and more specific log path so each pod has
// it's own log based on PV + Pod
log := path . Join ( p , b . pod . Name + "-glusterfs.log" )
options = append ( options , "log-level=ERROR" )
2015-09-11 13:23:19 +00:00
options = append ( options , "log-file=" + log )
addr := make ( map [ string ] struct { } )
for _ , s := range b . hosts . Subsets {
for _ , a := range s . Addresses {
addr [ a . IP ] = struct { } { }
}
}
2015-04-03 01:08:04 +00:00
// Avoid mount storm, pick a host randomly.
// Iterate all hosts until mount succeeds.
2015-09-11 13:23:19 +00:00
for hostIP := range addr {
2015-07-23 07:07:40 +00:00
errs = b . mounter . Mount ( hostIP + ":" + b . path , dir , "glusterfs" , options )
2015-03-26 18:53:21 +00:00
if errs == nil {
2016-04-26 17:06:30 +00:00
glog . Infof ( "glusterfs: successfully mounted %s" , dir )
2015-03-26 18:53:21 +00:00
return nil
}
}
2016-04-26 17:06:30 +00:00
// Failed mount scenario.
// Since gluster does not return eror text
// it all goes in a log file, we will read the log file
logerror := readGlusterLog ( log , b . pod . Name )
if logerror != nil {
// return fmt.Errorf("glusterfs: mount failed: %v", logerror)
return fmt . Errorf ( "glusterfs: mount failed: %v the following error information was pulled from the glusterfs log to help diagnose this issue: %v" , errs , logerror )
}
2015-10-07 16:47:11 +00:00
return fmt . Errorf ( "glusterfs: mount failed: %v" , errs )
2015-03-26 18:53:21 +00:00
}