summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-09-23 16:42:26 -0700
committerSage Weil <sage@inktank.com>2013-09-23 16:42:26 -0700
commit08c386f54254bb5652d811e4caf339b619a39109 (patch)
treeef5b65cab1cb447e5bd656363fd343497ff2e926
parent286a6991900fdfc66e1c44a0299f3de8d30e7785 (diff)
parentbfd4db2525b37f52a90c74deb8233edb60cc5d97 (diff)
downloadceph-08c386f54254bb5652d811e4caf339b619a39109.tar.gz
Merge pull request #588 from dachary/wip-6274
mon: unit tests to protect against some MonCommands.h typos
-rw-r--r--.gitignore8
-rw-r--r--ceph.spec.in1
-rw-r--r--debian/control1
-rw-r--r--src/.gitignore1
-rw-r--r--src/Makefile-env.am7
-rw-r--r--src/Makefile.am5
-rw-r--r--src/mon/MonCommands.h2
-rw-r--r--src/mon/Monitor.cc46
-rw-r--r--src/mon/Monitor.h12
-rw-r--r--src/pybind/ceph_argparse.py5
-rw-r--r--src/test/Makefile.am11
-rw-r--r--src/test/common/get_command_descriptions.cc116
-rwxr-xr-xsrc/test/pybind/test_ceph_argparse.py1036
13 files changed, 1223 insertions, 28 deletions
diff --git a/.gitignore b/.gitignore
index 211c09cbba7..7e637866366 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,4 +69,10 @@ web/*.html
# dir from coverity tools
cov-int/
-/test-driver \ No newline at end of file
+/test-driver
+
+# gtags(1) generated files
+GPATH
+GRTAGS
+GSYMS
+GTAGS
diff --git a/ceph.spec.in b/ceph.spec.in
index 851ee7acfd5..a60d87ad814 100644
--- a/ceph.spec.in
+++ b/ceph.spec.in
@@ -37,6 +37,7 @@ BuildRequires: perl
BuildRequires: gdbm
BuildRequires: pkgconfig
BuildRequires: python
+BuildRequires: python-nose
BuildRequires: libaio-devel
BuildRequires: libcurl-devel
BuildRequires: libxml2-devel
diff --git a/debian/control b/debian/control
index 44ee725efd4..1aec592c9f8 100644
--- a/debian/control
+++ b/debian/control
@@ -34,6 +34,7 @@ Build-Depends: autoconf,
libxml2-dev,
pkg-config,
python (>= 2.6.6-3~),
+ python-nose,
uuid-dev,
yasm
Standards-Version: 3.9.3
diff --git a/src/.gitignore b/src/.gitignore
index 4c98529bd87..6efe8dc6bc4 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -68,6 +68,7 @@ Makefile
/test_*
/cls_test_*
/unittest_*
+/get_command_descriptions
# old dir, may in use by older branches
/leveldb
diff --git a/src/Makefile-env.am b/src/Makefile-env.am
index 900998702f5..6a4e09512a2 100644
--- a/src/Makefile-env.am
+++ b/src/Makefile-env.am
@@ -8,6 +8,7 @@ CLEANFILES =
noinst_HEADERS =
bin_PROGRAMS =
+noinst_PROGRAMS =
bin_SCRIPTS =
sbin_PROGRAMS =
sbin_SCRIPTS =
@@ -26,6 +27,12 @@ ceph_sbindir = $(exec_prefix)$(sbindir)
# C/C++ tests to build will be appended to this
check_PROGRAMS =
+# tests scripts will be appended to this
+check_SCRIPTS =
+
+# python unit tests need to know where the scripts are located
+export PYTHONPATH=$(top_srcdir)/src/pybind
+
# when doing a debug build, make sure to make the targets
if WITH_DEBUG
bin_PROGRAMS += $(bin_DEBUGPROGRAMS)
diff --git a/src/Makefile.am b/src/Makefile.am
index ed07a91e3ae..5e745a0573f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -251,10 +251,11 @@ shell_scripts += init-ceph mkcephfs
# executables built, you need to replace this with manual assignments
# target by target
-TESTS = $(check_PROGRAMS) unittest_bufferlist.sh
+TESTS = \
+ $(check_PROGRAMS) \
+ $(check_SCRIPTS)
check-local:
- $(srcdir)/test/encoding/check-generated.sh
$(srcdir)/test/encoding/readable.sh ../ceph-object-corpus
diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h
index 365fd28b64e..482ea91ea02 100644
--- a/src/mon/MonCommands.h
+++ b/src/mon/MonCommands.h
@@ -290,7 +290,7 @@ COMMAND("mds newfs " \
* Monmap commands
*/
COMMAND("mon dump " \
- "name=epoch,type=CephInt,req=false", \
+ "name=epoch,type=CephInt,range=0,req=false", \
"dump formatted monmap (optionally from epoch)", \
"mon", "r", "cli,rest")
COMMAND("mon stat", "summarize monitor status", "mon", "r", "cli,rest")
diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc
index 10f5bfb149c..2c64a8f2ef2 100644
--- a/src/mon/Monitor.cc
+++ b/src/mon/Monitor.cc
@@ -1854,13 +1854,7 @@ void Monitor::get_status(stringstream &ss, Formatter *f)
}
#undef COMMAND
-struct MonCommand {
- string cmdstring;
- string helpstring;
- string module;
- string req_perms;
- string availability;
-} mon_commands[] = {
+MonCommand mon_commands[] = {
#define COMMAND(parsesig, helptext, modulename, req_perms, avail) \
{parsesig, helptext, modulename, req_perms, avail},
#include <mon/MonCommands.h>
@@ -1909,6 +1903,26 @@ bool Monitor::_allowed_command(MonSession *s, string &module, string &prefix,
return capable;
}
+void get_command_descriptions(const MonCommand *commands,
+ unsigned commands_size,
+ Formatter *f,
+ bufferlist *rdata) {
+ int cmdnum = 0;
+ f->open_object_section("command_descriptions");
+ for (const MonCommand *cp = commands;
+ cp < &commands[commands_size]; cp++) {
+
+ ostringstream secname;
+ secname << "cmd" << setfill('0') << std::setw(3) << cmdnum;
+ dump_cmddesc_to_json(f, secname.str(),
+ cp->cmdstring, cp->helpstring, cp->module,
+ cp->req_perms, cp->availability);
+ cmdnum++;
+ }
+ f->close_section(); // command_descriptions
+
+ f->flush(*rdata);
+}
void Monitor::handle_command(MMonCommand *m)
{
@@ -1953,23 +1967,9 @@ void Monitor::handle_command(MMonCommand *m)
cmd_getval(g_ceph_context, cmdmap, "prefix", prefix);
if (prefix == "get_command_descriptions") {
- int cmdnum = 0;
- Formatter *f = new_formatter("json");
- f->open_object_section("command_descriptions");
- for (MonCommand *cp = mon_commands;
- cp < &mon_commands[ARRAY_SIZE(mon_commands)]; cp++) {
-
- ostringstream secname;
- secname << "cmd" << setfill('0') << std::setw(3) << cmdnum;
- dump_cmddesc_to_json(f, secname.str(),
- cp->cmdstring, cp->helpstring, cp->module,
- cp->req_perms, cp->availability);
- cmdnum++;
- }
- f->close_section(); // command_descriptions
-
bufferlist rdata;
- f->flush(rdata);
+ Formatter *f = new_formatter("json");
+ get_command_descriptions(mon_commands, ARRAY_SIZE(mon_commands), f, &rdata);
delete f;
reply_command(m, 0, "", rdata, 0);
return;
diff --git a/src/mon/Monitor.h b/src/mon/Monitor.h
index df4a751361a..9b304428732 100644
--- a/src/mon/Monitor.h
+++ b/src/mon/Monitor.h
@@ -844,5 +844,17 @@ public:
long parse_pos_long(const char *s, ostream *pss = NULL);
+struct MonCommand {
+ string cmdstring;
+ string helpstring;
+ string module;
+ string req_perms;
+ string availability;
+};
+
+void get_command_descriptions(const MonCommand *commands,
+ unsigned commands_size,
+ Formatter *f,
+ bufferlist *rdata);
#endif
diff --git a/src/pybind/ceph_argparse.py b/src/pybind/ceph_argparse.py
index 427a4621216..f115d3791af 100644
--- a/src/pybind/ceph_argparse.py
+++ b/src/pybind/ceph_argparse.py
@@ -278,7 +278,10 @@ class CephEntityAddr(CephIPAddr):
EntityAddress, that is, IP address/nonce
"""
def valid(self, s, partial=False):
- ip, nonce = s.split('/')
+ try:
+ ip, nonce = s.split('/')
+ except:
+ raise ArgumentValid('{0} must contain a /'.format(s))
super(self.__class__, self).valid(ip)
self.nonce = nonce
self.val = s
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 647aad3550d..5b709d248a8 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -65,6 +65,11 @@ endif
bin_PROGRAMS += ceph-dencoder
+get_command_descriptions_SOURCES = test/common/get_command_descriptions.cc
+get_command_descriptions_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+get_command_descriptions_LDADD = $(LIBMON) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+noinst_PROGRAMS += get_command_descriptions
+
## Build tests
# These should all use explicit _CXXFLAGS so avoid basename conflicts
@@ -228,6 +233,10 @@ bin_DEBUGPROGRAMS += ceph_bench_log
## Unit tests
+check_SCRIPTS += \
+ $(srcdir)/unittest_bufferlist.sh \
+ $(srcdir)/test/encoding/check-generated.sh
+
# target to build but not run the unit tests
unittests:: $(check_PROGRAMS)
@@ -537,6 +546,8 @@ unittest_texttable_LDADD = $(LIBCOMMON) $(UNITTEST_LDADD)
unittest_texttable_CXXFLAGS = $(UNITTEST_CXXFLAGS)
check_PROGRAMS += unittest_texttable
+check_SCRIPTS += test/pybind/test_ceph_argparse.py
+
if WITH_RADOSGW
ceph_test_cors_SOURCES = test/test_cors.cc
ceph_test_cors_LDADD = \
diff --git a/src/test/common/get_command_descriptions.cc b/src/test/common/get_command_descriptions.cc
new file mode 100644
index 00000000000..afca8254c42
--- /dev/null
+++ b/src/test/common/get_command_descriptions.cc
@@ -0,0 +1,116 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library Public License for more details.
+ *
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include "mon/Monitor.h"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+#include "common/debug.h"
+
+#define dout_subsys ceph_subsys_mon
+
+static void usage(ostream &out)
+{
+ out << "usage: get_command_descriptions [options ...]" << std::endl;
+ out << "print on stdout the result of JSON formatted options\n";
+ out << "found in mon/MonCommands.h as produced by the\n";
+ out << "Monitor.cc::get_command_descriptions function.\n";
+ out << "Designed as a helper for ceph_argparse.py unit tests.\n";
+ out << "\n";
+ out << " --all all of mon/MonCommands.h \n";
+ out << " --pull585 reproduce the bug fixed by #585\n";
+ out << "\n";
+ out << "Examples:\n";
+ out << " get_command_descriptions --all\n";
+ out << " get_command_descriptions --pull585\n";
+}
+
+static void json_print(const MonCommand *mon_commands, int size)
+{
+ bufferlist rdata;
+ Formatter *f = new_formatter("json");
+ get_command_descriptions(mon_commands, size, f, &rdata);
+ delete f;
+ string data(rdata.c_str());
+ dout(0) << data << dendl;
+}
+
+static void all()
+{
+#undef COMMAND
+ MonCommand mon_commands[] = {
+#define COMMAND(parsesig, helptext, modulename, req_perms, avail) \
+ {parsesig, helptext, modulename, req_perms, avail},
+#include <mon/MonCommands.h>
+ };
+
+ json_print(mon_commands, ARRAY_SIZE(mon_commands));
+}
+
+// syntax error https://github.com/ceph/ceph/pull/585
+static void pull585()
+{
+ MonCommand mon_commands[] = {
+ { "osd pool create "
+ "name=pool,type=CephPoolname "
+ "name=pg_num,type=CephInt,range=0 "
+ "name=pgp_num,type=CephInt,range=0,req=false" // !!! missing trailing space
+ "name=properties,type=CephString,n=N,req=false,goodchars=[A-Za-z0-9-_.=]",
+ "create pool", "osd", "rw", "cli,rest" }
+ };
+
+ json_print(mon_commands, ARRAY_SIZE(mon_commands));
+}
+
+int main(int argc, char **argv) {
+ vector<const char*> args;
+ argv_to_vec(argc, (const char **)argv, args);
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(g_ceph_context);
+
+ if (args.empty()) {
+ usage(cerr);
+ exit(1);
+ }
+ for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ++i) {
+ string err;
+
+ if (*i == string("help") || *i == string("-h") || *i == string("--help")) {
+ usage(cout);
+ exit(0);
+ } else if (*i == string("--all")) {
+ all();
+ } else if (*i == string("--pull585")) {
+ pull585();
+ }
+ }
+}
+
+/*
+ * Local Variables:
+ * compile-command: "cd ../.. ;
+ * make get_command_descriptions &&
+ * ./get_command_descriptions --all --pull585"
+ * End:
+ */
+
diff --git a/src/test/pybind/test_ceph_argparse.py b/src/test/pybind/test_ceph_argparse.py
new file mode 100755
index 00000000000..85af54d6f75
--- /dev/null
+++ b/src/test/pybind/test_ceph_argparse.py
@@ -0,0 +1,1036 @@
+#!/usr/bin/nosetests --nocapture
+# -*- mode:python; tab-width:4; indent-tabs-mode:t -*-
+# vim: ts=4 sw=4 smarttab expandtab
+#
+# Ceph - scalable distributed file system
+#
+# Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+#
+# Author: Loic Dachary <loic@dachary.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+
+from nose.tools import eq_ as eq
+from nose.tools import *
+
+from ceph_argparse import validate_command, parse_json_funcsigs
+
+import os
+import re
+import json
+
+def get_command_descriptions(what):
+ buffer = os.popen("./get_command_descriptions " + "--" + what
+ + " 2>&1 | grep cmd000").read()
+ return re.sub(r'^.*?(\{.*\})', '\g<1>', buffer)
+
+def test_parse_json_funcsigs():
+ commands = get_command_descriptions("all")
+ cmd_json = parse_json_funcsigs(commands, 'cli')
+
+ # syntax error https://github.com/ceph/ceph/pull/585
+ commands = get_command_descriptions("pull585")
+ assert_raises(TypeError, parse_json_funcsigs, commands, 'cli')
+
+sigdict = parse_json_funcsigs(get_command_descriptions("all"), 'cli')
+
+
+class TestArgparse:
+
+ def assert_valid_command(self, args):
+ result = validate_command(sigdict, args)
+ assert_not_in(result, [None, {}])
+
+ def check_1_natural_arg(self, prefix, command):
+ self.assert_valid_command([prefix, command, '1'])
+ assert_equal({}, validate_command(sigdict, [prefix, command]))
+ assert_equal({}, validate_command(sigdict, [prefix, command, '-1']))
+ assert_equal({}, validate_command(sigdict, [prefix, command, '1',
+ '1']))
+
+ def check_0_or_1_natural_arg(self, prefix, command):
+ self.assert_valid_command([prefix, command, '1'])
+ self.assert_valid_command([prefix, command])
+ assert_equal({}, validate_command(sigdict, [prefix, command, '-1']))
+ assert_equal({}, validate_command(sigdict, [prefix, command, '1',
+ '1']))
+
+ def check_1_string_arg(self, prefix, command):
+ assert_equal({}, validate_command(sigdict, [prefix, command]))
+ self.assert_valid_command([prefix, command, 'string'])
+ assert_equal({}, validate_command(sigdict, [prefix,
+ command,
+ 'string',
+ 'toomany']))
+
+ def check_1_or_more_string_args(self, prefix, command):
+ assert_equal({}, validate_command(sigdict, [prefix,
+ command]))
+ self.assert_valid_command([prefix,
+ command,
+ 'string'])
+ self.assert_valid_command([prefix,
+ command,
+ 'string',
+ 'more string'])
+
+ def check_no_arg(self, prefix, command):
+ self.assert_valid_command([prefix,
+ command])
+ assert_equal({}, validate_command(sigdict, [prefix,
+ command,
+ 'toomany']))
+
+
+class TestPG(TestArgparse):
+
+ def test_stat(self):
+ self.assert_valid_command(['pg', 'stat'])
+
+ def test_getmap(self):
+ self.assert_valid_command(['pg', 'getmap'])
+
+ def test_send_pg_creates(self):
+ self.assert_valid_command(['pg', 'send_pg_creates'])
+
+ def test_dump(self):
+ self.assert_valid_command(['pg', 'dump'])
+ self.assert_valid_command(['pg', 'dump',
+ 'all',
+ 'summary',
+ 'sum',
+ 'delta',
+ 'pools',
+ 'osds',
+ 'pgs',
+ 'pgs_brief'])
+ assert_equal({}, validate_command(sigdict, ['pg', 'dump', 'invalid']))
+
+ def test_dump_json(self):
+ self.assert_valid_command(['pg', 'dump_json'])
+ self.assert_valid_command(['pg', 'dump_json',
+ 'all',
+ 'summary',
+ 'sum',
+ 'pools',
+ 'osds',
+ 'pgs'])
+ assert_equal({}, validate_command(sigdict, ['pg', 'dump_json',
+ 'invalid']))
+
+ def test_dump_pools_json(self):
+ self.assert_valid_command(['pg', 'dump_pools_json'])
+
+ def test_dump_pools_stuck(self):
+ self.assert_valid_command(['pg', 'dump_stuck'])
+ self.assert_valid_command(['pg', 'dump_stuck',
+ 'inactive',
+ 'unclean',
+ 'stale'])
+ assert_equal({}, validate_command(sigdict, ['pg', 'dump_stuck',
+ 'invalid']))
+ self.assert_valid_command(['pg', 'dump_stuck',
+ 'inactive',
+ '1234'])
+
+ def one_pgid(self, command):
+ self.assert_valid_command(['pg', command, '1.1'])
+ assert_equal({}, validate_command(sigdict, ['pg', command]))
+ assert_equal({}, validate_command(sigdict, ['pg', command, '1']))
+
+ def test_map(self):
+ self.one_pgid('map')
+
+ def test_scrub(self):
+ self.one_pgid('scrub')
+
+ def test_deep_scrub(self):
+ self.one_pgid('deep-scrub')
+
+ def test_repair(self):
+ self.one_pgid('repair')
+
+ def test_debug(self):
+ self.assert_valid_command(['pg',
+ 'debug',
+ 'unfound_objects_exist'])
+ self.assert_valid_command(['pg',
+ 'debug',
+ 'degraded_pgs_exist'])
+ assert_equal({}, validate_command(sigdict, ['pg', 'debug']))
+ assert_equal({}, validate_command(sigdict, ['pg', 'debug',
+ 'invalid']))
+
+ def test_force_create_pg(self):
+ self.one_pgid('force_create_pg')
+
+ def set_ratio(self, command):
+ self.assert_valid_command(['pg',
+ command,
+ '0.0'])
+ assert_equal({}, validate_command(sigdict, ['pg', command]))
+ assert_equal({}, validate_command(sigdict, ['pg',
+ command,
+ '2.0']))
+
+ def test_set_full_ratio(self):
+ self.set_ratio('set_full_ratio')
+
+ def test_set_nearfull_ratio(self):
+ self.set_ratio('set_nearfull_ratio')
+
+
+class TestAuth(TestArgparse):
+
+ def test_export(self):
+ self.assert_valid_command(['auth', 'export'])
+ self.assert_valid_command(['auth',
+ 'export',
+ 'string'])
+ assert_equal({}, validate_command(sigdict, ['auth',
+ 'export',
+ 'string',
+ 'toomany']))
+
+ def test_get(self):
+ self.check_1_string_arg('auth', 'get')
+
+ def test_get_key(self):
+ self.check_1_string_arg('auth', 'get-key')
+
+ def test_print_key(self):
+ self.check_1_string_arg('auth', 'print-key')
+ self.check_1_string_arg('auth', 'print_key')
+
+ def test_list(self):
+ self.check_no_arg('auth', 'list')
+
+ def test_import(self):
+ self.check_no_arg('auth', 'import')
+
+ def test_add(self):
+ self.check_1_or_more_string_args('auth', 'add')
+
+ def test_get_or_create_key(self):
+ self.check_1_or_more_string_args('auth', 'get-or-create-key')
+
+ def test_get_or_create(self):
+ self.check_1_or_more_string_args('auth', 'get-or-create')
+
+ def test_caps(self):
+ assert_equal({}, validate_command(sigdict, ['auth',
+ 'caps']))
+ assert_equal({}, validate_command(sigdict, ['auth',
+ 'caps',
+ 'string']))
+ self.assert_valid_command(['auth',
+ 'caps',
+ 'string',
+ 'more string'])
+
+ def test_del(self):
+ self.check_1_string_arg('auth', 'del')
+
+
+class TestMonitor(TestArgparse):
+
+ def test_compact(self):
+ self.assert_valid_command(['compact'])
+
+ def test_scrub(self):
+ self.assert_valid_command(['scrub'])
+
+ def test_fsid(self):
+ self.assert_valid_command(['fsid'])
+
+ def test_log(self):
+ assert_equal({}, validate_command(sigdict, ['log']))
+ self.assert_valid_command(['log', 'a logtext'])
+ self.assert_valid_command(['log', 'a logtext', 'and another'])
+
+ def test_injectargs(self):
+ assert_equal({}, validate_command(sigdict, ['injectargs']))
+ self.assert_valid_command(['injectargs', 'one'])
+ self.assert_valid_command(['injectargs', 'one', 'two'])
+
+ def test_status(self):
+ self.assert_valid_command(['status'])
+
+ def test_health(self):
+ self.assert_valid_command(['health'])
+ self.assert_valid_command(['health', 'detail'])
+ assert_equal({}, validate_command(sigdict, ['health', 'invalid']))
+ assert_equal({}, validate_command(sigdict, ['health', 'detail',
+ 'toomany']))
+
+ def test_df(self):
+ self.assert_valid_command(['df'])
+ self.assert_valid_command(['df', 'detail'])
+ assert_equal({}, validate_command(sigdict, ['df', 'invalid']))
+ assert_equal({}, validate_command(sigdict, ['df', 'detail',
+ 'toomany']))
+
+ def test_report(self):
+ self.assert_valid_command(['report'])
+ self.assert_valid_command(['report', 'tag1'])
+ self.assert_valid_command(['report', 'tag1', 'tag2'])
+
+ def test_quorum_status(self):
+ self.assert_valid_command(['quorum_status'])
+
+ def test_mon_status(self):
+ self.assert_valid_command(['mon_status'])
+
+ def test_sync_force(self):
+ self.assert_valid_command(['sync',
+ 'force',
+ '--yes-i-really-mean-it',
+ '--i-know-what-i-am-doing'])
+ assert_equal({}, validate_command(sigdict, ['sync']))
+ assert_equal({}, validate_command(sigdict, ['sync',
+ 'force']))
+ assert_equal({}, validate_command(sigdict, ['sync',
+ 'force',
+ '--yes-i-really-mean-it']))
+ assert_equal({}, validate_command(sigdict, ['sync',
+ 'force',
+ '--yes-i-really-mean-it',
+ '--i-know-what-i-am-doing',
+ 'toomany']))
+
+ def test_heap(self):
+ assert_equal({}, validate_command(sigdict, ['heap']))
+ assert_equal({}, validate_command(sigdict, ['heap', 'invalid']))
+ self.assert_valid_command(['heap', 'dump'])
+ self.assert_valid_command(['heap', 'start_profiler'])
+ self.assert_valid_command(['heap', 'stop_profiler'])
+ self.assert_valid_command(['heap', 'release'])
+ self.assert_valid_command(['heap', 'stats'])
+
+ def test_quorum(self):
+ assert_equal({}, validate_command(sigdict, ['quorum']))
+ assert_equal({}, validate_command(sigdict, ['quorum', 'invalid']))
+ self.assert_valid_command(['quorum', 'enter'])
+ self.assert_valid_command(['quorum', 'exit'])
+ assert_equal({}, validate_command(sigdict, ['quorum',
+ 'enter',
+ 'toomany']))
+
+ def test_tell(self):
+ assert_equal({}, validate_command(sigdict, ['tell']))
+ assert_equal({}, validate_command(sigdict, ['tell', 'invalid']))
+ for name in ('osd', 'mon', 'client', 'mds'):
+ assert_equal({}, validate_command(sigdict, ['tell', name]))
+ assert_equal({}, validate_command(sigdict, ['tell',
+ name + ".42"]))
+ self.assert_valid_command(['tell', name + ".42", 'something'])
+ self.assert_valid_command(['tell', name + ".42",
+ 'something',
+ 'something else'])
+
+
+class TestMDS(TestArgparse):
+
+ def test_stat(self):
+ self.check_no_arg('mds', 'stat')
+
+ def test_dump(self):
+ self.check_0_or_1_natural_arg('mds', 'dump')
+
+ def test_tell(self):
+ self.assert_valid_command(['mds', 'tell',
+ 'someone',
+ 'something'])
+ self.assert_valid_command(['mds', 'tell',
+ 'someone',
+ 'something',
+ 'something else'])
+ assert_equal({}, validate_command(sigdict, ['mds', 'tell']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'tell',
+ 'someone']))
+
+ def test_compat_show(self):
+ self.assert_valid_command(['mds', 'compat', 'show'])
+ assert_equal({}, validate_command(sigdict, ['mds', 'compat']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'compat',
+ 'show', 'toomany']))
+
+ def test_stop(self):
+ self.assert_valid_command(['mds', 'stop', 'someone'])
+ assert_equal({}, validate_command(sigdict, ['mds', 'stop']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'stop',
+ 'someone', 'toomany']))
+
+ def test_deactivate(self):
+ self.assert_valid_command(['mds', 'deactivate', 'someone'])
+ assert_equal({}, validate_command(sigdict, ['mds', 'deactivate']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'deactivate',
+ 'someone', 'toomany']))
+
+ def test_set_max_mds(self):
+ self.check_1_natural_arg('mds', 'set_max_mds')
+
+ def test_setmap(self):
+ self.check_1_natural_arg('mds', 'setmap')
+
+ def test_set_state(self):
+ self.assert_valid_command(['mds', 'set_state', '1', '2'])
+ assert_equal({}, validate_command(sigdict, ['mds', 'set_state']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'set_state', '-1']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'set_state',
+ '1', '-1']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'set_state',
+ '1', '21']))
+
+ def test_fail(self):
+ self.check_1_string_arg('mds', 'fail')
+
+ def test_rm(self):
+ assert_equal({}, validate_command(sigdict, ['mds', 'rm']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'rm', '1']))
+ for name in ('osd', 'mon', 'client', 'mds'):
+ self.assert_valid_command(['mds', 'rm', '1', name + '.42'])
+ assert_equal({}, validate_command(sigdict, ['mds', 'rm',
+ '-1', name + '.42']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'rm',
+ '-1', name]))
+ assert_equal({}, validate_command(sigdict, ['mds', 'rm',
+ '1', name + '.42',
+ 'toomany']))
+
+ def test_rmfailed(self):
+ self.check_1_natural_arg('mds', 'rmfailed')
+
+ def test_cluster_down(self):
+ self.check_no_arg('mds', 'cluster_down')
+
+ def test_cluster_up(self):
+ self.check_no_arg('mds', 'cluster_up')
+
+ def test_compat_rm_compat(self):
+ self.assert_valid_command(['mds', 'compat', 'rm_compat', '1'])
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'compat',
+ 'rm_compat']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'compat',
+ 'rm_compat', '-1']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'compat',
+ 'rm_compat', '1', '1']))
+
+ def test_incompat_rm_incompat(self):
+ self.assert_valid_command(['mds', 'compat', 'rm_incompat', '1'])
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'compat',
+ 'rm_incompat']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'compat',
+ 'rm_incompat', '-1']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'compat',
+ 'rm_incompat', '1', '1']))
+
+ def test_add_data_pool(self):
+ self.check_1_natural_arg('mds', 'add_data_pool')
+
+ def test_remove_data_pool(self):
+ self.check_1_natural_arg('mds', 'remove_data_pool')
+
+ def test_newfs(self):
+ self.assert_valid_command(['mds', 'newfs', '1', '2',
+ '--yes-i-really-mean-it'])
+ assert_equal({}, validate_command(sigdict, ['mds', 'newfs']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'newfs', '1']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'newfs', '1', '1']))
+ assert_equal({}, validate_command(sigdict, ['mds', 'newfs', '1', '1',
+ 'no I dont']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'newfs',
+ '1',
+ '2',
+ '--yes-i-really-mean-it',
+ 'toomany']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'newfs',
+ '-1',
+ '2',
+ '--yes-i-really-mean-it']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'newfs',
+ '1',
+ '-1',
+ '--yes-i-really-mean-it']))
+
+
+class TestMon(TestArgparse):
+
+ def test_dump(self):
+ self.check_0_or_1_natural_arg('mon', 'dump')
+
+ def test_stat(self):
+ self.check_no_arg('mon', 'stat')
+
+ def test_getmap(self):
+ self.check_0_or_1_natural_arg('mon', 'getmap')
+
+ def test_add(self):
+ self.assert_valid_command(['mon', 'add', 'name', '1.2.3.4:1234'])
+ assert_equal({}, validate_command(sigdict, ['mon', 'add']))
+ assert_equal({}, validate_command(sigdict, ['mon', 'add', 'name']))
+ assert_equal({}, validate_command(sigdict, ['mon', 'add',
+ 'name',
+ '400.500.600.700']))
+ assert_equal({}, validate_command(sigdict, ['mon', 'add', 'name',
+ '1.2.3.4:1234',
+ 'toomany']))
+
+ def test_remove(self):
+ self.assert_valid_command(['mon', 'remove', 'name'])
+ assert_equal({}, validate_command(sigdict, ['mon', 'remove']))
+ assert_equal({}, validate_command(sigdict, ['mon', 'remove',
+ 'name', 'toomany']))
+
+
+class TestOSD(TestArgparse):
+
+ def test_stat(self):
+ self.check_no_arg('osd', 'stat')
+
+ def test_dump(self):
+ self.check_0_or_1_natural_arg('osd', 'dump')
+
+ def test_osd_tree(self):
+ self.check_0_or_1_natural_arg('osd', 'tree')
+
+ def test_osd_ls(self):
+ self.check_0_or_1_natural_arg('osd', 'ls')
+
+ def test_osd_getmap(self):
+ self.check_0_or_1_natural_arg('osd', 'getmap')
+
+ def test_osd_getcrushmap(self):
+ self.check_0_or_1_natural_arg('osd', 'getcrushmap')
+
+ def test_perf(self):
+ self.check_no_arg('osd', 'perf')
+
+ def test_getmaxosd(self):
+ self.check_no_arg('osd', 'getmaxosd')
+
+ def test_find(self):
+ self.check_1_natural_arg('osd', 'find')
+
+ def test_map(self):
+ self.assert_valid_command(['osd', 'map', 'poolname', 'objectname'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'map']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'map', 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'map',
+ 'poolname', 'objectname',
+ 'toomany']))
+
+ def test_scrub(self):
+ self.check_1_string_arg('osd', 'scrub')
+
+ def test_deep_scrub(self):
+ self.check_1_string_arg('osd', 'deep-scrub')
+
+ def test_repair(self):
+ self.check_1_string_arg('osd', 'repair')
+
+ def test_lspools(self):
+ self.assert_valid_command(['osd', 'lspools'])
+ self.assert_valid_command(['osd', 'lspools', '1'])
+ self.assert_valid_command(['osd', 'lspools', '-1'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'lspools',
+ '1', 'toomany']))
+
+ def test_blacklist_ls(self):
+ self.assert_valid_command(['osd', 'blacklist', 'ls'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'blacklist']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'blacklist',
+ 'ls', 'toomany']))
+
+ def test_crush_rule(self):
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule']))
+ for subcommand in ('list', 'ls', 'dump'):
+ self.assert_valid_command(['osd', 'crush', 'rule', subcommand])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'rule', subcommand,
+ 'toomany']))
+
+ def test_crush_dump(self):
+ self.assert_valid_command(['osd', 'crush', 'dump'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'dump', 'toomany']))
+
+ def test_setcrushmap(self):
+ self.check_no_arg('osd', 'setcrushmap')
+
+ def test_crush_add_bucket(self):
+ self.assert_valid_command(['osd', 'crush', 'add-bucket',
+ 'name', 'type'])
+ 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']))
+
+ def check_crush_setter(self, setter):
+ self.assert_valid_command(['osd', 'crush', setter,
+ '*', '2.3', 'AZaz09-_.='])
+ self.assert_valid_command(['osd', 'crush', setter,
+ 'osd.0', '2.3', 'AZaz09-_.='])
+ self.assert_valid_command(['osd', 'crush', setter,
+ '0', '2.3', 'AZaz09-_.='])
+ self.assert_valid_command(['osd', 'crush', setter,
+ '0', '2.3', 'AZaz09-_.=', 'AZaz09-_.='])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ setter,
+ 'osd.0']))
+ assert_in(validate_command(sigdict, ['osd', 'crush',
+ setter,
+ 'osd.0',
+ '-1.0']),
+ [None, {}])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ setter,
+ 'osd.0',
+ '1.0',
+ '!!!']))
+
+ def test_crush_set(self):
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
+ self.check_crush_setter('set')
+
+ def test_crush_add(self):
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
+ self.check_crush_setter('add')
+
+ def test_crush_create_or_move(self):
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
+ self.check_crush_setter('create-or-move')
+
+ def test_crush_move(self):
+ self.assert_valid_command(['osd', 'crush', 'move',
+ 'AZaz09-_.', 'AZaz09-_.='])
+ self.assert_valid_command(['osd', 'crush', 'move',
+ '0', 'AZaz09-_.=', 'AZaz09-_.='])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'move']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'move', 'AZaz09-_.']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'move', '!!!',
+ 'AZaz09-_.=']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'move', 'AZaz09-_.',
+ '!!!']))
+
+ def test_crush_link(self):
+ self.assert_valid_command(['osd', 'crush', 'link',
+ 'name', 'AZaz09-_.='])
+ self.assert_valid_command(['osd', 'crush', 'link',
+ 'name', 'AZaz09-_.=', 'AZaz09-_.='])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'link']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'link',
+ 'name']))
+
+ def test_crush_rm(self):
+ for alias in ('rm', 'remove', 'unlink'):
+ self.assert_valid_command(['osd', 'crush', alias, 'AZaz09-_.'])
+ self.assert_valid_command(['osd', 'crush', alias,
+ 'AZaz09-_.', 'AZaz09-_.'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ alias]))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ alias,
+ 'AZaz09-_.',
+ 'AZaz09-_.',
+ 'toomany']))
+
+ def test_crush_reweight(self):
+ self.assert_valid_command(['osd', 'crush', 'reweight',
+ 'AZaz09-_.', '2.3'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'reweight']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'reweight',
+ 'AZaz09-_.']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'reweight',
+ 'AZaz09-_.',
+ '-1.0']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'reweight',
+ '!!!',
+ '2.3']))
+
+ def test_crush_tunables(self):
+ for tunable in ('legacy', 'argonaut', 'bobtail', 'optimal', 'default'):
+ self.assert_valid_command(['osd', 'crush', 'tunables',
+ tunable])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'tunables']))
+ assert_equal(None, validate_command(sigdict, ['osd', 'crush',
+ 'default', 'toomany']))
+
+ def test_crush_rule_create_simple(self):
+ self.assert_valid_command(['osd', 'crush', 'rule', 'create-simple',
+ 'AZaz09-_.', 'AZaz09-_.', 'AZaz09-_.'])
+ assert_equal(None, validate_command(sigdict, ['osd', 'crush',
+ 'create-simple']))
+ assert_equal(None, validate_command(sigdict, ['osd', 'crush',
+ 'create-simple',
+ 'AZaz09-_.']))
+ assert_equal(None, validate_command(sigdict, ['osd', 'crush',
+ 'create-simple',
+ 'AZaz09-_.',
+ 'AZaz09-_.']))
+ assert_equal(None, validate_command(sigdict, ['osd', 'crush',
+ 'create-simple',
+ '!!!',
+ 'AZaz09-_.',
+ 'AZaz09-_.']))
+ assert_equal(None, validate_command(sigdict, ['osd', 'crush',
+ 'create-simple',
+ 'AZaz09-_.',
+ '|||',
+ 'AZaz09-_.']))
+ assert_equal(None, validate_command(sigdict, ['osd', 'crush',
+ 'create-simple',
+ 'AZaz09-_.',
+ 'AZaz09-_.',
+ '+++']))
+ assert_equal(None, validate_command(sigdict, ['osd', 'crush',
+ 'create-simple',
+ 'AZaz09-_.',
+ 'AZaz09-_.',
+ 'AZaz09-_.',
+ 'toomany']))
+
+ def test_crush_rule_rm(self):
+ self.assert_valid_command(['osd', 'crush', 'rule', 'rm', 'AZaz09-_.'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'rule', 'rm']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'rule', 'rm',
+ '!!!!']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'crush',
+ 'rule', 'rm',
+ 'AZaz09-_.',
+ 'toomany']))
+
+ def test_setmaxosd(self):
+ self.check_1_natural_arg('osd', 'setmaxosd')
+
+ def test_pause(self):
+ self.check_no_arg('osd', 'pause')
+
+ def test_unpause(self):
+ self.check_no_arg('osd', 'unpause')
+
+ def test_set_unset(self):
+ for action in ('set', 'unset'):
+ for flag in ('pause', 'noup', 'nodown', 'noout', 'noin',
+ 'nobackfill', 'norecover', 'noscrub', 'nodeep-scrub'):
+ self.assert_valid_command(['osd', action, flag])
+ assert_equal({}, validate_command(sigdict, ['osd', action]))
+ assert_equal({}, validate_command(sigdict, ['osd', action,
+ 'invalid']))
+ assert_equal({}, validate_command(sigdict, ['osd', action,
+ 'pause', 'toomany']))
+
+ def test_cluster_snap(self):
+ assert_equal(None, validate_command(sigdict, ['osd', 'cluster_snap']))
+
+ def test_down(self):
+ self.check_1_or_more_string_args('osd', 'down')
+
+ def test_out(self):
+ self.check_1_or_more_string_args('osd', 'out')
+
+ def test_in(self):
+ self.check_1_or_more_string_args('osd', 'in')
+
+ def test_rm(self):
+ self.check_1_or_more_string_args('osd', 'rm')
+
+ def test_reweight(self):
+ self.assert_valid_command(['osd', 'reweight', '1', '0.1'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'reweight']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'reweight',
+ '1']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'reweight',
+ '1', '2.0']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'reweight',
+ '-1', '0.1']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'reweight',
+ '1', '0.1',
+ 'toomany']))
+
+ def test_lost(self):
+ self.assert_valid_command(['osd', 'lost', '1',
+ '--yes-i-really-mean-it'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'lost']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'lost',
+ '1']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'lost',
+ '1',
+ 'what?']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'lost',
+ '-1',
+ '--yes-i-really-mean-it']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'lost',
+ '1',
+ '--yes-i-really-mean-it',
+ 'toomany']))
+
+ def test_create(self):
+ uuid = '12345678123456781234567812345678'
+ self.assert_valid_command(['osd', 'create'])
+ self.assert_valid_command(['osd', 'create',
+ uuid])
+ assert_equal({}, validate_command(sigdict, ['osd', 'create',
+ 'invalid']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'create',
+ uuid,
+ 'toomany']))
+
+ def test_blackist(self):
+ for action in ('add', 'rm'):
+ self.assert_valid_command(['osd', 'blacklist', action,
+ '1.2.3.4/nonce'])
+ self.assert_valid_command(['osd', 'blacklist', action,
+ '1.2.3.4/nonce', '600.40'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'blacklist',
+ action,
+ 'invalid',
+ '600.40']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'blacklist',
+ action,
+ '1.2.3.4/nonce',
+ '-1.0']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'blacklist',
+ action,
+ '1.2.3.4/nonce',
+ '600.40',
+ 'toomany']))
+
+ def test_pool_mksnap(self):
+ self.assert_valid_command(['osd', 'pool', 'mksnap',
+ 'poolname', 'snapname'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'mksnap']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'mksnap',
+ 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'mksnap',
+ 'poolname', 'snapname',
+ 'toomany']))
+
+ def test_pool_rmsnap(self):
+ self.assert_valid_command(['osd', 'pool', 'rmsnap',
+ 'poolname', 'snapname'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rmsnap']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rmsnap',
+ 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rmsnap',
+ 'poolname', 'snapname',
+ 'toomany']))
+
+ def test_pool_create(self):
+ self.assert_valid_command(['osd', 'pool', 'create',
+ 'poolname', '128'])
+ self.assert_valid_command(['osd', 'pool', 'create',
+ 'poolname', '128', '128'])
+ self.assert_valid_command(['osd', 'pool', 'create',
+ 'poolname', '128', '128',
+ 'foo=bar'])
+ self.assert_valid_command(['osd', 'pool', 'create',
+ 'poolname', '128', '128',
+ 'foo=bar', 'baz=frob'])
+ self.assert_valid_command(['osd', 'pool', 'create',
+ 'poolname', '128',
+ 'foo=bar', 'baz=frob'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'create']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'create',
+ 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'create',
+ 'poolname', '-1']))
+
+ def test_pool_delete(self):
+ self.assert_valid_command(['osd', 'pool', 'delete',
+ 'poolname', 'poolname',
+ '--yes-i-really-really-mean-it'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'delete']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'delete',
+ 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'delete',
+ 'poolname', 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'delete',
+ 'poolname', 'poolname',
+ 'not really']))
+ assert_equal({}, validate_command(sigdict,
+ ['osd', 'pool', 'delete',
+ 'poolname', 'poolname',
+ '--yes-i-really-really-mean-it',
+ 'toomany']))
+
+ def test_pool_rename(self):
+ self.assert_valid_command(['osd', 'pool', 'rename',
+ 'poolname', 'othername'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rename']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rename',
+ 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rename',
+ 'poolname', 'othername',
+ 'toomany']))
+
+ def test_pool_get(self):
+ for var in ('size', 'min_size', 'crash_replay_interval',
+ 'pg_num', 'pgp_num', 'crush_ruleset'):
+ self.assert_valid_command(['osd', 'pool', 'get', 'poolname', var])
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'get']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'get', 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'get', 'poolname',
+ 'size', 'toomany']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'get', 'poolname',
+ 'invalid']))
+
+ def test_pool_set(self):
+ for var in ('size', 'min_size', 'crash_replay_interval',
+ 'pg_num', 'pgp_num', 'crush_ruleset'):
+ self.assert_valid_command(['osd', 'pool',
+ 'set', 'poolname', var, '-1'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set', 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set', 'poolname',
+ 'size', 'invalid']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set', 'poolname',
+ 'invalid', '-1']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set', 'poolname',
+ 'size', '-1',
+ 'toomany']))
+
+ def test_pool_set_quota(self):
+ for field in ('max_objects', 'max_bytes'):
+ self.assert_valid_command(['osd', 'pool', 'set-quota',
+ 'poolname', field, '10K'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set-quota']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set-quota',
+ 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set-quota',
+ 'poolname',
+ 'max_objects']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set-quota',
+ 'poolname',
+ 'invalid',
+ '10K']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'pool',
+ 'set-quota',
+ 'poolname',
+ 'max_objects',
+ '10K',
+ 'toomany']))
+
+ def test_reweight_by_utilization(self):
+ self.assert_valid_command(['osd', 'reweight-by-utilization'])
+ self.assert_valid_command(['osd', 'reweight-by-utilization', '100'])
+ assert_equal({}, validate_command(sigdict, ['osd',
+ 'reweight-by-utilization',
+ '50']))
+ assert_equal({}, validate_command(sigdict, ['osd',
+ 'reweight-by-utilization',
+ '100',
+ 'toomany']))
+
+ def test_thrash(self):
+ self.check_1_natural_arg('osd', 'thrash')
+
+ def test_tier_op(self):
+ for op in ('add', 'remove', 'set-overlay'):
+ self.assert_valid_command(['osd', 'tier', op,
+ 'poolname', 'othername'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'tier', op]))
+ assert_equal({}, validate_command(sigdict, ['osd', 'tier', op,
+ 'poolname']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'tier', op,
+ 'poolname',
+ 'othername',
+ 'toomany']))
+
+ def test_tier_cache_mode(self):
+ for mode in ('none', 'writeback', 'invalidate+forward', 'readonly'):
+ self.assert_valid_command(['osd', 'tier', 'cache-mode',
+ 'poolname', mode])
+ assert_equal({}, validate_command(sigdict, ['osd', 'tier',
+ 'cache-mode']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'tier',
+ 'cache-mode',
+ 'invalid']))
+
+ def test_tier_remove_overlay(self):
+ self.assert_valid_command(['osd', 'tier', 'remove-overlay',
+ 'poolname'])
+ assert_equal({}, validate_command(sigdict, ['osd', 'tier',
+ 'remove-overlay']))
+ assert_equal({}, validate_command(sigdict, ['osd', 'tier',
+ 'remove-overlay',
+ 'poolname',
+ 'toomany']))
+
+
+class TestConfigKey(TestArgparse):
+
+ def test_get(self):
+ self.check_1_string_arg('config-key', 'get')
+
+ def test_put(self):
+ self.assert_valid_command(['config-key', 'put',
+ 'key'])
+ self.assert_valid_command(['config-key', 'put',
+ 'key', 'value'])
+ assert_equal({}, validate_command(sigdict, ['config-key', 'put']))
+ assert_equal({}, validate_command(sigdict, ['config-key', 'put',
+ 'key', 'value',
+ 'toomany']))
+
+ def test_del(self):
+ self.check_1_string_arg('config-key', 'del')
+
+ def test_exists(self):
+ self.check_1_string_arg('config-key', 'exists')
+
+ def test_list(self):
+ self.check_no_arg('config-key', 'list')
+# Local Variables:
+# compile-command: "cd ../.. ; make -j4 &&
+# PYTHONPATH=pybind nosetests --stop \
+# test/pybind/test_ceph_argparse.py # test_ceph_argparse.py:TestOSD.test_rm"
+# End: