Skip to content

Commit

Permalink
ceph-volume: an osd ID must exist and be destroyed before reuse
Browse files Browse the repository at this point in the history
Fixes: https://tracker.ceph.com/issues/24044

Signed-off-by: Andrew Schoen <aschoen@redhat.com>
(cherry picked from commit 02a13f2)
  • Loading branch information
andrewschoen committed Jul 17, 2018
1 parent 0021e9c commit cd843d9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 15 deletions.
27 changes: 18 additions & 9 deletions src/ceph-volume/ceph_volume/tests/util/test_prepare.py
Expand Up @@ -7,32 +7,32 @@
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=[
dict(id=0),
])
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):
Expand All @@ -41,9 +41,18 @@ def test_invalid_osd_id(self, monkeypatch):
])
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):

Expand Down
18 changes: 12 additions & 6 deletions src/ceph-volume/ceph_volume/util/prepare.py
Expand Up @@ -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,
Expand All @@ -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
"""
Expand All @@ -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):
Expand Down

0 comments on commit cd843d9

Please sign in to comment.