diff options
author | Sage Weil <sage@inktank.com> | 2013-03-04 16:38:57 -0800 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-03-04 17:30:13 -0800 |
commit | 3bd0ac0ab011c4cdf0121f0d9732938d085fb8bf (patch) | |
tree | 88c36c9a0f4b22114b5ce6972bd386e644cdb443 | |
parent | f03f62697f170d42b4b62c53d2860ff2f24a2d73 (diff) | |
download | ceph-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-x | src/ceph-disk-prepare | 51 |
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 |