From bf0dffe467475be5ee506626ad3f14d313e4ff90 Mon Sep 17 00:00:00 2001 From: sjhaveri Date: Tue, 6 Jan 2026 17:48:21 +1100 Subject: [PATCH] Fix hugepagereport failure due to permission error on demote Newer kernels have a write-only 'demote' file in the sysfs hugepages directory. The hugepagereport action uses a wildcard grep command to read all files in these directories. Since the 'demote' file is write-only, grep fails with a "Permission denied" error, causing the action and the functional tests to fail. This patch refactors the action to explicitly target only the relevant metrics: 'nr_hugepages', 'free_hugepages', and 'surplus_hugepages'. Closes-Bug: #2137526 Change-Id: I65cb8e4161bd5a6ca777ccd8aeeb88a61f7a294d Signed-off-by: sjhaveri --- actions/hugepagereport.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/actions/hugepagereport.py b/actions/hugepagereport.py index 260394d0..f3a549bf 100755 --- a/actions/hugepagereport.py +++ b/actions/hugepagereport.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import glob import os import sys @@ -29,7 +30,6 @@ def _add_path(path): _add_path(_hooks) -import subprocess from charmhelpers.core import hookenv SYSFS = '/sys' @@ -41,16 +41,30 @@ def hugepages_report(): hugepage allocation. Takes no params. ''' outmap = {} - try: - devp = "{}/devices/system/node/node*/hugepages/*/*".format(SYSFS) - outmap['hugepagestats'] = subprocess.check_output( - "grep -H . {}".format(devp), - shell=True).decode('UTF-8') - except subprocess.CalledProcessError as e: - hookenv.log(e) - hookenv.action_fail( - "Getting hugepages report failed: {}".format(e) - ) + stats = [] + + # Only target the specific metrics of interest: + # This avoids write-only files and unnecessary noise + target_metrics = ['nr_hugepages', 'free_hugepages', 'surplus_hugepages'] + files = [] + + for m in target_metrics: + path = "{}/devices/system/node/node*/hugepages/*/{}".format(SYSFS, m) + files.extend(glob.glob(path)) + + for f in files: + try: + with open(f, 'r') as fh: + for line in fh: + line = line.strip() + # only include non-empty lines in output + if line: + stats.append("{}:{}".format(f, line)) + except IOError as e: + hookenv.log("Could not read file {}: {}".format(f, e)) + + outmap['hugepagestats'] = "\n".join(stats) + with open(KERNELCMD, 'rb') as cmdline: try: outmap['kernelcmd'] = cmdline.read().strip()