ceph osd crush dump | grep -q '~asdf' && return 1
ceph osd crush tree --show-shadow | grep -q '~asdf' && return 1
+ # test 'class rm' automatically recycles shadow trees
+ ceph osd crush set-device-class asdf 0 1 2 || return 1
+ ceph osd tree | grep -q 'asdf' || return 1
+ ceph osd crush dump | grep -q '~asdf' || return 1
+ ceph osd crush tree --show-shadow | grep -q '~asdf' || return 1
+ ceph osd crush class ls | grep -q 'asdf' || return 1
+ ceph osd crush class rm asdf || return 1
+ ceph osd tree | grep -q 'asdf' && return 1
+ ceph osd crush dump | grep -q '~asdf' && return 1
+ ceph osd crush tree --show-shadow | grep -q '~asdf' && return 1
+ ceph osd crush class ls | grep -q 'asdf' && return 1
+
ceph osd crush set-device-class abc osd.2 || return 1
ceph osd crush move osd.2 root=foo rack=foo-rack host=foo-host || return 1
out=`ceph osd tree |awk '$1 == 2 && $2 == "abc" {print $0}'`
goto reply;
}
- err = newcrush.remove_class_name(device_class);
- if (err < 0) {
- ss << "class '" << device_class << "' cannot be removed '"
- << cpp_strerror(err) << "'";
- goto reply;
+ set<int> osds;
+ newcrush.get_devices_by_class(device_class, &osds);
+ for (auto& p: osds) {
+ err = newcrush.remove_device_class(g_ceph_context, p, &ss);
+ if (err < 0) {
+ // ss has reason for failure
+ goto reply;
+ }
+ }
+
+ if (osds.empty()) {
+ // empty class, remove directly
+ err = newcrush.remove_class_name(device_class);
+ if (err < 0) {
+ ss << "class '" << device_class << "' cannot be removed '"
+ << cpp_strerror(err) << "'";
+ goto reply;
+ }
}
pending_inc.crush.clear();