From ef272b0b7d73913827ed77e7306daa4eaeef745b Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Fri, 21 Jun 2019 15:52:28 -0400 Subject: [PATCH] Add removal confirmations and zap disk before add --- client-cli/pvc.py | 106 +++++++++++++++++++++---------- node-daemon/pvcd/CephInstance.py | 11 +++- 2 files changed, 82 insertions(+), 35 deletions(-) diff --git a/client-cli/pvc.py b/client-cli/pvc.py index 9cb031db..7f010b20 100755 --- a/client-cli/pvc.py +++ b/client-cli/pvc.py @@ -1133,11 +1133,22 @@ def ceph_osd(): default=1.0, show_default=True, help='Weight of the OSD within the CRUSH map.' ) -def ceph_osd_add(node, device, weight): +@click.option( + '--yes', 'yes', + is_flag=True, default=False, + help='Pre-confirm the disk destruction.' +) +def ceph_osd_add(node, device, weight, yes): """ Add a new Ceph OSD on node NODE with block device DEVICE to the cluster. """ + if not yes: + click.echo('DANGER: This will completely destroy all data on disk {}.'.format(device)) + choice = input('Are you sure you want to do this? (y/N) ') + if choice != 'y' and choice != 'Y': + exit(0) + zk_conn = pvc_common.startZKConnection(zk_host) retcode, retmsg = pvc_ceph.add_osd(zk_conn, node, device, weight) cleanup(retcode, retmsg, zk_conn) @@ -1149,11 +1160,22 @@ def ceph_osd_add(node, device, weight): @click.argument( 'osdid' ) -def ceph_osd_remove(osdid): +@click.option( + '--yes', 'yes', + is_flag=True, default=False, + help='Pre-confirm the removal.' +) +def ceph_osd_remove(osdid, yes): """ Remove a Ceph OSD with ID OSDID from the cluster. """ + if not yes: + click.echo('DANGER: This will completely remove OSD {} from cluster. OSDs will rebalance.'.format(osdid)) + choice = input('Are you sure you want to do this? (y/N) ') + if choice != 'y' and choice != 'Y': + exit(0) + zk_conn = pvc_common.startZKConnection(zk_host) retcode, retmsg = pvc_ceph.remove_osd(zk_conn, osdid) cleanup(retcode, retmsg, zk_conn) @@ -1282,23 +1304,27 @@ def ceph_pool_add(name, pgs): @click.argument( 'name' ) -def ceph_pool_remove(name): +@click.option( + '--yes', 'yes', + is_flag=True, default=False, + help='Pre-confirm the removal.' +) +def ceph_pool_remove(name, yes): """ Remove a Ceph RBD pool with name NAME and all volumes on it. """ - click.echo('DANGER: This will completely remove pool {} and all data contained in it.'.format(name)) - choice = input('Are you sure you want to do this? (y/N) ') - if choice == 'y' or choice == 'Y': - pool_name_check = input('Please enter the pool name to confirm: ') - if pool_name_check == name: - zk_conn = pvc_common.startZKConnection(zk_host) - retcode, retmsg = pvc_ceph.remove_pool(zk_conn, name) - cleanup(retcode, retmsg, zk_conn) - else: - click.echo('Aborting.') - else: - click.echo('Aborting.') + if not yes: + click.echo('DANGER: This will completely remove pool {} and all data contained in it.'.format(name)) + choice = input('Are you sure you want to do this? (y/N) ') + if choice != 'y' and choice != 'Y': + pool_name_check = input('Please enter the pool name to confirm: ') + if pool_name_check != name: + exit(0) + + zk_conn = pvc_common.startZKConnection(zk_host) + retcode, retmsg = pvc_ceph.remove_pool(zk_conn, name) + cleanup(retcode, retmsg, zk_conn) ############################################################################### # pvc ceph pool list @@ -1358,19 +1384,25 @@ def ceph_volume_add(pool, name, size): @click.argument( 'name' ) -def ceph_volume_remove(pool, name): +@click.option( + '--yes', 'yes', + is_flag=True, default=False, + help='Pre-confirm the removal.' +) +def ceph_volume_remove(pool, name, yes): """ Remove a Ceph RBD volume with name NAME from pool POOL. """ - click.echo('DANGER: This will completely remove volume {} from pool {} and all data contained in it.'.format(name, pool)) - choice = input('Are you sure you want to do this? (y/N) ') - if choice == 'y' or choice == 'Y': - zk_conn = pvc_common.startZKConnection(zk_host) - retcode, retmsg = pvc_ceph.remove_volume(zk_conn, pool, name) - cleanup(retcode, retmsg, zk_conn) - else: - click.echo('Aborting.') + if not yes: + click.echo('DANGER: This will completely remove volume {} from pool {} and all data contained in it.'.format(name, pool)) + choice = input('Are you sure you want to do this? (y/N) ') + if choice != 'y' and choice != 'Y': + exit(0) + + zk_conn = pvc_common.startZKConnection(zk_host) + retcode, retmsg = pvc_ceph.remove_volume(zk_conn, pool, name) + cleanup(retcode, retmsg, zk_conn) ############################################################################### # pvc ceph volume list @@ -1438,19 +1470,25 @@ def ceph_volume_snapshot_add(pool, volume, name): @click.argument( 'name' ) -def ceph_volume_snapshot_remove(pool, volume, name): +@click.option( + '--yes', 'yes', + is_flag=True, default=False, + help='Pre-confirm the removal.' +) +def ceph_volume_snapshot_remove(pool, volume, name, yes): """ Remove a Ceph RBD volume with name NAME from pool POOL. """ - click.echo('DANGER: This will completely remove snapshot {} from volume {}/{} and all data contained in it.'.format(name, pool, volume)) - choice = input('Are you sure you want to do this? (y/N) ') - if choice == 'y' or choice == 'Y': - zk_conn = pvc_common.startZKConnection(zk_host) - retcode, retmsg = pvc_ceph.remove_snapshot(zk_conn, pool, volume, name) - cleanup(retcode, retmsg, zk_conn) - else: - click.echo('Aborting.') + if not yes: + click.echo('DANGER: This will completely remove snapshot {} from volume {}/{} and all data contained in it.'.format(name, pool, volume)) + choice = input('Are you sure you want to do this? (y/N) ') + if choice != 'y' and choice != 'Y': + exit(0) + + zk_conn = pvc_common.startZKConnection(zk_host) + retcode, retmsg = pvc_ceph.remove_snapshot(zk_conn, pool, volume, name) + cleanup(retcode, retmsg, zk_conn) ############################################################################### # pvc ceph volume snapshot list @@ -1512,7 +1550,7 @@ def init_cluster(yes): if not yes: click.echo('DANGER: This will remove any existing cluster on these coordinators and create a new cluster. Any existing resources on the old cluster will be left abandoned.') choice = input('Are you sure you want to do this? (y/N) ') - if choice != 'y' or choice != 'Y': + if choice != 'y' and choice != 'Y': exit(0) import pvc_init diff --git a/node-daemon/pvcd/CephInstance.py b/node-daemon/pvcd/CephInstance.py index 5f4f6b55..a0b029b4 100644 --- a/node-daemon/pvcd/CephInstance.py +++ b/node-daemon/pvcd/CephInstance.py @@ -89,7 +89,16 @@ def add_osd(zk_conn, logger, node, device, weight): print(stderr) raise - # 3. Create the OSD for real + # 3a. Zap the disk to ensure it is ready to go + logger.out('Zapping disk {}'.format(device), state='i') + retcode, stdout, stderr = common.run_os_command('ceph-volume lvm zap --destroy {}'.format(device)) + if retcode: + print('ceph-volume lvm zap') + print(stdout) + print(stderr) + raise + + # 3b. Create the OSD for real logger.out('Preparing LVM for new OSD disk with ID {} on {}'.format(osd_id, device), state='i') retcode, stdout, stderr = common.run_os_command( 'ceph-volume lvm prepare --bluestore --data {device}'.format(