utilities/tools/engtools/hostdata-collectors/scripts/buddyinfo.py
Long Li 9ec7cf4447 Update engtools to use python3
Change spec and scripts to only use
python3 explicitly

Verification:
1. Regard as the README,in development docker environment, run
./patch-engtools.sh,
it will generate the ENGTOOLS-20.01.patch
if we scp the patch to controller,
we could sw-patch upload and sw-apply it successfully.

2. The engtools-1.0-4.tis.noarch.rpm is not built into bootimage by default
thus if we package it into bootimage when to verify it.
1). Run some bash script, such as
ceph.sh, memstats.sh, netstats.sh and so on
it will display the collect system resource information.
2). The service of collect-engtools.service
could start and stop without problem
3). If we run the modified python which we have changed to python3.
python3 buddyinfo.py
it will deplay the resource information
python3 live_stream.py
the log of livestream.log will display collect information

This package only be packaged into bootimage when we need it to
collect system resource information.

Change-Id: I9bd77e34650e200f0c65db966635a8ebcdc584aa
Story: 2007106
Task: 39112
Depends-on: https://review.opendev.org/#/c/712218/
Depends-on: https://review.opendev.org/#/c/714072/
Signed-off-by: Long Li <lilong-neu@neusoft.com>
2020-04-07 08:04:59 +00:00

124 lines
4.2 KiB
Python

#!/usr/bin/env python3
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 textwidth=79 autoindent
"""
Python source code
Last modified: 15 Feb 2014 - 13:38
Last author: lmwangi at gmail com
Displays the available memory fragments
by querying /proc/buddyinfo
Example:
# python3 buddyinfo.py
"""
import optparse
import os
import re
from collections import defaultdict
import logging
class Logger:
def __init__(self, log_level):
self.log_level = log_level
def get_formatter(self):
return logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
def get_handler(self):
return logging.StreamHandler()
def get_logger(self):
"""Returns a Logger instance for the specified module_name"""
logger = logging.getLogger('main')
logger.setLevel(self.log_level)
log_handler = self.get_handler()
log_handler.setFormatter(self.get_formatter())
logger.addHandler(log_handler)
return logger
class BuddyInfo(object):
"""BuddyInfo DAO"""
def __init__(self, logger):
super(BuddyInfo, self).__init__()
self.log = logger
self.buddyinfo = self.load_buddyinfo()
def parse_line(self, line):
line = line.strip()
self.log.debug("Parsing line: %s" % line)
parsed_line = re.match("Node\s+(?P<numa_node>\d+).*zone\s+(?P<zone>\w+)\s+(?P<nr_free>.*)", line).groupdict()
self.log.debug("Parsed line: %s" % parsed_line)
return parsed_line
def read_buddyinfo(self):
buddyhash = defaultdict(list)
buddyinfo = open("/proc/buddyinfo").readlines()
for line in map(self.parse_line, buddyinfo):
numa_node = int(line["numa_node"])
zone = line["zone"]
free_fragments = [int(nr) for nr in line["nr_free"].split()]
max_order = len(free_fragments)
fragment_sizes = self.get_order_sizes(max_order)
usage_in_bytes = [block[0] * block[1] for block in zip(free_fragments, fragment_sizes)]
buddyhash[numa_node].append({
"zone": zone,
"nr_free": free_fragments,
"sz_fragment": fragment_sizes,
"usage": usage_in_bytes})
return buddyhash
def load_buddyinfo(self):
buddyhash = self.read_buddyinfo()
self.log.info(buddyhash)
return buddyhash
def page_size(self):
return os.sysconf("SC_PAGE_SIZE")
def get_order_sizes(self, max_order):
return [self.page_size() * 2**order for order in range(0, max_order)]
def __str__(self):
ret_string = ""
width = 20
for node in self.buddyinfo:
ret_string += "Node: %s\n" % node
for zoneinfo in self.buddyinfo.get(node):
ret_string += " Zone: %s\n" % zoneinfo.get("zone")
ret_string += " Free KiB in zone: %.2f\n" % (sum(zoneinfo.get("usage")) / (1024.0))
ret_string += '\t{0:{align}{width}} {1:{align}{width}} {2:{align}{width}}\n'.format(
"Fragment size", "Free fragments", "Total available KiB",
width=width,
align="<")
for idx in range(len(zoneinfo.get("sz_fragment"))):
ret_string += '\t{order:{align}{width}} {nr:{align}{width}} {usage:{align}{width}}\n'.format(
width=width,
align="<",
order=zoneinfo.get("sz_fragment")[idx],
nr=zoneinfo.get("nr_free")[idx],
usage=zoneinfo.get("usage")[idx] / 1024.0)
return ret_string
def main():
"""Main function. Called when this file is a shell script"""
usage = "usage: %prog [options]"
parser = optparse.OptionParser(usage)
parser.add_option("-s", "--size", dest="size", choices=["B", "K", "M"],
action="store", type="choice", help="Return results in bytes, kib, mib")
(options, args) = parser.parse_args()
logger = Logger(logging.DEBUG).get_logger()
logger.info("Starting....")
logger.info("Parsed options: %s" % options)
print(logger)
buddy = BuddyInfo(logger)
print(buddy)
if __name__ == '__main__':
main()