Merge pull request #932 from ceph/wip-6979

replace sgdisk subprocess calls with a helper

Reviewed-by: Sage Weil <sage@inktank.com>
This commit is contained in:
Sage Weil 2013-12-13 10:03:43 -08:00
commit e7652e6b4d

View File

@ -174,8 +174,20 @@ class TooManyLinesError(Error):
class FilesystemTypeError(Error):
"""
Cannot discover filesystem type
"""
"""
class CephDiskException(Exception):
"""
A base exception for ceph-disk to provide custom (ad-hoc) messages that
will be caught and dealt with when main() is executed
"""
pass
class ExecutableNotFound(CephDiskException):
"""
Exception to report on executables not available in PATH
"""
pass
####### utils
@ -198,6 +210,73 @@ def maybe_mkdir(*a, **kw):
raise
def which(executable):
"""find the location of an executable"""
locations = (
'/usr/local/bin',
'/bin',
'/usr/bin',
'/usr/local/sbin',
'/usr/sbin',
'/sbin',
)
for location in locations:
executable_path = os.path.join(location, executable)
if os.path.exists(executable_path):
return executable_path
def _get_command_executable(arguments):
"""
Return the full path for an executable, raise if the executable is not
found. If the executable has already a full path do not perform any checks.
"""
if arguments[0].startswith('/'): # an absolute path
return arguments
executable = which(arguments[0])
if not executable:
command_msg = 'Could not run command: %s' % ' '.join(arguments)
executable_msg = '%s not in path.' % arguments[0]
raise ExecutableNotFound('%s %s' % (executable_msg, command_msg))
# swap the old executable for the new one
arguments[0] = executable
return arguments
def command(arguments):
"""
Safely execute a ``subprocess.Popen`` call making sure that the
executable exists and raising a helpful error message
if it does not.
.. note:: This should be the prefered way of calling ``subprocess.Popen``
since it provides the caller with the safety net of making sure that
executables *will* be found and will error nicely otherwise.
"""
arguments = _get_command_executable(arguments)
return subprocess.Popen(
arguments,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).stdout.read()
def command_check_call(arguments):
"""
Safely execute a ``subprocess.check_call`` call making sure that the
executable exists and raising a helpful error message if it does not.
.. note:: This should be the prefered way of calling
``subprocess.check_call`` since it provides the caller with the safety net
of making sure that executables *will* be found and will error nicely
otherwise.
"""
arguments = _get_command_executable(arguments)
return subprocess.check_call(arguments)
# a device "name" is something like
# sdb
# cciss!c0d1
@ -489,7 +568,6 @@ def _check_output(*args, **kwargs):
cmd = kwargs.get("args")
if cmd is None:
cmd = args[0]
#raise subprocess.CalledProcessError(ret, cmd, output=out)
error = subprocess.CalledProcessError(ret, cmd)
error.output = out
raise error
@ -741,7 +819,7 @@ def get_free_partition_index(dev):
lines = str(lines).splitlines(True)
# work around buggy libreadline(?) library in rhel/centos.
idiot_prefix = '\x1b\x5b\x3f\x31\x30\x33\x34\x68';
idiot_prefix = '\x1b\x5b\x3f\x31\x30\x33\x34\x68'
if lines[0].startswith(idiot_prefix):
lines[0] = lines[0][8:]
@ -780,16 +858,16 @@ def zap(dev):
dev_file.seek(-size, os.SEEK_END)
dev_file.write(size*'\0')
subprocess.check_call(
args=[
command_check_call(
[
'sgdisk',
'--zap-all',
'--clear',
'--mbrtogpt',
'--',
dev,
],
)
]
)
except subprocess.CalledProcessError as e:
raise Error(e)
@ -837,8 +915,8 @@ def prepare_journal_dev(
try:
LOG.debug('Creating journal partition num %d size %d on %s', num, journal_size, journal)
subprocess.check_call(
args=[
command_check_call(
[
'sgdisk',
'--new={part}'.format(part=journal_part),
'--change-name={num}:ceph journal'.format(num=num),
@ -853,8 +931,8 @@ def prepare_journal_dev(
'--mbrtogpt',
'--',
journal,
],
)
]
)
# try to make sure the kernel refreshes the table. note
# that if this gets ebusy, we are probably racing with
@ -1030,8 +1108,8 @@ def prepare_dev(
else:
LOG.debug('Creating osd partition on %s', data)
try:
subprocess.check_call(
args=[
command_check_call(
[
'sgdisk',
'--largest-new=1',
'--change-name=1:ceph data',
@ -1041,8 +1119,8 @@ def prepare_dev(
'--typecode=1:%s' % ptype_tobe,
'--',
data,
],
)
]
)
subprocess.call(
args=[
# wait for udev event queue to clear
@ -1106,14 +1184,14 @@ def prepare_dev(
if not is_partition(data):
try:
subprocess.check_call(
args=[
command_check_call(
[
'sgdisk',
'--typecode=1:%s' % ptype_osd,
'--',
data,
],
)
]
)
except subprocess.CalledProcessError as e:
raise Error(e)
@ -1615,7 +1693,7 @@ def find_cluster_by_uuid(_uuid):
cluster = conf_file[:-5]
try:
fsid = get_fsid(cluster)
except Error as e:
except Error as e:
if e.message != 'getting cluster uuid from configuration failed':
raise e
no_fsid.append(cluster)
@ -1897,14 +1975,14 @@ def get_dev_fs(dev):
def get_partition_type(part):
(base, partnum) = re.match('(\D+)(\d+)', part).group(1, 2)
sgdisk = subprocess.Popen(
sgdisk = command(
[
'sgdisk',
'-p',
base,
],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE).stdout.read()
]
)
for line in sgdisk.splitlines():
m = re.search('\s+(\d+)\s+\d+\s+\d+\s+\S+ \S+B\s+\S+\s+(.*)', line)
if m is not None:
@ -1916,10 +1994,7 @@ def get_partition_type(part):
def get_partition_uuid(dev):
(base, partnum) = re.match('(\D+)(\d+)', dev).group(1, 2)
out = subprocess.Popen(
[ 'sgdisk', '-i', partnum, base ],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE).stdout.read()
out = command(['sgdisk', '-i', partnum, base])
for line in out.splitlines():
m = re.match('Partition unique GUID: (\S+)', line)
if m:
@ -2335,11 +2410,22 @@ def main():
args.func(args)
except Error as e:
print >> sys.stderr, '{prog}: {msg}'.format(
prog=args.prog,
msg=e,
raise SystemExit(
'{prog}: {msg}'.format(
prog=args.prog,
msg=e,
)
sys.exit(1)
)
except CephDiskException as error:
exc_name = error.__class__.__name__
raise SystemExit(
'{prog} {exc_name}: {msg}'.format(
prog=args.prog,
exc_name=exc_name,
msg=error,
)
)
if __name__ == '__main__':