cleanup: move core functions to core pkg

as we are refractoring the cephfs code,
Moving all the core functions to a new folder
/pkg called core. This will make things easier
to implement. For now onwards all the core
functionalities will be added to the core
package.

Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
Madhu Rajanna 2021-09-16 19:17:57 +05:30 committed by mergify[bot]
parent 64ade1d4c3
commit b1ef842640
15 changed files with 320 additions and 285 deletions

View File

@ -21,7 +21,9 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/ceph/ceph-csi/internal/cephfs/core"
cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors" cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors"
fsutil "github.com/ceph/ceph-csi/internal/cephfs/util"
csicommon "github.com/ceph/ceph-csi/internal/csi-common" csicommon "github.com/ceph/ceph-csi/internal/csi-common"
"github.com/ceph/ceph-csi/internal/util" "github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
@ -53,11 +55,11 @@ type ControllerServer struct {
func (cs *ControllerServer) createBackingVolume( func (cs *ControllerServer) createBackingVolume(
ctx context.Context, ctx context.Context,
volOptions, volOptions,
parentVolOpt *volumeOptions, parentVolOpt *core.VolumeOptions,
vID, vID,
pvID *volumeIdentifier, pvID *core.VolumeIdentifier,
sID *snapshotIdentifier) error { sID *core.SnapshotIdentifier) error {
var err error var err error
if sID != nil { if sID != nil {
if err = cs.OperationLocks.GetRestoreLock(sID.SnapshotID); err != nil { if err = cs.OperationLocks.GetRestoreLock(sID.SnapshotID); err != nil {
@ -67,7 +69,7 @@ func (cs *ControllerServer) createBackingVolume(
} }
defer cs.OperationLocks.ReleaseRestoreLock(sID.SnapshotID) defer cs.OperationLocks.ReleaseRestoreLock(sID.SnapshotID)
err = createCloneFromSnapshot(ctx, parentVolOpt, volOptions, vID, sID) err = core.CreateCloneFromSnapshot(ctx, parentVolOpt, volOptions, vID, sID)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to create clone from snapshot %s: %v", sID.FsSnapshotName, err) log.ErrorLog(ctx, "failed to create clone from snapshot %s: %v", sID.FsSnapshotName, err)
@ -83,14 +85,14 @@ func (cs *ControllerServer) createBackingVolume(
return status.Error(codes.Aborted, err.Error()) return status.Error(codes.Aborted, err.Error())
} }
defer cs.OperationLocks.ReleaseCloneLock(pvID.VolumeID) defer cs.OperationLocks.ReleaseCloneLock(pvID.VolumeID)
err = createCloneFromSubvolume( err = core.CreateCloneFromSubvolume(
ctx, ctx,
volumeID(pvID.FsSubvolName), fsutil.VolumeID(pvID.FsSubvolName),
volumeID(vID.FsSubvolName), fsutil.VolumeID(vID.FsSubvolName),
volOptions, volOptions,
parentVolOpt) parentVolOpt)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to create clone from subvolume %s: %v", volumeID(pvID.FsSubvolName), err) log.ErrorLog(ctx, "failed to create clone from subvolume %s: %v", fsutil.VolumeID(pvID.FsSubvolName), err)
return err return err
} }
@ -98,7 +100,7 @@ func (cs *ControllerServer) createBackingVolume(
return nil return nil
} }
if err = createVolume(ctx, volOptions, volumeID(vID.FsSubvolName), volOptions.Size); err != nil { if err = core.CreateVolume(ctx, volOptions, fsutil.VolumeID(vID.FsSubvolName), volOptions.Size); err != nil {
log.ErrorLog(ctx, "failed to create volume %s: %v", volOptions.RequestName, err) log.ErrorLog(ctx, "failed to create volume %s: %v", volOptions.RequestName, err)
return status.Error(codes.Internal, err.Error()) return status.Error(codes.Internal, err.Error())
@ -110,7 +112,7 @@ func (cs *ControllerServer) createBackingVolume(
func checkContentSource( func checkContentSource(
ctx context.Context, ctx context.Context,
req *csi.CreateVolumeRequest, req *csi.CreateVolumeRequest,
cr *util.Credentials) (*volumeOptions, *volumeIdentifier, *snapshotIdentifier, error) { cr *util.Credentials) (*core.VolumeOptions, *core.VolumeIdentifier, *core.SnapshotIdentifier, error) {
if req.VolumeContentSource == nil { if req.VolumeContentSource == nil {
return nil, nil, nil, nil return nil, nil, nil, nil
} }
@ -118,7 +120,7 @@ func checkContentSource(
switch volumeSource.Type.(type) { switch volumeSource.Type.(type) {
case *csi.VolumeContentSource_Snapshot: case *csi.VolumeContentSource_Snapshot:
snapshotID := req.VolumeContentSource.GetSnapshot().GetSnapshotId() snapshotID := req.VolumeContentSource.GetSnapshot().GetSnapshotId()
volOpt, _, sid, err := newSnapshotOptionsFromID(ctx, snapshotID, cr) volOpt, _, sid, err := core.NewSnapshotOptionsFromID(ctx, snapshotID, cr)
if err != nil { if err != nil {
if errors.Is(err, cerrors.ErrSnapNotFound) { if errors.Is(err, cerrors.ErrSnapNotFound) {
return nil, nil, nil, status.Error(codes.NotFound, err.Error()) return nil, nil, nil, status.Error(codes.NotFound, err.Error())
@ -131,7 +133,7 @@ func checkContentSource(
case *csi.VolumeContentSource_Volume: case *csi.VolumeContentSource_Volume:
// Find the volume using the provided VolumeID // Find the volume using the provided VolumeID
volID := req.VolumeContentSource.GetVolume().GetVolumeId() volID := req.VolumeContentSource.GetVolume().GetVolumeId()
parentVol, pvID, err := newVolumeOptionsFromVolID(ctx, volID, nil, req.Secrets) parentVol, pvID, err := core.NewVolumeOptionsFromVolID(ctx, volID, nil, req.Secrets)
if err != nil { if err != nil {
if !errors.Is(err, cerrors.ErrVolumeNotFound) { if !errors.Is(err, cerrors.ErrVolumeNotFound) {
return nil, nil, nil, status.Error(codes.NotFound, err.Error()) return nil, nil, nil, status.Error(codes.NotFound, err.Error())
@ -177,7 +179,7 @@ func (cs *ControllerServer) CreateVolume(
} }
defer cs.VolumeLocks.Release(requestName) defer cs.VolumeLocks.Release(requestName)
volOptions, err := newVolumeOptions(ctx, requestName, req, cr) volOptions, err := core.NewVolumeOptions(ctx, requestName, req, cr)
if err != nil { if err != nil {
log.ErrorLog(ctx, "validation and extraction of volume options failed: %v", err) log.ErrorLog(ctx, "validation and extraction of volume options failed: %v", err)
@ -197,9 +199,9 @@ func (cs *ControllerServer) CreateVolume(
defer parentVol.Destroy() defer parentVol.Destroy()
} }
vID, err := checkVolExists(ctx, volOptions, parentVol, pvID, sID, cr) vID, err := core.CheckVolExists(ctx, volOptions, parentVol, pvID, sID, cr)
if err != nil { if err != nil {
if isCloneRetryError(err) { if cerrors.IsCloneRetryError(err) {
return nil, status.Error(codes.Aborted, err.Error()) return nil, status.Error(codes.Aborted, err.Error())
} }
@ -230,15 +232,15 @@ func (cs *ControllerServer) CreateVolume(
} }
// Reservation // Reservation
vID, err = reserveVol(ctx, volOptions, secret) vID, err = core.ReserveVol(ctx, volOptions, secret)
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
defer func() { defer func() {
if err != nil { if err != nil {
if !isCloneRetryError(err) { if !cerrors.IsCloneRetryError(err) {
errDefer := undoVolReservation(ctx, volOptions, *vID, secret) errDefer := core.UndoVolReservation(ctx, volOptions, *vID, secret)
if errDefer != nil { if errDefer != nil {
log.WarningLog(ctx, "failed undoing reservation of volume: %s (%s)", log.WarningLog(ctx, "failed undoing reservation of volume: %s (%s)",
requestName, errDefer) requestName, errDefer)
@ -250,16 +252,16 @@ func (cs *ControllerServer) CreateVolume(
// Create a volume // Create a volume
err = cs.createBackingVolume(ctx, volOptions, parentVol, vID, pvID, sID) err = cs.createBackingVolume(ctx, volOptions, parentVol, vID, pvID, sID)
if err != nil { if err != nil {
if isCloneRetryError(err) { if cerrors.IsCloneRetryError(err) {
return nil, status.Error(codes.Aborted, err.Error()) return nil, status.Error(codes.Aborted, err.Error())
} }
return nil, err return nil, err
} }
volOptions.RootPath, err = volOptions.getVolumeRootPathCeph(ctx, volumeID(vID.FsSubvolName)) volOptions.RootPath, err = volOptions.GetVolumeRootPathCeph(ctx, fsutil.VolumeID(vID.FsSubvolName))
if err != nil { if err != nil {
purgeErr := volOptions.purgeVolume(ctx, volumeID(vID.FsSubvolName), true) purgeErr := volOptions.PurgeVolume(ctx, fsutil.VolumeID(vID.FsSubvolName), true)
if purgeErr != nil { if purgeErr != nil {
log.ErrorLog(ctx, "failed to delete volume %s: %v", vID.FsSubvolName, purgeErr) log.ErrorLog(ctx, "failed to delete volume %s: %v", vID.FsSubvolName, purgeErr)
// All errors other than ErrVolumeNotFound should return an error back to the caller // All errors other than ErrVolumeNotFound should return an error back to the caller
@ -311,7 +313,7 @@ func (cs *ControllerServer) DeleteVolume(
return nil, err return nil, err
} }
volID := volumeID(req.GetVolumeId()) volID := fsutil.VolumeID(req.GetVolumeId())
secrets := req.GetSecrets() secrets := req.GetSecrets()
// lock out parallel delete operations // lock out parallel delete operations
@ -331,7 +333,7 @@ func (cs *ControllerServer) DeleteVolume(
defer cs.OperationLocks.ReleaseDeleteLock(req.GetVolumeId()) defer cs.OperationLocks.ReleaseDeleteLock(req.GetVolumeId())
// Find the volume using the provided VolumeID // Find the volume using the provided VolumeID
volOptions, vID, err := newVolumeOptionsFromVolID(ctx, string(volID), nil, secrets) volOptions, vID, err := core.NewVolumeOptionsFromVolID(ctx, string(volID), nil, secrets)
if err != nil { if err != nil {
// if error is ErrPoolNotFound, the pool is already deleted we dont // if error is ErrPoolNotFound, the pool is already deleted we dont
// need to worry about deleting subvolume or omap data, return success // need to worry about deleting subvolume or omap data, return success
@ -362,7 +364,7 @@ func (cs *ControllerServer) DeleteVolume(
} }
defer cs.VolumeLocks.Release(volOptions.RequestName) defer cs.VolumeLocks.Release(volOptions.RequestName)
if err = undoVolReservation(ctx, volOptions, *vID, secrets); err != nil { if err = core.UndoVolReservation(ctx, volOptions, *vID, secrets); err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -386,7 +388,7 @@ func (cs *ControllerServer) DeleteVolume(
} }
defer cr.DeleteCredentials() defer cr.DeleteCredentials()
if err = volOptions.purgeVolume(ctx, volumeID(vID.FsSubvolName), false); err != nil { if err = volOptions.PurgeVolume(ctx, fsutil.VolumeID(vID.FsSubvolName), false); err != nil {
log.ErrorLog(ctx, "failed to delete volume %s: %v", volID, err) log.ErrorLog(ctx, "failed to delete volume %s: %v", volID, err)
if errors.Is(err, cerrors.ErrVolumeHasSnapshots) { if errors.Is(err, cerrors.ErrVolumeHasSnapshots) {
return nil, status.Error(codes.FailedPrecondition, err.Error()) return nil, status.Error(codes.FailedPrecondition, err.Error())
@ -397,7 +399,7 @@ func (cs *ControllerServer) DeleteVolume(
} }
} }
if err := undoVolReservation(ctx, volOptions, *vID, secrets); err != nil { if err := core.UndoVolReservation(ctx, volOptions, *vID, secrets); err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -460,7 +462,7 @@ func (cs *ControllerServer) ControllerExpandVolume(
} }
defer cr.DeleteCredentials() defer cr.DeleteCredentials()
volOptions, volIdentifier, err := newVolumeOptionsFromVolID(ctx, volID, nil, secret) volOptions, volIdentifier, err := core.NewVolumeOptionsFromVolID(ctx, volID, nil, secret)
if err != nil { if err != nil {
log.ErrorLog(ctx, "validation and extraction of volume options failed: %v", err) log.ErrorLog(ctx, "validation and extraction of volume options failed: %v", err)
@ -470,8 +472,8 @@ func (cs *ControllerServer) ControllerExpandVolume(
RoundOffSize := util.RoundOffBytes(req.GetCapacityRange().GetRequiredBytes()) RoundOffSize := util.RoundOffBytes(req.GetCapacityRange().GetRequiredBytes())
if err = volOptions.resizeVolume(ctx, volumeID(volIdentifier.FsSubvolName), RoundOffSize); err != nil { if err = volOptions.ResizeVolume(ctx, fsutil.VolumeID(volIdentifier.FsSubvolName), RoundOffSize); err != nil {
log.ErrorLog(ctx, "failed to expand volume %s: %v", volumeID(volIdentifier.FsSubvolName), err) log.ErrorLog(ctx, "failed to expand volume %s: %v", fsutil.VolumeID(volIdentifier.FsSubvolName), err)
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -497,7 +499,7 @@ func (cs *ControllerServer) CreateSnapshot(
} }
defer cr.DeleteCredentials() defer cr.DeleteCredentials()
clusterData, err := getClusterInformation(req.GetParameters()) clusterData, err := core.GetClusterInformation(req.GetParameters())
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -521,7 +523,7 @@ func (cs *ControllerServer) CreateSnapshot(
defer cs.OperationLocks.ReleaseSnapshotCreateLock(sourceVolID) defer cs.OperationLocks.ReleaseSnapshotCreateLock(sourceVolID)
// Find the volume using the provided VolumeID // Find the volume using the provided VolumeID
parentVolOptions, vid, err := newVolumeOptionsFromVolID(ctx, sourceVolID, nil, req.GetSecrets()) parentVolOptions, vid, err := core.NewVolumeOptionsFromVolID(ctx, sourceVolID, nil, req.GetSecrets())
if err != nil { if err != nil {
if errors.Is(err, util.ErrPoolNotFound) { if errors.Is(err, util.ErrPoolNotFound) {
log.WarningLog(ctx, "failed to get backend volume for %s: %v", sourceVolID, err) log.WarningLog(ctx, "failed to get backend volume for %s: %v", sourceVolID, err)
@ -545,7 +547,7 @@ func (cs *ControllerServer) CreateSnapshot(
parentVolOptions.ClusterID) parentVolOptions.ClusterID)
} }
cephfsSnap, genSnapErr := genSnapFromOptions(ctx, req) cephfsSnap, genSnapErr := core.GenSnapFromOptions(ctx, req)
if genSnapErr != nil { if genSnapErr != nil {
return nil, status.Error(codes.Internal, genSnapErr.Error()) return nil, status.Error(codes.Internal, genSnapErr.Error())
} }
@ -558,7 +560,7 @@ func (cs *ControllerServer) CreateSnapshot(
} }
defer cs.VolumeLocks.Release(sourceVolID) defer cs.VolumeLocks.Release(sourceVolID)
snapName := req.GetName() snapName := req.GetName()
sid, snapInfo, err := checkSnapExists(ctx, parentVolOptions, vid.FsSubvolName, cephfsSnap, cr) sid, snapInfo, err := core.CheckSnapExists(ctx, parentVolOptions, vid.FsSubvolName, cephfsSnap, cr)
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -568,18 +570,18 @@ func (cs *ControllerServer) CreateSnapshot(
// as we are not able to retrieve the parent size we are rejecting the // as we are not able to retrieve the parent size we are rejecting the
// request to create snapshot. // request to create snapshot.
// TODO: For this purpose we could make use of cached clusterAdditionalInfo too. // TODO: For this purpose we could make use of cached clusterAdditionalInfo too.
info, err := parentVolOptions.getSubVolumeInfo(ctx, volumeID(vid.FsSubvolName)) info, err := parentVolOptions.GetSubVolumeInfo(ctx, fsutil.VolumeID(vid.FsSubvolName))
if err != nil { if err != nil {
// Check error code value against ErrInvalidCommand to understand the cluster // Check error code value against ErrInvalidCommand to understand the cluster
// support it or not, It's safe to evaluate as the filtering // support it or not, It's safe to evaluate as the filtering
// is already done from getSubVolumeInfo() and send out the error here. // is already done from GetSubVolumeInfo() and send out the error here.
if errors.Is(err, cerrors.ErrInvalidCommand) { if errors.Is(err, cerrors.ErrInvalidCommand) {
return nil, status.Error( return nil, status.Error(
codes.FailedPrecondition, codes.FailedPrecondition,
"subvolume info command not supported in current ceph cluster") "subvolume info command not supported in current ceph cluster")
} }
if sid != nil { if sid != nil {
errDefer := undoSnapReservation(ctx, parentVolOptions, *sid, snapName, cr) errDefer := core.UndoSnapReservation(ctx, parentVolOptions, *sid, snapName, cr)
if errDefer != nil { if errDefer != nil {
log.WarningLog(ctx, "failed undoing reservation of snapshot: %s (%s)", log.WarningLog(ctx, "failed undoing reservation of snapshot: %s (%s)",
requestName, errDefer) requestName, errDefer)
@ -592,8 +594,8 @@ func (cs *ControllerServer) CreateSnapshot(
if sid != nil { if sid != nil {
// check snapshot is protected // check snapshot is protected
protected := true protected := true
if !(snapInfo.Protected == snapshotIsProtected) { if !(snapInfo.Protected == core.SnapshotIsProtected) {
err = parentVolOptions.protectSnapshot(ctx, volumeID(sid.FsSnapshotName), volumeID(vid.FsSubvolName)) err = parentVolOptions.ProtectSnapshot(ctx, fsutil.VolumeID(sid.FsSnapshotName), fsutil.VolumeID(vid.FsSubvolName))
if err != nil { if err != nil {
protected = false protected = false
log.WarningLog(ctx, "failed to protect snapshot of snapshot: %s (%s)", log.WarningLog(ctx, "failed to protect snapshot of snapshot: %s (%s)",
@ -613,13 +615,13 @@ func (cs *ControllerServer) CreateSnapshot(
} }
// Reservation // Reservation
sID, err := reserveSnap(ctx, parentVolOptions, vid.FsSubvolName, cephfsSnap, cr) sID, err := core.ReserveSnap(ctx, parentVolOptions, vid.FsSubvolName, cephfsSnap, cr)
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
defer func() { defer func() {
if err != nil { if err != nil {
errDefer := undoSnapReservation(ctx, parentVolOptions, *sID, snapName, cr) errDefer := core.UndoSnapReservation(ctx, parentVolOptions, *sID, snapName, cr)
if errDefer != nil { if errDefer != nil {
log.WarningLog(ctx, "failed undoing reservation of snapshot: %s (%s)", log.WarningLog(ctx, "failed undoing reservation of snapshot: %s (%s)",
requestName, errDefer) requestName, errDefer)
@ -642,11 +644,15 @@ func (cs *ControllerServer) CreateSnapshot(
}, nil }, nil
} }
func doSnapshot(ctx context.Context, volOpt *volumeOptions, subvolumeName, snapshotName string) (snapshotInfo, error) { func doSnapshot(
volID := volumeID(subvolumeName) ctx context.Context,
snapID := volumeID(snapshotName) volOpt *core.VolumeOptions,
snap := snapshotInfo{} subvolumeName,
err := volOpt.createSnapshot(ctx, snapID, volID) snapshotName string) (core.SnapshotInfo, error) {
volID := fsutil.VolumeID(subvolumeName)
snapID := fsutil.VolumeID(snapshotName)
snap := core.SnapshotInfo{}
err := volOpt.CreateSnapshot(ctx, snapID, volID)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to create snapshot %s %v", snapID, err) log.ErrorLog(ctx, "failed to create snapshot %s %v", snapID, err)
@ -654,25 +660,25 @@ func doSnapshot(ctx context.Context, volOpt *volumeOptions, subvolumeName, snaps
} }
defer func() { defer func() {
if err != nil { if err != nil {
dErr := volOpt.deleteSnapshot(ctx, snapID, volID) dErr := volOpt.DeleteSnapshot(ctx, snapID, volID)
if dErr != nil { if dErr != nil {
log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapID, err) log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapID, err)
} }
} }
}() }()
snap, err = volOpt.getSnapshotInfo(ctx, snapID, volID) snap, err = volOpt.GetSnapshotInfo(ctx, snapID, volID)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to get snapshot info %s %v", snapID, err) log.ErrorLog(ctx, "failed to get snapshot info %s %v", snapID, err)
return snap, fmt.Errorf("failed to get snapshot info for snapshot:%s", snapID) return snap, fmt.Errorf("failed to get snapshot info for snapshot:%s", snapID)
} }
var t *timestamp.Timestamp var t *timestamp.Timestamp
t, err = parseTime(ctx, snap.CreatedAt) t, err = fsutil.ParseTime(ctx, snap.CreatedAt)
if err != nil { if err != nil {
return snap, err return snap, err
} }
snap.CreationTime = t snap.CreationTime = t
err = volOpt.protectSnapshot(ctx, snapID, volID) err = volOpt.ProtectSnapshot(ctx, snapID, volID)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to protect snapshot %s %v", snapID, err) log.ErrorLog(ctx, "failed to protect snapshot %s %v", snapID, err)
} }
@ -736,7 +742,7 @@ func (cs *ControllerServer) DeleteSnapshot(
} }
defer cs.OperationLocks.ReleaseDeleteLock(snapshotID) defer cs.OperationLocks.ReleaseDeleteLock(snapshotID)
volOpt, snapInfo, sid, err := newSnapshotOptionsFromID(ctx, snapshotID, cr) volOpt, snapInfo, sid, err := core.NewSnapshotOptionsFromID(ctx, snapshotID, cr)
if err != nil { if err != nil {
switch { switch {
case errors.Is(err, util.ErrPoolNotFound): case errors.Is(err, util.ErrPoolNotFound):
@ -751,7 +757,7 @@ func (cs *ControllerServer) DeleteSnapshot(
// success as deletion is complete // success as deletion is complete
return &csi.DeleteSnapshotResponse{}, nil return &csi.DeleteSnapshotResponse{}, nil
case errors.Is(err, cerrors.ErrSnapNotFound): case errors.Is(err, cerrors.ErrSnapNotFound):
err = undoSnapReservation(ctx, volOpt, *sid, sid.FsSnapshotName, cr) err = core.UndoSnapReservation(ctx, volOpt, *sid, sid.FsSnapshotName, cr)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) (%s)", log.ErrorLog(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) (%s)",
sid.FsSubvolName, sid.FsSnapshotName, err) sid.FsSubvolName, sid.FsSnapshotName, err)
@ -764,7 +770,7 @@ func (cs *ControllerServer) DeleteSnapshot(
// if the error is ErrVolumeNotFound, the subvolume is already deleted // if the error is ErrVolumeNotFound, the subvolume is already deleted
// from backend, Hence undo the omap entries and return success // from backend, Hence undo the omap entries and return success
log.ErrorLog(ctx, "Volume not present") log.ErrorLog(ctx, "Volume not present")
err = undoSnapReservation(ctx, volOpt, *sid, sid.FsSnapshotName, cr) err = core.UndoSnapReservation(ctx, volOpt, *sid, sid.FsSnapshotName, cr)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) (%s)", log.ErrorLog(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) (%s)",
sid.FsSubvolName, sid.FsSnapshotName, err) sid.FsSubvolName, sid.FsSnapshotName, err)
@ -791,17 +797,17 @@ func (cs *ControllerServer) DeleteSnapshot(
if snapInfo.HasPendingClones == "yes" { if snapInfo.HasPendingClones == "yes" {
return nil, status.Errorf(codes.FailedPrecondition, "snapshot %s has pending clones", snapshotID) return nil, status.Errorf(codes.FailedPrecondition, "snapshot %s has pending clones", snapshotID)
} }
if snapInfo.Protected == snapshotIsProtected { if snapInfo.Protected == core.SnapshotIsProtected {
err = volOpt.unprotectSnapshot(ctx, volumeID(sid.FsSnapshotName), volumeID(sid.FsSubvolName)) err = volOpt.UnprotectSnapshot(ctx, fsutil.VolumeID(sid.FsSnapshotName), fsutil.VolumeID(sid.FsSubvolName))
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
} }
err = volOpt.deleteSnapshot(ctx, volumeID(sid.FsSnapshotName), volumeID(sid.FsSubvolName)) err = volOpt.DeleteSnapshot(ctx, fsutil.VolumeID(sid.FsSnapshotName), fsutil.VolumeID(sid.FsSubvolName))
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
err = undoSnapReservation(ctx, volOpt, *sid, sid.FsSnapshotName, cr) err = core.UndoSnapReservation(ctx, volOpt, *sid, sid.FsSnapshotName, cr)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) (%s)", log.ErrorLog(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) (%s)",
sid.RequestName, sid.FsSnapshotName, err) sid.RequestName, sid.FsSnapshotName, err)

View File

@ -14,13 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package core
import ( import (
"context" "context"
"errors" "errors"
cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors" cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors"
fsutil "github.com/ceph/ceph-csi/internal/cephfs/util"
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
) )
@ -39,8 +40,8 @@ const (
// cephFSCloneComplete indicates that clone is in complete state. // cephFSCloneComplete indicates that clone is in complete state.
cephFSCloneComplete = cephFSCloneState("complete") cephFSCloneComplete = cephFSCloneState("complete")
// snapshotIsProtected string indicates that the snapshot is currently protected. // SnapshotIsProtected string indicates that the snapshot is currently protected.
snapshotIsProtected = "yes" SnapshotIsProtected = "yes"
) )
// toError checks the state of the clone if it's not cephFSCloneComplete. // toError checks the state of the clone if it's not cephFSCloneComplete.
@ -61,9 +62,13 @@ func (cs cephFSCloneState) toError() error {
return nil return nil
} }
func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volOpt, parentvolOpt *volumeOptions) error { func CreateCloneFromSubvolume(
ctx context.Context,
volID, cloneID fsutil.VolumeID,
volOpt,
parentvolOpt *VolumeOptions) error {
snapshotID := cloneID snapshotID := cloneID
err := parentvolOpt.createSnapshot(ctx, snapshotID, volID) err := parentvolOpt.CreateSnapshot(ctx, snapshotID, volID)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to create snapshot %s %v", snapshotID, err) log.ErrorLog(ctx, "failed to create snapshot %s %v", snapshotID, err)
@ -77,17 +82,17 @@ func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volO
) )
defer func() { defer func() {
if protectErr != nil { if protectErr != nil {
err = parentvolOpt.deleteSnapshot(ctx, snapshotID, volID) err = parentvolOpt.DeleteSnapshot(ctx, snapshotID, volID)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapshotID, err) log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapshotID, err)
} }
} }
if cloneErr != nil { if cloneErr != nil {
if err = volOpt.purgeVolume(ctx, cloneID, true); err != nil { if err = volOpt.PurgeVolume(ctx, cloneID, true); err != nil {
log.ErrorLog(ctx, "failed to delete volume %s: %v", cloneID, err) log.ErrorLog(ctx, "failed to delete volume %s: %v", cloneID, err)
} }
if err = parentvolOpt.unprotectSnapshot(ctx, snapshotID, volID); err != nil { if err = parentvolOpt.UnprotectSnapshot(ctx, snapshotID, volID); err != nil {
// In case the snap is already unprotected we get ErrSnapProtectionExist error code // In case the snap is already unprotected we get ErrSnapProtectionExist error code
// in that case we are safe and we could discard this error and we are good to go // in that case we are safe and we could discard this error and we are good to go
// ahead with deletion // ahead with deletion
@ -95,12 +100,12 @@ func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volO
log.ErrorLog(ctx, "failed to unprotect snapshot %s %v", snapshotID, err) log.ErrorLog(ctx, "failed to unprotect snapshot %s %v", snapshotID, err)
} }
} }
if err = parentvolOpt.deleteSnapshot(ctx, snapshotID, volID); err != nil { if err = parentvolOpt.DeleteSnapshot(ctx, snapshotID, volID); err != nil {
log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapshotID, err) log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapshotID, err)
} }
} }
}() }()
protectErr = parentvolOpt.protectSnapshot(ctx, snapshotID, volID) protectErr = parentvolOpt.ProtectSnapshot(ctx, snapshotID, volID)
if protectErr != nil { if protectErr != nil {
log.ErrorLog(ctx, "failed to protect snapshot %s %v", snapshotID, protectErr) log.ErrorLog(ctx, "failed to protect snapshot %s %v", snapshotID, protectErr)
@ -127,14 +132,14 @@ func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volO
return cloneState.toError() return cloneState.toError()
} }
// This is a work around to fix sizing issue for cloned images // This is a work around to fix sizing issue for cloned images
err = volOpt.resizeVolume(ctx, cloneID, volOpt.Size) err = volOpt.ResizeVolume(ctx, cloneID, volOpt.Size)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to expand volume %s: %v", cloneID, err) log.ErrorLog(ctx, "failed to expand volume %s: %v", cloneID, err)
return err return err
} }
// As we completed clone, remove the intermediate snap // As we completed clone, remove the intermediate snap
if err = parentvolOpt.unprotectSnapshot(ctx, snapshotID, volID); err != nil { if err = parentvolOpt.UnprotectSnapshot(ctx, snapshotID, volID); err != nil {
// In case the snap is already unprotected we get ErrSnapProtectionExist error code // In case the snap is already unprotected we get ErrSnapProtectionExist error code
// in that case we are safe and we could discard this error and we are good to go // in that case we are safe and we could discard this error and we are good to go
// ahead with deletion // ahead with deletion
@ -144,7 +149,7 @@ func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volO
return err return err
} }
} }
if err = parentvolOpt.deleteSnapshot(ctx, snapshotID, volID); err != nil { if err = parentvolOpt.DeleteSnapshot(ctx, snapshotID, volID); err != nil {
log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapshotID, err) log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapshotID, err)
return err return err
@ -155,12 +160,12 @@ func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volO
func cleanupCloneFromSubvolumeSnapshot( func cleanupCloneFromSubvolumeSnapshot(
ctx context.Context, ctx context.Context,
volID, cloneID volumeID, volID, cloneID fsutil.VolumeID,
parentVolOpt *volumeOptions) error { parentVolOpt *VolumeOptions) error {
// snapshot name is same as clone name as we need a name which can be // snapshot name is same as clone name as we need a name which can be
// identified during PVC-PVC cloning. // identified during PVC-PVC cloning.
snapShotID := cloneID snapShotID := cloneID
snapInfo, err := parentVolOpt.getSnapshotInfo(ctx, snapShotID, volID) snapInfo, err := parentVolOpt.GetSnapshotInfo(ctx, snapShotID, volID)
if err != nil { if err != nil {
if errors.Is(err, cerrors.ErrSnapNotFound) { if errors.Is(err, cerrors.ErrSnapNotFound) {
return nil return nil
@ -169,15 +174,15 @@ func cleanupCloneFromSubvolumeSnapshot(
return err return err
} }
if snapInfo.Protected == snapshotIsProtected { if snapInfo.Protected == SnapshotIsProtected {
err = parentVolOpt.unprotectSnapshot(ctx, snapShotID, volID) err = parentVolOpt.UnprotectSnapshot(ctx, snapShotID, volID)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to unprotect snapshot %s %v", snapShotID, err) log.ErrorLog(ctx, "failed to unprotect snapshot %s %v", snapShotID, err)
return err return err
} }
} }
err = parentVolOpt.deleteSnapshot(ctx, snapShotID, volID) err = parentVolOpt.DeleteSnapshot(ctx, snapShotID, volID)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapShotID, err) log.ErrorLog(ctx, "failed to delete snapshot %s %v", snapShotID, err)
@ -187,33 +192,32 @@ func cleanupCloneFromSubvolumeSnapshot(
return nil return nil
} }
// isCloneRetryError returns true if the clone error is pending,in-progress func CreateCloneFromSnapshot(
// error.
func isCloneRetryError(err error) bool {
return errors.Is(err, cerrors.ErrCloneInProgress) || errors.Is(err, cerrors.ErrClonePending)
}
func createCloneFromSnapshot(
ctx context.Context, ctx context.Context,
parentVolOpt, volOptions *volumeOptions, parentVolOpt, volOptions *VolumeOptions,
vID *volumeIdentifier, vID *VolumeIdentifier,
sID *snapshotIdentifier) error { sID *SnapshotIdentifier) error {
snapID := volumeID(sID.FsSnapshotName) snapID := fsutil.VolumeID(sID.FsSnapshotName)
err := parentVolOpt.cloneSnapshot(ctx, volumeID(sID.FsSubvolName), snapID, volumeID(vID.FsSubvolName), volOptions) err := parentVolOpt.cloneSnapshot(
ctx,
fsutil.VolumeID(sID.FsSubvolName),
snapID,
fsutil.VolumeID(vID.FsSubvolName),
volOptions)
if err != nil { if err != nil {
return err return err
} }
defer func() { defer func() {
if err != nil { if err != nil {
if !isCloneRetryError(err) { if !cerrors.IsCloneRetryError(err) {
if dErr := volOptions.purgeVolume(ctx, volumeID(vID.FsSubvolName), true); dErr != nil { if dErr := volOptions.PurgeVolume(ctx, fsutil.VolumeID(vID.FsSubvolName), true); dErr != nil {
log.ErrorLog(ctx, "failed to delete volume %s: %v", vID.FsSubvolName, dErr) log.ErrorLog(ctx, "failed to delete volume %s: %v", vID.FsSubvolName, dErr)
} }
} }
} }
}() }()
cloneState, err := volOptions.getCloneState(ctx, volumeID(vID.FsSubvolName)) cloneState, err := volOptions.getCloneState(ctx, fsutil.VolumeID(vID.FsSubvolName))
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to get clone state: %v", err) log.ErrorLog(ctx, "failed to get clone state: %v", err)
@ -226,7 +230,7 @@ func createCloneFromSnapshot(
// The clonedvolume currently does not reflect the proper size due to an issue in cephfs // The clonedvolume currently does not reflect the proper size due to an issue in cephfs
// however this is getting addressed in cephfs and the parentvolume size will be reflected // however this is getting addressed in cephfs and the parentvolume size will be reflected
// in the new cloned volume too. Till then we are explicitly making the size set // in the new cloned volume too. Till then we are explicitly making the size set
err = volOptions.resizeVolume(ctx, volumeID(vID.FsSubvolName), volOptions.Size) err = volOptions.ResizeVolume(ctx, fsutil.VolumeID(vID.FsSubvolName), volOptions.Size)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to expand volume %s with error: %v", vID.FsSubvolName, err) log.ErrorLog(ctx, "failed to expand volume %s with error: %v", vID.FsSubvolName, err)
@ -236,7 +240,7 @@ func createCloneFromSnapshot(
return nil return nil
} }
func (vo *volumeOptions) getCloneState(ctx context.Context, volID volumeID) (cephFSCloneState, error) { func (vo *VolumeOptions) getCloneState(ctx context.Context, volID fsutil.VolumeID) (cephFSCloneState, error) {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog( log.ErrorLog(

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package core
import ( import (
"testing" "testing"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package core
import ( import (
"context" "context"
@ -25,7 +25,7 @@ import (
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
) )
func (vo *volumeOptions) getFscID(ctx context.Context) (int64, error) { func (vo *VolumeOptions) getFscID(ctx context.Context) (int64, error) {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin, can not fetch filesystem ID for %s:", vo.FsName, err) log.ErrorLog(ctx, "could not get FSAdmin, can not fetch filesystem ID for %s:", vo.FsName, err)
@ -51,7 +51,7 @@ func (vo *volumeOptions) getFscID(ctx context.Context) (int64, error) {
return 0, cerrors.ErrVolumeNotFound return 0, cerrors.ErrVolumeNotFound
} }
func (vo *volumeOptions) getMetadataPool(ctx context.Context) (string, error) { func (vo *VolumeOptions) getMetadataPool(ctx context.Context) (string, error) {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin, can not fetch metadata pool for %s:", vo.FsName, err) log.ErrorLog(ctx, "could not get FSAdmin, can not fetch metadata pool for %s:", vo.FsName, err)
@ -75,7 +75,7 @@ func (vo *volumeOptions) getMetadataPool(ctx context.Context) (string, error) {
return "", fmt.Errorf("%w: could not find metadata pool for %s", util.ErrPoolNotFound, vo.FsName) return "", fmt.Errorf("%w: could not find metadata pool for %s", util.ErrPoolNotFound, vo.FsName)
} }
func (vo *volumeOptions) getFsName(ctx context.Context) (string, error) { func (vo *VolumeOptions) getFsName(ctx context.Context) (string, error) {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin, can not fetch filesystem name for ID %d:", vo.FscID, err) log.ErrorLog(ctx, "could not get FSAdmin, can not fetch filesystem name for ID %d:", vo.FscID, err)

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package core
import ( import (
"context" "context"
@ -22,20 +22,32 @@ import (
"fmt" "fmt"
cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors" cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors"
fsutil "github.com/ceph/ceph-csi/internal/cephfs/util"
"github.com/ceph/ceph-csi/internal/journal"
"github.com/ceph/ceph-csi/internal/util" "github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
"github.com/golang/protobuf/ptypes/timestamp" "github.com/golang/protobuf/ptypes/timestamp"
) )
// volumeIdentifier structure contains an association between the CSI VolumeID to its subvolume var (
// VolJournal is used to maintain RADOS based journals for CO generated.
// VolumeName to backing CephFS subvolumes.
VolJournal *journal.Config
// SnapJournal is used to maintain RADOS based journals for CO generated.
// SnapshotName to backing CephFS subvolumes.
SnapJournal *journal.Config
)
// VolumeIdentifier structure contains an association between the CSI VolumeID to its subvolume
// name on the backing CephFS instance. // name on the backing CephFS instance.
type volumeIdentifier struct { type VolumeIdentifier struct {
FsSubvolName string FsSubvolName string
VolumeID string VolumeID string
} }
type snapshotIdentifier struct { type SnapshotIdentifier struct {
FsSnapshotName string FsSnapshotName string
SnapshotID string SnapshotID string
RequestName string RequestName string
@ -44,7 +56,7 @@ type snapshotIdentifier struct {
} }
/* /*
checkVolExists checks to determine if passed in RequestName in volOptions exists on the backend. CheckVolExists checks to determine if passed in RequestName in volOptions exists on the backend.
**NOTE:** These functions manipulate the rados omaps that hold information regarding **NOTE:** These functions manipulate the rados omaps that hold information regarding
volume names as requested by the CSI drivers. Hence, these need to be invoked only when the volume names as requested by the CSI drivers. Hence, these need to be invoked only when the
@ -58,16 +70,16 @@ request name lock, and hence any stale omaps are leftovers from incomplete trans
hence safe to garbage collect. hence safe to garbage collect.
*/ */
// nolint:gocognit,gocyclo,nestif,cyclop // TODO: reduce complexity // nolint:gocognit,gocyclo,nestif,cyclop // TODO: reduce complexity
func checkVolExists(ctx context.Context, func CheckVolExists(ctx context.Context,
volOptions, volOptions,
parentVolOpt *volumeOptions, parentVolOpt *VolumeOptions,
pvID *volumeIdentifier, pvID *VolumeIdentifier,
sID *snapshotIdentifier, sID *SnapshotIdentifier,
cr *util.Credentials) (*volumeIdentifier, error) { cr *util.Credentials) (*VolumeIdentifier, error) {
var vid volumeIdentifier var vid VolumeIdentifier
// Connect to cephfs' default radosNamespace (csi) // Connect to cephfs' default radosNamespace (csi)
j, err := volJournal.Connect(volOptions.Monitors, radosNamespace, cr) j, err := VolJournal.Connect(volOptions.Monitors, fsutil.RadosNamespace, cr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -85,13 +97,13 @@ func checkVolExists(ctx context.Context,
vid.FsSubvolName = imageData.ImageAttributes.ImageName vid.FsSubvolName = imageData.ImageAttributes.ImageName
if sID != nil || pvID != nil { if sID != nil || pvID != nil {
cloneState, cloneStateErr := volOptions.getCloneState(ctx, volumeID(vid.FsSubvolName)) cloneState, cloneStateErr := volOptions.getCloneState(ctx, fsutil.VolumeID(vid.FsSubvolName))
if cloneStateErr != nil { if cloneStateErr != nil {
if errors.Is(cloneStateErr, cerrors.ErrVolumeNotFound) { if errors.Is(cloneStateErr, cerrors.ErrVolumeNotFound) {
if pvID != nil { if pvID != nil {
err = cleanupCloneFromSubvolumeSnapshot( err = cleanupCloneFromSubvolumeSnapshot(
ctx, volumeID(pvID.FsSubvolName), ctx, fsutil.VolumeID(pvID.FsSubvolName),
volumeID(vid.FsSubvolName), fsutil.VolumeID(vid.FsSubvolName),
parentVolOpt) parentVolOpt)
if err != nil { if err != nil {
return nil, err return nil, err
@ -112,7 +124,7 @@ func checkVolExists(ctx context.Context,
return nil, cerrors.ErrClonePending return nil, cerrors.ErrClonePending
} }
if cloneState == cephFSCloneFailed { if cloneState == cephFSCloneFailed {
err = volOptions.purgeVolume(ctx, volumeID(vid.FsSubvolName), true) err = volOptions.PurgeVolume(ctx, fsutil.VolumeID(vid.FsSubvolName), true)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to delete volume %s: %v", vid.FsSubvolName, err) log.ErrorLog(ctx, "failed to delete volume %s: %v", vid.FsSubvolName, err)
@ -120,8 +132,8 @@ func checkVolExists(ctx context.Context,
} }
if pvID != nil { if pvID != nil {
err = cleanupCloneFromSubvolumeSnapshot( err = cleanupCloneFromSubvolumeSnapshot(
ctx, volumeID(pvID.FsSubvolName), ctx, fsutil.VolumeID(pvID.FsSubvolName),
volumeID(vid.FsSubvolName), fsutil.VolumeID(vid.FsSubvolName),
parentVolOpt) parentVolOpt)
if err != nil { if err != nil {
return nil, err return nil, err
@ -136,7 +148,7 @@ func checkVolExists(ctx context.Context,
return nil, fmt.Errorf("clone is not in complete state for %s", vid.FsSubvolName) return nil, fmt.Errorf("clone is not in complete state for %s", vid.FsSubvolName)
} }
} }
volOptions.RootPath, err = volOptions.getVolumeRootPathCeph(ctx, volumeID(vid.FsSubvolName)) volOptions.RootPath, err = volOptions.GetVolumeRootPathCeph(ctx, fsutil.VolumeID(vid.FsSubvolName))
if err != nil { if err != nil {
if errors.Is(err, cerrors.ErrVolumeNotFound) { if errors.Is(err, cerrors.ErrVolumeNotFound) {
// If the subvolume is not present, cleanup the stale snapshot // If the subvolume is not present, cleanup the stale snapshot
@ -144,8 +156,8 @@ func checkVolExists(ctx context.Context,
if parentVolOpt != nil && pvID != nil { if parentVolOpt != nil && pvID != nil {
err = cleanupCloneFromSubvolumeSnapshot( err = cleanupCloneFromSubvolumeSnapshot(
ctx, ctx,
volumeID(pvID.FsSubvolName), fsutil.VolumeID(pvID.FsSubvolName),
volumeID(vid.FsSubvolName), fsutil.VolumeID(vid.FsSubvolName),
parentVolOpt) parentVolOpt)
if err != nil { if err != nil {
return nil, err return nil, err
@ -168,7 +180,7 @@ func checkVolExists(ctx context.Context,
// found a volume already available, process and return it! // found a volume already available, process and return it!
vid.VolumeID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID, vid.VolumeID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
"", volOptions.ClusterID, imageUUID, volIDVersion) "", volOptions.ClusterID, imageUUID, fsutil.VolIDVersion)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -179,8 +191,8 @@ func checkVolExists(ctx context.Context,
if parentVolOpt != nil && pvID != nil { if parentVolOpt != nil && pvID != nil {
err = cleanupCloneFromSubvolumeSnapshot( err = cleanupCloneFromSubvolumeSnapshot(
ctx, ctx,
volumeID(pvID.FsSubvolName), fsutil.VolumeID(pvID.FsSubvolName),
volumeID(vid.FsSubvolName), fsutil.VolumeID(vid.FsSubvolName),
parentVolOpt) parentVolOpt)
if err != nil { if err != nil {
return nil, err return nil, err
@ -190,11 +202,11 @@ func checkVolExists(ctx context.Context,
return &vid, nil return &vid, nil
} }
// undoVolReservation is a helper routine to undo a name reservation for a CSI VolumeName. // UndoVolReservation is a helper routine to undo a name reservation for a CSI VolumeName.
func undoVolReservation( func UndoVolReservation(
ctx context.Context, ctx context.Context,
volOptions *volumeOptions, volOptions *VolumeOptions,
vid volumeIdentifier, vid VolumeIdentifier,
secret map[string]string) error { secret map[string]string) error {
cr, err := util.NewAdminCredentials(secret) cr, err := util.NewAdminCredentials(secret)
if err != nil { if err != nil {
@ -203,7 +215,7 @@ func undoVolReservation(
defer cr.DeleteCredentials() defer cr.DeleteCredentials()
// Connect to cephfs' default radosNamespace (csi) // Connect to cephfs' default radosNamespace (csi)
j, err := volJournal.Connect(volOptions.Monitors, radosNamespace, cr) j, err := VolJournal.Connect(volOptions.Monitors, fsutil.RadosNamespace, cr)
if err != nil { if err != nil {
return err return err
} }
@ -215,7 +227,7 @@ func undoVolReservation(
return err return err
} }
func updateTopologyConstraints(volOpts *volumeOptions) error { func updateTopologyConstraints(volOpts *VolumeOptions) error {
// update request based on topology constrained parameters (if present) // update request based on topology constrained parameters (if present)
poolName, _, topology, err := util.FindPoolAndTopology(volOpts.TopologyPools, volOpts.TopologyRequirement) poolName, _, topology, err := util.FindPoolAndTopology(volOpts.TopologyPools, volOpts.TopologyRequirement)
if err != nil { if err != nil {
@ -229,11 +241,11 @@ func updateTopologyConstraints(volOpts *volumeOptions) error {
return nil return nil
} }
// reserveVol is a helper routine to request a UUID reservation for the CSI VolumeName and, // ReserveVol is a helper routine to request a UUID reservation for the CSI VolumeName and,
// to generate the volume identifier for the reserved UUID. // to generate the volume identifier for the reserved UUID.
func reserveVol(ctx context.Context, volOptions *volumeOptions, secret map[string]string) (*volumeIdentifier, error) { func ReserveVol(ctx context.Context, volOptions *VolumeOptions, secret map[string]string) (*VolumeIdentifier, error) {
var ( var (
vid volumeIdentifier vid VolumeIdentifier
imageUUID string imageUUID string
err error err error
) )
@ -250,7 +262,7 @@ func reserveVol(ctx context.Context, volOptions *volumeOptions, secret map[strin
} }
// Connect to cephfs' default radosNamespace (csi) // Connect to cephfs' default radosNamespace (csi)
j, err := volJournal.Connect(volOptions.Monitors, radosNamespace, cr) j, err := VolJournal.Connect(volOptions.Monitors, fsutil.RadosNamespace, cr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -266,7 +278,7 @@ func reserveVol(ctx context.Context, volOptions *volumeOptions, secret map[strin
// generate the volume ID to return to the CO system // generate the volume ID to return to the CO system
vid.VolumeID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID, vid.VolumeID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
"", volOptions.ClusterID, imageUUID, volIDVersion) "", volOptions.ClusterID, imageUUID, fsutil.VolIDVersion)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -277,22 +289,22 @@ func reserveVol(ctx context.Context, volOptions *volumeOptions, secret map[strin
return &vid, nil return &vid, nil
} }
// reserveSnap is a helper routine to request a UUID reservation for the CSI SnapName and, // ReserveSnap is a helper routine to request a UUID reservation for the CSI SnapName and,
// to generate the snapshot identifier for the reserved UUID. // to generate the snapshot identifier for the reserved UUID.
func reserveSnap( func ReserveSnap(
ctx context.Context, ctx context.Context,
volOptions *volumeOptions, volOptions *VolumeOptions,
parentSubVolName string, parentSubVolName string,
snap *cephfsSnapshot, snap *CephfsSnapshot,
cr *util.Credentials) (*snapshotIdentifier, error) { cr *util.Credentials) (*SnapshotIdentifier, error) {
var ( var (
vid snapshotIdentifier vid SnapshotIdentifier
imageUUID string imageUUID string
err error err error
) )
// Connect to cephfs' default radosNamespace (csi) // Connect to cephfs' default radosNamespace (csi)
j, err := snapJournal.Connect(volOptions.Monitors, radosNamespace, cr) j, err := SnapJournal.Connect(volOptions.Monitors, fsutil.RadosNamespace, cr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -308,7 +320,7 @@ func reserveSnap(
// generate the snapshot ID to return to the CO system // generate the snapshot ID to return to the CO system
vid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID, vid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
"", volOptions.ClusterID, imageUUID, volIDVersion) "", volOptions.ClusterID, imageUUID, fsutil.VolIDVersion)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -319,15 +331,15 @@ func reserveSnap(
return &vid, nil return &vid, nil
} }
// undoSnapReservation is a helper routine to undo a name reservation for a CSI SnapshotName. // UndoSnapReservation is a helper routine to undo a name reservation for a CSI SnapshotName.
func undoSnapReservation( func UndoSnapReservation(
ctx context.Context, ctx context.Context,
volOptions *volumeOptions, volOptions *VolumeOptions,
vid snapshotIdentifier, vid SnapshotIdentifier,
snapName string, snapName string,
cr *util.Credentials) error { cr *util.Credentials) error {
// Connect to cephfs' default radosNamespace (csi) // Connect to cephfs' default radosNamespace (csi)
j, err := snapJournal.Connect(volOptions.Monitors, radosNamespace, cr) j, err := SnapJournal.Connect(volOptions.Monitors, fsutil.RadosNamespace, cr)
if err != nil { if err != nil {
return err return err
} }
@ -340,7 +352,7 @@ func undoSnapReservation(
} }
/* /*
checkSnapExists checks to determine if passed in RequestName in volOptions exists on the backend. CheckSnapExists checks to determine if passed in RequestName in volOptions exists on the backend.
**NOTE:** These functions manipulate the rados omaps that hold information regarding **NOTE:** These functions manipulate the rados omaps that hold information regarding
volume names as requested by the CSI drivers. Hence, these need to be invoked only when the volume names as requested by the CSI drivers. Hence, these need to be invoked only when the
@ -353,14 +365,14 @@ because, the order of omap creation and deletion are inverse of each other, and
request name lock, and hence any stale omaps are leftovers from incomplete transactions and are request name lock, and hence any stale omaps are leftovers from incomplete transactions and are
hence safe to garbage collect. hence safe to garbage collect.
*/ */
func checkSnapExists( func CheckSnapExists(
ctx context.Context, ctx context.Context,
volOptions *volumeOptions, volOptions *VolumeOptions,
parentSubVolName string, parentSubVolName string,
snap *cephfsSnapshot, snap *CephfsSnapshot,
cr *util.Credentials) (*snapshotIdentifier, *snapshotInfo, error) { cr *util.Credentials) (*SnapshotIdentifier, *SnapshotInfo, error) {
// Connect to cephfs' default radosNamespace (csi) // Connect to cephfs' default radosNamespace (csi)
j, err := snapJournal.Connect(volOptions.Monitors, radosNamespace, cr) j, err := SnapJournal.Connect(volOptions.Monitors, fsutil.RadosNamespace, cr)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -374,11 +386,11 @@ func checkSnapExists(
if snapData == nil { if snapData == nil {
return nil, nil, nil return nil, nil, nil
} }
sid := &snapshotIdentifier{} sid := &SnapshotIdentifier{}
snapUUID := snapData.ImageUUID snapUUID := snapData.ImageUUID
snapID := snapData.ImageAttributes.ImageName snapID := snapData.ImageAttributes.ImageName
sid.FsSnapshotName = snapData.ImageAttributes.ImageName sid.FsSnapshotName = snapData.ImageAttributes.ImageName
snapInfo, err := volOptions.getSnapshotInfo(ctx, volumeID(snapID), volumeID(parentSubVolName)) snapInfo, err := volOptions.GetSnapshotInfo(ctx, fsutil.VolumeID(snapID), fsutil.VolumeID(parentSubVolName))
if err != nil { if err != nil {
if errors.Is(err, cerrors.ErrSnapNotFound) { if errors.Is(err, cerrors.ErrSnapNotFound) {
err = j.UndoReservation(ctx, volOptions.MetadataPool, err = j.UndoReservation(ctx, volOptions.MetadataPool,
@ -392,7 +404,7 @@ func checkSnapExists(
defer func() { defer func() {
if err != nil { if err != nil {
err = volOptions.deleteSnapshot(ctx, volumeID(snapID), volumeID(parentSubVolName)) err = volOptions.DeleteSnapshot(ctx, fsutil.VolumeID(snapID), fsutil.VolumeID(parentSubVolName))
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to delete snapshot %s: %v", snapID, err) log.ErrorLog(ctx, "failed to delete snapshot %s: %v", snapID, err)
@ -405,7 +417,7 @@ func checkSnapExists(
} }
} }
}() }()
tm, err := parseTime(ctx, snapInfo.CreatedAt) tm, err := fsutil.ParseTime(ctx, snapInfo.CreatedAt)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -413,7 +425,7 @@ func checkSnapExists(
sid.CreationTime = tm sid.CreationTime = tm
// found a snapshot already available, process and return it! // found a snapshot already available, process and return it!
sid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID, sid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
"", volOptions.ClusterID, snapUUID, volIDVersion) "", volOptions.ClusterID, snapUUID, fsutil.VolIDVersion)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package core
import ( import (
"context" "context"
@ -22,6 +22,7 @@ import (
"time" "time"
cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors" cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors"
fsutil "github.com/ceph/ceph-csi/internal/cephfs/util"
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
"github.com/ceph/go-ceph/cephfs/admin" "github.com/ceph/go-ceph/cephfs/admin"
@ -35,8 +36,8 @@ const (
autoProtect = "snapshot-autoprotect" autoProtect = "snapshot-autoprotect"
) )
// cephfsSnapshot represents a CSI snapshot and its cluster information. // CephfsSnapshot represents a CSI snapshot and its cluster information.
type cephfsSnapshot struct { type CephfsSnapshot struct {
NamePrefix string NamePrefix string
Monitors string Monitors string
// MetadataPool & Pool fields are not used atm. But its definitely good to have it in this struct // MetadataPool & Pool fields are not used atm. But its definitely good to have it in this struct
@ -49,7 +50,7 @@ type cephfsSnapshot struct {
ReservedID string ReservedID string
} }
func (vo *volumeOptions) createSnapshot(ctx context.Context, snapID, volID volumeID) error { func (vo *VolumeOptions) CreateSnapshot(ctx context.Context, snapID, volID fsutil.VolumeID) error {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin: %s", err) log.ErrorLog(ctx, "could not get FSAdmin: %s", err)
@ -68,7 +69,7 @@ func (vo *volumeOptions) createSnapshot(ctx context.Context, snapID, volID volum
return nil return nil
} }
func (vo *volumeOptions) deleteSnapshot(ctx context.Context, snapID, volID volumeID) error { func (vo *VolumeOptions) DeleteSnapshot(ctx context.Context, snapID, volID fsutil.VolumeID) error {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin: %s", err) log.ErrorLog(ctx, "could not get FSAdmin: %s", err)
@ -87,15 +88,15 @@ func (vo *volumeOptions) deleteSnapshot(ctx context.Context, snapID, volID volum
return nil return nil
} }
type snapshotInfo struct { type SnapshotInfo struct {
CreatedAt time.Time CreatedAt time.Time
CreationTime *timestamp.Timestamp CreationTime *timestamp.Timestamp
HasPendingClones string HasPendingClones string
Protected string Protected string
} }
func (vo *volumeOptions) getSnapshotInfo(ctx context.Context, snapID, volID volumeID) (snapshotInfo, error) { func (vo *VolumeOptions) GetSnapshotInfo(ctx context.Context, snapID, volID fsutil.VolumeID) (SnapshotInfo, error) {
snap := snapshotInfo{} snap := SnapshotInfo{}
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin: %s", err) log.ErrorLog(ctx, "could not get FSAdmin: %s", err)
@ -125,7 +126,7 @@ func (vo *volumeOptions) getSnapshotInfo(ctx context.Context, snapID, volID volu
return snap, nil return snap, nil
} }
func (vo *volumeOptions) protectSnapshot(ctx context.Context, snapID, volID volumeID) error { func (vo *VolumeOptions) ProtectSnapshot(ctx context.Context, snapID, volID fsutil.VolumeID) error {
// If "snapshot-autoprotect" feature is present, The ProtectSnapshot // If "snapshot-autoprotect" feature is present, The ProtectSnapshot
// call should be treated as a no-op. // call should be treated as a no-op.
if checkSubvolumeHasFeature(autoProtect, vo.Features) { if checkSubvolumeHasFeature(autoProtect, vo.Features) {
@ -158,7 +159,7 @@ func (vo *volumeOptions) protectSnapshot(ctx context.Context, snapID, volID volu
return nil return nil
} }
func (vo *volumeOptions) unprotectSnapshot(ctx context.Context, snapID, volID volumeID) error { func (vo *VolumeOptions) UnprotectSnapshot(ctx context.Context, snapID, volID fsutil.VolumeID) error {
// If "snapshot-autoprotect" feature is present, The UnprotectSnapshot // If "snapshot-autoprotect" feature is present, The UnprotectSnapshot
// call should be treated as a no-op. // call should be treated as a no-op.
if checkSubvolumeHasFeature(autoProtect, vo.Features) { if checkSubvolumeHasFeature(autoProtect, vo.Features) {
@ -193,10 +194,10 @@ func (vo *volumeOptions) unprotectSnapshot(ctx context.Context, snapID, volID vo
return nil return nil
} }
func (vo *volumeOptions) cloneSnapshot( func (vo *VolumeOptions) cloneSnapshot(
ctx context.Context, ctx context.Context,
volID, snapID, cloneID volumeID, volID, snapID, cloneID fsutil.VolumeID,
cloneVolOptions *volumeOptions, cloneVolOptions *VolumeOptions,
) error { ) error {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package core
import ( import (
"context" "context"
@ -24,6 +24,7 @@ import (
"strings" "strings"
cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors" cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors"
fsutil "github.com/ceph/ceph-csi/internal/cephfs/util"
"github.com/ceph/ceph-csi/internal/util" "github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
@ -54,11 +55,11 @@ type Subvolume struct {
Features []string Features []string
} }
func getVolumeRootPathCephDeprecated(volID volumeID) string { func GetVolumeRootPathCephDeprecated(volID fsutil.VolumeID) string {
return path.Join("/", "csi-volumes", string(volID)) return path.Join("/", "csi-volumes", string(volID))
} }
func (vo *volumeOptions) getVolumeRootPathCeph(ctx context.Context, volID volumeID) (string, error) { func (vo *VolumeOptions) GetVolumeRootPathCeph(ctx context.Context, volID fsutil.VolumeID) (string, error) {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin err %s", err) log.ErrorLog(ctx, "could not get FSAdmin err %s", err)
@ -78,7 +79,7 @@ func (vo *volumeOptions) getVolumeRootPathCeph(ctx context.Context, volID volume
return svPath, nil return svPath, nil
} }
func (vo *volumeOptions) getSubVolumeInfo(ctx context.Context, volID volumeID) (*Subvolume, error) { func (vo *VolumeOptions) GetSubVolumeInfo(ctx context.Context, volID fsutil.VolumeID) (*Subvolume, error) {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin, can not fetch metadata pool for %s:", vo.FsName, err) log.ErrorLog(ctx, "could not get FSAdmin, can not fetch metadata pool for %s:", vo.FsName, err)
@ -141,7 +142,7 @@ type localClusterState struct {
subVolumeGroupCreated bool subVolumeGroupCreated bool
} }
func createVolume(ctx context.Context, volOptions *volumeOptions, volID volumeID, bytesQuota int64) error { func CreateVolume(ctx context.Context, volOptions *VolumeOptions, volID fsutil.VolumeID, bytesQuota int64) error {
// verify if corresponding ClusterID key is present in the map, // verify if corresponding ClusterID key is present in the map,
// and if not, initialize with default values(false). // and if not, initialize with default values(false).
if _, keyPresent := clusterAdditionalInfo[volOptions.ClusterID]; !keyPresent { if _, keyPresent := clusterAdditionalInfo[volOptions.ClusterID]; !keyPresent {
@ -192,10 +193,10 @@ func createVolume(ctx context.Context, volOptions *volumeOptions, volID volumeID
return nil return nil
} }
// resizeVolume will try to use ceph fs subvolume resize command to resize the // ResizeVolume will try to use ceph fs subvolume resize command to resize the
// subvolume. If the command is not available as a fallback it will use // subvolume. If the command is not available as a fallback it will use
// CreateVolume to resize the subvolume. // CreateVolume to resize the subvolume.
func (vo *volumeOptions) resizeVolume(ctx context.Context, volID volumeID, bytesQuota int64) error { func (vo *VolumeOptions) ResizeVolume(ctx context.Context, volID fsutil.VolumeID, bytesQuota int64) error {
// keyPresent checks whether corresponding clusterID key is present in clusterAdditionalInfo // keyPresent checks whether corresponding clusterID key is present in clusterAdditionalInfo
var keyPresent bool var keyPresent bool
// verify if corresponding ClusterID key is present in the map, // verify if corresponding ClusterID key is present in the map,
@ -229,10 +230,10 @@ func (vo *volumeOptions) resizeVolume(ctx context.Context, volID volumeID, bytes
} }
clusterAdditionalInfo[vo.ClusterID].resizeState = unsupported clusterAdditionalInfo[vo.ClusterID].resizeState = unsupported
return createVolume(ctx, vo, volID, bytesQuota) return CreateVolume(ctx, vo, volID, bytesQuota)
} }
func (vo *volumeOptions) purgeVolume(ctx context.Context, volID volumeID, force bool) error { func (vo *VolumeOptions) PurgeVolume(ctx context.Context, volID fsutil.VolumeID, force bool) error {
fsa, err := vo.conn.GetFSAdmin() fsa, err := vo.conn.GetFSAdmin()
if err != nil { if err != nil {
log.ErrorLog(ctx, "could not get FSAdmin %s:", err) log.ErrorLog(ctx, "could not get FSAdmin %s:", err)

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package core
import ( import (
"context" "context"
@ -74,7 +74,7 @@ func execCommandErr(ctx context.Context, program string, args ...string) error {
// Load available ceph mounters installed on system into availableMounters // Load available ceph mounters installed on system into availableMounters
// Called from driver.go's Run(). // Called from driver.go's Run().
func loadAvailableMounters(conf *util.Config) error { func LoadAvailableMounters(conf *util.Config) error {
// #nosec // #nosec
fuseMounterProbe := exec.Command("ceph-fuse", "--version") fuseMounterProbe := exec.Command("ceph-fuse", "--version")
// #nosec // #nosec
@ -113,12 +113,12 @@ func loadAvailableMounters(conf *util.Config) error {
return nil return nil
} }
type volumeMounter interface { type VolumeMounter interface {
mount(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error Mount(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *VolumeOptions) error
name() string Name() string
} }
func newMounter(volOptions *volumeOptions) (volumeMounter, error) { func NewMounter(volOptions *VolumeOptions) (VolumeMounter, error) {
// Get the mounter from the configuration // Get the mounter from the configuration
wantMounter := volOptions.Mounter wantMounter := volOptions.Mounter
@ -145,17 +145,17 @@ func newMounter(volOptions *volumeOptions) (volumeMounter, error) {
switch chosenMounter { switch chosenMounter {
case volumeMounterFuse: case volumeMounterFuse:
return &fuseMounter{}, nil return &FuseMounter{}, nil
case volumeMounterKernel: case volumeMounterKernel:
return &kernelMounter{}, nil return &KernelMounter{}, nil
} }
return nil, fmt.Errorf("unknown mounter '%s'", chosenMounter) return nil, fmt.Errorf("unknown mounter '%s'", chosenMounter)
} }
type fuseMounter struct{} type FuseMounter struct{}
func mountFuse(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error { func mountFuse(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *VolumeOptions) error {
args := []string{ args := []string{
mountPoint, mountPoint,
"-m", volOptions.Monitors, "-m", volOptions.Monitors,
@ -203,11 +203,11 @@ func mountFuse(ctx context.Context, mountPoint string, cr *util.Credentials, vol
return nil return nil
} }
func (m *fuseMounter) mount( func (m *FuseMounter) Mount(
ctx context.Context, ctx context.Context,
mountPoint string, mountPoint string,
cr *util.Credentials, cr *util.Credentials,
volOptions *volumeOptions) error { volOptions *VolumeOptions) error {
if err := util.CreateMountPoint(mountPoint); err != nil { if err := util.CreateMountPoint(mountPoint); err != nil {
return err return err
} }
@ -215,11 +215,11 @@ func (m *fuseMounter) mount(
return mountFuse(ctx, mountPoint, cr, volOptions) return mountFuse(ctx, mountPoint, cr, volOptions)
} }
func (m *fuseMounter) name() string { return "Ceph FUSE driver" } func (m *FuseMounter) Name() string { return "Ceph FUSE driver" }
type kernelMounter struct{} type KernelMounter struct{}
func mountKernel(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error { func mountKernel(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *VolumeOptions) error {
if err := execCommandErr(ctx, "modprobe", "ceph"); err != nil { if err := execCommandErr(ctx, "modprobe", "ceph"); err != nil {
return err return err
} }
@ -247,11 +247,11 @@ func mountKernel(ctx context.Context, mountPoint string, cr *util.Credentials, v
return err return err
} }
func (m *kernelMounter) mount( func (m *KernelMounter) Mount(
ctx context.Context, ctx context.Context,
mountPoint string, mountPoint string,
cr *util.Credentials, cr *util.Credentials,
volOptions *volumeOptions) error { volOptions *VolumeOptions) error {
if err := util.CreateMountPoint(mountPoint); err != nil { if err := util.CreateMountPoint(mountPoint); err != nil {
return err return err
} }
@ -259,9 +259,9 @@ func (m *kernelMounter) mount(
return mountKernel(ctx, mountPoint, cr, volOptions) return mountKernel(ctx, mountPoint, cr, volOptions)
} }
func (m *kernelMounter) name() string { return "Ceph kernel client" } func (m *KernelMounter) Name() string { return "Ceph kernel client" }
func bindMount(ctx context.Context, from, to string, readOnly bool, mntOptions []string) error { func BindMount(ctx context.Context, from, to string, readOnly bool, mntOptions []string) error {
mntOptionSli := strings.Join(mntOptions, ",") mntOptionSli := strings.Join(mntOptions, ",")
if err := execCommandErr(ctx, "mount", "-o", mntOptionSli, from, to); err != nil { if err := execCommandErr(ctx, "mount", "-o", mntOptionSli, from, to); err != nil {
return fmt.Errorf("failed to bind-mount %s to %s: %w", from, to, err) return fmt.Errorf("failed to bind-mount %s to %s: %w", from, to, err)
@ -277,7 +277,7 @@ func bindMount(ctx context.Context, from, to string, readOnly bool, mntOptions [
return nil return nil
} }
func unmountVolume(ctx context.Context, mountPoint string) error { func UnmountVolume(ctx context.Context, mountPoint string) error {
if _, stderr, err := util.ExecCommand(ctx, "umount", mountPoint); err != nil { if _, stderr, err := util.ExecCommand(ctx, "umount", mountPoint); err != nil {
err = fmt.Errorf("%w stderr: %s", err, stderr) err = fmt.Errorf("%w stderr: %s", err, stderr)
if strings.Contains(err.Error(), fmt.Sprintf("umount: %s: not mounted", mountPoint)) || if strings.Contains(err.Error(), fmt.Sprintf("umount: %s: not mounted", mountPoint)) ||

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package core
import ( import (
"context" "context"
@ -26,13 +26,12 @@ import (
"github.com/container-storage-interface/spec/lib/go/csi" "github.com/container-storage-interface/spec/lib/go/csi"
cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors" cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors"
fsutil "github.com/ceph/ceph-csi/internal/cephfs/util"
"github.com/ceph/ceph-csi/internal/util" "github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
) )
type volumeID string type VolumeOptions struct {
type volumeOptions struct {
TopologyPools *[]util.TopologyConstrainedPool TopologyPools *[]util.TopologyConstrainedPool
TopologyRequirement *csi.TopologyRequirement TopologyRequirement *csi.TopologyRequirement
Topology map[string]string Topology map[string]string
@ -60,7 +59,7 @@ type volumeOptions struct {
} }
// Connect a CephFS volume to the Ceph cluster. // Connect a CephFS volume to the Ceph cluster.
func (vo *volumeOptions) Connect(cr *util.Credentials) error { func (vo *VolumeOptions) Connect(cr *util.Credentials) error {
if vo.conn != nil { if vo.conn != nil {
return nil return nil
} }
@ -77,7 +76,7 @@ func (vo *volumeOptions) Connect(cr *util.Credentials) error {
// Destroy cleans up the CephFS volume object and closes the connection to the // Destroy cleans up the CephFS volume object and closes the connection to the
// Ceph cluster in case one was setup. // Ceph cluster in case one was setup.
func (vo *volumeOptions) Destroy() { func (vo *VolumeOptions) Destroy() {
if vo.conn != nil { if vo.conn != nil {
vo.conn.Destroy() vo.conn.Destroy()
} }
@ -147,7 +146,7 @@ func extractMounter(dest *string, options map[string]string) error {
return nil return nil
} }
func getClusterInformation(options map[string]string) (*util.ClusterInfo, error) { func GetClusterInformation(options map[string]string) (*util.ClusterInfo, error) {
clusterID, ok := options["clusterID"] clusterID, ok := options["clusterID"]
if !ok { if !ok {
err := fmt.Errorf("clusterID must be set") err := fmt.Errorf("clusterID must be set")
@ -181,17 +180,17 @@ func getClusterInformation(options map[string]string) (*util.ClusterInfo, error)
return clusterData, nil return clusterData, nil
} }
// newVolumeOptions generates a new instance of volumeOptions from the provided // NewVolumeOptions generates a new instance of volumeOptions from the provided
// CSI request parameters. // CSI request parameters.
func newVolumeOptions(ctx context.Context, requestName string, req *csi.CreateVolumeRequest, func NewVolumeOptions(ctx context.Context, requestName string, req *csi.CreateVolumeRequest,
cr *util.Credentials) (*volumeOptions, error) { cr *util.Credentials) (*VolumeOptions, error) {
var ( var (
opts volumeOptions opts VolumeOptions
err error err error
) )
volOptions := req.GetParameters() volOptions := req.GetParameters()
clusterData, err := getClusterInformation(volOptions) clusterData, err := GetClusterInformation(volOptions)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -259,16 +258,16 @@ func newVolumeOptions(ctx context.Context, requestName string, req *csi.CreateVo
return &opts, nil return &opts, nil
} }
// newVolumeOptionsFromVolID generates a new instance of volumeOptions and volumeIdentifier // newVolumeOptionsFromVolID generates a new instance of volumeOptions and VolumeIdentifier
// from the provided CSI VolumeID. // from the provided CSI VolumeID.
func newVolumeOptionsFromVolID( func NewVolumeOptionsFromVolID(
ctx context.Context, ctx context.Context,
volID string, volID string,
volOpt, secrets map[string]string) (*volumeOptions, *volumeIdentifier, error) { volOpt, secrets map[string]string) (*VolumeOptions, *VolumeIdentifier, error) {
var ( var (
vi util.CSIIdentifier vi util.CSIIdentifier
volOptions volumeOptions volOptions VolumeOptions
vid volumeIdentifier vid VolumeIdentifier
) )
// Decode the VolID first, to detect older volumes or pre-provisioned volumes // Decode the VolID first, to detect older volumes or pre-provisioned volumes
@ -320,7 +319,7 @@ func newVolumeOptionsFromVolID(
} }
// Connect to cephfs' default radosNamespace (csi) // Connect to cephfs' default radosNamespace (csi)
j, err := volJournal.Connect(volOptions.Monitors, radosNamespace, cr) j, err := VolJournal.Connect(volOptions.Monitors, fsutil.RadosNamespace, cr)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -358,27 +357,27 @@ func newVolumeOptionsFromVolID(
volOptions.ProvisionVolume = true volOptions.ProvisionVolume = true
info, err := volOptions.getSubVolumeInfo(ctx, volumeID(vid.FsSubvolName)) info, err := volOptions.GetSubVolumeInfo(ctx, fsutil.VolumeID(vid.FsSubvolName))
if err == nil { if err == nil {
volOptions.RootPath = info.Path volOptions.RootPath = info.Path
volOptions.Features = info.Features volOptions.Features = info.Features
} }
if errors.Is(err, cerrors.ErrInvalidCommand) { if errors.Is(err, cerrors.ErrInvalidCommand) {
volOptions.RootPath, err = volOptions.getVolumeRootPathCeph(ctx, volumeID(vid.FsSubvolName)) volOptions.RootPath, err = volOptions.GetVolumeRootPathCeph(ctx, fsutil.VolumeID(vid.FsSubvolName))
} }
return &volOptions, &vid, err return &volOptions, &vid, err
} }
// newVolumeOptionsFromMonitorList generates a new instance of volumeOptions and // NewVolumeOptionsFromMonitorList generates a new instance of VolumeOptions and
// volumeIdentifier from the provided CSI volume context. // VolumeIdentifier from the provided CSI volume context.
func newVolumeOptionsFromMonitorList( func NewVolumeOptionsFromMonitorList(
volID string, volID string,
options, secrets map[string]string) (*volumeOptions, *volumeIdentifier, error) { options, secrets map[string]string) (*VolumeOptions, *VolumeIdentifier, error) {
var ( var (
opts volumeOptions opts VolumeOptions
vid volumeIdentifier vid VolumeIdentifier
provisionVolumeBool string provisionVolumeBool string
err error err error
) )
@ -408,7 +407,7 @@ func newVolumeOptionsFromMonitorList(
return nil, nil, err return nil, nil, err
} }
opts.RootPath = getVolumeRootPathCephDeprecated(volumeID(volID)) opts.RootPath = GetVolumeRootPathCephDeprecated(fsutil.VolumeID(volID))
} else { } else {
if err = extractOption(&opts.RootPath, "rootPath", options); err != nil { if err = extractOption(&opts.RootPath, "rootPath", options); err != nil {
return nil, nil, err return nil, nil, err
@ -433,15 +432,15 @@ func newVolumeOptionsFromMonitorList(
return &opts, &vid, nil return &opts, &vid, nil
} }
// newVolumeOptionsFromStaticVolume generates a new instance of volumeOptions and // NewVolumeOptionsFromStaticVolume generates a new instance of volumeOptions and
// volumeIdentifier from the provided CSI volume context, if the provided context is // VolumeIdentifier from the provided CSI volume context, if the provided context is
// detected to be a statically provisioned volume. // detected to be a statically provisioned volume.
func newVolumeOptionsFromStaticVolume( func NewVolumeOptionsFromStaticVolume(
volID string, volID string,
options map[string]string) (*volumeOptions, *volumeIdentifier, error) { options map[string]string) (*VolumeOptions, *VolumeIdentifier, error) {
var ( var (
opts volumeOptions opts VolumeOptions
vid volumeIdentifier vid VolumeIdentifier
staticVol bool staticVol bool
err error err error
) )
@ -463,7 +462,7 @@ func newVolumeOptionsFromStaticVolume(
// store NOT of static boolean // store NOT of static boolean
opts.ProvisionVolume = !staticVol opts.ProvisionVolume = !staticVol
clusterData, err := getClusterInformation(options) clusterData, err := GetClusterInformation(options)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -502,16 +501,16 @@ func newVolumeOptionsFromStaticVolume(
return &opts, &vid, nil return &opts, &vid, nil
} }
// newSnapshotOptionsFromID generates a new instance of volumeOptions and snapshotIdentifier // NewSnapshotOptionsFromID generates a new instance of volumeOptions and SnapshotIdentifier
// from the provided CSI VolumeID. // from the provided CSI VolumeID.
func newSnapshotOptionsFromID( func NewSnapshotOptionsFromID(
ctx context.Context, ctx context.Context,
snapID string, snapID string,
cr *util.Credentials) (*volumeOptions, *snapshotInfo, *snapshotIdentifier, error) { cr *util.Credentials) (*VolumeOptions, *SnapshotInfo, *SnapshotIdentifier, error) {
var ( var (
vi util.CSIIdentifier vi util.CSIIdentifier
volOptions volumeOptions volOptions VolumeOptions
sid snapshotIdentifier sid SnapshotIdentifier
) )
// Decode the snapID first, to detect pre-provisioned snapshot before other errors // Decode the snapID first, to detect pre-provisioned snapshot before other errors
err := vi.DecomposeCSIID(snapID) err := vi.DecomposeCSIID(snapID)
@ -560,7 +559,7 @@ func newSnapshotOptionsFromID(
} }
// Connect to cephfs' default radosNamespace (csi) // Connect to cephfs' default radosNamespace (csi)
j, err := snapJournal.Connect(volOptions.Monitors, radosNamespace, cr) j, err := SnapJournal.Connect(volOptions.Monitors, fsutil.RadosNamespace, cr)
if err != nil { if err != nil {
return &volOptions, nil, &sid, err return &volOptions, nil, &sid, err
} }
@ -576,13 +575,13 @@ func newSnapshotOptionsFromID(
sid.FsSnapshotName = imageAttributes.ImageName sid.FsSnapshotName = imageAttributes.ImageName
sid.FsSubvolName = imageAttributes.SourceName sid.FsSubvolName = imageAttributes.SourceName
subvolInfo, err := volOptions.getSubVolumeInfo(ctx, volumeID(sid.FsSubvolName)) subvolInfo, err := volOptions.GetSubVolumeInfo(ctx, fsutil.VolumeID(sid.FsSubvolName))
if err != nil { if err != nil {
return &volOptions, nil, &sid, err return &volOptions, nil, &sid, err
} }
volOptions.Features = subvolInfo.Features volOptions.Features = subvolInfo.Features
info, err := volOptions.getSnapshotInfo(ctx, volumeID(sid.FsSnapshotName), volumeID(sid.FsSubvolName)) info, err := volOptions.GetSnapshotInfo(ctx, fsutil.VolumeID(sid.FsSnapshotName), fsutil.VolumeID(sid.FsSubvolName))
if err != nil { if err != nil {
return &volOptions, nil, &sid, err return &volOptions, nil, &sid, err
} }
@ -590,8 +589,8 @@ func newSnapshotOptionsFromID(
return &volOptions, &info, &sid, nil return &volOptions, &info, &sid, nil
} }
func genSnapFromOptions(ctx context.Context, req *csi.CreateSnapshotRequest) (snap *cephfsSnapshot, err error) { func GenSnapFromOptions(ctx context.Context, req *csi.CreateSnapshotRequest) (snap *CephfsSnapshot, err error) {
cephfsSnap := &cephfsSnapshot{} cephfsSnap := &CephfsSnapshot{}
cephfsSnap.RequestName = req.GetName() cephfsSnap.RequestName = req.GetName()
snapOptions := req.GetParameters() snapOptions := req.GetParameters()

View File

@ -17,6 +17,8 @@ limitations under the License.
package cephfs package cephfs
import ( import (
"github.com/ceph/ceph-csi/internal/cephfs/core"
fsutil "github.com/ceph/ceph-csi/internal/cephfs/util"
csicommon "github.com/ceph/ceph-csi/internal/csi-common" csicommon "github.com/ceph/ceph-csi/internal/csi-common"
"github.com/ceph/ceph-csi/internal/journal" "github.com/ceph/ceph-csi/internal/journal"
"github.com/ceph/ceph-csi/internal/util" "github.com/ceph/ceph-csi/internal/util"
@ -25,14 +27,6 @@ import (
"github.com/container-storage-interface/spec/lib/go/csi" "github.com/container-storage-interface/spec/lib/go/csi"
) )
const (
// volIDVersion is the version number of volume ID encoding scheme.
volIDVersion uint16 = 1
// RADOS namespace to store CSI specific objects and keys.
radosNamespace = "csi"
)
// Driver contains the default identity,node and controller struct. // Driver contains the default identity,node and controller struct.
type Driver struct { type Driver struct {
cd *csicommon.CSIDriver cd *csicommon.CSIDriver
@ -46,14 +40,6 @@ var (
// CSIInstanceID is the instance ID that is unique to an instance of CSI, used when sharing // CSIInstanceID is the instance ID that is unique to an instance of CSI, used when sharing
// ceph clusters across CSI instances, to differentiate omap names per CSI instance. // ceph clusters across CSI instances, to differentiate omap names per CSI instance.
CSIInstanceID = "default" CSIInstanceID = "default"
// volJournal is used to maintain RADOS based journals for CO generated
// VolumeName to backing CephFS subvolumes.
volJournal *journal.Config
// snapJournal is used to maintain RADOS based journals for CO generated
// SnapshotName to backing CephFS subvolumes.
snapJournal *journal.Config
) )
// NewDriver returns new ceph driver. // NewDriver returns new ceph driver.
@ -93,7 +79,7 @@ func (fs *Driver) Run(conf *util.Config) {
var topology map[string]string var topology map[string]string
// Configuration // Configuration
if err = loadAvailableMounters(conf); err != nil { if err = core.LoadAvailableMounters(conf); err != nil {
log.FatalLogMsg("cephfs: failed to load ceph mounters: %v", err) log.FatalLogMsg("cephfs: failed to load ceph mounters: %v", err)
} }
@ -102,9 +88,9 @@ func (fs *Driver) Run(conf *util.Config) {
CSIInstanceID = conf.InstanceID CSIInstanceID = conf.InstanceID
} }
// Create an instance of the volume journal // Create an instance of the volume journal
volJournal = journal.NewCSIVolumeJournalWithNamespace(CSIInstanceID, radosNamespace) core.VolJournal = journal.NewCSIVolumeJournalWithNamespace(CSIInstanceID, fsutil.RadosNamespace)
snapJournal = journal.NewCSISnapshotJournalWithNamespace(CSIInstanceID, radosNamespace) core.SnapJournal = journal.NewCSISnapshotJournalWithNamespace(CSIInstanceID, fsutil.RadosNamespace)
// Initialize default library driver // Initialize default library driver
fs.cd = csicommon.NewCSIDriver(conf.DriverName, util.DriverVersion, conf.NodeID) fs.cd = csicommon.NewCSIDriver(conf.DriverName, util.DriverVersion, conf.NodeID)

View File

@ -62,3 +62,9 @@ var (
// ErrVolumeHasSnapshots is returned when a subvolume has snapshots. // ErrVolumeHasSnapshots is returned when a subvolume has snapshots.
ErrVolumeHasSnapshots = coreError.New("volume has snapshots") ErrVolumeHasSnapshots = coreError.New("volume has snapshots")
) )
// IsCloneRetryError returns true if the clone error is pending,in-progress
// error.
func IsCloneRetryError(err error) bool {
return coreError.Is(err, ErrCloneInProgress) || coreError.Is(err, ErrClonePending)
}

View File

@ -23,7 +23,9 @@ import (
"os" "os"
"strings" "strings"
"github.com/ceph/ceph-csi/internal/cephfs/core"
cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors" cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors"
fsutil "github.com/ceph/ceph-csi/internal/cephfs/util"
csicommon "github.com/ceph/ceph-csi/internal/csi-common" csicommon "github.com/ceph/ceph-csi/internal/csi-common"
"github.com/ceph/ceph-csi/internal/util" "github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log" "github.com/ceph/ceph-csi/internal/util/log"
@ -42,7 +44,9 @@ type NodeServer struct {
VolumeLocks *util.VolumeLocks VolumeLocks *util.VolumeLocks
} }
func getCredentialsForVolume(volOptions *volumeOptions, req *csi.NodeStageVolumeRequest) (*util.Credentials, error) { func getCredentialsForVolume(
volOptions *core.VolumeOptions,
req *csi.NodeStageVolumeRequest) (*util.Credentials, error) {
var ( var (
err error err error
cr *util.Credentials cr *util.Credentials
@ -72,7 +76,7 @@ func getCredentialsForVolume(volOptions *volumeOptions, req *csi.NodeStageVolume
func (ns *NodeServer) NodeStageVolume( func (ns *NodeServer) NodeStageVolume(
ctx context.Context, ctx context.Context,
req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) { req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
var volOptions *volumeOptions var volOptions *core.VolumeOptions
if err := util.ValidateNodeStageVolumeRequest(req); err != nil { if err := util.ValidateNodeStageVolumeRequest(req); err != nil {
return nil, err return nil, err
} }
@ -80,7 +84,7 @@ func (ns *NodeServer) NodeStageVolume(
// Configuration // Configuration
stagingTargetPath := req.GetStagingTargetPath() stagingTargetPath := req.GetStagingTargetPath()
volID := volumeID(req.GetVolumeId()) volID := fsutil.VolumeID(req.GetVolumeId())
if acquired := ns.VolumeLocks.TryAcquire(req.GetVolumeId()); !acquired { if acquired := ns.VolumeLocks.TryAcquire(req.GetVolumeId()); !acquired {
log.ErrorLog(ctx, util.VolumeOperationAlreadyExistsFmt, volID) log.ErrorLog(ctx, util.VolumeOperationAlreadyExistsFmt, volID)
@ -89,21 +93,21 @@ func (ns *NodeServer) NodeStageVolume(
} }
defer ns.VolumeLocks.Release(req.GetVolumeId()) defer ns.VolumeLocks.Release(req.GetVolumeId())
volOptions, _, err := newVolumeOptionsFromVolID(ctx, string(volID), req.GetVolumeContext(), req.GetSecrets()) volOptions, _, err := core.NewVolumeOptionsFromVolID(ctx, string(volID), req.GetVolumeContext(), req.GetSecrets())
if err != nil { if err != nil {
if !errors.Is(err, cerrors.ErrInvalidVolID) { if !errors.Is(err, cerrors.ErrInvalidVolID) {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
// gets mon IPs from the supplied cluster info // gets mon IPs from the supplied cluster info
volOptions, _, err = newVolumeOptionsFromStaticVolume(string(volID), req.GetVolumeContext()) volOptions, _, err = core.NewVolumeOptionsFromStaticVolume(string(volID), req.GetVolumeContext())
if err != nil { if err != nil {
if !errors.Is(err, cerrors.ErrNonStaticVolume) { if !errors.Is(err, cerrors.ErrNonStaticVolume) {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
// get mon IPs from the volume context // get mon IPs from the volume context
volOptions, _, err = newVolumeOptionsFromMonitorList(string(volID), req.GetVolumeContext(), volOptions, _, err = core.NewVolumeOptionsFromMonitorList(string(volID), req.GetVolumeContext(),
req.GetSecrets()) req.GetSecrets())
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
@ -137,9 +141,9 @@ func (ns *NodeServer) NodeStageVolume(
return &csi.NodeStageVolumeResponse{}, nil return &csi.NodeStageVolumeResponse{}, nil
} }
func (*NodeServer) mount(ctx context.Context, volOptions *volumeOptions, req *csi.NodeStageVolumeRequest) error { func (*NodeServer) mount(ctx context.Context, volOptions *core.VolumeOptions, req *csi.NodeStageVolumeRequest) error {
stagingTargetPath := req.GetStagingTargetPath() stagingTargetPath := req.GetStagingTargetPath()
volID := volumeID(req.GetVolumeId()) volID := fsutil.VolumeID(req.GetVolumeId())
cr, err := getCredentialsForVolume(volOptions, req) cr, err := getCredentialsForVolume(volOptions, req)
if err != nil { if err != nil {
@ -149,14 +153,14 @@ func (*NodeServer) mount(ctx context.Context, volOptions *volumeOptions, req *cs
} }
defer cr.DeleteCredentials() defer cr.DeleteCredentials()
m, err := newMounter(volOptions) m, err := core.NewMounter(volOptions)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to create mounter for volume %s: %v", volID, err) log.ErrorLog(ctx, "failed to create mounter for volume %s: %v", volID, err)
return status.Error(codes.Internal, err.Error()) return status.Error(codes.Internal, err.Error())
} }
log.DebugLog(ctx, "cephfs: mounting volume %s with %s", volID, m.name()) log.DebugLog(ctx, "cephfs: mounting volume %s with %s", volID, m.Name())
readOnly := "ro" readOnly := "ro"
fuseMountOptions := strings.Split(volOptions.FuseMountOptions, ",") fuseMountOptions := strings.Split(volOptions.FuseMountOptions, ",")
@ -165,12 +169,12 @@ func (*NodeServer) mount(ctx context.Context, volOptions *volumeOptions, req *cs
if req.VolumeCapability.AccessMode.Mode == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY || if req.VolumeCapability.AccessMode.Mode == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY ||
req.VolumeCapability.AccessMode.Mode == csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY { req.VolumeCapability.AccessMode.Mode == csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY {
switch m.(type) { switch m.(type) {
case *fuseMounter: case *core.FuseMounter:
if !csicommon.MountOptionContains(strings.Split(volOptions.FuseMountOptions, ","), readOnly) { if !csicommon.MountOptionContains(strings.Split(volOptions.FuseMountOptions, ","), readOnly) {
volOptions.FuseMountOptions = util.MountOptionsAdd(volOptions.FuseMountOptions, readOnly) volOptions.FuseMountOptions = util.MountOptionsAdd(volOptions.FuseMountOptions, readOnly)
fuseMountOptions = append(fuseMountOptions, readOnly) fuseMountOptions = append(fuseMountOptions, readOnly)
} }
case *kernelMounter: case *core.KernelMounter:
if !csicommon.MountOptionContains(strings.Split(volOptions.KernelMountOptions, ","), readOnly) { if !csicommon.MountOptionContains(strings.Split(volOptions.KernelMountOptions, ","), readOnly) {
volOptions.KernelMountOptions = util.MountOptionsAdd(volOptions.KernelMountOptions, readOnly) volOptions.KernelMountOptions = util.MountOptionsAdd(volOptions.KernelMountOptions, readOnly)
kernelMountOptions = append(kernelMountOptions, readOnly) kernelMountOptions = append(kernelMountOptions, readOnly)
@ -178,7 +182,7 @@ func (*NodeServer) mount(ctx context.Context, volOptions *volumeOptions, req *cs
} }
} }
if err = m.mount(ctx, stagingTargetPath, cr, volOptions); err != nil { if err = m.Mount(ctx, stagingTargetPath, cr, volOptions); err != nil {
log.ErrorLog(ctx, log.ErrorLog(ctx,
"failed to mount volume %s: %v Check dmesg logs if required.", "failed to mount volume %s: %v Check dmesg logs if required.",
volID, volID,
@ -197,7 +201,7 @@ func (*NodeServer) mount(ctx context.Context, volOptions *volumeOptions, req *cs
stagingTargetPath, stagingTargetPath,
volID, volID,
err) err)
uErr := unmountVolume(ctx, stagingTargetPath) uErr := core.UnmountVolume(ctx, stagingTargetPath)
if uErr != nil { if uErr != nil {
log.ErrorLog( log.ErrorLog(
ctx, ctx,
@ -259,7 +263,12 @@ func (ns *NodeServer) NodePublishVolume(
// It's not, mount now // It's not, mount now
if err = bindMount(ctx, req.GetStagingTargetPath(), req.GetTargetPath(), req.GetReadonly(), mountOptions); err != nil { if err = core.BindMount(
ctx,
req.GetStagingTargetPath(),
req.GetTargetPath(),
req.GetReadonly(),
mountOptions); err != nil {
log.ErrorLog(ctx, "failed to bind-mount volume %s: %v", volID, err) log.ErrorLog(ctx, "failed to bind-mount volume %s: %v", volID, err)
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
@ -301,7 +310,7 @@ func (ns *NodeServer) NodeUnpublishVolume(
} }
// Unmount the bind-mount // Unmount the bind-mount
if err = unmountVolume(ctx, targetPath); err != nil { if err = core.UnmountVolume(ctx, targetPath); err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -349,7 +358,7 @@ func (ns *NodeServer) NodeUnstageVolume(
return &csi.NodeUnstageVolumeResponse{}, nil return &csi.NodeUnstageVolumeResponse{}, nil
} }
// Unmount the volume // Unmount the volume
if err = unmountVolume(ctx, stagingTargetPath); err != nil { if err = core.UnmountVolume(ctx, stagingTargetPath); err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cephfs package util
import ( import (
"context" "context"
@ -26,7 +26,18 @@ import (
"github.com/golang/protobuf/ptypes/timestamp" "github.com/golang/protobuf/ptypes/timestamp"
) )
func parseTime(ctx context.Context, createTime time.Time) (*timestamp.Timestamp, error) { // VolumeID string representation.
type VolumeID string
const (
// VolIDVersion is the version number of volume ID encoding scheme.
VolIDVersion uint16 = 1
// RadosNamespace to store CSI specific objects and keys.
RadosNamespace = "csi"
)
func ParseTime(ctx context.Context, createTime time.Time) (*timestamp.Timestamp, error) {
tm, err := ptypes.TimestampProto(createTime) tm, err := ptypes.TimestampProto(createTime)
if err != nil { if err != nil {
log.ErrorLog(ctx, "failed to convert time %s %v", createTime, err) log.ErrorLog(ctx, "failed to convert time %s %v", createTime, err)

View File

@ -880,7 +880,7 @@ func genSnapFromSnapID(
} }
rbdSnap.JournalPool = rbdSnap.Pool rbdSnap.JournalPool = rbdSnap.Pool
rbdSnap.RadosNamespace, err = util.RadosNamespace(util.CsiConfigFile, rbdSnap.ClusterID) rbdSnap.RadosNamespace, err = util.GetRadosNamespace(util.CsiConfigFile, rbdSnap.ClusterID)
if err != nil { if err != nil {
return err return err
} }
@ -959,7 +959,7 @@ func generateVolumeFromVolumeID(
return rbdVol, err return rbdVol, err
} }
rbdVol.RadosNamespace, err = util.RadosNamespace(util.CsiConfigFile, rbdVol.ClusterID) rbdVol.RadosNamespace, err = util.GetRadosNamespace(util.CsiConfigFile, rbdVol.ClusterID)
if err != nil { if err != nil {
return rbdVol, err return rbdVol, err
} }
@ -1179,7 +1179,7 @@ func genVolFromVolumeOptions(
return nil, err return nil, err
} }
rbdVol.RadosNamespace, err = util.RadosNamespace(util.CsiConfigFile, rbdVol.ClusterID) rbdVol.RadosNamespace, err = util.GetRadosNamespace(util.CsiConfigFile, rbdVol.ClusterID)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -108,8 +108,8 @@ func Mons(pathToConfig, clusterID string) (string, error) {
return strings.Join(cluster.Monitors, ","), nil return strings.Join(cluster.Monitors, ","), nil
} }
// RadosNamespace returns the namespace for the given clusterID. // GetRadosNamespace returns the namespace for the given clusterID.
func RadosNamespace(pathToConfig, clusterID string) (string, error) { func GetRadosNamespace(pathToConfig, clusterID string) (string, error) {
cluster, err := readClusterInfo(pathToConfig, clusterID) cluster, err := readClusterInfo(pathToConfig, clusterID)
if err != nil { if err != nil {
return "", err return "", err