summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-01-26 13:45:12 -0800
committerSage Weil <sage@inktank.com>2013-01-26 13:45:12 -0800
commitbbb86ec79409bc906c08c896e855d2a7b556fb9f (patch)
treeed7dc6c1c7b3ae0f9c98f1b7dc61484ce87bddf2
parent700bcede4d07b0565adcb081414cf840bbf17d66 (diff)
downloadceph-bbb86ec79409bc906c08c896e855d2a7b556fb9f.tar.gz
mon: safety interlock for pool deletion
Require that the pool name be passed twice along with an force option before we irreversibly delete an entire pool of objects. Signed-off-by: Sage Weil <sage@inktank.com>
-rwxr-xr-xqa/workunits/mon/pool_ops.sh10
-rwxr-xr-xqa/workunits/rbd/copy.sh17
-rwxr-xr-xqa/workunits/rbd/permissions.sh4
-rw-r--r--src/mon/OSDMonitor.cc25
4 files changed, 36 insertions, 20 deletions
diff --git a/qa/workunits/mon/pool_ops.sh b/qa/workunits/mon/pool_ops.sh
index 0fed24d7474..a9e9f422c40 100755
--- a/qa/workunits/mon/pool_ops.sh
+++ b/qa/workunits/mon/pool_ops.sh
@@ -7,9 +7,13 @@ ceph osd pool create fooo 123
ceph osd pool create foo 123 # idempotent
-ceph osd pool delete foo
-ceph osd pool delete foo
-ceph osd pool delete fuggg
+ceph osd pool delete foo && exit 1 || true # should fail due to safety interlock
+ceph osd pool delete foo foo && exit 1 || true # should fail due to safety interlock
+ceph osd pool delete foo foo --force && exit 1 || true # should fail due to safety interlock
+
+ceph osd pool delete foo foo --yes-i-really-really-mean-it
+ceph osd pool delete foo foo --yes-i-really-really-mean-it
+ceph osd pool delete fuggg fugg --yes-i-really-really-mean-it
ceph osd pool delete fooo
diff --git a/qa/workunits/rbd/copy.sh b/qa/workunits/rbd/copy.sh
index cd0bea79c2c..e2465fa3c45 100755
--- a/qa/workunits/rbd/copy.sh
+++ b/qa/workunits/rbd/copy.sh
@@ -1,5 +1,8 @@
#!/bin/sh -ex
+# make sure rbd pool is EMPTY.. this is a test script!!
+rbd ls | wc -l | grep -v '^0$' && echo "nonempty rbd pool, aborting! run this script on an empty test cluster only." && exit 1
+
IMGS="testimg1 testimg2 testimg3 foo foo2 bar bar2 test1 test2 test3"
remove_images() {
@@ -90,7 +93,7 @@ test_rename() {
! rbd rename rbd2/bar --dest-pool rbd foo
rbd rename --pool rbd2 bar --dest-pool rbd2 foo
rbd -p rbd2 ls | grep foo
- rados rmpool rbd2
+ rados rmpool rbd2 rbd2 --yes-i-really-really-mean-it
remove_images
}
@@ -234,7 +237,7 @@ test_pool_image_args() {
echo "testing pool and image args..."
remove_images
- ceph osd pool delete test || true
+ ceph osd pool delete test test --yes-i-really-really-mean-it || true
ceph osd pool create test 100
truncate -s 1 /tmp/empty
@@ -283,8 +286,8 @@ test_pool_image_args() {
rbd ls test | grep -qv test12
rm -f /tmp/empty
- ceph osd pool delete test
- ceph osd pool delete rbd
+ ceph osd pool delete test test --yes-i-really-really-mean-it
+ ceph osd pool delete rbd rbd --yes-i-really-really-mean-it
ceph osd pool create rbd 100
}
@@ -307,9 +310,9 @@ test_clone() {
rbd ls -l | grep clone2 | grep rbd2/clone@s1
rbd -p rbd2 ls | grep -v clone2
- rados rmpool rbd2
- rados rmpool rbd
- rados mkpool rbd
+ rados rmpool rbd2 rbd2 --yes-i-really-really-mean-it
+ rados rmpool rbd rbd --yes-i-really-really-mean-it
+ rados mkpool rbd rbd --yes-i-really-really-mean-it
}
test_pool_image_args
diff --git a/qa/workunits/rbd/permissions.sh b/qa/workunits/rbd/permissions.sh
index 40428df38e3..74c24c03c2b 100755
--- a/qa/workunits/rbd/permissions.sh
+++ b/qa/workunits/rbd/permissions.sh
@@ -6,8 +6,8 @@ create_pools() {
}
delete_pools() {
- (ceph osd pool delete images || true) >/dev/null 2>&1
- (ceph osd pool delete volumes || true) >/dev/null 2>&1
+ (ceph osd pool delete images images --yes-i-really-really-mean-it || true) >/dev/null 2>&1
+ (ceph osd pool delete volumes volumes --yes-i-really-really-mean-it || true) >/dev/null 2>&1
}
diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc
index 226229591d3..5786713e043 100644
--- a/src/mon/OSDMonitor.cc
+++ b/src/mon/OSDMonitor.cc
@@ -2779,19 +2779,28 @@ bool OSDMonitor::prepare_command(MMonCommand *m)
paxos->wait_for_commit(new Monitor::C_Command(mon, m, 0, rs, paxos->get_version()));
return true;
} else if (m->cmd[2] == "delete" && m->cmd.size() >= 4) {
- //hey, let's delete a pool!
+ // osd pool delete <poolname> <poolname again> --yes-i-really-really-mean-it
int64_t pool = osdmap.lookup_pg_pool_name(m->cmd[3].c_str());
if (pool < 0) {
ss << "pool '" << m->cmd[3] << "' does not exist";
err = 0;
- } else {
- int ret = _prepare_remove_pool(pool);
- if (ret == 0)
- ss << "pool '" << m->cmd[3] << "' deleted";
- getline(ss, rs);
- paxos->wait_for_commit(new Monitor::C_Command(mon, m, ret, rs, paxos->get_version()));
- return true;
+ goto out;
}
+ if (m->cmd.size() != 6 ||
+ m->cmd[3] != m->cmd[4] ||
+ m->cmd[5] != "--yes-i-really-really-mean-it") {
+ ss << "WARNING: this will *PERMANENTLY DESTROY* all data stored in pool " << m->cmd[3]
+ << ". If you are *ABSOLUTELY CERTAIN* that is what you want, pass the pool name *twice*, "
+ << "followed by --yes-i-really-really-mean-it.";
+ err = -EPERM;
+ goto out;
+ }
+ int ret = _prepare_remove_pool(pool);
+ if (ret == 0)
+ ss << "pool '" << m->cmd[3] << "' deleted";
+ getline(ss, rs);
+ paxos->wait_for_commit(new Monitor::C_Command(mon, m, ret, rs, paxos->get_version()));
+ return true;
} else if (m->cmd[2] == "rename" && m->cmd.size() == 5) {
int64_t pool = osdmap.lookup_pg_pool_name(m->cmd[3].c_str());
if (pool < 0) {