Add OSD list function

This commit is contained in:
Joshua Boniface 2018-10-30 09:17:32 -04:00
parent bfbe9188ce
commit 9a271bda0a
2 changed files with 250 additions and 12 deletions

View File

@ -973,6 +973,22 @@ def ceph_osd_remove(osdid):
retcode, retmsg = pvc_ceph.remove_osd(zk_conn, osdid) retcode, retmsg = pvc_ceph.remove_osd(zk_conn, osdid)
cleanup(retcode, retmsg, zk_conn) cleanup(retcode, retmsg, zk_conn)
###############################################################################
# pvc ceph osd list
###############################################################################
@click.command(name='list', short_help='List cluster OSDs.')
@click.argument(
'limit', default=None, required=False
)
def ceph_osd_list(limit):
"""
List all Ceph OSDs in the cluster; optinally only match elements matching ID regex LIMIT.
"""
zk_conn = pvc_common.startZKConnection(zk_host)
retcode, retmsg = pvc_ceph.get_list_osd(zk_conn, limit)
cleanup(retcode, retmsg, zk_conn)
############################################################################### ###############################################################################
# pvc ceph pool # pvc ceph pool
############################################################################### ###############################################################################
@ -1119,7 +1135,7 @@ ceph_osd.add_command(ceph_osd_remove)
#ceph_osd.add_command(ceph_osd_set) #ceph_osd.add_command(ceph_osd_set)
#ceph_osd.add_command(ceph_osd_unset) #ceph_osd.add_command(ceph_osd_unset)
#ceph_osd.add_command(ceph_osd_info) #ceph_osd.add_command(ceph_osd_info)
#ceph_osd.add_command(ceph_osd_list) ceph_osd.add_command(ceph_osd_list)
#ceph_pool.add_command(ceph_pool_add) #ceph_pool.add_command(ceph_pool_add)
#ceph_pool.add_command(ceph_pool_remove) #ceph_pool.add_command(ceph_pool_remove)

View File

@ -20,19 +20,9 @@
# #
############################################################################### ###############################################################################
import os
import socket
import time
import uuid
import re import re
import tempfile
import subprocess
import difflib
import colorama
import click import click
import lxml.objectify import ast
import configparser
import kazoo.client
import client_lib.ansiprint as ansiprint import client_lib.ansiprint as ansiprint
import client_lib.zkhandler as zkhandler import client_lib.zkhandler as zkhandler
@ -42,6 +32,208 @@ import client_lib.common as common
# Supplemental functions # Supplemental functions
# #
#
# Cluster search functions
#
def getClusterOSDList(zk_conn):
# Get a list of VNIs by listing the children of /networks
osd_list = zkhandler.listchildren(zk_conn, '/ceph/osds')
return osd_list
def getOSDInformation(zk_conn, osd_id):
# Parse the stats data
osd_stats_raw = zkhandler.readdata(zk_conn, '/ceph/osds/{}/stats'.format(osd_id))
osd_stats = dict(ast.literal_eval(osd_stats_raw))
return osd_stats
def getCephOSDs(zk_conn):
osd_list = zkhandler.listchildren(zk_conn, '/ceph/osds')
return osd_list
def formatOSDList(zk_conn, osd_list):
osd_list_output = []
osd_uuid = dict()
osd_up = dict()
osd_up_colour = dict()
osd_in = dict()
osd_in_colour = dict()
osd_weight = dict()
osd_node = dict()
osd_used = dict()
osd_free = dict()
osd_wrops = dict()
osd_wrdata = dict()
osd_rdops = dict()
osd_rddata = dict()
osd_state = dict()
osd_state_colour = dict()
osd_id_length = 3
osd_up_length = 4
osd_in_length = 4
osd_weight_length = 7
osd_node_length = 5
osd_used_length = 5
osd_free_length = 6
osd_wrops_length = 4
osd_wrdata_length = 5
osd_rdops_length = 4
osd_rddata_length = 5
for osd in osd_list:
# Set the OSD ID length
_osd_id_length = len(osd) + 1
if _osd_id_length > osd_id_length:
osd_id_length = _osd_id_length
# Get stats
osd_stats = getOSDInformation(zk_conn, osd)
# Set the parent node and length
osd_node[osd] = osd_stats['node']
_osd_node_length = len(osd_node[osd]) + 1
if _osd_node_length > osd_node_length:
osd_node_length = _osd_node_length
# Set the UP status
if osd_stats['up'] == 1:
osd_up[osd] = 'Yes'
osd_up_colour[osd] = ansiprint.green()
else:
osd_up[osd] = 'No'
osd_up_colour[osd] = ansiprint.red()
# Set the IN status
if osd_stats['in'] == 1:
osd_in[osd] = 'Yes'
osd_in_colour[osd] = ansiprint.green()
else:
osd_in[osd] = 'No'
osd_in_colour[osd] = ansiprint.red()
# Set the weight and length
osd_weight[osd] = osd_stats['weight']
_osd_weight_length = len(str(osd_weight[osd])) + 1
if _osd_weight_length > osd_weight_length:
osd_weight_length = _osd_weight_length
# Set the used/available space and length
osd_used[osd] = osd_stats['used']
_osd_used_length = len(osd_used[osd]) + 1
if _osd_used_length > osd_used_length:
osd_used_length = _osd_used_length
osd_free[osd] = osd_stats['avail']
_osd_free_length = len(osd_free[osd]) + 1
if _osd_free_length > osd_free_length:
osd_free_length = _osd_free_length
# Set the write IOPS/data and length
osd_wrops[osd] = osd_stats['wr_ops']
_osd_wrops_length = len(osd_wrops[osd]) + 1
if _osd_wrops_length > osd_wrops_length:
osd_wrops_length = _osd_wrops_length
osd_wrdata[osd] = osd_stats['wr_data']
_osd_wrdata_length = len(osd_wrdata[osd]) + 1
if _osd_wrdata_length > osd_wrdata_length:
osd_wrdata_length = _osd_wrdata_length
# Set the read IOPS/data and length
osd_rdops[osd] = osd_stats['rd_ops']
_osd_rdops_length = len(osd_rdops[osd]) + 1
if _osd_rdops_length > osd_rdops_length:
osd_rdops_length = _osd_rdops_length
osd_rddata[osd] = osd_stats['rd_data']
_osd_rddata_length = len(osd_rddata[osd]) + 1
if _osd_rddata_length > osd_rddata_length:
osd_rddata_length = _osd_rddata_length
# Format the output header
osd_list_output_header = '{bold}\
{osd_id: <{osd_id_length}} \
{osd_node: <{osd_node_length}} \
{osd_up: <{osd_up_length}} \
{osd_in: <{osd_in_length}} \
{osd_weight: <{osd_weight_length}} \
Space: {osd_used: <{osd_used_length}} \
{osd_free: <{osd_free_length}} \
Write: {osd_wrops: <{osd_wrops_length}} \
{osd_wrdata: <{osd_wrdata_length}} \
Read: {osd_rdops: <{osd_rdops_length}} \
{osd_rddata: <{osd_rddata_length}} \
{end_bold}'.format(
bold=ansiprint.bold(),
end_bold=ansiprint.end(),
osd_id_length=osd_id_length,
osd_node_length=osd_node_length,
osd_up_length=osd_up_length,
osd_in_length=osd_in_length,
osd_weight_length=osd_weight_length,
osd_used_length=osd_used_length,
osd_free_length=osd_free_length,
osd_wrops_length=osd_wrops_length,
osd_wrdata_length=osd_wrdata_length,
osd_rdops_length=osd_rdops_length,
osd_rddata_length=osd_rddata_length,
osd_id='ID',
osd_node='Node',
osd_up='Up',
osd_in='In',
osd_weight='Weight',
osd_used='Used',
osd_free='Free',
osd_wrops='OPS',
osd_wrdata='Data',
osd_rdops='OPS',
osd_rddata='Data'
)
for osd in osd_list:
# Format the output header
osd_list_output.append('{bold}\
{osd_id: <{osd_id_length}} \
{osd_node: <{osd_node_length}} \
{osd_up_colour}{osd_up: <{osd_up_length}}{end_colour} \
{osd_in_colour}{osd_in: <{osd_in_length}}{end_colour} \
{osd_weight: <{osd_weight_length}} \
{osd_used: <{osd_used_length}} \
{osd_free: <{osd_free_length}} \
{osd_wrops: <{osd_wrops_length}} \
{osd_wrdata: <{osd_wrdata_length}} \
{osd_rdops: <{osd_rdops_length}} \
{osd_rddata: <{osd_rddata_length}} \
{end_bold}'.format(
bold=ansiprint.bold(),
end_bold=ansiprint.end(),
end_colour=ansiprint.end(),
osd_id_length=osd_id_length,
osd_node_length=osd_node_length,
osd_up_length=osd_up_length,
osd_in_length=osd_in_length,
osd_weight_length=osd_weight_length,
osd_used_length=osd_used_length,
osd_free_length=osd_free_length,
osd_wrops_length=osd_wrops_length,
osd_wrdata_length=osd_wrdata_length,
osd_rdops_length=osd_rdops_length,
osd_rddata_length=osd_rddata_length,
osd_id=osd,
osd_node=osd_node[osd],
osd_up_colour=osd_up_colour[osd],
osd_up=osd_up[osd],
osd_in_colour=osd_in_colour[osd],
osd_in=osd_in[osd],
osd_weight=osd_weight[osd],
osd_used=osd_used[osd],
osd_free=osd_free[osd],
osd_wrops=osd_wrops[osd],
osd_wrdata=osd_wrdata[osd],
osd_rdops=osd_rdops[osd],
osd_rddata=osd_rddata[osd]
)
)
output_string = osd_list_output_header + '\n' + '\n'.join(sorted(osd_list_output))
return output_string
# #
# Direct functions # Direct functions
@ -69,3 +261,33 @@ def remove_osd(zk_conn, osd_id):
zkhandler.writedata(zk_conn, {'/ceph/osd_cmd': remove_osd_string}) zkhandler.writedata(zk_conn, {'/ceph/osd_cmd': remove_osd_string})
click.echo('Removed OSD with ID {} from the cluster.'.format(osd_id)) click.echo('Removed OSD with ID {} from the cluster.'.format(osd_id))
return True, '' return True, ''
def get_list_osd(zk_conn, limit):
osd_list = []
full_osd_list = getCephOSDs(zk_conn)
if limit:
try:
# Implicitly assume fuzzy limits
if re.match('\^.*', limit) == None:
limit = '.*' + limit
if re.match('.*\$', limit) == None:
limit = limit + '.*'
except Exception as e:
return False, 'Regex Error: {}'.format(e)
for osd in full_osd_list:
valid_osd = False
if limit:
if re.match(limit, osd['osd_id']) != None:
valid_osd = True
else:
valid_osd = True
if valid_osd:
osd_list.append(osd)
output_string = formatOSDList(zk_conn, osd_list)
click.echo(output_string)
return True, ''