ceph osd crush rm foo
ceph osd dump -f json-pretty | jq ".crush_node_flags" | expect_false grep 'foo'
+ # test device class flags
+ osd_0_device_class=$(ceph osd crush get-device-class osd.0)
+ ceph osd set-group noup $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noup'
+ ceph osd set-group noup,nodown $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noup'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'nodown'
+ ceph osd set-group noup,nodown,noin $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noup'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'nodown'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noin'
+ ceph osd set-group noup,nodown,noin,noout $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noup'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'nodown'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noin'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noout'
+
+ ceph osd unset-group noup $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | expect_false grep 'noup'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'nodown'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noin'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noout'
+ ceph osd unset-group noup,nodown $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | expect_false grep 'noup\|nodown'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noin'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noout'
+ ceph osd unset-group noup,nodown,noin $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | expect_false grep 'noup\|nodown\|noin'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noout'
+ ceph osd unset-group noup,nodown,noin,noout $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | expect_false grep 'noup\|nodown\|noin\|noout'
+
+ ceph osd set-group noin,noout $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noin'
+ ceph osd dump -f json-pretty | jq ".device_class_flags.$osd_0_device_class" | grep 'noout'
+ ceph osd unset-group noin,noout $osd_0_device_class
+ ceph osd dump -f json-pretty | jq ".crush_node_flags" | expect_false grep $osd_0_device_class
+
# make sure mark out preserves weight
ceph osd reweight osd.0 .5
ceph osd dump | grep ^osd.0 | grep 'weight 0.5'
return 0;
return get_class_name(p->second);
}
+ int get_item_class_id(int t) const {
+ auto p = class_map.find(t);
+ if (p == class_map.end())
+ return -ENOENT;
+ return p->second;
+ }
int set_item_class(int i, const string& name) {
if (!is_valid_crush_name(name))
return -EINVAL;
return false;
}
+ if (auto class_id = osdmap.crush->get_item_class_id(i); class_id >= 0 &&
+ (osdmap.get_device_class_flags(class_id) & CEPH_OSD_NODOWN)) {
+ dout(5) << __func__ << " osd." << i
+ << " is marked as nodown via device class, "
+ << "will not mark it down" << dendl;
+ return false;
+ }
+
int num_osds = osdmap.get_num_osds();
if (num_osds == 0) {
dout(5) << __func__ << " no osds" << dendl;
return false;
}
+ if (auto class_id = osdmap.crush->get_item_class_id(i); class_id >= 0 &&
+ (osdmap.get_device_class_flags(class_id) & CEPH_OSD_NOUP)) {
+ dout(5) << __func__ << " osd." << i
+ << " is marked as noup via device class, "
+ << "will not mark it up" << dendl;
+ return false;
+ }
+
return true;
}
return false;
}
+ if (auto class_id = osdmap.crush->get_item_class_id(i); class_id >= 0 &&
+ (osdmap.get_device_class_flags(class_id) & CEPH_OSD_NOOUT)) {
+ dout(5) << __func__ << " osd." << i
+ << " is marked as noout via device class, "
+ << "will not mark it out" << dendl;
+ return false;
+ }
+
int num_osds = osdmap.get_num_osds();
if (num_osds == 0) {
dout(5) << __func__ << " no osds" << dendl;
return false;
}
+ if (auto class_id = osdmap.crush->get_item_class_id(i); class_id >= 0 &&
+ (osdmap.get_device_class_flags(class_id) & CEPH_OSD_NOIN)) {
+ dout(5) << __func__ << " osd." << i
+ << " is marked as noin via device class, "
+ << "will not mark it in" << dendl;
+ return false;
+ }
+
return true;
}
}
set<int> osds;
set<int> crush_nodes;
+ set<int> device_classes;
for (auto& w : who) {
if (w == "any" || w == "all" || w == "*") {
osdmap.get_all_osds(osds);
osds.insert(osd);
} else if (osdmap.crush->name_exists(w)) {
crush_nodes.insert(osdmap.crush->get_item_id(w));
+ } else if (osdmap.crush->class_exists(w)) {
+ device_classes.insert(osdmap.crush->get_class_id(w));
} else {
- ss << "unable to parse osd id or crush node:\"" << w << "\". ";
+ ss << "unable to parse osd id or crush node or device class: "
+ << "\"" << w << "\". ";
}
}
- if (osds.empty() && crush_nodes.empty()) {
+ if (osds.empty() && crush_nodes.empty() && device_classes.empty()) {
// ss has reason for failure
err = -EINVAL;
goto reply;
}
any = true;
}
+ for (auto& id : device_classes) {
+ auto old_flags = osdmap.get_device_class_flags(id);
+ auto& pending_flags = pending_inc.new_device_class_flags[id];
+ pending_flags |= old_flags;
+ if (do_set) {
+ pending_flags |= flags;
+ } else {
+ pending_flags &= ~flags;
+ }
+ any = true;
+ }
if (any) {
getline(ss, rs);
wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, err, rs,
}
{
- uint8_t target_v = 8;
+ uint8_t target_v = 9;
if (!HAVE_FEATURE(features, SERVER_LUMINOUS)) {
target_v = 2;
} else if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) {
if (target_v >= 8) {
encode(new_crush_node_flags, bl);
}
+ if (target_v >= 9) {
+ encode(new_device_class_flags, bl);
+ }
ENCODE_FINISH(bl); // osd-only data
}
}
{
- DECODE_START(8, bl); // extended, osd-only data
+ DECODE_START(9, bl); // extended, osd-only data
decode(new_hb_back_up, bl);
decode(new_up_thru, bl);
decode(new_last_clean_interval, bl);
if (struct_v >= 8) {
decode(new_crush_node_flags, bl);
}
+ if (struct_v >= 9) {
+ decode(new_device_class_flags, bl);
+ }
DECODE_FINISH(bl); // osd-only data
}
f->close_section();
}
f->close_section();
+ f->open_array_section("new_device_class_flags");
+ for (auto& i : new_device_class_flags) {
+ f->open_object_section("device_class");
+ f->dump_int("id", i.first);
+ set<string> st;
+ calc_state_set(i.second, st);
+ for (auto& j : st) {
+ f->dump_string("flag", j);
+ }
+ f->close_section();
+ }
+ f->close_section();
f->close_section();
}
}
}
+ for (auto& i : inc.new_device_class_flags) {
+ if (i.second) {
+ device_class_flags[i.first] = i.second;
+ } else {
+ device_class_flags.erase(i.first);
+ }
+ }
+
// cluster snapshot?
if (inc.cluster_snapshot.length()) {
cluster_snapshot = inc.cluster_snapshot;
// it in the canonical version, don't change it.
++crush_version;
}
+ for (auto it = device_class_flags.begin();
+ it != device_class_flags.end();) {
+ const char* class_name = crush->get_class_name(it->first);
+ if (!class_name) // device class is gone
+ it = device_class_flags.erase(it);
+ else
+ it++;
+ }
}
calc_num_osds();
{
// NOTE: any new encoding dependencies must be reflected by
// SIGNIFICANT_FEATURES
- uint8_t target_v = 8;
+ uint8_t target_v = 9;
if (!HAVE_FEATURE(features, SERVER_LUMINOUS)) {
target_v = 1;
} else if (!HAVE_FEATURE(features, SERVER_MIMIC)) {
if (target_v >= 8) {
encode(crush_node_flags, bl);
}
+ if (target_v >= 9) {
+ encode(device_class_flags, bl);
+ }
ENCODE_FINISH(bl); // osd-only data
}
}
{
- DECODE_START(8, bl); // extended, osd-only data
+ DECODE_START(9, bl); // extended, osd-only data
decode(osd_addrs->hb_back_addrs, bl);
decode(osd_info, bl);
decode(blacklist, bl);
} else {
crush_node_flags.clear();
}
+ if (struct_v >= 9) {
+ decode(device_class_flags, bl);
+ } else {
+ device_class_flags.clear();
+ }
DECODE_FINISH(bl); // osd-only data
}
f->close_section();
}
f->close_section();
+ f->open_object_section("device_class_flags");
+ for (auto& i : device_class_flags) {
+ const char* class_name = crush->get_class_name(i.first);
+ string s = class_name ? class_name : stringify(i.first);
+ f->open_array_section(s.c_str());
+ set<string> st;
+ calc_state_set(i.second, st);
+ for (auto& j : st) {
+ f->dump_string("flag", j);
+ }
+ f->close_section();
+ }
+ f->close_section();
}
void OSDMap::generate_test_instances(list<OSDMap*>& o)
detail.push_back(ss.str());
}
}
+ for (auto& i : device_class_flags) {
+ const char* class_name = crush->get_class_name(i.first);
+ if (i.second && class_name) {
+ ostringstream ss;
+ set<string> states;
+ OSDMap::calc_state_set(i.second, states);
+ ss << "device class '" << class_name << "' has flags " << states;
+ detail.push_back(ss.str());
+ }
+ }
if (!detail.empty()) {
ostringstream ss;
- ss << detail.size() << " OSDs or CRUSH nodes have {NOUP,NODOWN,NOIN,NOOUT} flags set";
+ ss << detail.size() << " OSDs or CRUSH {nodes, device-classes} have {NOUP,NODOWN,NOIN,NOOUT} flags set";
auto& d = checks->add("OSD_FLAGS", HEALTH_WARN, ss.str());
d.detail.swap(detail);
}
flags = it->second;
return flags;
}
+
+unsigned OSDMap::get_device_class_flags(int id) const
+{
+ unsigned flags = 0;
+ auto it = device_class_flags.find(id);
+ if (it != device_class_flags.end())
+ flags = it->second;
+ return flags;
+}
mempool::osdmap::map<int64_t, snap_interval_set_t> new_purged_snaps;
mempool::osdmap::map<int32_t,uint32_t> new_crush_node_flags;
+ mempool::osdmap::map<int32_t,uint32_t> new_device_class_flags;
string cluster_snapshot;
vector<uint32_t> osd_state;
mempool::osdmap::map<int32_t,uint32_t> crush_node_flags; // crush node -> CEPH_OSD_* flags
+ mempool::osdmap::map<int32_t,uint32_t> device_class_flags; // device class -> CEPH_OSD_* flags
utime_t last_up_change, last_in_change;
unsigned get_osd_crush_node_flags(int osd) const;
unsigned get_crush_node_flags(int id) const;
+ unsigned get_device_class_flags(int id) const;
bool is_noup(int osd) const {
return exists(osd) && (osd_state[osd] & CEPH_OSD_NOUP);