summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-08-08 22:18:16 -0700
committerSage Weil <sage@inktank.com>2013-08-08 22:18:16 -0700
commit7e285149fb2616d59f5f70d722a28d8a0bbfcdb7 (patch)
tree443d66b4b318b10df6f91238344d70f7e1250c7c
parent469d30b851584b90c7de4e36372a49c02f9a2043 (diff)
parentb2515b9e0b1e5e709716308a515026b3e6ff23b5 (diff)
downloadceph-7e285149fb2616d59f5f70d722a28d8a0bbfcdb7.tar.gz
Merge remote-tracking branch 'gh/next'
-rwxr-xr-xqa/workunits/cephtool/test.sh55
-rwxr-xr-xqa/workunits/cephtool/test_daemon.sh3
-rwxr-xr-xqa/workunits/rest/test.py22
-rw-r--r--src/auth/KeyRing.cc3
-rwxr-xr-xsrc/ceph.in22
-rw-r--r--src/client/Client.cc3
-rw-r--r--src/common/cmdparse.cc6
-rw-r--r--src/common/cmdparse.h6
-rw-r--r--src/common/config_opts.h11
-rw-r--r--src/include/buffer.h3
-rw-r--r--src/mon/AuthMonitor.cc1
-rw-r--r--src/mon/MonCommands.h9
-rw-r--r--src/mon/Monitor.cc7
-rw-r--r--src/mon/OSDMonitor.cc17
-rw-r--r--src/mon/PGMap.cc9
-rw-r--r--src/mon/PGMap.h2
-rw-r--r--src/mon/PGMonitor.cc6
-rw-r--r--src/osd/OSD.cc20
-rw-r--r--src/osd/OSD.h10
-rw-r--r--src/osd/OpRequest.cc16
-rw-r--r--src/osd/OpRequest.h12
-rw-r--r--src/osd/PG.cc9
-rw-r--r--src/osd/PG.h14
-rw-r--r--src/osd/ReplicatedPG.cc42
-rw-r--r--src/osd/ReplicatedPG.h20
-rw-r--r--src/osd/osd_types.cc13
-rw-r--r--src/osd/osd_types.h1
-rw-r--r--src/osdc/Objecter.cc3
-rw-r--r--src/pybind/ceph_argparse.py161
-rwxr-xr-xsrc/pybind/ceph_rest_api.py8
-rw-r--r--src/rgw/rgw_admin.cc2
-rw-r--r--src/rgw/rgw_main.cc22
-rw-r--r--src/rgw/rgw_rados.cc2
-rw-r--r--src/rgw/rgw_rest.cc5
-rw-r--r--src/rgw/rgw_rest.h8
35 files changed, 386 insertions, 167 deletions
diff --git a/qa/workunits/cephtool/test.sh b/qa/workunits/cephtool/test.sh
index d759d675276..7915e48a6ed 100755
--- a/qa/workunits/cephtool/test.sh
+++ b/qa/workunits/cephtool/test.sh
@@ -25,6 +25,29 @@ expect_false()
if "$@"; then return 1; else return 0; fi
}
+TMPFILE=/tmp/test_invalid.$$
+trap "rm $TMPFILE" 0
+
+function check_response()
+{
+ retcode=$1
+ expected_retcode=$2
+ expected_stderr_string=$3
+ if [ $1 != $2 ] ; then
+ echo "return code invalid: got $1, expected $2" >&2
+ exit 1
+ fi
+
+ if ! grep "$3" $TMPFILE >/dev/null 2>&1 ; then
+ echo "Didn't find $3 in stderr output" >&2
+ echo "Stderr: " >&2
+ cat $TMPFILE >&2
+ exit 1
+ fi
+}
+
+
+
#
# Assumes there are at least 3 MDSes and two OSDs
#
@@ -132,6 +155,14 @@ ceph osd scrub 0
ceph osd deep-scrub 0
ceph osd repair 0
+for f in noup nodown noin noout noscrub nodeep-scrub nobackfill norecover
+do
+ ceph osd set $f
+ ceph osd unset $f
+done
+expect_false ceph osd set bogus
+expect_false ceph osd unset bogus
+
ceph osd set noup
ceph osd down 0
ceph osd dump | grep 'osd.0 down'
@@ -204,6 +235,14 @@ ceph pg debug unfound_objects_exist
ceph pg debug degraded_pgs_exist
ceph pg deep-scrub 0.0
ceph pg dump
+ceph pg dump pgs_brief --format=json
+ceph pg dump pgs --format=json
+ceph pg dump pools --format=json
+ceph pg dump osds --format=json
+ceph pg dump sum --format=json
+ceph pg dump all --format=json
+ceph pg dump pgs_brief osds --format=json
+ceph pg dump pools osds pgs_brief --format=json
ceph pg dump_json
ceph pg dump_pools_json
ceph pg dump_stuck inactive
@@ -225,6 +264,8 @@ ceph pg set_nearfull_ratio 0.90
ceph pg dump --format=plain | grep '^nearfull_ratio 0.9'
ceph pg set_nearfull_ratio 0.85
ceph pg stat | grep 'pgs:'
+ceph pg 0.0 query
+ceph tell 0.0 query
ceph quorum enter
ceph quorum_status
ceph report | grep osd_stats
@@ -255,4 +296,18 @@ ceph osd pool get rbd crush_ruleset | grep 'crush_ruleset: 2'
ceph osd thrash 10
+set +e
+
+# expect error about missing 'pool' argument
+ceph osd map 2>$TMPFILE; check_response $? 22 'pool'
+
+# expect error about unused argument foo
+ceph osd ls foo 2>$TMPFILE; check_response $? 22 'unused'
+
+# expect "not in range" for invalid full ratio
+ceph pg set_full_ratio 95 2>$TMPFILE; check_response $? 22 'not in range'
+
+# expect "not in range" for invalid overload percentage
+ceph osd reweight-by-utilization 80 2>$TMPFILE; check_response $? 22 'not in range'
+
echo OK
diff --git a/qa/workunits/cephtool/test_daemon.sh b/qa/workunits/cephtool/test_daemon.sh
index 8d2bd27f700..f598708d019 100755
--- a/qa/workunits/cephtool/test_daemon.sh
+++ b/qa/workunits/cephtool/test_daemon.sh
@@ -24,4 +24,7 @@ new_ms=$(sudo ceph daemon mon.a config get debug_ms | grep debug_ms | \
sed -e 's/.*: //' -e 's/["\}\\]//g')
[ "$new_ms" = "$old_ms" ]
+# unregistered/non-existent command
+expect_false sudo ceph daemon mon.a bogus_command_blah foo
+
echo OK
diff --git a/qa/workunits/rest/test.py b/qa/workunits/rest/test.py
index 3fcf3fd75fb..c40ec916016 100755
--- a/qa/workunits/rest/test.py
+++ b/qa/workunits/rest/test.py
@@ -32,7 +32,7 @@ def expect_nofail(url, method, respcode, contenttype, extra_hdrs=None,
f = fdict[method.lower()]
r = f(BASEURL + '/' + url, headers=extra_hdrs, data=data)
- print '{0}: {1} {2}'.format(url, contenttype, r.status_code)
+ print '{0} {1}: {2} {3}'.format(method, url, contenttype, r.status_code)
if r.status_code != respcode:
return 'expected {0}, got {1}'.format(respcode, r.status_code), r
@@ -330,10 +330,7 @@ if __name__ == '__main__':
r = expect('osd/ls', 'GET', 200, 'json', JSONHDR)
for osdid in r.myjson['output']:
- # XXX no tell yet
- # expect('tell?target=osd.{0}&args=version'.format(osdid), 'PUT',
- # 200, '')
- print >> sys.stderr, 'would be telling osd.{0} version'.format(osdid)
+ expect('tell/osd.{0}/version'.format(osdid), 'GET', 200, '')
expect('pg/debug?debugop=unfound_objects_exist', 'GET', 200, '')
expect('pg/debug?debugop=degraded_pgs_exist', 'GET', 200, '')
@@ -378,6 +375,7 @@ if __name__ == '__main__':
r = expect('pg/stat', 'GET', 200, 'xml', XMLHDR)
assert(r.tree.find('output/pg_map/pg_stats_sum') is not None)
+ expect('tell/0.0/query', 'GET', 200, 'json', JSONHDR)
expect('quorum?quorumcmd=enter', 'PUT', 200, 'json', JSONHDR)
expect('quorum?quorumcmd=enter', 'PUT', 200, 'xml', XMLHDR)
expect('quorum_status', 'GET', 200, 'json', JSONHDR)
@@ -394,15 +392,13 @@ if __name__ == '__main__':
r = expect('status', 'GET', 200, 'xml', XMLHDR)
assert(r.tree.find('output/status/osdmap') is not None)
- # XXX tell not implemented yet
- # r = expect('tell?target=osd.0&args=version', 'PUT', 200, '')
- # assert('ceph version' in r.content)
- # expect('tell?target=osd.999&args=version', 'PUT', 400, '')
- # expect('tell?target=osd.foo&args=version', 'PUT', 400, '')
+ r = expect('tell/osd.0/version', 'GET', 200, '')
+ assert('ceph version' in r.content)
+ expect('tell/osd.999/version', 'GET', 400, '')
+ expect('tell/osd.foo/version', 'GET', 400, '')
-
- # r = expect('tell?target=osd.0&args=dump_get_recovery_stats', 'PUT', '200', '')
- # assert('Started' in r.content)
+ r = expect('tell/osd.0/dump_pg_recovery_stats', 'GET', 200, '')
+ assert('Started' in r.content)
expect('osd/reweight?id=0&weight=0.9', 'PUT', 200, '')
expect('osd/reweight?id=0&weight=-1', 'PUT', 400, '')
diff --git a/src/auth/KeyRing.cc b/src/auth/KeyRing.cc
index 56655392bae..5a8b2288e6a 100644
--- a/src/auth/KeyRing.cc
+++ b/src/auth/KeyRing.cc
@@ -157,8 +157,7 @@ void KeyRing::encode_formatted(string label, Formatter *f, bufferlist& bl)
f->close_section(); /* auth_entities */
}
f->close_section(); /* auth_dump */
- f->flush(os);
- bl.append(os.str());
+ f->flush(bl);
}
void KeyRing::decode_plaintext(bufferlist::iterator& bli)
diff --git a/src/ceph.in b/src/ceph.in
index 0ae8df77cd7..144704ee05b 100755
--- a/src/ceph.in
+++ b/src/ceph.in
@@ -54,7 +54,10 @@ import string
import struct
import subprocess
-from ceph_argparse import *
+from ceph_argparse import \
+ concise_sig, descsort, parse_json_funcsigs, \
+ matchnum, validate_command, find_cmd_target, \
+ send_command, json_command
# just a couple of globals
@@ -318,7 +321,7 @@ def admin_socket(asok_path, cmd, format=''):
sigdict = parse_json_funcsigs(cmd_json, 'cli')
valid_dict = validate_command(sigdict, cmd)
if not valid_dict:
- return -errno.EINVAL
+ raise RuntimeError('invalid command')
if format:
valid_dict['format'] = format
@@ -393,10 +396,15 @@ def new_style_command(parsed_args, cmdargs, target, sigdict, inbuf, verbose):
target=target,
argdict=valid_dict)
if ret:
- sys.stderr.write('Error {0}: {1}'.format(ret, outs))
- return ret, '', outs
+ ret = abs(ret)
+ print >> sys.stderr, \
+ 'Error: {0} {1}'.format(ret, errno.errorcode[ret])
+ if outbuf:
+ print outbuf
+ if outs:
+ print >> sys.stderr, 'Status:\n', outs
else:
- print "invalid command"
+ print >> sys.stderr, "Invalid command"
if verbose:
print >> sys.stderr, "Submitting command ", valid_dict
@@ -512,6 +520,7 @@ def main():
print admin_socket(childargs[1], childargs[2:], format)
except Exception as e:
print >> sys.stderr, 'admin_socket: {0}'.format(e)
+ return errno.EINVAL
return 0
else:
# try resolve daemon name
@@ -520,10 +529,11 @@ def main():
print admin_socket(path, childargs[2:], format)
except Exception as e:
print >> sys.stderr, 'admin_socket: {0}'.format(e)
+ return errno.EINVAL
return 0
else:
print >> sys.stderr, 'Daemon requires at least 2 arguments'
- return 1
+ return errno.EINVAL
# handle any 'generic' ceph arguments that we didn't parse here
global cluster_handle
diff --git a/src/client/Client.cc b/src/client/Client.cc
index af465cb78bc..4b10cf5c1ba 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -117,8 +117,7 @@ bool Client::CommandHook::call(std::string command, cmdmap_t& cmdmap,
else
assert(0 == "bad command registered");
m_client->client_lock.Unlock();
- f->flush(ss);
- out.append(ss);
+ f->flush(out);
delete f;
return true;
}
diff --git a/src/common/cmdparse.cc b/src/common/cmdparse.cc
index 370591cb3bb..16c62349c40 100644
--- a/src/common/cmdparse.cc
+++ b/src/common/cmdparse.cc
@@ -27,7 +27,7 @@ using namespace std;
*/
void
-dump_cmd_to_json(JSONFormatter *f, const string& cmd)
+dump_cmd_to_json(Formatter *f, const string& cmd)
{
// put whole command signature in an already-opened container
// elements are: "name", meaning "the typeless name that means a literal"
@@ -77,7 +77,7 @@ dump_cmd_to_json(JSONFormatter *f, const string& cmd)
}
void
-dump_cmd_and_help_to_json(JSONFormatter *jf,
+dump_cmd_and_help_to_json(Formatter *jf,
const string& secname,
const string& cmdsig,
const string& helptext)
@@ -91,7 +91,7 @@ dump_cmd_and_help_to_json(JSONFormatter *jf,
}
void
-dump_cmddesc_to_json(JSONFormatter *jf,
+dump_cmddesc_to_json(Formatter *jf,
const string& secname,
const string& cmdsig,
const string& helptext,
diff --git a/src/common/cmdparse.h b/src/common/cmdparse.h
index 58c66b46052..10e43ab0abe 100644
--- a/src/common/cmdparse.h
+++ b/src/common/cmdparse.h
@@ -20,12 +20,12 @@ class CephContext;
typedef boost::variant<std::string, bool, int64_t, double, std::vector<std::string> > cmd_vartype;
typedef std::map<std::string, cmd_vartype> cmdmap_t;
-void dump_cmd_to_json(ceph::JSONFormatter *f, const std::string& cmd);
-void dump_cmd_and_help_to_json(ceph::JSONFormatter *f,
+void dump_cmd_to_json(ceph::Formatter *f, const std::string& cmd);
+void dump_cmd_and_help_to_json(ceph::Formatter *f,
const std::string& secname,
const std::string& cmd,
const std::string& helptext);
-void dump_cmddesc_to_json(JSONFormatter *jf,
+void dump_cmddesc_to_json(ceph::Formatter *jf,
const std::string& secname,
const std::string& cmdsig,
const std::string& helptext,
diff --git a/src/common/config_opts.h b/src/common/config_opts.h
index 1c7a917602a..f67d0d1237d 100644
--- a/src/common/config_opts.h
+++ b/src/common/config_opts.h
@@ -426,7 +426,8 @@ OPTION(osd_default_data_pool_replay_window, OPT_INT, 45)
OPTION(osd_preserve_trimmed_log, OPT_BOOL, false)
OPTION(osd_auto_mark_unfound_lost, OPT_BOOL, false)
OPTION(osd_recovery_delay_start, OPT_FLOAT, 0)
-OPTION(osd_recovery_max_active, OPT_INT, 5)
+OPTION(osd_recovery_max_active, OPT_INT, 60)
+OPTION(osd_recovery_max_single_start, OPT_INT, 10)
OPTION(osd_recovery_max_chunk, OPT_U64, 8<<20) // max size of push chunk
OPTION(osd_push_per_object_cost, OPT_U64, 1000) // push cost per object
OPTION(osd_max_push_cost, OPT_U64, 8<<20) // max size of push message
@@ -489,9 +490,13 @@ OPTION(osd_leveldb_log, OPT_STR, "") // enable OSD leveldb log file
* osd_client_op_priority/osd_recovery_op_priority determines the ratio of
* available io between client and recovery. Each option may be set between
* 1..63.
+ *
+ * osd_recovery_op_warn_multiple scales the normal warning threshhold,
+ * osd_op_complaint_time, so that slow recovery ops won't cause noise
*/
-OPTION(osd_client_op_priority, OPT_INT, 63)
-OPTION(osd_recovery_op_priority, OPT_INT, 10)
+OPTION(osd_client_op_priority, OPT_U32, 63)
+OPTION(osd_recovery_op_priority, OPT_U32, 10)
+OPTION(osd_recovery_op_warn_multiple, OPT_U32, 16)
// Max time to wait between notifying mon of shutdown and shutting down
OPTION(osd_mon_shutdown_timeout, OPT_DOUBLE, 5)
diff --git a/src/include/buffer.h b/src/include/buffer.h
index 99c1985e616..8c4dfb56e17 100644
--- a/src/include/buffer.h
+++ b/src/include/buffer.h
@@ -16,17 +16,18 @@
#define CEPH_BUFFER_H
#if defined(__linux__)
+#include <stdlib.h>
#include <linux/types.h>
#elif defined(__FreeBSD__)
#include <sys/types.h>
#include "include/inttypes.h"
+#include <stdlib.h>
#endif
#ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 600
#endif
-#include <stdlib.h>
#include <stdio.h>
#ifdef DARWIN
diff --git a/src/mon/AuthMonitor.cc b/src/mon/AuthMonitor.cc
index 629451b5eac..f165b8c9fc7 100644
--- a/src/mon/AuthMonitor.cc
+++ b/src/mon/AuthMonitor.cc
@@ -626,7 +626,6 @@ bool AuthMonitor::preprocess_command(MMonCommand *m)
} else if (prefix == "auth list") {
if (f) {
mon->key_server.encode_formatted("auth", f.get(), rdata);
- f->flush(rdata);
} else {
mon->key_server.encode_plaintext(rdata);
if (rdata.length() > 0)
diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h
index 0980893bf9b..8e9c2bb333b 100644
--- a/src/mon/MonCommands.h
+++ b/src/mon/MonCommands.h
@@ -111,7 +111,7 @@ COMMAND("pg getmap", "get binary pg map to -o/stdout", "pg", "r", "cli,rest")
COMMAND("pg send_pg_creates", "trigger pg creates to be issued",\
"pg", "rw", "cli,rest")
COMMAND("pg dump " \
- "name=dumpcontents,type=CephChoices,strings=all|summary|sum|pools|osds|pgs,n=N,req=false", \
+ "name=dumpcontents,type=CephChoices,strings=all|summary|sum|pools|osds|pgs|pgs_brief,n=N,req=false", \
"show human-readable versions of pg map", "pg", "r", "cli,rest")
COMMAND("pg dump_json " \
"name=dumpcontents,type=CephChoices,strings=all|summary|sum|pools|osds|pgs,n=N,req=false", \
@@ -418,8 +418,7 @@ COMMAND("osd crush rule create-simple " \
"create crush rule <name> in <root> of type <type>", \
"osd", "rw", "cli,rest")
COMMAND("osd crush rule rm " \
- "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
- "name=name,type=CephString", \
+ "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] ", \
"remove crush rule <name>", "osd", "rw", "cli,rest")
COMMAND("osd setmaxosd " \
"name=newmax,type=CephInt,range=0", \
@@ -427,10 +426,10 @@ COMMAND("osd setmaxosd " \
COMMAND("osd pause", "pause osd", "osd", "rw", "cli,rest")
COMMAND("osd unpause", "unpause osd", "osd", "rw", "cli,rest")
COMMAND("osd set " \
- "name=key,type=CephChoices,strings=pause|noup|nodown|noout|noin|nobackfile|norecover", \
+ "name=key,type=CephChoices,strings=pause|noup|nodown|noout|noin|nobackfill|norecover|noscrub|nodeep-scrub", \
"set <key>", "osd", "rw", "cli,rest")
COMMAND("osd unset " \
- "name=key,type=CephChoices,strings=pause|noup|nodown|noout|noin|nobackfile|norecover", \
+ "name=key,type=CephChoices,strings=pause|noup|nodown|noout|noin|nobackfill|norecover|noscrub|nodeep-scrub", \
"unset <key>", "osd", "rw", "cli,rest")
COMMAND("osd cluster_snap", "take cluster snapshot (disabled)", \
"osd", "r", "")
diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc
index 118cf6f4a1e..a9d3e48a3be 100644
--- a/src/mon/Monitor.cc
+++ b/src/mon/Monitor.cc
@@ -1937,7 +1937,7 @@ void Monitor::handle_command(MMonCommand *m)
cmd_getval(g_ceph_context, cmdmap, "prefix", prefix);
if (prefix == "get_command_descriptions") {
int cmdnum = 0;
- JSONFormatter *f = new JSONFormatter();
+ Formatter *f = new_formatter("json");
f->open_object_section("command_descriptions");
for (MonCommand *cp = mon_commands;
cp < &mon_commands[ARRAY_SIZE(mon_commands)]; cp++) {
@@ -1952,9 +1952,8 @@ void Monitor::handle_command(MMonCommand *m)
f->close_section(); // command_descriptions
bufferlist rdata;
- f->flush(ds);
+ f->flush(rdata);
delete f;
- rdata.append(ds);
reply_command(m, 0, "", rdata, 0);
return;
}
@@ -2016,13 +2015,13 @@ void Monitor::handle_command(MMonCommand *m)
}
if (prefix == "fsid") {
- ds << monmap->fsid;
if (f) {
f->open_object_section("fsid");
f->dump_stream("fsid") << monmap->fsid;
f->close_section();
f->flush(rdata);
} else {
+ ds << monmap->fsid;
rdata.append(ds);
}
reply_command(m, 0, "", rdata, 0);
diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc
index c6db052a591..07022aec73b 100644
--- a/src/mon/OSDMonitor.cc
+++ b/src/mon/OSDMonitor.cc
@@ -1966,8 +1966,9 @@ bool OSDMonitor::preprocess_command(MMonCommand *m)
if (prefix == "osd stat") {
osdmap.print_summary(f.get(), ds);
if (f)
- f->flush(ds);
- rdata.append(ds);
+ f->flush(rdata);
+ else
+ rdata.append(ds);
}
else if (prefix == "osd dump" ||
prefix == "osd tree" ||
@@ -2080,9 +2081,7 @@ bool OSDMonitor::preprocess_command(MMonCommand *m)
f->dump_string(p->first.c_str(), p->second);
f->close_section();
f->close_section();
- f->flush(ds);
- ds << "\n";
- rdata.append(ds);
+ f->flush(rdata);
} else if (prefix == "osd map") {
string poolstr, objstr, namespacestr;
cmd_getval(g_ceph_context, cmdmap, "pool", poolstr);
@@ -3072,6 +3071,10 @@ bool OSDMonitor::prepare_command(MMonCommand *m)
return prepare_set_flag(m, CEPH_OSDMAP_NOBACKFILL);
else if (key == "norecover")
return prepare_set_flag(m, CEPH_OSDMAP_NORECOVER);
+ else if (key == "noscrub")
+ return prepare_set_flag(m, CEPH_OSDMAP_NOSCRUB);
+ else if (key == "nodeep-scrub")
+ return prepare_set_flag(m, CEPH_OSDMAP_NODEEP_SCRUB);
} else if (prefix == "osd unset") {
string key;
@@ -3090,6 +3093,10 @@ bool OSDMonitor::prepare_command(MMonCommand *m)
return prepare_unset_flag(m, CEPH_OSDMAP_NOBACKFILL);
else if (key == "norecover")
return prepare_unset_flag(m, CEPH_OSDMAP_NORECOVER);
+ else if (key == "noscrub")
+ return prepare_unset_flag(m, CEPH_OSDMAP_NOSCRUB);
+ else if (key == "nodeep-scrub")
+ return prepare_unset_flag(m, CEPH_OSDMAP_NODEEP_SCRUB);
} else if (prefix == "osd cluster_snap") {
// ** DISABLE THIS FOR NOW **
diff --git a/src/mon/PGMap.cc b/src/mon/PGMap.cc
index 86ad87bd929..f6b88fcbfe0 100644
--- a/src/mon/PGMap.cc
+++ b/src/mon/PGMap.cc
@@ -494,7 +494,7 @@ void PGMap::dirty_all(Incremental& inc)
void PGMap::dump(Formatter *f) const
{
dump_basic(f);
- dump_pg_stats(f);
+ dump_pg_stats(f, false);
dump_pool_stats(f);
dump_osd_stats(f);
}
@@ -521,7 +521,7 @@ void PGMap::dump_basic(Formatter *f) const
f->close_section();
}
-void PGMap::dump_pg_stats(Formatter *f) const
+void PGMap::dump_pg_stats(Formatter *f, bool brief) const
{
f->open_array_section("pg_stats");
for (hash_map<pg_t,pg_stat_t>::const_iterator i = pg_stat.begin();
@@ -529,7 +529,10 @@ void PGMap::dump_pg_stats(Formatter *f) const
++i) {
f->open_object_section("pg_stat");
f->dump_stream("pgid") << i->first;
- i->second.dump(f);
+ if (brief)
+ i->second.dump_brief(f);
+ else
+ i->second.dump(f);
f->close_section();
}
f->close_section();
diff --git a/src/mon/PGMap.h b/src/mon/PGMap.h
index 16c2f84b99e..e59d1b81a20 100644
--- a/src/mon/PGMap.h
+++ b/src/mon/PGMap.h
@@ -155,7 +155,7 @@ public:
void dump(Formatter *f) const;
void dump_basic(Formatter *f) const;
- void dump_pg_stats(Formatter *f) const;
+ void dump_pg_stats(Formatter *f, bool brief) const;
void dump_pool_stats(Formatter *f) const;
void dump_osd_stats(Formatter *f) const;
diff --git a/src/mon/PGMonitor.cc b/src/mon/PGMonitor.cc
index 93b0b0b3828..29c77dbe0ed 100644
--- a/src/mon/PGMonitor.cc
+++ b/src/mon/PGMonitor.cc
@@ -1358,7 +1358,6 @@ bool PGMonitor::preprocess_command(MMonCommand *m)
} else {
ds << pg_map;
}
- rdata.append(ds);
r = 0;
} else if (prefix == "pg getmap") {
pg_map.encode(rdata);
@@ -1404,7 +1403,10 @@ bool PGMonitor::preprocess_command(MMonCommand *m)
pg_map.dump_osd_stats(f.get());
}
if (what.count("pgs")) {
- pg_map.dump_pg_stats(f.get());
+ pg_map.dump_pg_stats(f.get(), false);
+ }
+ if (what.count("pgs_brief")) {
+ pg_map.dump_pg_stats(f.get(), true);
}
}
f->flush(ds);
diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc
index 69c181862cc..1a77dae730a 100644
--- a/src/osd/OSD.cc
+++ b/src/osd/OSD.cc
@@ -3935,7 +3935,6 @@ void OSD::do_command(Connection *con, tid_t tid, vector<string>& cmd, bufferlist
f->close_section(); // command_descriptions
f->flush(ds);
- odata.append(ds);
delete f;
goto out;
}
@@ -6633,11 +6632,12 @@ bool OSD::_recover_now()
return true;
}
-void OSD::do_recovery(PG *pg)
+void OSD::do_recovery(PG *pg, ThreadPool::TPHandle &handle)
{
// see how many we should try to start. note that this is a bit racy.
recovery_wq.lock();
- int max = g_conf->osd_recovery_max_active - recovery_ops_active;
+ int max = MAX(g_conf->osd_recovery_max_active - recovery_ops_active,
+ g_conf->osd_recovery_max_single_start);
if (max > 0) {
dout(10) << "do_recovery can start " << max << " (" << recovery_ops_active << "/" << g_conf->osd_recovery_max_active
<< " rops)" << dendl;
@@ -6653,7 +6653,7 @@ void OSD::do_recovery(PG *pg)
recovery_wq.queue(pg);
return;
} else {
- pg->lock();
+ pg->lock_suspend_timeout(handle);
if (pg->deleting || !(pg->is_active() && pg->is_primary())) {
pg->unlock();
goto out;
@@ -6665,7 +6665,7 @@ void OSD::do_recovery(PG *pg)
#endif
PG::RecoveryCtx rctx = create_context();
- int started = pg->start_recovery_ops(max, &rctx);
+ int started = pg->start_recovery_ops(max, &rctx, handle);
dout(10) << "do_recovery started " << started << "/" << max << " on " << *pg << dendl;
/*
@@ -7053,7 +7053,7 @@ void OSD::OpWQ::_process(PGRef pg, ThreadPool::TPHandle &handle)
if (!(pg_for_processing[&*pg].size()))
pg_for_processing.erase(&*pg);
}
- osd->dequeue_op(pg, op);
+ osd->dequeue_op(pg, op, handle);
pg->unlock();
}
@@ -7066,7 +7066,9 @@ void OSDService::dequeue_pg(PG *pg, list<OpRequestRef> *dequeued)
/*
* NOTE: dequeue called in worker thread, with pg lock
*/
-void OSD::dequeue_op(PGRef pg, OpRequestRef op)
+void OSD::dequeue_op(
+ PGRef pg, OpRequestRef op,
+ ThreadPool::TPHandle &handle)
{
utime_t latency = ceph_clock_now(g_ceph_context) - op->request->get_recv_stamp();
dout(10) << "dequeue_op " << op << " prio " << op->request->get_priority()
@@ -7079,7 +7081,7 @@ void OSD::dequeue_op(PGRef pg, OpRequestRef op)
op->mark_reached_pg();
- pg->do_request(op);
+ pg->do_request(op, handle);
// finish
dout(10) << "dequeue_op " << op << " finish" << dendl;
@@ -7131,7 +7133,7 @@ void OSD::process_peering_events(
++i) {
set<boost::intrusive_ptr<PG> > split_pgs;
PG *pg = *i;
- pg->lock();
+ pg->lock_suspend_timeout(handle);
curmap = service.get_osdmap();
if (pg->deleting) {
pg->unlock();
diff --git a/src/osd/OSD.h b/src/osd/OSD.h
index 5196a1dc1f3..82a251d9a80 100644
--- a/src/osd/OSD.h
+++ b/src/osd/OSD.h
@@ -915,7 +915,9 @@ private:
} op_wq;
void enqueue_op(PG *pg, OpRequestRef op);
- void dequeue_op(PGRef pg, OpRequestRef op);
+ void dequeue_op(
+ PGRef pg, OpRequestRef op,
+ ThreadPool::TPHandle &handle);
// -- peering queue --
struct PeeringWQ : public ThreadPool::BatchWorkQueue<PG> {
@@ -1371,8 +1373,8 @@ protected:
osd->recovery_queue.push_front(&pg->recovery_item);
}
}
- void _process(PG *pg) {
- osd->do_recovery(pg);
+ void _process(PG *pg, ThreadPool::TPHandle &handle) {
+ osd->do_recovery(pg, handle);
pg->put("RecoveryWQ");
}
void _clear() {
@@ -1386,7 +1388,7 @@ protected:
void start_recovery_op(PG *pg, const hobject_t& soid);
void finish_recovery_op(PG *pg, const hobject_t& soid, bool dequeue);
- void do_recovery(PG *pg);
+ void do_recovery(PG *pg, ThreadPool::TPHandle &handle);
bool _recover_now();
// replay / delayed pg activation
diff --git a/src/osd/OpRequest.cc b/src/osd/OpRequest.cc
index a6cdc9ecffb..c694362a8a5 100644
--- a/src/osd/OpRequest.cc
+++ b/src/osd/OpRequest.cc
@@ -20,6 +20,22 @@ static ostream& _prefix(std::ostream* _dout)
return *_dout << "--OSD::tracker-- ";
}
+OpRequest::OpRequest(Message *req, OpTracker *tracker) :
+ request(req), xitem(this),
+ rmw_flags(0),
+ warn_interval_multiplier(1),
+ lock("OpRequest::lock"),
+ tracker(tracker),
+ hit_flag_points(0), latest_flag_point(0),
+ seq(0) {
+ received_time = request->get_recv_stamp();
+ tracker->register_inflight_op(&xitem);
+ if (req->get_priority() < g_conf->osd_client_op_priority) {
+ // don't warn as quickly for low priority ops
+ warn_interval_multiplier = g_conf->osd_recovery_op_warn_multiple;
+ }
+}
+
void OpHistory::on_shutdown()
{
arrived.clear();
diff --git a/src/osd/OpRequest.h b/src/osd/OpRequest.h
index a2014472432..e72f03d1d77 100644
--- a/src/osd/OpRequest.h
+++ b/src/osd/OpRequest.h
@@ -156,17 +156,7 @@ private:
static const uint8_t flag_sub_op_sent = 1 << 4;
static const uint8_t flag_commit_sent = 1 << 5;
- OpRequest(Message *req, OpTracker *tracker) :
- request(req), xitem(this),
- rmw_flags(0),
- warn_interval_multiplier(1),
- lock("OpRequest::lock"),
- tracker(tracker),
- hit_flag_points(0), latest_flag_point(0),
- seq(0) {
- received_time = request->get_recv_stamp();
- tracker->register_inflight_op(&xitem);
- }
+ OpRequest(Message *req, OpTracker *tracker);
public:
~OpRequest() {
assert(request);
diff --git a/src/osd/PG.cc b/src/osd/PG.cc
index f731441e8a4..8e78eaa7a16 100644
--- a/src/osd/PG.cc
+++ b/src/osd/PG.cc
@@ -1397,7 +1397,9 @@ void PG::queue_op(OpRequestRef op)
osd->op_wq.queue(make_pair(PGRef(this), op));
}
-void PG::do_request(OpRequestRef op)
+void PG::do_request(
+ OpRequestRef op,
+ ThreadPool::TPHandle &handle)
{
// do any pending flush
do_pending_flush();
@@ -1435,7 +1437,7 @@ void PG::do_request(OpRequestRef op)
break;
case MSG_OSD_PG_SCAN:
- do_scan(op);
+ do_scan(op, handle);
break;
case MSG_OSD_PG_BACKFILL:
@@ -4510,7 +4512,7 @@ void PG::start_flush(ObjectStore::Transaction *t,
FlushStateRef flush_trigger(
new FlushState(this, get_osdmap()->get_epoch()));
t->nop();
- flushed = false;
+ assert(!flushed);
on_applied->push_back(new ContainerContext<FlushStateRef>(flush_trigger));
on_safe->push_back(new ContainerContext<FlushStateRef>(flush_trigger));
}
@@ -5217,6 +5219,7 @@ PG::RecoveryState::Reset::Reset(my_context ctx)
state_name = "Reset";
context< RecoveryMachine >().log_enter(state_name);
PG *pg = context< RecoveryMachine >().pg;
+ pg->flushed = false;
pg->set_last_peering_reset();
}
diff --git a/src/osd/PG.h b/src/osd/PG.h
index 8f572c75e19..d4679ce4fd8 100644
--- a/src/osd/PG.h
+++ b/src/osd/PG.h
@@ -645,7 +645,9 @@ public:
virtual void check_local() = 0;
- virtual int start_recovery_ops(int max, RecoveryCtx *prctx) = 0;
+ virtual int start_recovery_ops(
+ int max, RecoveryCtx *prctx,
+ ThreadPool::TPHandle &handle) = 0;
void purge_strays();
@@ -1804,12 +1806,18 @@ public:
// abstract bits
- void do_request(OpRequestRef op);
+ void do_request(
+ OpRequestRef op,
+ ThreadPool::TPHandle &handle
+ );
virtual void do_op(OpRequestRef op) = 0;
virtual void do_sub_op(OpRequestRef op) = 0;
virtual void do_sub_op_reply(OpRequestRef op) = 0;
- virtual void do_scan(OpRequestRef op) = 0;
+ virtual void do_scan(
+ OpRequestRef op,
+ ThreadPool::TPHandle &handle
+ ) = 0;
virtual void do_backfill(OpRequestRef op) = 0;
virtual void do_push(OpRequestRef op) = 0;
virtual void do_pull(OpRequestRef op) = 0;
diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc
index 658ea7cb746..ab9c8099a44 100644
--- a/src/osd/ReplicatedPG.cc
+++ b/src/osd/ReplicatedPG.cc
@@ -1252,7 +1252,9 @@ void ReplicatedPG::do_sub_op_reply(OpRequestRef op)
sub_op_modify_reply(op);
}
-void ReplicatedPG::do_scan(OpRequestRef op)
+void ReplicatedPG::do_scan(
+ OpRequestRef op,
+ ThreadPool::TPHandle &handle)
{
MOSDPGScan *m = static_cast<MOSDPGScan*>(op->request);
assert(m->get_header().type == MSG_OSD_PG_SCAN);
@@ -1278,7 +1280,9 @@ void ReplicatedPG::do_scan(OpRequestRef op)
BackfillInterval bi;
osr->flush();
- scan_range(m->begin, g_conf->osd_backfill_scan_min, g_conf->osd_backfill_scan_max, &bi);
+ scan_range(
+ m->begin, g_conf->osd_backfill_scan_min,
+ g_conf->osd_backfill_scan_max, &bi, handle);
MOSDPGScan *reply = new MOSDPGScan(MOSDPGScan::OP_SCAN_DIGEST,
get_osdmap()->get_epoch(), m->query_epoch,
info.pgid, bi.begin, bi.end);
@@ -6875,7 +6879,9 @@ void ReplicatedPG::check_recovery_sources(const OSDMapRef osdmap)
}
-int ReplicatedPG::start_recovery_ops(int max, RecoveryCtx *prctx)
+int ReplicatedPG::start_recovery_ops(
+ int max, RecoveryCtx *prctx,
+ ThreadPool::TPHandle &handle)
{
int started = 0;
assert(is_primary());
@@ -6898,15 +6904,15 @@ int ReplicatedPG::start_recovery_ops(int max, RecoveryCtx *prctx)
if (num_missing == num_unfound) {
// All of the missing objects we have are unfound.
// Recover the replicas.
- started = recover_replicas(max);
+ started = recover_replicas(max, handle);
}
if (!started) {
// We still have missing objects that we should grab from replicas.
- started += recover_primary(max);
+ started += recover_primary(max, handle);
}
if (!started && num_unfound != get_num_unfound()) {
// second chance to recovery replicas
- started = recover_replicas(max);
+ started = recover_replicas(max, handle);
}
bool deferred_backfill = false;
@@ -6931,7 +6937,7 @@ int ReplicatedPG::start_recovery_ops(int max, RecoveryCtx *prctx)
}
deferred_backfill = true;
} else {
- started += recover_backfill(max - started);
+ started += recover_backfill(max - started, handle);
}
}
@@ -6993,7 +6999,7 @@ int ReplicatedPG::start_recovery_ops(int max, RecoveryCtx *prctx)
* do one recovery op.
* return true if done, false if nothing left to do.
*/
-int ReplicatedPG::recover_primary(int max)
+int ReplicatedPG::recover_primary(int max, ThreadPool::TPHandle &handle)
{
assert(is_primary());
@@ -7012,6 +7018,7 @@ int ReplicatedPG::recover_primary(int max)
map<version_t, hobject_t>::const_iterator p =
missing.rmissing.lower_bound(pg_log.get_log().last_requested);
while (p != missing.rmissing.end()) {
+ handle.reset_tp_timeout();
hobject_t soid;
version_t v = p->first;
@@ -7204,7 +7211,7 @@ int ReplicatedPG::prep_object_replica_pushes(
return 1;
}
-int ReplicatedPG::recover_replicas(int max)
+int ReplicatedPG::recover_replicas(int max, ThreadPool::TPHandle &handle)
{
dout(10) << __func__ << "(" << max << ")" << dendl;
int started = 0;
@@ -7226,6 +7233,7 @@ int ReplicatedPG::recover_replicas(int max)
for (map<version_t, hobject_t>::const_iterator p = m.rmissing.begin();
p != m.rmissing.end() && started < max;
++p) {
+ handle.reset_tp_timeout();
const hobject_t soid(p->second);
if (pushing.count(soid)) {
@@ -7275,7 +7283,9 @@ int ReplicatedPG::recover_replicas(int max)
* peer_info[backfill_target].last_backfill = MIN(peer_backfill_info.begin,
* backfill_info.begin, backfills_in_flight)
*/
-int ReplicatedPG::recover_backfill(int max)
+int ReplicatedPG::recover_backfill(
+ int max,
+ ThreadPool::TPHandle &handle)
{
dout(10) << "recover_backfill (" << max << ")" << dendl;
assert(backfill_target >= 0);
@@ -7305,7 +7315,7 @@ int ReplicatedPG::recover_backfill(int max)
dout(10) << " rescanning local backfill_info from " << backfill_pos << dendl;
backfill_info.clear();
osr->flush();
- scan_range(backfill_pos, local_min, local_max, &backfill_info);
+ scan_range(backfill_pos, local_min, local_max, &backfill_info, handle);
int ops = 0;
map<hobject_t, pair<eversion_t, eversion_t> > to_push;
@@ -7319,7 +7329,8 @@ int ReplicatedPG::recover_backfill(int max)
if (backfill_info.begin <= pbi.begin &&
!backfill_info.extends_to_end() && backfill_info.empty()) {
osr->flush();
- scan_range(backfill_info.end, local_min, local_max, &backfill_info);
+ scan_range(backfill_info.end, local_min, local_max, &backfill_info,
+ handle);
backfill_info.trim();
}
backfill_pos = backfill_info.begin > pbi.begin ? pbi.begin : backfill_info.begin;
@@ -7407,6 +7418,7 @@ int ReplicatedPG::recover_backfill(int max)
for (map<hobject_t, eversion_t>::iterator i = to_remove.begin();
i != to_remove.end();
++i) {
+ handle.reset_tp_timeout();
send_remove_op(i->first, i->second, backfill_target);
}
@@ -7414,6 +7426,7 @@ int ReplicatedPG::recover_backfill(int max)
for (map<hobject_t, pair<eversion_t, eversion_t> >::iterator i = to_push.begin();
i != to_push.end();
++i) {
+ handle.reset_tp_timeout();
prep_backfill_object_push(
i->first, i->second.first, i->second.second, backfill_target, &pushes);
}
@@ -7480,7 +7493,9 @@ void ReplicatedPG::prep_backfill_object_push(
put_object_context(obc);
}
-void ReplicatedPG::scan_range(hobject_t begin, int min, int max, BackfillInterval *bi)
+void ReplicatedPG::scan_range(
+ hobject_t begin, int min, int max, BackfillInterval *bi,
+ ThreadPool::TPHandle &handle)
{
assert(is_locked());
dout(10) << "scan_range from " << begin << dendl;
@@ -7496,6 +7511,7 @@ void ReplicatedPG::scan_range(hobject_t begin, int min, int max, BackfillInterva
dout(20) << ls << dendl;
for (vector<hobject_t>::iterator p = ls.begin(); p != ls.end(); ++p) {
+ handle.reset_tp_timeout();
ObjectContext *obc = NULL;
if (is_primary())
obc = _lookup_object_context(*p);
diff --git a/src/osd/ReplicatedPG.h b/src/osd/ReplicatedPG.h
index 7b70b4381ea..41c8106ea00 100644
--- a/src/osd/ReplicatedPG.h
+++ b/src/osd/ReplicatedPG.h
@@ -759,10 +759,13 @@ protected:
void _clear_recovery_state();
void queue_for_recovery();
- int start_recovery_ops(int max, RecoveryCtx *prctx);
- int recover_primary(int max);
- int recover_replicas(int max);
- int recover_backfill(int max);
+ int start_recovery_ops(
+ int max, RecoveryCtx *prctx,
+ ThreadPool::TPHandle &handle);
+
+ int recover_primary(int max, ThreadPool::TPHandle &handle);
+ int recover_replicas(int max, ThreadPool::TPHandle &handle);
+ int recover_backfill(int max, ThreadPool::TPHandle &handle);
/**
* scan a (hash) range of objects in the current pg
@@ -772,7 +775,10 @@ protected:
* @max return no more than this many items
* @bi [out] resulting map of objects to eversion_t's
*/
- void scan_range(hobject_t begin, int min, int max, BackfillInterval *bi);
+ void scan_range(
+ hobject_t begin, int min, int max, BackfillInterval *bi,
+ ThreadPool::TPHandle &handle
+ );
void prep_backfill_object_push(
hobject_t oid, eversion_t v, eversion_t have, int peer,
@@ -939,7 +945,9 @@ public:
void do_pg_op(OpRequestRef op);
void do_sub_op(OpRequestRef op);
void do_sub_op_reply(OpRequestRef op);
- void do_scan(OpRequestRef op);
+ void do_scan(
+ OpRequestRef op,
+ ThreadPool::TPHandle &handle);
void do_backfill(OpRequestRef op);
void _do_push(OpRequestRef op);
void _do_pull_response(OpRequestRef op);
diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc
index fbd5cbbe9a0..0e8ecb99086 100644
--- a/src/osd/osd_types.cc
+++ b/src/osd/osd_types.cc
@@ -1190,6 +1190,19 @@ void pg_stat_t::dump(Formatter *f) const
f->close_section();
}
+void pg_stat_t::dump_brief(Formatter *f) const
+{
+ f->dump_string("state", pg_state_string(state));
+ f->open_array_section("up");
+ for (vector<int>::const_iterator p = up.begin(); p != up.end(); ++p)
+ f->dump_int("osd", *p);
+ f->close_section();
+ f->open_array_section("acting");
+ for (vector<int>::const_iterator p = acting.begin(); p != acting.end(); ++p)
+ f->dump_int("osd", *p);
+ f->close_section();
+}
+
void pg_stat_t::encode(bufferlist &bl) const
{
ENCODE_START(13, 8, bl);
diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h
index ca3dcc192b0..bf04e8e11e3 100644
--- a/src/osd/osd_types.h
+++ b/src/osd/osd_types.h
@@ -1079,6 +1079,7 @@ struct pg_stat_t {
}
void dump(Formatter *f) const;
+ void dump_brief(Formatter *f) const;
void encode(bufferlist &bl) const;
void decode(bufferlist::iterator &bl);
static void generate_test_instances(list<pg_stat_t*>& o);
diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc
index fc54daa3f27..eb490cef330 100644
--- a/src/osdc/Objecter.cc
+++ b/src/osdc/Objecter.cc
@@ -2334,9 +2334,8 @@ bool Objecter::RequestStateHook::call(std::string command, cmdmap_t& cmdmap,
m_objecter->client_lock.Lock();
m_objecter->dump_requests(f);
m_objecter->client_lock.Unlock();
- f->flush(ss);
+ f->flush(out);
delete f;
- out.append(ss);
return true;
}
diff --git a/src/pybind/ceph_argparse.py b/src/pybind/ceph_argparse.py
index 9a9db6758a5..9e56d38384c 100644
--- a/src/pybind/ceph_argparse.py
+++ b/src/pybind/ceph_argparse.py
@@ -15,6 +15,7 @@ Foundation. See file COPYING.
import copy
import json
import os
+import pprint
import re
import socket
import stat
@@ -46,6 +47,12 @@ class ArgumentValid(ArgumentError):
"""
pass
+class ArgumentTooFew(ArgumentError):
+ """
+ Fewer arguments than descriptors in signature; may mean to continue
+ the search, so gets a special exception type
+ """
+
class ArgumentPrefix(ArgumentError):
"""
Special for mismatched prefix; less severe, don't report by default
@@ -727,6 +734,55 @@ def matchnum(args, signature, partial=False):
matchcnt += 1
return matchcnt
+def get_next_arg(desc, args):
+ '''
+ Get either the value matching key 'desc.name' or the next arg in
+ the non-dict list. Return None if args are exhausted. Used in
+ validate() below.
+ '''
+ arg = None
+ if isinstance(args, dict):
+ arg = args.pop(desc.name, None)
+ # allow 'param=param' to be expressed as 'param'
+ if arg == '':
+ arg = desc.name
+ # Hack, or clever? If value is a list, keep the first element,
+ # push rest back onto myargs for later processing.
+ # Could process list directly, but nesting here is already bad
+ if arg and isinstance(arg, list):
+ args[desc.name] = arg[1:]
+ arg = arg[0]
+ elif args:
+ arg = args.pop(0)
+ if arg and isinstance(arg, list):
+ args = arg[1:] + args
+ arg = arg[0]
+ return arg
+
+def store_arg(desc, d):
+ '''
+ Store argument described by, and held in, thanks to valid(),
+ desc into the dictionary d, keyed by desc.name. Three cases:
+
+ 1) desc.N is set: value in d is a list
+ 2) prefix: multiple args are joined with ' ' into one d{} item
+ 3) single prefix or other arg: store as simple value
+
+ Used in validate() below.
+ '''
+ if desc.N:
+ # value should be a list
+ if desc.name in d:
+ d[desc.name] += [desc.instance.val]
+ else:
+ d[desc.name] = [desc.instance.val]
+ elif (desc.t == CephPrefix) and (desc.name in d):
+ # prefixes' values should be a space-joined concatenation
+ d[desc.name] += ' ' + desc.instance.val
+ else:
+ # if first CephPrefix or any other type, just set it
+ d[desc.name] = desc.instance.val
+
def validate(args, signature, partial=False):
"""
validate(args, signature, partial=False)
@@ -748,85 +804,79 @@ def validate(args, signature, partial=False):
myargs = copy.deepcopy(args)
mysig = copy.deepcopy(signature)
+ reqsiglen = len([desc for desc in mysig if desc.req])
+ matchcnt = 0
d = dict()
for desc in mysig:
setattr(desc, 'numseen', 0)
while desc.numseen < desc.n:
- myarg = None
- if not myargs:
- break
- # get either the value matching key 'desc.name' or the next arg in
- # the non-dict list
- if isinstance(myargs, dict):
- myarg = myargs.pop(desc.name, None)
- # allow 'param=param' to be expressed as 'param'
- if myarg == '':
- myarg = desc.name
- # Hack, or clever? If value is a list, keep the first element,
- # push rest back onto myargs for later processing.
- # Could process list directly, but nesting here is already bad
- if myarg and isinstance(myarg, list):
- myargs[desc.name] = myarg[1:]
- myarg = myarg[0]
- elif myargs:
- myarg = myargs.pop(0)
- if myarg and isinstance(myarg, list):
- myargs = myarg[1:] + myargs
- myarg = myarg[0]
-
- # no arg, but not required? March on
+ myarg = get_next_arg(desc, myargs)
+
+ # no arg, but not required? Continue consuming mysig
+ # in case there are later required args
if not myarg and not desc.req:
break
# out of arguments for a required param?
+ # Either return (if partial validation) or raise
if not myarg and desc.req:
if desc.N and desc.numseen < 1:
# wanted N, didn't even get 1
if partial:
return d
- raise ArgumentNumber('saw {0} of {1}, expected at least 1'.format(desc.numseen, desc))
+ raise ArgumentNumber(
+ 'saw {0} of {1}, expected at least 1'.\
+ format(desc.numseen, desc)
+ )
elif not desc.N and desc.numseen < desc.n:
# wanted n, got too few
if partial:
return d
- raise ArgumentNumber('saw {0} of {1}, expected {2}'.format(desc.numseen, desc, desc.n))
+ raise ArgumentNumber(
+ 'saw {0} of {1}, expected {2}'.\
+ format(desc.numseen, desc, desc.n)
+ )
break
- # not out of args; validate this one
+ # Have an arg; validate it
try:
validate_one(myarg, desc)
valid = True
- except Exception as e:
+ except ArgumentError as e:
valid = False
if not valid:
# argument mismatch
- # if not required, just push back for the next one
if not desc.req:
+ # if not required, just push back; it might match
+ # the next arg
+ print >> sys.stderr, myarg, 'not valid: ', str(e)
myargs.insert(0, myarg)
break
else:
- # hm, but it was required, so quit
+ # hm, it was required, so time to return/raise
if partial:
return d
raise e
- # valid arg acquired. Store in dict, as a list if multivalued
- if desc.N:
- # value should be a list
- if desc.name in d:
- d[desc.name] += [desc.instance.val]
- else:
- d[desc.name] = [desc.instance.val]
- elif (desc.t == CephPrefix) and (desc.name in d):
- # prefixes' values should be a space-joined concatenation
- d[desc.name] += ' ' + desc.instance.val
- else:
- # if first CephPrefix or any other type, just set it
- d[desc.name] = desc.instance.val
+ # Whew, valid arg acquired. Store in dict
+ matchcnt += 1
+ store_arg(desc, d)
+
+ # Done with entire list of argdescs
+ if matchcnt < reqsiglen:
+ raise ArgumentTooFew("not enough arguments given")
+
if myargs and not partial:
raise ArgumentError("unused arguments: " + str(myargs))
+
+ # Finally, success
return d
+def cmdsiglen(sig):
+ sigdict = sig.values()
+ assert len(sigdict) == 1
+ return len(sig.values()[0]['sig'])
+
def validate_command(sigdict, args, verbose=False):
"""
turn args into a valid dictionary ready to be sent off as JSON,
@@ -856,14 +906,19 @@ def validate_command(sigdict, args, verbose=False):
best_match_cnt, cmdtag, concise_sig(sig))
bestcmds.append({cmdtag:cmd})
+ # Sort bestcmds by number of args so we can try shortest first
+ # (relies on a cmdsig being key,val where val is a list of len 1)
+ bestcmds_sorted = sorted(bestcmds,
+ cmp=lambda x,y:cmp(cmdsiglen(x), cmdsiglen(y)))
+
if verbose:
- print >> sys.stderr, "bestcmds: ", bestcmds
+ print >> sys.stderr, "bestcmds_sorted: "
+ pprint.PrettyPrinter(stream=sys.stderr).pprint(bestcmds_sorted)
# for everything in bestcmds, look for a true match
- for cmdsig in bestcmds:
+ for cmdsig in bestcmds_sorted:
for cmd in cmdsig.itervalues():
sig = cmd['sig']
- helptext = cmd['help']
try:
valid_dict = validate(args, sig)
found = cmd
@@ -872,14 +927,22 @@ def validate_command(sigdict, args, verbose=False):
# ignore prefix mismatches; we just haven't found
# the right command yet
pass
+ except ArgumentTooFew:
+ # It looked like this matched the beginning, but it
+ # didn't have enough args supplied. If we're out of
+ # cmdsigs we'll fall out unfound; if we're not, maybe
+ # the next one matches completely. Whine, but pass.
+ if verbose:
+ print >> sys.stderr, 'Not enough args supplied for ', \
+ concise_sig(sig)
except ArgumentError as e:
- # prefixes matched, but some other arg didn't;
- # stop now, because we have the right command but
+ # Solid mismatch on an arg (type, range, etc.)
+ # Stop now, because we have the right command but
# some other input is invalid
print >> sys.stderr, "Invalid command: ", str(e)
return {}
- if found:
- break
+ if found:
+ break
if not found:
print >> sys.stderr, 'no valid command found; 10 closest matches:'
diff --git a/src/pybind/ceph_rest_api.py b/src/pybind/ceph_rest_api.py
index 59e3f60a3a7..421cc59edcc 100755
--- a/src/pybind/ceph_rest_api.py
+++ b/src/pybind/ceph_rest_api.py
@@ -1,20 +1,20 @@
#!/usr/bin/python
# vim: ts=4 sw=4 smarttab expandtab
-import collections
-import contextlib
import errno
import json
import logging
import logging.handlers
-import os
import rados
import textwrap
import xml.etree.ElementTree
import xml.sax.saxutils
import flask
-from ceph_argparse import *
+from ceph_argparse import \
+ ArgumentError, CephPgid, CephOsdName, CephChoices, CephPrefix, \
+ concise_sig, descsort, parse_funcsig, parse_json_funcsigs, \
+ validate, json_command
#
# Globals and defaults
diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc
index 364f60f78f7..2b8a716115b 100644
--- a/src/rgw/rgw_admin.cc
+++ b/src/rgw/rgw_admin.cc
@@ -2175,6 +2175,8 @@ next:
assert(0);
}
encode_json("bounds", bounds, formatter);
+ formatter->flush(cout);
+ cout << std::endl;
}
if (opt_cmd == OPT_REPLICALOG_DELETE) {
diff --git a/src/rgw/rgw_main.cc b/src/rgw/rgw_main.cc
index 6c383d822c1..5270f21be22 100644
--- a/src/rgw/rgw_main.cc
+++ b/src/rgw/rgw_main.cc
@@ -318,12 +318,16 @@ void RGWProcess::handle_request(RGWRequest *req)
RGWOp *op = NULL;
int init_error = 0;
- RGWHandler *handler = rest->get_handler(store, s, &client_io, &init_error);
+ bool should_log = false;
+ RGWRESTMgr *mgr;
+ RGWHandler *handler = rest->get_handler(store, s, &client_io, &mgr, &init_error);
if (init_error != 0) {
abort_early(s, init_error);
goto done;
}
+ should_log = mgr->get_logging();
+
req->log(s, "getting op");
op = handler->get_op(store);
if (!op) {
@@ -384,7 +388,9 @@ void RGWProcess::handle_request(RGWRequest *req)
op->execute();
op->complete();
done:
- rgw_log_op(store, s, (op ? op->name() : "unknown"), olog);
+ if (should_log) {
+ rgw_log_op(store, s, (op ? op->name() : "unknown"), olog);
+ }
int http_ret = s->err.http_ret;
@@ -431,6 +437,12 @@ int usage()
return 0;
}
+static RGWRESTMgr *set_logging(RGWRESTMgr *mgr)
+{
+ mgr->set_logging(true);
+ return mgr;
+}
+
/*
* start up the RADOS connection and then handle HTTP messages as they come in
*/
@@ -527,16 +539,16 @@ int main(int argc, const char **argv)
}
if (apis_map.count("s3") > 0)
- rest.register_default_mgr(new RGWRESTMgr_S3);
+ rest.register_default_mgr(set_logging(new RGWRESTMgr_S3));
if (apis_map.count("swift") > 0) {
do_swift = true;
swift_init(g_ceph_context);
- rest.register_resource(g_conf->rgw_swift_url_prefix, new RGWRESTMgr_SWIFT);
+ rest.register_resource(g_conf->rgw_swift_url_prefix, set_logging(new RGWRESTMgr_SWIFT));
}
if (apis_map.count("swift_auth") > 0)
- rest.register_resource(g_conf->rgw_swift_auth_entry, new RGWRESTMgr_SWIFT_Auth);
+ rest.register_resource(g_conf->rgw_swift_auth_entry, set_logging(new RGWRESTMgr_SWIFT_Auth));
if (apis_map.count("admin") > 0) {
RGWRESTMgr_Admin *admin_resource = new RGWRESTMgr_Admin;
diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc
index aba5cdf0ee2..222b79a7d2e 100644
--- a/src/rgw/rgw_rados.cc
+++ b/src/rgw/rgw_rados.cc
@@ -2551,7 +2551,7 @@ int RGWRados::copy_obj(void *ctx,
conn = rest_master_conn;
} else {
map<string, RGWRESTConn *>::iterator iter = region_conn_map.find(src_bucket_info.region);
- if (iter == zone_conn_map.end()) {
+ if (iter == region_conn_map.end()) {
ldout(cct, 0) << "could not find region connection to region: " << source_zone << dendl;
return -ENOENT;
}
diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc
index a0870708c44..ee73bb94fa5 100644
--- a/src/rgw/rgw_rest.cc
+++ b/src/rgw/rgw_rest.cc
@@ -1210,7 +1210,7 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO *cio)
}
RGWHandler *RGWREST::get_handler(RGWRados *store, struct req_state *s, RGWClientIO *cio,
- int *init_error)
+ RGWRESTMgr **pmgr, int *init_error)
{
RGWHandler *handler;
@@ -1224,6 +1224,9 @@ RGWHandler *RGWREST::get_handler(RGWRados *store, struct req_state *s, RGWClient
return NULL;
}
+ if (pmgr)
+ *pmgr = m;
+
handler = m->get_handler(s);
if (!handler) {
*init_error = -ERR_METHOD_NOT_ALLOWED;
diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h
index ded5b88366a..b65efb3de3e 100644
--- a/src/rgw/rgw_rest.h
+++ b/src/rgw/rgw_rest.h
@@ -263,13 +263,14 @@ class RGWHandler_SWIFT_Auth;
class RGWHandler_ObjStore_S3;
class RGWRESTMgr {
+ bool should_log;
protected:
map<string, RGWRESTMgr *> resource_mgrs;
multimap<size_t, string> resources_by_size;
RGWRESTMgr *default_mgr;
public:
- RGWRESTMgr() : default_mgr(NULL) {}
+ RGWRESTMgr() : should_log(false), default_mgr(NULL) {}
virtual ~RGWRESTMgr();
void register_resource(string resource, RGWRESTMgr *mgr);
@@ -278,6 +279,9 @@ public:
virtual RGWRESTMgr *get_resource_mgr(struct req_state *s, const string& uri, string *out_uri);
virtual RGWHandler *get_handler(struct req_state *s) { return NULL; }
virtual void put_handler(RGWHandler *handler) { delete handler; }
+
+ void set_logging(bool _should_log) { should_log = _should_log; }
+ bool get_logging() { return should_log; }
};
class RGWREST {
@@ -287,7 +291,7 @@ class RGWREST {
public:
RGWREST() {}
RGWHandler *get_handler(RGWRados *store, struct req_state *s, RGWClientIO *cio,
- int *init_error);
+ RGWRESTMgr **pmgr, int *init_error);
void put_handler(RGWHandler *handler) {
mgr.put_handler(handler);
}