From 4a2e25efe4cfcc483ffea036ec389a09ef322004 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Fri, 31 May 2024 17:07:26 +0000 Subject: [PATCH] Import from AlmaLinux stable repository --- .gitignore | 2 +- .rteval.metadata | 1 - ...DMI-WARNING-when-not-running-as-root.patch | 165 ----- ...ert-rteval-Change-the-default-kernel.patch | 68 ++ ...d-relative-cpulists-for-measurements.patch | 278 ++++++++ ...l-Catch-failures-in-python-dmidecode.patch | 54 -- ...al-Convert-CpuList-class-to-a-module.patch | 616 ++++++++++++++++++ ...empt-to-get-DMIinfo-if-there-are-dmi.patch | 169 ----- ...-Minor-improvements-to-CpuList-class.patch | 85 +++ ...ctor-collapse_cpulist-in-systopology.patch | 225 +++++++ .../rteval-Remove-upstream-spec-file.patch | 566 ++++++++++++++++ ...lace-python-ethtool-with-inline-code.patch | 399 ------------ SPECS/rteval.spec | 58 +- 13 files changed, 1892 insertions(+), 794 deletions(-) delete mode 100644 .rteval.metadata delete mode 100644 SOURCES/Fix-DMI-WARNING-when-not-running-as-root.patch create mode 100644 SOURCES/Revert-rteval-Change-the-default-kernel.patch create mode 100644 SOURCES/rteval-Add-relative-cpulists-for-measurements.patch delete mode 100644 SOURCES/rteval-Catch-failures-in-python-dmidecode.patch create mode 100644 SOURCES/rteval-Convert-CpuList-class-to-a-module.patch delete mode 100644 SOURCES/rteval-Don-t-attempt-to-get-DMIinfo-if-there-are-dmi.patch create mode 100644 SOURCES/rteval-Minor-improvements-to-CpuList-class.patch create mode 100644 SOURCES/rteval-Refactor-collapse_cpulist-in-systopology.patch create mode 100644 SOURCES/rteval-Remove-upstream-spec-file.patch delete mode 100644 SOURCES/rteval-Replace-python-ethtool-with-inline-code.patch diff --git a/.gitignore b/.gitignore index ce47971..f0db1ab 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/rteval-3.5.tar.xz +SOURCES/rteval-3.7.tar.xz diff --git a/.rteval.metadata b/.rteval.metadata deleted file mode 100644 index 476b584..0000000 --- a/.rteval.metadata +++ /dev/null @@ -1 +0,0 @@ -3aee70e8cca181b05b522acab8a44d45fb876e28 SOURCES/rteval-3.5.tar.xz diff --git a/SOURCES/Fix-DMI-WARNING-when-not-running-as-root.patch b/SOURCES/Fix-DMI-WARNING-when-not-running-as-root.patch deleted file mode 100644 index e901b20..0000000 --- a/SOURCES/Fix-DMI-WARNING-when-not-running-as-root.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 149c119df7c7a8ddfd1abc7a127d536cc0674230 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Tue, 23 Aug 2022 14:57:37 -0400 -Subject: [PATCH 1/3] rteval: Fix "DMI WARNING" when not running as root - -In some cases it is not necessary to run as root, for example when -running -Z (--summarize) to summarize an existing report. - -In such cases we do not want to see the message: -** DMI WARNING ** Failed to open memory buffer (/dev/mem): Permission denied - -The fix here is to surpresses that message. - -In addition: -- the unused "config" option to DMIinfo.__init__ is removed -- A few strings are converted to f-strings -- "with" is used to open the xsltfile - -Signed-off-by: John Kacur ---- - rteval/sysinfo/__init__.py | 6 ++--- - rteval/sysinfo/dmi.py | 45 +++++++++++++++++++------------------- - 2 files changed, 26 insertions(+), 25 deletions(-) - -diff --git a/rteval/sysinfo/__init__.py b/rteval/sysinfo/__init__.py -index 0436ebb350d9..a4359382f006 100644 ---- a/rteval/sysinfo/__init__.py -+++ b/rteval/sysinfo/__init__.py -@@ -42,7 +42,7 @@ class SystemInfo(KernelInfo, SystemServices, dmi.DMIinfo, CPUtopology, - self.__logger = logger - KernelInfo.__init__(self, logger=logger) - SystemServices.__init__(self, logger=logger) -- dmi.DMIinfo.__init__(self, config, logger=logger) -+ dmi.DMIinfo.__init__(self, logger=logger) - CPUtopology.__init__(self) - OSInfo.__init__(self, logger=logger) - cmdlineInfo.__init__(self, logger=logger) -@@ -80,8 +80,8 @@ if __name__ == "__main__": - cfg.installdir = "." - si = SystemInfo(cfg, logger=l) - -- print("\tRunning on %s" % si.get_base_os()) -- print("\tNUMA nodes: %d" % si.mem_get_numa_nodes()) -+ print(f"\tRunning on {si.get_base_os()}") -+ print(f"\tNUMA nodes: {si.mem_get_numa_nodes()}") - print("\tMemory available: %03.2f %s\n" % si.mem_get_size()) - - print("\tServices: ") -diff --git a/rteval/sysinfo/dmi.py b/rteval/sysinfo/dmi.py -index 80cf3c723b36..5965c128c093 100644 ---- a/rteval/sysinfo/dmi.py -+++ b/rteval/sysinfo/dmi.py -@@ -1,6 +1,4 @@ - # --# dmi.py - class to wrap DMI Table information --# - # Copyright 2009 - 2013 Clark Williams - # Copyright 2009 - 2013 David Sommerseth - # -@@ -24,6 +22,7 @@ - # including keys needed to generate an equivalently functional executable - # are deemed to be part of the source code. - # -+""" dmi.py class to wrap DMI Table Information """ - - import sys - import os -@@ -52,16 +51,18 @@ def ProcessWarnings(): - if warnings is None: - return - -+ ignore1 = '/dev/mem: Permission denied' -+ ignore2 = 'No SMBIOS nor DMI entry point found, sorry.' -+ ignore3 = 'Failed to open memory buffer (/dev/mem): Permission denied' -+ ignore = (ignore1, ignore2, ignore3) - for warnline in warnings.split('\n'): - # Ignore these warnings, as they are "valid" if not running as root -- if warnline == '/dev/mem: Permission denied': -- continue -- if warnline == 'No SMBIOS nor DMI entry point found, sorry.': -+ if warnline in ignore: - continue - - # All other warnings will be printed - if len(warnline) > 0: -- print("** DMI WARNING ** %s" % warnline) -+ print(f"** DMI WARNING ** {warnline}") - - dmidecode.clear_warnings() - -@@ -69,8 +70,7 @@ def ProcessWarnings(): - class DMIinfo: - '''class used to obtain DMI info via python-dmidecode''' - -- # TODO: Remove unnecessary config -- def __init__(self, config, logger): -+ def __init__(self, logger): - self.__version = '0.5' - - if not dmidecode_loaded: -@@ -83,22 +83,24 @@ class DMIinfo: - - self.__xsltparser = self.__load_xslt('rteval_dmi.xsl') - -- def __load_xslt(self, fname): -- xsltfile = None -+ @staticmethod -+ def __load_xslt(fname): -+ xsltf = None - if os.path.exists(fname): -- xsltfile = open(fname, "r") -- elif rtevalConfig.default_config_search([fname], os.path.isfile): -- xsltfile = open(rtevalConfig.default_config_search([fname], os.path.isfile), "r") -- -- if xsltfile: -- xsltdoc = lxml.etree.parse(xsltfile) -- ret = lxml.etree.XSLT(xsltdoc) -- xsltfile.close() -+ xsltf = fname -+ else: -+ xsltf = rtevalConfig.default_config_search([fname], os.path.isfile) -+ -+ if xsltf: -+ with open(xsltf, "r") as xsltfile: -+ xsltdoc = lxml.etree.parse(xsltfile) -+ ret = lxml.etree.XSLT(xsltdoc) - return ret - - raise RuntimeError(f'Could not locate XSLT template for DMI data ({fname})') - - def MakeReport(self): -+ """ Add DMI information to final report """ - rep_n = libxml2.newNode("DMIinfo") - rep_n.newProp("version", self.__version) - if self.__fake: -@@ -113,7 +115,7 @@ class DMIinfo: - return rep_n - - def unit_test(rootdir): -- """ unit_test for dmi.py, looks a little crufty! """ -+ """ unit_test for dmi.py """ - - class UnittestConfigDummy: - def __init__(self, rootdir): -@@ -132,15 +134,14 @@ def unit_test(rootdir): - - log = Log() - log.SetLogVerbosity(Log.DEBUG|Log.INFO) -- cfg = UnittestConfigDummy(rootdir) -- d = DMIinfo(cfg, log) -+ d = DMIinfo(log) - dx = d.MakeReport() - x = libxml2.newDoc("1.0") - x.setRootElement(dx) - x.saveFormatFileEnc("-", "UTF-8", 1) - return 0 - except Exception as e: -- print("** EXCEPTION: %s" % str(e)) -+ print(f"** EXCEPTION: {str(e)}") - return 1 - - if __name__ == '__main__': --- -2.37.3 - diff --git a/SOURCES/Revert-rteval-Change-the-default-kernel.patch b/SOURCES/Revert-rteval-Change-the-default-kernel.patch new file mode 100644 index 0000000..f732cef --- /dev/null +++ b/SOURCES/Revert-rteval-Change-the-default-kernel.patch @@ -0,0 +1,68 @@ +From 47fc74501aa5741fd5dcb2d04aacd857d3d87740 Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Wed, 25 Oct 2023 10:59:28 -0400 +Subject: [PATCH] Revert "rteval: Change the default kernel to compile to + linux-6.1.8" + +This reverts commit 0f39c69610985b07ce2aa41142d2f0481da8e3a4. + +For RHEL-8.x we want to continue using the same kernel for kcompile + +Signed-off-by: John Kacur +--- + Makefile | 2 +- + rteval/modules/loads/kcompile.py | 4 ++-- + rteval/rteval.conf | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Makefile b/Makefile +index b73e8c13f3e5..176435a8cfd5 100644 +--- a/Makefile ++++ b/Makefile +@@ -18,7 +18,7 @@ PREFIX := /usr + DATADIR := $(DESTDIR)/$(PREFIX)/share + LOADDIR := loadsource + +-KLOAD := $(LOADDIR)/linux-6.1.8.tar.xz ++KLOAD := $(LOADDIR)/linux-5.18.1.tar.xz + BLOAD := $(LOADDIR)/dbench-4.0.tar.gz + LOADS := $(KLOAD) $(BLOAD) + +diff --git a/rteval/modules/loads/kcompile.py b/rteval/modules/loads/kcompile.py +index 8be79ce630d5..e531b60754e9 100644 +--- a/rteval/modules/loads/kcompile.py ++++ b/rteval/modules/loads/kcompile.py +@@ -20,7 +20,7 @@ expand_cpulist = CpuList.expand_cpulist + compress_cpulist = CpuList.compress_cpulist + nonisolated_cpulist = CpuList.nonisolated_cpulist + +-DEFAULT_KERNEL_PREFIX = "linux-6.1" ++DEFAULT_KERNEL_PREFIX = "linux-5.18" + + class KBuildJob: + '''Class to manage a build job bound to a particular node''' +@@ -334,7 +334,7 @@ class Kcompile(CommandLineLoad): + + def ModuleParameters(): + return {"source": {"descr": "Source tar ball", +- "default": "linux-6.1.8.tar.xz", ++ "default": "linux-5.18.1.tar.xz", + "metavar": "TARBALL"}, + "jobspercore": {"descr": "Number of working threads per core", + "default": 2, +diff --git a/rteval/rteval.conf b/rteval/rteval.conf +index 79e28032dc6b..1a8d0afd2642 100644 +--- a/rteval/rteval.conf ++++ b/rteval/rteval.conf +@@ -18,7 +18,7 @@ dbench: external + stressng: module + + [kcompile] +-source: linux-6.1.8.xz ++source: linux-5.18.1.xz + jobspercore: 2 + + [hackbench] +-- +2.41.0 + diff --git a/SOURCES/rteval-Add-relative-cpulists-for-measurements.patch b/SOURCES/rteval-Add-relative-cpulists-for-measurements.patch new file mode 100644 index 0000000..933255f --- /dev/null +++ b/SOURCES/rteval-Add-relative-cpulists-for-measurements.patch @@ -0,0 +1,278 @@ +From 64ce7848dfabd2056d35c8a60f3354db45e36286 Mon Sep 17 00:00:00 2001 +From: Tomas Glozar +Date: Thu, 18 Jan 2024 10:18:10 +0100 +Subject: [PATCH 2/4] rteval: Add relative cpulists for measurements + +Instead of specifying an absolute list of CPUs to run measurements on +in --measurement-cpulist, implement an option to specify a relative list +with respect to the current cpuset of rteval. + +The relative cpulist can include CPUs both for addition and for removal, +e.g. +0,1,-7,8. + +Also move the logic for processing cpulists specified by the user as +a string into cpulists usable by rteval to a single function. + +Signed-off-by: Tomas Glozar +Signed-off-by: John Kacur +--- + rteval-cmd | 26 +++++++----- + rteval/cpulist_utils.py | 33 ++++++++++++++++ + rteval/modules/measurement/__init__.py | 9 +---- + rteval/modules/measurement/cyclictest.py | 50 +++--------------------- + rteval/systopology.py | 33 ++++++++++++++++ + 5 files changed, 90 insertions(+), 61 deletions(-) + +diff --git a/rteval-cmd b/rteval-cmd +index d224728..a5e8746 100755 +--- a/rteval-cmd ++++ b/rteval-cmd +@@ -30,7 +30,7 @@ from rteval import RtEval, rtevalConfig + from rteval.modules.loads import LoadModules + from rteval.modules.measurement import MeasurementModules + from rteval.version import RTEVAL_VERSION +-from rteval.systopology import SysTopology ++from rteval.systopology import SysTopology, parse_cpulist_from_config + from rteval.modules.loads.kcompile import ModuleParameters + import rteval.cpulist_utils as cpulist_utils + +@@ -339,26 +339,32 @@ if __name__ == '__main__': + + ldcfg = config.GetSection('loads') + msrcfg = config.GetSection('measurement') +- if ldcfg.cpulist and msrcfg.cpulist: ++ msrcfg_cpulist_present = msrcfg.cpulist != "" ++ # Parse measurement cpulist using parse_cpulist_from_config to account for run-on-isolcpus ++ # and relative cpusets ++ cpulist = parse_cpulist_from_config(msrcfg.cpulist, msrcfg.run_on_isolcpus) ++ if msrcfg_cpulist_present and not cpulist_utils.is_relative(msrcfg.cpulist) and msrcfg.run_on_isolcpus: ++ logger.log(Log.WARN, "ignoring --measurement-run-on-isolcpus, since cpulist is specified") ++ msrcfg.cpulist = collapse_cpulist(cpulist) ++ if ldcfg.cpulist: + ldcfg.cpulist = remove_offline(ldcfg.cpulist) +- msrcfg.cpulist = remove_offline(msrcfg.cpulist) + # if we only specified one set of cpus (loads or measurement) + # default the other to the inverse of the specified list +- if not ldcfg.cpulist and msrcfg.cpulist: ++ if not ldcfg.cpulist and msrcfg_cpulist_present: + tmplist = expand_cpulist(msrcfg.cpulist) + tmplist = SysTopology().invert_cpulist(tmplist) +- ldcfg.cpulist = compress_cpulist(tmplist) +- msrcfg.cpulist = remove_offline(msrcfg.cpulist) +- if not msrcfg.cpulist and ldcfg.cpulist: ++ tmplist = cpulist_utils.online_cpulist(tmplist) ++ ldcfg.cpulist = collapse_cpulist(tmplist) ++ if not msrcfg_cpulist_present and ldcfg.cpulist: + tmplist = expand_cpulist(ldcfg.cpulist) + tmplist = SysTopology().invert_cpulist(tmplist) +- msrcfg.cpulist = compress_cpulist(tmplist) +- ldcfg.cpulist = remove_offline(ldcfg.cpulist) ++ tmplist = cpulist_utils.online_cpulist(tmplist) ++ msrcfg.cpulist = collapse_cpulist(tmplist) + + if ldcfg.cpulist: + logger.log(Log.DEBUG, f"loads cpulist: {ldcfg.cpulist}") + # if --onlyload is specified msrcfg.cpulist is unused +- if msrcfg.cpulist and not rtevcfg.onlyload: ++ if msrcfg_cpulist_present and not rtevcfg.onlyload: + logger.log(Log.DEBUG, f"measurement cpulist: {msrcfg.cpulist}") + logger.log(Log.DEBUG, f"workdir: {rtevcfg.workdir}") + +diff --git a/rteval/cpulist_utils.py b/rteval/cpulist_utils.py +index 402d579..7abc45a 100644 +--- a/rteval/cpulist_utils.py ++++ b/rteval/cpulist_utils.py +@@ -126,3 +126,36 @@ def nonisolated_cpulist(cpulist): + isolated_cpulist = sysread(cpupath, "isolated") + isolated_cpulist = expand_cpulist(isolated_cpulist) + return list(set(cpulist).difference(set(isolated_cpulist))) ++ ++ ++def is_relative(cpulist): ++ return cpulist.startswith("+") or cpulist.startswith("-") ++ ++ ++def expand_relative_cpulist(cpulist): ++ """ ++ Expand a relative cpulist into a tuple of lists. ++ :param cpulist: Relative cpulist of form +1,2,3,-4,5,6 ++ :return: Tuple of two lists, one for added CPUs, one for removed CPUs ++ """ ++ added_cpus = [] ++ removed_cpus = [] ++ ++ if not cpulist: ++ return added_cpus, removed_cpus ++ ++ cpus = None ++ ++ for part in cpulist.split(','): ++ if part.startswith('+') or part.startswith('-'): ++ cpus = added_cpus if part[0] == '+' else removed_cpus ++ part = part[1:] ++ if '-' in part: ++ a, b = part.split('-') ++ a, b = int(a), int(b) ++ cpus.extend(list(range(a, b + 1))) ++ else: ++ a = int(part) ++ cpus.append(a) ++ ++ return list(set(added_cpus)), list(set(removed_cpus)) +diff --git a/rteval/modules/measurement/__init__.py b/rteval/modules/measurement/__init__.py +index 66dc9c5..11bd7b0 100644 +--- a/rteval/modules/measurement/__init__.py ++++ b/rteval/modules/measurement/__init__.py +@@ -5,7 +5,7 @@ + + import libxml2 + from rteval.modules import RtEvalModules, ModuleContainer +-from rteval.systopology import SysTopology as SysTop ++from rteval.systopology import parse_cpulist_from_config + import rteval.cpulist_utils as cpulist_utils + + class MeasurementProfile(RtEvalModules): +@@ -183,12 +183,7 @@ measurement profiles, based on their characteristics""" + rep_n = libxml2.newNode("Measurements") + cpulist = self.__cfg.GetSection("measurement").cpulist + run_on_isolcpus = self.__cfg.GetSection("measurement").run_on_isolcpus +- if cpulist: +- # Convert str to list and remove offline cpus +- cpulist = cpulist_utils.expand_cpulist(cpulist) +- cpulist = cpulist_utils.online_cpulist(cpulist) +- else: +- cpulist = SysTop().online_cpus() if run_on_isolcpus else SysTop().default_cpus() ++ cpulist = parse_cpulist_from_config(cpulist, run_on_isolcpus) + rep_n.newProp("measurecpus", cpulist_utils.collapse_cpulist(cpulist)) + + for mp in self.__measureprofiles: +diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py +index fdca257..7224225 100644 +--- a/rteval/modules/measurement/cyclictest.py ++++ b/rteval/modules/measurement/cyclictest.py +@@ -16,8 +16,7 @@ import math + import libxml2 + from rteval.Log import Log + from rteval.modules import rtevalModulePrototype +-from rteval.systopology import cpuinfo +-from rteval.systopology import SysTopology ++from rteval.systopology import cpuinfo, parse_cpulist_from_config + import rteval.cpulist_utils as cpulist_utils + + expand_cpulist = cpulist_utils.expand_cpulist +@@ -193,39 +192,9 @@ class Cyclictest(rtevalModulePrototype): + self.__priority = int(self.__cfg.setdefault('priority', 95)) + self.__buckets = int(self.__cfg.setdefault('buckets', 2000)) + self.__numcores = 0 +- self.__cpus = [] + self.__cyclicdata = {} +- self.__sparse = False +- self.__run_on_isolcpus = bool(self.__cfg.setdefault('run-on-isolcpus', False)) +- +- if self.__cfg.cpulist: +- self.__cpulist = self.__cfg.cpulist +- self.__cpus = expand_cpulist(self.__cpulist) +- # Only include online cpus +- self.__cpus = cpulist_utils.online_cpulist(self.__cpus) +- # Reset cpulist from the newly calculated self.__cpus +- self.__cpulist = cpulist_utils.collapse_cpulist(self.__cpus) +- self.__cpus = [str(c) for c in self.__cpus] +- self.__sparse = True +- if self.__run_on_isolcpus: +- self._log(Log.WARN, "ignoring --measurement-run-on-isolcpus, since cpulist is specified") +- else: +- self.__cpus = SysTopology().online_cpus_str() +- # Get the cpuset from the environment +- cpuset = os.sched_getaffinity(0) +- # Convert the elements to strings +- cpuset = [str(c) for c in cpuset] +- # Get isolated CPU list +- isolcpus = [str(c) for c in SysTopology().isolated_cpus()] +- # Only include cpus that are in the cpuset and isolated CPUs if run_on_isolcpus is enabled +- self.__cpus = [c for c in self.__cpus if c in cpuset or self.__run_on_isolcpus and c in isolcpus] +- if self.__run_on_isolcpus: +- self.__sparse = True +- self.__cpulist = cpulist_utils.collapse_cpulist([int(c) for c in self.__cpus]) +- +- # Sort the list of cpus to align with the order reported by cyclictest +- self.__cpus.sort(key=int) +- ++ self.__cpulist = self.__cfg.cpulist ++ self.__cpus = [str(c) for c in expand_cpulist(self.__cpulist)] + self.__numcores = len(self.__cpus) + + info = cpuinfo() +@@ -242,10 +211,7 @@ class Cyclictest(rtevalModulePrototype): + logfnc=self._log) + self.__cyclicdata['system'].description = (f"({self.__numcores} cores) ") + info['0']['model name'] + +- if self.__sparse: +- self._log(Log.DEBUG, f"system using {self.__numcores} cpu cores") +- else: +- self._log(Log.DEBUG, f"system has {self.__numcores} cpu cores") ++ self._log(Log.DEBUG, f"system using {self.__numcores} cpu cores") + self.__started = False + self.__cyclicoutput = None + self.__breaktraceval = None +@@ -280,12 +246,8 @@ class Cyclictest(rtevalModulePrototype): + f'-h {self.__buckets}', + f"-p{int(self.__priority)}", + ] +- if self.__sparse: +- self.__cmd.append(f'-t{self.__numcores}') +- self.__cmd.append(f'-a{self.__cpulist}') +- else: +- self.__cmd.append('-t') +- self.__cmd.append('-a') ++ self.__cmd.append(f'-t{self.__numcores}') ++ self.__cmd.append(f'-a{self.__cpulist}') + + if 'threads' in self.__cfg and self.__cfg.threads: + self.__cmd.append(f"-t{int(self.__cfg.threads)}") +diff --git a/rteval/systopology.py b/rteval/systopology.py +index 9e45762..6bcfc77 100644 +--- a/rteval/systopology.py ++++ b/rteval/systopology.py +@@ -241,6 +241,39 @@ class SysTopology: + """ return a list of online cpus in cpulist """ + return [c for c in self.online_cpus() if c in cpulist] + ++ ++def parse_cpulist_from_config(cpulist, run_on_isolcpus=False): ++ """ ++ Generates a cpulist based on --*-cpulist argument given by user ++ :param cpulist: Value of --*-cpulist argument ++ :param run_on_isolcpus: Value of --*-run-on-isolcpus argument ++ :return: Sorted list of CPUs as integers ++ """ ++ if cpulist and not cpulist_utils.is_relative(cpulist): ++ result = cpulist_utils.expand_cpulist(cpulist) ++ # Only include online cpus ++ result = cpulist_utils.online_cpulist(result) ++ else: ++ result = SysTopology().online_cpus() ++ # Get the cpuset from the environment ++ cpuset = os.sched_getaffinity(0) ++ # Get isolated CPU list ++ isolcpus = SysTopology().isolated_cpus() ++ if cpulist and cpulist_utils.is_relative(cpulist): ++ # Include cpus that are not removed in relative cpuset and are either in cpuset from affinity, ++ # isolcpus (with run_on_isolcpus enabled, or added by relative cpuset ++ added_cpus, removed_cpus = cpulist_utils.expand_relative_cpulist(cpulist) ++ result = [c for c in result ++ if (c in cpuset or ++ c in added_cpus or ++ run_on_isolcpus and c in isolcpus) and ++ c not in removed_cpus] ++ else: ++ # Only include cpus that are in the cpuset and isolated CPUs if run_on_isolcpus is enabled ++ result = [c for c in result if c in cpuset or run_on_isolcpus and c in isolcpus] ++ return result ++ ++ + if __name__ == "__main__": + + def unit_test(): +-- +2.43.0 + diff --git a/SOURCES/rteval-Catch-failures-in-python-dmidecode.patch b/SOURCES/rteval-Catch-failures-in-python-dmidecode.patch deleted file mode 100644 index 04d2bb3..0000000 --- a/SOURCES/rteval-Catch-failures-in-python-dmidecode.patch +++ /dev/null @@ -1,54 +0,0 @@ -From eacf0f1e55fa0e7217133172808bfef2c59242fb Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 2 Feb 2023 00:47:31 -0500 -Subject: [PATCH] rteval: Catch failures in python-dmidecode - -python-dmidecode can generate incorrect xml, -namely Attribute unit redefined - -Although useful, the dmidecode is not critical to rteval reporting. - -Therefore catch this, and first see if we can at least query the bios. -If that works report the bios instead of all, and if that -doesn't work, just continue without the dmidecode report. - -Signed-off-by: John Kacur ---- - rteval/sysinfo/dmi.py | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/rteval/sysinfo/dmi.py b/rteval/sysinfo/dmi.py -index 83f347623b58..89a7faae06b1 100644 ---- a/rteval/sysinfo/dmi.py -+++ b/rteval/sysinfo/dmi.py -@@ -79,6 +79,7 @@ class DMIinfo: - - def __init__(self, logger=None): - self.__version = '0.6' -+ self._log = logger - - if not dmidecode_avail: - logger.log(Log.DEBUG, "DMI info unavailable, ignoring DMI tables") -@@ -115,7 +116,18 @@ class DMIinfo: - rep_n.newProp("not_available", "1") - else: - self.__dmixml.SetResultType(dmidecode.DMIXML_DOC) -- dmiqry = xmlout.convert_libxml2_to_lxml_doc(self.__dmixml.QuerySection('all')) -+ try: -+ dmiqry = xmlout.convert_libxml2_to_lxml_doc(self.__dmixml.QuerySection('all')) -+ except Exception as ex1: -+ self._log.log(Log.DEBUG, f'** EXCEPTION {str(ex1)}, will query BIOS only') -+ try: -+ # If we can't query 'all', at least query 'bios' -+ dmiqry = xmlout.convert_libxml2_to_lxml_doc(self.__dmixml.QuerySection('bios')) -+ except Exception as ex2: -+ rep_n.addContent("No DMI tables available") -+ rep_n.newProp("not_available", "1") -+ self._log.log(Log.DEBUG, f'** EXCEPTION {str(ex2)}, dmi info will not be reported') -+ return rep_n - resdoc = self.__xsltparser(dmiqry) - dmi_n = xmlout.convert_lxml_to_libxml2_nodes(resdoc.getroot()) - rep_n.addChild(dmi_n) --- -2.39.0 - diff --git a/SOURCES/rteval-Convert-CpuList-class-to-a-module.patch b/SOURCES/rteval-Convert-CpuList-class-to-a-module.patch new file mode 100644 index 0000000..99c51cc --- /dev/null +++ b/SOURCES/rteval-Convert-CpuList-class-to-a-module.patch @@ -0,0 +1,616 @@ +From a788ea3ec976e51309f0bfae1a41cce704a77f2d Mon Sep 17 00:00:00 2001 +From: Tomas Glozar +Date: Thu, 18 Jan 2024 10:18:09 +0100 +Subject: [PATCH 1/4] rteval: Convert CpuList class to a module + +Move out code from CpuList class in rteval.systopology into a separate +module named rteval.cpulist_utils and avoid wrapping CPU lists in +a CpuList object. + +Almost all uses of CpuList in the code either use the static methods of +the class or its constructor to filter online CPUs by running +CpuList(...).cpulist. The only exception to this are NumaNode and +SimNumaNode classes in systopology; these store a CpuList object, +however their .getcpulist() method extracts the list out. Thus, +the class is completely unnecessary. + +Note: A better name for the module would be cpulist, consistent with the +original name of the class, but this name is already used for variables +throughout the code, hence cpulist_utils is used instead. + +Signed-off-by: Tomas Glozar +Signed-off-by: John Kacur +--- + rteval-cmd | 10 +- + rteval/cpulist_utils.py | 128 ++++++++++++++++++ + rteval/modules/loads/__init__.py | 8 +- + rteval/modules/loads/hackbench.py | 9 +- + rteval/modules/loads/kcompile.py | 11 +- + rteval/modules/loads/stressng.py | 8 +- + rteval/modules/measurement/__init__.py | 8 +- + rteval/modules/measurement/cyclictest.py | 11 +- + rteval/systopology.py | 165 ++--------------------- + 9 files changed, 177 insertions(+), 181 deletions(-) + create mode 100644 rteval/cpulist_utils.py + +diff --git a/rteval-cmd b/rteval-cmd +index 7c41429..d224728 100755 +--- a/rteval-cmd ++++ b/rteval-cmd +@@ -30,11 +30,13 @@ from rteval import RtEval, rtevalConfig + from rteval.modules.loads import LoadModules + from rteval.modules.measurement import MeasurementModules + from rteval.version import RTEVAL_VERSION +-from rteval.systopology import CpuList, SysTopology ++from rteval.systopology import SysTopology + from rteval.modules.loads.kcompile import ModuleParameters ++import rteval.cpulist_utils as cpulist_utils + +-compress_cpulist = CpuList.compress_cpulist +-expand_cpulist = CpuList.expand_cpulist ++compress_cpulist = cpulist_utils.compress_cpulist ++expand_cpulist = cpulist_utils.expand_cpulist ++collapse_cpulist = cpulist_utils.collapse_cpulist + + def summarize(repfile, xslt): + """ Summarize an already existing XML report """ +@@ -211,7 +213,7 @@ def remove_offline(cpulist): + """ return cpulist in collapsed compressed form with only online cpus """ + tmplist = expand_cpulist(cpulist) + tmplist = SysTopology().online_cpulist(tmplist) +- return CpuList.collapse_cpulist(tmplist) ++ return collapse_cpulist(tmplist) + + + if __name__ == '__main__': +diff --git a/rteval/cpulist_utils.py b/rteval/cpulist_utils.py +new file mode 100644 +index 0000000..402d579 +--- /dev/null ++++ b/rteval/cpulist_utils.py +@@ -0,0 +1,128 @@ ++# -*- coding: utf-8 -*- ++# SPDX-License-Identifier: GPL-2.0-or-later ++# ++# Copyright 2016 - Clark Williams ++# Copyright 2021 - John Kacur ++# Copyright 2023 - Tomas Glozar ++# ++"""Module providing utility functions for working with CPU lists""" ++ ++import os ++ ++ ++cpupath = "/sys/devices/system/cpu" ++ ++ ++def sysread(path, obj): ++ """ Helper function for reading system files """ ++ with open(os.path.join(path, obj), "r") as fp: ++ return fp.readline().strip() ++ ++ ++def _online_file_exists(): ++ """ Check whether machine / kernel is configured with online file """ ++ # Note: some machines do not have cpu0/online so we check cpu1/online. ++ # In the case of machines with a single CPU, there is no cpu1, but ++ # that is not a problem, since a single CPU cannot be offline ++ return os.path.exists(os.path.join(cpupath, "cpu1/online")) ++ ++ ++def _isolated_file_exists(): ++ """ Check whether machine / kernel is configured with isolated file """ ++ return os.path.exists(os.path.join(cpupath, "isolated")) ++ ++ ++def collapse_cpulist(cpulist): ++ """ ++ Collapse a list of cpu numbers into a string range ++ of cpus (e.g. 0-5, 7, 9) ++ """ ++ cur_range = [None, None] ++ result = [] ++ for cpu in cpulist + [None]: ++ if cur_range[0] is None: ++ cur_range[0] = cur_range[1] = cpu ++ continue ++ if cpu is not None and cpu == cur_range[1] + 1: ++ # Extend currently processed range ++ cur_range[1] += 1 ++ else: ++ # Range processing finished, add range to string ++ result.append(f"{cur_range[0]}-{cur_range[1]}" ++ if cur_range[0] != cur_range[1] ++ else str(cur_range[0])) ++ # Reset ++ cur_range[0] = cur_range[1] = cpu ++ return ",".join(result) ++ ++ ++def compress_cpulist(cpulist): ++ """ return a string representation of cpulist """ ++ if not cpulist: ++ return "" ++ if isinstance(cpulist[0], int): ++ return ",".join(str(e) for e in cpulist) ++ return ",".join(cpulist) ++ ++ ++def expand_cpulist(cpulist): ++ """ expand a range string into an array of cpu numbers ++ don't error check against online cpus ++ """ ++ result = [] ++ ++ if not cpulist: ++ return result ++ ++ for part in cpulist.split(','): ++ if '-' in part: ++ a, b = part.split('-') ++ a, b = int(a), int(b) ++ result.extend(list(range(a, b + 1))) ++ else: ++ a = int(part) ++ result.append(a) ++ return [int(i) for i in list(set(result))] ++ ++ ++def is_online(n): ++ """ check whether cpu n is online """ ++ path = os.path.join(cpupath, f'cpu{n}') ++ ++ # Some hardware doesn't allow cpu0 to be turned off ++ if not os.path.exists(path + '/online') and n == 0: ++ return True ++ ++ return sysread(path, "online") == "1" ++ ++ ++def online_cpulist(cpulist): ++ """ Given a cpulist, return a cpulist of online cpus """ ++ # This only works if the sys online files exist ++ if not _online_file_exists(): ++ return cpulist ++ newlist = [] ++ for cpu in cpulist: ++ if not _online_file_exists() and cpu == '0': ++ newlist.append(cpu) ++ elif is_online(int(cpu)): ++ newlist.append(cpu) ++ return newlist ++ ++ ++def isolated_cpulist(cpulist): ++ """Given a cpulist, return a cpulist of isolated CPUs""" ++ if not _isolated_file_exists(): ++ return cpulist ++ isolated_cpulist = sysread(cpupath, "isolated") ++ isolated_cpulist = expand_cpulist(isolated_cpulist) ++ return list(set(isolated_cpulist) & set(cpulist)) ++ ++ ++def nonisolated_cpulist(cpulist): ++ """Given a cpulist, return a cpulist of non-isolated CPUs""" ++ if not _isolated_file_exists(): ++ return cpulist ++ isolated_cpulist = sysread(cpupath, "isolated") ++ isolated_cpulist = expand_cpulist(isolated_cpulist) ++ return list(set(cpulist).difference(set(isolated_cpulist))) +diff --git a/rteval/modules/loads/__init__.py b/rteval/modules/loads/__init__.py +index 13fba1e..0845742 100644 +--- a/rteval/modules/loads/__init__.py ++++ b/rteval/modules/loads/__init__.py +@@ -11,7 +11,8 @@ import libxml2 + from rteval.Log import Log + from rteval.rtevalConfig import rtevalCfgSection + from rteval.modules import RtEvalModules, rtevalModulePrototype +-from rteval.systopology import CpuList, SysTopology as SysTop ++from rteval.systopology import SysTopology as SysTop ++import rteval.cpulist_utils as cpulist_utils + + class LoadThread(rtevalModulePrototype): + def __init__(self, name, config, logger=None): +@@ -117,10 +118,11 @@ class LoadModules(RtEvalModules): + cpulist = self._cfg.GetSection(self._module_config).cpulist + if cpulist: + # Convert str to list and remove offline cpus +- cpulist = CpuList(cpulist).cpulist ++ cpulist = cpulist_utils.expand_cpulist(cpulist) ++ cpulist = cpulist_utils.online_cpulist(cpulist) + else: + cpulist = SysTop().default_cpus() +- rep_n.newProp("loadcpus", CpuList.collapse_cpulist(cpulist)) ++ rep_n.newProp("loadcpus", cpulist_utils.collapse_cpulist(cpulist)) + + return rep_n + +diff --git a/rteval/modules/loads/hackbench.py b/rteval/modules/loads/hackbench.py +index cfc7063..a70fdb3 100644 +--- a/rteval/modules/loads/hackbench.py ++++ b/rteval/modules/loads/hackbench.py +@@ -16,10 +16,11 @@ import errno + from signal import SIGKILL + from rteval.modules.loads import CommandLineLoad + from rteval.Log import Log +-from rteval.systopology import CpuList, SysTopology ++from rteval.systopology import SysTopology ++import rteval.cpulist_utils as cpulist_utils + +-expand_cpulist = CpuList.expand_cpulist +-isolated_cpulist = CpuList.isolated_cpulist ++expand_cpulist = cpulist_utils.expand_cpulist ++isolated_cpulist = cpulist_utils.isolated_cpulist + + class Hackbench(CommandLineLoad): + def __init__(self, config, logger): +@@ -61,7 +62,7 @@ class Hackbench(CommandLineLoad): + self.cpus[n] = [c for c in self.cpus[n] if c in expand_cpulist(self.cpulist)] + # if a cpulist was not specified, exclude isolated cpus + else: +- self.cpus[n] = CpuList.nonisolated_cpulist(self.cpus[n]) ++ self.cpus[n] = cpulist_utils.nonisolated_cpulist(self.cpus[n]) + + # track largest number of cpus used on a node + node_biggest = len(self.cpus[n]) +diff --git a/rteval/modules/loads/kcompile.py b/rteval/modules/loads/kcompile.py +index 0d02577..b606f7a 100644 +--- a/rteval/modules/loads/kcompile.py ++++ b/rteval/modules/loads/kcompile.py +@@ -14,11 +14,12 @@ import subprocess + from rteval.modules import rtevalRuntimeError + from rteval.modules.loads import CommandLineLoad + from rteval.Log import Log +-from rteval.systopology import CpuList, SysTopology ++from rteval.systopology import SysTopology ++import rteval.cpulist_utils as cpulist_utils + +-expand_cpulist = CpuList.expand_cpulist +-compress_cpulist = CpuList.compress_cpulist +-nonisolated_cpulist = CpuList.nonisolated_cpulist ++expand_cpulist = cpulist_utils.expand_cpulist ++compress_cpulist = cpulist_utils.compress_cpulist ++nonisolated_cpulist = cpulist_utils.nonisolated_cpulist + + DEFAULT_KERNEL_PREFIX = "linux-5.18" + +@@ -38,7 +39,7 @@ class KBuildJob: + os.mkdir(self.objdir) + + # Exclude isolated CPUs if cpulist not set +- cpus_available = len(nonisolated_cpulist(self.node.cpus.cpulist)) ++ cpus_available = len(nonisolated_cpulist(self.node.cpus)) + + if os.path.exists('/usr/bin/numactl') and not cpulist: + # Use numactl +diff --git a/rteval/modules/loads/stressng.py b/rteval/modules/loads/stressng.py +index 7c9e63f..cbcf6b7 100644 +--- a/rteval/modules/loads/stressng.py ++++ b/rteval/modules/loads/stressng.py +@@ -7,10 +7,10 @@ import subprocess + import signal + from rteval.modules.loads import CommandLineLoad + from rteval.Log import Log +-from rteval.systopology import CpuList, SysTopology ++from rteval.systopology import SysTopology ++import rteval.cpulist_utils as cpulist_utils + +-expand_cpulist = CpuList.expand_cpulist +-nonisolated_cpulist = CpuList.nonisolated_cpulist ++expand_cpulist = cpulist_utils.expand_cpulist + + class Stressng(CommandLineLoad): + " This class creates a load module that runs stress-ng " +@@ -73,7 +73,7 @@ class Stressng(CommandLineLoad): + cpus[n] = [c for c in cpus[n] if c in expand_cpulist(self.cpulist)] + # if a cpulist was not specified, exclude isolated cpus + else: +- cpus[n] = CpuList.nonisolated_cpulist(cpus[n]) ++ cpus[n] = cpulist_utils.nonisolated_cpulist(cpus[n]) + + + # remove nodes with no cpus available for running +diff --git a/rteval/modules/measurement/__init__.py b/rteval/modules/measurement/__init__.py +index 41b8022..66dc9c5 100644 +--- a/rteval/modules/measurement/__init__.py ++++ b/rteval/modules/measurement/__init__.py +@@ -5,7 +5,8 @@ + + import libxml2 + from rteval.modules import RtEvalModules, ModuleContainer +-from rteval.systopology import CpuList, SysTopology as SysTop ++from rteval.systopology import SysTopology as SysTop ++import rteval.cpulist_utils as cpulist_utils + + class MeasurementProfile(RtEvalModules): + """Keeps and controls all the measurement modules with the same measurement profile""" +@@ -184,10 +185,11 @@ measurement profiles, based on their characteristics""" + run_on_isolcpus = self.__cfg.GetSection("measurement").run_on_isolcpus + if cpulist: + # Convert str to list and remove offline cpus +- cpulist = CpuList(cpulist).cpulist ++ cpulist = cpulist_utils.expand_cpulist(cpulist) ++ cpulist = cpulist_utils.online_cpulist(cpulist) + else: + cpulist = SysTop().online_cpus() if run_on_isolcpus else SysTop().default_cpus() +- rep_n.newProp("measurecpus", CpuList.collapse_cpulist(cpulist)) ++ rep_n.newProp("measurecpus", cpulist_utils.collapse_cpulist(cpulist)) + + for mp in self.__measureprofiles: + mprep_n = mp.MakeReport() +diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py +index 1b14e7e..fdca257 100644 +--- a/rteval/modules/measurement/cyclictest.py ++++ b/rteval/modules/measurement/cyclictest.py +@@ -17,9 +17,10 @@ import libxml2 + from rteval.Log import Log + from rteval.modules import rtevalModulePrototype + from rteval.systopology import cpuinfo +-from rteval.systopology import CpuList, SysTopology ++from rteval.systopology import SysTopology ++import rteval.cpulist_utils as cpulist_utils + +-expand_cpulist = CpuList.expand_cpulist ++expand_cpulist = cpulist_utils.expand_cpulist + + class RunData: + '''class to keep instance data from a cyclictest run''' +@@ -201,9 +202,9 @@ class Cyclictest(rtevalModulePrototype): + self.__cpulist = self.__cfg.cpulist + self.__cpus = expand_cpulist(self.__cpulist) + # Only include online cpus +- self.__cpus = CpuList(self.__cpus).cpulist ++ self.__cpus = cpulist_utils.online_cpulist(self.__cpus) + # Reset cpulist from the newly calculated self.__cpus +- self.__cpulist = CpuList.collapse_cpulist(self.__cpus) ++ self.__cpulist = cpulist_utils.collapse_cpulist(self.__cpus) + self.__cpus = [str(c) for c in self.__cpus] + self.__sparse = True + if self.__run_on_isolcpus: +@@ -220,7 +221,7 @@ class Cyclictest(rtevalModulePrototype): + self.__cpus = [c for c in self.__cpus if c in cpuset or self.__run_on_isolcpus and c in isolcpus] + if self.__run_on_isolcpus: + self.__sparse = True +- self.__cpulist = CpuList.collapse_cpulist([int(c) for c in self.__cpus]) ++ self.__cpulist = cpulist_utils.collapse_cpulist([int(c) for c in self.__cpus]) + + # Sort the list of cpus to align with the order reported by cyclictest + self.__cpus.sort(key=int) +diff --git a/rteval/systopology.py b/rteval/systopology.py +index bed5192..9e45762 100644 +--- a/rteval/systopology.py ++++ b/rteval/systopology.py +@@ -9,12 +9,8 @@ + import os + import os.path + import glob +- +- +-def sysread(path, obj): +- """ Helper function for reading system files """ +- with open(os.path.join(path, obj), "r") as fp: +- return fp.readline().strip() ++import rteval.cpulist_utils as cpulist_utils ++from rteval.cpulist_utils import sysread + + def cpuinfo(): + ''' return a dictionary of cpu keys with various cpu information ''' +@@ -56,145 +52,6 @@ def cpuinfo(): + return info + + +-# +-# class to provide access to a list of cpus +-# +- +-class CpuList: +- "Object that represents a group of system cpus" +- +- cpupath = '/sys/devices/system/cpu' +- +- def __init__(self, cpulist): +- if isinstance(cpulist, list): +- self.cpulist = cpulist +- elif isinstance(cpulist, str): +- self.cpulist = self.expand_cpulist(cpulist) +- self.cpulist = self.online_cpulist(self.cpulist) +- self.cpulist.sort() +- +- def __str__(self): +- return self.collapse_cpulist(self.cpulist) +- +- def __contains__(self, cpu): +- return cpu in self.cpulist +- +- def __len__(self): +- return len(self.cpulist) +- +- def getcpulist(self): +- """ return the list of cpus tracked """ +- return self.cpulist +- +- @staticmethod +- def online_file_exists(): +- """ Check whether machine / kernel is configured with online file """ +- # Note: some machines do not have cpu0/online so we check cpu1/online. +- # In the case of machines with a single CPU, there is no cpu1, but +- # that is not a problem, since a single CPU cannot be offline +- return os.path.exists(os.path.join(CpuList.cpupath, "cpu1/online")) +- +- @staticmethod +- def isolated_file_exists(): +- """ Check whether machine / kernel is configured with isolated file """ +- return os.path.exists(os.path.join(CpuList.cpupath, "isolated")) +- +- @staticmethod +- def collapse_cpulist(cpulist): +- """ +- Collapse a list of cpu numbers into a string range +- of cpus (e.g. 0-5, 7, 9) +- """ +- cur_range = [None, None] +- result = [] +- for cpu in cpulist + [None]: +- if cur_range[0] is None: +- cur_range[0] = cur_range[1] = cpu +- continue +- if cpu is not None and cpu == cur_range[1] + 1: +- # Extend currently processed range +- cur_range[1] += 1 +- else: +- # Range processing finished, add range to string +- result.append(f"{cur_range[0]}-{cur_range[1]}" +- if cur_range[0] != cur_range[1] +- else str(cur_range[0])) +- # Reset +- cur_range[0] = cur_range[1] = cpu +- return ",".join(result) +- +- @staticmethod +- def compress_cpulist(cpulist): +- """ return a string representation of cpulist """ +- if not cpulist: +- return "" +- if isinstance(cpulist[0], int): +- return ",".join(str(e) for e in cpulist) +- return ",".join(cpulist) +- +- @staticmethod +- def expand_cpulist(cpulist): +- """ expand a range string into an array of cpu numbers +- don't error check against online cpus +- """ +- result = [] +- +- if not cpulist: +- return result +- +- for part in cpulist.split(','): +- if '-' in part: +- a, b = part.split('-') +- a, b = int(a), int(b) +- result.extend(list(range(a, b + 1))) +- else: +- a = int(part) +- result.append(a) +- return [int(i) for i in list(set(result))] +- +- @staticmethod +- def is_online(n): +- """ check whether cpu n is online """ +- path = os.path.join(CpuList.cpupath, f'cpu{n}') +- +- # Some hardware doesn't allow cpu0 to be turned off +- if not os.path.exists(path + '/online') and n == 0: +- return True +- +- return sysread(path, "online") == "1" +- +- @staticmethod +- def online_cpulist(cpulist): +- """ Given a cpulist, return a cpulist of online cpus """ +- # This only works if the sys online files exist +- if not CpuList.online_file_exists(): +- return cpulist +- newlist = [] +- for cpu in cpulist: +- if not CpuList.online_file_exists() and cpu == '0': +- newlist.append(cpu) +- elif CpuList.is_online(int(cpu)): +- newlist.append(cpu) +- return newlist +- +- @staticmethod +- def isolated_cpulist(cpulist): +- """Given a cpulist, return a cpulist of isolated CPUs""" +- if not CpuList.isolated_file_exists(): +- return cpulist +- isolated_cpulist = sysread(CpuList.cpupath, "isolated") +- isolated_cpulist = CpuList.expand_cpulist(isolated_cpulist) +- return list(set(isolated_cpulist) & set(cpulist)) +- +- @staticmethod +- def nonisolated_cpulist(cpulist): +- """Given a cpulist, return a cpulist of non-isolated CPUs""" +- if not CpuList.isolated_file_exists(): +- return cpulist +- isolated_cpulist = sysread(CpuList.cpupath, "isolated") +- isolated_cpulist = CpuList.expand_cpulist(isolated_cpulist) +- return list(set(cpulist).difference(set(isolated_cpulist))) +- + # + # class to abstract access to NUMA nodes in /sys filesystem + # +@@ -208,7 +65,8 @@ class NumaNode: + """ + self.path = path + self.nodeid = int(os.path.basename(path)[4:].strip()) +- self.cpus = CpuList(sysread(self.path, "cpulist")) ++ self.cpus = cpulist_utils.expand_cpulist(sysread(self.path, "cpulist")) ++ self.cpus = cpulist_utils.online_cpulist(self.cpus) + self.getmeminfo() + + def __contains__(self, cpu): +@@ -240,11 +98,11 @@ class NumaNode: + + def getcpustr(self): + """ return list of cpus for this node as a string """ +- return str(self.cpus) ++ return cpulist_utils.collapse_cpulist(self.cpus) + + def getcpulist(self): + """ return list of cpus for this node """ +- return self.cpus.getcpulist() ++ return self.cpus + + class SimNumaNode(NumaNode): + """class representing a simulated NUMA node. +@@ -257,7 +115,8 @@ class SimNumaNode(NumaNode): + + def __init__(self): + self.nodeid = 0 +- self.cpus = CpuList(sysread(SimNumaNode.cpupath, "possible")) ++ self.cpus = cpulist_utils.expand_cpulist(sysread(SimNumaNode.cpupath, "possible")) ++ self.cpus = cpulist_utils.online_cpulist(self.cpus) + self.getmeminfo() + + def getmeminfo(self): +@@ -339,7 +198,7 @@ class SysTopology: + """ return a list of integers of all online cpus """ + cpulist = [] + for n in self.nodes: +- cpulist += self.getcpus(n) ++ cpulist += cpulist_utils.online_cpulist(self.getcpus(n)) + cpulist.sort() + return cpulist + +@@ -347,7 +206,7 @@ class SysTopology: + """ return a list of integers of all isolated cpus """ + cpulist = [] + for n in self.nodes: +- cpulist += CpuList.isolated_cpulist(self.getcpus(n)) ++ cpulist += cpulist_utils.isolated_cpulist(self.getcpus(n)) + cpulist.sort() + return cpulist + +@@ -355,7 +214,7 @@ class SysTopology: + """ return a list of integers of all default schedulable cpus, i.e. online non-isolated cpus """ + cpulist = [] + for n in self.nodes: +- cpulist += CpuList.nonisolated_cpulist(self.getcpus(n)) ++ cpulist += cpulist_utils.nonisolated_cpulist(self.getcpus(n)) + cpulist.sort() + return cpulist + +@@ -403,7 +262,7 @@ if __name__ == "__main__": + + onlcpus = s.online_cpus() + print(f'onlcpus = {onlcpus}') +- onlcpus = CpuList.collapse_cpulist(onlcpus) ++ onlcpus = cpulist_utils.collapse_cpulist(onlcpus) + print(f'onlcpus = {onlcpus}') + + onlcpus_str = s.online_cpus_str() +-- +2.43.0 + diff --git a/SOURCES/rteval-Don-t-attempt-to-get-DMIinfo-if-there-are-dmi.patch b/SOURCES/rteval-Don-t-attempt-to-get-DMIinfo-if-there-are-dmi.patch deleted file mode 100644 index aaf95f8..0000000 --- a/SOURCES/rteval-Don-t-attempt-to-get-DMIinfo-if-there-are-dmi.patch +++ /dev/null @@ -1,169 +0,0 @@ -From bce23ecc5d8bb6cab86843f7a42164ee44ef091f Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 27 Oct 2022 11:14:27 -0400 -Subject: [PATCH 3/3] rteval: Don't attempt to get DMIinfo if there are dmi - warnings - -If the python module dmidecode is available, but produces warnings, -you can get a traceback. This happens on some arm boxes, -as shown in the traceback below. - -Fix this by treating any warnings that are not listed in the -ignorable warnings as if dmi info is not available. - -Also add logging to dmi.ProcessWarnings() - -./rteval-cmd -d10s -** DMI WARNING ** /sys/firmware/efi/systab: SMBIOS entry point missing -got system topology: 1 node system (4 cores per node) -rteval run on 5.19.16-200.fc36.aarch64 started at Fri Oct 21 16:11:51 2022 -started 3 loads on 4 cores -started measurement threads on 4 cores -Run duration: 10.0 seconds -stopping run at Fri Oct 21 16:13:26 2022 -Traceback (most recent call last): - File "/root/src/rteval/./rteval-cmd", line 402, in - ec = rteval.Measure() - File "/root/src/rteval/rteval/__init__.py", line 286, in Measure - self._report(measure_start, self.__rtevcfg.xslt_report) - File "/root/src/rteval/rteval/rtevalReport.py", line 76, in _report - self.__xmlreport.AppendXMLnodes(self._sysinfo.MakeReport()) - File "/root/src/rteval/rteval/sysinfo/__init__.py", line 69, in MakeReport - report_n.addChild(dmi.DMIinfo.MakeReport(self)) - File "/root/src/rteval/rteval/sysinfo/dmi.py", line 111, in MakeReport - dmiqry = xmlout.convert_libxml2_to_lxml_doc(self.__dmixml.QuerySection('all')) - File "/usr/lib64/python3.10/site-packages/dmidecode.py", line 64, in QuerySection - ret = libxml2.xmlDoc( _obj = xmlapi(query_type='s', -RuntimeError: [src/dmidecodemodule.c:331] Error decoding DMI data - -** COLLECTED WARNINGS ** -/sys/firmware/efi/systab: SMBIOS entry point missing -** END OF WARNINGS ** - -Signed-off-by: John Kacur ---- - rteval-cmd | 4 ++-- - rteval/sysinfo/__init__.py | 2 +- - rteval/sysinfo/dmi.py | 34 +++++++++++++++++++++------------- - 3 files changed, 24 insertions(+), 16 deletions(-) - -diff --git a/rteval-cmd b/rteval-cmd -index 6a928362828f..1e6a7fc86baa 100755 ---- a/rteval-cmd -+++ b/rteval-cmd -@@ -210,8 +210,6 @@ def remove_offline(cpulist): - if __name__ == '__main__': - from rteval.sysinfo import dmi - -- dmi.ProcessWarnings() -- - # set LD_BIND_NOW to resolve shared library symbols - # note: any string will do, nothing significant about 'rteval' - -@@ -261,6 +259,8 @@ if __name__ == '__main__': - | (rtevcfg.debugging and Log.DEBUG) - logger.SetLogVerbosity(loglev) - -+ dmi.ProcessWarnings(logger=logger) -+ - # Load modules - loadmods = LoadModules(config, logger=logger) - measuremods = MeasurementModules(config, logger=logger) -diff --git a/rteval/sysinfo/__init__.py b/rteval/sysinfo/__init__.py -index bb1d00810856..5767e5b7f6fe 100644 ---- a/rteval/sysinfo/__init__.py -+++ b/rteval/sysinfo/__init__.py -@@ -49,7 +49,7 @@ class SystemInfo(KernelInfo, SystemServices, dmi.DMIinfo, CPUtopology, - NetworkInfo.__init__(self, logger=logger) - - # Parse initial DMI decoding errors -- dmi.ProcessWarnings() -+ dmi.ProcessWarnings(logger=logger) - - # Parse CPU info - CPUtopology._parse(self) -diff --git a/rteval/sysinfo/dmi.py b/rteval/sysinfo/dmi.py -index 5965c128c093..83f347623b58 100644 ---- a/rteval/sysinfo/dmi.py -+++ b/rteval/sysinfo/dmi.py -@@ -1,6 +1,7 @@ - # - # Copyright 2009 - 2013 Clark Williams - # Copyright 2009 - 2013 David Sommerseth -+# Copyright 2022 John Kacur - # - # This program is free software; you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by -@@ -34,14 +35,19 @@ from rteval import rtevalConfig - - try: - import dmidecode -- dmidecode_loaded = True -+ dmidecode_avail = True - except ModuleNotFoundError: -- dmidecode_loaded = False -+ dmidecode_avail = False - --def ProcessWarnings(): -+def set_dmidecode_avail(val): -+ """ Used to set global variable dmidecode_avail from a function """ -+ global dmidecode_avail -+ dmidecode_avail = val -+ -+def ProcessWarnings(logger=None): - """ Process Warnings from dmidecode """ - -- if not dmidecode_loaded: -+ if not dmidecode_avail: - return - - if not hasattr(dmidecode, 'get_warnings'): -@@ -62,7 +68,8 @@ def ProcessWarnings(): - - # All other warnings will be printed - if len(warnline) > 0: -- print(f"** DMI WARNING ** {warnline}") -+ logger.log(Log.DEBUG, f"** DMI WARNING ** {warnline}") -+ set_dmidecode_avail(False) - - dmidecode.clear_warnings() - -@@ -70,11 +77,11 @@ def ProcessWarnings(): - class DMIinfo: - '''class used to obtain DMI info via python-dmidecode''' - -- def __init__(self, logger): -- self.__version = '0.5' -+ def __init__(self, logger=None): -+ self.__version = '0.6' - -- if not dmidecode_loaded: -- logger.log(Log.DEBUG|Log.WARN, "No dmidecode module found, ignoring DMI tables") -+ if not dmidecode_avail: -+ logger.log(Log.DEBUG, "DMI info unavailable, ignoring DMI tables") - self.__fake = True - return - -@@ -127,14 +134,15 @@ def unit_test(rootdir): - self.__dict__[k] = self.config[k] - - try: -- ProcessWarnings() -+ log = Log() -+ log.SetLogVerbosity(Log.DEBUG|Log.INFO) -+ -+ ProcessWarnings(logger=log) - if os.getuid() != 0: - print("** ERROR ** Must be root to run this unit_test()") - return 1 - -- log = Log() -- log.SetLogVerbosity(Log.DEBUG|Log.INFO) -- d = DMIinfo(log) -+ d = DMIinfo(logger=log) - dx = d.MakeReport() - x = libxml2.newDoc("1.0") - x.setRootElement(dx) --- -2.37.3 - diff --git a/SOURCES/rteval-Minor-improvements-to-CpuList-class.patch b/SOURCES/rteval-Minor-improvements-to-CpuList-class.patch new file mode 100644 index 0000000..44430e0 --- /dev/null +++ b/SOURCES/rteval-Minor-improvements-to-CpuList-class.patch @@ -0,0 +1,85 @@ +From 768daa63ec8e2299da53afe081e7304b37fc91cf Mon Sep 17 00:00:00 2001 +From: Tomas Glozar +Date: Wed, 29 Nov 2023 10:34:55 +0100 +Subject: [PATCH 2/9] rteval: Minor improvements to CpuList class + +- Remove unnecessary if-else from online_file_exists +- Use cpupath in online_file_exists +- In is_online, remove check for n in cpuset and make it static +- Mark also the remaining methods static since they do not rely on +any fields of the class + +Signed-off-by: Tomas Glozar +- Removed incorrect line from commit message +Signed-off-by: John Kacur +--- + rteval/systopology.py | 29 +++++++++++++++-------------- + 1 file changed, 15 insertions(+), 14 deletions(-) + +diff --git a/rteval/systopology.py b/rteval/systopology.py +index ea8e242..60ac8e8 100644 +--- a/rteval/systopology.py ++++ b/rteval/systopology.py +@@ -82,12 +82,17 @@ class CpuList: + def __len__(self): + return len(self.cpulist) + ++ def getcpulist(self): ++ """ return the list of cpus tracked """ ++ return self.cpulist ++ + @staticmethod + def online_file_exists(): + """ Check whether machine / kernel is configured with online file """ +- if os.path.exists('/sys/devices/system/cpu/cpu1/online'): +- return True +- return False ++ # Note: some machines do not have cpu0/online so we check cpu1/online. ++ # In the case of machines with a single CPU, there is no cpu1, but ++ # that is not a problem, since a single CPU cannot be offline ++ return os.path.exists(os.path.join(CpuList.cpupath, "cpu1/online")) + + @staticmethod + def isolated_file_exists(): +@@ -147,14 +152,9 @@ class CpuList: + result.append(a) + return [int(i) for i in list(set(result))] + +- def getcpulist(self): +- """ return the list of cpus tracked """ +- return self.cpulist +- +- def is_online(self, n): ++ @staticmethod ++ def is_online(n): + """ check whether cpu n is online """ +- if n not in self.cpulist: +- raise RuntimeError(f"invalid cpu number {n}") + path = os.path.join(CpuList.cpupath, f'cpu{n}') + + # Some hardware doesn't allow cpu0 to be turned off +@@ -163,16 +163,17 @@ class CpuList: + + return sysread(path, "online") == "1" + +- def online_cpulist(self, cpulist): ++ @staticmethod ++ def online_cpulist(cpulist): + """ Given a cpulist, return a cpulist of online cpus """ + # This only works if the sys online files exist +- if not self.online_file_exists(): ++ if not CpuList.online_file_exists(): + return cpulist + newlist = [] + for cpu in cpulist: +- if not self.online_file_exists() and cpu == '0': ++ if not CpuList.online_file_exists() and cpu == '0': + newlist.append(cpu) +- elif self.is_online(int(cpu)): ++ elif CpuList.is_online(int(cpu)): + newlist.append(cpu) + return newlist + +-- +2.43.0 + diff --git a/SOURCES/rteval-Refactor-collapse_cpulist-in-systopology.patch b/SOURCES/rteval-Refactor-collapse_cpulist-in-systopology.patch new file mode 100644 index 0000000..cb43c85 --- /dev/null +++ b/SOURCES/rteval-Refactor-collapse_cpulist-in-systopology.patch @@ -0,0 +1,225 @@ +From 4b4f50900e38a931ed9585c6cf200b74c0120a20 Mon Sep 17 00:00:00 2001 +From: Tomas Glozar +Date: Wed, 29 Nov 2023 10:34:54 +0100 +Subject: [PATCH 1/9] rteval: Refactor collapse_cpulist in systopology + +Instead of having duplicate code in two functions, one top-level and +one member function of CpuList, have only one static function in +CpuList. + +Additionally re-write the implementation to use a more straight forward +one-pass algorithm. + +Signed-off-by: Tomas Glozar +Signed-off-by: John Kacur +--- + rteval-cmd | 4 +- + rteval/modules/loads/__init__.py | 4 +- + rteval/modules/measurement/__init__.py | 4 +- + rteval/modules/measurement/cyclictest.py | 6 +-- + rteval/systopology.py | 68 ++++++++---------------- + 5 files changed, 30 insertions(+), 56 deletions(-) + +diff --git a/rteval-cmd b/rteval-cmd +index 6f613a3..7c41429 100755 +--- a/rteval-cmd ++++ b/rteval-cmd +@@ -30,7 +30,7 @@ from rteval import RtEval, rtevalConfig + from rteval.modules.loads import LoadModules + from rteval.modules.measurement import MeasurementModules + from rteval.version import RTEVAL_VERSION +-from rteval.systopology import CpuList, SysTopology, collapse_cpulist ++from rteval.systopology import CpuList, SysTopology + from rteval.modules.loads.kcompile import ModuleParameters + + compress_cpulist = CpuList.compress_cpulist +@@ -211,7 +211,7 @@ def remove_offline(cpulist): + """ return cpulist in collapsed compressed form with only online cpus """ + tmplist = expand_cpulist(cpulist) + tmplist = SysTopology().online_cpulist(tmplist) +- return collapse_cpulist(tmplist) ++ return CpuList.collapse_cpulist(tmplist) + + + if __name__ == '__main__': +diff --git a/rteval/modules/loads/__init__.py b/rteval/modules/loads/__init__.py +index aca0c9f..13fba1e 100644 +--- a/rteval/modules/loads/__init__.py ++++ b/rteval/modules/loads/__init__.py +@@ -11,7 +11,7 @@ import libxml2 + from rteval.Log import Log + from rteval.rtevalConfig import rtevalCfgSection + from rteval.modules import RtEvalModules, rtevalModulePrototype +-from rteval.systopology import collapse_cpulist, CpuList, SysTopology as SysTop ++from rteval.systopology import CpuList, SysTopology as SysTop + + class LoadThread(rtevalModulePrototype): + def __init__(self, name, config, logger=None): +@@ -120,7 +120,7 @@ class LoadModules(RtEvalModules): + cpulist = CpuList(cpulist).cpulist + else: + cpulist = SysTop().default_cpus() +- rep_n.newProp("loadcpus", collapse_cpulist(cpulist)) ++ rep_n.newProp("loadcpus", CpuList.collapse_cpulist(cpulist)) + + return rep_n + +diff --git a/rteval/modules/measurement/__init__.py b/rteval/modules/measurement/__init__.py +index 2a0556b..41b8022 100644 +--- a/rteval/modules/measurement/__init__.py ++++ b/rteval/modules/measurement/__init__.py +@@ -5,7 +5,7 @@ + + import libxml2 + from rteval.modules import RtEvalModules, ModuleContainer +-from rteval.systopology import collapse_cpulist, CpuList, SysTopology as SysTop ++from rteval.systopology import CpuList, SysTopology as SysTop + + class MeasurementProfile(RtEvalModules): + """Keeps and controls all the measurement modules with the same measurement profile""" +@@ -187,7 +187,7 @@ measurement profiles, based on their characteristics""" + cpulist = CpuList(cpulist).cpulist + else: + cpulist = SysTop().online_cpus() if run_on_isolcpus else SysTop().default_cpus() +- rep_n.newProp("measurecpus", collapse_cpulist(cpulist)) ++ rep_n.newProp("measurecpus", CpuList.collapse_cpulist(cpulist)) + + for mp in self.__measureprofiles: + mprep_n = mp.MakeReport() +diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py +index 0af1d31..1b14e7e 100644 +--- a/rteval/modules/measurement/cyclictest.py ++++ b/rteval/modules/measurement/cyclictest.py +@@ -17,7 +17,7 @@ import libxml2 + from rteval.Log import Log + from rteval.modules import rtevalModulePrototype + from rteval.systopology import cpuinfo +-from rteval.systopology import CpuList, SysTopology, collapse_cpulist ++from rteval.systopology import CpuList, SysTopology + + expand_cpulist = CpuList.expand_cpulist + +@@ -203,7 +203,7 @@ class Cyclictest(rtevalModulePrototype): + # Only include online cpus + self.__cpus = CpuList(self.__cpus).cpulist + # Reset cpulist from the newly calculated self.__cpus +- self.__cpulist = collapse_cpulist(self.__cpus) ++ self.__cpulist = CpuList.collapse_cpulist(self.__cpus) + self.__cpus = [str(c) for c in self.__cpus] + self.__sparse = True + if self.__run_on_isolcpus: +@@ -220,7 +220,7 @@ class Cyclictest(rtevalModulePrototype): + self.__cpus = [c for c in self.__cpus if c in cpuset or self.__run_on_isolcpus and c in isolcpus] + if self.__run_on_isolcpus: + self.__sparse = True +- self.__cpulist = collapse_cpulist(self.__cpus) ++ self.__cpulist = CpuList.collapse_cpulist([int(c) for c in self.__cpus]) + + # Sort the list of cpus to align with the order reported by cyclictest + self.__cpus.sort(key=int) +diff --git a/rteval/systopology.py b/rteval/systopology.py +index 62ad355..ea8e242 100644 +--- a/rteval/systopology.py ++++ b/rteval/systopology.py +@@ -10,25 +10,6 @@ import os + import os.path + import glob + +-# Utility version of collapse_cpulist that doesn't require a CpuList object +-def collapse_cpulist(cpulist): +- """ Collapse a list of cpu numbers into a string range +- of cpus (e.g. 0-5, 7, 9) """ +- if len(cpulist) == 0: +- return "" +- idx = CpuList.longest_sequence(cpulist) +- if idx == 0: +- seq = str(cpulist[0]) +- else: +- if idx == 1: +- seq = f"{cpulist[0]},{cpulist[idx]}" +- else: +- seq = f"{cpulist[0]}-{cpulist[idx]}" +- +- rest = collapse_cpulist(cpulist[idx+1:]) +- if rest == "": +- return seq +- return ",".join((seq, rest)) + + def sysread(path, obj): + """ Helper function for reading system files """ +@@ -93,7 +74,7 @@ class CpuList: + self.cpulist.sort() + + def __str__(self): +- return self.__collapse_cpulist(self.cpulist) ++ return self.collapse_cpulist(self.cpulist) + + def __contains__(self, cpu): + return cpu in self.cpulist +@@ -114,35 +95,28 @@ class CpuList: + return os.path.exists(os.path.join(CpuList.cpupath, "isolated")) + + @staticmethod +- def longest_sequence(cpulist): +- """ return index of last element of a sequence that steps by one """ +- lim = len(cpulist) +- for idx, _ in enumerate(cpulist): +- if idx+1 == lim: +- break +- if int(cpulist[idx+1]) != (int(cpulist[idx])+1): +- return idx +- return lim - 1 +- +- def __collapse_cpulist(self, cpulist): +- """ Collapse a list of cpu numbers into a string range ++ def collapse_cpulist(cpulist): ++ """ ++ Collapse a list of cpu numbers into a string range + of cpus (e.g. 0-5, 7, 9) + """ +- if len(cpulist) == 0: +- return "" +- idx = self.longest_sequence(cpulist) +- if idx == 0: +- seq = str(cpulist[0]) +- else: +- if idx == 1: +- seq = f"{cpulist[0]},{cpulist[idx]}" ++ cur_range = [None, None] ++ result = [] ++ for cpu in cpulist + [None]: ++ if cur_range[0] is None: ++ cur_range[0] = cur_range[1] = cpu ++ continue ++ if cpu is not None and cpu == cur_range[1] + 1: ++ # Extend currently processed range ++ cur_range[1] += 1 + else: +- seq = f"{cpulist[0]}-{cpulist[idx]}" +- +- rest = self.__collapse_cpulist(cpulist[idx+1:]) +- if rest == "": +- return seq +- return ",".join((seq, rest)) ++ # Range processing finished, add range to string ++ result.append(f"{cur_range[0]}-{cur_range[1]}" ++ if cur_range[0] != cur_range[1] ++ else str(cur_range[0])) ++ # Reset ++ cur_range[0] = cur_range[1] = cpu ++ return ",".join(result) + + @staticmethod + def compress_cpulist(cpulist): +@@ -428,7 +402,7 @@ if __name__ == "__main__": + + onlcpus = s.online_cpus() + print(f'onlcpus = {onlcpus}') +- onlcpus = collapse_cpulist(onlcpus) ++ onlcpus = CpuList.collapse_cpulist(onlcpus) + print(f'onlcpus = {onlcpus}') + + onlcpus_str = s.online_cpus_str() +-- +2.43.0 + diff --git a/SOURCES/rteval-Remove-upstream-spec-file.patch b/SOURCES/rteval-Remove-upstream-spec-file.patch new file mode 100644 index 0000000..d35f4cc --- /dev/null +++ b/SOURCES/rteval-Remove-upstream-spec-file.patch @@ -0,0 +1,566 @@ +From de8e25ff3a30dbdbba6fb1b68ea0921dff55cd91 Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Mon, 13 Nov 2023 14:32:19 -0500 +Subject: [PATCH] rteval: Remove upstream spec file + +Specfiles should be maintained by distributions and not in the upstream +code. In practice they are not maintained upstream except for version +numbers, so just remove the specfile. + +This also moves a lot of functionality around rpms in the Makefile, but +this functionality exists in tools such as rpmbuild and friends anyway. + +Signed-off-by: John Kacur +--- + Makefile | 37 ---- + rteval.spec | 484 ---------------------------------------------------- + 2 files changed, 521 deletions(-) + delete mode 100644 rteval.spec + +diff --git a/Makefile b/Makefile +index 14f74e087eff..ee4cca555b95 100644 +--- a/Makefile ++++ b/Makefile +@@ -79,49 +79,12 @@ rpm_prep: + + rpms rpm: rpm_prep rtevalrpm loadrpm + +-rtevalrpm: rteval-$(VERSION).tar.bz2 +- cp $^ rpm/SOURCES +- cp rteval.spec rpm/SPECS +- rpmbuild -ba --define "_topdir $(HERE)/rpm" rpm/SPECS/rteval.spec +- +-rtevalsrpm: rteval-$(VERSION).tar.bz2 +- cp $^ rpm/SOURCES +- cp rteval.spec rpm/SPECS +- rpmbuild -bs --define "_topdir $(HERE)/rpm" rpm/SPECS/rteval.spec +- +- +-xmlrpcrpm: rteval-xmlrpc-$(XMLRPCVER).tar.gz +- cp rteval-xmlrpc-$(XMLRPCVER).tar.gz rpm/SOURCES/ +- cp server/rteval-parser.spec rpm/SPECS/ +- rpmbuild -ba --define "_topdir $(HERE)/rpm" rpm/SPECS/rteval-parser.spec +- +-xmlsrpm: rteval-xmlrpc-$(XMLRPCVER).tar.gz +- cp rteval-xmlrpc-$(XMLRPCVER).tar.gz rpm/SOURCES/ +- cp server/rteval-parser.spec rpm/SPECS/ +- rpmbuild -bs --define "_topdir $(HERE)/rpm" rpm/SPECS/rteval-parser.spec +- +-loadrpm: +- rm -rf rpm-loads +- mkdir -p rpm-loads/{BUILD,RPMS,SRPMS,SOURCES,SPECS} +- cp rteval-loads.spec rpm-loads/SPECS +- cp $(LOADS) rpm-loads/SOURCES +- rpmbuild -ba --define "_topdir $(HERE)/rpm-loads" rpm-loads/SPECS/rteval-loads.spec +- +-rpmlint: rpms +- @echo "===============" +- @echo "running rpmlint" +- rpmlint -v $(shell find ./rpm -type f -name "*.rpm") \ +- $(shell find ./rpm-loads -type f -name "*.rpm") \ +- $(shell find ./rpm/SPECS -type f -name "rteval*.spec") \ +- $(shell find ./rpm-loads/SPECS -type f -name "rteval*.spec" ) + + help: + @echo "" + @echo "rteval Makefile targets:" + @echo "" + @echo " runit: do a short testrun locally [default]" +- @echo " rpm: run rpmbuild for all rpms" +- @echo " rpmlint: run rpmlint against all rpms/srpms/specfiles" + @echo " tarfile: create the source tarball" + @echo " install: install rteval locally" + @echo " clean: cleanup generated files" +diff --git a/rteval.spec b/rteval.spec +deleted file mode 100644 +index b5842f0d8206..000000000000 +--- a/rteval.spec ++++ /dev/null +@@ -1,484 +0,0 @@ +-%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} +-%{!?python_ver: %define python_ver %(%{__python} -c "import sys ; print sys.version[:3]")} +- +-Name: rteval +-Version: 3.7 +-Release: 1%{?dist} +-Summary: Utility to evaluate system suitability for RT Linux +- +-Group: Development/Tools +-License: GPLv2 +-URL: http://git.kernel.org/?p=linux/kernel/git/clrkwllms/rteval.git +-Source0: rteval-%{version}.tar.bz2 +-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +- +-BuildRequires: python3-devel +-Requires: platform-python +-Requires: python3-ethtool python3-lxml +-Requires: python3-dmidecode >= 3.10 +-Requires: rt-tests >= 0.97 +-Requires: rteval-loads >= 1.4 +-Requires: rteval-common => %{version}-%{release} +-Requires: sysstat +-Requires: bzip2 +-Requires: kernel-headers +-Requires: sos +-BuildArch: noarch +-Obsoletes: rteval <= 1.7 +-Requires: numactl +- +-%description +-The rteval script is a utility for measuring various aspects of +-realtime behavior on a system under load. The script unpacks the +-kernel source, and then goes into a loop, running hackbench and +-compiling a kernel tree. During that loop the cyclictest program +-is run to measure event response time. After the run time completes, +-a statistical analysis of the event response times is done and printed +-to the screen. +- +- +-%package common +-Summary: Common rteval files +-BuildArch: noarch +- +-%description common +-Common files used by rteval, rteval-xmlrpc and rteval-parser +- +-%prep +-%setup -q +- +-# version sanity check (make sure specfile and rteval.py match) +-cp rteval/version.py rtevalversion.py +-srcver=$(%{__python} -c "from rtevalversion import RTEVAL_VERSION; print RTEVAL_VERSION") +-rm -rf rtevalversion.py +-if [ $srcver != %{version} ]; then +- printf "\n***\n*** rteval spec file version do not match the rteval/rteval.py version\n***\n\n" +- exit -1 +-fi +- +-%build +-%{__python} setup.py build +- +-%install +-%{__python} setup.py install --root=$RPM_BUILD_ROOT +- +-%clean +-rm -rf $RPM_BUILD_ROOT +- +-%files common +-%doc COPYING +-%dir %{_datadir}/%{name} +-%{python_sitelib}/rteval/rtevalclient.py* +-%{python_sitelib}/rteval/rtevalConfig.py* +-%{python_sitelib}/rteval/rtevalXMLRPC.py* +-%{python_sitelib}/rteval/version.py* +-%{python_sitelib}/rteval/Log.py* +-%{python_sitelib}/rteval/misc.py* +-%{python_sitelib}/rteval/systopology.py* +- +-%files +-%defattr(-,root,root,-) +-%if "%{python_ver}" >= "2.5" +-%{python_sitelib}/*.egg-info +-%endif +- +-%doc COPYING README doc/rteval.txt +-%{_mandir}/man8/rteval.8.gz +-%config(noreplace) %{_sysconfdir}/rteval.conf +-%{_datadir}/%{name}/rteval_*.xsl +-%{python_sitelib}/rteval/__init__.py* +-%{python_sitelib}/rteval/rtevalMailer.py* +-%{python_sitelib}/rteval/rtevalReport.py* +-%{python_sitelib}/rteval/xmlout.py* +-%{python_sitelib}/rteval/modules +-%{python_sitelib}/rteval/sysinfo +-/usr/bin/rteval +- +-%changelog +-* Thu Mar 16 2017 Clark Williams - 2.14-1 +-- removed leftover import of systopology from sysinfo +- +-* Wed Mar 15 2017 Clark Williams - 2.13-2 +-- Updated specfile to correct version and bz [1382155] +- +-* Tue Sep 20 2016 Clark Williams - 2.12-1 +-- handle empty environment variables SUDO_USER and USER [1312057] +- +-* Tue Aug 30 2016 Clark Williams - 2.11-1 +-- make sure we return non-zero for early exit from tests +- +-* Wed Aug 3 2016 Clark Williams - 2.10-1 +-- bumped version for RHEL 7.3 release +- +-* Mon May 9 2016 Clark Williams - 2.9.1 +-- default cpulist for modules if only one specified [1333831] +- +-* Tue Apr 26 2016 Clark Williams - 2.8.1 +-- add the --version option to print the rteval version +-- made the --cyclictest-breaktrace option work properly [1209986] +- +-* Fri Apr 1 2016 Clark Williams - 2.7.1 +-- treat SIGINT and SIGTERM as valid end-of-run events [1278757] +-- added cpulist options to man page +- +-* Thu Feb 11 2016 Clark Williams - 2.6.1 +-- update to make --loads-cpulist and --measurement-cpulist work [1306437] +- +-* Thu Dec 10 2015 Clark Williams - 2.5-1 +-- stop using old numactl --cpubind argument +- +-* Wed Dec 9 2015 Clark Williams - 2.4.2 +-- added Require of package numactl +- +-* Tue Nov 17 2015 Clark Williams - 2.4.1 +-- rework hackbench load to not generate cross-node traffic [1282826] +- +-* Wed Aug 12 2015 Clark Williams - 2.3-1 +-- comment out HWLatDetect module from default config [1245699] +- +-* Wed Jun 10 2015 Clark Williams - 2.2-1 +-- add --loads-cpulist and --measurement-cpulist to allow cpu placement [1230401] +- +-* Thu Apr 23 2015 Luis Claudio R. Goncalves - 2.1-8 +-- load default configs when no config file is specified (Jiri kastner) [1212452] +- +-* Wed Jan 14 2015 Clark Williams - 2.1-7 +-- added requires of bzip2 to specfile [1151567] +- +-* Thu Jan 8 2015 Clark Williams - 2.1-6 +-- cleaned up product documentation [1173315] +- +-* Mon Nov 10 2014 Luis Claudio R. Goncalves - 2.1-5 +-- rebuild for RHEL-7.1 (1151567) +- +-* Thu Mar 27 2014 Clark Williams - 2.1-4 +-- cherry-picked old commit to deal with installdir problem +- +-* Wed Mar 26 2014 Clark Williams - 2.1-3 +-- added sysstat requires to specfile +- +-* Tue Mar 12 2013 David Sommerseth - 2.1-2 +-- Migrated from libxslt-python to python-lxml +- +-* Fri Jan 18 2013 David Sommerseth - 2.1-1 +-- Made some log lines clearer +-- cyclictest: Added --cyclictest-breaktrace feature +-- cyclictest: Removed --cyclictest-distance option +-- cyclictest: Use a tempfile buffer for cyclictest's stdout data +-- cyclictest: Report if breaktrace was triggered +-- cyclictest: Make the unit test work again +-- cyclictest: Only log and show statistic data when samples are collected +-- Copyright updates +- +-* Thu Jan 17 2013 David Sommerseth - 2.0.1-1 +-- Fix up type casting in the core module code +-- hwlatdetect: Add some more useful debug info +-- Reworked the run logic for modules - allow them to flag they won't run +-- Fixed a few log messages in load modules +-- Add a 30 seconds sleep before unleashing the measurement threads +- +-* Thu Jan 10 2013 David Sommerseth - 2.0-3 +-- Separate out RTEVAL_VERSION into rteval.version, to avoid +- massive BuildRequirements +- +-* Fri Dec 21 2012 David Sommerseth - 2.0-2 +-- Split out common files into rteval-common +- +-* Fri Dec 21 2012 David Sommerseth - 2.0-1 +-- Updated to rteval v2.0 and reworked spec file to use setup.py directly +- +-* Tue Oct 23 2012 Clark Williams - 1.36-1 +-- deal with system not having dmidecode python module +-- make sure to cast priority parameter to int +-- from Raphaƫl Beamonte : +- - Rewrite of the get_kthreads method to make it cross-distribution +- - Adds getcmdpath method to use which to locate the used commands +- - Rewrite of the get_services method to make it cross-distribution +- +-* Mon Apr 2 2012 Clark Williams - 1.35-1 +-- fix thinko where SIGINT and SIGTERM handlers were commented out +- +-* Thu Jan 12 2012 Clark Williams - 1.34-1 +-- fix missing config merge in rteval.py to pass parameters +- down to cyclictest +-- modify hackbench to use helper function to start process +- +-* Sat May 14 2011 Clark Williams - 1.33-1 +-- modify hackbench cutoff to be 0.75GB/core +- +-* Mon Aug 23 2010 Clark Williams - 1.32-1 +-- update docs +-- refactor some RTEval methods to utility functions +-- modify hackbench.py not to run under low memory conditions +-- clean up XML generation to deal with new hackbench code +-- clean up XSL code to deal with new XML 'run' attribute +-- from David Sommerseth : +- - improve CPU socket counting logic +- - delay log directory creation until actually needed +-- from Gowrishankar : +- - check if the core id really exists (multithreading fix) +- +-* Mon Jul 26 2010 Clark Williams - 1.31-1 +-- from David Sommerseth : +- - Updated hackbench implementation to avoid overusing resources +- - Don't show NUMA node information if it's missing in the summary.xml +- - Show CPU cores properly +- +-* Wed Jul 21 2010 Clark Williams - 1.30-1 +-- added code to hackbench to try to detect and ease memory pressure +- +-* Fri Jul 16 2010 Clark Williams - 1.29-1 +-- fixed incorrect type value in kcompile.py +- +-* Fri Jul 16 2010 Clark Williams - 1.28-1 +-- added logic to loads to adjust number of jobs based on ratio +- of memory per core +- +-* Wed Jul 14 2010 Clark Williams - 1.27-1 +-- modified hackbench to go back to using threads rather than +- processes for units of work +-- added memory size, number of numa nodes and run duration to the +- parameter dictionary passed to all loads and cyclictest +- +-* Tue Jul 13 2010 Clark Williams - 1.26-1 +-- modified hackbench parameters to reduce memory consumption +- +-* Mon Jul 12 2010 Clark Williams - 1.25-1 +-- fixed cyclictest bug that caused everything to be uniprocessor +-- updated source copyrights to 2010 +- +-* Fri Jul 9 2010 Clark Williams - 1.24-1 +-- modified hackbench arguments and added new parameters for +- hackbench in rteval.conf +- +-* Thu Jul 8 2010 Clark Williams - 1.23-1 +-- version bump to deal with out-of-sync cvs issue +- +-* Thu Jul 8 2010 Clark Williams - 1.22-1 +-- merged David Sommerseth changes to use +- hackbench from rt-tests packages rather than carry local copy +-- converted all loads and cyclictest to pass __init__ parameters +- in a dictionary rather than as discrete parameters +-- added logging for load output +- +-* Tue Apr 13 2010 Clark Williams - 1.21-1 +-- from Luis Claudio Goncalves : +- - remove unecessary wait() call in cyclictest.py +- - close /dev/null after using it +- - call subprocess.wait() when needed +- - remove delayloop code in hackbench.py +-- from David Sommerseth : +- - add SIGINT handler +- - handle non-root user case +- - process DMI warnings before command line arguments +- - added --annotate feature to rteval +- - updates to xmlrpc code +- +-* Tue Apr 6 2010 Clark Williams - 1.20-1 +-- code fixes from Luis Claudio Goncalves +-- from David Sommerseth : +- - xmlrpc server updates +- - cputopology.py for recording topology in xml +- - added NUMA node recording for run data +- - rpmlint fixes +-- added start of rteval whitepaper in docs dir +- +-* Tue Mar 16 2010 Clark Williams - 1.19-1 +-- add ability for --summarize to read tarfiles +-- from David Sommerseth +- - gather info about loaded kernel modules for XML file +- - added child tracking to hackbench to prevent zombies +- +-* Tue Feb 16 2010 Clark Williams - 1.18-1 +-- fix usage of python 2.6 features on RHEL5 (python 2.4) +- +-* Tue Feb 16 2010 Clark Williams - 1.17-1 +-- added logic to filter non-printables from service status output +- so that we have legal XML output +-- added logic to hackbench.py to cleanup properly at the end +- of the test +- +-* Thu Feb 11 2010 Clark Williams - 1.16-1 +-- fix errors in show_remaining_time() introduced because +- time values are floats rather than ints +- +-* Thu Feb 11 2010 Clark Williams - 1.15-1 +-- added logic to use --numa and --smp options of new cyclictest +-- added countdown report for time remaining in a run +- +-* Tue Feb 9 2010 Clark Williams - 1.14-1 +-- David Sommerseth : +- merged XMLReport() changes for hwcert suite +- +-* Tue Dec 22 2009 Clark Williams - 1.13-1 +-- added cyclictest default initializers +-- added sanity checks to statistics reduction code +-- updated release checklist to include origin push +-- updated Makefile clean and help targets +-- davids updates (mainly for v7 integration): +- - Add explicit sys.path directory to the python sitelib+ +- '/rteval' +- - Send program arguments via RtEval() constructor +- - Added more DMI data into the summary.xml report +- - Fixed issue with not including all devices in the +- OnBoardDeviceInfo tag +- +-* Thu Dec 3 2009 David Sommerseth - 1.12-2 +-- fixed Makefile and specfile to include and install the +- rteval/rteval_histogram_raw.py source file for gaining +- raw access to histogram data +-- Removed xmlrpc package during merge against master_ipv4 branch +- +-* Wed Nov 25 2009 Clark Williams - 1.12-1 +-- fix incorrect reporting of measurement thread priorities +- +-* Mon Nov 16 2009 Clark Williams - 1.11-5 +-- ensure that no double-slashes ("//") appear in the symlink +- path for /usr/bin/rteval (problem with rpmdiff) +- +-* Tue Nov 10 2009 Clark Williams - 1.11-4 +-- changed symlink back to install and tracked by %%files +- +-* Mon Nov 9 2009 Clark Williams - 1.11-3 +-- changed symlink generation from %%post to %%posttrans +- +-* Mon Nov 9 2009 Clark Williams - 1.11-2 +-- fixed incorrect dependency for libxslt +- +-* Fri Nov 6 2009 Clark Williams - 1.11-1 +-- added base OS info to XML file and XSL report +-- created new package rteval-loads for the load source code +- +-* Wed Nov 4 2009 Clark Williams - 1.10-1 +-- added config file section for cyclictest and two settable +- parameters, buckets and interval +- +-* Thu Oct 29 2009 Clark Williams - 1.9-1 +-- merged davids updates: +- -H option (raw histogram data) +- cleaned up xsl files +- fixed cpu sorting +- +-* Mon Oct 26 2009 David Sommerseth - 1.8-3 +-- Fixed rpmlint complaints +- +-* Mon Oct 26 2009 David Sommerseth - 1.8-2 +-- Added xmlrpc package, containing the XML-RPC mod_python modules +- +-* Tue Oct 20 2009 Clark Williams - 1.8-1 +-- split kcompile and hackbench into sub-packages +-- reworked Makefile (and specfile) install/uninstall logic +-- fixed sysreport incorrect plugin option +-- catch failure when running on root-squashed NFS +- +-* Tue Oct 13 2009 Clark Williams - 1.7-1 +-- added kthread status to xml file +-- merged davids changes for option processing and additions +- to xml summary +- +-* Tue Oct 13 2009 Clark Williams - 1.6-1 +-- changed stat calculation to loop less +-- added methods to grab service and kthread status +- +-* Mon Oct 12 2009 Clark Williams - 1.5-1 +-- changed cyclictest to use less memory when doing statisics +- calculations +-- updated debug output to use module name prefixes +-- changed option processing to only process config file once +- +-* Fri Oct 9 2009 Clark Williams - 1.4-1 +-- changed cyclictest to use histogram rather than sample array +-- calcuated statistics directly from histogram +-- changed sample interval to 100us +-- added -a (affinity) argument to force cpu affinity for +- measurement threads +- +-* Thu Sep 24 2009 David Sommerseth - 1.3-3 +-- Cleaned up the spec file and made rpmlint happy +- +-* Wed Sep 23 2009 David Sommerseth - 1.3-2 +-- Removed version number from /usr/share/rteval path +- +-* Tue Sep 22 2009 Clark Williams - 1.3-1 +-- changes from davids: +- * changed report code to sort by processor id +- * added report submission retry logic +- * added emailer class +- +-* Fri Sep 18 2009 Clark Williams - 1.2-1 +-- added config file handling for modifying load behavior and +- setting defaults +-- added units in report per IBM request +- +-* Wed Aug 26 2009 Clark Williams - 1.1-2 +-- missed a version change in rteval/rteval.py +- +-* Wed Aug 26 2009 Clark Williams - 1.1-1 +-- modified cyclictest.py to start cyclictest threads with a +- 'distance' of zero, meaning they all have the same measurement +- interval +- +-* Tue Aug 25 2009 Clark Williams - 1.0-1 +-- merged davids XMLRPC fixes +-- fixed --workdir option +-- verion bump to 1.0 +- +-* Thu Aug 13 2009 Clark Williams - 0.9-2 +-- fixed problem with incorrect version in rteval.py +- +-* Tue Aug 4 2009 Clark Williams - 0.9-1 +-- merged dsommers XMLRPC and database changes +-- Specify minimum python-dmidecode version, which got native XML support +-- Added rteval_dmi.xsl +-- Fixed permission issues in /usr/share/rteval-x.xx +- +-* Wed Jul 22 2009 Clark Williams - 0.8-1 +-- added code to capture clocksource info +-- added code to copy dmesg info to report directory +-- added code to display clocksource info in report +-- added --summarize option to display summary of existing report +-- added helpfile target to Makefile +- +-* Thu Mar 26 2009 Clark Williams - 0.7-1 +-- added require for python-schedutils to specfile +-- added default for cyclictest output file +-- added help parameter to option parser data +-- renamed xml output file to summary.xml +-- added routine to create tarfile of result files +- +-* Wed Mar 18 2009 Clark Williams - 0.6-6 +-- added code to handle binary data coming from DMI tables +- +-* Wed Mar 18 2009 Clark Williams - 0.6-5 +-- fixed logic for locating XSL template (williams) +-- fixed another stupid typo in specfile (williams) +- +-* Wed Mar 18 2009 Clark Williams - 0.6-4 +-- fixed specfile to install rteval_text.xsl in /usr/share directory +- +-* Wed Mar 18 2009 Clark Williams - 0.6-3 +-- added Requires for libxslt-python (williams) +-- fixed race condition in xmlout constructor/destructor (williams) +- +-* Wed Mar 18 2009 Clark Williams - 0.6-2 +-- added Requires for libxslt (williams) +-- fixed stupid typo in rteval/rteval.py (williams) +- +-* Wed Mar 18 2009 Clark Williams - 0.6-1 +-- added xml output logic (williams, dsommers) +-- added xlst template for report generator (dsommers) +-- added dmi/smbios output to report (williams) +-- added __del__ method to hackbench to cleanup after run (williams) +-- modified to always keep run data (williams) +- +-* Fri Feb 20 2009 Clark Williams - 0.5-1 +-- fixed tab/space mix problem +-- added report path line to report +- +-* Fri Feb 20 2009 Clark Williams - 0.4-1 +-- reworked report output +-- handle keyboard interrupt better +-- removed duration mismatch between rteval and cyclictest +- +-* Mon Feb 2 2009 Clark Williams - 0.3-1 +-- initial checkin +-- +2.41.0 + diff --git a/SOURCES/rteval-Replace-python-ethtool-with-inline-code.patch b/SOURCES/rteval-Replace-python-ethtool-with-inline-code.patch deleted file mode 100644 index 59b4592..0000000 --- a/SOURCES/rteval-Replace-python-ethtool-with-inline-code.patch +++ /dev/null @@ -1,399 +0,0 @@ -From d0552193364d160252d117c5bf2e298a31550e3c Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Mon, 10 Oct 2022 09:49:47 -0400 -Subject: [PATCH] rteval: Replace python-ethtool with inline code - -This patch adds the file newnet.py to replace the use of python-ethtool -The information it generates will appear in the summary.xml -You can also test the functionality by running -python rteval/sysinfo/newnet.py - -Signed-off-by: John Kacur -- V2 Add SPDX license identifier -Signed-off-by: John Kacur ---- - rteval/sysinfo/__init__.py | 3 +- - rteval/sysinfo/network.py | 117 ------------------- - rteval/sysinfo/newnet.py | 225 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 227 insertions(+), 118 deletions(-) - delete mode 100644 rteval/sysinfo/network.py - create mode 100644 rteval/sysinfo/newnet.py - -diff --git a/rteval/sysinfo/__init__.py b/rteval/sysinfo/__init__.py -index a4359382f006..bb1d00810856 100644 ---- a/rteval/sysinfo/__init__.py -+++ b/rteval/sysinfo/__init__.py -@@ -32,7 +32,7 @@ from rteval.sysinfo.services import SystemServices - from rteval.sysinfo.cputopology import CPUtopology - from rteval.sysinfo.memory import MemoryInfo - from rteval.sysinfo.osinfo import OSInfo --from rteval.sysinfo.network import NetworkInfo -+from rteval.sysinfo.newnet import NetworkInfo - from rteval.sysinfo.cmdline import cmdlineInfo - from rteval.sysinfo import dmi - -@@ -46,6 +46,7 @@ class SystemInfo(KernelInfo, SystemServices, dmi.DMIinfo, CPUtopology, - CPUtopology.__init__(self) - OSInfo.__init__(self, logger=logger) - cmdlineInfo.__init__(self, logger=logger) -+ NetworkInfo.__init__(self, logger=logger) - - # Parse initial DMI decoding errors - dmi.ProcessWarnings() -diff --git a/rteval/sysinfo/network.py b/rteval/sysinfo/network.py -deleted file mode 100644 -index ce9989a1240b..000000000000 ---- a/rteval/sysinfo/network.py -+++ /dev/null -@@ -1,117 +0,0 @@ --# -*- coding: utf-8 -*- --# --# Copyright 2009 - 2013 David Sommerseth --# --# This program is free software; you can redistribute it and/or modify --# it under the terms of the GNU General Public License as published by --# the Free Software Foundation; either version 2 of the License, or --# (at your option) any later version. --# --# This program is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --# GNU General Public License for more details. --# --# You should have received a copy of the GNU General Public License along --# with this program; if not, write to the Free Software Foundation, Inc., --# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --# --# For the avoidance of doubt the "preferred form" of this code is one which --# is in an open unpatent encumbered format. Where cryptographic key signing --# forms part of the process of creating an executable the information --# including keys needed to generate an equivalently functional executable --# are deemed to be part of the source code. --# -- --import ethtool, libxml2 -- --class NetworkInfo(object): -- def __init__(self): -- pass -- -- def net_GetDefaultGW(self): -- # Get the interface name for the IPv4 default gw -- route = open('/proc/net/route') -- defgw4 = None -- if route: -- rl = route.readline() -- while rl != '' : -- rl = route.readline() -- splt = rl.split("\t") -- # Only catch default route -- if len(splt) > 2 and splt[2] != '00000000' and splt[1] == '00000000': -- defgw4 = splt[0] -- break -- route.close() -- return (defgw4, None) # IPv6 gw not yet implemented -- -- def MakeReport(self): -- ncfg_n = libxml2.newNode("NetworkConfig") -- (defgw4, defgw6) = self.net_GetDefaultGW() -- -- # Make an interface tag for each device found -- if hasattr(ethtool, 'get_interfaces_info'): -- # Using the newer python-ethtool API (version >= 0.4) -- for dev in ethtool.get_interfaces_info(ethtool.get_devices()): -- if dev.device == 'lo': -- continue -- -- intf_n = libxml2.newNode('interface') -- intf_n.newProp('device', dev.device) -- intf_n.newProp('hwaddr', dev.mac_address) -- ncfg_n.addChild(intf_n) -- -- # Protcol configurations -- if dev.ipv4_address: -- ipv4_n = libxml2.newNode('IPv4') -- ipv4_n.newProp('ipaddr', dev.ipv4_address) -- ipv4_n.newProp('netmask', str(dev.ipv4_netmask)) -- ipv4_n.newProp('broadcast', dev.ipv4_broadcast) -- ipv4_n.newProp('defaultgw', (defgw4 == dev.device) and '1' or '0') -- intf_n.addChild(ipv4_n) -- -- for ip6 in dev.get_ipv6_addresses(): -- ipv6_n = libxml2.newNode('IPv6') -- ipv6_n.newProp('ipaddr', ip6.address) -- ipv6_n.newProp('netmask', str(ip6.netmask)) -- ipv6_n.newProp('scope', ip6.scope) -- intf_n.addChild(ipv6_n) -- -- else: # Fall back to older python-ethtool API (version < 0.4) -- ifdevs = ethtool.get_active_devices() -- ifdevs.remove('lo') -- ifdevs.sort() -- -- for dev in ifdevs: -- intf_n = libxml2.newNode('interface') -- intf_n.newProp('device', dev.device) -- intf_n.newProp('hwaddr', dev.mac_address) -- ncfg_n.addChild(intf_n) -- -- ipv4_n = libxml2.newNode('IPv4') -- ipv4_n.newProp('ipaddr', ethtool.get_ipaddr(dev)) -- ipv4_n.newProp('netmask', str(ethtool.get_netmask(dev))) -- ipv4_n.newProp('defaultgw', (defgw4 == dev) and '1' or '0') -- intf_n.addChild(ipv4_n) -- -- return ncfg_n -- -- --def unit_test(rootdir): -- import sys -- try: -- net = NetworkInfo() -- doc = libxml2.newDoc('1.0') -- cfg = net.MakeReport() -- doc.setRootElement(cfg) -- doc.saveFormatFileEnc('-', 'UTF-8', 1) -- -- except Exception as e: -- import traceback -- traceback.print_exc(file=sys.stdout) -- print("** EXCEPTION %s", str(e)) -- return 1 -- --if __name__ == '__main__': -- unit_test(None) -- -diff --git a/rteval/sysinfo/newnet.py b/rteval/sysinfo/newnet.py -new file mode 100644 -index 000000000000..63417d9e59f1 ---- /dev/null -+++ b/rteval/sysinfo/newnet.py -@@ -0,0 +1,225 @@ -+''' Module to obtain network information for the rteval report ''' -+# -+# Copyright 2022 John Kacur 0: -+ (iface, dest, gateway, _, _, _, _, _, _, _, _) = line.split() -+ if iface == 'Iface': -+ line = f.readline().strip() -+ continue -+ if dest == '00000000' and gateway != '00000000': -+ addr = int(gateway, base=16) -+ defaultgw = str(ipaddress.IPv4Address(socket.ntohl(addr))) -+ return defaultgw -+ line = f.readline().strip() -+ return defaultgw -+ -+class IPv6Addresses(): -+ ''' Obtains a list of IPv6 addresses from the proc file system ''' -+ -+ def __init__(self): -+ self.data = {} -+ IPv6Addresses.load(self) -+ -+ def __contains__(self, dev): -+ return dev in self.data -+ -+ def __getitem__(self, dev): -+ return self.data.get(dev, None) -+ -+ def __iter__(self): -+ return iter(self.data) -+ -+ def load(self): -+ ''' -+ Called by init to load the self.data dictionary with device keys -+ and a list of ipv6addresses -+ ''' -+ MYP = '/proc/net/if_inet6' -+ with open(MYP, 'r') as f: -+ mystr = f.readline().strip() -+ while len(mystr) > 0: -+ ipv6addr , _, _, _, _, intf = mystr.split() -+ ipv6addr = compress_iv6(ipv6addr) -+ if intf == 'lo': -+ mystr = f.readline().strip() -+ continue -+ if intf not in self.data: -+ self.data[intf] = [ipv6addr] -+ else: -+ self.data[intf].append(ipv6addr) -+ mystr = f.readline().strip() -+ -+class IPv4Addresses(): -+ ''' Obtains a list of IPv4 addresses from the proc file system ''' -+ -+ def __init__(self): -+ self.data = {} -+ IPv4Addresses.load(self) -+ -+ def __contains__(self, dev): -+ return dev in self.data -+ -+ def __getitem__(self, dev): -+ return self.data[dev] -+ -+ def __iter__(self): -+ return iter(self.data) -+ -+ def load(self): -+ ''' -+ Called by init to load the self.data dictionary with -+ device keys, and value consisting of a list of -+ ipv4address, netmask and broadcast address -+ ''' -+ MYP = '/proc/net/route' -+ with open(MYP, 'r') as f: -+ mystr = f.readline().strip() -+ while len(mystr) > 0: -+ intf, dest, _, _, _, _, _, mask, _, _, _ = mystr.split() -+ # Skip over the head of the table an the gateway line -+ if intf == "Iface" or dest == '00000000': -+ mystr = f.readline().strip() -+ continue -+ d1 = int(dest, base=16) -+ m1 = int(mask, base=16) -+ addr = str(ipaddress.IPv4Address(socket.ntohl(d1))) -+ netmask = str(ipaddress.IPv4Address(socket.ntohl(m1))) -+ addr_with_mask = ipaddress.ip_network(addr + '/' + netmask) -+ broadcast = str(addr_with_mask.broadcast_address) -+ if intf not in self.data: -+ self.data[intf] = [(addr, netmask, broadcast)] -+ else: -+ self.data[intf].append((addr, netmask, broadcast)) -+ mystr = f.readline().strip() -+ -+ -+class MacAddresses(): -+ ''' Obtains a list of hardware addresses of network devices ''' -+ -+ def __init__(self): -+ self.mac_address = {} -+ self.path = None -+ MacAddresses.load(self) -+ -+ def load(self): -+ ''' -+ called by init to load self.mac_address as a dictionary of -+ device keys, and mac or hardware addresses as values -+ ''' -+ nics = get_active_devices() -+ for nic in nics: -+ self.path = f'/sys/class/net/{nic}' -+ hwaddr = MacAddresses.set_val(self, 'address') -+ self.mac_address[nic] = hwaddr -+ -+ def set_val(self, val): -+ ''' Return the result of reading self.path/val ''' -+ val_path = f'{self.path}/{val}' -+ if os.path.exists(val_path): -+ with open(val_path, 'r') as f: -+ return f.readline().strip() -+ return None -+ -+ def __contains__(self, dev): -+ return dev in self.mac_address -+ -+ def __getitem__(self, dev): -+ return self.mac_address[dev] -+ -+ def __iter__(self): -+ return iter(self.mac_address) -+ -+class NetworkInfo(): -+ ''' Creates an xml report of the network for rteval ''' -+ -+ def __init__(self, logger): -+ self.defgw4 = get_defaultgw() -+ self.__logger = logger -+ -+ def MakeReport(self): -+ ''' Make an xml report for rteval ''' -+ ncfg_n = libxml2.newNode("NetworkConfig") -+ defgw4 = self.defgw4 -+ -+ mads = MacAddresses() -+ for device in mads: -+ if device == 'lo': -+ continue -+ intf_n = libxml2.newNode('interface') -+ intf_n.newProp('device', device) -+ intf_n.newProp('hwaddr', mads[device]) -+ ncfg_n.addChild(intf_n) -+ -+ ipv4ads = IPv4Addresses() -+ ipv6ads = IPv6Addresses() -+ for dev in ipv4ads: -+ if dev != device: -+ continue -+ for lelem in ipv4ads[dev]: -+ ipv4_n = libxml2.newNode('IPv4') -+ (ipaddr, netmask, broadcast) = lelem -+ ipv4_n.newProp('ipaddr', ipaddr) -+ ipv4_n.newProp('netmask', netmask) -+ ipv4_n.newProp('broadcast', broadcast) -+ ipv4_n.newProp('defaultgw', (defgw4 == ipaddr) and '1' or '0') -+ intf_n.addChild(ipv4_n) -+ if ipv6ads[dev]: -+ for lelem in ipv6ads[dev]: -+ ipv6_n = libxml2.newNode('IPv6') -+ ipaddr = lelem -+ ipv6_n.newProp('ipaddr', ipaddr) -+ intf_n.addChild(ipv6_n) -+ return ncfg_n -+ -+if __name__ == "__main__": -+ -+ try: -+ log = Log() -+ log.SetLogVerbosity(Log.DEBUG|Log.INFO) -+ net = NetworkInfo(logger=log) -+ doc = libxml2.newDoc('1.0') -+ cfg = net.MakeReport() -+ doc.setRootElement(cfg) -+ doc.saveFormatFileEnc('-', 'UTF-8', 1) -+ -+ except Exception as e: -+ import traceback -+ traceback.print_exc(file=sys.stdout) -+ print(f"** EXCEPTION {str(e)}") --- -2.37.3 - diff --git a/SPECS/rteval.spec b/SPECS/rteval.spec index 780df22..3d4f2f1 100644 --- a/SPECS/rteval.spec +++ b/SPECS/rteval.spec @@ -1,5 +1,5 @@ Name: rteval -Version: 3.5 +Version: 3.7 Release: 4%{?dist} Summary: Utility to evaluate system suitability for RT Linux @@ -33,10 +33,13 @@ Requires: libmpc libmpc-devel Obsoletes: rteval-common <= 3.1 #Patches -Patch1: rteval-Replace-python-ethtool-with-inline-code.patch -Patch2: Fix-DMI-WARNING-when-not-running-as-root.patch -Patch3: rteval-Don-t-attempt-to-get-DMIinfo-if-there-are-dmi.patch -Patch4: rteval-Catch-failures-in-python-dmidecode.patch +Patch1: Revert-rteval-Change-the-default-kernel.patch +Patch2: rteval-Remove-upstream-spec-file.patch +Patch3: rteval-Refactor-collapse_cpulist-in-systopology.patch +Patch4: rteval-Minor-improvements-to-CpuList-class.patch +Patch5: rteval-Convert-CpuList-class-to-a-module.patch +Patch6: rteval-Add-relative-cpulists-for-measurements.patch + %description The rteval script is a utility for measuring various aspects of @@ -53,6 +56,9 @@ to the screen. %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 +%patch6 -p1 + %build %{__python3} setup.py build @@ -72,6 +78,7 @@ to the screen. %{python3_sitelib}/rteval/version.py* %{python3_sitelib}/rteval/Log.py* %{python3_sitelib}/rteval/systopology.py* +%{python3_sitelib}/rteval/cpulist_utils.py* %{_mandir}/man8/rteval.8.gz %config(noreplace) %{_sysconfdir}/rteval.conf %{_datadir}/%{name}/rteval_*.xsl @@ -86,6 +93,47 @@ to the screen. %{python3_sitelib}/rteval/__pycache__/* %changelog +* Wed Jan 31 2024 Tomas Glozar - 3.7-4 +- Added patchset for relative cpuset functionality from upstream +Resolves: RHEL-21926 + +* Wed Nov 15 2023 John Kacur - 3.7-3 +- Add an rpminspect file to pass gating which is failing due to + python egg-info directory permissions +Resolves: RHEL-16401 + +* Mon Nov 13 2023 John Kacur - 3.7-2 +- Remove upstream spec files +Resolves: RHEL-9189 + +* Wed Oct 25 2023 John Kacur - 3.7-1 +- Rebase to upstream rteval-3.7 +- Revert the change to use a newer default kernel +Resolves: RHEL-8967 + +* Thu Oct 05 2023 Tomas Glozar - 3.5-9 +- Added patch set that enables rteval to do load calculations and reporting +correctly on systems with isolated CPUs +jiraProject== RHEL-8680 + +* Wed Oct 04 2023 John Kacur - 3.5-8 +- Added patches to use argparse instead of deprecated optparse +jiraProject == RHEL-9029 + +* Fri Aug 11 2023 John Kacur - 3.5-7 +- Added patches to use f-strings where possible, no functional change +jiraProject == RHEL-797 + +* Thu Jun 08 2023 John Kacur - 3.5-6 +- Add tests/tests.yml and tests/scripts/run_tests.sh for gating +Resolves: rhbz#2213609 +jiraProject == RHELPLAN-159326 + +* Wed Jun 07 2023 John Kacur - 3.5-5 +- Added code to check if the /proc/net/if_net6 file exists. +Resolves: rhbz#2210106 +jiraProject == RHELPLAN-158239 + * Wed Feb 08 2023 John Kacur - 3.5-4 - Add check to catch python-dmidecode if it fails Resolves: rhbz#2168373