Import from AlmaLinux stable repository

This commit is contained in:
eabdullin 2025-12-04 12:43:07 +00:00
parent e0338d234d
commit 0784561b3e
8 changed files with 878 additions and 5 deletions

View File

@ -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 <bits/wordsize.h>
#if __WORDSIZE == 32
#include "config32.h"

View File

@ -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()

View File

@ -0,0 +1,39 @@
commit f7476aaaede432f851562d0e8b7f6c4e2f618e66
Author: William Cohen <wcohen@redhat.com>
Date: Wed Apr 2 16:56:04 2025 -0400
libpcp_web, qa: Fix the selection and testing of exact match filtering
Testing showed that globbing matching was being used for the exact
match filtering. Corrected the code to use exact matching when
selected and updated qa/1543 to have the correct output when using
exact match for filtering.
diff --git a/qa/1543.out b/qa/1543.out
index fcaa3f4e4..9ff2f82c7 100644
--- a/qa/1543.out
+++ b/qa/1543.out
@@ -1041,6 +1041,10 @@ sample_long_one{role="testing",agent="sample",hostname="HOSTNAME",cluster="zero"
# HELP sample_long_one 1 as a 32-bit integer
# TYPE sample_long_one gauge
sample_long_one{role="testing",agent="sample",hostname="HOSTNAME",cluster="zero",domainname="DOMAINNAME",machineid="MACHINEID"} 1
+# PCP5 sample.long.ten 29.0.11 32 PM_INDOM_NULL instant none
+# HELP sample_long_ten 10 as a 32-bit integer
+# TYPE sample_long_ten gauge
+sample_long_ten{role="testing",agent="sample",hostname="HOSTNAME",cluster="zero",domainname="DOMAINNAME",machineid="MACHINEID"} 10
== good filter regex ==
# PCP5 sample.long.one 29.0.10 32 PM_INDOM_NULL instant none
# HELP sample_long_one 1 as a 32-bit integer
diff --git a/src/libpcp_web/src/webgroup.c b/src/libpcp_web/src/webgroup.c
index e0b16d1c5..8f5e8a4ea 100644
--- a/src/libpcp_web/src/webgroup.c
+++ b/src/libpcp_web/src/webgroup.c
@@ -2021,7 +2021,7 @@ pmWebGroupScrape(pmWebGroupSettings *settings, sds id, dict *params, void *arg)
if (strcmp(match, "regex") == 0) {
scrape.match = MATCH_REGEX;
} else if (strcmp(match, "exact") == 0)
- scrape.match = MATCH_GLOB;
+ scrape.match = MATCH_EXACT;
else if (strcmp(match, "glob") != 0) {
infofmt(msg, "%s - invalid 'match' parameter value", match);
sts = -EINVAL;

View File

@ -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");

View File

@ -0,0 +1,21 @@
commit 081aa84d3809b64f3e7765abf13a9a90f1072ec8
Author: Nathan Scott <nathans@redhat.com>
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 };

View File

@ -0,0 +1,52 @@
commit 7047f77ccaa84e9af356b9918395a4057af23933
Author: Nathan Scott <nathans@redhat.com>
Date: Mon Apr 14 11:58:41 2025 +1000
selinux: add permissions allowing proc_psi_t access
Access to /proc/pressure recently became selinux policy
protected so we need to allow pcp_pmcd_t to access that
as it contains important system level metrics.
Resolves Red Hat bugzilla #2358326.
diff --git a/src/selinux/pcp.if b/src/selinux/pcp.if
index 3ce68c2039..0297185c61 100644
--- a/src/selinux/pcp.if
+++ b/src/selinux/pcp.if
@@ -535,3 +535,23 @@ ifndef(`userdom_manage_tmp_files',`
')
')
')
+
+########################################
+## <summary>
+## Dummy kernel_read_psi().
+## Allow caller to set up pressure stall information (PSI),
+## but if you don't have actual kernel_read_psi() interface
+## nothing needs to be done.
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </summary>
+#
+ifndef(`kernel_read_psi',`
+ interface(`kernel_read_psi',`
+ gen_require(`
+ type $1;
+ ')
+ ')
+')
diff --git a/src/selinux/pcp.te b/src/selinux/pcp.te
index 9ad27c5c91..a301449500 100644
--- a/src/selinux/pcp.te
+++ b/src/selinux/pcp.te
@@ -123,6 +123,7 @@ kernel_read_vm_sysctls(pcp_pmcd_t)
kernel_read_rpc_sysctls(pcp_pmcd_t)
kernel_search_network_sysctl(pcp_pmcd_t)
kernel_read_net_sysctls(pcp_pmcd_t)
+kernel_read_psi(pcp_pmcd_t)
corecmd_exec_bin(pcp_pmcd_t)
corecmd_exec_shell(pcp_pmcd_t)

View File

@ -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 - -

View File

@ -1,6 +1,6 @@
Name: pcp
Version: 6.3.7
Release: 1%{?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,7 +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
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}
@ -167,7 +174,16 @@ ExcludeArch: %{ix86}
%global disable_mssql 1
%endif
# No mysql support on 32-bit x86 platforms from el9 and later
%ifarch %{ix86}
%if 0%{?rhel} >= 9
%global disable_mysql 1
%else
%global disable_mysql 0
%endif
%else
%global disable_mysql 0
%endif
# support for pmdanutcracker (perl deps missing on rhel)
%if 0%{?rhel} == 0
@ -233,7 +249,7 @@ ExcludeArch: %{ix86}
%global disable_xlsx 1
%endif
%if 0%{?fedora} >= 40 || 0%{?rhel} >= 10
%if 0%{?fedora} >= 40 || 0%{?rhel} >= 9
%global disable_amdgpu 0
%else
%global disable_amdgpu 1
@ -357,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
@ -2492,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
@ -3235,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
@ -3606,6 +3628,21 @@ fi
%files zeroconf -f pcp-zeroconf-files.rpm
%changelog
* Fri Jun 27 2025 Nathan Scott <nathans@redhat.com> - 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 <lchilton@redhat.com> - 6.3.7-4
- Backport metric removal for pmdaopenmetrics
* Tue Apr 22 2025 William Cohen <wcohen@redhat.com> - 6.3.7-3
- Backport the webapi filtering fix to allow the use of exact matching. (RHEL-85792)
* Tue Apr 15 2025 Nathan Scott <nathans@redhat.com> - 6.3.7-2
- Add selinux policy for new proc_psi_t-induced failure
* Mon Mar 31 2025 Nathan Scott <nathans@redhat.com> - 6.3.7-1
- Update to latest stable version of PCP (RHEL-83482)