dd if=/bin/dd of=${TMPDIR}/img bs=1k count=10 seek=100
rbd import $RBD_CREATE_ARGS ${TMPDIR}/img testimg
rbd snap create testimg@snap
+ rbd image-meta set testimg key1 value1
+ IMAGEMETA_BEFORE=`rbd image-meta list testimg`
rbd export --export-format 2 testimg ${TMPDIR}/img_v2
rbd import --export-format 2 ${TMPDIR}/img_v2 testimg_import
rbd info testimg_import
rbd info testimg_import@snap
+ IMAGEMETA_AFTER=`rbd image-meta list testimg_import`
+ [ "$IMAGEMETA_BEFORE" = "$IMAGEMETA_AFTER" ]
# compare the contents between testimg and testimg_import
rbd export testimg_import ${TMPDIR}/img_import
int m_fd;
};
+const uint32_t MAX_KEYS = 64;
+
static int do_export_v2(librbd::Image& image, librbd::image_info_t &info, int fd,
uint64_t period, int max_concurrent_ops, utils::ProgressContext &pc)
{
::encode(length, bl);
::encode(stripe_count, bl);
+ //retrieve metadata of image
+ std::map<std::string, string> imagemetas;
+ std::string last_key;
+ bool more_results = true;
+ while (more_results) {
+ std::map<std::string, bufferlist> pairs;
+ r = image.metadata_list(last_key, MAX_KEYS, &pairs);
+ if (r < 0) {
+ std::cerr << "failed to retrieve metadata of image : " << cpp_strerror(r)
+ << std::endl;
+ return r;
+ }
+
+ if (!pairs.empty()) {
+ last_key = pairs.rbegin()->first;
+
+ for (auto kv : pairs) {
+ std::string key = kv.first;
+ std::string val(kv.second.c_str(), kv.second.length());
+ imagemetas[key] = val;
+ }
+ }
+ more_results = (pairs.size() == MAX_KEYS);
+ }
+
+ //encode imageMeta key and value
+ for (std::map<std::string, string>::iterator it = imagemetas.begin();
+ it != imagemetas.end(); ++it) {
+ string key = it->first;
+ string value = it->second;
+
+ tag = RBD_EXPORT_IMAGE_META;
+ length = key.length() + value.length() + 4 * 2;
+ ::encode(tag, bl);
+ ::encode(length, bl);
+ ::encode(key, bl);
+ ::encode(value, bl);
+ }
+
// encode end tag
tag = RBD_EXPORT_IMAGE_END;
::encode(tag, bl);
return 0;
}
-static int do_import_header(int fd, int import_format, uint64_t &size, librbd::ImageOptions& opts)
+static int do_import_metadata(int import_format, librbd::Image& image,
+ const std::map<std::string, std::string> &imagemetas)
+{
+ int r = 0;
+
+ //v1 format
+ if (import_format == 1) {
+ return r;
+ }
+
+ for (std::map<std::string, std::string>::const_iterator it = imagemetas.begin();
+ it != imagemetas.end(); ++it) {
+ r = image.metadata_set(it->first, it->second);
+ if (r < 0)
+ return r;
+ }
+
+ return r;
+}
+
+static int decode_imagemeta(int fd, uint64_t length, std::map<std::string, std::string>* imagemetas)
+{
+ int r;
+ string key;
+ string value;
+
+ r = utils::read_string(fd, length, &key);
+ if (r < 0)
+ return r;
+
+ r = utils::read_string(fd, length, &value);
+ if (r < 0)
+ return r;
+
+ (*imagemetas)[key] = value;
+ return 0;
+}
+
+static int do_import_header(int fd, int import_format, uint64_t &size, librbd::ImageOptions& opts,
+ std::map<std::string, std::string>* imagemetas)
{
// There is no header in v1 image.
if (import_format == 1) {
r = decode_and_set_image_option(fd, RBD_IMAGE_OPTION_STRIPE_UNIT, opts);
} else if (tag == RBD_EXPORT_IMAGE_STRIPE_COUNT) {
r = decode_and_set_image_option(fd, RBD_IMAGE_OPTION_STRIPE_COUNT, opts);
+ } else if (tag == RBD_EXPORT_IMAGE_META) {
+ r = decode_imagemeta(fd, length, imagemetas);
} else {
std::cerr << "rbd: invalid tag in image properties zone: " << tag << "Skip it."
<< std::endl;
int fd, r;
struct stat stat_buf;
utils::ProgressContext pc("Importing image", no_progress);
+ std::map<std::string, std::string> imagemetas;
assert(imgname);
#endif
}
- r = do_import_header(fd, import_format, size, opts);
+ r = do_import_header(fd, import_format, size, opts, &imagemetas);
if (r < 0) {
std::cerr << "rbd: import header failed." << std::endl;
goto done;
goto err;
}
+ r = do_import_metadata(import_format, image, imagemetas);
+ if (r < 0) {
+ std::cerr << "rbd: failed to import image-meta" << std::endl;
+ goto err;
+ }
+
if (import_format == 1) {
r = do_import_v1(fd, image, size, imgblklen, pc, sparse_size);
} else {