From 2f0b233a31edfa28c6695e5ab1efac7cd7564422 Mon Sep 17 00:00:00 2001 From: PCzhangPC Date: Fri, 29 Sep 2017 13:30:01 +0800 Subject: [PATCH] rbd:export/import image-meta when we export/import an image when we do exporting/importing an image, we should export or import the image-meta of this image at the same time Signed-off-by: PCzhangPC --- doc/dev/rbd-export.rst | 8 +++++ qa/workunits/rbd/import_export.sh | 4 +++ src/tools/rbd/Utils.h | 1 + src/tools/rbd/action/Export.cc | 41 ++++++++++++++++++++++++ src/tools/rbd/action/Import.cc | 52 +++++++++++++++++++++++++++++-- 5 files changed, 104 insertions(+), 2 deletions(-) diff --git a/doc/dev/rbd-export.rst b/doc/dev/rbd-export.rst index 0d34d611b64f4..d009b79953ab4 100644 --- a/doc/dev/rbd-export.rst +++ b/doc/dev/rbd-export.rst @@ -65,6 +65,14 @@ Image Stripe count - le64: length of appending data (8) - le64: image striping count +ImageMeta Key and Value +----------------------- + +- u8: 'M' +- le64: length of appending data (length of key + length of value + 4 * 2) +- string: image-meta key +- string: image-meta value + Final Record ~~~~~~~~~~~~ diff --git a/qa/workunits/rbd/import_export.sh b/qa/workunits/rbd/import_export.sh index 639f569d0bbed..aff0ad82c7063 100755 --- a/qa/workunits/rbd/import_export.sh +++ b/qa/workunits/rbd/import_export.sh @@ -79,10 +79,14 @@ if rbd help export | grep -q export-format; then 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 diff --git a/src/tools/rbd/Utils.h b/src/tools/rbd/Utils.h index d60a7b3e2cb67..fe7538315cc48 100644 --- a/src/tools/rbd/Utils.h +++ b/src/tools/rbd/Utils.h @@ -50,6 +50,7 @@ static const std::string RBD_DIFF_BANNER_V2 ("rbd diff v2\n"); #define RBD_EXPORT_IMAGE_FEATURES 'T' #define RBD_EXPORT_IMAGE_STRIPE_UNIT 'U' #define RBD_EXPORT_IMAGE_STRIPE_COUNT 'C' +#define RBD_EXPORT_IMAGE_META 'M' #define RBD_EXPORT_IMAGE_END 'E' enum SnapshotPresence { diff --git a/src/tools/rbd/action/Export.cc b/src/tools/rbd/action/Export.cc index bfda6980598a6..0fa0eb07ac16f 100644 --- a/src/tools/rbd/action/Export.cc +++ b/src/tools/rbd/action/Export.cc @@ -371,6 +371,8 @@ private: 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) { @@ -414,6 +416,45 @@ static int do_export_v2(librbd::Image& image, librbd::image_info_t &info, int fd ::encode(length, bl); ::encode(stripe_count, bl); + //retrieve metadata of image + std::map imagemetas; + std::string last_key; + bool more_results = true; + while (more_results) { + std::map 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::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); diff --git a/src/tools/rbd/action/Import.cc b/src/tools/rbd/action/Import.cc index 3c71785527057..988d2d1cfe09e 100644 --- a/src/tools/rbd/action/Import.cc +++ b/src/tools/rbd/action/Import.cc @@ -555,7 +555,46 @@ static int decode_and_set_image_option(int fd, uint64_t imageopt, librbd::ImageO 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 &imagemetas) +{ + int r = 0; + + //v1 format + if (import_format == 1) { + return r; + } + + for (std::map::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* 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* imagemetas) { // There is no header in v1 image. if (import_format == 1) { @@ -594,6 +633,8 @@ static int do_import_header(int fd, int import_format, uint64_t &size, librbd::I 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; @@ -743,6 +784,7 @@ static int do_import(librados::Rados &rados, librbd::RBD &rbd, int fd, r; struct stat stat_buf; utils::ProgressContext pc("Importing image", no_progress); + std::map imagemetas; assert(imgname); @@ -796,7 +838,7 @@ static int do_import(librados::Rados &rados, librbd::RBD &rbd, #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; @@ -814,6 +856,12 @@ static int do_import(librados::Rados &rados, librbd::RBD &rbd, 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 { -- 2.39.5