]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: apply pool level config overrides on image create
authorMykola Golub <mgolub@suse.com>
Sun, 26 Aug 2018 08:29:04 +0000 (11:29 +0300)
committerMykola Golub <mgolub@suse.com>
Thu, 20 Sep 2018 07:37:11 +0000 (10:37 +0300)
Signed-off-by: Mykola Golub <mgolub@suse.com>
src/librbd/image/CreateRequest.cc
src/librbd/image/CreateRequest.h

index 08abc6831f5ddd525e02be77339b1969eee40c8c..fac1bb884b0c2a78203a7e436711f90155dde673 100644 (file)
@@ -1,11 +1,14 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 
+#include <boost/algorithm/string/predicate.hpp>
+
 #include "librbd/image/CreateRequest.h"
 #include "common/dout.h"
 #include "common/errno.h"
 #include "cls/rbd/cls_rbd_client.h"
 #include "include/ceph_assert.h"
+#include "librbd/Features.h"
 #include "librbd/Utils.h"
 #include "common/ceph_context.h"
 #include "osdc/Striper.h"
@@ -30,6 +33,8 @@ using util::create_context_callback;
 
 namespace {
 
+const uint64_t MAX_METADATA_ITEMS = 128;
+
 int validate_features(CephContext *cct, uint64_t features,
                        bool force_non_primary) {
   if (features & ~RBD_FEATURES_ALL) {
@@ -121,8 +126,9 @@ CreateRequest<I>::CreateRequest(IoCtx &ioctx, const std::string &image_name,
                                 const std::string &primary_mirror_uuid,
                                 bool skip_mirror_enable,
                                 ContextWQ *op_work_queue, Context *on_finish)
-  : m_image_name(image_name), m_image_id(image_id),
-    m_size(size), m_non_primary_global_image_id(non_primary_global_image_id),
+  : m_image_name(image_name), m_image_id(image_id), m_size(size),
+    m_image_options(image_options),
+    m_non_primary_global_image_id(non_primary_global_image_id),
     m_primary_mirror_uuid(primary_mirror_uuid),
     m_skip_mirror_enable(skip_mirror_enable),
     m_op_work_queue(op_work_queue), m_on_finish(on_finish) {
@@ -133,16 +139,84 @@ CreateRequest<I>::CreateRequest(IoCtx &ioctx, const std::string &image_name,
   m_id_obj = util::id_obj_name(m_image_name);
   m_header_obj = util::header_name(m_image_id);
   m_objmap_name = ObjectMap<>::object_map_name(m_image_id, CEPH_NOSNAP);
+  m_force_non_primary = !non_primary_global_image_id.empty();
+}
+
+template<typename I>
+void CreateRequest<I>::send() {
+  ldout(m_cct, 20) << dendl;
+
+  get_pool_metadata();
+}
+
+template <typename I>
+void CreateRequest<I>::get_pool_metadata() {
+  ldout(m_cct, 20) << "start_key=" << m_last_metadata_key << dendl;
+
+  librados::ObjectReadOperation op;
+  cls_client::metadata_list_start(&op, m_last_metadata_key, MAX_METADATA_ITEMS);
+
+  using klass = CreateRequest<I>;
+  librados::AioCompletion *comp =
+    create_rados_callback<klass, &klass::handle_get_pool_metadata>(this);
+  m_outbl.clear();
+  m_io_ctx.aio_operate(RBD_INFO, comp, &op, &m_outbl);
+  comp->release();
+}
+
+template <typename I>
+void CreateRequest<I>::handle_get_pool_metadata(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
+
+  std::map<std::string, bufferlist> metadata;
+  if (r == 0) {
+    auto it = m_outbl.cbegin();
+    r = cls_client::metadata_list_finish(&it, &metadata);
+  }
+
+  if (r == -EOPNOTSUPP || r == -ENOENT) {
+    ldout(m_cct, 10) << "pool metadata not supported by OSD" << dendl;
+  } else if (r < 0) {
+    lderr(m_cct) << "failed to retrieve pool metadata: " << cpp_strerror(r)
+                 << dendl;
+    complete(r);
+    return;
+  }
+
+  if (!metadata.empty()) {
+    m_metadata.insert(metadata.begin(), metadata.end());
+    m_last_metadata_key = metadata.rbegin()->first;
+    if (boost::starts_with(m_last_metadata_key,
+                           ImageCtx::METADATA_CONF_PREFIX)) {
+      get_pool_metadata();
+      return;
+    }
+  }
 
-  if (image_options.get(RBD_IMAGE_OPTION_FEATURES, &m_features) != 0) {
-    m_features = util::get_rbd_default_features(m_cct);
+  ConfigProxy config(m_cct->_conf);
+  for (auto &it : m_metadata) {
+    std::string key;
+    if (!util::is_metadata_config_override(it.first, &key)) {
+      continue;
+    }
+    std::string value(it.second.c_str(), it.second.length());
+    r = config.set_val(key.c_str(), value);
+    if (r != 0) {
+      lderr(m_cct) << " failed to set config " << key << " with value "
+                   << it.second << ": " << cpp_strerror(r) << dendl;
+    }
+  }
+
+  if (m_image_options.get(RBD_IMAGE_OPTION_FEATURES, &m_features) != 0) {
+    m_features = librbd::rbd_features_from_string(
+      config.get_val<std::string>("rbd_default_features"), nullptr);
     m_negotiate_features = true;
   }
 
   uint64_t features_clear = 0;
   uint64_t features_set = 0;
-  image_options.get(RBD_IMAGE_OPTION_FEATURES_CLEAR, &features_clear);
-  image_options.get(RBD_IMAGE_OPTION_FEATURES_SET, &features_set);
+  m_image_options.get(RBD_IMAGE_OPTION_FEATURES_CLEAR, &features_clear);
+  m_image_options.get(RBD_IMAGE_OPTION_FEATURES_SET, &features_set);
 
   uint64_t features_conflict = features_clear & features_set;
   features_clear &= ~features_conflict;
@@ -154,31 +228,32 @@ CreateRequest<I>::CreateRequest(IoCtx &ioctx, const std::string &image_name,
       m_features |= RBD_FEATURE_FAST_DIFF;
   }
 
-  if (image_options.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &m_stripe_unit) != 0 ||
+  if (m_image_options.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &m_stripe_unit) != 0 ||
       m_stripe_unit == 0) {
-    m_stripe_unit = m_cct->_conf.get_val<Option::size_t>("rbd_default_stripe_unit");
+    m_stripe_unit = config.get_val<Option::size_t>("rbd_default_stripe_unit");
   }
-  if (image_options.get(RBD_IMAGE_OPTION_STRIPE_COUNT, &m_stripe_count) != 0 ||
-      m_stripe_count == 0) {
-    m_stripe_count = m_cct->_conf.get_val<uint64_t>("rbd_default_stripe_count");
+  if (m_image_options.get(RBD_IMAGE_OPTION_STRIPE_COUNT,
+                          &m_stripe_count) != 0 || m_stripe_count == 0) {
+    m_stripe_count = config.get_val<uint64_t>("rbd_default_stripe_count");
   }
-  if (get_image_option(image_options, RBD_IMAGE_OPTION_ORDER, &m_order) != 0 ||
-      m_order == 0) {
-    m_order = m_cct->_conf.get_val<int64_t>("rbd_default_order");
+  if (get_image_option(m_image_options, RBD_IMAGE_OPTION_ORDER,
+                       &m_order) != 0 || m_order == 0) {
+    m_order = config.get_val<int64_t>("rbd_default_order");
   }
-  if (get_image_option(image_options, RBD_IMAGE_OPTION_JOURNAL_ORDER,
-      &m_journal_order) != 0) {
-    m_journal_order = m_cct->_conf.get_val<uint64_t>("rbd_journal_order");
+  if (get_image_option(m_image_options, RBD_IMAGE_OPTION_JOURNAL_ORDER,
+                       &m_journal_order) != 0) {
+    m_journal_order = config.get_val<uint64_t>("rbd_journal_order");
   }
-  if (get_image_option(image_options, RBD_IMAGE_OPTION_JOURNAL_SPLAY_WIDTH,
+  if (get_image_option(m_image_options, RBD_IMAGE_OPTION_JOURNAL_SPLAY_WIDTH,
                        &m_journal_splay_width) != 0) {
-    m_journal_splay_width = m_cct->_conf.get_val<uint64_t>("rbd_journal_splay_width");
+    m_journal_splay_width = config.get_val<uint64_t>("rbd_journal_splay_width");
   }
-  if (image_options.get(RBD_IMAGE_OPTION_JOURNAL_POOL, &m_journal_pool) != 0) {
-    m_journal_pool = m_cct->_conf.get_val<std::string>("rbd_journal_pool");
+  if (m_image_options.get(RBD_IMAGE_OPTION_JOURNAL_POOL,
+                          &m_journal_pool) != 0) {
+    m_journal_pool = config.get_val<std::string>("rbd_journal_pool");
   }
-  if (image_options.get(RBD_IMAGE_OPTION_DATA_POOL, &m_data_pool) != 0) {
-    m_data_pool = m_cct->_conf.get_val<std::string>("rbd_default_data_pool");
+  if (m_image_options.get(RBD_IMAGE_OPTION_DATA_POOL, &m_data_pool) != 0) {
+    m_data_pool = config.get_val<std::string>("rbd_default_data_pool");
   }
 
   m_layout.object_size = 1ull << m_order;
@@ -190,9 +265,7 @@ CreateRequest<I>::CreateRequest(IoCtx &ioctx, const std::string &image_name,
     m_layout.stripe_count = m_stripe_count;
   }
 
-  m_force_non_primary = !non_primary_global_image_id.empty();
-
-  if (!m_data_pool.empty() && m_data_pool != ioctx.get_pool_name()) {
+  if (!m_data_pool.empty() && m_data_pool != m_io_ctx.get_pool_name()) {
     m_features |= RBD_FEATURE_DATA_POOL;
   } else {
     m_data_pool.clear();
@@ -218,13 +291,8 @@ CreateRequest<I>::CreateRequest(IoCtx &ioctx, const std::string &image_name,
                    << (uint64_t)m_journal_splay_width << ", "
                    << "journal_pool=" << m_journal_pool << ", "
                    << "data_pool=" << m_data_pool << dendl;
-}
 
-template<typename I>
-void CreateRequest<I>::send() {
-  ldout(m_cct, 20) << dendl;
-
-  int r = validate_features(m_cct, m_features, m_force_non_primary);
+  r = validate_features(m_cct, m_features, m_force_non_primary);
   if (r < 0) {
     complete(r);
     return;
@@ -248,11 +316,6 @@ void CreateRequest<I>::send() {
     return;
   }
 
-  validate_data_pool();
-}
-
-template <typename I>
-void CreateRequest<I>::validate_data_pool() {
   m_data_io_ctx = m_io_ctx;
   if ((m_features & RBD_FEATURE_DATA_POOL) != 0) {
     librados::Rados rados(m_io_ctx);
@@ -266,11 +329,16 @@ void CreateRequest<I>::validate_data_pool() {
     m_data_io_ctx.set_namespace(m_io_ctx.get_namespace());
   }
 
-  if (!m_cct->_conf.get_val<bool>("rbd_validate_pool")) {
+  if (!config.get_val<bool>("rbd_validate_pool")) {
     add_image_to_directory();
     return;
   }
 
+  validate_data_pool();
+}
+
+template <typename I>
+void CreateRequest<I>::validate_data_pool() {
   ldout(m_cct, 20) << dendl;
 
   using klass = CreateRequest<I>;
index 24aa0eb3f1b3c9dd500d8f5ec1744ed31152f45d..98f950cf9e86101161fab16efaac9f5b18b253ed 100644 (file)
@@ -51,12 +51,15 @@ private:
   /**
    * @verbatim
    *
-   *                                  <start> . . . . > . . . . .
-   *                                     |                      .
-   *                                     v                      .
-   *                               VALIDATE DATA POOL           v (pool validation
-   *                                     |                      .  disabled)
-   *                                     v                      .
+   *                                  <start>
+   *                                     |
+   *                                     v
+   *                               GET POOL METADATA
+   *                                     |
+   *                                     v
+   *                               VALIDATE DATA POOL . . . . . .
+   *                                     |                      . (pool validation
+   *                                     v                      .  disabled)
    * (error: bottom up)         ADD IMAGE TO DIRECTORY  < . . . .
    *  _______<_______                    |
    * |               |                   v
@@ -103,6 +106,7 @@ private:
   std::string m_image_name;
   std::string m_image_id;
   uint64_t m_size;
+  ImageOptions m_image_options;
   uint8_t m_order = 0;
   uint64_t m_features = 0;
   uint64_t m_stripe_unit = 0;
@@ -130,6 +134,12 @@ private:
   rbd_mirror_mode_t m_mirror_mode = RBD_MIRROR_MODE_DISABLED;
   cls::rbd::MirrorImage m_mirror_image_internal;
 
+  std::string m_last_metadata_key;
+  std::map<std::string, bufferlist> m_metadata;
+
+  void get_pool_metadata();
+  void handle_get_pool_metadata(int r);
+
   void validate_data_pool();
   void handle_validate_data_pool(int r);