diff options
author | Sage Weil <sage@inktank.com> | 2013-03-05 13:33:05 -0800 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-03-05 13:33:05 -0800 |
commit | 8184b68c37f1a2c9303e13caeaad0eccd5678ab6 (patch) | |
tree | 081bf8f098e19ff6a3483163ecab44fe087c3442 | |
parent | 8550e5c6ab4a331d07f5e4e4cf110121c2ae8e77 (diff) | |
parent | 32407c994f309cd788bf13fe9af27e17a422309a (diff) | |
download | ceph-8184b68c37f1a2c9303e13caeaad0eccd5678ab6.tar.gz |
Merge branch 'wip-prepare'
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Reviewed-by: Alexandre Marangone <alexandre.marangone@inktank.com>
Tested-by: Tamil Muthamizhan <tamil.muthamizhan@inktank.com>
-rwxr-xr-x | src/ceph-disk-prepare | 92 |
1 files changed, 76 insertions, 16 deletions
diff --git a/src/ceph-disk-prepare b/src/ceph-disk-prepare index b0f003b6e5c..d8ee86f1243 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,28 +71,82 @@ 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): """ Check whether a given device is a partition or a full disk. """ - # resolve symlink(s) - max = 10 - while stat.S_ISLNK(os.lstat(dev).st_mode): - dev = os.readlink(dev) - max -= 1 - if max == 0: - raise PrepareError('%s is a rats nest of symlinks' % dev) + dev = os.path.realpath(dev) if not stat.S_ISBLK(os.lstat(dev).st_mode): raise PrepareError('not a block device', dev) # if the device ends in a number, it is a partition (e.g., /dev/sda3) - - # ugh i have no internet.. how do you do a python regex? - if dev.endswith('0') or dev.endswith('1') or dev.endswith('2') or dev.endswith('3') or dev.endswith('4') or dev.endswith('4') or dev.endswith('6') or dev.endswith('7') or dev.endswith('8') or dev.endswith('9'): + if dev[-1].isdigit(): 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 is_held(dev): + """ + Check if a device is held by another device (e.g., a dm-crypt mapping) + """ + assert os.path.exists(dev) + dev = os.path.realpath(dev) + base = dev[5:] + disk = base + while disk[-1].isdigit(): + disk = disk[:-1] + dir = '/sys/block/{disk}/{base}/holders'.format(disk=disk, base=base) + if not os.path.exists(dir): + return [] + return os.listdir(dir) + +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) + holders = is_held(dev) + if holders: + raise PrepareError('Device is in use by a device-mapper mapping (dm-crypt?)' % dev, ','.join(holders)) + else: + for p in list_partitions(dev): + if is_mounted(p): + raise PrepareError('Device is mounted', p) + holders = is_held(p) + if holders: + raise PrepareError('Device %s is in use by a device-mapper mapping (dm-crypt?)' % p, ','.join(holders)) def write_one_line(parent, name, text): """ @@ -804,12 +859,18 @@ def main(): if not os.path.exists(args.data): raise PrepareError('data path does not exist', args.data) - # FIXME: verify disk/partitions is not in use + # in use? + dmode = os.stat(args.data).st_mode + if stat.S_ISBLK(dmode): + verify_not_in_use(args.data) + + if args.journal and os.path.exists(args.journal): + jmode = os.stat(args.journal).st_mode + if stat.S_ISBLK(jmode): + verify_not_in_use(args.journal) + if args.zap_disk is not None: - if not os.path.exists(args.data): - raise PrepareError('does not exist', args.data) - mode = os.stat(args.data).st_mode - if stat.S_ISBLK(mode) and not is_partition(args.data): + if stat.S_ISBLK(dmode) and not is_partition(args.data): zap(args.data) else: raise PrepareError('not full block device; cannot zap', args.data) @@ -869,7 +930,6 @@ def main(): journal_size = int(journal_size) # colocate journal with data? - dmode = os.stat(args.data).st_mode 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 |