1f1687a1bSjiaqizho#!/usr/bin/env python3 2*17538bdcSpaul luse# SPDX-License-Identifier: BSD-3-Clause 3*17538bdcSpaul luse# Copyright (C) 2019 Intel Corporation 4*17538bdcSpaul luse# All rights reserved. 5*17538bdcSpaul luse# 6f1687a1bSjiaqizho 7f1687a1bSjiaqizhoimport logging 87610bc38SKonrad Sztyberimport os 9f1687a1bSjiaqizhoimport sys 10f1687a1bSjiaqizhoimport argparse 11f1687a1bSjiaqizhoimport time 127610bc38SKonrad Sztyber 137610bc38SKonrad Sztybersys.path.append(os.path.dirname(__file__) + '/../python') 147610bc38SKonrad Sztyber 157610bc38SKonrad Sztyberimport spdk.rpc as rpc # noqa 16f1687a1bSjiaqizho 17f1687a1bSjiaqizho 18f1687a1bSjiaqizhoSPDK_CPU_STAT = "/proc/stat" 19f1687a1bSjiaqizhoSPDK_UPTIME = "/proc/uptime" 20f1687a1bSjiaqizho 21f1687a1bSjiaqizhoSPDK_CPU_STAT_HEAD = ['cpu_stat:', 'user_stat', 'nice_stat', 22f1687a1bSjiaqizho 'system_stat', 'iowait_stat', 'steal_stat', 'idle_stat'] 23f1687a1bSjiaqizhoSPDK_BDEV_KB_STAT_HEAD = ['Device', 'tps', 'KB_read/s', 24f1687a1bSjiaqizho 'KB_wrtn/s', 'KB_dscd/s', 'KB_read', 'KB_wrtn', 'KB_dscd'] 25f1687a1bSjiaqizhoSPDK_BDEV_MB_STAT_HEAD = ['Device', 'tps', 'MB_read/s', 26f1687a1bSjiaqizho 'MB_wrtn/s', 'MB_dscd/s', 'MB_read', 'MB_wrtn', 'MB_dscd'] 2781a8bc67SjiaqizhoSPDK_BDEV_EXT_STAT_HEAD = ['qu-sz', 'aqu-sz', 'wareq-sz', 'rareq-sz', 'w_await(us)', 'r_await(us)', 'util'] 2881a8bc67Sjiaqizho 29f1687a1bSjiaqizho 30f1687a1bSjiaqizhoSPDK_MAX_SECTORS = 0xffffffff 31f1687a1bSjiaqizho 32f1687a1bSjiaqizho 33f1687a1bSjiaqizhoclass BdevStat: 34f1687a1bSjiaqizho 35f1687a1bSjiaqizho def __init__(self, dictionary): 36f1687a1bSjiaqizho if dictionary is None: 37f1687a1bSjiaqizho return 3881a8bc67Sjiaqizho self.qd_period = 0 39f1687a1bSjiaqizho for k, value in dictionary.items(): 40f1687a1bSjiaqizho if k == 'name': 41f1687a1bSjiaqizho self.bdev_name = value 42f1687a1bSjiaqizho elif k == 'bytes_read': 43f1687a1bSjiaqizho self.rd_sectors = value >> 9 44f1687a1bSjiaqizho elif k == 'bytes_written': 45f1687a1bSjiaqizho self.wr_sectors = value >> 9 46f1687a1bSjiaqizho elif k == 'bytes_unmapped': 47f1687a1bSjiaqizho self.dc_sectors = value >> 9 48f1687a1bSjiaqizho elif k == 'num_read_ops': 49f1687a1bSjiaqizho self.rd_ios = value 50f1687a1bSjiaqizho elif k == 'num_write_ops': 51f1687a1bSjiaqizho self.wr_ios = value 52f1687a1bSjiaqizho elif k == 'num_unmap_ops': 53f1687a1bSjiaqizho self.dc_ios = value 54f1687a1bSjiaqizho elif k == 'read_latency_ticks': 55f1687a1bSjiaqizho self.rd_ticks = value 56f1687a1bSjiaqizho elif k == 'write_latency_ticks': 57f1687a1bSjiaqizho self.wr_ticks = value 58f1687a1bSjiaqizho elif k == 'unmap_latency_ticks': 59f1687a1bSjiaqizho self.dc_ticks = value 6081a8bc67Sjiaqizho elif k == 'queue_depth_polling_period': 6181a8bc67Sjiaqizho self.qd_period = value 62f1687a1bSjiaqizho elif k == 'queue_depth': 6381a8bc67Sjiaqizho self.queue_depth = value 64f1687a1bSjiaqizho elif k == 'io_time': 6581a8bc67Sjiaqizho self.io_time = value 66f1687a1bSjiaqizho elif k == 'weighted_io_time': 6781a8bc67Sjiaqizho self.weighted_io_time = value 68f1687a1bSjiaqizho self.upt = 0.0 69f1687a1bSjiaqizho 70f1687a1bSjiaqizho def __getattr__(self, name): 71f1687a1bSjiaqizho return 0 72f1687a1bSjiaqizho 73f1687a1bSjiaqizho 74f1687a1bSjiaqizhodef uptime(): 75f1687a1bSjiaqizho with open(SPDK_UPTIME, 'r') as f: 76f1687a1bSjiaqizho return float(f.readline().split()[0]) 77f1687a1bSjiaqizho 78f1687a1bSjiaqizho 79f1687a1bSjiaqizhodef _stat_format(data, header, leave_first=False): 80f1687a1bSjiaqizho list_size = len(data) 81f1687a1bSjiaqizho header_len = len(header) 82f1687a1bSjiaqizho 83f1687a1bSjiaqizho if list_size == 0: 84f1687a1bSjiaqizho raise AssertionError 85f1687a1bSjiaqizho list_len = len(data[0]) 86f1687a1bSjiaqizho 87f1687a1bSjiaqizho for ll in data: 88f1687a1bSjiaqizho if len(ll) != list_len: 89f1687a1bSjiaqizho raise AssertionError 90f1687a1bSjiaqizho for i, r in enumerate(ll): 91f1687a1bSjiaqizho ll[i] = str(r) 92f1687a1bSjiaqizho 93f1687a1bSjiaqizho if (leave_first and list_len + 1 != header_len) or \ 94f1687a1bSjiaqizho (not leave_first and list_len != header_len): 95f1687a1bSjiaqizho raise AssertionError 96f1687a1bSjiaqizho 97f1687a1bSjiaqizho item_sizes = [0 for i in range(header_len)] 98f1687a1bSjiaqizho 99f1687a1bSjiaqizho for i in range(0, list_len): 100f1687a1bSjiaqizho if leave_first and i == 0: 101f1687a1bSjiaqizho item_sizes[i] = len(header[i + 1]) 102f1687a1bSjiaqizho 103f1687a1bSjiaqizho data_len = 0 104f1687a1bSjiaqizho for x in data: 105f1687a1bSjiaqizho data_len = max(data_len, len(x[i])) 106f1687a1bSjiaqizho index = i + 1 if leave_first else i 107f1687a1bSjiaqizho item_sizes[index] = max(len(header[index]), data_len) 108f1687a1bSjiaqizho 109f1687a1bSjiaqizho _format = ' '.join('%%-%ss' % item_sizes[i] for i in range(0, header_len)) 110f1687a1bSjiaqizho print(_format % tuple(header)) 111f1687a1bSjiaqizho if leave_first: 112f1687a1bSjiaqizho print('\n'.join(_format % ('', *tuple(ll)) for ll in data)) 113f1687a1bSjiaqizho else: 114f1687a1bSjiaqizho print('\n'.join(_format % tuple(ll) for ll in data)) 115f1687a1bSjiaqizho 116f1687a1bSjiaqizho print() 117f1687a1bSjiaqizho sys.stdout.flush() 118f1687a1bSjiaqizho 119f1687a1bSjiaqizho 120f1687a1bSjiaqizhodef read_cpu_stat(last_cpu_info, cpu_info): 121f1687a1bSjiaqizho jiffies = 0 122f1687a1bSjiaqizho for i in range(0, 7): 123f1687a1bSjiaqizho jiffies += cpu_info[i] - \ 124f1687a1bSjiaqizho (last_cpu_info[i] if last_cpu_info else 0) 125f1687a1bSjiaqizho 126f1687a1bSjiaqizho if last_cpu_info: 127f1687a1bSjiaqizho info_stat = [ 128f1687a1bSjiaqizho "{:.2%}".format((cpu_info[0] - last_cpu_info[0]) / jiffies), 129f1687a1bSjiaqizho "{:.2%}".format((cpu_info[1] - last_cpu_info[1]) / jiffies), 130f1687a1bSjiaqizho "{:.2%}".format(((cpu_info[2] + cpu_info[5] + cpu_info[6]) - 131f1687a1bSjiaqizho (last_cpu_info[2] + last_cpu_info[5] + last_cpu_info[6])) / jiffies), 132f1687a1bSjiaqizho "{:.2%}".format((cpu_info[4] - last_cpu_info[4]) / jiffies), 133f1687a1bSjiaqizho "{:.2%}".format((cpu_info[7] - last_cpu_info[7]) / jiffies), 134f1687a1bSjiaqizho "{:.2%}".format((cpu_info[3] - last_cpu_info[3]) / jiffies), 135f1687a1bSjiaqizho ] 136f1687a1bSjiaqizho else: 137f1687a1bSjiaqizho info_stat = [ 138f1687a1bSjiaqizho "{:.2%}".format(cpu_info[0] / jiffies), 139f1687a1bSjiaqizho "{:.2%}".format(cpu_info[1] / jiffies), 140f1687a1bSjiaqizho "{:.2%}".format((cpu_info[2] + cpu_info[5] 141f1687a1bSjiaqizho + cpu_info[6]) / jiffies), 142f1687a1bSjiaqizho "{:.2%}".format(cpu_info[4] / jiffies), 143f1687a1bSjiaqizho "{:.2%}".format(cpu_info[7] / jiffies), 144f1687a1bSjiaqizho "{:.2%}".format(cpu_info[3] / jiffies), 145f1687a1bSjiaqizho ] 146f1687a1bSjiaqizho 147f1687a1bSjiaqizho _stat_format([info_stat], SPDK_CPU_STAT_HEAD, True) 148f1687a1bSjiaqizho 149f1687a1bSjiaqizho 150f1687a1bSjiaqizhodef check_positive(value): 151f1687a1bSjiaqizho v = int(value) 152f1687a1bSjiaqizho if v <= 0: 153f1687a1bSjiaqizho raise argparse.ArgumentTypeError("%s should be positive int value" % v) 154f1687a1bSjiaqizho return v 155f1687a1bSjiaqizho 156f1687a1bSjiaqizho 157f1687a1bSjiaqizhodef get_cpu_stat(): 158f1687a1bSjiaqizho with open(SPDK_CPU_STAT, "r") as cpu_file: 159f1687a1bSjiaqizho cpu_dump_info = [] 160f1687a1bSjiaqizho line = cpu_file.readline() 161f1687a1bSjiaqizho while line: 162f1687a1bSjiaqizho line = line.strip() 163f1687a1bSjiaqizho if "cpu " in line: 164f1687a1bSjiaqizho cpu_dump_info = [int(data) for data in line[5:].split(' ')] 165f1687a1bSjiaqizho break 166f1687a1bSjiaqizho 167f1687a1bSjiaqizho line = cpu_file.readline() 168f1687a1bSjiaqizho return cpu_dump_info 169f1687a1bSjiaqizho 170f1687a1bSjiaqizho 17181a8bc67Sjiaqizhodef read_bdev_stat(last_stat, stat, mb, use_upt, ext_info): 172f1687a1bSjiaqizho if use_upt: 173f1687a1bSjiaqizho upt_cur = uptime() 174f1687a1bSjiaqizho else: 175f1687a1bSjiaqizho upt_cur = stat['ticks'] 17681a8bc67Sjiaqizho 177f1687a1bSjiaqizho upt_rate = stat['tick_rate'] 178f1687a1bSjiaqizho 179f1687a1bSjiaqizho info_stats = [] 180f1687a1bSjiaqizho unit = 2048 if mb else 2 181f1687a1bSjiaqizho 182f1687a1bSjiaqizho bdev_stats = [] 183f1687a1bSjiaqizho if last_stat: 184f1687a1bSjiaqizho for bdev in stat['bdevs']: 185f1687a1bSjiaqizho _stat = BdevStat(bdev) 186f1687a1bSjiaqizho _stat.upt = upt_cur 187f1687a1bSjiaqizho bdev_stats.append(_stat) 188f1687a1bSjiaqizho _last_stat = None 189f1687a1bSjiaqizho for last_bdev in last_stat: 190f1687a1bSjiaqizho if (_stat.bdev_name == last_bdev.bdev_name): 191f1687a1bSjiaqizho _last_stat = last_bdev 192f1687a1bSjiaqizho break 193f1687a1bSjiaqizho 194f1687a1bSjiaqizho # get the interval time 195f1687a1bSjiaqizho if use_upt: 196f1687a1bSjiaqizho upt = _stat.upt - _last_stat.upt 197f1687a1bSjiaqizho else: 198f1687a1bSjiaqizho upt = (_stat.upt - _last_stat.upt) / upt_rate 199f1687a1bSjiaqizho 200f1687a1bSjiaqizho rd_sec = _stat.rd_sectors - _last_stat.rd_sectors 201f1687a1bSjiaqizho if (_stat.rd_sectors < _last_stat.rd_sectors) and (_last_stat.rd_sectors <= SPDK_MAX_SECTORS): 202f1687a1bSjiaqizho rd_sec &= SPDK_MAX_SECTORS 203f1687a1bSjiaqizho 204f1687a1bSjiaqizho wr_sec = _stat.wr_sectors - _last_stat.wr_sectors 205f1687a1bSjiaqizho if (_stat.wr_sectors < _last_stat.wr_sectors) and (_last_stat.wr_sectors <= SPDK_MAX_SECTORS): 206f1687a1bSjiaqizho wr_sec &= SPDK_MAX_SECTORS 207f1687a1bSjiaqizho 208f1687a1bSjiaqizho dc_sec = _stat.dc_sectors - _last_stat.dc_sectors 209f1687a1bSjiaqizho if (_stat.dc_sectors < _last_stat.dc_sectors) and (_last_stat.dc_sectors <= SPDK_MAX_SECTORS): 210f1687a1bSjiaqizho dc_sec &= SPDK_MAX_SECTORS 211f1687a1bSjiaqizho 212f1687a1bSjiaqizho tps = ((_stat.rd_ios + _stat.dc_ios + _stat.wr_ios) - 213f1687a1bSjiaqizho (_last_stat.rd_ios + _last_stat.dc_ios + _last_stat.wr_ios)) / upt 214f1687a1bSjiaqizho 215f1687a1bSjiaqizho info_stat = [ 216f1687a1bSjiaqizho _stat.bdev_name, 217f1687a1bSjiaqizho "{:.2f}".format(tps), 218f1687a1bSjiaqizho "{:.2f}".format( 219f1687a1bSjiaqizho (_stat.rd_sectors - _last_stat.rd_sectors) / upt / unit), 220f1687a1bSjiaqizho "{:.2f}".format( 221f1687a1bSjiaqizho (_stat.wr_sectors - _last_stat.wr_sectors) / upt / unit), 222f1687a1bSjiaqizho "{:.2f}".format( 223f1687a1bSjiaqizho (_stat.dc_sectors - _last_stat.dc_sectors) / upt / unit), 224f1687a1bSjiaqizho "{:.2f}".format(rd_sec / unit), 225f1687a1bSjiaqizho "{:.2f}".format(wr_sec / unit), 226f1687a1bSjiaqizho "{:.2f}".format(dc_sec / unit), 227f1687a1bSjiaqizho ] 22881a8bc67Sjiaqizho if ext_info: 22981a8bc67Sjiaqizho if _stat.qd_period > 0: 23081a8bc67Sjiaqizho tot_sampling_time = upt * 1000000 / _stat.qd_period 23181a8bc67Sjiaqizho busy_times = (_stat.io_time - _last_stat.io_time) / _stat.qd_period 23281a8bc67Sjiaqizho 23381a8bc67Sjiaqizho wr_ios = _stat.wr_ios - _last_stat.wr_ios 23481a8bc67Sjiaqizho rd_ios = _stat.rd_ios - _last_stat.rd_ios 23581a8bc67Sjiaqizho if busy_times != 0: 23681a8bc67Sjiaqizho aqu_sz = (_stat.weighted_io_time - _last_stat.weighted_io_time) / _stat.qd_period / busy_times 23781a8bc67Sjiaqizho else: 23881a8bc67Sjiaqizho aqu_sz = 0 23981a8bc67Sjiaqizho 24081a8bc67Sjiaqizho if wr_ios != 0: 24181a8bc67Sjiaqizho wareq_sz = wr_sec / wr_ios 24281a8bc67Sjiaqizho w_await = (_stat.wr_ticks * 1000000 / upt_rate - 24381a8bc67Sjiaqizho _last_stat.wr_ticks * 1000000 / upt_rate) / wr_ios 24481a8bc67Sjiaqizho else: 24581a8bc67Sjiaqizho wareq_sz = 0 24681a8bc67Sjiaqizho w_await = 0 24781a8bc67Sjiaqizho 24881a8bc67Sjiaqizho if rd_ios != 0: 24981a8bc67Sjiaqizho rareq_sz = rd_sec / rd_ios 25081a8bc67Sjiaqizho r_await = (_stat.rd_ticks * 1000000 / upt_rate - 25181a8bc67Sjiaqizho _last_stat.rd_ticks * 1000000 / upt_rate) / rd_ios 25281a8bc67Sjiaqizho else: 25381a8bc67Sjiaqizho rareq_sz = 0 25481a8bc67Sjiaqizho r_await = 0 25581a8bc67Sjiaqizho 25681a8bc67Sjiaqizho util = busy_times / tot_sampling_time 25781a8bc67Sjiaqizho 25881a8bc67Sjiaqizho info_stat += [ 25981a8bc67Sjiaqizho "{:.2f}".format(_stat.queue_depth), 26081a8bc67Sjiaqizho "{:.2f}".format(aqu_sz), 26181a8bc67Sjiaqizho "{:.2f}".format(wareq_sz), 26281a8bc67Sjiaqizho "{:.2f}".format(rareq_sz), 26381a8bc67Sjiaqizho "{:.2f}".format(w_await), 26481a8bc67Sjiaqizho "{:.2f}".format(r_await), 26581a8bc67Sjiaqizho "{:.2f}".format(util), 26681a8bc67Sjiaqizho ] 26781a8bc67Sjiaqizho else: 26881a8bc67Sjiaqizho info_stat += ["N/A"] * len(SPDK_BDEV_EXT_STAT_HEAD) 26981a8bc67Sjiaqizho 270f1687a1bSjiaqizho info_stats.append(info_stat) 271f1687a1bSjiaqizho else: 272f1687a1bSjiaqizho for bdev in stat['bdevs']: 273f1687a1bSjiaqizho _stat = BdevStat(bdev) 274f1687a1bSjiaqizho _stat.upt = upt_cur 275f1687a1bSjiaqizho bdev_stats.append(_stat) 276f1687a1bSjiaqizho 277f1687a1bSjiaqizho if use_upt: 278f1687a1bSjiaqizho upt = _stat.upt 279f1687a1bSjiaqizho else: 280f1687a1bSjiaqizho upt = _stat.upt / upt_rate 281f1687a1bSjiaqizho 282f1687a1bSjiaqizho tps = (_stat.rd_ios + _stat.dc_ios + _stat.wr_ios) / upt 283f1687a1bSjiaqizho info_stat = [ 284f1687a1bSjiaqizho _stat.bdev_name, 285f1687a1bSjiaqizho "{:.2f}".format(tps), 286f1687a1bSjiaqizho "{:.2f}".format(_stat.rd_sectors / upt / unit), 287f1687a1bSjiaqizho "{:.2f}".format(_stat.wr_sectors / upt / unit), 288f1687a1bSjiaqizho "{:.2f}".format(_stat.dc_sectors / upt / unit), 289f1687a1bSjiaqizho "{:.2f}".format(_stat.rd_sectors / unit), 290f1687a1bSjiaqizho "{:.2f}".format(_stat.wr_sectors / unit), 291f1687a1bSjiaqizho "{:.2f}".format(_stat.dc_sectors / unit), 292f1687a1bSjiaqizho ] 29381a8bc67Sjiaqizho 29481a8bc67Sjiaqizho # add extended statistics 29581a8bc67Sjiaqizho if ext_info: 29681a8bc67Sjiaqizho if _stat.qd_period > 0: 29781a8bc67Sjiaqizho tot_sampling_time = upt * 1000000 / _stat.qd_period 29881a8bc67Sjiaqizho busy_times = _stat.io_time / _stat.qd_period 29981a8bc67Sjiaqizho if busy_times != 0: 30081a8bc67Sjiaqizho aqu_sz = _stat.weighted_io_time / _stat.qd_period / busy_times 30181a8bc67Sjiaqizho else: 30281a8bc67Sjiaqizho aqu_sz = 0 30381a8bc67Sjiaqizho 30481a8bc67Sjiaqizho if _stat.wr_ios != 0: 30581a8bc67Sjiaqizho wareq_sz = _stat.wr_sectors / _stat.wr_ios 30681a8bc67Sjiaqizho w_await = _stat.wr_ticks * 1000000 / upt_rate / _stat.wr_ios 30781a8bc67Sjiaqizho else: 30881a8bc67Sjiaqizho wareq_sz = 0 30981a8bc67Sjiaqizho w_await = 0 31081a8bc67Sjiaqizho 31181a8bc67Sjiaqizho if _stat.rd_ios != 0: 31281a8bc67Sjiaqizho rareq_sz = _stat.rd_sectors / _stat.rd_ios 31381a8bc67Sjiaqizho r_await = _stat.rd_ticks * 1000000 / upt_rate / _stat.rd_ios 31481a8bc67Sjiaqizho else: 31581a8bc67Sjiaqizho rareq_sz = 0 31681a8bc67Sjiaqizho r_await = 0 31781a8bc67Sjiaqizho 31881a8bc67Sjiaqizho util = busy_times / tot_sampling_time 31981a8bc67Sjiaqizho 32081a8bc67Sjiaqizho info_stat += [ 32181a8bc67Sjiaqizho "{:.2f}".format(_stat.queue_depth), 32281a8bc67Sjiaqizho "{:.2f}".format(aqu_sz), 32381a8bc67Sjiaqizho "{:.2f}".format(wareq_sz), 32481a8bc67Sjiaqizho "{:.2f}".format(rareq_sz), 32581a8bc67Sjiaqizho "{:.2f}".format(w_await), 32681a8bc67Sjiaqizho "{:.2f}".format(r_await), 32781a8bc67Sjiaqizho "{:.2f}".format(util), 32881a8bc67Sjiaqizho ] 32981a8bc67Sjiaqizho else: 33081a8bc67Sjiaqizho info_stat += ["N/A"] * len(SPDK_BDEV_EXT_STAT_HEAD) 33181a8bc67Sjiaqizho 332f1687a1bSjiaqizho info_stats.append(info_stat) 333f1687a1bSjiaqizho 33481a8bc67Sjiaqizho head = [] 33581a8bc67Sjiaqizho head += SPDK_BDEV_MB_STAT_HEAD if mb else SPDK_BDEV_KB_STAT_HEAD 33681a8bc67Sjiaqizho if ext_info: 33781a8bc67Sjiaqizho head += SPDK_BDEV_EXT_STAT_HEAD 33881a8bc67Sjiaqizho 33981a8bc67Sjiaqizho _stat_format(info_stats, head) 340f1687a1bSjiaqizho return bdev_stats 341f1687a1bSjiaqizho 342f1687a1bSjiaqizho 343f1687a1bSjiaqizhodef get_bdev_stat(client, name): 344f1687a1bSjiaqizho return rpc.bdev.bdev_get_iostat(client, name=name) 345f1687a1bSjiaqizho 346f1687a1bSjiaqizho 347f1687a1bSjiaqizhodef io_stat_display(args, cpu_info, stat): 348f1687a1bSjiaqizho if args.cpu_stat and not args.bdev_stat: 349f1687a1bSjiaqizho _cpu_info = get_cpu_stat() 350f1687a1bSjiaqizho read_cpu_stat(cpu_info, _cpu_info) 351f1687a1bSjiaqizho return _cpu_info, None 352f1687a1bSjiaqizho 353f1687a1bSjiaqizho if args.bdev_stat and not args.cpu_stat: 354f1687a1bSjiaqizho _stat = get_bdev_stat(args.client, args.name) 355f1687a1bSjiaqizho bdev_stats = read_bdev_stat( 35681a8bc67Sjiaqizho stat, _stat, args.mb_display, args.use_uptime, args.extended_display) 357f1687a1bSjiaqizho return None, bdev_stats 358f1687a1bSjiaqizho 359f1687a1bSjiaqizho _cpu_info = get_cpu_stat() 360f1687a1bSjiaqizho read_cpu_stat(cpu_info, _cpu_info) 361f1687a1bSjiaqizho 362f1687a1bSjiaqizho _stat = get_bdev_stat(args.client, args.name) 36381a8bc67Sjiaqizho bdev_stats = read_bdev_stat(stat, _stat, args.mb_display, args.use_uptime, args.extended_display) 364f1687a1bSjiaqizho return _cpu_info, bdev_stats 365f1687a1bSjiaqizho 366f1687a1bSjiaqizho 367f1687a1bSjiaqizhodef io_stat_display_loop(args): 368f1687a1bSjiaqizho interval = args.interval 369f1687a1bSjiaqizho time_in_second = args.time_in_second 370f1687a1bSjiaqizho args.client = rpc.client.JSONRPCClient( 371f1687a1bSjiaqizho args.server_addr, args.port, args.timeout, log_level=getattr(logging, args.verbose.upper())) 372f1687a1bSjiaqizho 373f1687a1bSjiaqizho last_cpu_stat = None 374f1687a1bSjiaqizho bdev_stats = None 375f1687a1bSjiaqizho 376f1687a1bSjiaqizho cur = 0 377f1687a1bSjiaqizho while True: 378f1687a1bSjiaqizho last_cpu_stat, bdev_stats = io_stat_display( 379f1687a1bSjiaqizho args, last_cpu_stat, bdev_stats) 380f1687a1bSjiaqizho 381f1687a1bSjiaqizho time.sleep(interval) 382f1687a1bSjiaqizho cur += interval 383f1687a1bSjiaqizho if cur >= time_in_second: 384f1687a1bSjiaqizho break 385f1687a1bSjiaqizho 386f1687a1bSjiaqizho 387f1687a1bSjiaqizhoif __name__ == "__main__": 388f1687a1bSjiaqizho parser = argparse.ArgumentParser( 389f1687a1bSjiaqizho description='SPDK iostats command line interface') 390f1687a1bSjiaqizho 391f1687a1bSjiaqizho parser.add_argument('-c', '--cpu-status', dest='cpu_stat', 392f1687a1bSjiaqizho action='store_true', help="Only display cpu status", 393f1687a1bSjiaqizho required=False, default=False) 394f1687a1bSjiaqizho 395f1687a1bSjiaqizho parser.add_argument('-d', '--bdev-status', dest='bdev_stat', 396f1687a1bSjiaqizho action='store_true', help="Only display Blockdev io stats", 397f1687a1bSjiaqizho required=False, default=False) 398f1687a1bSjiaqizho 399f1687a1bSjiaqizho parser.add_argument('-k', '--kb-display', dest='kb_display', 400f1687a1bSjiaqizho action='store_true', help="Display drive stats in KiB", 401f1687a1bSjiaqizho required=False, default=False) 402f1687a1bSjiaqizho 403f1687a1bSjiaqizho parser.add_argument('-m', '--mb-display', dest='mb_display', 404f1687a1bSjiaqizho action='store_true', help="Display drive stats in MiB", 405f1687a1bSjiaqizho required=False, default=False) 406f1687a1bSjiaqizho 407f1687a1bSjiaqizho parser.add_argument('-u', '--use-uptime', dest='use_uptime', 408f1687a1bSjiaqizho action='store_true', help='Use uptime or spdk ticks(default) as \ 409f1687a1bSjiaqizho the interval variable to calculate iostat changes.', 410f1687a1bSjiaqizho required=False, default=False) 411f1687a1bSjiaqizho 412f1687a1bSjiaqizho parser.add_argument('-i', '--interval', dest='interval', 413f1687a1bSjiaqizho type=check_positive, help='Time interval (in seconds) on which \ 414f1687a1bSjiaqizho to poll I/O stats. Used in conjunction with -t', 415f1687a1bSjiaqizho required=False, default=0) 416f1687a1bSjiaqizho 417f1687a1bSjiaqizho parser.add_argument('-t', '--time', dest='time_in_second', 418f1687a1bSjiaqizho type=check_positive, help='The number of second to display stats \ 419f1687a1bSjiaqizho before returning. Used in conjunction with -i', 420f1687a1bSjiaqizho required=False, default=0) 421f1687a1bSjiaqizho 422f1687a1bSjiaqizho parser.add_argument('-s', "--server", dest='server_addr', 423f1687a1bSjiaqizho help='RPC domain socket path or IP address', 424f1687a1bSjiaqizho default='/var/tmp/spdk.sock') 425f1687a1bSjiaqizho 426f1687a1bSjiaqizho parser.add_argument('-p', "--port", dest='port', 427f1687a1bSjiaqizho help='RPC port number (if server_addr is IP address)', 428f1687a1bSjiaqizho default=4420, type=int) 429f1687a1bSjiaqizho 430f1687a1bSjiaqizho parser.add_argument('-b', '--name', dest='name', 431f1687a1bSjiaqizho help="Name of the Blockdev. Example: Nvme0n1", required=False) 432f1687a1bSjiaqizho 433f1687a1bSjiaqizho parser.add_argument('-o', '--timeout', dest='timeout', 434f1687a1bSjiaqizho help='Timeout as a floating point number expressed in seconds \ 435f1687a1bSjiaqizho waiting for response. Default: 60.0', 436f1687a1bSjiaqizho default=60.0, type=float) 437f1687a1bSjiaqizho 438f1687a1bSjiaqizho parser.add_argument('-v', dest='verbose', action='store_const', const="INFO", 439f1687a1bSjiaqizho help='Set verbose mode to INFO', default="ERROR") 440f1687a1bSjiaqizho 44181a8bc67Sjiaqizho parser.add_argument('-x', '--extended', dest='extended_display', 44281a8bc67Sjiaqizho action='store_true', help="Display extended statistics.", 44381a8bc67Sjiaqizho required=False, default=False) 44481a8bc67Sjiaqizho 445f1687a1bSjiaqizho args = parser.parse_args() 446f1687a1bSjiaqizho if ((args.interval == 0 and args.time_in_second != 0) or 447f1687a1bSjiaqizho (args.interval != 0 and args.time_in_second == 0)): 448f1687a1bSjiaqizho raise argparse.ArgumentTypeError( 449f1687a1bSjiaqizho "interval and time_in_second should be greater than 0 at the same time") 450f1687a1bSjiaqizho 451f1687a1bSjiaqizho if args.kb_display and args.mb_display: 452f1687a1bSjiaqizho parser.print_help() 453f1687a1bSjiaqizho exit() 454f1687a1bSjiaqizho 455f1687a1bSjiaqizho io_stat_display_loop(args) 456