mirror of https://github.com/ceph/go-ceph
211 lines
5.5 KiB
Go
211 lines
5.5 KiB
Go
package admin
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
var sampleCloneStatusPending = []byte(`{
|
|
"status": {
|
|
"state": "pending",
|
|
"source": {
|
|
"volume": "cephfs",
|
|
"subvolume": "jurrasic",
|
|
"snapshot": "dinodna",
|
|
"group": "park"
|
|
}
|
|
}
|
|
}`)
|
|
|
|
var sampleCloneStatusInProg = []byte(`{
|
|
"status": {
|
|
"state": "in-progress",
|
|
"source": {
|
|
"volume": "cephfs",
|
|
"subvolume": "subvol1",
|
|
"snapshot": "snap1"
|
|
}
|
|
}
|
|
}`)
|
|
|
|
func TestParseCloneStatus(t *testing.T) {
|
|
R := newResponse
|
|
t.Run("error", func(t *testing.T) {
|
|
_, err := parseCloneStatus(R(nil, "", errors.New("flub")))
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "flub", err.Error())
|
|
})
|
|
t.Run("statusSet", func(t *testing.T) {
|
|
_, err := parseCloneStatus(R(nil, "unexpected!", nil))
|
|
assert.Error(t, err)
|
|
})
|
|
t.Run("badJSON", func(t *testing.T) {
|
|
_, err := parseCloneStatus(R([]byte("_XxXxX"), "", nil))
|
|
assert.Error(t, err)
|
|
})
|
|
t.Run("okPending", func(t *testing.T) {
|
|
status, err := parseCloneStatus(R(sampleCloneStatusPending, "", nil))
|
|
assert.NoError(t, err)
|
|
if assert.NotNil(t, status) {
|
|
assert.EqualValues(t, ClonePending, status.State)
|
|
assert.EqualValues(t, "cephfs", status.Source.Volume)
|
|
assert.EqualValues(t, "jurrasic", status.Source.SubVolume)
|
|
assert.EqualValues(t, "dinodna", status.Source.Snapshot)
|
|
assert.EqualValues(t, "park", status.Source.Group)
|
|
}
|
|
})
|
|
t.Run("okInProg", func(t *testing.T) {
|
|
status, err := parseCloneStatus(R(sampleCloneStatusInProg, "", nil))
|
|
assert.NoError(t, err)
|
|
if assert.NotNil(t, status) {
|
|
assert.EqualValues(t, CloneInProgress, status.State)
|
|
assert.EqualValues(t, "cephfs", status.Source.Volume)
|
|
assert.EqualValues(t, "subvol1", status.Source.SubVolume)
|
|
assert.EqualValues(t, "snap1", status.Source.Snapshot)
|
|
assert.EqualValues(t, "", status.Source.Group)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestCloneSubVolumeSnapshot(t *testing.T) {
|
|
fsa := getFSAdmin(t)
|
|
volume := "cephfs"
|
|
group := "Park"
|
|
subname := "Jurrasic"
|
|
snapname := "dinodna0"
|
|
clonename := "babydino"
|
|
|
|
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)
|
|
}()
|
|
|
|
err = fsa.CreateSubVolumeSnapshot(volume, group, subname, snapname)
|
|
assert.NoError(t, err)
|
|
defer func() {
|
|
err := fsa.RemoveSubVolumeSnapshot(volume, group, subname, snapname)
|
|
assert.NoError(t, err)
|
|
}()
|
|
|
|
err = fsa.CloneSubVolumeSnapshot(
|
|
volume, group, subname, snapname, clonename,
|
|
&CloneOptions{TargetGroup: group})
|
|
var x NotProtectedError
|
|
if errors.As(err, &x) {
|
|
err = fsa.ProtectSubVolumeSnapshot(volume, group, subname, snapname)
|
|
assert.NoError(t, err)
|
|
defer func() {
|
|
err := fsa.UnprotectSubVolumeSnapshot(volume, group, subname, snapname)
|
|
assert.NoError(t, err)
|
|
}()
|
|
|
|
err = fsa.CloneSubVolumeSnapshot(
|
|
volume, group, subname, snapname, clonename,
|
|
&CloneOptions{TargetGroup: group})
|
|
}
|
|
assert.NoError(t, err)
|
|
defer func() {
|
|
err := fsa.RemoveSubVolume(volume, group, clonename)
|
|
assert.NoError(t, err)
|
|
}()
|
|
|
|
for done := false; !done; {
|
|
status, err := fsa.CloneStatus(volume, group, clonename)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, status)
|
|
switch status.State {
|
|
case ClonePending, CloneInProgress:
|
|
case CloneComplete:
|
|
done = true
|
|
case CloneFailed:
|
|
t.Fatal("clone failed")
|
|
default:
|
|
t.Fatalf("invalid status.State: %q", status.State)
|
|
}
|
|
time.Sleep(5 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func TestCancelClone(t *testing.T) {
|
|
if serverVersion == cephQuincy || serverVersion == cephPacfic {
|
|
t.Skipf("temporarily disabled on quincy and pacific: very flaky")
|
|
}
|
|
|
|
fsa := getFSAdmin(t)
|
|
volume := "cephfs"
|
|
group := "Park"
|
|
subname := "Jurrasic"
|
|
snapname := "dinodna0"
|
|
clonename := "babydino2"
|
|
|
|
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)
|
|
}()
|
|
|
|
err = fsa.CreateSubVolumeSnapshot(volume, group, subname, snapname)
|
|
assert.NoError(t, err)
|
|
defer func() {
|
|
err := fsa.RemoveSubVolumeSnapshot(volume, group, subname, snapname)
|
|
assert.NoError(t, err)
|
|
}()
|
|
|
|
err = fsa.CloneSubVolumeSnapshot(
|
|
volume, group, subname, snapname, clonename,
|
|
&CloneOptions{TargetGroup: group})
|
|
var x NotProtectedError
|
|
if errors.As(err, &x) {
|
|
err = fsa.ProtectSubVolumeSnapshot(volume, group, subname, snapname)
|
|
assert.NoError(t, err)
|
|
defer func() {
|
|
err := fsa.UnprotectSubVolumeSnapshot(volume, group, subname, snapname)
|
|
assert.NoError(t, err)
|
|
}()
|
|
|
|
err = fsa.CloneSubVolumeSnapshot(
|
|
volume, group, subname, snapname, clonename,
|
|
&CloneOptions{TargetGroup: group})
|
|
}
|
|
assert.NoError(t, err)
|
|
defer func() {
|
|
err := fsa.ForceRemoveSubVolume(volume, group, clonename)
|
|
assert.NoError(t, err)
|
|
}()
|
|
|
|
// we can't guarantee that this clone is can be canceled here, especially
|
|
// if the clone happens fast on the ceph server side, but I have not yet
|
|
// seen an instance where it fails. If it happens we can adjust the test as
|
|
// needed.
|
|
err = fsa.CancelClone(volume, group, clonename)
|
|
assert.NoError(t, err)
|
|
}
|