From ac36b471a37aed0001d5d8003d895ddd2d8857d4 Mon Sep 17 00:00:00 2001 From: xie xingguo Date: Mon, 21 Aug 2017 17:04:27 +0800 Subject: [PATCH] mon/OSDMonitor: add location option for "crush add-bucket" command So we can combine "crush add-bucket" with "crush move" command, and hence avoid making two separate changes to the osdmap, and hence slow down map-epoch generation. Signed-off-by: xie xingguo --- qa/workunits/mon/crush_ops.sh | 8 +++++++ src/mon/MonCommands.h | 6 ++++-- src/mon/OSDMonitor.cc | 31 +++++++++++++++++++++++++-- src/test/pybind/test_ceph_argparse.py | 6 ++---- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/qa/workunits/mon/crush_ops.sh b/qa/workunits/mon/crush_ops.sh index 1ef6e5cc1ed..d720349c3d1 100755 --- a/qa/workunits/mon/crush_ops.sh +++ b/qa/workunits/mon/crush_ops.sh @@ -78,6 +78,14 @@ ceph osd tree | grep -c host1 | grep -q 0 expect_false ceph osd crush rm bar # not empty ceph osd crush unlink host2 +ceph osd crush add-bucket host-for-test host root=root-for-test rack=rack-for-test +ceph osd tree | grep host-for-test +ceph osd tree | grep rack-for-test +ceph osd tree | grep root-for-test +ceph osd crush rm host-for-test +ceph osd crush rm rack-for-test +ceph osd crush rm root-for-test + # reference foo and bar with a rule ceph osd crush rule create-simple foo-rule foo host firstn expect_false ceph osd crush rm foo diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index b0aeff8ed10..82df7de3bc3 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -524,8 +524,10 @@ COMMAND("osd crush set name=prior_version,type=CephInt,req=false", \ "osd", "rw", "cli,rest") COMMAND("osd crush add-bucket " \ "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ - "name=type,type=CephString", \ - "add no-parent (probably root) crush bucket of type ", \ + "name=type,type=CephString " \ + "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=],req=false", \ + "add no-parent (probably root) crush bucket of type " \ + "to location ", \ "osd", "rw", "cli,rest") COMMAND("osd crush rename-bucket " \ "name=srcname,type=CephString,goodchars=[A-Za-z0-9-_.] " \ diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 164899aed2e..0bb9b87da71 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -7578,8 +7578,16 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, } else if (prefix == "osd crush add-bucket") { // os crush add-bucket string name, typestr; + vector argvec; cmd_getval(g_ceph_context, cmdmap, "name", name); cmd_getval(g_ceph_context, cmdmap, "type", typestr); + cmd_getval(g_ceph_context, cmdmap, "args", argvec); + map loc; + if (!argvec.empty()) { + CrushWrapper::parse_loc_map(argvec, &loc); + dout(0) << "will create and move bucket '" << name + << "' to location " << loc << dendl; + } if (!_have_pending_crush() && _get_stable_crush().name_exists(name)) { @@ -7619,10 +7627,29 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, goto reply; } + if (!loc.empty()) { + if (!newcrush.check_item_loc(g_ceph_context, bucketno, loc, + (int *)NULL)) { + err = newcrush.move_bucket(g_ceph_context, bucketno, loc); + if (err < 0) { + ss << "error moving bucket '" << name << "' to location " << loc; + goto reply; + } + } else { + ss << "no need to move item id " << bucketno << " name '" << name + << "' to location " << loc << " in crush map"; + } + } + pending_inc.crush.clear(); newcrush.encode(pending_inc.crush, mon->get_quorum_con_features()); - ss << "added bucket " << name << " type " << typestr - << " to crush map"; + if (loc.empty()) { + ss << "added bucket " << name << " type " << typestr + << " to crush map"; + } else { + ss << "added bucket " << name << " type " << typestr + << " to location " << loc; + } goto update; } else if (prefix == "osd crush rename-bucket") { string srcname, dstname; diff --git a/src/test/pybind/test_ceph_argparse.py b/src/test/pybind/test_ceph_argparse.py index bc9f2d929fc..9759b87d73d 100755 --- a/src/test/pybind/test_ceph_argparse.py +++ b/src/test/pybind/test_ceph_argparse.py @@ -613,13 +613,11 @@ class TestOSD(TestArgparse): def test_crush_add_bucket(self): self.assert_valid_command(['osd', 'crush', 'add-bucket', 'name', 'type']) + self.assert_valid_command(['osd', 'crush', 'add-bucket', + 'name', 'type', 'root=foo-root', 'host=foo-host']) assert_equal({}, validate_command(sigdict, ['osd', 'crush'])) assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'add-bucket'])) - assert_equal({}, validate_command(sigdict, ['osd', 'crush', - 'add-bucket', 'name', - 'type', - 'toomany'])) assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'add-bucket', '^^^', 'type']))