]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common: add 'enable experimental data corrupting features'
authorSage Weil <sage@redhat.com>
Mon, 29 Dec 2014 19:33:00 +0000 (11:33 -0800)
committerSage Weil <sage@redhat.com>
Mon, 29 Dec 2014 22:19:13 +0000 (14:19 -0800)
Signed-off-by: Sage Weil <sage@redhat.com>
src/common/ceph_context.cc
src/common/ceph_context.h
src/common/config_opts.h
src/test/common/test_context.cc

index 1ef517b10b693ed97598d8645553cad6f59f83a5..1c939b45d0a7fc31768a873740778fdeebe64343 100644 (file)
@@ -155,6 +155,55 @@ public:
 };
 
 
+// cct config watcher
+class CephContextObs : public md_config_obs_t {
+  CephContext *cct;
+
+public:
+  CephContextObs(CephContext *cct) : cct(cct) {}
+
+  const char** get_tracked_conf_keys() const {
+    static const char *KEYS[] = {
+      "enable_experimental_unrecoverable_data_corrupting_features",
+      NULL
+    };
+    return KEYS;
+  }
+
+  void handle_conf_change(const md_config_t *conf,
+                          const std::set <std::string> &changed) {
+    ceph_spin_lock(&cct->_feature_lock);
+    get_str_set(conf->enable_experimental_unrecoverable_data_corrupting_features,
+               cct->_experimental_features);
+    ceph_spin_unlock(&cct->_feature_lock);
+  }
+};
+
+bool CephContext::check_experimental_feature_enabled(std::string feat)
+{
+  ceph_spin_lock(&_feature_lock);
+  bool enabled = _experimental_features.count(feat);
+  ceph_spin_unlock(&_feature_lock);
+
+  if (enabled) {
+    lderr(this) << "WARNING: experimental feature '" << feat << "' is enabled" << dendl;
+    lderr(this) << "Please be aware that this feature is experimental, untested," << dendl;
+    lderr(this) << "unsupported, and may result in data corruption, data loss," << dendl;
+    lderr(this) << "and/or irreparable damage to your cluster.  Do not use" << dendl;
+    lderr(this) << "feature with important data." << dendl;
+  } else {
+    lderr(this) << "*** experimental feature '" << feat << "' is not enabled ***" << dendl;
+    lderr(this) << "This feature is marked as experimental, which means it" << dendl;
+    lderr(this) << " - is untested" << dendl;
+    lderr(this) << " - is unsupported" << dendl;
+    lderr(this) << " - may corrupt your data" << dendl;
+    lderr(this) << " - may break your cluster is an unrecoverable fashion" << dendl;
+    lderr(this) << "To enable this feature, add this to your ceph.conf:" << dendl;
+    lderr(this) << "  enable experimental unrecoverable data corrupting features = " << feat << dendl;
+  }
+  return enabled;
+}
+
 // perfcounter hooks
 
 class CephContextHook : public AdminSocketHook {
@@ -311,6 +360,7 @@ CephContext::CephContext(uint32_t module_type_)
 {
   ceph_spin_init(&_service_thread_lock);
   ceph_spin_init(&_associated_objs_lock);
+  ceph_spin_init(&_feature_lock);
 
   _log = new ceph::log::Log(&_conf->subsys);
   _log->start();
@@ -318,6 +368,9 @@ CephContext::CephContext(uint32_t module_type_)
   _log_obs = new LogObs(_log);
   _conf->add_observer(_log_obs);
 
+  _cct_obs = new CephContextObs(this);
+  _conf->add_observer(_cct_obs);
+
   _perf_counters_collection = new PerfCountersCollection(this);
   _admin_socket = new AdminSocket(this);
   _heartbeat_map = new HeartbeatMap(this);
@@ -385,6 +438,10 @@ CephContext::~CephContext()
   delete _log_obs;
   _log_obs = NULL;
 
+  _conf->remove_observer(_cct_obs);
+  delete _cct_obs;
+  _cct_obs = NULL;
+
   _log->stop();
   delete _log;
   _log = NULL;
@@ -392,6 +449,7 @@ CephContext::~CephContext()
   delete _conf;
   ceph_spin_destroy(&_service_thread_lock);
   ceph_spin_destroy(&_associated_objs_lock);
+  ceph_spin_destroy(&_feature_lock);
 
   delete _crypto_none;
   delete _crypto_aes;
index 7241c85583da3cf82443e757ce19347da7de84af..c332bdfa70bc34418f564530581a68366194cc6c 100644 (file)
@@ -18,6 +18,7 @@
 #include <iostream>
 #include <stdint.h>
 #include <string>
+#include <set>
 
 #include "include/buffer.h"
 #include "include/atomic.h"
@@ -30,6 +31,7 @@ class PerfCountersCollection;
 class md_config_obs_t;
 struct md_config_t;
 class CephContextHook;
+class CephContextObs;
 class CryptoNone;
 class CryptoAES;
 class CryptoHandler;
@@ -123,6 +125,9 @@ public:
    */
   CryptoHandler *get_crypto_handler(int type);
 
+  /// check if experimental feature is enable, and emit appropriate warnings
+  bool check_experimental_feature_enabled(std::string feature);
+
 private:
   CephContext(const CephContext &rhs);
   CephContext &operator=(const CephContext &rhs);
@@ -160,6 +165,13 @@ private:
   // crypto
   CryptoNone *_crypto_none;
   CryptoAES *_crypto_aes;
+
+  // experimental
+  CephContextObs *_cct_obs;
+  ceph_spinlock_t _feature_lock;
+  std::set<std::string> _experimental_features;
+
+  friend class CephContextObs;
 };
 
 #endif
index ff269670154ede448d3fb8868ed065a8cb75bfa1..23f62ab6161067ce59f5e969b6c351ade96134c3 100644 (file)
@@ -61,6 +61,8 @@ OPTION(mon_cluster_log_file, OPT_STR,
     "default=/var/log/ceph/$cluster.$channel.log cluster=/var/log/ceph/$cluster.log")
 OPTION(mon_cluster_log_file_level, OPT_STR, "info")
 
+OPTION(enable_experimental_unrecoverable_data_corrupting_features, OPT_STR, "")
+
 DEFAULT_SUBSYS(0, 5)
 SUBSYS(lockdep, 0, 1)
 SUBSYS(context, 0, 1)
index cb513051af84b0a6720731d6e56982f965f0a98a..0d0d2aaac5f8258db78fa383fe87a37ce0e9be92 100644 (file)
@@ -24,6 +24,7 @@
 #include "include/msgr.h"
 #include "common/ceph_context.h"
 #include "common/config.h"
+#include "log/Log.h"
 
 TEST(CephContext, do_command)
 {
@@ -52,6 +53,38 @@ TEST(CephContext, do_command)
   cct->put();
 }
 
+TEST(CephContext, experimental_features)
+{
+  CephContext *cct = (new CephContext(CEPH_ENTITY_TYPE_CLIENT))->get();
+
+  ASSERT_FALSE(cct->check_experimental_feature_enabled("foo"));
+  ASSERT_FALSE(cct->check_experimental_feature_enabled("bar"));
+  ASSERT_FALSE(cct->check_experimental_feature_enabled("baz"));
+
+  cct->_conf->set_val("enable_experimental_unrecoverable_data_corrupting_features",
+                     "foo,bar");
+  cct->_conf->apply_changes(&cout);
+  ASSERT_TRUE(cct->check_experimental_feature_enabled("foo"));
+  ASSERT_TRUE(cct->check_experimental_feature_enabled("bar"));
+  ASSERT_FALSE(cct->check_experimental_feature_enabled("baz"));
+
+  cct->_conf->set_val("enable_experimental_unrecoverable_data_corrupting_features",
+                     "foo bar");
+  cct->_conf->apply_changes(&cout);
+  ASSERT_TRUE(cct->check_experimental_feature_enabled("foo"));
+  ASSERT_TRUE(cct->check_experimental_feature_enabled("bar"));
+  ASSERT_FALSE(cct->check_experimental_feature_enabled("baz"));
+
+  cct->_conf->set_val("enable_experimental_unrecoverable_data_corrupting_features",
+                     "baz foo");
+  cct->_conf->apply_changes(&cout);
+  ASSERT_TRUE(cct->check_experimental_feature_enabled("foo"));
+  ASSERT_FALSE(cct->check_experimental_feature_enabled("bar"));
+  ASSERT_TRUE(cct->check_experimental_feature_enabled("baz"));
+
+  cct->_log->flush();
+}
+
 /*
  * Local Variables:
  * compile-command: "cd ../.. ;