From: Jason Dillaman Date: Mon, 19 Jun 2017 20:18:59 +0000 (-0400) Subject: mon: added new "osd pool application" commands X-Git-Tag: v12.1.2~224^2~16 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3514d6e53e1aacd2f2b5505f873d189f5b3f587d;p=ceph.git mon: added new "osd pool application" commands Signed-off-by: Jason Dillaman --- diff --git a/qa/workunits/cephtool/test.sh b/qa/workunits/cephtool/test.sh index 9586d81c0df..4c8c9e1f319 100755 --- a/qa/workunits/cephtool/test.sh +++ b/qa/workunits/cephtool/test.sh @@ -2318,6 +2318,42 @@ function test_mon_cephdf_commands() expect_false test $cal_raw_used_size != $raw_used_size } +function test_mon_pool_application() +{ + ceph osd pool create app_for_test 10 + + ceph osd pool application enable app_for_test rbd + expect_false ceph osd pool application enable app_for_test rgw + ceph osd pool application enable app_for_test rgw --yes-i-really-mean-it + ceph osd pool ls detail | grep "application rbd,rgw" + ceph osd pool ls detail --format=json | grep '"application_metadata":{"rbd":{},"rgw":{}}' + + expect_false ceph osd pool application set app_for_test cephfs key value + ceph osd pool application set app_for_test rbd key1 value1 + ceph osd pool application set app_for_test rbd key2 value2 + ceph osd pool application set app_for_test rgw key1 value1 + + ceph osd pool ls detail --format=json | grep '"application_metadata":{"rbd":{"key1":"value1","key2":"value2"},"rgw":{"key1":"value1"}}' + + ceph osd pool application rm app_for_test rgw key1 + ceph osd pool ls detail --format=json | grep '"application_metadata":{"rbd":{"key1":"value1","key2":"value2"},"rgw":{}}' + ceph osd pool application rm app_for_test rbd key2 + ceph osd pool ls detail --format=json | grep '"application_metadata":{"rbd":{"key1":"value1"},"rgw":{}}' + ceph osd pool application rm app_for_test rbd key1 + ceph osd pool ls detail --format=json | grep '"application_metadata":{"rbd":{},"rgw":{}}' + + expect_false ceph osd pool application disable app_for_test rgw + ceph osd pool application disable app_for_test rgw --yes-i-really-mean-it + ceph osd pool ls detail | grep "application rbd" + ceph osd pool ls detail --format=json | grep '"application_metadata":{"rbd":{}}' + + ceph osd pool application disable app_for_test rgw --yes-i-really-mean-it + ceph osd pool ls detail | grep -v "application " + ceph osd pool ls detail --format=json | grep '"application_metadata":{}' + + ceph osd pool rm app_for_test app_for_test --yes-i-really-really-mean-it +} + function test_mon_tell_help_command() { ceph tell mon.a help diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index e4df26b305a..2fef9c8d7c0 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -78,9 +78,19 @@ #include "json_spirit/json_spirit_reader.h" +#include + #define dout_subsys ceph_subsys_mon #define OSD_PG_CREATING_PREFIX "osd_pg_creating" +namespace { + +const uint32_t MAX_POOL_APPLICATIONS = 4; +const uint32_t MAX_POOL_APPLICATION_KEYS = 64; +const uint32_t MAX_POOL_APPLICATION_LENGTH = 128; + +} // anonymous namespace + void LastEpochClean::Lec::report(ps_t ps, epoch_t last_epoch_clean) { if (epoch_by_pg.size() <= ps) { @@ -6221,6 +6231,136 @@ int OSDMonitor::prepare_command_pool_set(map &cmdmap, return 0; } +int OSDMonitor::prepare_command_pool_application(const string &prefix, + map &cmdmap, + stringstream& ss) +{ + string pool_name; + cmd_getval(g_ceph_context, cmdmap, "pool", pool_name); + int64_t pool = osdmap.lookup_pg_pool_name(pool_name.c_str()); + if (pool < 0) { + ss << "unrecognized pool '" << pool_name << "'"; + return -ENOENT; + } + + pg_pool_t p = *osdmap.get_pg_pool(pool); + if (pending_inc.new_pools.count(pool)) { + p = pending_inc.new_pools[pool]; + } + + string app; + cmd_getval(g_ceph_context, cmdmap, "app", app); + bool app_exists = (p.application_metadata.count(app) > 0); + + if (boost::algorithm::ends_with(prefix, "enable")) { + if (app.empty()) { + ss << "application name must be provided"; + return -EINVAL; + } + + string force; + cmd_getval(g_ceph_context, cmdmap, "force", force); + + if (!app_exists && !p.application_metadata.empty() && + force != "--yes-i-really-mean-it") { + ss << "Are you SURE? Pool '" << pool_name << "' already has an enabled " + << "application; pass --yes-i-really-mean-it to proceed anyway"; + return -EPERM; + } + + if (!app_exists && p.application_metadata.size() >= MAX_POOL_APPLICATIONS) { + ss << "too many enabled applications on pool '" << pool_name << "'; " + << "max " << MAX_POOL_APPLICATIONS; + return -EINVAL; + } + + if (app.length() > MAX_POOL_APPLICATION_LENGTH) { + ss << "application name '" << app << "' too long; max length " + << MAX_POOL_APPLICATION_LENGTH; + return -EINVAL; + } + + if (!app_exists) { + p.application_metadata[app] = {}; + } + ss << "enabled application '" << app << "' on pool '" << pool_name << "'"; + + } else if (boost::algorithm::ends_with(prefix, "disable")) { + string force; + cmd_getval(g_ceph_context, cmdmap, "force", force); + + if (force != "--yes-i-really-mean-it") { + ss << "Are you SURE? Disabling an application within a pool might result " + << "in loss of application functionality; pass " + << "--yes-i-really-mean-it to proceed anyway"; + return -EPERM; + } + + p.application_metadata.erase(app); + ss << "disable application '" << app << "' on pool '" << pool_name << "'"; + + } else if (boost::algorithm::ends_with(prefix, "set")) { + if (!app_exists) { + ss << "application '" << app << "' is not enabled on pool '" << pool_name + << "'"; + return -ENOENT; + } + + string key; + cmd_getval(g_ceph_context, cmdmap, "key", key); + + if (key.empty()) { + ss << "key must be provided"; + return -EINVAL; + } + + auto &app_keys = p.application_metadata[app]; + if (app_keys.count(key) == 0 && + app_keys.size() >= MAX_POOL_APPLICATION_KEYS) { + ss << "too many keys set for application '" << app << "' on pool '" + << pool_name << "'; max " << MAX_POOL_APPLICATION_KEYS; + return -EINVAL; + } + + if (key.length() > MAX_POOL_APPLICATION_LENGTH) { + ss << "key '" << app << "' too long; max length " + << MAX_POOL_APPLICATION_LENGTH; + return -EINVAL; + } + + string value; + cmd_getval(g_ceph_context, cmdmap, "value", value); + if (value.length() > MAX_POOL_APPLICATION_LENGTH) { + ss << "value '" << value << "' too long; max length " + << MAX_POOL_APPLICATION_LENGTH; + return -EINVAL; + } + + p.application_metadata[app][key] = value; + ss << "set application '" << app << "' key '" << key << "' to '" + << value << "' on pool '" << pool_name << "'"; + } else if (boost::algorithm::ends_with(prefix, "rm")) { + if (!app_exists) { + ss << "application '" << app << "' is not enabled on pool '" << pool_name + << "'"; + return -ENOENT; + } + + string key; + cmd_getval(g_ceph_context, cmdmap, "key", key); + + p.application_metadata[app].erase(key); + ss << "removed application '" << app << "' key '" << key << "' on pool '" + << pool_name << "'"; + } else { + assert(false); + } + + p.last_change = pending_inc.epoch; + pending_inc.new_pools[pool] = p; + return 0; +} + int OSDMonitor::_prepare_command_osd_crush_remove( CrushWrapper &newcrush, int32_t id, @@ -10388,7 +10528,20 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs, get_last_committed() + 1)); return true; + } else if (prefix == "osd pool application enable" || + prefix == "osd pool application disable" || + prefix == "osd pool application set" || + prefix == "osd pool application rm") { + err = prepare_command_pool_application(prefix, cmdmap, ss); + if (err == -EAGAIN) + goto wait; + if (err < 0) + goto reply; + getline(ss, rs); + wait_for_finished_proposal( + op, new Monitor::C_Command(mon, op, 0, rs, get_last_committed() + 1)); + return true; } else if (prefix == "osd reweight-by-pg" || prefix == "osd reweight-by-utilization" || prefix == "osd test-reweight-by-pg" || diff --git a/src/mon/OSDMonitor.h b/src/mon/OSDMonitor.h index 9a944107970..e7a4c9f6836 100644 --- a/src/mon/OSDMonitor.h +++ b/src/mon/OSDMonitor.h @@ -514,6 +514,9 @@ public: int prepare_command_pool_set(map &cmdmap, stringstream& ss); + int prepare_command_pool_application(const string &prefix, + map &cmdmap, + stringstream& ss); bool handle_osd_timeouts(const utime_t &now, std::map &last_osd_report);