diff --git a/cephfs/admin/subvolume.go b/cephfs/admin/subvolume.go index d17ce32..ac3cb90 100644 --- a/cephfs/admin/subvolume.go +++ b/cephfs/admin/subvolume.go @@ -211,3 +211,56 @@ func (fsa *FSAdmin) SubVolumeInfo(volume, group, name string) (*SubVolumeInfo, e } return parseSubVolumeInfo(fsa.marshalMgrCommand(m)) } + +// CreateSubVolumeSnapshot creates a new snapshot from the source subvolume. +// +// Similar To: +// ceph fs subvolume snapshot create --group-name= +func (fsa *FSAdmin) CreateSubVolumeSnapshot(volume, group, source, name string) error { + m := map[string]string{ + "prefix": "fs subvolume snapshot create", + "vol_name": volume, + "sub_name": source, + "snap_name": name, + "format": "json", + } + if group != NoGroup { + m["group_name"] = group + } + return checkEmptyResponseExpected(fsa.marshalMgrCommand(m)) +} + +// RemoveSubVolumeSnapshot removes the specified snapshot from the subvolume. +// +// Similar To: +// ceph fs subvolume snapshot rm --group-name= +func (fsa *FSAdmin) RemoveSubVolumeSnapshot(volume, group, subvolume, name string) error { + m := map[string]string{ + "prefix": "fs subvolume snapshot rm", + "vol_name": volume, + "sub_name": subvolume, + "snap_name": name, + "format": "json", + } + if group != NoGroup { + m["group_name"] = group + } + return checkEmptyResponseExpected(fsa.marshalMgrCommand(m)) +} + +// ListSubVolumeSnapshots returns a listing of snapshots for a given subvolume. +// +// Similar To: +// ceph fs subvolume snapshot ls --group-name= +func (fsa *FSAdmin) ListSubVolumeSnapshots(volume, group, name string) ([]string, error) { + m := map[string]string{ + "prefix": "fs subvolume snapshot ls", + "vol_name": volume, + "sub_name": name, + "format": "json", + } + if group != NoGroup { + m["group_name"] = group + } + return parseListNames(fsa.marshalMgrCommand(m)) +} diff --git a/cephfs/admin/subvolume_test.go b/cephfs/admin/subvolume_test.go index f78f1da..5a54ccf 100644 --- a/cephfs/admin/subvolume_test.go +++ b/cephfs/admin/subvolume_test.go @@ -347,3 +347,72 @@ func TestSubVolumeInfo(t *testing.T) { assert.Equal(t, 040750, vinfo.Mode) assert.GreaterOrEqual(t, 2020, vinfo.Ctime.Year()) } + +func TestSubVolumeSnapshots(t *testing.T) { + fsa := getFSAdmin(t) + volume := "cephfs" + group := "20000leagues" + subname := "nautilus" + snapname1 := "ne1" + snapname2 := "mo2" + + err := fsa.CreateSubVolumeGroup(volume, group, nil) + assert.NoError(t, err) + defer func() { + err := fsa.RemoveSubVolumeGroup(volume, group) + assert.NoError(t, err) + }() + + svopts := &SubVolumeOptions{ + Mode: 0750, + Size: 20 * gibiByte, + } + err = fsa.CreateSubVolume(volume, group, subname, svopts) + assert.NoError(t, err) + defer func() { + err := fsa.RemoveSubVolume(volume, group, subname) + assert.NoError(t, err) + }() + + t.Run("createAndRemove", func(t *testing.T) { + err = fsa.CreateSubVolumeSnapshot(volume, group, subname, snapname1) + assert.NoError(t, err) + err := fsa.RemoveSubVolumeSnapshot(volume, group, subname, snapname1) + assert.NoError(t, err) + }) + + t.Run("listOne", func(t *testing.T) { + err = fsa.CreateSubVolumeSnapshot(volume, group, subname, snapname1) + assert.NoError(t, err) + defer func() { + err := fsa.RemoveSubVolumeSnapshot(volume, group, subname, snapname1) + assert.NoError(t, err) + }() + + snaps, err := fsa.ListSubVolumeSnapshots(volume, group, subname) + assert.NoError(t, err) + assert.Len(t, snaps, 1) + assert.Contains(t, snaps, snapname1) + }) + + t.Run("listTwo", func(t *testing.T) { + err = fsa.CreateSubVolumeSnapshot(volume, group, subname, snapname1) + assert.NoError(t, err) + defer func() { + err := fsa.RemoveSubVolumeSnapshot(volume, group, subname, snapname1) + assert.NoError(t, err) + }() + err = fsa.CreateSubVolumeSnapshot(volume, group, subname, snapname2) + assert.NoError(t, err) + defer func() { + err := fsa.RemoveSubVolumeSnapshot(volume, group, subname, snapname2) + assert.NoError(t, err) + }() + + snaps, err := fsa.ListSubVolumeSnapshots(volume, group, subname) + assert.NoError(t, err) + assert.Len(t, snaps, 2) + assert.Contains(t, snaps, snapname1) + assert.Contains(t, snaps, snapname2) + }) +}