Merge pull request #69 from gman0/cephfs-probe

cephfs: volumemounter probe
This commit is contained in:
Huamin Chen 2018-08-14 10:59:14 -04:00 committed by GitHub
commit d09ce2d003
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 37 deletions

View File

@ -46,14 +46,6 @@ var (
DefaultVolumeMounter string DefaultVolumeMounter string
) )
func getVolumeMounterByProbing() string {
if execCommandAndValidate("ceph-fuse", "--version") == nil {
return volumeMounter_fuse
} else {
return volumeMounter_kernel
}
}
func NewCephFSDriver() *cephfsDriver { func NewCephFSDriver() *cephfsDriver {
return &cephfsDriver{} return &cephfsDriver{}
} }
@ -90,6 +82,10 @@ func (fs *cephfsDriver) Run(driverName, nodeId, endpoint, volumeMounter string)
glog.Errorf("cephfs: failed to read volume cache: %v", err) glog.Errorf("cephfs: failed to read volume cache: %v", err)
} }
if err := loadAvailableMounters(); err != nil {
glog.Fatalf("cephfs: failed to load ceph mounters: %v", err)
}
if volumeMounter != "" { if volumeMounter != "" {
if err := validateMounter(volumeMounter); err != nil { if err := validateMounter(volumeMounter); err != nil {
glog.Fatalln(err) glog.Fatalln(err)
@ -97,7 +93,10 @@ func (fs *cephfsDriver) Run(driverName, nodeId, endpoint, volumeMounter string)
DefaultVolumeMounter = volumeMounter DefaultVolumeMounter = volumeMounter
} }
} else { } else {
DefaultVolumeMounter = getVolumeMounterByProbing() // Pick the first available mounter as the default one.
// The choice is biased towards "fuse" in case both
// ceph fuse and kernel mounters are available.
DefaultVolumeMounter = availableMounters[0]
} }
glog.Infof("cephfs: setting default volume mounter to %s", DefaultVolumeMounter) glog.Infof("cephfs: setting default volume mounter to %s", DefaultVolumeMounter)

View File

@ -134,9 +134,12 @@ func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
m := newMounter(volOptions) m, err := newMounter(volOptions)
glog.V(4).Infof("cephfs: mounting volume %s with %s", volId, m.name()) if err != nil {
glog.Errorf("failed to create mounter for volume %s: %v", volId, err)
}
glog.V(4).Infof("cephfs: mounting volume %s with %s", volId, m.name())
if err = m.mount(stagingTargetPath, cr, volOptions, volId); err != nil { if err = m.mount(stagingTargetPath, cr, volOptions, volId); err != nil {
glog.Errorf("failed to mount volume %s: %v", volId, err) glog.Errorf("failed to mount volume %s: %v", volId, err)
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())

View File

@ -97,23 +97,6 @@ func storeCephCredentials(volId volumeID, cr *credentials) error {
return nil return nil
} }
func newMounter(volOptions *volumeOptions) volumeMounter {
mounter := volOptions.Mounter
if mounter == "" {
mounter = DefaultVolumeMounter
}
switch mounter {
case volumeMounter_fuse:
return &fuseMounter{}
case volumeMounter_kernel:
return &kernelMounter{}
}
return nil
}
// //
// Controller service request validation // Controller service request validation
// //

View File

@ -60,7 +60,12 @@ func createVolume(volOptions *volumeOptions, adminCr *credentials, volId volumeI
// Access to cephfs's / is required // Access to cephfs's / is required
volOptions.RootPath = "/" volOptions.RootPath = "/"
if err := mountKernel(cephRoot, adminCr, volOptions, volId); err != nil { m, err := newMounter(volOptions)
if err != nil {
return fmt.Errorf("failed to create mounter: %v", err)
}
if err = m.mount(cephRoot, adminCr, volOptions, volId); err != nil {
return fmt.Errorf("error mounting ceph root: %v", err) return fmt.Errorf("error mounting ceph root: %v", err)
} }
@ -91,22 +96,28 @@ func createVolume(volOptions *volumeOptions, adminCr *credentials, volId volumeI
return nil return nil
} }
func purgeVolume(volId volumeID, cr *credentials, volOptions *volumeOptions) error { func purgeVolume(volId volumeID, adminCr *credentials, volOptions *volumeOptions) error {
// Root path is not set for dynamically provisioned volumes
volOptions.RootPath = "/"
var ( var (
root = getCephRootPath_local(volId) cephRoot = getCephRootPath_local(volId)
volRoot = getCephRootVolumePath_local(volId) volRoot = getCephRootVolumePath_local(volId)
volRootDeleting = volRoot + "-deleting" volRootDeleting = volRoot + "-deleting"
) )
if err := createMountPoint(root); err != nil { if err := createMountPoint(cephRoot); err != nil {
return err return err
} }
if err := mountKernel(root, cr, volOptions, volId); err != nil { // Root path is not set for dynamically provisioned volumes
return err // Access to cephfs's / is required
volOptions.RootPath = "/"
m, err := newMounter(volOptions)
if err != nil {
return fmt.Errorf("failed to create mounter: %v", err)
}
if err = m.mount(cephRoot, adminCr, volOptions, volId); err != nil {
return fmt.Errorf("error mounting ceph root: %v", err)
} }
defer func() { defer func() {

View File

@ -20,6 +20,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"os" "os"
"os/exec"
) )
const ( const (
@ -27,11 +28,74 @@ const (
volumeMounter_kernel = "kernel" volumeMounter_kernel = "kernel"
) )
var (
availableMounters []string
)
// Load available ceph mounters installed on system into availableMounters
// Called from driver.go's Run()
func loadAvailableMounters() error {
fuseMounterProbe := exec.Command("ceph-fuse", "--version")
kernelMounterProbe := exec.Command("mount.ceph")
if fuseMounterProbe.Run() == nil {
availableMounters = append(availableMounters, volumeMounter_fuse)
}
if kernelMounterProbe.Run() == nil {
availableMounters = append(availableMounters, volumeMounter_kernel)
}
if len(availableMounters) == 0 {
return fmt.Errorf("no ceph mounters found on system")
}
return nil
}
type volumeMounter interface { type volumeMounter interface {
mount(mountPoint string, cr *credentials, volOptions *volumeOptions, volId volumeID) error mount(mountPoint string, cr *credentials, volOptions *volumeOptions, volId volumeID) error
name() string name() string
} }
func newMounter(volOptions *volumeOptions) (volumeMounter, error) {
// Get the mounter from the configuration
wantMounter := volOptions.Mounter
if wantMounter == "" {
wantMounter = DefaultVolumeMounter
}
// Verify that it's available
var chosenMounter string
for _, availMounter := range availableMounters {
if chosenMounter == "" {
if availMounter == wantMounter {
chosenMounter = wantMounter
}
}
}
if chosenMounter == "" {
// Otherwise pick whatever is left
chosenMounter = availableMounters[0]
}
// Create the mounter
switch chosenMounter {
case volumeMounter_fuse:
return &fuseMounter{}, nil
case volumeMounter_kernel:
return &kernelMounter{}, nil
}
return nil, fmt.Errorf("unknown mounter '%s'", chosenMounter)
}
type fuseMounter struct{} type fuseMounter struct{}
func mountFuse(mountPoint string, cr *credentials, volOptions *volumeOptions, volId volumeID) error { func mountFuse(mountPoint string, cr *credentials, volOptions *volumeOptions, volId volumeID) error {