From 98cf0780e1b7fd2609c653ea0261b92be1d5c0bd Mon Sep 17 00:00:00 2001 From: Nikhil-Ladha Date: Mon, 28 Oct 2024 11:39:13 +0530 Subject: [PATCH] cephfs: log clone progress log cephfs clone progress report during cephfs clone operation Signed-off-by: Nikhil-Ladha --- internal/cephfs/core/clone.go | 34 +++++++++++++++++++----------- internal/cephfs/core/clone_test.go | 10 ++++----- internal/cephfs/core/volume.go | 2 +- internal/cephfs/store/fsjournal.go | 11 ++++++++++ 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/internal/cephfs/core/clone.go b/internal/cephfs/core/clone.go index 6ec18db94..3f0fa2d65 100644 --- a/internal/cephfs/core/clone.go +++ b/internal/cephfs/core/clone.go @@ -28,16 +28,17 @@ import ( // cephFSCloneState describes the status of the clone. type cephFSCloneState struct { - state admin.CloneState - errno string - errorMsg string + state admin.CloneState + progressReport admin.CloneProgressReport + errno string + errorMsg string } // CephFSCloneError indicates that fetching the clone state returned an error. -var CephFSCloneError = cephFSCloneState{} +var CephFSCloneError = &cephFSCloneState{} // ToError checks the state of the clone if it's not cephFSCloneComplete. -func (cs cephFSCloneState) ToError() error { +func (cs *cephFSCloneState) ToError() error { switch cs.state { case admin.CloneComplete: return nil @@ -54,6 +55,14 @@ func (cs cephFSCloneState) ToError() error { return nil } +func (cs *cephFSCloneState) GetProgressReport() admin.CloneProgressReport { + return admin.CloneProgressReport{ + PercentageCloned: cs.progressReport.PercentageCloned, + AmountCloned: cs.progressReport.AmountCloned, + FilesCloned: cs.progressReport.FilesCloned, + } +} + // CreateCloneFromSubvolume creates a clone from a subvolume. func (s *subVolumeClient) CreateCloneFromSubvolume( ctx context.Context, @@ -87,7 +96,7 @@ func (s *subVolumeClient) CreateCloneFromSubvolume( return err } - var cloneState cephFSCloneState + var cloneState *cephFSCloneState cloneState, err = s.GetCloneState(ctx) if err != nil { log.ErrorLog(ctx, "failed to get clone state: %v", err) @@ -157,7 +166,7 @@ func (s *subVolumeClient) CreateCloneFromSnapshot( } } }() - var cloneState cephFSCloneState + var cloneState *cephFSCloneState // avoid err variable shadowing cloneState, err = s.GetCloneState(ctx) if err != nil { @@ -182,7 +191,7 @@ func (s *subVolumeClient) CreateCloneFromSnapshot( } // GetCloneState returns the clone state of the subvolume. -func (s *subVolumeClient) GetCloneState(ctx context.Context) (cephFSCloneState, error) { +func (s *subVolumeClient) GetCloneState(ctx context.Context) (*cephFSCloneState, error) { fsa, err := s.conn.GetFSAdmin() if err != nil { log.ErrorLog( @@ -209,10 +218,11 @@ func (s *subVolumeClient) GetCloneState(ctx context.Context) (cephFSCloneState, errStr = failure.ErrStr } - state := cephFSCloneState{ - state: cs.State, - errno: errno, - errorMsg: errStr, + state := &cephFSCloneState{ + state: cs.State, + progressReport: cs.ProgressReport, + errno: errno, + errorMsg: errStr, } return state, nil diff --git a/internal/cephfs/core/clone_test.go b/internal/cephfs/core/clone_test.go index 1cf9cd6c2..2e4cc7c85 100644 --- a/internal/cephfs/core/clone_test.go +++ b/internal/cephfs/core/clone_test.go @@ -28,11 +28,11 @@ import ( func TestCloneStateToError(t *testing.T) { t.Parallel() errorState := make(map[cephFSCloneState]error) - errorState[cephFSCloneState{fsa.CloneComplete, "", ""}] = nil - errorState[CephFSCloneError] = cerrors.ErrInvalidClone - errorState[cephFSCloneState{fsa.CloneInProgress, "", ""}] = cerrors.ErrCloneInProgress - errorState[cephFSCloneState{fsa.ClonePending, "", ""}] = cerrors.ErrClonePending - errorState[cephFSCloneState{fsa.CloneFailed, "", ""}] = cerrors.ErrCloneFailed + errorState[cephFSCloneState{fsa.CloneComplete, fsa.CloneProgressReport{}, "", ""}] = nil + errorState[*CephFSCloneError] = cerrors.ErrInvalidClone + errorState[cephFSCloneState{fsa.CloneInProgress, fsa.CloneProgressReport{}, "", ""}] = cerrors.ErrCloneInProgress + errorState[cephFSCloneState{fsa.ClonePending, fsa.CloneProgressReport{}, "", ""}] = cerrors.ErrClonePending + errorState[cephFSCloneState{fsa.CloneFailed, fsa.CloneProgressReport{}, "", ""}] = cerrors.ErrCloneFailed for state, err := range errorState { require.ErrorIs(t, state.ToError(), err) diff --git a/internal/cephfs/core/volume.go b/internal/cephfs/core/volume.go index 25b281ee3..dd53b2a76 100644 --- a/internal/cephfs/core/volume.go +++ b/internal/cephfs/core/volume.go @@ -75,7 +75,7 @@ type SubVolumeClient interface { // CreateCloneFromSubVolume creates a clone from the subvolume. CreateCloneFromSubvolume(ctx context.Context, parentvolOpt *SubVolume) error // GetCloneState returns the clone state of the subvolume. - GetCloneState(ctx context.Context) (cephFSCloneState, error) + GetCloneState(ctx context.Context) (*cephFSCloneState, error) // CreateCloneFromSnapshot creates a clone from the subvolume snapshot. CreateCloneFromSnapshot(ctx context.Context, snap Snapshot) error // CleanupSnapshotFromSubvolume removes the snapshot from the subvolume. diff --git a/internal/cephfs/store/fsjournal.go b/internal/cephfs/store/fsjournal.go index 3e3c676e5..dc9115ac3 100644 --- a/internal/cephfs/store/fsjournal.go +++ b/internal/cephfs/store/fsjournal.go @@ -128,6 +128,17 @@ func CheckVolExists(ctx context.Context, } err = cloneState.ToError() if errors.Is(err, cerrors.ErrCloneInProgress) { + progressReport := cloneState.GetProgressReport() + // append progress report only if the progress report parameters are present. + if progressReport.PercentageCloned != "" { + err = fmt.Errorf("%w. progress report: percentage cloned=%s, amount cloned=%s, files cloned=%s", + err, + progressReport.PercentageCloned, + progressReport.AmountCloned, + progressReport.FilesCloned) + log.ErrorLog(ctx, err.Error()) + } + return nil, err } if errors.Is(err, cerrors.ErrClonePending) {