2020-11-03 19:44:23 +00:00
|
|
|
// +build !nautilus
|
|
|
|
|
|
|
|
// Initially, we're only providing mirroring related functions for octopus as
|
|
|
|
// that version of ceph deprecated a number of the functions in nautilus. If
|
|
|
|
// you need mirroring on an earlier supported version of ceph please file an
|
|
|
|
// issue in our tracker.
|
|
|
|
|
|
|
|
package rbd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestGetMirrorMode(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
poolName := GetUUID()
|
|
|
|
err := conn.MakePool(poolName)
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
assert.NoError(t, conn.DeletePool(poolName))
|
|
|
|
conn.Shutdown()
|
|
|
|
}()
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
ioctx.Destroy()
|
|
|
|
}()
|
|
|
|
|
|
|
|
t.Run("mirrorModeDisabled", func(t *testing.T) {
|
|
|
|
m, err := GetMirrorMode(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, m, MirrorModeDisabled)
|
|
|
|
})
|
|
|
|
t.Run("mirrorModeEnabled", func(t *testing.T) {
|
|
|
|
err = SetMirrorMode(ioctx, MirrorModeImage)
|
|
|
|
require.NoError(t, err)
|
|
|
|
m, err := GetMirrorMode(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, m, MirrorModeImage)
|
|
|
|
})
|
|
|
|
t.Run("ioctxNil", func(t *testing.T) {
|
|
|
|
assert.Panics(t, func() {
|
|
|
|
GetMirrorMode(nil)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMirroring(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
poolName := GetUUID()
|
|
|
|
err := conn.MakePool(poolName)
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
assert.NoError(t, conn.DeletePool(poolName))
|
|
|
|
conn.Shutdown()
|
|
|
|
}()
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
ioctx.Destroy()
|
|
|
|
}()
|
|
|
|
|
|
|
|
// verify that mirroring is not enabled on this new pool
|
|
|
|
m, err := GetMirrorMode(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, m, MirrorModeDisabled)
|
|
|
|
|
|
|
|
// enable per-image mirroring for this pool
|
|
|
|
err = SetMirrorMode(ioctx, MirrorModeImage)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name1 := GetUUID()
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
assert.NoError(t,
|
|
|
|
options.SetUint64(ImageOptionOrder, uint64(testImageOrder)))
|
|
|
|
err = CreateImage(ioctx, name1, testImageSize, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
t.Run("enableDisable", func(t *testing.T) {
|
|
|
|
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
}()
|
|
|
|
|
|
|
|
err = img.MirrorEnable(ImageMirrorModeSnapshot)
|
|
|
|
assert.NoError(t, err)
|
2021-01-25 08:51:02 +00:00
|
|
|
|
|
|
|
mode, err := img.GetImageMirrorMode()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, mode, ImageMirrorModeSnapshot)
|
|
|
|
|
2020-11-03 19:44:23 +00:00
|
|
|
err = img.MirrorDisable(false)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("enableDisableInvalid", func(t *testing.T) {
|
|
|
|
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
|
|
|
|
err = img.MirrorEnable(ImageMirrorModeSnapshot)
|
|
|
|
assert.Error(t, err)
|
|
|
|
err = img.MirrorDisable(false)
|
|
|
|
assert.Error(t, err)
|
2021-01-25 08:51:02 +00:00
|
|
|
_, err = img.GetImageMirrorMode()
|
|
|
|
assert.Error(t, err)
|
2020-11-03 19:44:23 +00:00
|
|
|
})
|
|
|
|
t.Run("promoteDemote", func(t *testing.T) {
|
|
|
|
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
}()
|
|
|
|
|
|
|
|
err = img.MirrorEnable(ImageMirrorModeSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = img.MirrorDemote()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = img.MirrorPromote(false)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = img.MirrorDisable(false)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("promoteDemoteInvalid", func(t *testing.T) {
|
|
|
|
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
|
|
|
|
err = img.MirrorDemote()
|
|
|
|
assert.Error(t, err)
|
|
|
|
err = img.MirrorPromote(false)
|
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
t.Run("resync", func(t *testing.T) {
|
|
|
|
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
}()
|
|
|
|
|
|
|
|
err = img.MirrorEnable(ImageMirrorModeSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = img.MirrorDemote()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = img.MirrorResync()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = img.MirrorDisable(true)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("resyncInvalid", func(t *testing.T) {
|
|
|
|
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
|
|
|
|
err = img.MirrorResync()
|
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
t.Run("instanceId", func(t *testing.T) {
|
|
|
|
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
}()
|
|
|
|
|
|
|
|
err = img.MirrorEnable(ImageMirrorModeSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
miid, err := img.MirrorInstanceID()
|
|
|
|
// this is not currently testable for the "success" case
|
|
|
|
// see also the ceph tree where nothing is asserted except
|
|
|
|
// that the error is raised.
|
|
|
|
// TODO(?): figure out how to test this
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.Equal(t, "", miid)
|
|
|
|
err = img.MirrorDisable(false)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("instanceIdInvalid", func(t *testing.T) {
|
|
|
|
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
|
|
|
|
_, err = img.MirrorInstanceID()
|
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
}
|
2021-01-25 08:09:00 +00:00
|
|
|
|
|
|
|
func TestGetMirrorImageInfo(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
poolName := GetUUID()
|
|
|
|
err := conn.MakePool(poolName)
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
assert.NoError(t, conn.DeletePool(poolName))
|
|
|
|
conn.Shutdown()
|
|
|
|
}()
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
ioctx.Destroy()
|
|
|
|
}()
|
|
|
|
|
|
|
|
// enable per-image mirroring for this pool
|
|
|
|
err = SetMirrorMode(ioctx, MirrorModeImage)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
imgName := GetUUID()
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
assert.NoError(t, options.SetUint64(ImageOptionOrder, uint64(testImageOrder)))
|
|
|
|
err = CreateImage(ioctx, imgName, testImageSize, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
t.Run("closedImage", func(t *testing.T) {
|
|
|
|
img := GetImage(ioctx, imgName)
|
|
|
|
_, err = img.GetMirrorImageInfo()
|
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("getInfo", func(t *testing.T) {
|
|
|
|
// open image, enable, mirroring.
|
|
|
|
img, err := OpenImage(ioctx, imgName, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
assert.NoError(t, img.Close())
|
|
|
|
}()
|
|
|
|
|
|
|
|
err = img.MirrorEnable(ImageMirrorModeSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
mii, err := img.GetMirrorImageInfo()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, mii.GlobalID)
|
|
|
|
assert.Equal(t, mii.State, MirrorImageEnabled)
|
|
|
|
assert.Equal(t, mii.Primary, true)
|
|
|
|
})
|
|
|
|
}
|