2019-12-13 16:12:17 +00:00
|
|
|
package rbd
|
2015-01-13 06:15:32 +00:00
|
|
|
|
|
|
|
import (
|
2015-07-17 02:27:57 +00:00
|
|
|
"bytes"
|
2015-02-11 21:21:05 +00:00
|
|
|
"encoding/json"
|
2019-12-18 22:21:35 +00:00
|
|
|
"fmt"
|
2020-01-22 12:17:45 +00:00
|
|
|
"io"
|
2015-02-11 21:21:05 +00:00
|
|
|
"sort"
|
|
|
|
"testing"
|
2018-09-17 21:07:18 +00:00
|
|
|
"time"
|
2019-12-05 16:53:41 +00:00
|
|
|
|
|
|
|
"github.com/ceph/go-ceph/rados"
|
2019-10-31 15:43:08 +00:00
|
|
|
"github.com/gofrs/uuid"
|
2019-12-05 16:53:41 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
2015-01-13 06:15:32 +00:00
|
|
|
)
|
|
|
|
|
2020-01-24 14:55:04 +00:00
|
|
|
var (
|
|
|
|
testImageSize = uint64(1 << 22)
|
|
|
|
testImageOrder = 22
|
|
|
|
)
|
|
|
|
|
2015-01-13 06:15:32 +00:00
|
|
|
func GetUUID() string {
|
2019-10-31 15:43:08 +00:00
|
|
|
return uuid.Must(uuid.NewV4()).String()
|
2015-01-13 06:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestVersion(t *testing.T) {
|
2019-12-13 16:12:17 +00:00
|
|
|
var major, minor, patch = Version()
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.False(t, major < 0 || major > 1000, "invalid major")
|
|
|
|
assert.False(t, minor < 0 || minor > 1000, "invalid minor")
|
|
|
|
assert.False(t, patch < 0 || patch > 1000, "invalid patch")
|
2015-01-13 06:15:32 +00:00
|
|
|
}
|
|
|
|
|
2019-12-18 22:21:35 +00:00
|
|
|
func radosConnect(t *testing.T) *rados.Conn {
|
|
|
|
conn, err := rados.NewConn()
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = conn.ReadDefaultConfigFile()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
timeout := time.After(time.Second * 5)
|
|
|
|
ch := make(chan error)
|
|
|
|
go func(conn *rados.Conn) {
|
|
|
|
ch <- conn.Connect()
|
|
|
|
}(conn)
|
|
|
|
select {
|
|
|
|
case err = <-ch:
|
|
|
|
case <-timeout:
|
|
|
|
err = fmt.Errorf("timed out waiting for connect")
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
return conn
|
|
|
|
}
|
|
|
|
|
2019-12-06 17:25:08 +00:00
|
|
|
func TestImageCreate(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2016-12-22 16:21:55 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
2019-12-05 16:53:41 +00:00
|
|
|
require.NoError(t, err)
|
2016-12-22 16:21:55 +00:00
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
image, err := Create(ioctx, name, testImageSize, testImageOrder)
|
2016-12-22 16:21:55 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
name = GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
image, err = Create(ioctx, name, testImageSize, testImageOrder,
|
2019-12-06 11:37:01 +00:00
|
|
|
FeatureLayering|FeatureStripingV2)
|
2016-12-22 16:21:55 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
name = GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
image, err = Create(ioctx, name, testImageSize, testImageOrder,
|
2019-12-06 11:37:01 +00:00
|
|
|
FeatureLayering|FeatureStripingV2, 4096, 2)
|
2016-12-22 16:21:55 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-13 16:12:17 +00:00
|
|
|
// invalid order
|
|
|
|
name = GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
_, err = Create(ioctx, name, testImageSize, -1)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
// too many arguments
|
2020-01-24 14:55:04 +00:00
|
|
|
_, err = Create(ioctx, name, testImageSize, testImageOrder,
|
2019-12-06 11:37:01 +00:00
|
|
|
FeatureLayering|FeatureStripingV2, 4096, 2, 123)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Error(t, err)
|
|
|
|
|
2016-12-22 16:21:55 +00:00
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2019-12-06 17:25:08 +00:00
|
|
|
func TestImageCreate2(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-06 17:25:08 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
image, err := Create2(ioctx, name, testImageSize,
|
2019-12-06 11:37:01 +00:00
|
|
|
FeatureLayering|FeatureStripingV2, testImageOrder)
|
2019-12-06 17:25:08 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestImageCreate3(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-06 17:25:08 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
image, err := Create3(ioctx, name, testImageSize,
|
2019-12-06 11:37:01 +00:00
|
|
|
FeatureLayering|FeatureStripingV2, testImageOrder, 4096, 2)
|
2019-12-06 17:25:08 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2019-11-28 09:43:33 +00:00
|
|
|
func TestCreateImageWithOptions(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-11-28 09:43:33 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// nil options, causes a panic if not handled correctly
|
|
|
|
name := GetUUID()
|
2020-06-10 08:39:04 +00:00
|
|
|
options := NewRbdImageOptions()
|
|
|
|
err = CreateImage(nil, name, testImageSize, options)
|
|
|
|
assert.Error(t, err)
|
|
|
|
err = CreateImage(ioctx, "", testImageSize, options)
|
|
|
|
assert.Error(t, err)
|
2020-01-24 14:55:04 +00:00
|
|
|
err = CreateImage(ioctx, name, testImageSize, nil)
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
// empty/default options
|
|
|
|
name = GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.NoError(t, err)
|
2020-01-24 14:34:29 +00:00
|
|
|
err = RemoveImage(ioctx, name)
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// create image with RbdImageOptionOrder
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
name = GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.NoError(t, err)
|
2020-01-24 14:34:29 +00:00
|
|
|
err = RemoveImage(ioctx, name)
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
options.Clear()
|
|
|
|
|
|
|
|
// create image with a different data pool
|
|
|
|
datapool := GetUUID()
|
|
|
|
err = conn.MakePool(datapool)
|
|
|
|
assert.NoError(t, err)
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetString(ImageOptionDataPool, datapool)
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
name = GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.NoError(t, err)
|
2020-01-24 14:34:29 +00:00
|
|
|
err = RemoveImage(ioctx, name)
|
2019-11-28 09:43:33 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
conn.DeletePool(datapool)
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
options.Destroy()
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2015-01-13 06:15:32 +00:00
|
|
|
func TestGetImageNames(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2015-02-11 21:21:05 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
2019-12-05 16:53:41 +00:00
|
|
|
require.NoError(t, err)
|
2015-02-11 21:21:05 +00:00
|
|
|
|
|
|
|
createdList := []string{}
|
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
name := GetUUID()
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
createdList = append(createdList, name)
|
|
|
|
}
|
|
|
|
|
2019-12-13 16:12:17 +00:00
|
|
|
imageNames, err := GetImageNames(ioctx)
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
sort.Strings(createdList)
|
|
|
|
sort.Strings(imageNames)
|
|
|
|
assert.Equal(t, createdList, imageNames)
|
|
|
|
|
|
|
|
for _, name := range createdList {
|
2019-12-13 16:12:17 +00:00
|
|
|
img := GetImage(ioctx, name)
|
2015-02-11 21:21:05 +00:00
|
|
|
err := img.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
2015-01-13 06:15:32 +00:00
|
|
|
}
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2019-12-29 21:20:29 +00:00
|
|
|
func TestDeprecatedImageOpen(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-10 09:50:07 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-24 14:55:04 +00:00
|
|
|
image, err := Create(ioctx, name, testImageSize, testImageOrder)
|
2019-12-10 09:50:07 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-10 13:02:55 +00:00
|
|
|
// an integer is not a valid argument
|
|
|
|
err = image.Open(123)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
2019-12-29 21:20:29 +00:00
|
|
|
// open read-write
|
|
|
|
err = image.Open()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = image.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-10 13:02:55 +00:00
|
|
|
// open read-only
|
2019-12-10 09:50:07 +00:00
|
|
|
err = image.Open(true)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
bytes_in := []byte("input data")
|
|
|
|
_, err = image.Write(bytes_in)
|
|
|
|
// writing should fail in read-only mode
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
2020-01-31 13:42:06 +00:00
|
|
|
err = image.Remove()
|
|
|
|
// removing should fail while image is opened
|
|
|
|
assert.Equal(t, err, ErrImageIsOpen)
|
|
|
|
|
2019-12-10 09:50:07 +00:00
|
|
|
err = image.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2019-12-10 09:49:47 +00:00
|
|
|
func TestImageResize(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-10 09:49:47 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
|
|
|
reqSize := uint64(1024 * 1024 * 4) // 4MB
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, reqSize, testImageOrder)
|
2019-12-10 09:49:47 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
image, err := OpenImage(ioctx, name, NoSnapshot)
|
2019-12-10 09:49:47 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
size, err := image.GetSize()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, size, reqSize)
|
|
|
|
|
|
|
|
err = image.Resize(reqSize * 2)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
size, err = image.GetSize()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, size, reqSize*2)
|
|
|
|
|
|
|
|
err = image.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
err = image.Resize(reqSize * 2)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
|
|
|
|
2019-12-10 09:49:47 +00:00
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2019-12-10 09:49:35 +00:00
|
|
|
func TestImageProperties(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-10 09:49:35 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
|
|
|
reqSize := uint64(1024 * 1024 * 4) // 4MB
|
2019-12-29 21:22:39 +00:00
|
|
|
_, err = Create3(ioctx, name, reqSize,
|
2019-12-06 11:37:01 +00:00
|
|
|
FeatureLayering|FeatureStripingV2, testImageOrder, 4096, 2)
|
2019-12-10 09:49:35 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2019-12-29 21:22:39 +00:00
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
2019-12-10 09:49:35 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
format, err := img.IsOldFormat()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, format, false)
|
|
|
|
|
|
|
|
size, err := img.GetSize()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, size, reqSize)
|
|
|
|
|
|
|
|
features, err := img.GetFeatures()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
// compare features with the two requested ones
|
2019-12-06 11:37:01 +00:00
|
|
|
assert.Equal(t, features&(FeatureLayering|FeatureStripingV2),
|
|
|
|
FeatureLayering|FeatureStripingV2)
|
2019-12-10 09:49:35 +00:00
|
|
|
|
|
|
|
stripeUnit, err := img.GetStripeUnit()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, stripeUnit, uint64(4096))
|
|
|
|
|
|
|
|
stripeCount, err := img.GetStripeCount()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, stripeCount, uint64(2))
|
|
|
|
|
|
|
|
_, err = img.GetOverlap()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = img.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2019-12-10 09:49:14 +00:00
|
|
|
func TestImageRename(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-10 09:49:14 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2019-12-10 09:49:14 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
img := GetImage(ioctx, name)
|
2019-12-10 09:49:14 +00:00
|
|
|
err = img.Rename(name)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = img.Rename(GetUUID())
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2020-01-31 16:37:19 +00:00
|
|
|
err = img.Remove()
|
|
|
|
assert.NoError(t, err)
|
2019-12-10 09:49:14 +00:00
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2019-12-10 11:10:45 +00:00
|
|
|
func TestImageSeek(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-10 11:10:45 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2019-12-10 11:10:45 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-29 21:22:39 +00:00
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
2019-12-10 11:10:45 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = img.Seek(0, SeekSet)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
bytes_in := []byte("input data")
|
|
|
|
n_in, err := img.Write(bytes_in)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, n_in, len(bytes_in))
|
|
|
|
|
|
|
|
pos, err := img.Seek(0, SeekCur)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, pos, int64(n_in))
|
|
|
|
|
|
|
|
pos, err = img.Seek(0, SeekSet)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, pos, int64(0))
|
|
|
|
|
|
|
|
bytes_out := make([]byte, len(bytes_in))
|
|
|
|
n_out, err := img.Read(bytes_out)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, n_out, len(bytes_out))
|
|
|
|
assert.Equal(t, bytes_in, bytes_out)
|
|
|
|
|
|
|
|
pos, err = img.Seek(0, SeekCur)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, pos, int64(n_out))
|
|
|
|
|
|
|
|
pos, err = img.Seek(0, SeekSet)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, pos, int64(0))
|
|
|
|
|
|
|
|
pos, err = img.Seek(0, SeekEnd)
|
|
|
|
assert.NoError(t, err)
|
2020-01-24 14:55:04 +00:00
|
|
|
assert.Equal(t, pos, int64(testImageSize))
|
2019-12-10 11:10:45 +00:00
|
|
|
|
|
|
|
_, err = img.Seek(0, -1)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = img.Seek(0, SeekEnd)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
|
|
|
|
|
|
|
err = img.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2019-12-10 11:57:29 +00:00
|
|
|
func TestImageDiscard(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-10 11:57:29 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2019-12-10 11:57:29 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-29 21:22:39 +00:00
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
2019-12-10 11:57:29 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
n, err := img.Discard(0, 1<<16)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, n, 1<<16)
|
|
|
|
|
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-29 21:22:39 +00:00
|
|
|
img, err = OpenImageReadOnly(ioctx, name, NoSnapshot)
|
2019-12-10 11:57:29 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// when read-only, discard should fail
|
|
|
|
_, err = img.Discard(0, 1<<16)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = img.Discard(0, 1<<16)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
|
|
|
|
|
|
|
err = img.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2015-01-15 14:19:20 +00:00
|
|
|
func TestIOReaderWriter(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
2019-12-05 16:53:41 +00:00
|
|
|
require.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
name := GetUUID()
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
stats, err := img.Stat()
|
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
encoder := json.NewEncoder(img)
|
2020-04-08 20:36:57 +00:00
|
|
|
assert.NoError(t, encoder.Encode(stats))
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
err = img.Flush()
|
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2019-12-10 11:10:45 +00:00
|
|
|
_, err = img.Seek(0, SeekSet)
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2019-12-13 16:12:17 +00:00
|
|
|
var stats2 *ImageInfo
|
2015-02-11 21:21:05 +00:00
|
|
|
decoder := json.NewDecoder(img)
|
2020-04-08 20:36:57 +00:00
|
|
|
assert.NoError(t, decoder.Decode(&stats2))
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.Equal(t, &stats, &stats2)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2019-12-10 11:10:45 +00:00
|
|
|
_, err = img.Seek(0, SeekSet)
|
2015-02-11 21:21:05 +00:00
|
|
|
bytes_in := []byte("input data")
|
|
|
|
_, err = img.Write(bytes_in)
|
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2019-12-10 11:10:45 +00:00
|
|
|
_, err = img.Seek(0, SeekSet)
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2020-01-22 11:40:38 +00:00
|
|
|
// reading 0 bytes should succeed
|
|
|
|
nil_bytes := make([]byte, 0)
|
|
|
|
n_out, err := img.Read(nil_bytes)
|
|
|
|
assert.Equal(t, n_out, 0)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
bytes_out := make([]byte, len(bytes_in))
|
2020-01-22 11:40:38 +00:00
|
|
|
n_out, err = img.Read(bytes_out)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.Equal(t, n_out, len(bytes_in))
|
|
|
|
assert.Equal(t, bytes_in, bytes_out)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2020-01-22 16:04:37 +00:00
|
|
|
// write some data at the end of the image
|
|
|
|
offset := int64(stats.Size) - int64(len(bytes_in))
|
|
|
|
|
|
|
|
_, err = img.Seek(offset, SeekSet)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
n_out, err = img.Write(bytes_in)
|
|
|
|
assert.Equal(t, len(bytes_in), n_out)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = img.Seek(offset, SeekSet)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
bytes_out = make([]byte, len(bytes_in))
|
|
|
|
n_out, err = img.Read(bytes_out)
|
|
|
|
assert.Equal(t, n_out, len(bytes_in))
|
|
|
|
assert.Equal(t, bytes_in, bytes_out)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// reading after EOF (needs to be large enough to hit EOF)
|
|
|
|
_, err = img.Seek(offset, SeekSet)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
bytes_in = make([]byte, len(bytes_out)+256)
|
|
|
|
n_out, err = img.Read(bytes_in)
|
|
|
|
assert.Equal(t, n_out, len(bytes_out))
|
|
|
|
assert.Equal(t, bytes_in[0:len(bytes_out)], bytes_out)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2020-01-31 16:37:19 +00:00
|
|
|
err = img.Remove()
|
2015-02-11 21:21:05 +00:00
|
|
|
assert.NoError(t, err)
|
2015-01-15 14:19:20 +00:00
|
|
|
|
2015-02-11 21:21:05 +00:00
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
2015-01-15 14:19:20 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 12:17:45 +00:00
|
|
|
func TestReadAt(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-24 15:59:46 +00:00
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
|
2020-01-24 15:59:46 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
2020-01-22 12:17:45 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-01-24 15:59:46 +00:00
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
2020-01-22 12:17:45 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// write 0 bytes should succeed
|
|
|
|
data_out := make([]byte, 0)
|
|
|
|
n_out, err := img.WriteAt(data_out, 256)
|
|
|
|
assert.Equal(t, 0, n_out)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// reading 0 bytes should be successful
|
|
|
|
data_in := make([]byte, 0)
|
|
|
|
n_in, err := img.ReadAt(data_in, 256)
|
|
|
|
assert.Equal(t, 0, n_in)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// write some data at the end of the image
|
|
|
|
data_out = []byte("Hi rbd! Nice to talk through go-ceph :)")
|
|
|
|
|
|
|
|
stats, err := img.Stat()
|
|
|
|
require.NoError(t, err)
|
|
|
|
offset := int64(stats.Size) - int64(len(data_out))
|
|
|
|
|
|
|
|
n_out, err = img.WriteAt(data_out, offset)
|
|
|
|
assert.Equal(t, len(data_out), n_out)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
data_in = make([]byte, len(data_out))
|
|
|
|
n_in, err = img.ReadAt(data_in, offset)
|
|
|
|
assert.Equal(t, n_in, len(data_in))
|
|
|
|
assert.Equal(t, data_in, data_out)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// reading after EOF (needs to be large enough to hit EOF)
|
|
|
|
data_in = make([]byte, len(data_out)+256)
|
|
|
|
n_in, err = img.ReadAt(data_in, offset)
|
|
|
|
assert.Equal(t, n_in, len(data_out))
|
|
|
|
assert.Equal(t, data_in[0:len(data_out)], data_out)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
|
|
|
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// writing to a read-only image should fail
|
2020-01-24 15:59:46 +00:00
|
|
|
img, err = OpenImageReadOnly(ioctx, name, NoSnapshot)
|
2020-01-22 12:17:45 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = img.WriteAt(data_out, 256)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = img.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2019-12-11 10:05:32 +00:00
|
|
|
func TestImageCopy(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
t.Run("invalidParameters", func(t *testing.T) {
|
|
|
|
name := GetUUID()
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
|
2020-01-24 15:59:59 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
|
|
|
require.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
// img not open, should fail
|
|
|
|
img := GetImage(ioctx, name)
|
|
|
|
err = img.Copy(nil, "")
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// pass invalid parameters
|
|
|
|
err = img.Copy(nil, "")
|
|
|
|
assert.Error(t, err) // order of errors not enforced
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img.Copy(ioctx, "")
|
|
|
|
assert.Equal(t, err, ErrNoName)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img.Copy(nil, "duplicate")
|
|
|
|
assert.Equal(t, err, ErrNoIOContext)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = RemoveImage(ioctx, name)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
2019-12-11 10:05:32 +00:00
|
|
|
|
|
|
|
// try successful copying
|
2020-01-24 15:59:59 +00:00
|
|
|
t.Run("successfulCopy", func(t *testing.T) {
|
|
|
|
name := GetUUID()
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
|
2020-01-24 15:59:59 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
|
|
|
require.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
|
|
|
require.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
name2 := GetUUID()
|
|
|
|
err = img.Copy(ioctx, name2)
|
|
|
|
require.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
img2, err := OpenImage(ioctx, name2, NoSnapshot)
|
|
|
|
require.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img2.Close()
|
|
|
|
assert.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img2.Remove()
|
|
|
|
assert.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
t.Run("copy2ImageNotOpen", func(t *testing.T) {
|
|
|
|
name := GetUUID()
|
|
|
|
name2 := GetUUID()
|
|
|
|
img := GetImage(ioctx, name)
|
|
|
|
img2 := GetImage(ioctx, name2)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img.Copy2(img2)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
|
2020-01-24 15:59:59 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
img, err = OpenImage(ioctx, name, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img.Copy2(img2)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = RemoveImage(ioctx, name)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
t.Run("successfulCopy2", func(t *testing.T) {
|
|
|
|
name := GetUUID()
|
|
|
|
name2 := GetUUID()
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
|
2020-01-24 15:59:59 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
2019-12-11 10:05:32 +00:00
|
|
|
|
2020-01-24 15:59:59 +00:00
|
|
|
err = CreateImage(ioctx, name2, testImageSize, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
img2, err := OpenImage(ioctx, name2, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = img.Copy2(img2)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = img2.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = img2.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = img.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
2019-12-11 10:05:32 +00:00
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2015-07-17 02:27:57 +00:00
|
|
|
func TestParentInfo(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2015-07-17 02:27:57 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
2019-12-05 16:53:41 +00:00
|
|
|
require.NoError(t, err)
|
2015-07-17 02:27:57 +00:00
|
|
|
|
|
|
|
name := "parent"
|
2020-01-24 14:55:04 +00:00
|
|
|
img, err := Create(ioctx, name, testImageSize, testImageOrder, 1)
|
2015-07-17 02:27:57 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-29 21:22:39 +00:00
|
|
|
img, err = OpenImage(ioctx, name, NoSnapshot)
|
2015-07-17 02:27:57 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
snapshot, err := img.CreateSnapshot("mysnap")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = snapshot.Protect()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2016-04-05 15:47:47 +00:00
|
|
|
// create an image context with the parent+snapshot
|
2019-12-29 21:22:39 +00:00
|
|
|
snapImg, err := OpenImage(ioctx, name, "mysnap")
|
2016-04-05 15:47:47 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// ensure no children prior to clone
|
|
|
|
pools, images, err := snapImg.ListChildren()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, len(pools), 0, "pools equal")
|
|
|
|
assert.Equal(t, len(images), 0, "children length equal")
|
|
|
|
|
2019-12-10 13:03:10 +00:00
|
|
|
// invalid order, should fail
|
|
|
|
_, err = img.Clone("mysnap", ioctx, "child", 1, -1)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
2020-01-24 14:55:04 +00:00
|
|
|
_, err = img.Clone("mysnap", ioctx, "child", 1, testImageOrder)
|
2015-07-17 02:27:57 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-29 21:22:39 +00:00
|
|
|
imgNew, err := OpenImage(ioctx, "child", NoSnapshot)
|
2015-07-17 02:27:57 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
parentPool := make([]byte, 128)
|
|
|
|
parentName := make([]byte, 128)
|
|
|
|
parentSnapname := make([]byte, 128)
|
|
|
|
|
|
|
|
err = imgNew.GetParentInfo(parentPool, parentName, parentSnapname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
n := bytes.Index(parentName, []byte{0})
|
|
|
|
pName := string(parentName[:n])
|
|
|
|
|
|
|
|
n = bytes.Index(parentSnapname, []byte{0})
|
|
|
|
pSnapname := string(parentSnapname[:n])
|
|
|
|
assert.Equal(t, pName, "parent", "they should be equal")
|
|
|
|
assert.Equal(t, pSnapname, "mysnap", "they should be equal")
|
|
|
|
|
2016-04-05 15:47:47 +00:00
|
|
|
pools, images, err = snapImg.ListChildren()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, len(pools), 1, "pools equal")
|
|
|
|
assert.Equal(t, len(images), 1, "children length equal")
|
|
|
|
|
2015-07-17 02:27:57 +00:00
|
|
|
err = imgNew.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = imgNew.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = snapshot.Unprotect()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = snapshot.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = img.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2016-04-05 15:47:47 +00:00
|
|
|
err = snapImg.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2015-07-17 02:27:57 +00:00
|
|
|
err = img.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
2015-07-20 04:15:40 +00:00
|
|
|
|
2019-12-09 13:19:30 +00:00
|
|
|
func TestNoIOContext(t *testing.T) {
|
2019-12-13 16:12:17 +00:00
|
|
|
image := GetImage(nil, "nonexistent")
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err := image.Clone("new snapshot", nil, "clone", 0, 0)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoIOContext)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Remove()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoIOContext)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Trash(15 * time.Second)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoIOContext)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Rename("unknown")
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoIOContext)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Open()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoIOContext)
|
2019-12-09 13:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestErrorNoName(t *testing.T) {
|
2019-12-13 16:12:17 +00:00
|
|
|
image := GetImage(nil, "")
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err := image.Remove()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoName)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Trash(15 * time.Second)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoName)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Rename("unknown")
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoName)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Open()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNoName)
|
2019-12-09 13:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestErrorImageNotOpen(t *testing.T) {
|
2019-12-13 16:12:17 +00:00
|
|
|
image := GetImage(nil, "nonexistent")
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err := image.Close()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Resize(2 << 22)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.Stat()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.IsOldFormat()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.GetSize()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.GetFeatures()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.GetStripeUnit()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.GetStripeCount()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.GetOverlap()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Flatten()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, _, err = image.ListChildren()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, _, err = image.ListLockers()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.LockExclusive("a magic cookie")
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.LockShared("a magic cookie", "tasty")
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.BreakLock("a magic cookie", "tasty")
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.Read(nil)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.Write(nil)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.ReadAt(nil, 0)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
_, err = image.WriteAt(nil, 0)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
|
|
|
|
err = image.Flush()
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
2019-12-09 13:19:30 +00:00
|
|
|
}
|
|
|
|
|
2015-07-20 04:15:40 +00:00
|
|
|
func TestNotFound(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2015-07-20 04:15:40 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
2019-12-05 16:53:41 +00:00
|
|
|
require.NoError(t, err)
|
2015-07-20 04:15:40 +00:00
|
|
|
|
|
|
|
name := GetUUID()
|
|
|
|
|
2019-12-29 21:22:39 +00:00
|
|
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
2019-12-13 16:12:17 +00:00
|
|
|
assert.Equal(t, err, ErrNotFound)
|
2019-12-29 21:22:39 +00:00
|
|
|
assert.Nil(t, img)
|
2015-07-20 04:15:40 +00:00
|
|
|
|
2019-12-09 13:19:30 +00:00
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2018-09-17 21:07:18 +00:00
|
|
|
func TestTrashImage(t *testing.T) {
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2018-09-17 21:07:18 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
2019-12-05 16:53:41 +00:00
|
|
|
require.NoError(t, err)
|
2018-09-17 21:07:18 +00:00
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2018-09-17 21:07:18 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
image := GetImage(ioctx, name)
|
2018-09-17 21:07:18 +00:00
|
|
|
err = image.Trash(time.Hour)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-13 16:12:17 +00:00
|
|
|
trashList, err := GetTrashList(ioctx)
|
2018-09-17 21:07:18 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, len(trashList), 1, "trashList length equal")
|
|
|
|
|
2019-12-13 16:12:17 +00:00
|
|
|
err = TrashRestore(ioctx, trashList[0].Id, name+"_restored")
|
2018-09-17 21:07:18 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-13 16:12:17 +00:00
|
|
|
image2 := GetImage(ioctx, name+"_restored")
|
2018-09-17 21:07:18 +00:00
|
|
|
err = image2.Trash(time.Hour)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2019-12-13 16:12:17 +00:00
|
|
|
trashList, err = GetTrashList(ioctx)
|
2018-09-17 21:07:18 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, len(trashList), 1, "trashList length equal")
|
|
|
|
|
2019-12-13 16:12:17 +00:00
|
|
|
err = TrashRemove(ioctx, trashList[0].Id, true)
|
2018-09-17 21:07:18 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
2019-12-14 01:16:56 +00:00
|
|
|
|
|
|
|
func TestImageMetadata(t *testing.T) {
|
|
|
|
metadataKey := "mykey"
|
|
|
|
metadataValue := "myvalue"
|
|
|
|
|
2019-12-18 22:21:35 +00:00
|
|
|
conn := radosConnect(t)
|
2019-12-14 01:16:56 +00:00
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2019-12-14 01:16:56 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
image := GetImage(ioctx, name)
|
2019-12-14 01:16:56 +00:00
|
|
|
// Set a metadata key/value on unopen image
|
|
|
|
err = image.SetMetadata(metadataKey, metadataValue)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
|
|
|
// Get the metadata value on unopen image
|
|
|
|
value, err := image.GetMetadata(metadataKey)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
|
|
|
assert.Equal(t, "", value)
|
|
|
|
// Remove the metadata key on unopen image
|
|
|
|
err = image.RemoveMetadata(metadataKey)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
|
|
|
// check key is removed on unopen image
|
|
|
|
value, err = image.GetMetadata(metadataKey)
|
|
|
|
assert.Equal(t, "", value)
|
|
|
|
assert.Equal(t, err, ErrImageNotOpen)
|
|
|
|
|
2019-12-29 21:22:39 +00:00
|
|
|
image, err = OpenImage(ioctx, name, NoSnapshot)
|
2019-12-14 01:16:56 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// Set a metadata key/value
|
|
|
|
err = image.SetMetadata(metadataKey, metadataValue)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
// Get the metadata value
|
|
|
|
value, err = image.GetMetadata(metadataKey)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, metadataValue, value)
|
|
|
|
// Remove the metadata key
|
|
|
|
err = image.RemoveMetadata(metadataKey)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
// check key is removed
|
|
|
|
value, err = image.GetMetadata(metadataKey)
|
|
|
|
assert.Equal(t, "", value)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = image.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
2020-01-21 13:46:27 +00:00
|
|
|
|
|
|
|
func TestClosedImage(t *testing.T) {
|
|
|
|
t.Skipf("many of the following functions cause a panic or hang, skip this test")
|
|
|
|
|
|
|
|
conn := radosConnect(t)
|
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2020-01-21 13:46:27 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
image, err := OpenImage(ioctx, name, NoSnapshot)
|
2020-01-21 13:46:27 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// keep the rbdImage around after close
|
|
|
|
rbdImage := image.image
|
|
|
|
|
|
|
|
// close the image
|
|
|
|
err = image.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// restore the image so image.validate() succeeds
|
|
|
|
image.image = rbdImage
|
|
|
|
|
|
|
|
// functions should now fail with an RBDError
|
|
|
|
|
|
|
|
err = image.Close()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = image.Resize(1 << 22)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.Stat()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.IsOldFormat()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.GetSize()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.GetFeatures()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.GetStripeUnit()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.GetStripeCount()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.GetOverlap()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = image.Flatten()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, _, err = image.ListChildren()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = image.Flush()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.GetSnapshotNames()
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.CreateSnapshot("new_snapshot")
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
_, err = image.GetMetadata("metadata-key")
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = image.SetMetadata("metadata-key", "metadata-value")
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = image.RemoveMetadata("metadata-key")
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
2019-12-29 19:44:41 +00:00
|
|
|
|
|
|
|
func TestOpenImage(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
|
|
|
|
2020-06-10 08:38:27 +00:00
|
|
|
// pass invalid arguments
|
|
|
|
_, err = OpenImage(nil, "some-image", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
_, err = OpenImage(ioctx, "", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
// image does not exist yet
|
2019-12-29 19:44:41 +00:00
|
|
|
_, err = OpenImage(ioctx, name, NoSnapshot)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
2019-12-29 19:44:41 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
oImage, err := OpenImage(ioctx, name, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, name, oImage.name)
|
|
|
|
err = oImage.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// open read-only
|
2020-06-10 08:38:27 +00:00
|
|
|
// pass invalid parameters
|
|
|
|
_, err = OpenImageReadOnly(nil, "some-image", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
_, err = OpenImageReadOnly(ioctx, "", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
|
2019-12-29 19:44:41 +00:00
|
|
|
oImage, err = OpenImageReadOnly(ioctx, name, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
bytes_in := []byte("input data")
|
2020-01-29 16:38:48 +00:00
|
|
|
_, err = oImage.Write(bytes_in)
|
2019-12-29 19:44:41 +00:00
|
|
|
// writing should fail in read-only mode
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
err = oImage.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = oImage.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = OpenImageReadOnly(ioctx, name, NoSnapshot)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
2020-01-24 14:34:29 +00:00
|
|
|
|
|
|
|
func TestRemoveImage(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-06-10 08:38:56 +00:00
|
|
|
// pass invalid parameters
|
|
|
|
err = RemoveImage(nil, "some-name")
|
|
|
|
require.Error(t, err)
|
|
|
|
err = RemoveImage(ioctx, "")
|
|
|
|
require.Error(t, err)
|
|
|
|
|
2020-01-24 14:34:29 +00:00
|
|
|
// trying to remove a non-existent image is an error
|
|
|
|
err = RemoveImage(ioctx, "bananarama")
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
// create and then remove an image
|
|
|
|
name := GetUUID()
|
2020-01-30 18:36:56 +00:00
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
2020-01-24 14:34:29 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
imageNames, err := GetImageNames(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Contains(t, imageNames, name)
|
|
|
|
|
|
|
|
err = RemoveImage(ioctx, name)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
imageNames, err = GetImageNames(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotContains(t, imageNames, name)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
2020-01-29 16:38:48 +00:00
|
|
|
|
2020-01-03 20:35:15 +00:00
|
|
|
func TestCloneImage(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
imageName := "parent1"
|
|
|
|
snapName := "snap1"
|
|
|
|
cloneName := "clone1"
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
|
2020-01-03 20:35:15 +00:00
|
|
|
assert.NoError(t, err)
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionFeatures, 1)
|
2020-01-03 20:35:15 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = CreateImage(ioctx, imageName, testImageSize, options)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
image, err := OpenImage(ioctx, imageName, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
snapshot, err := image.CreateSnapshot(snapName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = snapshot.Protect()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
t.Run("cloneImage", func(t *testing.T) {
|
|
|
|
imageNames, err := GetImageNames(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Contains(t, imageNames, imageName)
|
|
|
|
assert.NotContains(t, imageNames, cloneName)
|
|
|
|
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionFormat, uint64(2))
|
2020-01-03 20:35:15 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = CloneImage(ioctx, imageName, snapName, ioctx, cloneName, options)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
imageNames, err = GetImageNames(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Contains(t, imageNames, imageName)
|
|
|
|
assert.Contains(t, imageNames, cloneName)
|
|
|
|
|
|
|
|
err = RemoveImage(ioctx, cloneName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("cloneFromImage", func(t *testing.T) {
|
|
|
|
imageNames, err := GetImageNames(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Contains(t, imageNames, imageName)
|
|
|
|
assert.NotContains(t, imageNames, cloneName)
|
|
|
|
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionFormat, uint64(2))
|
2020-01-03 20:35:15 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
err = CloneFromImage(image, snapName, ioctx, cloneName, options)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
imageNames, err = GetImageNames(ioctx)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Contains(t, imageNames, imageName)
|
|
|
|
assert.Contains(t, imageNames, cloneName)
|
|
|
|
|
|
|
|
err = RemoveImage(ioctx, cloneName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("cloneFromImageInvalidCtx", func(t *testing.T) {
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err = options.SetUint64(ImageOptionFormat, uint64(2))
|
2020-01-03 20:35:15 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
badImage := GetImage(nil, image.name)
|
|
|
|
err = CloneFromImage(badImage, snapName, ioctx, cloneName, options)
|
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("cloneImageNilOpts", func(t *testing.T) {
|
|
|
|
err = CloneImage(ioctx, imageName, snapName, ioctx, cloneName, nil)
|
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
err = snapshot.Unprotect()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = snapshot.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = image.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
|
|
|
|
2020-01-29 16:38:48 +00:00
|
|
|
// quickCreate creates an image similar to Create but uses CreateImage.
|
|
|
|
// If possible, avoid using this function for new code/tests. It mainly exists
|
|
|
|
// to help with refactoring of existing tests.
|
|
|
|
func quickCreate(ioctx *rados.IOContext, name string, size uint64, order int) error {
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
defer options.Destroy()
|
2020-03-20 13:52:09 +00:00
|
|
|
err := options.SetUint64(ImageOptionOrder, uint64(order))
|
2020-01-29 16:38:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return CreateImage(ioctx, name, size, options)
|
|
|
|
}
|
2019-12-30 00:31:26 +00:00
|
|
|
|
|
|
|
func TestGetId(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
assert.NoError(t,
|
2020-03-20 13:52:09 +00:00
|
|
|
options.SetUint64(ImageOptionOrder, uint64(testImageOrder)))
|
2019-12-30 00:31:26 +00:00
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
image, err := OpenImage(ioctx, name, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
id, err := image.GetId()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Greater(t, len(id), 8)
|
|
|
|
|
|
|
|
err = image.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
id, err = image.GetId()
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.Equal(t, "", id)
|
|
|
|
|
|
|
|
err = image.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|
2019-12-30 00:31:49 +00:00
|
|
|
|
|
|
|
func TestOpenImageById(t *testing.T) {
|
|
|
|
conn := radosConnect(t)
|
|
|
|
|
|
|
|
poolname := GetUUID()
|
|
|
|
err := conn.MakePool(poolname)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx, err := conn.OpenIOContext(poolname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
name := GetUUID()
|
|
|
|
options := NewRbdImageOptions()
|
|
|
|
assert.NoError(t,
|
2020-03-20 13:52:09 +00:00
|
|
|
options.SetUint64(ImageOptionOrder, uint64(testImageOrder)))
|
2019-12-30 00:31:49 +00:00
|
|
|
err = CreateImage(ioctx, name, testImageSize, options)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
workingImage, err := OpenImage(ioctx, name, NoSnapshot)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
id, err := workingImage.GetId()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = workingImage.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2020-06-10 08:38:27 +00:00
|
|
|
t.Run("InvalidArguments", func(t *testing.T) {
|
|
|
|
_, err = OpenImageById(nil, "some-id", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
_, err = OpenImageById(ioctx, "", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
_, err = OpenImageByIdReadOnly(nil, "some-id", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
_, err = OpenImageByIdReadOnly(ioctx, "", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
})
|
2019-12-30 00:31:49 +00:00
|
|
|
t.Run("ReadWriteBadId", func(t *testing.T) {
|
|
|
|
t.Skip("segfaults due to https://tracker.ceph.com/issues/43178")
|
|
|
|
// phony id
|
|
|
|
img, err := OpenImageById(ioctx, "102f00aaabbbccd", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, img)
|
|
|
|
})
|
|
|
|
t.Run("ReadOnlyBadId", func(t *testing.T) {
|
|
|
|
t.Skip("segfaults due to https://tracker.ceph.com/issues/43178")
|
|
|
|
// phony id
|
|
|
|
img, err := OpenImageByIdReadOnly(ioctx, "blubb", NoSnapshot)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, img)
|
|
|
|
})
|
|
|
|
t.Run("ReadWrite", func(t *testing.T) {
|
|
|
|
img, err := OpenImageById(ioctx, id, NoSnapshot)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, img)
|
|
|
|
defer func() { assert.NoError(t, img.Close()) }()
|
|
|
|
|
|
|
|
data := []byte("input data")
|
|
|
|
_, err = img.Write(data)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("ReadOnly", func(t *testing.T) {
|
|
|
|
img, err := OpenImageByIdReadOnly(ioctx, id, NoSnapshot)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, img)
|
|
|
|
defer func() { assert.NoError(t, img.Close()) }()
|
|
|
|
|
|
|
|
data := []byte("input data")
|
|
|
|
_, err = img.Write(data)
|
|
|
|
// writing should fail in read-only mode
|
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
t.Run("Snapshot", func(t *testing.T) {
|
|
|
|
img, err := OpenImageById(ioctx, id, NoSnapshot)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, img)
|
|
|
|
defer func() { assert.NoError(t, img.Close()) }()
|
|
|
|
|
|
|
|
snapshot, err := img.CreateSnapshot("snerpshort")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() { assert.NoError(t, snapshot.Remove()) }()
|
|
|
|
|
|
|
|
snapImage, err := OpenImageById(ioctx, id, "snerpshort")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, snapImage)
|
|
|
|
assert.NoError(t, snapImage.Close())
|
|
|
|
})
|
|
|
|
t.Run("ReadOnlySnapshot", func(t *testing.T) {
|
|
|
|
img, err := OpenImageById(ioctx, id, NoSnapshot)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, img)
|
|
|
|
defer func() { assert.NoError(t, img.Close()) }()
|
|
|
|
|
|
|
|
snapshot, err := img.CreateSnapshot("snerpshort2")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
defer func() { assert.NoError(t, snapshot.Remove()) }()
|
|
|
|
|
|
|
|
snapImage, err := OpenImageByIdReadOnly(ioctx, id, "snerpshort2")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, snapImage)
|
|
|
|
assert.NoError(t, snapImage.Close())
|
|
|
|
})
|
|
|
|
|
|
|
|
err = workingImage.Remove()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ioctx.Destroy()
|
|
|
|
conn.DeletePool(poolname)
|
|
|
|
conn.Shutdown()
|
|
|
|
}
|