From f414a15bebf590811dc17386d530c1918f24b7ee Mon Sep 17 00:00:00 2001 From: Kevin Fox Date: Thu, 28 Feb 2019 14:00:41 -0800 Subject: [PATCH 1/2] Ephemeral support This adds support to the hostPath driver to be used in an ephemeral mode. Signed-off-by: Kevin Fox --- cmd/hostpathplugin/main.go | 3 ++- pkg/hostpath/hostpath.go | 34 +++++++++++++++++++--------------- pkg/hostpath/nodeserver.go | 24 +++++++++++++++++++++--- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/cmd/hostpathplugin/main.go b/cmd/hostpathplugin/main.go index d4f443f79..23467107a 100644 --- a/cmd/hostpathplugin/main.go +++ b/cmd/hostpathplugin/main.go @@ -32,6 +32,7 @@ var ( endpoint = flag.String("endpoint", "unix://tmp/csi.sock", "CSI endpoint") driverName = flag.String("drivername", "csi-hostpath", "name of the driver") nodeID = flag.String("nodeid", "", "node id") + ephemeral = flag.Bool("ephemeral", false, "deploy in ephemeral mode") ) func main() { @@ -42,7 +43,7 @@ func main() { } func handle() { - driver, err := hostpath.NewHostPathDriver(*driverName, *nodeID, *endpoint) + driver, err := hostpath.NewHostPathDriver(*driverName, *nodeID, *endpoint, *ephemeral) if err != nil { fmt.Printf("Failed to initialize driver: %s", err.Error()) os.Exit(1) diff --git a/pkg/hostpath/hostpath.go b/pkg/hostpath/hostpath.go index 299ac4b97..caf28b5ac 100644 --- a/pkg/hostpath/hostpath.go +++ b/pkg/hostpath/hostpath.go @@ -34,10 +34,11 @@ const ( ) type hostPath struct { - name string - nodeID string - version string - endpoint string + name string + nodeID string + version string + endpoint string + ephemeral bool ids *identityServer ns *nodeServer @@ -73,7 +74,7 @@ func init() { hostPathVolumeSnapshots = map[string]hostPathSnapshot{} } -func NewHostPathDriver(driverName, nodeID, endpoint string) (*hostPath, error) { +func NewHostPathDriver(driverName, nodeID, endpoint string, ephemeral bool) (*hostPath, error) { if driverName == "" { return nil, fmt.Errorf("No driver name provided") } @@ -90,21 +91,24 @@ func NewHostPathDriver(driverName, nodeID, endpoint string) (*hostPath, error) { glog.Infof("Version: %s", vendorVersion) return &hostPath{ - name: driverName, - version: vendorVersion, - nodeID: nodeID, - endpoint: endpoint, + name: driverName, + version: vendorVersion, + nodeID: nodeID, + endpoint: endpoint, + ephemeral: ephemeral, }, nil } func (hp *hostPath) Run() { - - // Create GRPC servers - hp.ids = NewIdentityServer(hp.name, hp.version) - hp.ns = NewNodeServer(hp.nodeID) - hp.cs = NewControllerServer() - s := NewNonBlockingGRPCServer() + + hp.ids = nil + hp.cs = nil + hp.ns = NewNodeServer(hp.nodeID, hp.ephemeral) + if !hp.ephemeral { + hp.ids = NewIdentityServer(hp.name, hp.version) + hp.cs = NewControllerServer() + } s.Start(hp.endpoint, hp.ids, hp.cs, hp.ns) s.Wait() } diff --git a/pkg/hostpath/nodeserver.go b/pkg/hostpath/nodeserver.go index fbc8eb978..3094869a1 100644 --- a/pkg/hostpath/nodeserver.go +++ b/pkg/hostpath/nodeserver.go @@ -29,12 +29,14 @@ import ( ) type nodeServer struct { - nodeID string + nodeID string + ephemeral bool } -func NewNodeServer(nodeId string) *nodeServer { +func NewNodeServer(nodeId string, ephemeral bool) *nodeServer { return &nodeServer{ - nodeID: nodeId, + nodeID: nodeId, + ephemeral: ephemeral, } } @@ -89,7 +91,17 @@ func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis } mounter := mount.New("") path := provisionRoot + volumeId + newEphemeral := false + if ns.ephemeral { + if err = os.MkdirAll(path, 0777); err != nil && !os.IsNotExist(err) { + return nil, status.Error(codes.Internal, err.Error()) + } + newEphemeral = true + } if err := mounter.Mount(path, targetPath, "", options); err != nil { + if newEphemeral { + os.RemoveAll(path) + } return nil, err } @@ -115,6 +127,12 @@ func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpu } glog.V(4).Infof("hostpath: volume %s/%s has been unmounted.", targetPath, volumeID) + if ns.ephemeral { + glog.V(4).Infof("deleting volume %s", volumeID) + path := provisionRoot + volumeID + os.RemoveAll(path) + } + return &csi.NodeUnpublishVolumeResponse{}, nil } From 46d99b0d2fbec44289dfbd4f19a118ff4a40263c Mon Sep 17 00:00:00 2001 From: Vladimir Vivien Date: Wed, 13 Mar 2019 11:39:17 -0400 Subject: [PATCH 2/2] Hostpath fixes for ephemeral support (vladimirvivien) Clean up nill pointer execptions Return proper cabilities for ephemeral Properly provision volume/delete volume during node operations Refactor code volume operation code for reuse --- pkg/hostpath/controllerserver.go | 12 +++++----- pkg/hostpath/hostpath.go | 40 +++++++++++++++++++++++++++----- pkg/hostpath/nodeserver.go | 25 +++++++++++++------- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/pkg/hostpath/controllerserver.go b/pkg/hostpath/controllerserver.go index f4c53546f..6b8962cb0 100644 --- a/pkg/hostpath/controllerserver.go +++ b/pkg/hostpath/controllerserver.go @@ -37,7 +37,6 @@ import ( const ( deviceID = "deviceID" - provisionRoot = "/tmp/" snapshotRoot = "/tmp/" maxStorageCapacity = tib ) @@ -46,7 +45,10 @@ type controllerServer struct { caps []*csi.ControllerServiceCapability } -func NewControllerServer() *controllerServer { +func NewControllerServer(ephemeral bool) *controllerServer { + if ephemeral { + return &controllerServer{caps: getControllerServiceCapabilities(nil)} + } return &controllerServer{ caps: getControllerServiceCapabilities( []csi.ControllerServiceCapability_RPC_Type{ @@ -95,8 +97,7 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol return nil, status.Errorf(codes.OutOfRange, "Requested capacity %d exceeds maximum allowed %d", capacity, maxStorageCapacity) } volumeID := uuid.NewUUID().String() - path := provisionRoot + volumeID - err := os.MkdirAll(path, 0777) + path, err := createVolumeDir(volumeID) if err != nil { glog.V(3).Infof("failed to create volume: %v", err) return nil, err @@ -150,8 +151,7 @@ func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol } volumeID := req.VolumeId glog.V(4).Infof("deleting volume %s", volumeID) - path := provisionRoot + volumeID - os.RemoveAll(path) + deleteVolumeDir(volumeID) delete(hostPathVolumes, volumeID) return &csi.DeleteVolumeResponse{}, nil } diff --git a/pkg/hostpath/hostpath.go b/pkg/hostpath/hostpath.go index caf28b5ac..95a2210cc 100644 --- a/pkg/hostpath/hostpath.go +++ b/pkg/hostpath/hostpath.go @@ -18,6 +18,7 @@ package hostpath import ( "fmt" + "os" "github.com/golang/glog" @@ -33,6 +34,10 @@ const ( tib100 int64 = tib * 100 ) +const ( + volumeRoot = "/tmp" +) + type hostPath struct { name string nodeID string @@ -102,13 +107,10 @@ func NewHostPathDriver(driverName, nodeID, endpoint string, ephemeral bool) (*ho func (hp *hostPath) Run() { s := NewNonBlockingGRPCServer() - hp.ids = nil - hp.cs = nil + hp.ids = NewIdentityServer(hp.name, hp.version) hp.ns = NewNodeServer(hp.nodeID, hp.ephemeral) - if !hp.ephemeral { - hp.ids = NewIdentityServer(hp.name, hp.version) - hp.cs = NewControllerServer() - } + hp.cs = NewControllerServer(hp.ephemeral) + s.Start(hp.endpoint, hp.ids, hp.cs, hp.ns) s.Wait() } @@ -137,3 +139,29 @@ func getSnapshotByName(name string) (hostPathSnapshot, error) { } return hostPathSnapshot{}, fmt.Errorf("snapshot name %s does not exit in the snapshots list", name) } + +// getVolumePath returs the canonical path for hostpath volume +func getVolumePath(volID string) string { + return fmt.Sprintf("%s/%s", volumeRoot, volID) +} + +// createVolume create the directory for the hostpath volume. +// It returns the volume path or err if one occurs. +func createVolumeDir(volID string) (string, error) { + path := getVolumePath(volID) + err := os.MkdirAll(path, 0777) + if err != nil { + return "", err + } + + return path, nil +} + +// deleteVolume deletes the directory for the hostpath volume. +func deleteVolumeDir(volID string) error { + path := getVolumePath(volID) + if err := os.RemoveAll(path); err != nil { + return err + } + return nil +} diff --git a/pkg/hostpath/nodeserver.go b/pkg/hostpath/nodeserver.go index 3094869a1..cd7a7cb61 100644 --- a/pkg/hostpath/nodeserver.go +++ b/pkg/hostpath/nodeserver.go @@ -17,7 +17,9 @@ limitations under the License. package hostpath import ( + "fmt" "os" + "strings" "github.com/golang/glog" "golang.org/x/net/context" @@ -90,19 +92,25 @@ func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis options = append(options, "ro") } mounter := mount.New("") - path := provisionRoot + volumeId - newEphemeral := false + + path := getVolumePath(volumeId) if ns.ephemeral { - if err = os.MkdirAll(path, 0777); err != nil && !os.IsNotExist(err) { + volPath, err := createVolumeDir(volumeId) + if err != nil && !os.IsExist(err) { return nil, status.Error(codes.Internal, err.Error()) } - newEphemeral = true + glog.V(4).Infof("ephemeral mode: created volume: %s", volPath) } + if err := mounter.Mount(path, targetPath, "", options); err != nil { - if newEphemeral { - os.RemoveAll(path) + var errList strings.Builder + errList.WriteString(err.Error()) + if ns.ephemeral { + if rmErr := os.RemoveAll(path); rmErr != nil && !os.IsNotExist(rmErr) { + errList.WriteString(fmt.Sprintf(" :%s", rmErr.Error())) + } } - return nil, err + return nil, status.Error(codes.Internal, errList.String()) } return &csi.NodePublishVolumeResponse{}, nil @@ -129,8 +137,7 @@ func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpu if ns.ephemeral { glog.V(4).Infof("deleting volume %s", volumeID) - path := provisionRoot + volumeID - os.RemoveAll(path) + deleteVolumeDir(volumeID) } return &csi.NodeUnpublishVolumeResponse{}, nil