From 14f54a75ff76a6e661c00a154882abac0dd9c773 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 27 Jun 2025 10:35:41 +1000 Subject: [PATCH] Update to pcp-6.3.7-5 with recent important fixes Resolves: RHEL-93186 Resolves: RHEL-54039 --- pcp.spec | 30 +- pcp_openmetrics.patch | 278 ----------- pmapi-header-multilib-fix.patch | 202 ++++++++ pmda-openmetrics-rollup.patch | 465 ++++++++++++++++++ ...exact.patch => pmwebapi-filter-exact.patch | 0 python-pmda-wrapper-list-fix.patch | 17 + selinux-pcp_pmie_t.patch | 21 + systemd-tmpfiles.d-directories.patch | 40 ++ 8 files changed, 768 insertions(+), 285 deletions(-) delete mode 100644 pcp_openmetrics.patch create mode 100644 pmapi-header-multilib-fix.patch create mode 100644 pmda-openmetrics-rollup.patch rename pcp-filter-exact.patch => pmwebapi-filter-exact.patch (100%) create mode 100644 python-pmda-wrapper-list-fix.patch create mode 100644 selinux-pcp_pmie_t.patch create mode 100644 systemd-tmpfiles.d-directories.patch diff --git a/pcp.spec b/pcp.spec index 2e7b094..4f67ea2 100644 --- a/pcp.spec +++ b/pcp.spec @@ -1,6 +1,6 @@ Name: pcp Version: 6.3.7 -Release: 4%{?dist} +Release: 5%{?dist} Summary: System-level performance monitoring and performance management License: GPL-2.0-or-later AND LGPL-2.1-or-later AND CC-BY-3.0 URL: https://pcp.io @@ -10,10 +10,14 @@ Source0: https://github.com/performancecopilot/pcp/releases/pcp-%{version}.src.t # Keep xx-default-archive-version.patch for the life of RHEL9 Patch0: redhat-issues-RHEL-2317-default-archive-version.patch Patch1: redhat-issues-RHEL-58953-perl-drop-Y2038-checks.patch -Patch2: fix-pmdabpf-noarch-man-page-build-failure.patch -Patch3: selinux-proc_psi_t.patch -Patch4: pcp-filter-exact.patch -Patch5: pcp_openmetrics.patch +Patch2: selinux-proc_psi_t.patch +Patch3: selinux-pcp_pmie_t.patch +Patch4: pmwebapi-filter-exact.patch +Patch5: pmda-openmetrics-rollup.patch +Patch6: pmapi-header-multilib-fix.patch +Patch7: python-pmda-wrapper-list-fix.patch +Patch8: systemd-tmpfiles.d-directories.patch +Patch9: fix-pmdabpf-noarch-man-page-build-failure.patch %if 0%{?fedora} >= 40 || 0%{?rhel} >= 10 ExcludeArch: %{ix86} @@ -369,6 +373,8 @@ Requires: pcp-selinux = %{version}-%{release} %global _ieconfdir %{_localstatedir}/lib/pcp/config/pmieconf %global _selinuxdir %{_datadir}/selinux/packages/targeted +%global _with_multilib --enable-multilib=true + %if 0%{?fedora} >= 20 || 0%{?rhel} >= 8 %global _with_doc --with-docdir=%{_docdir}/%{name} %endif @@ -2504,7 +2510,7 @@ sed -i "/PACKAGE_BUILD/s/=[0-9]*/=$_build/" VERSION.pcp %if !%{disable_python2} && 0%{?default_python} != 3 export PYTHON=python%{?default_python} %endif -%configure %{?_with_initd} %{?_with_doc} %{?_with_dstat} %{?_with_ib} %{?_with_gfs2} %{?_with_statsd} %{?_with_perfevent} %{?_with_bcc} %{?_with_bpf} %{?_with_bpftrace} %{?_with_json} %{?_with_mongodb} %{?_with_mysql} %{?_with_snmp} %{?_with_nutcracker} %{?_with_python2} +%configure %{?_with_multilib} %{?_with_initd} %{?_with_doc} %{?_with_dstat} %{?_with_ib} %{?_with_gfs2} %{?_with_statsd} %{?_with_perfevent} %{?_with_bcc} %{?_with_bpf} %{?_with_bpftrace} %{?_with_json} %{?_with_mongodb} %{?_with_mysql} %{?_with_snmp} %{?_with_nutcracker} %{?_with_python2} make %{?_smp_mflags} default_pcp %install @@ -3247,7 +3253,11 @@ for PMDA in dm nfsclient openmetrics ; do fi done # managed via /usr/lib/systemd/system-preset/90-default.preset nowadays: -%if 0%{?rhel} > 0 && 0%{?rhel} < 10 +%if 0%{?fedora} > 40 || 0%{?rhel} > 9 + for s in pmcd pmlogger pmie; do + systemctl --quiet is-enabled $s && systemctl restart $s >/dev/null 2>&1 + done +%else # old-school methods follow %if !%{disable_systemd} systemctl restart pmcd pmlogger pmie >/dev/null 2>&1 systemctl enable pmcd pmlogger pmie >/dev/null 2>&1 @@ -3618,6 +3628,12 @@ fi %files zeroconf -f pcp-zeroconf-files.rpm %changelog +* Fri Jun 27 2025 Nathan Scott - 6.3.7-5 +- Backport some more fixes to the OpenMetrics PMDA (RHEL-54039) +- Fix a multilib regression in PCP header files (RHEL-93186) +- Fix python PMDA wrapper handling of list objects +- Improve tmpfiles.d handling of empty directories + * Wed Apr 30 2025 Lauren Chilton - 6.3.7-4 - Backport metric removal for pmdaopenmetrics diff --git a/pcp_openmetrics.patch b/pcp_openmetrics.patch deleted file mode 100644 index d2b55dd..0000000 --- a/pcp_openmetrics.patch +++ /dev/null @@ -1,278 +0,0 @@ -commit 26e7f6e58be9237c2fd37ae8a98b7941f0ff1345 -Author: lmchilton -Date: Mon Apr 14 10:46:11 2025 -0400 - - added logic to support metric removal in pmdaopenmetrics. - A bug was discovered during development: the PMDA - did not support metric re-addition. So, logic was - added to address that scenario. Additionally, QA test - 1976 was added to the testsuite. - - Addressed changes from PR review. Tested with a script and found/fixed a bug. - -diff --git a/qa/1976 b/qa/1976 -new file mode 100755 -index 000000000..1427ef119 ---- /dev/null -+++ b/qa/1976 -@@ -0,0 +1,90 @@ -+#!/bin/sh -+# PCP QA Test No. 1976 -+# test pmdaopenmetrics metric removal -+# -+# Copyright (c) 2017, 2025 Red Hat. All Rights Reserved. -+# -+# Note: if anything gets added or changed in qa/openmetrics/samples directory, -+# then this test (and all tests in group pmda.openmetrics) will need to be remade. -+ -+seq=`basename $0` -+echo "QA output created by $seq" -+ -+# get standard environment, filters and checks -+. ./common.openmetrics -+ -+_pmdaopenmetrics_check || _notrun "openmetrics pmda not installed" -+ -+status=1 # failure is the default! -+ -+_cleanup() -+{ -+ cd $here -+ _pmdaopenmetrics_cleanup -+ $sudo rm -rf $tmp $tmp.* -+} -+ -+_prepare_pmda openmetrics -+trap "_cleanup; exit \$status" 0 1 2 3 15 -+_stop_auto_restart pmcd -+ -+_pmdaopenmetrics_save_config -+ -+# add all the sample text files as urls. -+# need to be a place the user $PCP_USER (pmcd) can read -+# -+( cd $here/openmetrics/samples; ls -1 *.txt ) | sort | while read file -+do -+ cp $here/openmetrics/samples/$file $tmp.$file -+ urlbase=`basename "$file" .txt | tr .- _` -+ echo 'file://'$tmp.$file >$tmp.tmp -+ $sudo cp $tmp.tmp $PCP_PMDAS_DIR/openmetrics/config.d/$urlbase.url -+done -+ls -l $PCP_PMDAS_DIR/openmetrics/config.d >>$seq_full -+ -+# add all the sample scripts -+cp -a $here/openmetrics/scripts/* $PCP_PMDAS_DIR/openmetrics/config.d -+find $PCP_PMDAS_DIR/openmetrics/config.d -name GNU\* -exec rm -f {} ";" -+ -+_pmdaopenmetrics_install -+ -+if ! _pmdaopenmetrics_wait_for_metric openmetrics.thermostat -+then -+ status=1 -+ exit -+fi -+ -+echo "-- metric removal of new source/metric --" -+$sudo rm $PCP_PMDAS_DIR/openmetrics/config.d/simple_metric.url -+if pminfo openmetrics | grep openmetrics.simple_metric -+then -+ echo "metric removal failed..exiting" -+ status=1 -+ exit -+else -+ echo "metric removal success" -+fi -+echo -+ -+echo "-- source re-addition --" -+path=$here/openmetrics/samples/simple_metric.txt -+echo 'file:///'$path > $PCP_PMDAS_DIR/openmetrics/config.d/simple_metric.url -+pminfo openmetrics.simple_metric -+echo -+ -+echo "-- metric removal of recognized source/metric --" -+$sudo rm $PCP_PMDAS_DIR/openmetrics/config.d/simple_metric.url -+if pminfo openmetrics | grep openmetrics.simple_metric -+then -+ echo "metric removal failed..exiting" -+ status=1 -+ exit -+else -+ echo "metric removal success" -+fi -+ -+_pmdaopenmetrics_remove >/dev/null 2>&1 -+ -+# success, all done -+status=0 -+exit -diff --git a/qa/1976.out b/qa/1976.out -new file mode 100644 -index 000000000..bcfe03f8d ---- /dev/null -+++ b/qa/1976.out -@@ -0,0 +1,11 @@ -+QA output created by 1976 -+ -+=== openmetrics agent installation === -+-- metric removal of new source/metric -- -+metric removal success -+ -+-- source re-addition -- -+openmetrics.simple_metric.metric1 -+ -+-- metric removal of recognized source/metric -- -+metric removal success -diff --git a/qa/group b/qa/group -index 55828846a..83c8f2e8a 100644 ---- a/qa/group -+++ b/qa/group -@@ -2216,6 +2216,7 @@ pmcd.pdu - 1963 pmda.linux local - 1970 pmda.bpf local - 1973 pcp zoneinfo python local -+1976 pmdaopenmetrics python local - 1978 atop local pmlogrewrite - 1984 pmlogconf pmda.redis local - 1985 pmfind local valgrind -diff --git a/src/pmdas/openmetrics/pmdaopenmetrics.python b/src/pmdas/openmetrics/pmdaopenmetrics.python -index c33a56400..a9e65af93 100755 ---- a/src/pmdas/openmetrics/pmdaopenmetrics.python -+++ b/src/pmdas/openmetrics/pmdaopenmetrics.python -@@ -127,15 +127,9 @@ class Metric(object): - (name, pmContext.pmIDStr(self.pmid), self.mtype, self.msem, self.singular, self.mindom, self.labels)) - - self.obj = pmdaMetric(self.pmid, self.mtype, self.mindom, self.msem, self.munits) -+ self.source.pmda.all_metrics[self.mname] = self.obj - -- if helpline: # it could be None! -- unescaped = helpline.replace('\\\\', '\\').replace('\\n', '\n') -- split = unescaped.split('\n') -- help_oneline = split[0] # must have at least one entry -- help_text = '\n'.join(split[1:]) # may have other entries -- else: -- help_oneline = '' -- help_text = '' -+ help_text, help_oneline = self.source.helptext(helpline) - - try: - self.source.pmda.add_metric(self.mname, self.obj, help_oneline, help_text) -@@ -588,6 +582,16 @@ class Source(object): - self.metrics_by_name = {} # name -> Metric - self.metrics_by_num = {} # number (last component of pmid) -> Metric - -+ def helptext(self, helpline): -+ if helpline: # it could be None! -+ unescaped = helpline.replace('\\\\', '\\').replace('\\n', '\n') -+ split = unescaped.split('\n') -+ help_oneline = split[0] # must have at least one entry -+ help_text = '\n'.join(split[1:]) # may have other entries -+ else: -+ help_oneline = '' -+ help_text = '' -+ return help_text, help_oneline - - def old_enough_for_refresh(self): - '''But what is "old"? If it is empty (no metrics), then it -@@ -685,6 +689,23 @@ class Source(object): - self.pmda.debug("included_labels '%s'" % (included_labels)) if self.pmda.dbg else None - self.pmda.debug("optional_labels '%s'" % (optional_labels)) if self.pmda.dbg else None - if sp.name in self.metrics_by_name: -+ if ("openmetrics.%s.%s" % (self.name, sp.name)) not in self.pmda.all_metrics and self.name in self.pmda.re_add_list: -+ # re-add metric to namespace -+ if pcpline: -+ split = pcpline.split(" ") -+ fullname = "openmetrics.%s.%s" % (self.name, split[1]) -+ else: -+ fullname = "openmetrics.%s.%s" % (self.name, sp.name.replace(":", ".")) -+ help_oneline, help_text = self.helptext(helpline) -+ try: -+ obj = self.pmda.removed_metrics[fullname] -+ self.pmda.add_metric(fullname, obj, help_oneline, help_text) -+ self.pmda.debug("re-adding metric: %s to namespace" % fullname) if self.pmda.dbg else None -+ self.pmda.all_metrics[fullname] = obj -+ del self.pmda.removed_metrics[fullname] -+ self.pmda.set_need_refresh() -+ except Exception as e: -+ self.pmda.debug("Can't re-add metric: %s, see error: %s" % (fullname, e)) if self.pmda.dbg else None - m = self.metrics_by_name[sp.name] - assert self.metrics_by_num[m.metricnum] == m - if m.singular: -@@ -693,6 +714,7 @@ class Source(object): - else: - m.store_inst(naming_labels, sp.value) - self.pmda.debug("naming_labels '%s'" % (naming_labels)) if self.pmda.dbg else None -+ # new metric case - else: - # check metric is not excluded by filters - fullname = "openmetrics.%s.%s" % (self.name, sp.name) -@@ -1014,6 +1036,10 @@ class OpenMetricsPMDA(PMDA): - reserved_cluster = self.cluster_table.intern_lookup_value("control") - assert reserved_cluster == 0 - self.source_by_cluster = {} -+ # all metrics added, to be used for removal -+ self.all_metrics = {} -+ # keep track of removed metrics, in case of re-addition -+ self.removed_metrics = {} - - # compiled regex cache - self.regex_cache = {} -@@ -1148,8 +1174,40 @@ class OpenMetricsPMDA(PMDA): - - self.log("Config change detected, traversed %d config entries in %.04fs, rescanning ..." % (len(conf_filelist), traverse_time)) - nickname_regexp = self.lookup_regex(r"^[A-Za-z][A-Za-z0-9_.]*$") -+ self.re_add_list = [] -+ -+ # calculate config entry nicknames -+ nicknames = [] -+ for file in conf_filelist: -+ file_split = os.path.splitext(file) -+ name = file_split[0].replace(self.config_dir + "/", "").replace("/", ".") -+ nicknames.append(name) -+ -+ # check if config change adds a previously removed source -+ for key in self.removed_metrics: -+ split_name = key.split(".") -+ if split_name[1] in nicknames: -+ self.re_add_list.append(split_name[1]) -+ -+ # if source is not in config directory, remove the metric -+ for key, value in self.all_metrics.items(): -+ split_name = key.split(".") -+ if split_name[1] in nicknames: -+ continue -+ try: -+ remove_name = key -+ remove_obj = value -+ self.remove_metric(remove_name, remove_obj) -+ self.removed_metrics[remove_name] = remove_obj -+ self.debug("removed metric name: %s" % remove_name) if self.dbg else None -+ self.set_need_refresh() -+ except Exception as e: -+ self.debug("can't remove metric: %s, see error: %s" % (key, e)) if self.dbg else None -+ -+ for key in self.removed_metrics: -+ if key in self.all_metrics: -+ del self.all_metrics[key] - -- # TODO: maybe nuke sources related to removed files - save_cluster_table = False - if sort_conf_list: - # sorted for indom cluster consistency -@@ -1177,6 +1235,16 @@ class OpenMetricsPMDA(PMDA): - if name in self.source_by_name: - # this source is already known - self.assert_source_invariants(name=name) -+ s = self.source_by_name[name] -+ cluster_for_refresh = [] -+ cluster_for_refresh_names = [] -+ if name in self.re_add_list: -+ for key,value in self.source_by_cluster.items(): -+ if value == s: -+ cluster_for_refresh.append(key) -+ cluster_for_refresh_names.append(name) -+ self.debug("refreshing cluster list: %s" % cluster_for_refresh_names) if self.dbg else None -+ self.refresh_some_clusters_for_fetch(cluster_for_refresh) - else: - try: - path = file diff --git a/pmapi-header-multilib-fix.patch b/pmapi-header-multilib-fix.patch new file mode 100644 index 0000000..b26db21 --- /dev/null +++ b/pmapi-header-multilib-fix.patch @@ -0,0 +1,202 @@ +diff -Naurp pcp-6.3.7.orig/configure pcp-6.3.7/configure +--- pcp-6.3.7.orig/configure 2025-03-31 12:41:26.000000000 +1100 ++++ pcp-6.3.7/configure 2025-06-26 19:38:57.864414825 +1000 +@@ -932,6 +932,7 @@ sed + SED + awk + AWK ++enable_multilib + enable_shared + cxx + ac_ct_CXX +@@ -1055,6 +1056,7 @@ enable_ssp + enable_pie + enable_visibility + enable_shared ++enable_multilib + with_perl_installdirs + with_perl_install_base + with_python_prefix +@@ -1748,7 +1750,8 @@ Optional Features: + --disable-ssp disable gcc stack-protector + --disable-pie disable position-independent-executable + --disable-visibility disable gcc symbol visibility +- --disable-shared disable core shared libary generation ++ --disable-shared disable core shared library generation ++ --enable-multilib enable multilib installations + + Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] +@@ -5696,6 +5699,21 @@ else case e in #( + esac + fi + ++ ++ ++# Check whether --enable-multilib was given. ++if test ${enable_multilib+y} ++then : ++ enableval=$enable_multilib; PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --enable-multilib=$withval" ++ ++printf "%s\n" "#define HAVE_MULTILIB 1" >>confdefs.h ++ ++ enable_multilib=true ++else case e in #( ++ e) enable_multilib=false ;; ++esac ++fi ++ + + + +diff -Naurp pcp-6.3.7.orig/configure.ac pcp-6.3.7/configure.ac +--- pcp-6.3.7.orig/configure.ac 2025-03-31 12:41:26.000000000 +1100 ++++ pcp-6.3.7/configure.ac 2025-06-26 19:38:57.867577540 +1000 +@@ -655,11 +655,20 @@ AC_LANG_POP([C++]) + + dnl Prevent shared libraries from being built for libpcp and other core libraries + AC_ARG_ENABLE([shared], +- [AS_HELP_STRING([--disable-shared], [disable core shared libary generation])], ++ [AS_HELP_STRING([--disable-shared], [disable core shared library generation])], + [PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --disable-shared=$withval"], + [enable_shared=false]) + AC_SUBST(enable_shared) + ++dnl Support installing both devel package variants on either 32/64 bit platform ++AC_ARG_ENABLE([multilib], ++ [AS_HELP_STRING([--enable-multilib], [enable multilib installations])], ++ [PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --enable-multilib=$withval" ++ AC_DEFINE(HAVE_MULTILIB, [1], [multilib defined]) ++ enable_multilib=true], ++ [enable_multilib=false]) ++AC_SUBST(enable_multilib) ++ + dnl check if user wants to use any of their own commands; + dnl ordering is important: some tests use earlier results + +diff -Naurp pcp-6.3.7.orig/src/include/builddefs.in pcp-6.3.7/src/include/builddefs.in +--- pcp-6.3.7.orig/src/include/builddefs.in 2025-03-27 17:01:59.000000000 +1100 ++++ pcp-6.3.7/src/include/builddefs.in 2025-06-26 19:38:57.869743878 +1000 +@@ -259,6 +259,7 @@ QT_VERSION = @qt_version@ + CLANG_MAJOR_VERSION = @CLANG_MAJOR_VERSION@ + + # configuration state affecting the entire build ++ENABLE_MULTILIB = @enable_multilib@ + ENABLE_SHARED = @enable_shared@ + ENABLE_SECURE = @enable_secure@ + ENABLE_PROBES = @enable_probes@ +diff -Naurp pcp-6.3.7.orig/src/include/pcp/config32.h pcp-6.3.7/src/include/pcp/config32.h +--- pcp-6.3.7.orig/src/include/pcp/config32.h 2024-07-30 16:43:55.000000000 +1000 ++++ pcp-6.3.7/src/include/pcp/config32.h 2025-06-26 19:38:57.871096964 +1000 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014,2016 Red Hat. ++ * Copyright (c) 2014,2016,2025 Red Hat. + * Headers for "multilib" support (32-bit and 64-bit packages co-existing) + * + * This library is free software; you can redistribute it and/or modify it +@@ -19,5 +19,7 @@ + #define HAVE_32BIT_LONG 1 + #define HAVE_32BIT_PTR 1 + /* #undef HAVE_64BIT_PTR */ ++#define PM_PAD_RESULT 4 ++#define PM_PAD_TIMESPEC 4 + + #endif /* PCP_CONFIG32_H */ +diff -Naurp pcp-6.3.7.orig/src/include/pcp/config64.h pcp-6.3.7/src/include/pcp/config64.h +--- pcp-6.3.7.orig/src/include/pcp/config64.h 2024-07-30 16:43:55.000000000 +1000 ++++ pcp-6.3.7/src/include/pcp/config64.h 2025-06-26 19:38:57.871276548 +1000 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014,2016 Red Hat. ++ * Copyright (c) 2014,2016,2025 Red Hat. + * Headers for "multilib" support (32-bit and 64-bit packages co-existing) + * + * This library is free software; you can redistribute it and/or modify it +@@ -19,5 +19,7 @@ + /* #undef HAVE_32BIT_LONG */ + /* #undef HAVE_32BIT_PTR */ + #define HAVE_64BIT_PTR 1 ++/* #undef PM_PAD_RESULT */ ++/* #undef PM_PAD_TIMESPEC */ + + #endif /* PCP_CONFIG64_H */ +diff -Naurp pcp-6.3.7.orig/src/include/pcp/config.h.in pcp-6.3.7/src/include/pcp/config.h.in +--- pcp-6.3.7.orig/src/include/pcp/config.h.in 2025-03-14 14:41:06.000000000 +1100 ++++ pcp-6.3.7/src/include/pcp/config.h.in 2025-06-26 19:38:57.871702924 +1000 +@@ -792,6 +792,9 @@ + #undef HAVE__ETEXT + #undef HAVE_ETEXT + ++/* multilib headers */ ++#undef HAVE_MULTILIB ++ + /* sizeof suseconds_t ... only ever going to exist on linux-like systems */ + #undef PM_SIZEOF_SUSECONDS_T + +@@ -801,9 +804,3 @@ + #ifndef PM_SIZEOF_TIME_T + #error Unknown time_t size + #endif +- +-/* __pmResult padding */ +-#undef PM_PAD_RESULT +- +-/* timespec padding */ +-#undef PM_PAD_TIMESPEC +diff -Naurp pcp-6.3.7.orig/src/include/pcp/configsz.h.in pcp-6.3.7/src/include/pcp/configsz.h.in +--- pcp-6.3.7.orig/src/include/pcp/configsz.h.in 2024-07-30 16:43:55.000000000 +1000 ++++ pcp-6.3.7/src/include/pcp/configsz.h.in 2025-06-26 19:38:57.872742426 +1000 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2017 Red Hat. ++ * Copyright (c) 2014-2017,2025 Red Hat. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published +@@ -26,4 +26,10 @@ + /* pointer size */ + #undef HAVE_64BIT_PTR + ++/* __pmResult padding */ ++#undef PM_PAD_RESULT ++ ++/* timespec padding */ ++#undef PM_PAD_TIMESPEC ++ + #endif /* PCP_CONFIGSZ_H */ +diff -Naurp pcp-6.3.7.orig/src/include/pcp/GNUmakefile pcp-6.3.7/src/include/pcp/GNUmakefile +--- pcp-6.3.7.orig/src/include/pcp/GNUmakefile 2024-07-30 16:43:55.000000000 +1000 ++++ pcp-6.3.7/src/include/pcp/GNUmakefile 2025-06-26 19:38:57.873157593 +1000 +@@ -22,11 +22,16 @@ SDSH_HFILES = sds.h sdsalloc.h + EXTERNAL_HFILES = dict.h + HFILES = pmapi.h impl.h pmda.h pmtime.h pmdaroot.h pmafm.h \ + trace.h trace_dev.h mmv_stats.h mmv_dev.h import.h \ +- config32.h config64.h platform32.h platform64.h \ + pmjson.h pmhttp.h pmdbg.h pmwebapi.h deprecated.h \ + ini.h sds.h dict.h archive.h +-INFILES = config.h.in configsz.h.in platform_defs.h.in platformsz.h.in +-CONFFILES = config.h configsz.h platform_defs.h platformsz.h ++INFILES = config.h.in platform_defs.h.in ++CONFFILES = config.h platform_defs.h ++ifeq "$(ENABLE_MULTILIB)" "true" ++HFILES += config32.h config64.h platform32.h platform64.h ++else ++INFILES += configsz.h.in platformsz.h.in ++CONFFILES += configsz.h platformsz.h ++endif + GENERATED_HFILES = $(CONFFILES) + NOSHIP_HFILES = libpcp.h sdsalloc.h + +diff -Naurp pcp-6.3.7.orig/src/include/pcp/platform_defs.h.in pcp-6.3.7/src/include/pcp/platform_defs.h.in +--- pcp-6.3.7.orig/src/include/pcp/platform_defs.h.in 2025-03-31 12:41:26.000000000 +1100 ++++ pcp-6.3.7/src/include/pcp/platform_defs.h.in 2025-06-26 19:38:57.873423552 +1000 +@@ -36,7 +36,7 @@ extern "C" { + #define FMT_PID "@fmt_pid@" + #define FMT_PTHREAD "@fmt_pthread@" + +-#ifdef HAVE_BITS_WORDSIZE_H ++#if defined(HAVE_MULTILIB) && defined(HAVE_BITS_WORDSIZE_H) + #include + #if __WORDSIZE == 32 + #include "config32.h" diff --git a/pmda-openmetrics-rollup.patch b/pmda-openmetrics-rollup.patch new file mode 100644 index 0000000..e63f800 --- /dev/null +++ b/pmda-openmetrics-rollup.patch @@ -0,0 +1,465 @@ +diff -Naurp pcp-6.3.7.orig/qa/1976 pcp-6.3.7/qa/1976 +--- pcp-6.3.7.orig/qa/1976 1970-01-01 10:00:00.000000000 +1000 ++++ pcp-6.3.7/qa/1976 2025-06-26 18:02:39.313416612 +1000 +@@ -0,0 +1,85 @@ ++#!/bin/sh ++# PCP QA Test No. 1976 ++# Test pmdaopenmetrics metric removal ++# ++# Copyright (c) 2017, 2025 Red Hat. All Rights Reserved. ++# ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++# get standard environment, filters and checks ++. ./common.openmetrics ++ ++_pmdaopenmetrics_check || _notrun "openmetrics pmda not installed" ++ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ cd $here ++ _pmdaopenmetrics_cleanup ++ $sudo rm -rf $tmp $tmp.* ++} ++ ++_prepare_pmda openmetrics ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++_stop_auto_restart pmcd ++ ++_pmdaopenmetrics_save_config ++ ++# add all the sample text files as urls. ++# need to be a place the user $PCP_USER (pmcd) can read ++# ++( cd $here/openmetrics/samples; ls -1 *.txt ) | sort | while read file ++do ++ cp $here/openmetrics/samples/$file $tmp.$file ++ urlbase=`basename "$file" .txt | tr .- _` ++ echo 'file://'$tmp.$file >$tmp.tmp ++ $sudo cp $tmp.tmp $PCP_PMDAS_DIR/openmetrics/config.d/$urlbase.url ++done ++ls -l $PCP_PMDAS_DIR/openmetrics/config.d >>$seq_full ++ ++# add all the sample scripts ++cp -a $here/openmetrics/scripts/* $PCP_PMDAS_DIR/openmetrics/config.d ++find $PCP_PMDAS_DIR/openmetrics/config.d -name GNU\* -exec rm -f {} ";" ++ ++_pmdaopenmetrics_install ++ ++if ! _pmdaopenmetrics_wait_for_metric openmetrics.thermostat ++then ++ status=1 ++ exit ++fi ++ ++echo "-- metric removal of new source/metric --" ++$sudo rm $PCP_PMDAS_DIR/openmetrics/config.d/simple_metric.url ++pminfo openmetrics.simple_metric ++echo ++ ++echo "-- source re-addition --" ++# same access controls logic as above, user $PCP_USER needs to be ++# able to read the file at the end of the URL ++# ++cp $here/openmetrics/samples/simple_metric.txt $tmp.simple_metric.txt ++echo 'file:///'$tmp.simple_metric.txt >$PCP_PMDAS_DIR/openmetrics/config.d/simple_metric.url ++pminfo openmetrics.simple_metric ++echo ++ ++echo "-- metric removal of recognized source/metric --" ++$sudo rm $PCP_PMDAS_DIR/openmetrics/config.d/simple_metric.url ++pminfo openmetrics.simple_metric ++echo ++ ++echo "-- source re-addition with epoch timestamp --" ++txtpath=$here/openmetrics/samples/simple_metric.txt ++urlfile=$PCP_PMDAS_DIR/openmetrics/config.d/simple_metric.url ++echo 'file:///'$txtpath > $urlfile ++$sudo touch -t 197001010000 $urlfile ++pminfo openmetrics.simple_metric ++echo ++ ++_pmdaopenmetrics_remove >/dev/null 2>&1 ++ ++# success, all done ++status=0 ++exit +diff -Naurp pcp-6.3.7.orig/qa/1976.out pcp-6.3.7/qa/1976.out +--- pcp-6.3.7.orig/qa/1976.out 1970-01-01 10:00:00.000000000 +1000 ++++ pcp-6.3.7/qa/1976.out 2025-06-26 18:02:01.879861640 +1000 +@@ -0,0 +1,17 @@ ++QA output created by 1976 ++ ++=== openmetrics agent installation === ++-- metric removal of new source/metric -- ++Error: openmetrics.simple_metric: Unknown metric name ++ ++-- source re-addition -- ++openmetrics.simple_metric.metric2 ++openmetrics.simple_metric.metric1 ++ ++-- metric removal of recognized source/metric -- ++Error: openmetrics.simple_metric: Unknown metric name ++ ++-- source re-addition with epoch timestamp -- ++openmetrics.simple_metric.metric2 ++openmetrics.simple_metric.metric1 ++ +diff -Naurp pcp-6.3.7.orig/qa/group pcp-6.3.7/qa/group +--- pcp-6.3.7.orig/qa/group 2025-06-26 17:55:37.790462638 +1000 ++++ pcp-6.3.7/qa/group 2025-06-26 17:58:18.996389423 +1000 +@@ -2205,6 +2205,7 @@ pmcd.pdu + 1963 pmda.linux local + 1970 pmda.bpf local + 1973 pcp zoneinfo python local ++1976 pmdaopenmetrics python local + 1978 atop local pmlogrewrite + 1984 pmlogconf pmda.redis local + 1985 pmfind local valgrind +diff -Naurp pcp-6.3.7.orig/qa/openmetrics/scripts/curl/script.sh pcp-6.3.7/qa/openmetrics/scripts/curl/script.sh +--- pcp-6.3.7.orig/qa/openmetrics/scripts/curl/script.sh 2023-11-16 17:51:39.000000000 +1100 ++++ pcp-6.3.7/qa/openmetrics/scripts/curl/script.sh 2025-06-26 18:02:50.155355973 +1000 +@@ -1,4 +1,4 @@ + #! /bin/sh + + . /etc/pcp.conf +-curl -Gq file://$PCP_PMDAS_DIR/openmetrics/config.d/some_metric.txt ++curl -Gqs file://$PCP_PMDAS_DIR/openmetrics/config.d/some_metric.txt +diff -Naurp pcp-6.3.7.orig/qa/openmetrics/scripts/curl_filtered.sh pcp-6.3.7/qa/openmetrics/scripts/curl_filtered.sh +--- pcp-6.3.7.orig/qa/openmetrics/scripts/curl_filtered.sh 2023-11-16 17:51:39.000000000 +1100 ++++ pcp-6.3.7/qa/openmetrics/scripts/curl_filtered.sh 2025-06-26 18:02:50.155694515 +1000 +@@ -7,6 +7,6 @@ + + . /etc/pcp.conf + +-( curl -Gq file://$PCP_PMDAS_DIR/openmetrics/config.d/some_metric.txt ; \ +-curl -Gq file://$PCP_PMDAS_DIR/openmetrics/config.d/some_other_metric.txt) \ ++( curl -Gqs file://$PCP_PMDAS_DIR/openmetrics/config.d/some_metric.txt ; \ ++curl -Gqs file://$PCP_PMDAS_DIR/openmetrics/config.d/some_other_metric.txt) \ + | sed -e '/metric2/d' +diff -Naurp pcp-6.3.7.orig/qa/openmetrics/scripts/curl_hostname_label.sh pcp-6.3.7/qa/openmetrics/scripts/curl_hostname_label.sh +--- pcp-6.3.7.orig/qa/openmetrics/scripts/curl_hostname_label.sh 2023-11-16 17:51:39.000000000 +1100 ++++ pcp-6.3.7/qa/openmetrics/scripts/curl_hostname_label.sh 2025-06-26 18:02:50.155942641 +1000 +@@ -12,5 +12,5 @@ + + # here for QA purposes we're fetching from a local file + # and just pretending it came from a remote host. +-curl -q -G file://$PCP_PMDAS_DIR/openmetrics/config.d/some_metric.txt 2>/dev/null | \ ++curl -Gqs file://$PCP_PMDAS_DIR/openmetrics/config.d/some_metric.txt 2>/dev/null | \ + sed -e 's/[a-z0-9]*=/hostname="remotehost",&/' +diff -Naurp pcp-6.3.7.orig/qa/openmetrics/scripts/curl_scripted.sh pcp-6.3.7/qa/openmetrics/scripts/curl_scripted.sh +--- pcp-6.3.7.orig/qa/openmetrics/scripts/curl_scripted.sh 2023-11-16 17:51:39.000000000 +1100 ++++ pcp-6.3.7/qa/openmetrics/scripts/curl_scripted.sh 2025-06-26 18:02:50.156229975 +1000 +@@ -1,5 +1,5 @@ + #! /bin/sh + + . /etc/pcp.conf +-curl -Gq file://$PCP_PMDAS_DIR/openmetrics/config.d/some_metric.txt +-curl -Gq file://$PCP_PMDAS_DIR/openmetrics/config.d/some_other_metric.txt ++curl -Gqs file://$PCP_PMDAS_DIR/openmetrics/config.d/some_metric.txt ++curl -Gqs file://$PCP_PMDAS_DIR/openmetrics/config.d/some_other_metric.txt +diff -Naurp pcp-6.3.7.orig/src/pmdas/openmetrics/pmdaopenmetrics.python pcp-6.3.7/src/pmdas/openmetrics/pmdaopenmetrics.python +--- pcp-6.3.7.orig/src/pmdas/openmetrics/pmdaopenmetrics.python 2025-06-26 17:55:37.790973098 +1000 ++++ pcp-6.3.7/src/pmdas/openmetrics/pmdaopenmetrics.python 2025-06-26 18:02:26.571388227 +1000 +@@ -32,7 +32,8 @@ import subprocess + import sys + from ctypes import c_int + from socket import gethostname +-from stat import ST_MODE, S_IXUSR, ST_CTIME ++from urllib.parse import urlparse ++from stat import ST_MODE, S_IXUSR + import requests + + from pcp.pmapi import pmUnits, pmContext +@@ -127,15 +128,9 @@ class Metric(object): + (name, pmContext.pmIDStr(self.pmid), self.mtype, self.msem, self.singular, self.mindom, self.labels)) + + self.obj = pmdaMetric(self.pmid, self.mtype, self.mindom, self.msem, self.munits) ++ self.source.pmda.all_metrics[self.mname] = self.obj + +- if helpline: # it could be None! +- unescaped = helpline.replace('\\\\', '\\').replace('\\n', '\n') +- split = unescaped.split('\n') +- help_oneline = split[0] # must have at least one entry +- help_text = '\n'.join(split[1:]) # may have other entries +- else: +- help_oneline = '' +- help_text = '' ++ help_text, help_oneline = self.source.helptext(helpline) + + try: + self.source.pmda.add_metric(self.mname, self.obj, help_oneline, help_text) +@@ -565,7 +560,7 @@ class Source(object): + self.path = path # pathname to .url or executable file + self.url = None + self.parse_error = False +- self.parse_url_time = 0 # timestamp of config file when it was last parsed ++ self.parse_time = None # last time config file was parsed + self.is_scripted = is_scripted + self.pmda = thispmda # the shared pmda + self.requests = None +@@ -588,6 +583,16 @@ class Source(object): + self.metrics_by_name = {} # name -> Metric + self.metrics_by_num = {} # number (last component of pmid) -> Metric + ++ def helptext(self, helpline): ++ if helpline: # it could be None! ++ unescaped = helpline.replace('\\\\', '\\').replace('\\n', '\n') ++ split = unescaped.split('\n') ++ help_oneline = split[0] # must have at least one entry ++ help_text = '\n'.join(split[1:]) # may have other entries ++ else: ++ help_oneline = '' ++ help_text = '' ++ return help_text, help_oneline + + def old_enough_for_refresh(self): + '''But what is "old"? If it is empty (no metrics), then it +@@ -685,6 +690,23 @@ class Source(object): + self.pmda.debug("included_labels '%s'" % (included_labels)) if self.pmda.dbg else None + self.pmda.debug("optional_labels '%s'" % (optional_labels)) if self.pmda.dbg else None + if sp.name in self.metrics_by_name: ++ if ("openmetrics.%s.%s" % (self.name, sp.name)) not in self.pmda.all_metrics and self.name in self.pmda.re_add_list: ++ # re-add metric to namespace ++ if pcpline: ++ split = pcpline.split(" ") ++ fullname = "openmetrics.%s.%s" % (self.name, split[1]) ++ else: ++ fullname = "openmetrics.%s.%s" % (self.name, sp.name.replace(":", ".")) ++ help_oneline, help_text = self.helptext(helpline) ++ try: ++ obj = self.pmda.removed_metrics[fullname] ++ self.pmda.add_metric(fullname, obj, help_oneline, help_text) ++ self.pmda.debug("re-adding metric: %s to namespace" % fullname) if self.pmda.dbg else None ++ self.pmda.all_metrics[fullname] = obj ++ del self.pmda.removed_metrics[fullname] ++ self.pmda.set_need_refresh() ++ except Exception as e: ++ self.pmda.debug("Can't re-add metric: %s, see error: %s" % (fullname, e)) if self.pmda.dbg else None + m = self.metrics_by_name[sp.name] + assert self.metrics_by_num[m.metricnum] == m + if m.singular: +@@ -693,6 +715,7 @@ class Source(object): + else: + m.store_inst(naming_labels, sp.value) + self.pmda.debug("naming_labels '%s'" % (naming_labels)) if self.pmda.dbg else None ++ # new metric case + else: + # check metric is not excluded by filters + fullname = "openmetrics.%s.%s" % (self.name, sp.name) +@@ -800,9 +823,9 @@ class Source(object): + + return num_metrics + +- def parse_url_config(self, filepath): ++ def parse_config(self, filepath): + ''' +- Parse a URL config file. The first line is always the URL. ++ Parse a configuration file. The first line is always the URL. + Remaining lines are prefixed with a keyword. Supported keywords + include '#' for a comment, 'HEADER:' to add to the header passed + to the headers dict parameter to the get() call. Note the ':' are +@@ -900,12 +923,12 @@ class Source(object): + if not s[ST_MODE] & S_IXUSR: + self.pmda.err("cannot execute script '%s'" % self.path) + return +- elif self.parse_url_time < s[ST_CTIME]: ++ elif self.parse_time is None or self.parse_time < s.st_mtime_ns: + # (re)parse the URL from given file +- self.parse_url_config(self.path) +- self.parse_url_time = s[ST_CTIME] ++ self.parse_config(self.path) ++ self.parse_time = s.st_mtime_ns + except Exception as e: +- self.pmda.err("cannot read %s: %s" % (self.path, e)) ++ self.pmda.err("cannot stat %s: %s" % (self.path, e)) + return + + # fetch the document +@@ -1001,7 +1024,7 @@ class OpenMetricsPMDA(PMDA): + # now everything else may take time + self.pmda_name = pmda_name + self.config_dir = os.path.normpath(config) +- self.config_dir_ctime = None ++ self.config_dir_mtime = 0.0 + self.timeout = timeout + + # a single central Session that all our sources can concurrently reuse +@@ -1014,6 +1037,11 @@ class OpenMetricsPMDA(PMDA): + reserved_cluster = self.cluster_table.intern_lookup_value("control") + assert reserved_cluster == 0 + self.source_by_cluster = {} ++ # all metrics added, to be used for removal ++ self.all_metrics = {} ++ # keep track of removed metrics, in case of re-addition ++ self.removed_metrics = {} ++ self.controls = {0:0} + + # compiled regex cache + self.regex_cache = {} +@@ -1106,26 +1134,53 @@ class OpenMetricsPMDA(PMDA): + assert s == self.source_by_name[s.name] + + +- def traverse(self, directory, ctime): ++ def traverse(self, directory, mtime): + ''' Return list of files below dir, recursively ''' + ret = [] +- m = os.path.getctime(directory) +- if ctime is None or m > ctime: +- ctime = m ++ m = os.path.getmtime(directory) ++ if mtime is None or m > mtime: ++ mtime = m + + for path, subdirs, files in os.walk(directory): + for f in files: + if not f.startswith("."): + fname = os.path.join(path, f) +- m = os.path.getctime(fname) +- if ctime is None or m > ctime: +- ctime = m ++ m = os.path.getmtime(fname) ++ if mtime is None or m > mtime: ++ mtime = m + ret.append(fname) ++ fname = os.path.join(path, f) ++ with open(fname, 'r') as name: ++ f_path = name.readline().strip() ++ if f_path.startswith("file:///"): ++ parsed = urlparse(f_path) ++ m = os.path.getmtime(parsed.path) ++ if mtime is None or m > mtime: ++ mtime = m + for d in subdirs: +- m, _ = self.traverse(os.path.join(path, d), ctime) +- if ctime is None or m > ctime: +- ctime = m +- return ctime, ret ++ m, _ = self.traverse(os.path.join(path, d), mtime) ++ if mtime is None or m > mtime: ++ mtime = m ++ return mtime, ret ++ ++ def initialize_controls(self, cluster): ++ # initialize statistics ++ self.stats_fetch_calls[cluster] = 0 ++ self.stats_fetch_time[cluster] = 0 ++ self.stats_parse_time[cluster] = 0 ++ self.stats_status[cluster] = "unknown" ++ self.stats_status_code[cluster] = 0 ++ ++ self.controls[cluster] = 1 ++ ++ def delete_controls(self, cluster): ++ del self.stats_fetch_calls[cluster] ++ del self.stats_fetch_time[cluster] ++ del self.stats_parse_time[cluster] ++ del self.stats_status[cluster] ++ del self.stats_status_code[cluster] ++ ++ self.controls[cluster] = 0 + + def rescan_confdir(self): + '''Scan the configuration directories for any new .url files +@@ -1138,19 +1193,56 @@ class OpenMetricsPMDA(PMDA): + ''' + + traverse_time = time.time() +- dir_ctime, conf_filelist = self.traverse(self.config_dir, self.config_dir_ctime) ++ dir_mtime, conf_filelist = self.traverse(self.config_dir, self.config_dir_mtime) + traverse_time = time.time() - traverse_time + +- if self.config_dir_ctime is None or self.config_dir_ctime < dir_ctime: +- self.config_dir_ctime = dir_ctime ++ if self.config_dir_mtime < dir_mtime: ++ self.config_dir_mtime = dir_mtime + else: # no new or changed conf files, don't rescan directory + return + + self.log("Config change detected, traversed %d config entries in %.04fs, rescanning ..." % (len(conf_filelist), traverse_time)) + nickname_regexp = self.lookup_regex(r"^[A-Za-z][A-Za-z0-9_.]*$") ++ self.re_add_list = [] ++ ++ # calculate config entry nicknames ++ nicknames = [] ++ for file in conf_filelist: ++ file_split = os.path.splitext(file) ++ name = file_split[0].replace(self.config_dir + "/", "").replace("/", ".") ++ nicknames.append(name) ++ ++ # check if config change adds a previously removed source ++ for key in self.removed_metrics: ++ split_name = key.split(".") ++ if split_name[1] in nicknames: ++ self.re_add_list.append(split_name[1]) ++ ++ # if source is not in config directory, remove the metric ++ for key, value in self.all_metrics.items(): ++ split_name = key.split(".") ++ if split_name[1] in nicknames: ++ continue ++ try: ++ remove_name = key ++ remove_obj = value ++ cluster = self.cluster_table.intern_lookup_value(split_name[1]) ++ if self.controls[cluster] == 1: ++ self.delete_controls(cluster) ++ self.remove_metric(remove_name, remove_obj) ++ self.removed_metrics[remove_name] = remove_obj ++ self.debug("removed metric name: %s" % remove_name) if self.dbg else None ++ self.set_need_refresh() ++ except Exception as e: ++ self.debug("can't remove metric: %s, see error: %s" % (key, e)) if self.dbg else None ++ ++ for key in self.removed_metrics: ++ if key in self.all_metrics: ++ del self.all_metrics[key] + +- # TODO: maybe nuke sources related to removed files + save_cluster_table = False ++ cluster_for_refresh_names = [] ++ cluster_for_refresh = [] + if sort_conf_list: + # sorted for indom cluster consistency + conf_filelist = sorted(conf_filelist) +@@ -1177,6 +1269,13 @@ class OpenMetricsPMDA(PMDA): + if name in self.source_by_name: + # this source is already known + self.assert_source_invariants(name=name) ++ s = self.source_by_name[name] ++ for key, value in self.source_by_cluster.items(): ++ if value == s: ++ cluster_for_refresh.append(key) ++ cluster_for_refresh_names.append(name) ++ if name in self.re_add_list: ++ self.initialize_controls(key) + else: + try: + path = file +@@ -1185,17 +1284,16 @@ class OpenMetricsPMDA(PMDA): + self.source_by_name[source.name] = source + self.source_by_cluster[source.cluster] = source + +- # initialize statistics +- self.stats_fetch_calls[cluster] = 0 +- self.stats_fetch_time[cluster] = 0 +- self.stats_parse_time[cluster] = 0 +- self.stats_status[cluster] = "unknown" +- self.stats_status_code[cluster] = 0 ++ self.initialize_controls(cluster) + + save_cluster_table = True + self.log("Found source %s cluster %d" % (name, cluster)) + except Exception as e: + self.err("Error allocating new cluster/source %s (%s)" % (name, e)) ++ ++ self.debug("refreshing cluster list: %s" % cluster_for_refresh_names) if self.dbg else None ++ self.refresh_some_clusters_for_fetch(cluster_for_refresh) ++ + if save_cluster_table: + self.cluster_table.save() + self.set_notify_change() diff --git a/pcp-filter-exact.patch b/pmwebapi-filter-exact.patch similarity index 100% rename from pcp-filter-exact.patch rename to pmwebapi-filter-exact.patch diff --git a/python-pmda-wrapper-list-fix.patch b/python-pmda-wrapper-list-fix.patch new file mode 100644 index 0000000..b26daa7 --- /dev/null +++ b/python-pmda-wrapper-list-fix.patch @@ -0,0 +1,17 @@ +diff -Naurp pcp-6.3.7.orig/src/python/pmda.c pcp-6.3.7/src/python/pmda.c +--- pcp-6.3.7.orig/src/python/pmda.c 2025-06-26 19:39:47.002695985 +1000 ++++ pcp-6.3.7/src/python/pmda.c 2025-06-26 19:40:16.426718001 +1000 +@@ -417,11 +417,11 @@ refresh_all_clusters(int numclusters, in + PyList_SET_ITEM(list, i, num); + } + +- arglist = Py_BuildValue("(N)", list); ++ arglist = Py_BuildValue("(O)", list); ++ Py_DECREF(list); + if (arglist == NULL) + return -ENOMEM; + result = PyObject_Call(refresh_all_func, arglist, NULL); +- Py_DECREF(list); + Py_DECREF(arglist); + if (result == NULL) + return callback_error("refresh_all_clusters"); diff --git a/selinux-pcp_pmie_t.patch b/selinux-pcp_pmie_t.patch new file mode 100644 index 0000000..383094f --- /dev/null +++ b/selinux-pcp_pmie_t.patch @@ -0,0 +1,21 @@ +commit 081aa84d3809b64f3e7765abf13a9a90f1072ec8 +Author: Nathan Scott +Date: Tue May 6 11:46:14 2025 +1000 + + selinux: additional policy needed for pcp_pmie_t using ps(1) + + Resolves Fedora BZ 2363903. + +diff --git a/src/selinux/pcp.te b/src/selinux/pcp.te +index a30144950..9cbd59bd2 100644 +--- a/src/selinux/pcp.te ++++ b/src/selinux/pcp.te +@@ -247,7 +247,7 @@ optional_policy(` + # + # pcp_pmie local policy + # +-allow pcp_pmie_t self:capability { chown fsetid sys_ptrace }; ++allow pcp_pmie_t self:capability { chown fsetid sys_admin sys_ptrace }; + allow pcp_pmie_t self:cap_userns sys_ptrace; + allow pcp_pmie_t self:netlink_route_socket { create_socket_perms nlmsg_read }; + allow pcp_pmie_t self:unix_dgram_socket { create_socket_perms sendto }; diff --git a/systemd-tmpfiles.d-directories.patch b/systemd-tmpfiles.d-directories.patch new file mode 100644 index 0000000..6accc0a --- /dev/null +++ b/systemd-tmpfiles.d-directories.patch @@ -0,0 +1,40 @@ +diff -Naurp pcp-6.3.7.orig/GNUmakefile pcp-6.3.7/GNUmakefile +--- pcp-6.3.7.orig/GNUmakefile 2025-03-27 17:01:59.000000000 +1100 ++++ pcp-6.3.7/GNUmakefile 2025-06-26 19:23:24.874469186 +1000 +@@ -135,6 +135,8 @@ pcp.lsm src/include/builddefs src/includ + + tmpfiles.init.setup: tmpfiles.init.setup.in + sed < $< > $@ \ ++ -e "s@PCP_VAR_DIR@$(PCP_VAR_DIR)@" \ ++ -e "s@PCP_TMP_DIR@$(PCP_TMP_DIR)@" \ + -e "s@PCP_RUN_DIR@$(PCP_RUN_DIR)@" \ + -e "s@PCP_LOG_DIR@$(PCP_LOG_DIR)@" \ + -e "s/PCP_GROUP/$(PCP_GROUP)/" \ +diff -Naurp pcp-6.3.7.orig/tmpfiles.init.setup.in pcp-6.3.7/tmpfiles.init.setup.in +--- pcp-6.3.7.orig/tmpfiles.init.setup.in 2024-07-30 16:43:55.000000000 +1000 ++++ pcp-6.3.7/tmpfiles.init.setup.in 2025-06-26 19:23:24.875070062 +1000 +@@ -1,10 +1,16 @@ + # tmpfiles.d(5) config for Performance Co-Pilot startup components + # +-# Type Path Mode User Group Age Argument +-D PCP_RUN_DIR 0775 PCP_USER PCP_GROUP - - +-d PCP_LOG_DIR 0775 PCP_USER PCP_GROUP - - +-d PCP_LOG_DIR/pmcd 0755 root root - - +-d PCP_LOG_DIR/pmfind 0775 PCP_USER PCP_GROUP - - +-d PCP_LOG_DIR/pmie 0775 PCP_USER PCP_GROUP - - +-d PCP_LOG_DIR/pmlogger 0775 PCP_USER PCP_GROUP - - +-d PCP_LOG_DIR/pmproxy 0775 PCP_USER PCP_GROUP - - ++# Path Mode User Group Age Argument ++D PCP_RUN_DIR 0775 PCP_USER PCP_GROUP - - ++d PCP_VAR_DIR 0755 root root - - ++d PCP_VAR_DIR/config 0755 root root - - ++d PCP_VAR_DIR/config/pmda 0775 PCP_USER PCP_GROUP - - ++d PCP_VAR_DIR/config/pmie 0775 PCP_USER PCP_GROUP - - ++d PCP_VAR_DIR/config/pmlogger 0775 PCP_USER PCP_GROUP - - ++d PCP_TMP_DIR 0775 PCP_USER PCP_GROUP - - ++d PCP_LOG_DIR 0775 PCP_USER PCP_GROUP - - ++d PCP_LOG_DIR/pmcd 0755 root root - - ++d PCP_LOG_DIR/pmfind 0775 PCP_USER PCP_GROUP - - ++d PCP_LOG_DIR/pmie 0775 PCP_USER PCP_GROUP - - ++d PCP_LOG_DIR/pmlogger 0775 PCP_USER PCP_GROUP - - ++d PCP_LOG_DIR/pmproxy 0775 PCP_USER PCP_GROUP - -