]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ceph-volume: an osd ID must exist and be destroyed before reuse 23093/head
authorAndrew Schoen <aschoen@redhat.com>
Mon, 16 Jul 2018 21:06:03 +0000 (16:06 -0500)
committerAndrew Schoen <aschoen@redhat.com>
Tue, 17 Jul 2018 13:13:07 +0000 (08:13 -0500)
Fixes: https://tracker.ceph.com/issues/24044
Signed-off-by: Andrew Schoen <aschoen@redhat.com>
src/ceph-volume/ceph_volume/tests/util/test_prepare.py
src/ceph-volume/ceph_volume/util/prepare.py

index 23dce21c5641ffc730dd4acc1751ab29592a67a0..8148a7f2d18f45e11d17b45e0614bee0c8dcdee7 100644 (file)
@@ -7,24 +7,24 @@ from ceph_volume import conf
 from ceph_volume.tests.conftest import Factory
 
 
-class TestCheckID(object):
+class TestOSDIDAvailable(object):
 
     def test_false_if_id_is_none(self):
-        assert not prepare.check_id(None)
+        assert not prepare.osd_id_available(None)
 
     def test_returncode_is_not_zero(self, monkeypatch):
         monkeypatch.setattr('ceph_volume.process.call', lambda *a, **kw: ('', '', 1))
         with pytest.raises(RuntimeError):
-            prepare.check_id(1)
+            prepare.osd_id_available(1)
 
-    def test_id_does_exist(self, monkeypatch):
+    def test_id_does_exist_but_not_available(self, monkeypatch):
         stdout = dict(nodes=[
-            dict(id=0),
+            dict(id=0, status="up"),
         ])
         stdout = ['', json.dumps(stdout)]
         monkeypatch.setattr('ceph_volume.process.call', lambda *a, **kw: (stdout, '', 0))
-        result = prepare.check_id(0)
-        assert result
+        result = prepare.osd_id_available(0)
+        assert not result
 
     def test_id_does_not_exist(self, monkeypatch):
         stdout = dict(nodes=[
@@ -32,7 +32,7 @@ class TestCheckID(object):
         ])
         stdout = ['', json.dumps(stdout)]
         monkeypatch.setattr('ceph_volume.process.call', lambda *a, **kw: (stdout, '', 0))
-        result = prepare.check_id(1)
+        result = prepare.osd_id_available(1)
         assert not result
 
     def test_invalid_osd_id(self, monkeypatch):
@@ -41,9 +41,18 @@ class TestCheckID(object):
         ])
         stdout = ['', json.dumps(stdout)]
         monkeypatch.setattr('ceph_volume.process.call', lambda *a, **kw: (stdout, '', 0))
-        result = prepare.check_id("foo")
+        result = prepare.osd_id_available("foo")
         assert not result
 
+    def test_returns_true_when_id_is_destroyed(self, monkeypatch):
+        stdout = dict(nodes=[
+            dict(id=0, status="destroyed"),
+        ])
+        stdout = ['', json.dumps(stdout)]
+        monkeypatch.setattr('ceph_volume.process.call', lambda *a, **kw: (stdout, '', 0))
+        result = prepare.osd_id_available(0)
+        assert result
+
 
 class TestFormatDevice(object):
 
index 59d60fc0cbeeb169e07033891a469aab890aa705..32d5fe20d53bd296810fd1479718096d76824ccc 100644 (file)
@@ -64,8 +64,11 @@ def create_id(fsid, json_secrets, osd_id=None):
         '-i', '-',
         'osd', 'new', fsid
     ]
-    if osd_id is not None and not osd_id_exists(osd_id):
-        cmd.append(osd_id)
+    if osd_id is not None:
+        if osd_id_available(osd_id):
+            cmd.append(osd_id)
+        else:
+            raise RuntimeError("The osd ID {} is already in use or does not exist.".format(osd_id))
     stdout, stderr, returncode = process.call(
         cmd,
         stdin=json_secrets,
@@ -76,10 +79,10 @@ def create_id(fsid, json_secrets, osd_id=None):
     return ' '.join(stdout).strip()
 
 
-def osd_id_exists(osd_id):
+def osd_id_available(osd_id):
     """
-    Checks to see if an osd ID exists or not. Returns True
-    if it does exist, False if it doesn't.
+    Checks to see if an osd ID exists and if it's available for
+    reuse. Returns True if it is, False if it isn't.
 
     :param osd_id: The osd ID to check
     """
@@ -103,7 +106,10 @@ def osd_id_exists(osd_id):
 
     output = json.loads(''.join(stdout).strip())
     osds = output['nodes']
-    return any([str(osd['id']) == str(osd_id) for osd in osds])
+    osd = [osd for osd in osds if str(osd['id']) == str(osd_id)]
+    if osd and osd[0].get('status') == "destroyed":
+        return True
+    return False
 
 
 def mount_tmpfs(path):