Merge pull request #122 from andyzhangx/createvolume-mountoptions
fix: support mountOptions in CreateVolume
This commit is contained in:
commit
c1d04d8eff
@ -1,28 +0,0 @@
|
|||||||
// +build linux darwin
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright 2020 The Kubernetes Authors.
|
|
||||||
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 mounter
|
|
||||||
|
|
||||||
import (
|
|
||||||
utilexec "k8s.io/utils/exec"
|
|
||||||
"k8s.io/utils/mount"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewSafeMounter() (*mount.SafeFormatAndMount, error) {
|
|
||||||
return &mount.SafeFormatAndMount{
|
|
||||||
Interface: mount.New(""),
|
|
||||||
Exec: utilexec.New(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
@ -29,6 +29,7 @@ import (
|
|||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ControllerServer controller server setting
|
||||||
type ControllerServer struct {
|
type ControllerServer struct {
|
||||||
Driver *Driver
|
Driver *Driver
|
||||||
// Working directory for the provisioner to temporarily mount nfs shares at
|
// Working directory for the provisioner to temporarily mount nfs shares at
|
||||||
@ -65,13 +66,12 @@ const (
|
|||||||
totalIDElements // Always last
|
totalIDElements // Always last
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CreateVolume create a volume
|
||||||
func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
|
func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
|
||||||
// Validate arguments
|
|
||||||
name := req.GetName()
|
name := req.GetName()
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
return nil, status.Error(codes.InvalidArgument, "CreateVolume name must be provided")
|
return nil, status.Error(codes.InvalidArgument, "CreateVolume name must be provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cs.validateVolumeCapabilities(req.GetVolumeCapabilities()); err != nil {
|
if err := cs.validateVolumeCapabilities(req.GetVolumeCapabilities()); err != nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||||
}
|
}
|
||||||
@ -82,8 +82,12 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
|
|||||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var volCap *csi.VolumeCapability
|
||||||
|
if len(req.GetVolumeCapabilities()) > 0 {
|
||||||
|
volCap = req.GetVolumeCapabilities()[0]
|
||||||
|
}
|
||||||
// Mount nfs base share so we can create a subdirectory
|
// Mount nfs base share so we can create a subdirectory
|
||||||
if err = cs.internalMount(ctx, nfsVol); err != nil {
|
if err = cs.internalMount(ctx, nfsVol, volCap); err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "failed to mount nfs server: %v", err.Error())
|
return nil, status.Errorf(codes.Internal, "failed to mount nfs server: %v", err.Error())
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -103,6 +107,7 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
|
|||||||
return &csi.CreateVolumeResponse{Volume: cs.nfsVolToCSI(nfsVol, reqCapacity)}, nil
|
return &csi.CreateVolumeResponse{Volume: cs.nfsVolToCSI(nfsVol, reqCapacity)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteVolume delete a volume
|
||||||
func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
|
func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
|
||||||
volumeID := req.GetVolumeId()
|
volumeID := req.GetVolumeId()
|
||||||
if volumeID == "" {
|
if volumeID == "" {
|
||||||
@ -111,12 +116,12 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
|
|||||||
nfsVol, err := cs.getNfsVolFromID(volumeID)
|
nfsVol, err := cs.getNfsVolFromID(volumeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// An invalid ID should be treated as doesn't exist
|
// An invalid ID should be treated as doesn't exist
|
||||||
glog.V(5).Infof("failed to get nfs volume for volume id %v deletion: %v", volumeID, err)
|
glog.Warningf("failed to get nfs volume for volume id %v deletion: %v", volumeID, err)
|
||||||
return &csi.DeleteVolumeResponse{}, nil
|
return &csi.DeleteVolumeResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount nfs base share so we can delete the subdirectory
|
// Mount nfs base share so we can delete the subdirectory
|
||||||
if err = cs.internalMount(ctx, nfsVol); err != nil {
|
if err = cs.internalMount(ctx, nfsVol, nil); err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "failed to mount nfs server: %v", err.Error())
|
return nil, status.Errorf(codes.Internal, "failed to mount nfs server: %v", err.Error())
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -128,7 +133,7 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
|
|||||||
// Delete subdirectory under base-dir
|
// Delete subdirectory under base-dir
|
||||||
internalVolumePath := cs.getInternalVolumePath(nfsVol)
|
internalVolumePath := cs.getInternalVolumePath(nfsVol)
|
||||||
|
|
||||||
glog.V(4).Infof("Removing subdirectory at %v", internalVolumePath)
|
glog.V(2).Infof("Removing subdirectory at %v", internalVolumePath)
|
||||||
if err = os.RemoveAll(internalVolumePath); err != nil {
|
if err = os.RemoveAll(internalVolumePath); err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "failed to delete subdirectory: %v", err.Error())
|
return nil, status.Errorf(codes.Internal, "failed to delete subdirectory: %v", err.Error())
|
||||||
}
|
}
|
||||||
@ -171,8 +176,6 @@ func (cs *ControllerServer) GetCapacity(ctx context.Context, req *csi.GetCapacit
|
|||||||
// ControllerGetCapabilities implements the default GRPC callout.
|
// ControllerGetCapabilities implements the default GRPC callout.
|
||||||
// Default supports all capabilities
|
// Default supports all capabilities
|
||||||
func (cs *ControllerServer) ControllerGetCapabilities(ctx context.Context, req *csi.ControllerGetCapabilitiesRequest) (*csi.ControllerGetCapabilitiesResponse, error) {
|
func (cs *ControllerServer) ControllerGetCapabilities(ctx context.Context, req *csi.ControllerGetCapabilitiesRequest) (*csi.ControllerGetCapabilitiesResponse, error) {
|
||||||
glog.V(5).Infof("Using default ControllerGetCapabilities")
|
|
||||||
|
|
||||||
return &csi.ControllerGetCapabilitiesResponse{
|
return &csi.ControllerGetCapabilitiesResponse{
|
||||||
Capabilities: cs.Driver.cscap,
|
Capabilities: cs.Driver.cscap,
|
||||||
}, nil
|
}, nil
|
||||||
@ -230,13 +233,16 @@ func (cs *ControllerServer) validateVolumeCapability(c *csi.VolumeCapability) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mount nfs server at base-dir
|
// Mount nfs server at base-dir
|
||||||
func (cs *ControllerServer) internalMount(ctx context.Context, vol *nfsVolume) error {
|
func (cs *ControllerServer) internalMount(ctx context.Context, vol *nfsVolume, volCap *csi.VolumeCapability) error {
|
||||||
sharePath := filepath.Join(string(filepath.Separator) + vol.baseDir)
|
sharePath := filepath.Join(string(filepath.Separator) + vol.baseDir)
|
||||||
targetPath := cs.getInternalMountPath(vol)
|
targetPath := cs.getInternalMountPath(vol)
|
||||||
stdVolCap := csi.VolumeCapability{
|
|
||||||
AccessType: &csi.VolumeCapability_Mount{
|
if volCap == nil {
|
||||||
Mount: &csi.VolumeCapability_MountVolume{},
|
volCap = &csi.VolumeCapability{
|
||||||
},
|
AccessType: &csi.VolumeCapability_Mount{
|
||||||
|
Mount: &csi.VolumeCapability_MountVolume{},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(4).Infof("internally mounting %v:%v at %v", vol.server, sharePath, targetPath)
|
glog.V(4).Infof("internally mounting %v:%v at %v", vol.server, sharePath, targetPath)
|
||||||
@ -246,7 +252,7 @@ func (cs *ControllerServer) internalMount(ctx context.Context, vol *nfsVolume) e
|
|||||||
paramServer: vol.server,
|
paramServer: vol.server,
|
||||||
paramShare: sharePath,
|
paramShare: sharePath,
|
||||||
},
|
},
|
||||||
VolumeCapability: &stdVolCap,
|
VolumeCapability: volCap,
|
||||||
VolumeId: vol.id,
|
VolumeId: vol.id,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -18,11 +18,8 @@ package nfs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kubernetes-csi/csi-driver-nfs/pkg/mounter"
|
|
||||||
|
|
||||||
"k8s.io/utils/mount"
|
"k8s.io/utils/mount"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,9 +61,6 @@ func (f *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeMounter() (*mount.SafeFormatAndMount, error) {
|
func NewFakeMounter() (*mount.SafeFormatAndMount, error) {
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
return mounter.NewSafeMounter()
|
|
||||||
}
|
|
||||||
return &mount.SafeFormatAndMount{
|
return &mount.SafeFormatAndMount{
|
||||||
Interface: &fakeMounter{},
|
Interface: &fakeMounter{},
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@ -21,28 +21,29 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
|
|
||||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||||
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
"k8s.io/utils/mount"
|
"k8s.io/utils/mount"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NodeServer driver
|
||||||
type NodeServer struct {
|
type NodeServer struct {
|
||||||
Driver *Driver
|
Driver *Driver
|
||||||
mounter mount.Interface
|
mounter mount.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodePublishVolume mount the volume
|
||||||
func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
||||||
if req.GetVolumeCapability() == nil {
|
if req.GetVolumeCapability() == nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, "Volume capability missing in request")
|
return nil, status.Error(codes.InvalidArgument, "Volume capability missing in request")
|
||||||
}
|
}
|
||||||
if len(req.GetVolumeId()) == 0 {
|
volumeID := req.GetVolumeId()
|
||||||
|
if len(volumeID) == 0 {
|
||||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||||
}
|
}
|
||||||
|
|
||||||
targetPath := req.GetTargetPath()
|
targetPath := req.GetTargetPath()
|
||||||
if len(targetPath) == 0 {
|
if len(targetPath) == 0 {
|
||||||
return nil, status.Error(codes.InvalidArgument, "Target path not provided")
|
return nil, status.Error(codes.InvalidArgument, "Target path not provided")
|
||||||
@ -59,21 +60,21 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
|||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !notMnt {
|
if !notMnt {
|
||||||
return &csi.NodePublishVolumeResponse{}, nil
|
return &csi.NodePublishVolumeResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mo := req.GetVolumeCapability().GetMount().GetMountFlags()
|
mountOptions := req.GetVolumeCapability().GetMount().GetMountFlags()
|
||||||
if req.GetReadonly() {
|
if req.GetReadonly() {
|
||||||
mo = append(mo, "ro")
|
mountOptions = append(mountOptions, "ro")
|
||||||
}
|
}
|
||||||
|
|
||||||
s := req.GetVolumeContext()[paramServer]
|
s := req.GetVolumeContext()[paramServer]
|
||||||
ep := req.GetVolumeContext()[paramShare]
|
ep := req.GetVolumeContext()[paramShare]
|
||||||
source := fmt.Sprintf("%s:%s", s, ep)
|
source := fmt.Sprintf("%s:%s", s, ep)
|
||||||
|
|
||||||
err = ns.mounter.Mount(source, targetPath, "nfs", mo)
|
glog.V(2).Infof("NodePublishVolume: volumeID(%v) source(%s) targetPath(%s) mountflags(%v)", volumeID, source, targetPath, mountOptions)
|
||||||
|
err = ns.mounter.Mount(source, targetPath, "nfs", mountOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsPermission(err) {
|
if os.IsPermission(err) {
|
||||||
return nil, status.Error(codes.PermissionDenied, err.Error())
|
return nil, status.Error(codes.PermissionDenied, err.Error())
|
||||||
@ -93,14 +94,16 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
|||||||
return &csi.NodePublishVolumeResponse{}, nil
|
return &csi.NodePublishVolumeResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeUnpublishVolume unmount the volume
|
||||||
func (ns *NodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
|
func (ns *NodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
|
||||||
if len(req.GetVolumeId()) == 0 {
|
volumeID := req.GetVolumeId()
|
||||||
|
if len(volumeID) == 0 {
|
||||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||||
}
|
}
|
||||||
if len(req.GetTargetPath()) == 0 {
|
targetPath := req.GetTargetPath()
|
||||||
|
if len(targetPath) == 0 {
|
||||||
return nil, status.Error(codes.InvalidArgument, "Target path missing in request")
|
return nil, status.Error(codes.InvalidArgument, "Target path missing in request")
|
||||||
}
|
}
|
||||||
targetPath := req.GetTargetPath()
|
|
||||||
notMnt, err := ns.mounter.IsLikelyNotMountPoint(targetPath)
|
notMnt, err := ns.mounter.IsLikelyNotMountPoint(targetPath)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -113,7 +116,8 @@ func (ns *NodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpu
|
|||||||
return nil, status.Error(codes.NotFound, "Volume not mounted")
|
return nil, status.Error(codes.NotFound, "Volume not mounted")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mount.CleanupMountPoint(req.GetTargetPath(), ns.mounter, false)
|
glog.V(2).Infof("NodeUnpublishVolume: CleanupMountPoint %s on volumeID(%s)", targetPath, volumeID)
|
||||||
|
err = mount.CleanupMountPoint(targetPath, ns.mounter, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
@ -121,17 +125,15 @@ func (ns *NodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpu
|
|||||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeGetInfo return info of the node on which this plugin is running
|
||||||
func (ns *NodeServer) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRequest) (*csi.NodeGetInfoResponse, error) {
|
func (ns *NodeServer) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRequest) (*csi.NodeGetInfoResponse, error) {
|
||||||
glog.V(5).Infof("Using default NodeGetInfo")
|
|
||||||
|
|
||||||
return &csi.NodeGetInfoResponse{
|
return &csi.NodeGetInfoResponse{
|
||||||
NodeId: ns.Driver.nodeID,
|
NodeId: ns.Driver.nodeID,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeGetCapabilities return the capabilities of the Node plugin
|
||||||
func (ns *NodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) {
|
func (ns *NodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) {
|
||||||
glog.V(5).Infof("Using default NodeGetCapabilities")
|
|
||||||
|
|
||||||
return &csi.NodeGetCapabilitiesResponse{
|
return &csi.NodeGetCapabilitiesResponse{
|
||||||
Capabilities: []*csi.NodeServiceCapability{
|
Capabilities: []*csi.NodeServiceCapability{
|
||||||
{
|
{
|
||||||
@ -145,18 +147,22 @@ func (ns *NodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetC
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeGetVolumeStats get volume stats
|
||||||
func (ns *NodeServer) NodeGetVolumeStats(ctx context.Context, in *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) {
|
func (ns *NodeServer) NodeGetVolumeStats(ctx context.Context, in *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "")
|
return nil, status.Error(codes.Unimplemented, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeUnstageVolume unstage volume
|
||||||
func (ns *NodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
|
func (ns *NodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
|
||||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeStageVolume stage volume
|
||||||
func (ns *NodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
|
func (ns *NodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
|
||||||
return &csi.NodeStageVolumeResponse{}, nil
|
return &csi.NodeStageVolumeResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeExpandVolume node expand volume
|
||||||
func (ns *NodeServer) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) {
|
func (ns *NodeServer) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "")
|
return nil, status.Error(codes.Unimplemented, "")
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user