summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-03-05 13:33:05 -0800
committerSage Weil <sage@inktank.com>2013-03-05 13:33:05 -0800
commit8184b68c37f1a2c9303e13caeaad0eccd5678ab6 (patch)
tree081bf8f098e19ff6a3483163ecab44fe087c3442
parent8550e5c6ab4a331d07f5e4e4cf110121c2ae8e77 (diff)
parent32407c994f309cd788bf13fe9af27e17a422309a (diff)
downloadceph-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-xsrc/ceph-disk-prepare92
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