diff --git a/daemon-common/ceph.py b/daemon-common/ceph.py index fd442f2d..418607ae 100644 --- a/daemon-common/ceph.py +++ b/daemon-common/ceph.py @@ -205,6 +205,8 @@ def getOutputColoursOSD(osd_information): return osd_up_flag, osd_up_colour, osd_in_flag, osd_in_colour +# OSD addition and removal uses the /cmd/ceph pipe +# These actions must occur on the specific node they reference def add_osd(zk_conn, node, device, weight): # Verify the target node exists if not common.verifyNode(zk_conn, node): @@ -279,118 +281,35 @@ def in_osd(zk_conn, osd_id): if not verifyOSD(zk_conn, osd_id): return False, 'ERROR: No OSD with ID "{}" is present in the cluster.'.format(osd_id) - # Tell the cluster to online an OSD - in_osd_string = 'osd_in {}'.format(osd_id) - zkhandler.writedata(zk_conn, {'/cmd/ceph': in_osd_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-osd_in': - message = 'Set OSD {} online in the cluster.'.format(osd_id) - success = True - else: - message = 'ERROR: Failed to set OSD online; check node logs for details.' - success = False - except: - success = False - message = 'ERROR Command ignored by node.' + retcode, stdout, stderr = common.run_os_command('ceph osd in {}'.format(osd_id)) + if retcode: + return False, 'ERROR: Failed to enable OSD {}: {}'.format(osd_id, stderr) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) - - return success, message + return True, 'Set OSD {} online.'.format(osd_id) def out_osd(zk_conn, osd_id): if not verifyOSD(zk_conn, osd_id): return False, 'ERROR: No OSD with ID "{}" is present in the cluster.'.format(osd_id) - # Tell the cluster to offline an OSD - out_osd_string = 'osd_out {}'.format(osd_id) - zkhandler.writedata(zk_conn, {'/cmd/ceph': out_osd_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-osd_out': - message = 'Set OSD {} offline in the cluster.'.format(osd_id) - success = True - else: - message = 'ERROR: Failed to set OSD offline; check node logs for details.' - success = False - except: - success = False - message = 'ERROR Command ignored by node.' + retcode, stdout, stderr = common.run_os_command('ceph osd out {}'.format(osd_id)) + if retcode: + return False, 'ERROR: Failed to disable OSD {}: {}'.format(osd_id, stderr) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) - - return success, message + return True, 'Set OSD {} offline.'.format(osd_id) def set_osd(zk_conn, option): - # Tell the cluster to set an OSD property - set_osd_string = 'osd_set {}'.format(option) - zkhandler.writedata(zk_conn, {'/cmd/ceph': set_osd_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-osd_set': - message = 'Set OSD property {} on the cluster.'.format(option) - success = True - else: - message = 'ERROR: Failed to set OSD property; check node logs for details.' - success = False - except: - success = False - message = 'ERROR Command ignored by node.' + retcode, stdout, stderr = common.run_os_command('ceph osd set {}'.format(option)) + if retcode: + return False, 'ERROR: Failed to set property "{}": {}'.format(option, stderr) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) - return success, message + return True, 'Set OSD property "{}".'.format(option) def unset_osd(zk_conn, option): - # Tell the cluster to unset an OSD property - unset_osd_string = 'osd_unset {}'.format(option) - zkhandler.writedata(zk_conn, {'/cmd/ceph': unset_osd_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-osd_unset': - message = 'Unset OSD property {} on the cluster.'.format(option) - success = True - else: - message = 'ERROR: Failed to unset OSD property; check node logs for details.' - success = False - except: - success = False - message = 'ERROR Command ignored by node.' + retcode, stdout, stderr = common.run_os_command('ceph osd unset {}'.format(option)) + if retcode: + return False, 'ERROR: Failed to unset property "{}": {}'.format(option, stderr) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) - - return success, message + return True, 'Unset OSD property "{}".'.format(option) def get_list_osd(zk_conn, limit, is_fuzzy=True): osd_list = [] @@ -664,65 +583,66 @@ def getPoolInformation(zk_conn, pool): return pool_information def add_pool(zk_conn, name, pgs, replcfg): - # Tell the cluster to create a new pool - add_pool_string = 'pool_add {},{},{}'.format(name, pgs, replcfg) - zkhandler.writedata(zk_conn, {'/cmd/ceph': add_pool_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-pool_add': - message = 'Created new RBD pool "{}" with "{}" PGs and replication configuration {}.'.format(name, pgs, replcfg) - success = True - else: - message = 'ERROR: Failed to create new pool; check node logs for details.' - success = False - except: - message = 'ERROR: Command ignored by node.' - success = False + # Prepare the copies/mincopies variables + try: + copies, mincopies = replcfg.split(',') + copies = int(copies.replace('copies=', '')) + mincopies = int(mincopies.replace('mincopies=', '')) + except: + copies = None + mincopies = None + if not copies or not mincopies: + return False, 'ERROR: Replication configuration "{}" is not valid.'.format(replcfg) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 1. Create the pool + retcode, stdout, stderr = common.run_os_command('ceph osd pool create {} {} replicated'.format(name, pgs)) + if retcode: + return False, 'ERROR: Failed to create pool "{}" with {} PGs: {}'.format(name, pgs, stderr) + + # 2. Set the size and minsize + retcode, stdout, stderr = common.run_os_command('ceph osd pool set {} size {}'.format(name, copies)) + if retcode: + return False, 'ERROR: Failed to set pool "{}" size of {}: {}'.format(name, copies, stderr) - return success, message + retcode, stdout, stderr = common.run_os_command('ceph osd pool set {} min_size {}'.format(name, mincopies)) + if retcode: + return False, 'ERROR: Failed to set pool "{}" minimum size of {}: {}'.format(name, mincopies, stderr) + + # 3. Enable RBD application + retcode, stdout, stderr = common.run_os_command('ceph osd pool application enable {} rbd'.format(name)) + if retcode: + return False, 'ERROR: Failed to enable RBD application on pool "{}" : {}'.format(name, stderr) + + # 4. Add the new pool to Zookeeper + zkhandler.writedata(zk_conn, { + '/ceph/pools/{}'.format(name): '', + '/ceph/pools/{}/pgs'.format(name): pgs, + '/ceph/pools/{}/stats'.format(name): '{}', + '/ceph/volumes/{}'.format(name): '', + '/ceph/snapshots/{}'.format(name): '', + }) + + return True, 'Created RBD pool "{}" with {} PGs'.format(name, pgs) def remove_pool(zk_conn, name): if not verifyPool(zk_conn, name): return False, 'ERROR: No pool with name "{}" is present in the cluster.'.format(name) - # Tell the cluster to create a new pool - remove_pool_string = 'pool_remove {}'.format(name) - zkhandler.writedata(zk_conn, {'/cmd/ceph': remove_pool_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-pool_remove': - message = 'Removed RBD pool "{}" and all volumes.'.format(name) - success = True - else: - message = 'ERROR: Failed to remove pool; check node logs for details.' - success = False - except Exception as e: - message = 'ERROR: Command ignored by node: {}'.format(e) - success = False + # 1. Remove pool volumes + for volume in zkhandler.listchildren(zk_conn, '/ceph/volumes/{}'.format(name)): + remove_volume(zk_conn, logger, name, volume) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 2. Remove the pool + retcode, stdout, stderr = common.run_os_command('ceph osd pool rm {pool} {pool} --yes-i-really-really-mean-it'.format(pool=name)) + if retcode: + return False, 'ERROR: Failed to remove pool "{}": {}'.format(name, stderr) - return success, message + # 3. Delete pool from Zookeeper + zkhandler.deletekey(zk_conn, '/ceph/pools/{}'.format(name)) + zkhandler.deletekey(zk_conn, '/ceph/volumes/{}'.format(name)) + zkhandler.deletekey(zk_conn, '/ceph/snapshots/{}'.format(name)) + + return True, 'Removed RBD pool "{}" and all volumes.'.format(name) def get_list_pool(zk_conn, limit, is_fuzzy=True): pool_list = [] @@ -967,154 +887,112 @@ def getVolumeInformation(zk_conn, pool, volume): return volume_information def add_volume(zk_conn, pool, name, size): - # Tell the cluster to create a new volume - databytes = format_bytes_fromhuman(size) - add_volume_string = 'volume_add {},{},{}'.format(pool, name, databytes) - zkhandler.writedata(zk_conn, {'/cmd/ceph': add_volume_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-volume_add': - message = 'Created new RBD volume "{}" of size "{}" on pool "{}".'.format(name, size, pool) - success = True - else: - message = 'ERROR: Failed to create new volume; check node logs for details.' - success = False - except: - message = 'ERROR: Command ignored by node.' - success = False + # 1. Create the volume + retcode, stdout, stderr = common.run_os_command('rbd create --size {} --image-feature layering,exclusive-lock {}/{}'.format(size, pool, name)) + if retcode: + return False, 'ERROR: Failed to create RBD volume "{}": {}'.format(name, stderr) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 2. Get volume stats + retcode, stdout, stderr = common.run_os_command('rbd info --format json {}/{}'.format(pool, name)) + volstats = stdout - return success, message + # 3. Add the new volume to Zookeeper + zkhandler.writedata(zk_conn, { + '/ceph/volumes/{}/{}'.format(pool, name): '', + '/ceph/volumes/{}/{}/stats'.format(pool, name): volstats, + '/ceph/snapshots/{}/{}'.format(pool, name): '', + }) + + return True, 'Created RBD volume "{}/{}" ({})'.format(pool, name, size) + +def clone_volume(zk_conn, pool, name_src, name_new): + if not verifyVolume(zk_conn, pool, name_src): + return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name_src, pool) + + # 1. Clone the volume + retcode, stdout, stderr = common.run_os_command('rbd copy {}/{} {}/{}'.format(pool, name_src, pool, name_new)) + if retcode: + return False, 'ERROR: Failed to clone RBD volume "{}" to "{}" in pool "{}": {}'.format(name_src, new_name, pool, stderr) + + # 2. Get volume stats + retcode, stdout, stderr = common.run_os_command('rbd info --format json {}/{}'.format(pool, name_new)) + volstats = stdout + + # 3. Add the new volume to Zookeeper + zkhandler.writedata(zk_conn, { + '/ceph/volumes/{}/{}'.format(pool, name_new): '', + '/ceph/volumes/{}/{}/stats'.format(pool, name_new): volstats, + '/ceph/snapshots/{}/{}'.format(pool, name_new): '', + }) + + return True, 'Cloned RBD volume "{}" to "{}" in pool "{}"'.format(name, name_new, pool) def resize_volume(zk_conn, pool, name, size): - # Tell the cluster to resize the volume - databytes = format_bytes_fromhuman(size) - resize_volume_string = 'volume_resize {},{},{}'.format(pool, name, databytes) - zkhandler.writedata(zk_conn, {'/cmd/ceph': resize_volume_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-volume_resize': - message = 'Resized RBD volume "{}" to size "{}" on pool "{}".'.format(name, size, pool) - success = True - else: - message = 'ERROR: Failed to resize volume; check node logs for details.' - success = False - except: - message = 'ERROR: Command ignored by node.' - success = False + if not verifyVolume(zk_conn, pool, name): + return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name, pool) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 1. Resize the volume + retcode, stdout, stderr = common.run_os_command('rbd resize --size {} {}/{}'.format(size, pool, name)) + if retcode: + return False, 'ERROR: Failed to resize RBD volume "{}" to size "{}" in pool "{}": {}'.format(name, size, pool, stderr) - return success, message + # 2. Get volume stats + retcode, stdout, stderr = common.run_os_command('rbd info --format json {}/{}'.format(pool, name)) + volstats = stdout + + # 3. Add the new volume to Zookeeper + zkhandler.writedata(zk_conn, { + '/ceph/volumes/{}/{}'.format(pool, name): '', + '/ceph/volumes/{}/{}/stats'.format(pool, name): volstats, + '/ceph/snapshots/{}/{}'.format(pool, name): '', + }) + + return True, 'Resized RBD volume "{}" to size "{}" in pool "{}".'.format(name, size, pool) def rename_volume(zk_conn, pool, name, new_name): - # Tell the cluster to rename - rename_volume_string = 'volume_rename {},{},{}'.format(pool, name, new_name) - zkhandler.writedata(zk_conn, {'/cmd/ceph': rename_volume_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-volume_rename': - message = 'Renamed RBD volume "{}" to "{}" on pool "{}".'.format(name, new_name, pool) - success = True - else: - message = 'ERROR: Failed to rename volume {} to {}; check node logs for details.'.format(name, new_name) - success = False - except: - message = 'ERROR: Command ignored by node.' - success = False + if not verifyVolume(zk_conn, pool, name): + return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name, pool) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 1. Rename the volume + retcode, stdout, stderr = common.run_os_command('rbd rename {}/{} {}'.format(pool, name, new_name)) + if retcode: + return False, 'ERROR: Failed to rename volume "{}" to "{}" in pool "{}": {}'.format(name, new_name, pool, stderr) - return success, message + # 2. Rename the volume in Zookeeper + zkhandler.renamekey(zk_conn, { + '/ceph/volumes/{}/{}'.format(pool, name): '/ceph/volumes/{}/{}'.format(pool, new_name), + '/ceph/snapshots/{}/{}'.format(pool, name): '/ceph/snapshots/{}/{}'.format(pool, new_name), + }) -def clone_volume(zk_conn, pool, name, new_name): - # Tell the cluster to clone - clone_volume_string = 'volume_clone {},{},{}'.format(pool, name, new_name) - zkhandler.writedata(zk_conn, {'/cmd/ceph': clone_volume_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-volume_clone': - message = 'Cloned RBD volume "{}" to "{}" on pool "{}".'.format(name, new_name, pool) - success = True - else: - message = 'ERROR: Failed to clone volume {} to {}; check node logs for details.'.format(name, new_name) - success = False - except: - message = 'ERROR: Command ignored by node.' - success = False + # 3. Get volume stats + retcode, stdout, stderr = common.run_os_command('rbd info --format json {}/{}'.format(pool, new_name)) + volstats = stdout - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 4. Update the volume stats in Zookeeper + zkhandler.writedata(zk_conn, { + '/ceph/volumes/{}/{}/stats'.format(pool, new_name): volstats, + }) - return success, message + return True, 'Renamed RBD volume "{}" to "{}" in pool "{}".'.format(name, new_name, pool) def remove_volume(zk_conn, pool, name): if not verifyVolume(zk_conn, pool, name): - return False, 'ERROR: No volume with name "{}" is present in pool {}.'.format(name, pool) + return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name, pool) - # Tell the cluster to create a new volume - remove_volume_string = 'volume_remove {},{}'.format(pool, name) - zkhandler.writedata(zk_conn, {'/cmd/ceph': remove_volume_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-volume_remove': - message = 'Removed RBD volume "{}" in pool "{}".'.format(name, pool) - success = True - else: - message = 'ERROR: Failed to remove volume; check node logs for details.' - success = False - except Exception as e: - message = 'ERROR: Command ignored by node: {}'.format(e) - success = False + # 1. Remove volume snapshots + for snapshot in zkhandler.listchildren(zk_conn, '/ceph/snapshots/{}/{}'.format(pool, name)): + remove_snapshot(zk_conn, logger, pool, volume, snapshot) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 2. Remove the volume + retcode, stdout, stderr = common.run_os_command('rbd rm {}/{}'.format(pool, name)) + if retcode: + return False, 'ERROR: Failed to remove RBD volume "{}" in pool "{}": {}'.format(name, pool, stderr) - return success, message + # 3. Delete volume from Zookeeper + zkhandler.deletekey(zk_conn, '/ceph/volumes/{}/{}'.format(pool, name)) + zkhandler.deletekey(zk_conn, '/ceph/snapshots/{}/{}'.format(pool, name)) + + return True, 'Removed RBD volume "{}" in pool "{}".'.format(name, pool) def get_list_volume(zk_conn, pool, limit, is_fuzzy=True): volume_list = [] @@ -1276,94 +1154,55 @@ def getCephSnapshots(zk_conn, pool, volume): return snapshot_list def add_snapshot(zk_conn, pool, volume, name): - # Tell the cluster to create a new snapshot - add_snapshot_string = 'snapshot_add {},{},{}'.format(pool, volume, name) - zkhandler.writedata(zk_conn, {'/cmd/ceph': add_snapshot_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-snapshot_add': - message = 'Created new RBD snapshot "{}" of volume "{}" on pool "{}".'.format(name, volume, pool) - success = True - else: - message = 'ERROR: Failed to create new snapshot; check node logs for details.' - success = False - except: - message = 'ERROR: Command ignored by node.' - success = False + if not verifyVolume(zk_conn, pool, volume): + return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(volume, pool) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 1. Create the snapshot + retcode, stdout, stderr = common.run_os_command('rbd snap create {}/{}@{}'.format(pool, volume, name)) + if retcode: + return False, 'ERROR: Failed to create RBD snapshot "{}" of volume "{}" in pool "{}": {}'.format(name, volume, pool, stderr) - return success, message + # 2. Add the snapshot to Zookeeper + zkhandler.writedata(zk_conn, { + '/ceph/snapshots/{}/{}/{}'.format(pool, volume, name): '', + '/ceph/snapshots/{}/{}/{}/stats'.format(pool, volume, name): '{}' + }) + + return True, 'Created RBD snapshot "{}" of volume "{}" in pool "{}".'.format(name, volume, pool) def rename_snapshot(zk_conn, pool, volume, name, new_name): - # Tell the cluster to rename - rename_snapshot_string = 'snapshot_rename {},{},{}'.format(pool, name, new_name) - zkhandler.writedata(zk_conn, {'/cmd/ceph': rename_snapshot_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-snapshot_rename': - message = 'Renamed RBD volume snapshot "{}" to "{}" for volume {} on pool "{}".'.format(name, new_name, volume, pool) - success = True - else: - message = 'ERROR: Failed to rename volume {} to {}; check node logs for details.'.format(name, new_name) - success = False - except: - message = 'ERROR: Command ignored by node.' - success = False + if not verifyVolume(zk_conn, pool, volume): + return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(volume, pool) + if not verifySnapshot(zk_conn, pool, volume, name): + return False, 'ERROR: No snapshot with name "{}" is present for volume "{}" in pool "{}".'.format(name, volume, pool) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 1. Rename the snapshot + retcode, stdout, stderr = common.run_os_command('rbd snap rename {}/{}@{} {}'.format(pool, volume, name, new_name)) + if retcode: + return False, 'ERROR: Failed to rename RBD snapshot "{}" to "{}" for volume "{}" in pool "{}": {}'.format(name, new_name, volume, pool, stderr) - return success, message + # 2. Rename the snapshot in ZK + zkhandler.renamekey(zk_conn, { + '/ceph/snapshots/{}/{}/{}'.format(pool, volume, name): '/ceph/snapshots/{}/{}/{}'.format(pool, volume, new_name) + }) + + return True, 'Renamed RBD snapshot "{}" to "{}" for volume "{}" in pool "{}".'.format(name, new_name, volume, pool) def remove_snapshot(zk_conn, pool, volume, name): + if not verifyVolume(zk_conn, pool, volume): + return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(volume, pool) if not verifySnapshot(zk_conn, pool, volume, name): - return False, 'ERROR: No snapshot with name "{}" is present of volume {} on pool {}.'.format(name, volume, pool) + return False, 'ERROR: No snapshot with name "{}" is present of volume {} in pool {}.'.format(name, volume, pool) - # Tell the cluster to create a new snapshot - remove_snapshot_string = 'snapshot_remove {},{},{}'.format(pool, volume, name) - zkhandler.writedata(zk_conn, {'/cmd/ceph': remove_snapshot_string}) - # Wait 1/2 second for the cluster to get the message and start working - time.sleep(0.5) - # Acquire a read lock, so we get the return exclusively - lock = zkhandler.readlock(zk_conn, '/cmd/ceph') - with lock: - try: - result = zkhandler.readdata(zk_conn, '/cmd/ceph').split()[0] - if result == 'success-snapshot_remove': - message = 'Removed RBD snapshot "{}" of volume "{}" in pool "{}".'.format(name, volume, pool) - success = True - else: - message = 'ERROR: Failed to remove snapshot; check node logs for details.' - success = False - except Exception as e: - message = 'ERROR: Command ignored by node: {}'.format(e) - success = False + # 1. Remove the snapshot + retcode, stdout, stderr = common.run_os_command('rbd snap rm {}/{}@{}'.format(pool, volume, name)) + if retcode: + return False, 'Failed to remove RBD snapshot "{}" of volume "{}" in pool "{}": {}'.format(name, volume, pool, stderr) - # Acquire a write lock to ensure things go smoothly - lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with lock: - time.sleep(0.5) - zkhandler.writedata(zk_conn, {'/cmd/ceph': ''}) + # 2. Delete snapshot from Zookeeper + zkhandler.deletekey(zk_conn, '/ceph/snapshots/{}/{}/{}'.format(pool, volume, name)) - return success, message + return True, 'Removed RBD snapshot "{}" of volume "{}" in pool "{}".'.format(name, volume, pool) def get_list_snapshot(zk_conn, pool, volume, limit, is_fuzzy=True): snapshot_list = [] diff --git a/node-daemon/pvcnoded/CephInstance.py b/node-daemon/pvcnoded/CephInstance.py index d373fd3c..8cdf7e8c 100644 --- a/node-daemon/pvcnoded/CephInstance.py +++ b/node-daemon/pvcnoded/CephInstance.py @@ -283,86 +283,6 @@ def remove_osd(zk_conn, logger, osd_id, osd_obj): logger.out('Failed to purge OSD disk with ID {}: {}'.format(osd_id, e), state='e') return False -def in_osd(zk_conn, logger, osd_id): - # We are ready to create a new pool on this node - logger.out('Setting OSD {} in'.format(osd_id), state='i') - try: - # 1. Set it in - retcode, stdout, stderr = common.run_os_command('ceph osd in {}'.format(osd_id)) - if retcode: - print('ceph osd in') - print(stdout) - print(stderr) - raise - - # Log it - logger.out('Set OSD {} in'.format(osd_id), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to set OSD {} in: {}'.format(osd_id, e), state='e') - return False - -def out_osd(zk_conn, logger, osd_id): - # We are ready to create a new pool on this node - logger.out('Settoutg OSD {} out'.format(osd_id), state='i') - try: - # 1. Set it out - retcode, stdout, stderr = common.run_os_command('ceph osd out {}'.format(osd_id)) - if retcode: - proutt('ceph osd out') - proutt(stdout) - proutt(stderr) - raise - - # Log it - logger.out('Set OSD {} out'.format(osd_id), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to set OSD {} out: {}'.format(osd_id, e), state='e') - return False - -def set_property(zk_conn, logger, option): - # We are ready to create a new pool on this node - logger.out('Setting OSD property {}'.format(option), state='i') - try: - # 1. Set it in - retcode, stdout, stderr = common.run_os_command('ceph osd set {}'.format(option)) - if retcode: - prsett('ceph osd set') - print(stdout) - print(stderr) - raise - - # Log it - logger.out('Set OSD property {}'.format(option), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to set OSD property {}: {}'.format(option, e), state='e') - return False - -def unset_property(zk_conn, logger, option): - # We are ready to create a new pool on this node - logger.out('Unsetting OSD property {}'.format(option), state='i') - try: - # 1. Set it in - retcode, stdout, stderr = common.run_os_command('ceph osd unset {}'.format(option)) - if retcode: - prunsett('ceph osd unset') - print(stdout) - print(stderr) - raise - - # Log it - logger.out('Unset OSD property {}'.format(option), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to unset OSD property {}: {}'.format(option, e), state='e') - return False - class CephPoolInstance(object): def __init__(self, zk_conn, this_node, name): self.zk_conn = zk_conn @@ -401,86 +321,6 @@ class CephPoolInstance(object): if data and data != self.stats: self.stats = json.loads(data) -def add_pool(zk_conn, logger, name, pgs, copies, mincopies): - # We are ready to create a new pool on this node - logger.out('Creating new RBD pool {}'.format(name), state='i') - try: - # 1. Create the pool - retcode, stdout, stderr = common.run_os_command('ceph osd pool create {} {} replicated'.format(name, pgs)) - if retcode: - print('ceph osd pool create') - print(stdout) - print(stderr) - raise - - # 2. Set the size and min_size - retcode, stdout, stderr = common.run_os_command('ceph osd pool set {} size {}'.format(name, copies)) - if retcode: - print('ceph osd pool set size') - print(stdout) - print(stderr) - raise - retcode, stdout, stderr = common.run_os_command('ceph osd pool set {} min_size {}'.format(name, mincopies)) - if retcode: - print('ceph osd pool set min_size') - print(stdout) - print(stderr) - raise - - # 3. Enable RBD application - retcode, stdout, stderr = common.run_os_command('ceph osd pool application enable {} rbd'.format(name)) - if retcode: - print('ceph osd pool application enable') - print(stdout) - print(stderr) - raise - - # 4. Add the new pool to ZK - zkhandler.writedata(zk_conn, { - '/ceph/pools/{}'.format(name): '', - '/ceph/pools/{}/pgs'.format(name): pgs, - '/ceph/pools/{}/stats'.format(name): '{}', - '/ceph/volumes/{}'.format(name): '', - '/ceph/snapshots/{}'.format(name): '', - }) - - # Log it - logger.out('Created new RBD pool {}'.format(name), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to create new RBD pool {}: {}'.format(name, e), state='e') - return False - -def remove_pool(zk_conn, logger, name): - # We are ready to create a new pool on this node - logger.out('Removing RBD pool {}'.format(name), state='i') - try: - # Remove pool volumes first - for volume in zkhandler.listchildren(zk_conn, '/ceph/volumes/{}'.format(name)): - remove_volume(zk_conn, logger, name, volume) - - # Remove the pool - retcode, stdout, stderr = common.run_os_command('ceph osd pool rm {pool} {pool} --yes-i-really-really-mean-it'.format(pool=name)) - if retcode: - print('ceph osd pool rm') - print(stdout) - print(stderr) - raise - - # Delete pool from ZK - zkhandler.deletekey(zk_conn, '/ceph/pools/{}'.format(name)) - zkhandler.deletekey(zk_conn, '/ceph/volumes/{}'.format(name)) - zkhandler.deletekey(zk_conn, '/ceph/snapshots/{}'.format(name)) - - # Log it - logger.out('Removed RBD pool {}'.format(name), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to remove RBD pool {}: {}'.format(name, e), state='e') - return False - class CephVolumeInstance(object): def __init__(self, zk_conn, this_node, pool, name): self.zk_conn = zk_conn @@ -504,158 +344,6 @@ class CephVolumeInstance(object): if data and data != self.stats: self.stats = json.loads(data) -def add_volume(zk_conn, logger, pool, name, size): - # We are ready to create a new volume on this node - logger.out('Creating new RBD volume {} on pool {} of size {}'.format(name, pool, size), state='i') - try: - # Create the volume - retcode, stdout, stderr = common.run_os_command('rbd create --size {} --image-feature layering,exclusive-lock {}/{}'.format(size, pool, name)) - if retcode: - print('rbd create') - print(stdout) - print(stderr) - raise - - # Get volume stats - retcode, stdout, stderr = common.run_os_command('rbd info --format json {}/{}'.format(pool, name)) - volstats = stdout - - # Add the new volume to ZK - zkhandler.writedata(zk_conn, { - '/ceph/volumes/{}/{}'.format(pool, name): '', - '/ceph/volumes/{}/{}/stats'.format(pool, name): volstats, - '/ceph/snapshots/{}/{}'.format(pool, name): '', - }) - - # Log it - logger.out('Created new RBD volume {} on pool {}'.format(name, pool), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to create new RBD volume {} on pool {}: {}'.format(name, pool, e), state='e') - return False - -def clone_volume(zk_conn, logger, pool, name_orig, name_new, prefix): - if not prefix: - # Ensure that prefix is just an empty string if it isn't set - prefix = '' - logger.out('Cloning RBD volume {} to {}{} on pool {}'.format(name_orig, prefix, name_new, pool), state='i') - try: - # Clone the volume - retcode, stdout, stderr = common.run_os_command('rbd copy {}/{} {}/{}{}'.format(pool, name_orig, pool, prefix, name_new)) - if retcode: - print('rbd copy') - print(stdout) - print(stderr) - raise - - # Get volume stats - retcode, stdout, stderr = common.run_os_command('rbd info --format json {}/{}{}'.format(pool, prefix, name_new)) - volstats = stdout - - # Add the new volume to ZK - zkhandler.writedata(zk_conn, { - '/ceph/volumes/{}/{}{}'.format(pool, prefix, name_new): '', - '/ceph/volumes/{}/{}{}/stats'.format(pool, prefix, name_new): volstats, - '/ceph/snapshots/{}/{}{}'.format(pool, prefix, name_new): '', - }) - - # Log it - logger.out('Cloned RBD volume {} to {}{} on pool {}'.format(name_orig, prefix, name_new, pool), stats='o') - return True - except Exception as e: - # Log it - logger.out('Failed to clone RBD volume {} to {}{} on pool {}: {}'.format(name_orig, prefix, name_new, pool, e), state='e') - return False - -def resize_volume(zk_conn, logger, pool, name, size): - logger.out('Resizing RBD volume {} on pool {} to size {}'.format(name, pool, size), state='i') - try: - # Resize the volume - retcode, stdout, stderr = common.run_os_command('rbd resize --size {} {}/{}'.format(size, pool, name)) - if retcode: - print('rbd resize') - print(stdout) - print(stderr) - raise - - # Get volume stats - retcode, stdout, stderr = common.run_os_command('rbd info --format json {}/{}'.format(pool, name)) - volstats = stdout - - # Update the volume to ZK - zkhandler.writedata(zk_conn, { - '/ceph/volumes/{}/{}'.format(pool, name): '', - '/ceph/volumes/{}/{}/stats'.format(pool, name): volstats, - '/ceph/snapshots/{}/{}'.format(pool, name): '', - }) - - # Log it - logger.out('Created new RBD volume {} on pool {}'.format(name, pool), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to resize RBD volume {} on pool {}: {}'.format(name, pool, e), state='e') - return False - -def rename_volume(zk_conn, logger, pool, name, new_name): - logger.out('Renaming RBD volume {} to {} on pool {}'.format(name, new_name, pool)) - try: - # Rename the volume - retcode, stdout, stderr = common.run_os_command('rbd rename {}/{} {}'.format(pool, name, new_name)) - if retcode: - print('rbd rename') - print(stdout) - print(stderr) - raise - - # Rename the volume in ZK - zkhandler.renamekey(zk_conn, { - '/ceph/volumes/{}/{}'.format(pool, name): '/ceph/volumes/{}/{}'.format(pool, new_name), - '/ceph/snapshots/{}/{}'.format(pool, name): '/ceph/snapshots/{}/{}'.format(pool, new_name), - }) - - # Get volume stats - retcode, stdout, stderr = common.run_os_command('rbd info --format json {}/{}'.format(pool, new_name)) - volstats = stdout - - # Update the volume stats in ZK - zkhandler.writedata(zk_conn, { - '/ceph/volumes/{}/{}/stats'.format(pool, new_name): volstats, - }) - - # Log it - logger.out('Renamed RBD volume {} to {} on pool {}'.format(name, new_name, pool), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to rename RBD volume {} on pool {}: {}'.format(name, pool, e), state='e') - return False - -def remove_volume(zk_conn, logger, pool, name): - # We are ready to create a new volume on this node - logger.out('Removing RBD volume {} from pool {}'.format(name, pool), state='i') - try: - # Remove the volume - retcode, stdout, stderr = common.run_os_command('rbd rm {}/{}'.format(pool, name)) - if retcode: - print('ceph osd volume rm') - print(stdout) - print(stderr) - raise - - # Delete volume from ZK - zkhandler.deletekey(zk_conn, '/ceph/volumes/{}/{}'.format(pool, name)) - zkhandler.deletekey(zk_conn, '/ceph/snapshots/{}/{}'.format(pool, name)) - - # Log it - logger.out('Removed RBD volume {} from pool {}'.format(name, pool), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to remove RBD volume {} from pool {}: {}'.format(name, pool, e), state='e') - return False - class CephSnapshotInstance(object): def __init__(self, zk_conn, this_node, name): self.zk_conn = zk_conn @@ -680,85 +368,8 @@ class CephSnapshotInstance(object): if data and data != self.stats: self.stats = json.loads(data) -def add_snapshot(zk_conn, logger, pool, volume, name): - # We are ready to create a new snapshot on this node - logger.out('Creating new RBD snapshot {} of volume {} on pool {}'.format(name, volume, pool), state='i') - try: - # 1. Create the snapshot - retcode, stdout, stderr = common.run_os_command('rbd snap create {}/{}@{}'.format(pool, volume, name)) - if retcode: - print('rbd snap create') - print(stdout) - print(stderr) - raise - - # 2. Add the new snapshot to ZK - zkhandler.writedata(zk_conn, { - '/ceph/snapshots/{}/{}/{}'.format(pool, volume, name): '', - '/ceph/snapshots/{}/{}/{}/stats'.format(pool, volume, name): '{}' - }) - - # Log it - logger.out('Created new RBD snapshot {} of volume {} on pool {}'.format(name, volume, pool), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to create new RBD snapshot {} of volume {} on pool {}: {}'.format(name, volume, pool, e), state='e') - return False - -def rename_snapshot(zk_conn, logger, pool, volume, name, new_name): - logger.out('Renaming RBD volume snapshot {} to {} for volume {} on pool {}'.format(name, new_name, volume, pool)) - try: - # Rename the volume - retcode, stdout, stderr = common.run_os_command('rbd snap rename {}/{}@{} {}'.format(pool, volume, name, new_name)) - if retcode: - print('rbd snap rename') - print(stdout) - print(stderr) - raise - - # Rename the snapshot in ZK - zkhandler.renamekey(zk_conn, { - '/ceph/snapshots/{}/{}/{}'.format(pool, volume, name): '/ceph/snapshots/{}/{}/{}'.format(pool, volume, new_name) - }) - - # Update the snapshot stats in ZK - zkhandler.writedata(zk_conn, { - '/ceph/snapshots/{}/{}/{}/stats'.format(pool, volume, new_name): '{}', - }) - - # Log it - logger.out('Renamed RBD volume snapshot {} to {} for volume {} on pool {}'.format(name, new_name, volume, pool), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to rename RBD volume snapshot {} for volume {} on pool {}: {}'.format(name, volume, pool, e), state='e') - return False - -def remove_snapshot(zk_conn, logger, pool, volume, name): - # We are ready to create a new snapshot on this node - logger.out('Removing RBD snapshot {} of volume {} on pool {}'.format(name, volume, pool), state='i') - try: - # Delete snapshot from ZK - zkhandler.deletekey(zk_conn, '/ceph/snapshots/{}/{}/{}'.format(pool, volume, name)) - - # Remove the snapshot - retcode, stdout, stderr = common.run_os_command('rbd snap rm {}/{}@{}'.format(pool, volume, name)) - if retcode: - print('rbd snap rm') - print(stdout) - print(stderr) - raise - - # Log it - logger.out('Removed RBD snapshot {} of volume {} on pool {}'.format(name, volume, pool), state='o') - return True - except Exception as e: - # Log it - logger.out('Failed to remove RBD snapshot {} of volume {} on pool {}: {}'.format(name, volume, pool, e), state='e') - return False - # Primary command function +# This command pipe is only used for OSD adds and removes def run_command(zk_conn, logger, this_node, data, d_osd): # Get the command and args command, args = data.split() @@ -804,301 +415,3 @@ def run_command(zk_conn, logger, this_node, data, d_osd): zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) # Wait 1 seconds before we free the lock, to ensure the client hits the lock time.sleep(1) - - # Online an OSD - elif command == 'osd_in': - osd_id = args - - # Verify osd_id is in the list - if d_osd[osd_id] and d_osd[osd_id].node == this_node.name: - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Online the OSD - result = in_osd(zk_conn, logger, osd_id) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Offline an OSD - elif command == 'osd_out': - osd_id = args - - # Verify osd_id is in the list - if d_osd[osd_id] and d_osd[osd_id].node == this_node.name: - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Offline the OSD - result = out_osd(zk_conn, logger, osd_id) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Set a property - elif command == 'osd_set': - option = args - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Set the property - result = set_property(zk_conn, logger, option) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Unset a property - elif command == 'osd_unset': - option = args - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Unset the property - result = unset_property(zk_conn, logger, option) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Adding a new pool - elif command == 'pool_add': - name, pgs, copies, mincopies = args.split(',') - copies = copies.replace('copies=','') - mincopies = mincopies.replace('mincopies=','') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Add the pool - result = add_pool(zk_conn, logger, name, pgs, copies, mincopies) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Removing a pool - elif command == 'pool_remove': - name = args - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Remove the pool - result = remove_pool(zk_conn, logger, name) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Adding a new volume - elif command == 'volume_add': - pool, name, size = args.split(',') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Add the volume - result = add_volume(zk_conn, logger, pool, name, size) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Cloning a volume - elif command == 'volume_clone': - pool, name_orig, name_new, prefix = args.split(',') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Clone the volume - result = clone_volume(zk_conn, logger, pool, name_orig, name_new, prefix) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Resizing a volume - elif command == 'volume_resize': - pool, name, size = args.split(',') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Add the volume - result = resize_volume(zk_conn, logger, pool, name, size) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Renaming a new volume - elif command == 'volume_rename': - pool, name, new_name = args.split(',') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Add the volume - result = rename_volume(zk_conn, logger, pool, name, new_name) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Removing a volume - elif command == 'volume_remove': - pool, name = args.split(',') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Remove the volume - result = remove_volume(zk_conn, logger, pool, name) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Adding a new snapshot - elif command == 'snapshot_add': - pool, volume, name = args.split(',') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Add the snapshot - result = add_snapshot(zk_conn, logger, pool, volume, name) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Renaming a snapshot - elif command == 'snapshot_rename': - pool, volume, name, new_name = args.split(',') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Add the snapshot - result = rename_snapshot(zk_conn, logger, pool, volume, name, new_name) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1) - - # Removing a snapshot - elif command == 'snapshot_remove': - pool, volume, name = args.split(',') - - if this_node.router_state == 'primary': - # Lock the command queue - zk_lock = zkhandler.writelock(zk_conn, '/cmd/ceph') - with zk_lock: - # Remove the snapshot - result = remove_snapshot(zk_conn, logger, pool, volume, name) - # Command succeeded - if result: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'success-{}'.format(data)}) - # Command failed - else: - # Update the command queue - zkhandler.writedata(zk_conn, {'/cmd/ceph': 'failure-{}'.format(data)}) - # Wait 1 seconds before we free the lock, to ensure the client hits the lock - time.sleep(1)