From b66dcaf5651c945fa08985548a9b2f10db5a06b9 Mon Sep 17 00:00:00 2001 From: John Mulligan Date: Mon, 31 Aug 2020 17:11:40 -0400 Subject: [PATCH] cephfs admin: add a SubVolumePath function The SubVolumePath function maps the subvolume to a path from the root of the cephfs, and works like `ceph fs subvolume getpath ...`. Signed-off-by: John Mulligan --- cephfs/admin/fsadmin.go | 18 ++++++++++++++++++ cephfs/admin/subvolume.go | 17 +++++++++++++++++ cephfs/admin/subvolume_test.go | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/cephfs/admin/fsadmin.go b/cephfs/admin/fsadmin.go index 1f0c6ed..1312786 100644 --- a/cephfs/admin/fsadmin.go +++ b/cephfs/admin/fsadmin.go @@ -137,6 +137,24 @@ func unmarshalResponseJSON(res []byte, status string, err error, v interface{}) return json.Unmarshal(res, v) } +// extractPathResponse returns a cleaned up path from requests that get a path +// unless an error is encountered, then an error is returned. +func extractPathResponse(res []byte, status string, err error) (string, error) { + if err != nil { + return "", err + } + if status != "" { + return "", fmt.Errorf("error status: %s", status) + } + // if there's a trailing newline in the buffer strip it. + // ceph assumes a CLI wants the output of the buffer and there's + // no format=json mode available currently. + for len(res) >= 1 && res[len(res)-1] == '\n' { + res = res[:len(res)-1] + } + return string(res), nil +} + // modeString converts a unix-style mode value to a string-ified version in an // octal representation (e.g. "777", "700", etc). This format is expected by // some of the ceph JSON command inputs. diff --git a/cephfs/admin/subvolume.go b/cephfs/admin/subvolume.go index 90109c9..a0d02f7 100644 --- a/cephfs/admin/subvolume.go +++ b/cephfs/admin/subvolume.go @@ -143,3 +143,20 @@ func (fsa *FSAdmin) ResizeSubVolume( } return result[0], nil } + +// SubVolumePath returns the path to the subvolume from the root of the file system. +// +// Similar To: +// ceph fs subvolume getpath --group-name= +func (fsa *FSAdmin) SubVolumePath(volume, group, name string) (string, error) { + m := map[string]string{ + "prefix": "fs subvolume getpath", + "vol_name": volume, + "sub_name": name, + // ceph doesn't respond in json for this cmd (even if you ask) + } + if group != NoGroup { + m["group_name"] = group + } + return extractPathResponse(fsa.marshalMgrCommand(m)) +} diff --git a/cephfs/admin/subvolume_test.go b/cephfs/admin/subvolume_test.go index e3a4a9a..57bed10 100644 --- a/cephfs/admin/subvolume_test.go +++ b/cephfs/admin/subvolume_test.go @@ -173,3 +173,35 @@ func TestResizeSubVolume(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, rr) } + +func TestSubVolumePath(t *testing.T) { + fsa := getFSAdmin(t) + volume := "cephfs" + group := "svpGroup" + subname := "svp1" + + err := fsa.CreateSubVolumeGroup(volume, group, nil) + assert.NoError(t, err) + defer func() { + err := fsa.RemoveSubVolumeGroup(volume, group) + assert.NoError(t, err) + }() + + err = fsa.CreateSubVolume(volume, group, subname, nil) + assert.NoError(t, err) + defer func() { + err := fsa.RemoveSubVolume(volume, group, subname) + assert.NoError(t, err) + }() + + path, err := fsa.SubVolumePath(volume, group, subname) + assert.NoError(t, err) + assert.Contains(t, path, group) + assert.Contains(t, path, subname) + assert.NotContains(t, path, "\n") + + // invalid subname + path, err = fsa.SubVolumePath(volume, group, "oops") + assert.Error(t, err) + assert.Equal(t, "", path) +}