From: Sage Weil Date: Fri, 29 Mar 2013 22:46:00 +0000 (-0700) Subject: disk: new command, with list, prepare, activate X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=99f423e1789d23a8314780841dcdc5ad1b6a3c93;p=ceph-deploy.git disk: new command, with list, prepare, activate Create new disk command. Change 'osd prepare ...' to 'disk prepare ...' Change 'osd activate ...' to 'disk activate ...' Move 'zapdisk HOST' to 'disk zap HOST' Add 'disk list HOST' This keeps the osd command simple and clean, and makes 'disk list' make sense. The HOST vs HOST:DISK is slightly weird still. Oh well. Signed-off-by: Sage Weil Reviewed-by: Dan Mick --- diff --git a/ceph_deploy/osd.py b/ceph_deploy/osd.py index a280ef9..9917366 100644 --- a/ceph_deploy/osd.py +++ b/ceph_deploy/osd.py @@ -213,12 +213,83 @@ def activate(args, cfg): ) +# NOTE: this mirrors ceph-disk-prepare --zap-disk DEV +def zap(dev): + import subprocess + + try: + # this kills the crab + # + # sgdisk will wipe out the main copy of the GPT partition + # table (sorry), but it doesn't remove the backup copies, and + # subsequent commands will continue to complain and fail when + # they see those. zeroing the last few blocks of the device + # appears to do the trick. + lba_size = 4096 + size = 33 * lba_size + with file(dev, 'wb') as f: + f.seek(-size, os.SEEK_END) + f.write(size*'\0') + + subprocess.check_call( + args=[ + 'sgdisk', + '--zap-all', + '--clear', + '--mbrtogpt', + '--', + dev, + ], + ) + except subprocess.CalledProcessError as e: + raise RuntimeError(e) + +def disk_zap(args): + cfg = conf.load(args) + + for hostname, disk in args.disk: + LOG.debug('zapping %s on %s', disk, hostname) + + # TODO username + sudo = args.pushy('ssh+sudo:{hostname}'.format( + hostname=hostname, + )) + zap_r = sudo.compile(zap) + zap_r(disk) + + +def list_disk(): + import subprocess + proc = subprocess.Popen( + args=[ + 'ceph-disk', + 'list', + ], + stdout=subprocess.PIPE, + ) + return proc.stdout.read() + +def disk_list(args, cfg): + for hostname, disk, journal in args.disk: + + # TODO username + sudo = args.pushy('ssh+sudo:{hostname}'.format( + hostname=hostname, + )) + LOG.debug('Listing disks on {hostname}...'.format(hostname=hostname)) + + list_disk_r = sudo.compile(list_disk) + print list_disk_r(), + + def osd(args): cfg = conf.load(args) - if args.subcommand == 'prepare': + if args.subcommand == 'list': + do_list(args, cfg) + elif args.subcommand == 'prepare': prepare(args, cfg, activate_prepared_disk=False) - if args.subcommand == 'create': + elif args.subcommand == 'create': prepare(args, cfg, activate_prepared_disk=True) elif args.subcommand == 'activate': activate(args, cfg) @@ -227,19 +298,41 @@ def osd(args): sys.exit(1) + +def disk(args): + cfg = conf.load(args) + + if args.subcommand == 'list': + disk_list(args, cfg) + elif args.subcommand == 'prepare': + prepare(args, cfg, activate_prepared_disk=False) + elif args.subcommand == 'activate': + activate(args, cfg) + elif args.subcommand == 'zap': + disk_zap(args, cfg) + else: + LOG.error('subcommand %s not implemented', args.subcommand) + sys.exit(1) + + def colon_separated(s): journal = None + disk = None + host = None if s.count(':') == 2: (host, disk, journal) = s.split(':') elif s.count(':') == 1: (host, disk) = s.split(':') + elif s.count(':') == 0: + (host) = s else: raise argparse.ArgumentTypeError('must be in form HOST:DISK[:JOURNAL]') - # allow just "sdb" to mean /dev/sdb - disk = os.path.join('/dev', disk) - if journal is not None: - journal = os.path.join('/dev', journal) + if disk: + # allow just "sdb" to mean /dev/sdb + disk = os.path.join('/dev', disk) + if journal is not None: + journal = os.path.join('/dev', journal) return (host, disk, journal) @@ -253,12 +346,13 @@ def make(parser): 'subcommand', metavar='SUBCOMMAND', choices=[ + 'list', 'create', 'prepare', 'activate', 'destroy', ], - help='create (prepare+activate), prepare, activate, or destroy', + help='list, create (prepare+activate), prepare, activate, or destroy', ) parser.add_argument( 'disk', @@ -286,3 +380,47 @@ def make(parser): parser.set_defaults( func=osd, ) + + +@priority(50) +def make_disk(parser): + """ + Manage disks on a remote host. + """ + parser.add_argument( + 'subcommand', + metavar='SUBCOMMAND', + choices=[ + 'list', + 'prepare', + 'activate', + 'zap', + ], + help='list, prepare, activate, zap', + ) + parser.add_argument( + 'disk', + nargs='+', + metavar='HOST[:DISK]', + type=colon_separated, + help='host (and optionally disk)', + ) + parser.add_argument( + '--zap-disk', + action='store_true', default=None, + help='destroy existing partition table and content for DISK', + ) + parser.add_argument( + '--dmcrypt', + action='store_true', default=None, + help='use dm-crypt on DISK', + ) + parser.add_argument( + '--dmcrypt-key-dir', + metavar='KEYDIR', + default='/etc/ceph/dmcrypt-keys', + help='directory where dm-crypt keys are stored', + ) + parser.set_defaults( + func=disk, + ) diff --git a/ceph_deploy/zapdisk.py b/ceph_deploy/zapdisk.py deleted file mode 100644 index ebd0b77..0000000 --- a/ceph_deploy/zapdisk.py +++ /dev/null @@ -1,75 +0,0 @@ -import argparse -import logging -import os - -from . import conf -from .cliutil import priority - -LOG = logging.getLogger(__name__) - - -# NOTE: this mirrors ceph-disk-prepare --zap-disk DEV -def zap(dev): - import subprocess - - try: - # this kills the crab - lba_size = 4096 - size = 33 * lba_size - with file(dev, 'wb') as f: - f.seek(-size, os.SEEK_END) - f.write(size*'\0') - - subprocess.check_call( - args=[ - 'sgdisk', - '--zap-all', - '--clear', - '--mbrtogpt', - '--', - dev, - ], - ) - except subprocess.CalledProcessError as e: - raise RuntimeError(e) - -def zapdisk(args): - cfg = conf.load(args) - - for hostname, disk in args.disk: - LOG.debug('zapping %s on %s', disk, hostname) - - # TODO username - sudo = args.pushy('ssh+sudo:{hostname}'.format( - hostname=hostname, - )) - zap_r = sudo.compile(zap) - zap_r(disk) - -def colon_separated(s): - if s.count(':') == 1: - (host, disk) = s.split(':') - else: - raise argparse.ArgumentTypeError('must be in form HOST:DISK') - - # allow just "sdb" to mean /dev/sdb - disk = os.path.join('/dev', disk) - - return (host, disk) - - -@priority(50) -def make(parser): - """ - Zap a data disk on a remote host. - """ - parser.add_argument( - 'disk', - nargs='+', - metavar='HOST:DISK', - type=colon_separated, - help='host and disk to zap', - ) - parser.set_defaults( - func=zapdisk, - ) diff --git a/setup.py b/setup.py index 36c4545..153a763 100644 --- a/setup.py +++ b/setup.py @@ -53,11 +53,11 @@ setup( 'mon = ceph_deploy.mon:make', 'gatherkeys = ceph_deploy.gatherkeys:make', 'osd = ceph_deploy.osd:make', + 'disk = ceph_deploy.osd:make_disk', 'mds = ceph_deploy.mds:make', 'forgetkeys = ceph_deploy.forgetkeys:make', 'config = ceph_deploy.config:make', 'admin = ceph_deploy.admin:make', - 'zapdisk = ceph_deploy.zapdisk:make', ], },