summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-03-04 16:38:57 -0800
committerSage Weil <sage@inktank.com>2013-03-04 17:30:13 -0800
commit3bd0ac0ab011c4cdf0121f0d9732938d085fb8bf (patch)
tree88c36c9a0f4b22114b5ce6972bd386e644cdb443
parentf03f62697f170d42b4b62c53d2860ff2f24a2d73 (diff)
downloadceph-3bd0ac0ab011c4cdf0121f0d9732938d085fb8bf.tar.gz
ceph-disk-prepare: verify device is not mounted before using
Make sure the data and/or journal device(s) are not in use (mounted) before using them. Make room for additional "in-use" checks in the future. Closes: #3256 Signed-off-by: Sage Weil <sage@inktank.com>
-rwxr-xr-xsrc/ceph-disk-prepare51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/ceph-disk-prepare b/src/ceph-disk-prepare
index 3dd7e2950c2..ef39a009b5c 100755
--- a/src/ceph-disk-prepare
+++ b/src/ceph-disk-prepare
@@ -4,6 +4,7 @@ import argparse
import logging
import os
import os.path
+import re
import subprocess
import stat
import sys
@@ -70,6 +71,24 @@ class UnmountError(PrepareError):
Unmounting filesystem failed
"""
+def list_partitions(disk):
+ """
+ Return a list of partitions on the given device
+ """
+ disk = os.path.realpath(disk)
+ assert not is_partition(disk)
+ assert disk.startswith('/dev/')
+ base = disk[5:]
+ ls = []
+ with file('/proc/partitions', 'rb') as f:
+ for line in f.read().split('\n')[2:]:
+ fields = re.split('\s+', line)
+ if len(fields) < 5:
+ continue
+ (_, major, minor, blocks, name) = fields
+ if name != base and name.startswith(base):
+ ls.append('/dev/' + name)
+ return ls
def is_partition(dev):
"""
@@ -84,6 +103,29 @@ def is_partition(dev):
return True
return False
+def is_mounted(dev):
+ """
+ Check if the given device is mounted.
+ """
+ dev = os.path.realpath(dev)
+ with file('/proc/mounts') as f:
+ for line in f.read().split('\n'):
+ d = line.split(' ')[0]
+ if os.path.exists(d):
+ d = os.path.realpath(d)
+ if dev == d:
+ return True
+ return False
+
+def verify_not_in_use(dev):
+ assert os.path.exists(dev)
+ if is_partition(dev):
+ if is_mounted(dev):
+ raise PrepareError('Device is mounted', dev)
+ else:
+ for p in list_partitions(dev):
+ if is_mounted(p):
+ raise PrepareError('Device is mounted', p)
def write_one_line(parent, name, text):
"""
@@ -373,6 +415,9 @@ def prepare_journal_dev(
journal_dm_keypath,
):
+ if os.path.exists(journal):
+ verify_not_in_use(journal)
+
if is_partition(journal):
log.debug('Journal %s is a partition', journal)
log.warning('OSD will not be hot-swappable if journal is not the same device as the osd data')
@@ -860,8 +905,12 @@ def main():
)
journal_size = int(journal_size)
- # colocate journal with data?
+ # in use?
dmode = os.stat(args.data).st_mode
+ if stat.S_ISBLK(dmode):
+ verify_not_in_use(args.data)
+
+ # colocate journal with data?
if stat.S_ISBLK(dmode) and not is_partition(args.data) and args.journal is None and args.journal_file is None:
log.info('Will colocate journal with data on %s', args.data)
args.journal = args.data