rbd_linked_image_spec_t *parent_image,
rbd_snap_spec_t *parent_snap);
+CEPH_RBD_API int rbd_get_migration_source_spec(rbd_image_t image,
+ char* source_spec,
+ size_t* max_len);
+
CEPH_RBD_API int rbd_get_flags(rbd_image_t image, uint64_t *flags);
CEPH_RBD_API int rbd_get_group(rbd_image_t image, rbd_group_info_t *group_info,
size_t group_info_size);
CEPH_RBD_DEPRECATED;
int get_parent(linked_image_spec_t *parent_image, snap_spec_t *parent_snap);
+ int get_migration_source_spec(std::string* source_spec);
+
int old_format(uint8_t *old);
int size(uint64_t *size);
int get_group(group_info_t *group_info, size_t group_info_size);
#include "librbd/image/RemoveRequest.h"
#include "librbd/image/Types.h"
#include "librbd/internal.h"
+#include "librbd/migration/NativeFormat.h"
#include "librbd/mirror/DisableRequest.h"
#include "librbd/mirror/EnableRequest.h"
return 0;
}
+template <typename I>
+int Migration<I>::get_source_spec(I* image_ctx, std::string* source_spec) {
+ auto cct = image_ctx->cct;
+ ldout(cct, 10) << dendl;
+
+ if (image_ctx->migration_info.empty()) {
+ return -ENOENT;
+ }
+
+ if (!image_ctx->migration_info.source_spec.empty()) {
+ *source_spec = image_ctx->migration_info.source_spec;
+ } else {
+ // legacy migration source
+ *source_spec = migration::NativeFormat<I>::build_source_spec(
+ image_ctx->migration_info.pool_id,
+ image_ctx->migration_info.pool_namespace,
+ image_ctx->migration_info.image_name,
+ image_ctx->migration_info.image_id);
+ }
+
+ return 0;
+}
+
template <typename I>
Migration<I>::Migration(I *src_image_ctx, librados::IoCtx& dst_io_ctx,
const std::string &dstname,
static int status(librados::IoCtx& io_ctx, const std::string &image_name,
image_migration_status_t *status);
+ static int get_source_spec(ImageCtxT* image_ctx, std::string* source_spec);
+
private:
CephContext* m_cct;
ImageCtxT *m_src_image_ctx;
return r;
}
+ int Image::get_migration_source_spec(std::string* source_spec)
+ {
+ auto ictx = reinterpret_cast<ImageCtx*>(ctx);
+ return librbd::api::Migration<>::get_source_spec(ictx, source_spec);
+ }
+
int Image::get_flags(uint64_t *flags)
{
ImageCtx *ictx = (ImageCtx *)ctx;
return r;
}
+extern "C" int rbd_get_migration_source_spec(rbd_image_t image,
+ char* source_spec,
+ size_t* max_len)
+{
+ auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
+
+ std::string cpp_source_spec;
+ int r = librbd::api::Migration<>::get_source_spec(ictx, &cpp_source_spec);
+ if (r < 0) {
+ return r;
+ }
+
+ size_t expected_size = cpp_source_spec.size();
+ if (expected_size >= *max_len) {
+ *max_len = expected_size + 1;
+ return -ERANGE;
+ }
+
+ strncpy(source_spec, cpp_source_spec.c_str(), expected_size);
+ source_spec[expected_size] = '\0';
+ *max_len = expected_size + 1;
+
+ return 0;
+}
+
extern "C" int rbd_get_flags(rbd_image_t image, uint64_t *flags)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
# Copyright 2015 Hector Martin <marcan@marcan.st>
import cython
+import json
import sys
from cpython cimport PyObject, ref, exc
int rbd_get_parent(rbd_image_t image,
rbd_linked_image_spec_t *parent_image,
rbd_snap_spec_t *parent_snap)
+ int rbd_get_migration_source_spec(rbd_image_t image,
+ char* source_spec, size_t* max_len)
int rbd_get_flags(rbd_image_t image, uint64_t *flags)
int rbd_get_group(rbd_image_t image, rbd_group_info_t *group_info,
size_t group_info_size)
rbd_snap_spec_cleanup(&snap_spec)
return result
+ @requires_not_closed
+ def migration_source_spec(self):
+ """
+ Get migration source spec (if any)
+
+ :returns: dict
+ :raises: :class:`ImageNotFound` if the image is not migration destination
+ """
+ cdef:
+ size_t size = 512
+ char *spec = NULL
+ try:
+ while True:
+ spec = <char *>realloc_chk(spec, size)
+ with nogil:
+ ret = rbd_get_migration_source_spec(self.image, spec, &size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error retrieving migration source')
+ return json.loads(decode_cstr(spec))
+ finally:
+ free(spec)
+
@requires_not_closed
def old_format(self):
"""
#include "include/event_type.h"
#include "include/err.h"
#include "common/ceph_mutex.h"
+#include "json_spirit/json_spirit.h"
#include "gtest/gtest.h"
ASSERT_EQ(status.state, RBD_IMAGE_MIGRATION_STATE_PREPARED);
rbd_migration_status_cleanup(&status);
+ rbd_image_t image;
+ ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL));
+ char source_spec[2048];
+ size_t source_spec_length = sizeof(source_spec);
+ ASSERT_EQ(0, rbd_get_migration_source_spec(image, source_spec,
+ &source_spec_length));
+ json_spirit::mValue json_source_spec;
+ json_spirit::read(source_spec, json_source_spec);
+ EXPECT_EQ(0, rbd_close(image));
+
ASSERT_EQ(-EBUSY, rbd_remove(ioctx, name.c_str()));
ASSERT_EQ(-EBUSY, rbd_trash_move(ioctx, name.c_str(), 0));
ASSERT_EQ(0, rbd_migration_abort(ioctx, name.c_str()));
- rbd_image_t image;
ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL));
EXPECT_EQ(0, rbd_close(image));
}
ASSERT_NE(status.dest_image_id, "");
ASSERT_EQ(status.state, RBD_IMAGE_MIGRATION_STATE_PREPARED);
+ librbd::Image image;
+ ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
+ std::string source_spec;
+ ASSERT_EQ(0, image.get_migration_source_spec(&source_spec));
+ json_spirit::mValue json_source_spec;
+ json_spirit::read(source_spec, json_source_spec);
+ json_spirit::mObject json_source_spec_obj = json_source_spec.get_obj();
+ ASSERT_EQ(ioctx.get_id(), json_source_spec_obj["pool_id"].get_int64());
+ ASSERT_EQ("", json_source_spec_obj["pool_namespace"].get_str());
+ if (old_format) {
+ ASSERT_EQ(1, json_source_spec_obj.count("image_name"));
+ } else {
+ ASSERT_EQ(1, json_source_spec_obj.count("image_id"));
+ }
+ ASSERT_EQ(0, image.close());
+
ASSERT_EQ(-EBUSY, rbd.remove(ioctx, name.c_str()));
ASSERT_EQ(-EBUSY, rbd.trash_move(ioctx, name.c_str(), 0));
ASSERT_EQ(0, rbd.migration_abort(ioctx, name.c_str()));
- librbd::Image image;
ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
}
eq(image_name, status['dest_image_name'])
eq(RBD_IMAGE_MIGRATION_STATE_PREPARED, status['state'])
+ with Image(ioctx, image_name) as image:
+ source_spec = image.migration_source_spec()
+ eq("native", source_spec["type"])
+
RBD().migration_execute(ioctx, image_name)
RBD().migration_commit(ioctx, image_name)
remove_image()