From 88bd2b0b9743a7bd1ce34c46fbe9b92eaeb9e4bb Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: May 18 2021 14:11:53 +0000 Subject: import pcp-5.3.0-4.el8 --- diff --git a/SOURCES/redhat-bugzilla-1615718.patch b/SOURCES/redhat-bugzilla-1615718.patch new file mode 100644 index 0000000..c36bc9a --- /dev/null +++ b/SOURCES/redhat-bugzilla-1615718.patch @@ -0,0 +1,127 @@ +commit 0b62b6e2fef99a143b993bed273ce83e5a5563c3 +Author: Nathan Scott +Date: Fri May 14 11:46:29 2021 +1000 + + pmchart: use libpcp_qmc diagnostic for archives from same host + + Instead of providing a cryptic higher-level error message when + the user attempts to open archives from the same host, use the + message libpcp_qmc has constructed previously - all we need to + do is to pmflush(3) it. + + Resolves Red Hat BZ #1615718 + +diff --git a/src/pmchart/chartdialog.cpp b/src/pmchart/chartdialog.cpp +index 78ca0041b..5c3da5641 100644 +--- a/src/pmchart/chartdialog.cpp ++++ b/src/pmchart/chartdialog.cpp +@@ -388,12 +388,7 @@ void ChartDialog::archiveButtonClicked() + for (QStringList::Iterator it = al.begin(); it != al.end(); ++it) { + QString archive = *it; + if ((sts = archiveGroup->use(PM_CONTEXT_ARCHIVE, archive)) < 0) { +- archive.prepend(tr("Cannot open PCP archive: ")); +- archive.append(tr("\n")); +- archive.append(tr(pmErrStr(sts))); +- QMessageBox::warning(this, pmGetProgname(), archive, +- QMessageBox::Ok|QMessageBox::Default|QMessageBox::Escape, +- Qt::NoButton, Qt::NoButton); ++ pmflush(); + } else { + setupAvailableMetricsTree(true); + archiveGroup->updateBounds(); +@@ -419,12 +414,7 @@ void ChartDialog::hostButtonClicked() + QMessageBox::Ok|QMessageBox::Default|QMessageBox::Escape, + Qt::NoButton, Qt::NoButton); + } else if ((sts = liveGroup->use(PM_CONTEXT_HOST, hostspec, flags)) < 0) { +- hostspec.prepend(tr("Cannot connect to host: ")); +- hostspec.append(tr("\n")); +- hostspec.append(tr(pmErrStr(sts))); +- QMessageBox::warning(this, pmGetProgname(), hostspec, +- QMessageBox::Ok|QMessageBox::Default|QMessageBox::Escape, +- Qt::NoButton, Qt::NoButton); ++ pmflush(); + } else { + console->post(PmChart::DebugUi, + "ChartDialog::newHost: %s (flags=0x%x)", +diff --git a/src/pmchart/openviewdialog.cpp b/src/pmchart/openviewdialog.cpp +index ed5a9f943..0f48b2f88 100644 +--- a/src/pmchart/openviewdialog.cpp ++++ b/src/pmchart/openviewdialog.cpp +@@ -219,7 +219,6 @@ void OpenViewDialog::archiveAdd() + { + QFileDialog *af = new QFileDialog(this); + QStringList al; +- int sts; + + af->setFileMode(QFileDialog::ExistingFiles); + af->setAcceptMode(QFileDialog::AcceptOpen); +@@ -238,13 +237,8 @@ void OpenViewDialog::archiveAdd() + + for (QStringList::Iterator it = al.begin(); it != al.end(); ++it) { + QString archive = *it; +- if ((sts = archiveGroup->use(PM_CONTEXT_ARCHIVE, archive)) < 0) { +- archive.prepend(tr("Cannot open PCP archive: ")); +- archive.append(tr("\n")); +- archive.append(tr(pmErrStr(sts))); +- QMessageBox::warning(this, pmGetProgname(), archive, +- QMessageBox::Ok|QMessageBox::Default|QMessageBox::Escape, +- QMessageBox::NoButton, QMessageBox::NoButton); ++ if (archiveGroup->use(PM_CONTEXT_ARCHIVE, archive) < 0) { ++ pmflush(); + } else { + setupComboBoxes(true); + archiveGroup->updateBounds(); +@@ -262,20 +256,15 @@ void OpenViewDialog::hostAdd() + + if (host->exec() == QDialog::Accepted) { + QString hostspec = host->getHostSpecification(); +- int sts, flags = host->getContextFlags(); ++ int flags = host->getContextFlags(); + + if (hostspec.isNull() || hostspec.length() == 0) { + hostspec.append(tr("Hostname not specified\n")); + QMessageBox::warning(this, pmGetProgname(), hostspec, + QMessageBox::Ok|QMessageBox::Default|QMessageBox::Escape, + Qt::NoButton, Qt::NoButton); +- } else if ((sts = liveGroup->use(PM_CONTEXT_HOST, hostspec, flags)) < 0) { +- hostspec.prepend(tr("Cannot connect to host: ")); +- hostspec.append(tr("\n")); +- hostspec.append(tr(pmErrStr(sts))); +- QMessageBox::warning(this, pmGetProgname(), hostspec, +- QMessageBox::Ok|QMessageBox::Default|QMessageBox::Escape, +- Qt::NoButton, Qt::NoButton); ++ } else if (liveGroup->use(PM_CONTEXT_HOST, hostspec, flags) < 0) { ++ pmflush(); + } else { + console->post(PmChart::DebugUi, + "OpenViewDialog::newHost: %s (flags=0x%x)", +@@ -320,11 +309,7 @@ bool OpenViewDialog::useLiveContext(int index) + int sts; + + if ((sts = liveGroup->use(PM_CONTEXT_HOST, source.source())) < 0) { +- QString msg = QString("Failed to connect to pmcd on \"%1\".\n%2.\n\n") +- .arg(sourceName).arg(pmErrStr(sts)); +- QMessageBox::warning(NULL, pmGetProgname(), msg, +- QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape, +- QMessageBox::NoButton, QMessageBox::NoButton); ++ pmflush(); + result = false; + } + free(sourceName); +@@ -345,14 +330,9 @@ bool OpenViewDialog::useArchiveContext(int index) + QmcSource source = archiveGroup->context(index)->source(); + char *sourceName = source.sourceAscii(); + bool result = true; +- int sts; + +- if ((sts = archiveGroup->use(PM_CONTEXT_ARCHIVE, source.source())) < 0) { +- QString msg = QString("Failed to open archive \"%1\".\n%2.\n\n") +- .arg(sourceName).arg(pmErrStr(sts)); +- QMessageBox::warning(NULL, pmGetProgname(), msg, +- QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape, +- QMessageBox::NoButton, QMessageBox::NoButton); ++ if (archiveGroup->use(PM_CONTEXT_ARCHIVE, source.source()) < 0) { ++ pmflush(); + result = false; + } + free(sourceName); diff --git a/SOURCES/redhat-bugzilla-1615742.patch b/SOURCES/redhat-bugzilla-1615742.patch new file mode 100644 index 0000000..953e559 --- /dev/null +++ b/SOURCES/redhat-bugzilla-1615742.patch @@ -0,0 +1,494 @@ +commit f15e34b06bd25dce5fafa68eeee04f2b5a27e9a0 +Author: Nathan Scott +Date: Fri May 14 11:10:56 2021 +1000 + + pmchart: save changes to users prefered archive location + + Use the users QSettings configuration file to hold any new + preference given for archive locations, and restore this at + pmchart startup time. + + Similarly save and restore locations for exported images. + + While in here, some janitorial work has been done in terms + of dropping paths to configuration files not used in many, + many years now. + + Resolves Red Hat BZ #1615742 + +diff --git a/src/pmchart/chartdialog.cpp b/src/pmchart/chartdialog.cpp +index 3873abe9c..78ca0041b 100644 +--- a/src/pmchart/chartdialog.cpp ++++ b/src/pmchart/chartdialog.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2015, Red Hat. ++ * Copyright (c) 2013-2015,2021 Red Hat. + * Copyright (c) 2007-2008, Aconex. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it +@@ -374,10 +374,17 @@ void ChartDialog::archiveButtonClicked() + af->setAcceptMode(QFileDialog::AcceptOpen); + af->setIconProvider(fileIconProvider); + af->setWindowTitle(tr("Add Archive")); +- af->setDirectory(QDir::toNativeSeparators(QDir::homePath())); ++ af->setDirectory(globalSettings.lastArchivePath); + +- if (af->exec() == QDialog::Accepted) ++ if (af->exec() == QDialog::Accepted) { + al = af->selectedFiles(); ++ QString path = QFileInfo(al.at(0)).dir().absolutePath(); ++ if (globalSettings.lastArchivePath != path) { ++ globalSettings.lastArchivePath = path; ++ globalSettings.lastArchivePathModified = true; ++ } ++ } ++ + for (QStringList::Iterator it = al.begin(); it != al.end(); ++it) { + QString archive = *it; + if ((sts = archiveGroup->use(PM_CONTEXT_ARCHIVE, archive)) < 0) { +diff --git a/src/pmchart/exportdialog.cpp b/src/pmchart/exportdialog.cpp +index fe926ebfa..db38d16db 100644 +--- a/src/pmchart/exportdialog.cpp ++++ b/src/pmchart/exportdialog.cpp +@@ -1,6 +1,6 @@ + /* + * Copyright (c) 2007, Aconex. All Rights Reserved. +- * Copyright (c) 2013, Red Hat, Inc. ++ * Copyright (c) 2013,2021 Red Hat, Inc. + * + * 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 +@@ -48,7 +48,7 @@ void ExportDialog::languageChange() + void ExportDialog::init() + { + QChar sep(pmPathSeparator()); +- QString imgfile = QDir::toNativeSeparators(QDir::homePath()); ++ QString imgfile = globalSettings.lastExportPath; + + my.quality = 0; + my.format = strdup("png"); +@@ -122,10 +122,17 @@ void ExportDialog::displayQualitySlider() + void ExportDialog::filePushButton_clicked() + { + ExportFileDialog file(this); +- +- file.setDirectory(QDir::toNativeSeparators(QDir::homePath())); +- if (file.exec() == QDialog::Accepted) +- fileLineEdit->setText(file.selectedFiles().at(0)); ++ file.setDirectory(globalSettings.lastExportPath); ++ ++ if (file.exec() == QDialog::Accepted) { ++ QString selection = file.selectedFiles().at(0); ++ QString path = QFileInfo(selection).dir().absolutePath(); ++ if (globalSettings.lastExportPath != path) { ++ globalSettings.lastExportPath = path; ++ globalSettings.lastExportPathModified = true; ++ } ++ fileLineEdit->setText(selection); ++ } + } + + void ExportDialog::formatComboBox_currentIndexChanged(QString suffix) +diff --git a/src/pmchart/main.cpp b/src/pmchart/main.cpp +index 08de404d3..ef07fa012 100644 +--- a/src/pmchart/main.cpp ++++ b/src/pmchart/main.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014,2016, Red Hat. ++ * Copyright (c) 2014,2016,2021 Red Hat. + * Copyright (c) 2006, Ken McDonell. All Rights Reserved. + * Copyright (c) 2007-2009, Aconex. All Rights Reserved. + * +@@ -234,6 +234,14 @@ void writeSettings(void) + else + userSettings.remove("savedHosts"); + } ++ if (globalSettings.lastArchivePathModified) { ++ globalSettings.lastArchivePathModified = false; ++ userSettings.setValue("lastArchivePath", globalSettings.lastArchivePath); ++ } ++ if (globalSettings.lastExportPathModified) { ++ globalSettings.lastExportPathModified = false; ++ userSettings.setValue("lastExportPath", globalSettings.lastExportPath); ++ } + + userSettings.endGroup(); + } +@@ -373,6 +381,21 @@ static void readSettings(void) + globalSettings.savedHosts = + userSettings.value("savedHosts").toStringList(); + ++ // ++ // Saved filesystem search paths ++ // ++ globalSettings.lastArchivePathModified = false; ++ QChar sep(pmPathSeparator()); ++ QString pmlogger = QDir::toNativeSeparators(QDir::homePath()); ++ pmlogger.append(sep).append(".pcp").append(sep).append("pmlogger"); ++ globalSettings.lastArchivePath = ++ userSettings.value("lastArchivePath", pmlogger).toString(); ++ globalSettings.lastExportPathModified = false; ++ QString pictures = QDir::toNativeSeparators(QDir::homePath()); ++ pictures.append(sep).append("Pictures"); ++ globalSettings.lastExportPath = ++ userSettings.value("lastExportPath", pictures).toString(); ++ + userSettings.endGroup(); + } + +@@ -475,6 +498,7 @@ main(int argc, char ** argv) + QApplication a(argc, argv); + setupEnvironment(); + readSettings(); ++ atexit(writeSettings); + + opts.flags = PM_OPTFLAG_MULTI | PM_OPTFLAG_MIXED; + opts.short_options = "A:a:Cc:D:f:F:g:h:H:Ln:o:O:p:s:S:T:t:Vv:WzZ:?"; +diff --git a/src/pmchart/main.h b/src/pmchart/main.h +index ec79ec9a4..4be939186 100644 +--- a/src/pmchart/main.h ++++ b/src/pmchart/main.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014, Red Hat. ++ * Copyright (c) 2014,2021 Red Hat. + * Copyright (c) 2007, Aconex. All Rights Reserved. + * Copyright (c) 2006, Ken McDonell. All Rights Reserved. + * +@@ -71,6 +71,12 @@ typedef struct { + // Saved Hosts + QStringList savedHosts; + bool savedHostsModified; ++ ++ // Filesysten Paths ++ QString lastArchivePath; ++ bool lastArchivePathModified; ++ QString lastExportPath; ++ bool lastExportPathModified; + } Settings; + + extern Settings globalSettings; +diff --git a/src/pmchart/openviewdialog.cpp b/src/pmchart/openviewdialog.cpp +index d2eefa028..ed5a9f943 100644 +--- a/src/pmchart/openviewdialog.cpp ++++ b/src/pmchart/openviewdialog.cpp +@@ -1,6 +1,6 @@ + /* +- * Copyright (c) 2013, Red Hat. +- * Copyright (c) 2007-2009, Aconex. All Rights Reserved. ++ * Copyright (c) 2013,2021 Red Hat. ++ * Copyright (c) 2007-2009 Aconex. All Rights Reserved. + * + * 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 +@@ -36,36 +36,16 @@ OpenViewDialog::OpenViewDialog(QWidget *parent) : QDialog(parent) + + QDir dir; + QChar sep(pmPathSeparator()); +- QString sys = my.systemDir = pmGetConfig("PCP_VAR_DIR"); +- my.systemDir.append(sep); +- my.systemDir.append("config"); +- my.systemDir.append(sep); +- my.systemDir.append("kmchart"); +- if (dir.exists(my.systemDir)) +- pathComboBox->addItem(fileIconProvider->icon(QFileIconProvider::Folder), +- my.systemDir); +- my.systemDir = sys; +- my.systemDir.append(sep); +- my.systemDir.append("config"); +- my.systemDir.append(sep); +- my.systemDir.append("pmchart"); ++ my.systemDir = pmGetConfig("PCP_VAR_DIR"); ++ my.systemDir.append(sep).append("config"); ++ my.systemDir.append(sep).append("pmchart"); + if (dir.exists(my.systemDir)) + pathComboBox->addItem(fileIconProvider->icon(QFileIconProvider::Folder), + my.systemDir); + +- QString home = my.userDir = QDir::toNativeSeparators(QDir::homePath()); +- my.userDir.append(sep); +- my.userDir.append(".pcp"); +- my.userDir.append(sep); +- my.userDir.append("kmchart"); +- if (dir.exists(my.userDir)) +- pathComboBox->addItem(fileIconProvider->icon(QFileIconProvider::Folder), +- my.userDir); +- my.userDir = home; +- my.userDir.append(sep); +- my.userDir.append(".pcp"); +- my.userDir.append(sep); +- my.userDir.append("pmchart"); ++ QString home = my.userDir = QDir::homePath(); ++ my.userDir.append(sep).append(".pcp"); ++ my.userDir.append(sep).append("pmchart"); + if (dir.exists(my.userDir)) + pathComboBox->addItem(fileIconProvider->icon(QFileIconProvider::Folder), + my.userDir); +@@ -245,10 +225,17 @@ void OpenViewDialog::archiveAdd() + af->setAcceptMode(QFileDialog::AcceptOpen); + af->setWindowTitle(tr("Add Archive")); + af->setIconProvider(fileIconProvider); +- af->setDirectory(QDir::toNativeSeparators(QDir::homePath())); ++ af->setDirectory(globalSettings.lastArchivePath); + +- if (af->exec() == QDialog::Accepted) ++ if (af->exec() == QDialog::Accepted) { + al = af->selectedFiles(); ++ QString path = QFileInfo(al.at(0)).dir().absolutePath(); ++ if (globalSettings.lastArchivePath != path) { ++ globalSettings.lastArchivePath = path; ++ globalSettings.lastArchivePathModified = true; ++ } ++ } ++ + for (QStringList::Iterator it = al.begin(); it != al.end(); ++it) { + QString archive = *it; + if ((sts = archiveGroup->use(PM_CONTEXT_ARCHIVE, archive)) < 0) { +diff --git a/src/pmchart/recorddialog.cpp b/src/pmchart/recorddialog.cpp +index 35242078a..69a8a89c8 100644 +--- a/src/pmchart/recorddialog.cpp ++++ b/src/pmchart/recorddialog.cpp +@@ -33,26 +33,7 @@ void RecordDialog::languageChange() + + void RecordDialog::init(Tab *tab) + { +- QChar sep(pmPathSeparator()); +- QString pmlogger = QDir::toNativeSeparators(QDir::homePath()); +- QString view, folio, archive; +- +- pmlogger.append(sep); +- pmlogger.append(".pcp"); +- pmlogger.append(sep); +- pmlogger.append("pmlogger"); +- pmlogger.append(sep); +- view = folio = archive = pmlogger; +- +- view.append("[date].view"); +- viewLineEdit->setText(view); +- folio.append("[date].folio"); +- folioLineEdit->setText(folio); +- archive.append("[host]"); +- archive.append(sep); +- archive.append("[date]"); +- archiveLineEdit->setText(archive); +- ++ initText(); + my.tab = tab; + my.units = QmcTime::Seconds; + deltaLineEdit->setText( +@@ -62,6 +43,23 @@ void RecordDialog::init(Tab *tab) + allGadgetsRadioButton->setChecked(true); + } + ++void RecordDialog::initText() ++{ ++ QChar sep(pmPathSeparator()); ++ ++ my.viewText = globalSettings.lastArchivePath; ++ my.viewText.append(sep).append("[date].view"); ++ viewLineEdit->setText(my.viewText); ++ ++ my.folioText = globalSettings.lastArchivePath; ++ my.folioText.append(sep).append("[date].folio"); ++ folioLineEdit->setText(my.folioText); ++ ++ my.archiveText = globalSettings.lastArchivePath; ++ my.archiveText.append(sep).append("[host]").append(sep).append("[date]"); ++ archiveLineEdit->setText(my.archiveText); ++} ++ + void RecordDialog::selectedRadioButton_clicked() + { + selectedRadioButton->setChecked(true); +@@ -83,53 +81,41 @@ void RecordDialog::deltaUnitsComboBox_activated(int value) + + void RecordDialog::viewPushButton_clicked() + { +- RecordFileDialog view(this); ++ initText(); + +- QChar sep(pmPathSeparator()); +- QString pmlogger = QDir::toNativeSeparators(QDir::homePath()); +- pmlogger.append(sep); +- pmlogger.append(".pcp"); +- pmlogger.append(sep); +- pmlogger.append("pmlogger"); +- pmlogger.append(sep); ++ RecordFileDialog view(this); ++ view.setDirectory(my.viewText); + +- view.setDirectory(pmlogger); +- if (view.exec() == QDialog::Accepted) +- viewLineEdit->setText(view.selectedFiles().at(0)); ++ if (view.exec() == QDialog::Accepted) { ++ QString selection = view.selectedFiles().at(0); ++ viewLineEdit->setText(selection); ++ } + } + + void RecordDialog::folioPushButton_clicked() + { +- RecordFileDialog folio(this); ++ initText(); + +- QChar sep(pmPathSeparator()); +- QString pmlogger = QDir::toNativeSeparators(QDir::homePath()); +- pmlogger.append(sep); +- pmlogger.append(".pcp"); +- pmlogger.append(sep); +- pmlogger.append("pmlogger"); +- pmlogger.append(sep); ++ RecordFileDialog folio(this); ++ folio.setDirectory(my.folioText); + +- folio.setDirectory(pmlogger); +- if (folio.exec() == QDialog::Accepted) +- folioLineEdit->setText(folio.selectedFiles().at(0)); ++ if (folio.exec() == QDialog::Accepted) { ++ QString selection = folio.selectedFiles().at(0); ++ folioLineEdit->setText(selection); ++ } + } + + void RecordDialog::archivePushButton_clicked() + { +- RecordFileDialog archive(this); ++ initText(); + +- QChar sep(pmPathSeparator()); +- QString pmlogger = QDir::toNativeSeparators(QDir::homePath()); +- pmlogger.append(sep); +- pmlogger.append(".pcp"); +- pmlogger.append(sep); +- pmlogger.append("pmlogger"); +- pmlogger.append(sep); ++ RecordFileDialog archive(this); ++ archive.setDirectory(my.archiveText); + +- archive.setDirectory(pmlogger); +- if (archive.exec() == QDialog::Accepted) +- archiveLineEdit->setText(archive.selectedFiles().at(0)); ++ if (archive.exec() == QDialog::Accepted) { ++ QString selection = archive.selectedFiles().at(0); ++ archiveLineEdit->setText(selection); ++ } + } + + // substitute "local:" or "localhost" with actual hostname +diff --git a/src/pmchart/recorddialog.h b/src/pmchart/recorddialog.h +index 784530353..67011b934 100644 +--- a/src/pmchart/recorddialog.h ++++ b/src/pmchart/recorddialog.h +@@ -47,11 +47,17 @@ protected slots: + virtual void languageChange(); + + private: ++ void initText(void); ++ + struct { + Tab *tab; + QString delta; + QmcTime::DeltaUnits units; + ++ QString viewText; ++ QString folioText; ++ QString archiveText; ++ + QString view; + QString folio; + QStringList hosts; +diff --git a/src/pmchart/saveviewdialog.cpp b/src/pmchart/saveviewdialog.cpp +index b0363a19f..1a8b094f4 100644 +--- a/src/pmchart/saveviewdialog.cpp ++++ b/src/pmchart/saveviewdialog.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014 Red Hat. ++ * Copyright (c) 2014,2021 Red Hat. + * Copyright (c) 2007-2009, Aconex. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it +@@ -33,22 +33,14 @@ SaveViewDialog::SaveViewDialog(QWidget* parent) : QDialog(parent) + SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SLOT(dirListView_selectionChanged())); + ++ my.hostDynamic = true; ++ my.sizeDynamic = true; ++ + QDir dir; + QChar sep(pmPathSeparator()); + QString home = my.userDir = QDir::toNativeSeparators(QDir::homePath()); +- my.userDir.append(sep); +- my.userDir.append(".pcp"); +- my.userDir.append(sep); +- my.userDir.append("kmchart"); +- if (!dir.exists(my.userDir)) { +- my.userDir = home; +- my.userDir.append(sep); +- my.userDir.append(".pcp"); +- my.userDir.append(sep); +- my.userDir.append("pmchart"); +- } +- my.hostDynamic = true; +- my.sizeDynamic = true; ++ my.userDir.append(sep).append(".pcp"); ++ my.userDir.append(sep).append("pmchart"); + + pathComboBox->addItem(fileIconProvider->icon(QFileIconProvider::Folder), + my.userDir); +diff --git a/src/pmchart/view.cpp b/src/pmchart/view.cpp +index 16633243f..4fc79fd09 100644 +--- a/src/pmchart/view.cpp ++++ b/src/pmchart/view.cpp +@@ -1,6 +1,6 @@ + /* + * Copyright (c) 2006, Ken McDonell. All Rights Reserved. +- * Copyright (c) 2013, Red Hat Inc. ++ * Copyright (c) 2013,2021 Red Hat. + * + * 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 +@@ -281,37 +281,17 @@ bool OpenViewDialog::openView(const char *path) + + strcpy(_fname, path); + if ((f = fopen(_fname, "r")) == NULL) { +- // not found, start the great hunt +- // try user's pmchart dir ... ++ // not found, try users pmchart dir + pmsprintf(_fname, sizeof(_fname), + "%s%c" ".pcp%c" "pmchart%c" "%s", + (const char *)homepath.toLatin1(), sep, sep, sep, path); + if ((f = fopen(_fname, "r")) == NULL) { +- // try system pmchart dir ++ // not found, try system pmchart dir + pmsprintf(_fname, sizeof(_fname), + "%s%c" "config%c" "pmchart%c" "%s", + pmGetConfig("PCP_VAR_DIR"), sep, sep, sep, path); +- if ((f = fopen(_fname, "r")) == NULL) { +- // try user's kmchart dir +- pmsprintf(_fname, sizeof(_fname), +- "%s%c" ".pcp%c" "kmchart%c" "%s", +- (const char *)homepath.toLatin1(), +- sep, sep, sep, path); +- if ((f = fopen(_fname, "r")) == NULL) { +- // try system kmchart dir +- pmsprintf(_fname, sizeof(_fname), +- "%s%c" "config%c" "kmchart%c" "%s", +- pmGetConfig("PCP_VAR_DIR"), +- sep, sep, sep, path); +- if ((f = fopen(_fname, "r")) == NULL) { +- pmsprintf(_fname, sizeof(_fname), +- "%s%c" "config%c" "pmchart%c" "%s", +- pmGetConfig("PCP_VAR_DIR"), +- sep, sep, sep, path); +- goto noview; +- } +- } +- } ++ if ((f = fopen(_fname, "r")) == NULL) ++ goto noview; + } + } + // check for executable and __pmProcessPipe() as needed diff --git a/SOURCES/redhat-bugzilla-1956608.patch b/SOURCES/redhat-bugzilla-1956608.patch new file mode 100644 index 0000000..e330bc3 --- /dev/null +++ b/SOURCES/redhat-bugzilla-1956608.patch @@ -0,0 +1,2590 @@ +diff -Naurp pcp-5.3.0.orig/configure pcp-5.3.0/configure +--- pcp-5.3.0.orig/configure 2021-04-12 19:16:21.000000000 +1000 ++++ pcp-5.3.0/configure 2021-05-14 13:18:32.122079201 +1000 +@@ -775,9 +775,6 @@ ncursesw_CFLAGS + HAVE_NCURSES + ncurses_LIBS + ncurses_CFLAGS +-HAVE_LIBVARLINK +-libvarlink_LIBS +-libvarlink_CFLAGS + HAVE_LIBUV + libuv_LIBS + libuv_CFLAGS +@@ -1076,8 +1073,6 @@ openssl_CFLAGS + openssl_LIBS + libuv_CFLAGS + libuv_LIBS +-libvarlink_CFLAGS +-libvarlink_LIBS + ncurses_CFLAGS + ncurses_LIBS + ncursesw_CFLAGS +@@ -1818,10 +1813,6 @@ Some influential environment variables: + libuv_CFLAGS + C compiler flags for libuv, overriding pkg-config + libuv_LIBS linker flags for libuv, overriding pkg-config +- libvarlink_CFLAGS +- C compiler flags for libvarlink, overriding pkg-config +- libvarlink_LIBS +- linker flags for libvarlink, overriding pkg-config + ncurses_CFLAGS + C compiler flags for ncurses, overriding pkg-config + ncurses_LIBS +@@ -10769,80 +10760,6 @@ fi + + + pkg_failed=no +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libvarlink" >&5 +-$as_echo_n "checking for libvarlink... " >&6; } +- +-if test -n "$libvarlink_CFLAGS"; then +- pkg_cv_libvarlink_CFLAGS="$libvarlink_CFLAGS" +- elif test -n "$PKG_CONFIG"; then +- if test -n "$PKG_CONFIG" && \ +- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libvarlink\""; } >&5 +- ($PKG_CONFIG --exists --print-errors "libvarlink") 2>&5 +- ac_status=$? +- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 +- test $ac_status = 0; }; then +- pkg_cv_libvarlink_CFLAGS=`$PKG_CONFIG --cflags "libvarlink" 2>/dev/null` +- test "x$?" != "x0" && pkg_failed=yes +-else +- pkg_failed=yes +-fi +- else +- pkg_failed=untried +-fi +-if test -n "$libvarlink_LIBS"; then +- pkg_cv_libvarlink_LIBS="$libvarlink_LIBS" +- elif test -n "$PKG_CONFIG"; then +- if test -n "$PKG_CONFIG" && \ +- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libvarlink\""; } >&5 +- ($PKG_CONFIG --exists --print-errors "libvarlink") 2>&5 +- ac_status=$? +- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 +- test $ac_status = 0; }; then +- pkg_cv_libvarlink_LIBS=`$PKG_CONFIG --libs "libvarlink" 2>/dev/null` +- test "x$?" != "x0" && pkg_failed=yes +-else +- pkg_failed=yes +-fi +- else +- pkg_failed=untried +-fi +- +- +- +-if test $pkg_failed = yes; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +-$as_echo "no" >&6; } +- +-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then +- _pkg_short_errors_supported=yes +-else +- _pkg_short_errors_supported=no +-fi +- if test $_pkg_short_errors_supported = yes; then +- libvarlink_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libvarlink" 2>&1` +- else +- libvarlink_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libvarlink" 2>&1` +- fi +- # Put the nasty error message in config.log where it belongs +- echo "$libvarlink_PKG_ERRORS" >&5 +- +- have_libvarlink=false +-elif test $pkg_failed = untried; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +-$as_echo "no" >&6; } +- have_libvarlink=false +-else +- libvarlink_CFLAGS=$pkg_cv_libvarlink_CFLAGS +- libvarlink_LIBS=$pkg_cv_libvarlink_LIBS +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +-$as_echo "yes" >&6; } +- have_libvarlink=true +-fi +-HAVE_LIBVARLINK=$have_libvarlink +- +- +- +-pkg_failed=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ncurses" >&5 + $as_echo_n "checking for ncurses... " >&6; } + +@@ -11652,12 +11569,9 @@ $as_echo "no" >&6; }; fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the podman PMDA should be included" >&5 + $as_echo_n "checking if the podman PMDA should be included... " >&6; } +-pmda_podman=false +-if test "x$do_pmdapodman" = "xyes"; then : +- pmda_podman=true +-fi +-if test "x$do_pmdapodman" = "xcheck"; then : +- $have_libvarlink && pmda_podman=true ++pmda_podman=true ++if test "x$do_pmdapodman" = "xno"; then : ++ pmda_podman=false + fi + PMDA_PODMAN=$pmda_podman + +diff -Naurp pcp-5.3.0.orig/configure.ac pcp-5.3.0/configure.ac +--- pcp-5.3.0.orig/configure.ac 2021-04-12 19:16:21.000000000 +1000 ++++ pcp-5.3.0/configure.ac 2021-05-14 13:18:32.122079201 +1000 +@@ -1793,9 +1793,6 @@ AC_CHECK_LIB(uv, uv_pipe_chmod, + have_uv_pipe_chmod=true, + have_uv_pipe_chmod=false) + +-PKG_CHECK_MODULES([libvarlink], [libvarlink], [have_libvarlink=true], [have_libvarlink=false]) +-AC_SUBST(HAVE_LIBVARLINK, [$have_libvarlink]) +- + PKG_CHECK_MODULES([ncurses], [ncurses], [have_ncurses=true], [have_ncurses=false]) + AC_SUBST(HAVE_NCURSES, [$have_ncurses]) + +@@ -1917,11 +1914,9 @@ AS_IF([test "x$do_pmdastatsd" = "xcheck" + AC_SUBST(PMDA_STATSD, $pmda_statsd) + if $pmda_statsd; then AC_MSG_RESULT(yes); else AC_MSG_RESULT(no); fi + +-dnl Do you have varlink libraries for pmdapodman? + AC_MSG_CHECKING([if the podman PMDA should be included]) +-pmda_podman=false +-AS_IF([test "x$do_pmdapodman" = "xyes"], [pmda_podman=true]) +-AS_IF([test "x$do_pmdapodman" = "xcheck"], [$have_libvarlink && pmda_podman=true]) ++pmda_podman=true ++AS_IF([test "x$do_pmdapodman" = "xno"], [pmda_podman=false]) + AC_SUBST(PMDA_PODMAN, $pmda_podman) + if $pmda_podman; then AC_MSG_RESULT(yes); else AC_MSG_RESULT(no); fi + +diff -Naurp pcp-5.3.0.orig/qa/1357 pcp-5.3.0/qa/1357 +--- pcp-5.3.0.orig/qa/1357 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/qa/1357 2021-05-14 13:18:32.122079201 +1000 +@@ -1,8 +1,8 @@ + #!/bin/sh +-# PCP QA Test No. 1358 ++# PCP QA Test No. 1357 + # Verify podman PMDA memory accesses using valgrind. + # +-# Copyright (c) 2018 Red Hat. ++# Copyright (c) 2018,2021 Red Hat. + # + + seq=`basename $0` +@@ -11,6 +11,7 @@ echo "QA output created by $seq" + . ./common.containers + + [ -f $PCP_PMDAS_DIR/podman/pmdapodman ] || _notrun "podman pmda not installed" ++[ -x $PCP_BIN_DIR/systemctl ] || _notrun "systemctl command not available" + _check_valgrind + _check_containers + _check_podman_binary +@@ -48,18 +49,22 @@ _filter() + } + + # real QA test starts here ++$sudo $PCP_BIN_DIR/systemctl restart podman.service ++ + container=`$podman run -d busybox sleep 10` + echo "== container: $container" >> $here/$seq.full + [ -z "$container" ] && _fail "Failed to create container" +-pod=`$podman pod create` +-echo "== pod: $pod" >> $here/$seq.full +-[ -z "$pod" ] && _fail "Failed to create pod" ++ ++# RHBZ #1958732 ++#pod=`$podman pod create` ++#echo "== pod: $pod" >> $here/$seq.full ++#[ -z "$pod" ] && _fail "Failed to create pod" + + pmda=$PCP_PMDAS_DIR/podman/pmda_podman.so,podman_init + pmns=$PCP_VAR_DIR/pmns/root_podman + args="-L -K clear -K add,33,$pmda -v -n $pmns" + +-_run_valgrind --sudo pminfo $args podman 2>&1 | _filter ++_run_valgrind --sudo pminfo $args podman.container 2>&1 | _filter + + # success, all done + status=0 +diff -Naurp pcp-5.3.0.orig/qa/1357.out pcp-5.3.0/qa/1357.out +--- pcp-5.3.0.orig/qa/1357.out 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/qa/1357.out 2021-05-14 13:18:32.122079201 +1000 +@@ -3,10 +3,9 @@ QA output created by 1357 + === std err === + === filtered valgrind report === + Memcheck, a memory error detector +-Command: pminfo -L -K clear -K add,33,PCP_PMDAS_DIR/podman/pmda_podman.so,podman_init -v -n PCP_VAR_DIR/pmns/root_podman podman ++Command: pminfo -L -K clear -K add,33,PCP_PMDAS_DIR/podman/pmda_podman.so,podman_init -v -n PCP_VAR_DIR/pmns/root_podman podman.container + LEAK SUMMARY: + definitely lost: 0 bytes in 0 blocks + indirectly lost: 0 bytes in 0 blocks + ERROR SUMMARY: 0 errors from 0 contexts ... + == removing container +-== removing pod +diff -Naurp pcp-5.3.0.orig/qa/1358 pcp-5.3.0/qa/1358 +--- pcp-5.3.0.orig/qa/1358 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/qa/1358 2021-05-14 13:18:32.122079201 +1000 +@@ -2,7 +2,7 @@ + # PCP QA Test No. 1358 + # Exercise the podman PMDA. + # +-# Copyright (c) 2018 Red Hat. ++# Copyright (c) 2018,2021 Red Hat. + # + + seq=`basename $0` +@@ -11,6 +11,7 @@ echo "QA output created by $seq" + . ./common.containers + + [ -f $PCP_PMDAS_DIR/podman/pmdapodman ] || _notrun "podman pmda not installed" ++[ -x $PCP_BIN_DIR/systemctl ] || _notrun "systemctl command not available" + _check_containers + _check_podman_binary + _check_podman_images busybox +@@ -42,10 +43,9 @@ pmdapodman_install() + + _filter() + { +- egrep "^podman|$pod1|$pod2|$container1|$container2" | \ ++ #egrep "^podman|$pod1|$pod2|$container1|$container2" | \ ++ egrep "^podman|$container1|$container2" | \ + sed \ +- -e "s/$pod1/POD/g" \ +- -e "s/$pod2/POD/g" \ + -e "s/$container1/CONTAINER/g" \ + -e "s/$container2/CONTAINER/g" \ + -e 's/ value [0-9]\+\.\?[0-9]*[eE][+-][0-9]\+/ value FLOAT/g' \ +@@ -53,6 +53,8 @@ _filter() + -e 's/ value [0-9]\+/ value INTEGER/g' \ + -e 's/ value ".*"/ value STRING/g' \ + -e 's/inst \[[[0-9]\+ or/ inst [NNN or/g' \ ++ #-e "s/$pod1/POD/g" \ ++ #-e "s/$pod2/POD/g" \ + #end + } + +@@ -80,6 +82,8 @@ _prepare_pmda podman + trap "_cleanup; exit \$status" 0 1 2 3 15 + + # real QA test starts here ++$sudo $PCP_BIN_DIR/systemctl restart podman.service ++ + pmdapodman_install + + # create some new podman containers +@@ -89,16 +93,17 @@ container2=`$podman run -d busybox sleep + echo "== container2: $container2" >> $here/$seq.full + [ -z "$container1" -o -z "$container2" ] && _fail "Failed to create containers" + ++# RHBZ #1958732 + # create some new podman pods +-pod1=`$podman pod create` +-echo "== pod1: $pod1" >> $here/$seq.full +-pod2=`$podman pod create` +-echo "== pod2: $pod2" >> $here/$seq.full +-[ -z "$pod1" -o -z "$pod2" ] && _fail "Failed to create PODs" ++#pod1=`$podman pod create` ++#echo "== pod1: $pod1" >> $here/$seq.full ++#pod2=`$podman pod create` ++#echo "== pod2: $pod2" >> $here/$seq.full ++#[ -z "$pod1" -o -z "$pod2" ] && _fail "Failed to create PODs" + + # fetch new state, check for new containers and pods + echo "=== podman metric verification ===" +-pminfo --fetch podman | tee -a $here/$seq.full | _filter ++pminfo --fetch podman.container | tee -a $here/$seq.full | _filter + + echo + echo "=== remove $iam agent ===" +diff -Naurp pcp-5.3.0.orig/qa/1358.out pcp-5.3.0/qa/1358.out +--- pcp-5.3.0.orig/qa/1358.out 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/qa/1358.out 2021-05-14 13:18:32.122079201 +1000 +@@ -58,18 +58,6 @@ podman.container.stats.mem_perc + podman.container.stats.pids + inst [NNN or "CONTAINER"] value INTEGER + inst [NNN or "CONTAINER"] value INTEGER +-podman.pod.name +- inst [NNN or "POD"] value STRING +- inst [NNN or "POD"] value STRING +-podman.pod.cgroup +- inst [NNN or "POD"] value STRING +- inst [NNN or "POD"] value STRING +-podman.pod.status +- inst [NNN or "POD"] value STRING +- inst [NNN or "POD"] value STRING +-podman.pod.containers +- inst [NNN or "POD"] value INTEGER +- inst [NNN or "POD"] value INTEGER + + === remove podman agent === + Culling the Performance Metrics Name Space ... +@@ -78,4 +66,3 @@ Updating the PMCD control file, and noti + [...removing files...] + Check podman metrics have gone away ... OK + == removing containers +-== removing pods +diff -Naurp pcp-5.3.0.orig/qa/917.out.in pcp-5.3.0/qa/917.out.in +--- pcp-5.3.0.orig/qa/917.out.in 2021-03-23 12:34:51.000000000 +1100 ++++ pcp-5.3.0/qa/917.out.in 2021-05-14 13:18:32.122079201 +1000 +@@ -22,6 +22,7 @@ Checking policies. + allow [init_t] [tmp_t] : [file] { open }; + allow [init_t] [system_cronjob_t] : [dbus] { send_msg }; + allow [pcp_pmcd_t] [user_home_t] : [file] { execute execute_no_trans }; ++ allow [pcp_pmcd_t] [user_tmp_t] : [sock_file] { getattr write }; + allow [pcp_pmcd_t] [debugfs_t] : [file] { append getattr ioctl open read write }; + ! allow [pcp_pmcd_t] [pcp_pmie_exec_t] : [file] { execute execute_no_trans open read map }; + allow [pcp_pmcd_t] [pcp_var_lib_t] : [fifo_file] { getattr read open unlink }; +diff -Naurp pcp-5.3.0.orig/qa/admin/other-packages/manifest pcp-5.3.0/qa/admin/other-packages/manifest +--- pcp-5.3.0.orig/qa/admin/other-packages/manifest 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/qa/admin/other-packages/manifest 2021-05-14 13:18:32.123079184 +1000 +@@ -319,18 +319,6 @@ S_pkg? /usr/local/include/uv.h [N/A (bui + slackpkg? uv.h [N/A (build optional)] + pacman? /usr/include/uv.h [extra/libuv (build optional)] + brew? /usr/local/include/uv.h [libuv (build optional)] +-# -- libvarlink +-dpkg? varlink.h [N/A (build optional)] +-rpm? /usr/include/varlink.h [libvarlink-devel (build optional)] +-urpmi? /usr/include/varlink.h [libvarlink-devel (build optional)] +-emerge? varlink.h [N/A (build optional)] +-pkgin? varlink.h [N/A (build optional)] +-pkg_add? varlink.h [N/A (build optional)] +-F_pkg? varlink.h [N/A (build optional)] +-S_pkg? varlink.h [N/A (build optional)] +-slackpkg? varlink.h [N/A (build optional)] +-pacman? varlink.h [N/A (build optional)] +-brew? varlink.h [N/A (build optional)] + # -- liblzma + dpkg? /usr/include/lzma.h [liblzma-dev (build optional)] + rpm? /usr/include/lzma.h [xz-devel (build optional)] +diff -Naurp pcp-5.3.0.orig/qa/admin/other-packages/unavailable pcp-5.3.0/qa/admin/other-packages/unavailable +--- pcp-5.3.0.orig/qa/admin/other-packages/unavailable 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/qa/admin/other-packages/unavailable 2021-05-14 13:18:32.123079184 +1000 +@@ -17,13 +17,13 @@ + #-- ArchLinux + ArchLinux - - python-bcc qtchooser + #-- CentOS +-CentOS 8\.2\. - 389-ds 389-ds-base apache2 avahi-devel avahi-tools avahi-utils chan-devel Coin[0-9]-devel Coin-devel community-mysql cpan(YAML::LibYAML) cppcheck device-mapper-devel docker docker-common docker-io HdrHistogram_c-devel infiniband-diags-devel kubernetes-client kubernetes-node libavahi-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvarlink-devel libvirt-python libvirt-python3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-ldap perl-List-MoreUtils perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pkg-config pkgconfig python36-libs python36-lxml python36-pillow python36-requests python36-setuptools python36-six python3-curses python3-devel python3-libvirt-python python3-openpyxl python3-Pillow python3-pyodbc python3-rtslib-fb qt4-devel qtchooser qt-devel realpath RediSearch sensors SoQt-devel system-python-libs zabbix22-agent zabbix-agent zfs-fuse +-CentOS 8\.[0-1] - 389-ds 389-ds-base apache2 avahi-devel avahi-tools avahi-utils chan-devel Coin[0-9]-devel Coin-devel cpan(YAML::LibYAML) cppcheck device-mapper-devel docker-common docker-io HdrHistogram_c-devel infiniband-diags-devel kubernetes-client kubernetes-node libavahi-devel libvarlink-devel mandoc perl-File-Slurp perl-Getopt-Std perl-JSON perl-ldap perl-List-MoreUtils perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pylint python36-devel python36-lxml python3-libvirt-python python3-openpyxl python3-Pillow python3-pyodbc python3-rtslib-fb python-prometheus_client qt4-devel qtchooser qt-devel sensors SoQt-devel statsd zabbix22-agent zabbix-agent zfs-fuse +-CentOS 7\.8 - apache2 avahi-utils bpftrace chan-devel Coin[0-9]-devel Coin-devel community-mysql coreutils-single docker-io git-core HdrHistogram_c-devel libavahi-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvarlink-devel libvirt-python3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools mysql net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools python36-devel python36-libs python36-setuptools python3-bcc python3-curses python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-pylint python3-pyodbc python3-requests python3-rtslib python3-rtslib-fb python3-six qt4-devel qtchooser realpath RediSearch sensors sqlite-libs system-python-libs zabbix-agent zfs-fuse +-CentOS 7\.7 - bpftrace chan-devel coreutils-single HdrHistogram_c-devel libvarlink-devel libvirt-python3 perl-Getopt-Std perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC python2-openpyxl python3-bcc python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-psycopg2 python3-pyodbc python3-requests python3-rtslib python3-rtslib-fb python3-six python-openpyxl python-prometheus_client python-pylint qtchooser realpath redis-server system-python-libs zfs-fuse +-CentOS 7\.6 - apache2 avahi-utils bpftrace chan-devel Coin-devel community-mysql coreutils-single docker-io git-core HdrHistogram_c-devel libavahi-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvarlink-devel libvirt-python3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools mysql net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools python2-openpyxl python36-devel python36-libs python36-setuptools python3-bcc python3-curses python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-pylint python3-pyodbc python3-requests python3-rtslib python3-rtslib-fb python3-six python-openpyxl python-prometheus_client python-pylint qt4-devel qtchooser realpath RediSearch redis-server sensors sqlite-libs system-python-libs zabbix22-agent zabbix-agent zfs-fuse +-CentOS 7\.5 - bpftrace chan-devel coreutils-single HdrHistogram_c-devel libvarlink-devel libvirt-python3 perl-Getopt-Std perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC python2-openpyxl python3-bcc python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-psycopg2 python3-pyodbc python3-requests python3-rtslib python3-rtslib-fb python3-six python-openpyxl python-prometheus_client python-pylint qtchooser realpath redis-server system-python-libs zfs-fuse +-CentOS 6\.10 - 389-ds apache2 avahi-utils bpftrace ccache chan-devel Coin[0-9]-devel Coin-devel community-mysql coreutils-single cppcheck docker docker-common docker-io git-core HdrHistogram_c-devel java-latest-openjdk-headless kubernetes-client kubernetes-node libavahi-devel libpfm-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libuv-devel libvarlink-devel libvirt-daemon libvirt-daemon-driver-qemu mandoc mariadb mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools net-tools-deprecated perl-autodie perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-Net-SNMP perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-Spreadsheet-WriteExcel perl-Spreadsheet-XLSX perl-Text-CSV_XS perl-YAML-LibYAML pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools podman-docker pylint python2-devel python2-elasticsearch python2-jsonpointer python2-libs python2-libvirt python2-lxml python2-openpyxl python2-psycopg2 python2-pylint python2-requests python2-rtslib python2-rtslib-fb python2-setuptools python2-six python-curses python-elasticsearch python-libvirt-python python-openpyxl python-prometheus_client python-pylint qt4-devel qt5-qtbase-devel qt5-qtsvg-devel qtchooser ragel rdma-core-devel realpath redis RediSearch selinux-policy-devel sensors socat SoQt-devel sqlite-libs statsd systemd-devel system-python-libs uic zabbix22-agent zabbix-agent zfs-fuse ++CentOS 8\.2\. - 389-ds 389-ds-base apache2 avahi-devel avahi-tools avahi-utils chan-devel Coin[0-9]-devel Coin-devel community-mysql cpan(YAML::LibYAML) cppcheck device-mapper-devel docker docker-common docker-io HdrHistogram_c-devel infiniband-diags-devel kubernetes-client kubernetes-node libavahi-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvirt-python libvirt-python3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-ldap perl-List-MoreUtils perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pkg-config pkgconfig python36-libs python36-lxml python36-pillow python36-requests python36-setuptools python36-six python3-curses python3-devel python3-libvirt-python python3-openpyxl python3-Pillow python3-pyodbc python3-rtslib-fb qt4-devel qtchooser qt-devel realpath RediSearch sensors SoQt-devel system-python-libs zabbix22-agent zabbix-agent zfs-fuse ++CentOS 8\.[0-1] - 389-ds 389-ds-base apache2 avahi-devel avahi-tools avahi-utils chan-devel Coin[0-9]-devel Coin-devel cpan(YAML::LibYAML) cppcheck device-mapper-devel docker-common docker-io HdrHistogram_c-devel infiniband-diags-devel kubernetes-client kubernetes-node libavahi-devel mandoc perl-File-Slurp perl-Getopt-Std perl-JSON perl-ldap perl-List-MoreUtils perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pylint python36-devel python36-lxml python3-libvirt-python python3-openpyxl python3-Pillow python3-pyodbc python3-rtslib-fb python-prometheus_client qt4-devel qtchooser qt-devel sensors SoQt-devel statsd zabbix22-agent zabbix-agent zfs-fuse ++CentOS 7\.8 - apache2 avahi-utils bpftrace chan-devel Coin[0-9]-devel Coin-devel community-mysql coreutils-single docker-io git-core HdrHistogram_c-devel libavahi-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvirt-python3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools mysql net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools python36-devel python36-libs python36-setuptools python3-bcc python3-curses python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-pylint python3-pyodbc python3-requests python3-rtslib python3-rtslib-fb python3-six qt4-devel qtchooser realpath RediSearch sensors sqlite-libs system-python-libs zabbix-agent zfs-fuse ++CentOS 7\.7 - bpftrace chan-devel coreutils-single HdrHistogram_c-devel libvirt-python3 perl-Getopt-Std perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC python2-openpyxl python3-bcc python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-psycopg2 python3-pyodbc python3-requests python3-rtslib python3-rtslib-fb python3-six python-openpyxl python-prometheus_client python-pylint qtchooser realpath redis-server system-python-libs zfs-fuse ++CentOS 7\.6 - apache2 avahi-utils bpftrace chan-devel Coin-devel community-mysql coreutils-single docker-io git-core HdrHistogram_c-devel libavahi-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvirt-python3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools mysql net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools python2-openpyxl python36-devel python36-libs python36-setuptools python3-bcc python3-curses python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-pylint python3-pyodbc python3-requests python3-rtslib python3-rtslib-fb python3-six python-openpyxl python-prometheus_client python-pylint qt4-devel qtchooser realpath RediSearch redis-server sensors sqlite-libs system-python-libs zabbix22-agent zabbix-agent zfs-fuse ++CentOS 7\.5 - bpftrace chan-devel coreutils-single HdrHistogram_c-devel libvirt-python3 perl-Getopt-Std perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC python2-openpyxl python3-bcc python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-psycopg2 python3-pyodbc python3-requests python3-rtslib python3-rtslib-fb python3-six python-openpyxl python-prometheus_client python-pylint qtchooser realpath redis-server system-python-libs zfs-fuse ++CentOS 6\.10 - 389-ds apache2 avahi-utils bpftrace ccache chan-devel Coin[0-9]-devel Coin-devel community-mysql coreutils-single cppcheck docker docker-common docker-io git-core HdrHistogram_c-devel java-latest-openjdk-headless kubernetes-client kubernetes-node libavahi-devel libpfm-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libuv-devel libvirt-daemon libvirt-daemon-driver-qemu mandoc mariadb mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools net-tools-deprecated perl-autodie perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-Net-SNMP perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-Spreadsheet-WriteExcel perl-Spreadsheet-XLSX perl-Text-CSV_XS perl-YAML-LibYAML pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools podman-docker pylint python2-devel python2-elasticsearch python2-jsonpointer python2-libs python2-libvirt python2-lxml python2-openpyxl python2-psycopg2 python2-pylint python2-requests python2-rtslib python2-rtslib-fb python2-setuptools python2-six python-curses python-elasticsearch python-libvirt-python python-openpyxl python-prometheus_client python-pylint qt4-devel qt5-qtbase-devel qt5-qtsvg-devel qtchooser ragel rdma-core-devel realpath redis RediSearch selinux-policy-devel sensors socat SoQt-devel sqlite-libs statsd systemd-devel system-python-libs uic zabbix22-agent zabbix-agent zfs-fuse + #-- Debian + # Version Code Name + # 6 squeeze +@@ -60,22 +60,22 @@ OpenBSD 6\.7 - libibumad + OpenBSD 6\.4 - libibumad libvirt-python3 py3-bcc py3-openpyxl py3-prometheus-client py3-jsonpointer qtchooser realpath + OpenBSD 6\.3 - avahi-tools avahi-utils libibumad libvirt-python3 py3-bcc py3-elasticsearch py3-openpyxl py3-prometheus-client py3-jsonpointer qtchooser realpath + #-- openSUSE +-openSUSE 15\.[01] - 389-ds-base avahi-devel avahi-tools chan-devel community-mysql coreutils-single docker-common docker-io HdrHistogram_c-devel kubernetes-client kubernetes-node libvarlink-devel libvirt-python libvirt-python3 mysql perl-DBD-MySQL perl-Getopt-Std perl-LDAP perl-Spreadsheet-WriteExcel perl-XML-TokeParser podman-docker pylint python2-libs python2-libvirt python2-rtslib python36-devel python3-libvirt python3-pillow python3-rtslib python-libs python-pylint python-rtslib python-setuptools qt5-qtsvg-devel qtchooser selinux-policy selinux-policy-devel selinux-policy-targeted statsd zabbix22-agent zabbix-agent zfs-fuse ++openSUSE 15\.[01] - 389-ds-base avahi-devel avahi-tools chan-devel community-mysql coreutils-single docker-common docker-io HdrHistogram_c-devel kubernetes-client kubernetes-node libvirt-python libvirt-python3 mysql perl-DBD-MySQL perl-Getopt-Std perl-LDAP perl-Spreadsheet-WriteExcel perl-XML-TokeParser podman-docker pylint python2-libs python2-libvirt python2-rtslib python36-devel python3-libvirt python3-pillow python3-rtslib python-libs python-pylint python-rtslib python-setuptools qt5-qtsvg-devel qtchooser selinux-policy selinux-policy-devel selinux-policy-targeted statsd zabbix22-agent zabbix-agent zfs-fuse + openSUSE 15.0 - coreutils-single perl-Getopt-Std podman-docker python3-pyodbc +-openSUSE 42\.2 - Coin[0-9]-devel Coin-devel coreutils-single docker-io libvarlink-devel libvirt-python3 perl-Getopt-Std podman-docker pylint python2-pylint python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-pillow python3-rtslib python3-rtslib-fb python-pylint qtchooser selinux-policy selinux-policy-devel selinux-policy-targeted SoQt-devel zabbix22-agent zabbix-agent +-openSUSE 42\.3 - coreutils-single docker-io libvarlink-devel libvirt-python3 perl-Getopt-Std podman-docker pylint python2-pylint python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-pillow python3-rtslib python3-rtslib-fb qtchooser zabbix22-agent zabbix-agent ++openSUSE 42\.2 - Coin[0-9]-devel Coin-devel coreutils-single docker-io libvirt-python3 perl-Getopt-Std podman-docker pylint python2-pylint python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-pillow python3-rtslib python3-rtslib-fb python-pylint qtchooser selinux-policy selinux-policy-devel selinux-policy-targeted SoQt-devel zabbix22-agent zabbix-agent ++openSUSE 42\.3 - coreutils-single docker-io libvirt-python3 perl-Getopt-Std podman-docker pylint python2-pylint python3-elasticsearch python3-jsonpointer python3-libvirt python3-libvirt-python python3-pillow python3-rtslib python3-rtslib-fb qtchooser zabbix22-agent zabbix-agent + #-- Slackware + Slackware 14\.2 - cppcheck pylint python-psycopg2 socat valgrind mandoc + #-- SuSE SLES +-SUSE 12-SP0 - 389-ds 389-ds-base Coin[0-9]-devel Coin-devel coreutils-single cppcheck gfs2-utils kubernetes-client kubernetes-node libqt5-qtsvg-devel libuv-devel libvarlink-devel libvirt-python3 memcached perl-Getopt-Std python36-libs python36-six python3-bcc python3-curses python3-elasticsearch python3-jsonpointer python3-libs python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-psycopg2 python3-requests python3-rtslib python3-rtslib-fb python3-six qt5-qtbase-devel qt5-qtsvg-devel qtchooser SoQt-devel system-python-libs yajl zabbix22-agent zabbix-agent +-SUSE 12-SP4 - 389-ds 389-ds-base chan-devel Coin[0-9]-devel Coin-devel coreutils-single cppcheck gfs2-utils HdrHistogram_c-devel kubernetes-client kubernetes-node libuv-devel libvarlink-devel libvirt-python3 perl-Getopt-Std python36-libs python36-six python3-bcc python3-elasticsearch python3-jsonpointer python3-libs python3-libvirt python3-libvirt-python python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-psycopg2 python3-rtslib python3-rtslib-fb qt5-qtbase-devel qt5-qtsvg-devel qtchooser selinux-policy-targeted SoQt-devel statsd system-python-libs yajl zabbix22-agent zabbix-agent zfs-fuse ++SUSE 12-SP0 - 389-ds 389-ds-base Coin[0-9]-devel Coin-devel coreutils-single cppcheck gfs2-utils kubernetes-client kubernetes-node libqt5-qtsvg-devel libuv-devel libvirt-python3 memcached perl-Getopt-Std python36-libs python36-six python3-bcc python3-curses python3-elasticsearch python3-jsonpointer python3-libs python3-libvirt python3-libvirt-python python3-lxml python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-psycopg2 python3-requests python3-rtslib python3-rtslib-fb python3-six qt5-qtbase-devel qt5-qtsvg-devel qtchooser SoQt-devel system-python-libs yajl zabbix22-agent zabbix-agent ++SUSE 12-SP4 - 389-ds 389-ds-base chan-devel Coin[0-9]-devel Coin-devel coreutils-single cppcheck gfs2-utils HdrHistogram_c-devel kubernetes-client kubernetes-node libuv-devel libvirt-python3 perl-Getopt-Std python36-libs python36-six python3-bcc python3-elasticsearch python3-jsonpointer python3-libs python3-libvirt python3-libvirt-python python3-openpyxl python3-pillow python3-Pillow python3-prometheus_client python3-psycopg2 python3-rtslib python3-rtslib-fb qt5-qtbase-devel qt5-qtsvg-devel qtchooser selinux-policy-targeted SoQt-devel statsd system-python-libs yajl zabbix22-agent zabbix-agent zfs-fuse + #-- RedHat +-RHEL 8\.2 - 389-ds 389-ds-base apache2 avahi-devel avahi-tools avahi-utils chan-devel Coin[0-9]-devel Coin-devel community-mysql cpan(YAML::LibYAML) cppcheck device-mapper-devel docker docker-common docker-io HdrHistogram_c-devel infiniband-diags-devel kubernetes-client kubernetes-node libavahi-devel libibmad-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvarlink-devel libvirt-python libvirt-python3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-ldap perl-List-MoreUtils perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pkg-config pkgconfig python36-libs python36-lxml python36-pillow python36-requests python36-setuptools python36-six python3-curses python3-devel python3-libvirt-python python3-openpyxl python3-Pillow python3-pyodbc python3-rtslib-fb qt4-devel qtchooser qt-devel realpath RediSearch sensors SoQt-devel system-python-libs zabbix22-agent zabbix-agent zfs-fuse +-RHEL 8\.[0-1] - 389-ds 389-ds-base apache2 avahi-devel avahi-tools avahi-utils chan-devel Coin[0-9]-devel Coin-devel cpan(YAML::LibYAML) cppcheck device-mapper-devel docker-common docker-io HdrHistogram_c-devel infiniband-diags-devel kubernetes-client kubernetes-node libavahi-devel libibmad-devel libvarlink-devel mandoc perl-File-Slurp perl-Getopt-Std perl-JSON perl-ldap perl-List-MoreUtils perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pylint python36-devel python36-lxml python3-libvirt-python python3-openpyxl python3-Pillow python3-pyodbc python3-rtslib-fb python-prometheus_client qt4-devel qtchooser qt-devel sensors SoQt-devel statsd zabbix22-agent zabbix-agent zfs-fuse python2-pylint +-RHEL 7\.9 - apache2 avahi-utils bpftrace chan-devel Coin[0-9]-devel Coin-devel community-mysql docker-io git-core HdrHistogram_c-devel libavahi-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvarlink-devel mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools mysql net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools qt4-devel qtchooser realpath RediSearch sensors sqlite-libs system-python-libs zabbix-agent zfs-fuse zabbix22-agent python2-openpyxl python2-elasticsearch python-pylint python-prometheus_client python-openpyxl avahi-devel avahi-tools device-mapper-devel infiniband-diags-devel python2-jsonpointer python2-setuptools python2-libvirt python-libvirt-python python2-lxml python2-psycopg2 setools python-curses python2-libs python2-devel podman-docker coreutils-single python2-rtslib-fb python2-rtslib +-RHEL 7\.8 - apache2 avahi-utils bpftrace chan-devel Coin[0-9]-devel Coin-devel community-mysql docker-io git-core HdrHistogram_c-devel kubernetes-client libavahi-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvarlink-devel mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools mysql net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools qt4-devel qtchooser realpath RediSearch sensors sqlite-libs system-python-libs zabbix-agent zfs-fuse +-RHEL 7\.[5-7] - chan-devel Coin[0-9]-devel Coin-devel cppcheck device-mapper-devel HdrHistogram_c-devel kubernetes-client libvarlink-devel openssl-devel perl-Getopt-Std perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pylint python2-elasticsearch python2-openpyxl python2-prometheus_client python2-pylint python-elasticsearch python-openpyxl python-prometheus_client python-pylint qtchooser ruby SoQt-devel statsd system-python-libs zabbix22-agent zabbix-agent zfs-fuse +-RHEL 6\.10 - apache2 avahi-utils bpftrace chan-devel Coin[0-9]-devel Coin-devel community-mysql coreutils-single device-mapper-devel docker-common docker-io git-core HdrHistogram_c-devel infiniband-diags-devel java-latest-openjdk-headless kubernetes-client kubernetes-node libavahi-devel libicu-devel libpfm-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvarlink-devel libvirt-daemon libvirt-daemon-driver-qemu mandoc mariadb mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools net-tools-deprecated perl-autodie perl-base perl-DBD-mysql perl-Getopt-Std perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkg-configmandoc pkgconf-pkg-config platform-python-devel platform-python-setuptools podman-docker pylint python2-devel python2-elasticsearch python2-jsonpointer python2-libs python2-libvirt python2-lxml python2-openpyxl python2-psycopg2 python2-pylint python2-rtslib python2-rtslib-fb python-curses python-libvirt-python python-openpyxl python-prometheus_client python-pylint qt4-devel qtchooser ragel rdma-core-devel realpath RediSearch selinux-policy-devel sensors setools sqlite-libs systemd-devel system-python-libs uic xfsprogs ++RHEL 8\.2 - 389-ds 389-ds-base apache2 avahi-devel avahi-tools avahi-utils chan-devel Coin[0-9]-devel Coin-devel community-mysql cpan(YAML::LibYAML) cppcheck device-mapper-devel docker docker-common docker-io HdrHistogram_c-devel infiniband-diags-devel kubernetes-client kubernetes-node libavahi-devel libibmad-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvirt-python libvirt-python3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-ldap perl-List-MoreUtils perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pkg-config pkgconfig python36-libs python36-lxml python36-pillow python36-requests python36-setuptools python36-six python3-curses python3-devel python3-libvirt-python python3-openpyxl python3-Pillow python3-pyodbc python3-rtslib-fb qt4-devel qtchooser qt-devel realpath RediSearch sensors SoQt-devel system-python-libs zabbix22-agent zabbix-agent zfs-fuse ++RHEL 8\.[0-1] - 389-ds 389-ds-base apache2 avahi-devel avahi-tools avahi-utils chan-devel Coin[0-9]-devel Coin-devel cpan(YAML::LibYAML) cppcheck device-mapper-devel docker-common docker-io HdrHistogram_c-devel infiniband-diags-devel kubernetes-client kubernetes-node libavahi-devel libibmad-devel mandoc perl-File-Slurp perl-Getopt-Std perl-JSON perl-ldap perl-List-MoreUtils perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pylint python36-devel python36-lxml python3-libvirt-python python3-openpyxl python3-Pillow python3-pyodbc python3-rtslib-fb python-prometheus_client qt4-devel qtchooser qt-devel sensors SoQt-devel statsd zabbix22-agent zabbix-agent zfs-fuse python2-pylint ++RHEL 7\.9 - apache2 avahi-utils bpftrace chan-devel Coin[0-9]-devel Coin-devel community-mysql docker-io git-core HdrHistogram_c-devel libavahi-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools mysql net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools qt4-devel qtchooser realpath RediSearch sensors sqlite-libs system-python-libs zabbix-agent zfs-fuse zabbix22-agent python2-openpyxl python2-elasticsearch python-pylint python-prometheus_client python-openpyxl avahi-devel avahi-tools device-mapper-devel infiniband-diags-devel python2-jsonpointer python2-setuptools python2-libvirt python-libvirt-python python2-lxml python2-psycopg2 setools python-curses python2-libs python2-devel podman-docker coreutils-single python2-rtslib-fb python2-rtslib ++RHEL 7\.8 - apache2 avahi-utils bpftrace chan-devel Coin[0-9]-devel Coin-devel community-mysql docker-io git-core HdrHistogram_c-devel kubernetes-client libavahi-devel libibumad-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools mysql net-tools-deprecated perl-base perl-DBD-mysql perl-Getopt-Std perl-interpreter perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkgconf-pkg-config platform-python-devel platform-python-setuptools qt4-devel qtchooser realpath RediSearch sensors sqlite-libs system-python-libs zabbix-agent zfs-fuse ++RHEL 7\.[5-7] - chan-devel Coin[0-9]-devel Coin-devel cppcheck device-mapper-devel HdrHistogram_c-devel kubernetes-client openssl-devel perl-Getopt-Std perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC perl-YAML-LibYAML pylint python2-elasticsearch python2-openpyxl python2-prometheus_client python2-pylint python-elasticsearch python-openpyxl python-prometheus_client python-pylint qtchooser ruby SoQt-devel statsd system-python-libs zabbix22-agent zabbix-agent zfs-fuse ++RHEL 6\.10 - apache2 avahi-utils bpftrace chan-devel Coin[0-9]-devel Coin-devel community-mysql coreutils-single device-mapper-devel docker-common docker-io git-core HdrHistogram_c-devel infiniband-diags-devel java-latest-openjdk-headless kubernetes-client kubernetes-node libavahi-devel libicu-devel libpfm-devel libqt5Core-devel libQt5Core-devel libqt5-qtbase-devel libqt5-qtsvg-devel libsqlite3 libvirt-daemon libvirt-daemon-driver-qemu mandoc mariadb mariadb-client mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools net-tools-deprecated perl-autodie perl-base perl-DBD-mysql perl-Getopt-Std perl-ldap perl-rrdtool perl-Spreadsheet-Read perl-Spreadsheet-ReadSXC pkg-config pkg-configmandoc pkgconf-pkg-config platform-python-devel platform-python-setuptools podman-docker pylint python2-devel python2-elasticsearch python2-jsonpointer python2-libs python2-libvirt python2-lxml python2-openpyxl python2-psycopg2 python2-pylint python2-rtslib python2-rtslib-fb python-curses python-libvirt-python python-openpyxl python-prometheus_client python-pylint qt4-devel qtchooser ragel rdma-core-devel realpath RediSearch selinux-policy-devel sensors setools sqlite-libs systemd-devel system-python-libs uic xfsprogs + #-- Ubuntu + Ubuntu 20\.04 - apache2-mpm-worker avahi-tools kubernetes-client libicu libpython-dev libqt4-dev libreadline6-dev libsoqt4-dev libsoqt-dev libsoqt-dev-common libuv-dev mariadb-client-core mysql-client-core perl-modules qt4-qmake realpath redis-cli + Ubuntu 19\.10 - kubernetes-client libreadline6-dev libsoqt5-dev libsoqt-dev-common redis-tools +diff -Naurp pcp-5.3.0.orig/qa/admin/package-lists/Fedora+31+x86_64 pcp-5.3.0/qa/admin/package-lists/Fedora+31+x86_64 +--- pcp-5.3.0.orig/qa/admin/package-lists/Fedora+31+x86_64 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/qa/admin/package-lists/Fedora+31+x86_64 2021-05-14 13:18:32.123079184 +1000 +@@ -47,7 +47,6 @@ kubernetes-client + libicu-devel + libpfm-devel + libuv-devel +-libvarlink-devel + libvirt-daemon + libvirt-daemon-driver-qemu + lm_sensors +diff -Naurp pcp-5.3.0.orig/qa/admin/package-lists/Fedora+32+x86_64 pcp-5.3.0/qa/admin/package-lists/Fedora+32+x86_64 +--- pcp-5.3.0.orig/qa/admin/package-lists/Fedora+32+x86_64 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/qa/admin/package-lists/Fedora+32+x86_64 2021-05-14 13:18:32.123079184 +1000 +@@ -46,7 +46,6 @@ kubernetes-client + libicu-devel + libpfm-devel + libuv-devel +-libvarlink-devel + libvirt-daemon + libvirt-daemon-driver-qemu + lm_sensors +diff -Naurp pcp-5.3.0.orig/qa/admin/package-lists/Fedora+33+x86_64 pcp-5.3.0/qa/admin/package-lists/Fedora+33+x86_64 +--- pcp-5.3.0.orig/qa/admin/package-lists/Fedora+33+x86_64 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/qa/admin/package-lists/Fedora+33+x86_64 2021-05-14 13:18:32.123079184 +1000 +@@ -57,7 +57,6 @@ libibumad-devel + libicu-devel + libpfm-devel + libuv-devel +-libvarlink-devel + libvirt-daemon + libvirt-daemon-driver-qemu + libvirt-python3 +diff -Naurp pcp-5.3.0.orig/qa/admin/package-lists/Fedora+34+x86_64 pcp-5.3.0/qa/admin/package-lists/Fedora+34+x86_64 +--- pcp-5.3.0.orig/qa/admin/package-lists/Fedora+34+x86_64 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/qa/admin/package-lists/Fedora+34+x86_64 2021-05-14 13:18:32.123079184 +1000 +@@ -46,7 +46,6 @@ kubernetes-client + libicu-devel + libpfm-devel + libuv-devel +-libvarlink-devel + libvirt-daemon + libvirt-daemon-driver-qemu + lm_sensors +diff -Naurp pcp-5.3.0.orig/qa/admin/package-lists/Fedora+35+x86_64 pcp-5.3.0/qa/admin/package-lists/Fedora+35+x86_64 +--- pcp-5.3.0.orig/qa/admin/package-lists/Fedora+35+x86_64 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/qa/admin/package-lists/Fedora+35+x86_64 2021-05-14 13:18:32.123079184 +1000 +@@ -46,7 +46,6 @@ kubernetes-client + libicu-devel + libpfm-devel + libuv-devel +-libvarlink-devel + libvirt-daemon + libvirt-daemon-driver-qemu + lm_sensors +diff -Naurp pcp-5.3.0.orig/qa/common.containers pcp-5.3.0/qa/common.containers +--- pcp-5.3.0.orig/qa/common.containers 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/qa/common.containers 2021-05-14 13:18:32.123079184 +1000 +@@ -25,7 +25,7 @@ _check_podman_binary() + [ $? -eq 0 ] || _notrun "No podman binary found" + podman="$sudo $podman" + +- $sudo test -S /run/podman/io.podman || _notrun "no podman varlink socket" ++ $sudo test -f "$PCP_SYSTEMDUNIT_DIR/podman.socket" || _notrun "No podman REST API service found" + } + + _check_docker_binary() +diff -Naurp pcp-5.3.0.orig/src/include/builddefs.in pcp-5.3.0/src/include/builddefs.in +--- pcp-5.3.0.orig/src/include/builddefs.in 2021-04-01 14:24:05.000000000 +1100 ++++ pcp-5.3.0/src/include/builddefs.in 2021-05-14 13:18:32.123079184 +1000 +@@ -346,8 +346,6 @@ HAVE_LIBUV = @HAVE_LIBUV@ + LIB_FOR_LIBUV = @libuv_LIBS@ + HAVE_OPENSSL = @HAVE_OPENSSL@ + LIB_FOR_OPENSSL = @openssl_LIBS@ +-HAVE_LIBVARLINK = @HAVE_LIBVARLINK@ +-LIB_FOR_LIBVARLINK = @libvarlink_LIBS@ + HAVE_NCURSES = @HAVE_NCURSES@ + LIB_FOR_NCURSES = @ncurses_LIBS@ + HAVE_NCURSESW = @HAVE_NCURSESW@ +diff -Naurp pcp-5.3.0.orig/src/libpcp_web/src/http_client.c pcp-5.3.0/src/libpcp_web/src/http_client.c +--- pcp-5.3.0.orig/src/libpcp_web/src/http_client.c 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/src/libpcp_web/src/http_client.c 2021-05-14 13:18:32.124079167 +1000 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014,2016-2017,2020 Red Hat. ++ * Copyright (c) 2014,2016-2017,2020-2021 Red Hat. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public +@@ -501,7 +501,7 @@ on_header_value(http_parser *pp, const c + if (length + 1 > cp->type_length) { + cp->error_code = -E2BIG; + if (pmDebugOptions.http) +- fprintf(stderr, "on_header_value: Setting error E2BIG"); ++ fprintf(stderr, "on_header_value: Setting error E2BIG\n"); + return 1; + } + strncpy(cp->type_buffer, offset, length); +@@ -523,7 +523,7 @@ on_body(http_parser *pp, const char *off + if (length > cp->body_length - cp->offset) { + cp->error_code = -E2BIG; + if (pmDebugOptions.http) +- fprintf(stderr, "on_body: Setting error E2BIG"); ++ fprintf(stderr, "on_body: Setting error E2BIG\n"); + return 1; + } + strncpy(cp->body_buffer + cp->offset, offset, length); +@@ -595,7 +595,7 @@ http_client_response(http_client *cp) + return sts ? sts : -EAGAIN; + } + if (pmDebugOptions.http) +- fprintf(stderr, "http_client error code=%d", cp->error_code); ++ fprintf(stderr, "http_client_response error code=%d\n", cp->error_code); + + bytes = http_parser_execute(&cp->parser, &settings, buffer, sts); + if (pmDebugOptions.http) { +@@ -604,7 +604,7 @@ http_client_response(http_client *cp) + fprintf(stderr, "While loop condition=%d\n", (bytes && !(cp->flags & F_MESSAGE_END))); + } + +- } while (bytes && !(cp->flags & F_MESSAGE_END)); ++ } while (bytes && !cp->error_code && !(cp->flags & F_MESSAGE_END)); + + if (http_should_client_disconnect(cp)) + http_client_disconnect(cp); +@@ -650,6 +650,7 @@ void + pmhttpFreeClient(http_client *cp) + { + http_client_disconnect(cp); ++ free(cp->url); + free(cp); + } + +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/context.c pcp-5.3.0/src/pmdas/podman/context.c +--- pcp-5.3.0.orig/src/pmdas/podman/context.c 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/context.c 1970-01-01 10:00:00.000000000 +1000 +@@ -1,100 +0,0 @@ +-/* +- * Copyright (c) 2018 Red Hat. +- * +- * 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. +- */ +- +-#include "podman.h" +- +-enum { +- CTX_INACTIVE = 0, +- CTX_ACTIVE = (1<<0), +- CTX_CONTAINER= (1<<1), +-}; +- +-typedef struct context { +- unsigned int state; +- struct container *container; +-} context_t; +- +-static context_t *ctxtab; +-static int num_ctx; +- +-static void +-podman_context_clear(int ctx) +-{ +- ctxtab[ctx].state = CTX_INACTIVE; +- ctxtab[ctx].container = NULL; +-} +- +-void +-podman_context_end(int ctx) +-{ +- if (ctx < 0 || ctx >= num_ctx || ctxtab[ctx].state == CTX_INACTIVE) +- return; +- podman_context_clear(ctx); +-} +- +-static void +-podman_context_grow_table(int ctx) +-{ +- size_t need; +- +- if (ctx < num_ctx) +- return; +- +- need = (ctx + 1) * sizeof(ctxtab[0]); +- ctxtab = (context_t *)realloc(ctxtab, need); +- if (ctxtab == NULL) +- pmNoMem("podman context table", need, PM_FATAL_ERR); +- while (num_ctx <= ctx) +- podman_context_clear(num_ctx++); +-} +- +-struct container * +-podman_context_container(int ctx) +-{ +- context_t *pp; +- +- if (ctx < 0 || ctx >= num_ctx) +- return NULL; +- pp = &ctxtab[ctx]; +- if (pp->state == CTX_INACTIVE) +- return NULL; +- if (pp->state & CTX_CONTAINER) +- return pp->container; +- return NULL; +-} +- +-void +-podman_context_set_container(int ctx, pmInDom indom, const char *value, int length) +-{ +- struct container *cp = NULL; +- char name[64+1]; +- int sts; +- +- if (length < sizeof(name)) { +- pmsprintf(name, sizeof(name), "%s", value); +- sts = pmdaCacheLookupName(indom, name, NULL, (void **)&cp); +- if (sts < 0) +- cp = NULL; +- } +- +- podman_context_grow_table(ctx); +- if (cp) { +- ctxtab[ctx].container = cp; +- ctxtab[ctx].state |= CTX_CONTAINER; +- } else { +- ctxtab[ctx].container = NULL; +- ctxtab[ctx].state &= ~CTX_CONTAINER; +- } +- ctxtab[ctx].state |= CTX_ACTIVE; +-} +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/.gitignore pcp-5.3.0/src/pmdas/podman/.gitignore +--- pcp-5.3.0.orig/src/pmdas/podman/.gitignore 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/.gitignore 2021-05-14 13:18:32.124079167 +1000 +@@ -1,6 +1,8 @@ + domain.h + pmdapodman + pmda_podman.so ++jsonsl.c ++jsonsl.h + help.dir + help.pag + exports +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/GNUmakefile pcp-5.3.0/src/pmdas/podman/GNUmakefile +--- pcp-5.3.0.orig/src/pmdas/podman/GNUmakefile 2021-02-22 11:31:04.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/GNUmakefile 2021-05-14 13:18:32.124079167 +1000 +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2018,2020 Red Hat. ++# Copyright (c) 2018,2020-2021 Red Hat. + # + # 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 +@@ -21,18 +21,21 @@ CMDTARGET = pmda$(IAM) + LIBTARGET = pmda_$(IAM).$(DSOSUFFIX) + PMDAINIT = $(IAM)_init + +-CFILES = varlink.c context.c pmda.c ++PMDAADMDIR = $(PCP_PMDASADM_DIR)/$(IAM) ++PMDATMPDIR = $(PCP_PMDAS_DIR)/$(IAM) ++ ++LLDLIBS = $(PCP_WEBLIB) ++ ++CFILES = podman.c jsonsl.c pmda.c ++HFILES = podman.h jsonsl.h ++EXT_FILES = jsonsl.c jsonsl.h ++ ++LCFLAGS = -I$(TOPDIR)/src/libpcp_web/src + + SCRIPTS = Install Remove + VERSION_SCRIPT = exports + HELPTARGETS = help.dir help.pag +-LDIRT = $(HELPTARGETS) domain.h $(VERSION_SCRIPT) +- +-LLDLIBS = $(PCP_PMDALIB) $(LIB_FOR_LIBVARLINK) +-LCFLAGS = $(INVISIBILITY) +- +-PMDAADMDIR = $(PCP_PMDASADM_DIR)/$(IAM) +-PMDATMPDIR = $(PCP_PMDAS_DIR)/$(IAM) ++LDIRT = $(HELPTARGETS) domain.h $(VERSION_SCRIPT) $(EXT_FILES) + + MAN_SECTION = 1 + MAN_PAGES = pmda$(IAM).$(MAN_SECTION) +@@ -43,7 +46,7 @@ default: build-me + include $(BUILDRULES) + + ifeq "$(PMDA_PODMAN)" "true" +-build-me: $(LIBTARGET) $(CMDTARGET) $(HELPTARGETS) ++build-me: $(EXT_FILES) $(LIBTARGET) $(CMDTARGET) $(HELPTARGETS) + + install: default + $(INSTALL) -m 755 -d $(PMDAADMDIR) +@@ -57,6 +60,9 @@ build-me: + install: + endif + ++$(EXT_FILES): ++ $(LN_S) $(TOPDIR)/src/external/$@ . ++ + default_pcp : default + + install_pcp : install +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/help pcp-5.3.0/src/pmdas/podman/help +--- pcp-5.3.0.orig/src/pmdas/podman/help 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/help 2021-05-14 13:18:32.124079167 +1000 +@@ -32,9 +32,9 @@ + @ podman.container.name human-readable name for each podman container + @ podman.container.command command line of initial container process + @ podman.container.status string indicating current container status +-@ podman.container.rwsize prefered I/O size for podman container +-@ podman.container.rootfssize size of container root filesystem + @ podman.container.running zero or one indicating container running ++@ podman.container.image base image name for each container ++@ podman.container.pod pod mapping for containers in pods + + @ podman.container.stats.net_input interface bytes received per container + @ podman.container.stats.net_output interface bytes transmitted per container +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/Install pcp-5.3.0/src/pmdas/podman/Install +--- pcp-5.3.0.orig/src/pmdas/podman/Install 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/Install 2021-05-14 13:18:32.124079167 +1000 +@@ -1,6 +1,6 @@ + #!/bin/sh + # +-# Copyright (c) 2018 Red Hat. ++# Copyright (c) 2018-2021 Red Hat. + # + # 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 +@@ -23,14 +23,14 @@ daemon_opt=true + pipe_opt=true + pmns_source=root_podman + +-if [ ! -S /run/podman/io.podman ] ++if [ ! -S /run/podman/podman.sock ] + then +- $PCP_ECHO_PROG $PCP_ECHO_N "Do you wish to start the podman varlink socket? [y] ""$PCP_ECHO_C" ++ $PCP_ECHO_PROG $PCP_ECHO_N "Do you wish to start the podman system service? [y] ""$PCP_ECHO_C" + read ans + if [ "X$ans" = "Xy" -o "X$ans" = "XY" -o -z "$ans" ] + then +- systemctl enable io.podman.service +- systemctl start io.podman.service ++ systemctl enable podman.service ++ systemctl start podman.service + else + echo "Warning: continuing installation but expect no metric values" + fi +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/pmda.c pcp-5.3.0/src/pmdas/podman/pmda.c +--- pcp-5.3.0.orig/src/pmdas/podman/pmda.c 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/pmda.c 2021-05-14 13:18:32.124079167 +1000 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018 Red Hat. ++ * Copyright (c) 2018,2021 Red Hat. + * + * 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 +@@ -16,8 +16,8 @@ + #include "libpcp.h" + #include "domain.h" + +-static pmdaIndom podman_indomtab[NUM_INDOMS]; +-#define INDOM(x) (podman_indomtab[x].it_indom) ++char *podman_rundir; ++pmdaIndom podman_indomtab[NUM_INDOMS]; + + #define NUM_METRICS (NUM_CONTAINER_STATS + NUM_CONTAINER_INFO + NUM_POD_INFO) + static pmdaMetric podman_metrictab[] = { +@@ -67,15 +67,15 @@ static pmdaMetric podman_metrictab[] = { + { .m_desc = { PMDA_PMID(CLUSTER_INFO, INFO_STATUS), + PM_TYPE_STRING, CONTAINER_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(0,0,0,0,0,0) }, }, +- { .m_desc = { PMDA_PMID(CLUSTER_INFO, INFO_RWSIZE), +- PM_TYPE_U64, CONTAINER_INDOM, PM_SEM_INSTANT, +- PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, }, +- { .m_desc = { PMDA_PMID(CLUSTER_INFO, INFO_ROOTFSSIZE), +- PM_TYPE_U64, CONTAINER_INDOM, PM_SEM_INSTANT, +- PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, }, + { .m_desc = { PMDA_PMID(CLUSTER_INFO, INFO_RUNNING), + PM_TYPE_U32, CONTAINER_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) }, }, ++ { .m_desc = { PMDA_PMID(CLUSTER_INFO, INFO_IMAGE), ++ PM_TYPE_STRING, CONTAINER_INDOM, PM_SEM_DISCRETE, ++ PMDA_PMUNITS(0,0,0,0,0,0) }, }, ++ { .m_desc = { PMDA_PMID(CLUSTER_INFO, INFO_POD), ++ PM_TYPE_STRING, CONTAINER_INDOM, PM_SEM_DISCRETE, ++ PMDA_PMUNITS(0,0,0,0,0,0) }, }, + + /* pod info cluster (2) */ + { .m_desc = { PMDA_PMID(CLUSTER_POD, POD_NAME), +@@ -115,81 +115,23 @@ podman_strings_insert(const char *string + return pmdaCacheStore(dict, PMDA_CACHE_ADD, string, NULL); + } + +-static void +-podman_refresh_container(pmdaExt *pmda, pmInDom indom, int inst, state_flags_t flags) +-{ +- container_t *cp = podman_context_container(pmda->e_context); +- char *name = NULL; +- int sts; +- +- if (cp != NULL) +- name = podman_strings_lookup(cp->id); +- else if (inst != PM_IN_NULL) { +- sts = pmdaCacheLookup(indom, inst, &name, (void **)&cp); +- name = (sts < 0) ? NULL : podman_strings_lookup(cp->id); +- } +- if (name && name[0] == '\0') +- name = NULL; +- +- if (name) +- refresh_podman_container(indom, name, flags); +- else +- refresh_podman_containers(indom, flags); +-} +- +-static void +-podman_refresh_info(pmdaExt *pmda, pmInDom indom, int inst, char *name) +-{ +- container_t *cp = podman_context_container(pmda->e_context); +- int sts; +- +- if (cp != NULL) +- name = podman_strings_lookup(cp->id); +- else if (inst != PM_IN_NULL) { +- sts = pmdaCacheLookup(indom, inst, &name, (void **)&cp); +- name = (sts < 0) ? NULL : podman_strings_lookup(cp->id); +- } +- if (name && name[0] == '\0') +- name = NULL; +- +- if (name) +- refresh_podman_container(indom, name, STATE_INFO); +- else +- refresh_podman_containers(indom, STATE_INFO); +-} +- +-static void +-podman_refresh_pod(pmdaExt *pmda, pmInDom indom, int inst, char *name) +-{ +- container_t *cp; +- int sts; +- +- if (inst != PM_IN_NULL) { +- sts = pmdaCacheLookup(indom, inst, &name, (void **)&cp); +- name = (sts < 0) ? NULL : podman_strings_lookup(cp->id); +- } +- if (name && name[0] == '\0') +- name = NULL; +- +- if (name) +- refresh_podman_pod_info(indom, name); +- else +- refresh_podman_pods_info(indom); +-} +- + static int + podman_instance(pmInDom indom, int inst, char *name, pmInResult **result, pmdaExt *pmda) + { +- unsigned int serial = pmInDom_serial(indom); ++ unsigned int refresh = 0, need_refresh[NUM_CLUSTERS] = { 0 }; + +- switch(serial) { ++ switch (pmInDom_serial(indom)) { + case CONTAINER_INDOM: +- podman_refresh_info(pmda, indom, inst, name); ++ need_refresh[CLUSTER_INFO]++; ++ refresh++; + break; + case POD_INDOM: +- podman_refresh_pod(pmda, indom, inst, name); ++ need_refresh[CLUSTER_POD]++; ++ refresh++; + break; + } ++ if (refresh) ++ podman_refresh(need_refresh); + return pmdaInstance(indom, inst, name, result, pmda); + } + +@@ -271,15 +213,15 @@ podman_info_fetchCallBack(unsigned int i + case INFO_STATUS: + atom->cp = podman_strings_lookup(cp->info.status); + break; +- case INFO_RWSIZE: +- atom->ull = cp->info.rwsize; +- break; +- case INFO_ROOTFSSIZE: +- atom->ull = cp->info.rootfssize; +- break; + case INFO_RUNNING: + atom->ul = cp->info.running; + break; ++ case INFO_IMAGE: ++ atom->cp = podman_strings_lookup(cp->info.image); ++ break; ++ case INFO_POD: ++ atom->cp = podman_strings_lookup(cp->info.podid); ++ break; + default: + return PM_ERR_PMID; + } +@@ -289,7 +231,7 @@ podman_info_fetchCallBack(unsigned int i + static int + podman_pod_fetchCallBack(unsigned int item, unsigned int inst, pmAtomValue *atom) + { +- pod_info_t *pp; ++ pod_t *pp; + int sts; + + sts = pmdaCacheLookup(INDOM(POD_INDOM), inst, NULL, (void **)&pp); +@@ -297,19 +239,21 @@ podman_pod_fetchCallBack(unsigned int it + return sts; + if (sts != PMDA_CACHE_ACTIVE) + return PM_ERR_INST; ++ if (!(pp->flags & STATE_POD)) ++ return 0; + + switch (item) { + case POD_NAME: +- atom->cp = podman_strings_lookup(pp->name); ++ atom->cp = podman_strings_lookup(pp->info.name); + break; + case POD_CGROUP: +- atom->cp = podman_strings_lookup(pp->cgroup); ++ atom->cp = podman_strings_lookup(pp->info.cgroup); + break; + case POD_STATUS: +- atom->cp = podman_strings_lookup(pp->status); ++ atom->cp = podman_strings_lookup(pp->info.status); + break; + case POD_CONTAINERS: +- atom->ul = pp->ncontainers; ++ atom->ul = pp->info.ncontainers; + break; + default: + return PM_ERR_PMID; +@@ -340,7 +284,6 @@ static int + podman_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda) + { + unsigned int cluster, need_refresh[NUM_CLUSTERS] = { 0 }; +- state_flags_t flags = STATE_NONE; + int i; + + for (i = 0; i < numpmid; i++) { +@@ -348,16 +291,7 @@ podman_fetch(int numpmid, pmID pmidlist[ + if (cluster < NUM_CLUSTERS) + need_refresh[cluster]++; + } +- +- if (need_refresh[CLUSTER_STATS]) +- flags |= STATE_STATS; +- if (need_refresh[CLUSTER_INFO]) +- flags |= STATE_INFO; +- +- if (flags != STATE_NONE) +- podman_refresh_container(pmda, INDOM(CONTAINER_INDOM), PM_IN_NULL, flags); +- if (need_refresh[CLUSTER_POD]) +- podman_refresh_pod(pmda, INDOM(POD_INDOM), PM_IN_NULL, NULL); ++ podman_refresh(need_refresh); + + return pmdaFetch(numpmid, pmidlist, resp, pmda); + } +@@ -366,7 +300,7 @@ static int + podman_labelCallBack(pmInDom indom, unsigned int inst, pmLabelSet **lp) + { + container_t *cp; +- pod_info_t *pp; ++ pod_t *pp; + void *vp; + int sts; + +@@ -376,23 +310,19 @@ podman_labelCallBack(pmInDom indom, unsi + if (sts != PMDA_CACHE_ACTIVE) + return 0; + if (indom == INDOM(POD_INDOM)) { +- pp = (pod_info_t *)vp; +- // for (i = 0; i < cp->info.labels; i++) +- // pmdaAddLabels(lp, "{\"%s\":\"%s\"}", +- // podman_strings_lookup(pp->labelnames[n]), +- // podman_strings_lookup(pp->labelvalue[n])); +- return pp->labels; ++ pp = (pod_t *)vp; ++ if (pp->info.nlabels) ++ pmdaAddNotes(lp, "%s", podman_strings_lookup(pp->info.labelmap)); ++ return pp->info.nlabels; + } + if (indom == INDOM(CONTAINER_INDOM)) { + cp = (container_t *)vp; +- if (cp->podmap) ++ if (cp->info.podid) + pmdaAddLabels(lp, "{\"pod\":\"%s\"}", +- podman_strings_lookup(cp->podmap)); +- // for (i = 0; i < cp->info.labels; i++) +- // pmdaAddLabels(lp, "{\"%s\":\"%s\"}", +- // podman_strings_lookup(cp->info.labelnames[n]), +- // podman_strings_lookup(cp->info.labelvalues[n])); +- return cp->info.labels + (cp->podmap? 1 : 0); ++ podman_strings_lookup(cp->info.podid)); ++ if (cp->info.nlabels) ++ pmdaAddNotes(lp, "%s", podman_strings_lookup(cp->info.labelmap)); ++ return cp->info.nlabels + (cp->info.podid ? 1 : 0); + } + return 0; + } +@@ -403,19 +333,6 @@ podman_label(int ident, int type, pmLabe + return pmdaLabel(ident, type, lpp, pmda); + } + +-static int +-podman_attribute(int ctx, int attr, const char *value, int len, pmdaExt *pmda) +-{ +- switch (attr) { +- case PMDA_ATTR_CONTAINER: +- podman_context_set_container(ctx, INDOM(CONTAINER_INDOM), value, len); +- break; +- default: +- break; +- } +- return pmdaAttribute(ctx, attr, value, len, pmda); +-} +- + static pmLongOptions longopts[] = { + PMDA_OPTIONS_HEADER("Options"), + PMOPT_DEBUG, +@@ -447,13 +364,16 @@ podman_init(pmdaInterface *dp) + if (dp->status != 0) + return; + ++ if (podman_rundir == NULL) ++ podman_rundir = "/run"; ++ ++ podman_parse_init(); ++ + dp->version.seven.fetch = podman_fetch; + dp->version.seven.label = podman_label; + dp->version.seven.instance = podman_instance; +- dp->version.seven.attribute = podman_attribute; + pmdaSetFetchCallBack(dp, podman_fetchCallBack); + pmdaSetLabelCallBack(dp, podman_labelCallBack); +- pmdaSetEndContextCallBack(dp, podman_context_end); + + podman_indomtab[CONTAINER_INDOM].it_indom = CONTAINER_INDOM; + podman_indomtab[STRINGS_INDOM].it_indom = STRINGS_INDOM; +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/podman.c pcp-5.3.0/src/pmdas/podman/podman.c +--- pcp-5.3.0.orig/src/pmdas/podman/podman.c 1970-01-01 10:00:00.000000000 +1000 ++++ pcp-5.3.0/src/pmdas/podman/podman.c 2021-05-14 13:19:32.695039941 +1000 +@@ -0,0 +1,737 @@ ++/* ++ * Copyright (c) 2021 Red Hat. ++ * ++ * 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. ++ */ ++#include ++#include "podman.h" ++#include "jsonsl.h" ++#include "pmhttp.h" ++#include "http_client.h" ++#include "http_parser.h" ++ ++typedef struct { ++ uint32_t id; ++ container_stats_e field; ++ container_stats_t values; ++} container_stats_parser_t; ++ ++typedef struct { ++ uint32_t id; ++ container_info_e field; ++ container_info_t values; ++} container_info_parser_t; ++ ++typedef struct { ++ uint32_t id; ++ pod_info_e field; ++ pod_info_t values; ++} pod_info_parser_t; ++ ++static container_stats_parser_t container_stats_parser; ++static jsonsl_t container_stats_json; ++static container_info_parser_t container_info_parser; ++static jsonsl_t container_info_json; ++static pod_info_parser_t pod_info_parser; ++static jsonsl_t pod_info_json; ++ ++static int ++log_error(jsonsl_t json, jsonsl_error_t error, ++ struct jsonsl_state_st *state, jsonsl_char_t *at) ++{ ++ pmNotifyErr(LOG_ERR, "Error %s at position %lu. Remaining: %s\n", ++ jsonsl_strerror(error), json->pos, at); ++ return 0; ++} ++ ++/* ++ * Parse and refresh metric values relating to container stats cluster ++ */ ++ ++static void ++container_stats_update(container_stats_parser_t *parser, const char *position) ++{ ++ if (container_stats_json->level == 2) { /* complete */ ++ container_t *cp = NULL; ++ pmInDom indom = INDOM(CONTAINER_INDOM); ++ char *name = podman_strings_lookup(parser->id); ++ int sts = pmdaCacheLookupName(indom, name, NULL, (void **)&cp); ++ if (sts < 0 || cp == NULL) { ++ if ((cp = calloc(1, sizeof(*cp))) == NULL) ++ return; ++ if (pmDebugOptions.attr) ++ fprintf(stderr, "adding container %s (%u)\n", name, parser->id); ++ } ++ /* store the completed info values into the cached structure */ ++ cp->flags |= STATE_STATS; ++ memcpy(&cp->stats, &parser->values, sizeof(cp->stats)); ++ pmdaCacheStore(indom, PMDA_CACHE_ADD, name, (void *)cp); ++ } ++} ++ ++static void ++container_stats_field(container_stats_parser_t *cp, ++ const char *key, size_t len) ++{ ++ cp->field = -1; ++ ++ if (len == 11 && strncmp("ContainerID", key, len) == 0) ++ cp->field = STATS_ID; ++ else if (len == 10 && strncmp("BlockInput", key, len) == 0) ++ cp->field = STATS_BLOCK_INPUT; ++ else if (len == 11 && strncmp("BlockOutput", key, len) == 0) ++ cp->field = STATS_BLOCK_OUTPUT; ++ else if (len == 8 && strncmp("NetInput", key, len) == 0) ++ cp->field = STATS_NET_INPUT; ++ else if (len == 9 && strncmp("NetOutput", key, len) == 0) ++ cp->field = STATS_NET_OUTPUT; ++ else if (len == 3 && strncmp("CPU", key, len) == 0) ++ cp->field = STATS_CPU; ++ else if (len == 7 && strncmp("CPUNano", key, len) == 0) ++ cp->field = STATS_CPU_NANO; ++ else if (len == 13 && strncmp("CPUSystemNano", key, len) == 0) ++ cp->field = STATS_SYSTEM_NANO; ++ else if (len == 8 && strncmp("MemUsage", key, len) == 0) ++ cp->field = STATS_MEM_USAGE; ++ else if (len == 8 && strncmp("MemLimit", key, len) == 0) ++ cp->field = STATS_MEM_LIMIT; ++ else if (len == 7 && strncmp("MemPerc", key, len) == 0) ++ cp->field = STATS_MEM_PERC; ++ else if (len == 4 && strncmp("PIDs", key, len) == 0) ++ cp->field = STATS_PIDS; ++} ++ ++static void ++container_stats_value(container_stats_parser_t *cp, ++ const char *value, size_t len) ++{ ++ char buffer[BUFSIZ]; ++ char *end; ++ ++ switch (cp->field) { ++ case STATS_NET_INPUT: ++ cp->values.net_input = strtoull(value, &end, 0); ++ if (end - value != len) ++ cp->values.net_input = 0; ++ break; ++ case STATS_NET_OUTPUT: ++ cp->values.net_output = strtoull(value, &end, 0); ++ if (end - value != len) ++ cp->values.net_output = 0; ++ break; ++ case STATS_BLOCK_INPUT: ++ cp->values.block_input = strtoull(value, &end, 0); ++ if (end - value != len) ++ cp->values.block_input = 0; ++ break; ++ case STATS_BLOCK_OUTPUT: ++ cp->values.block_output = strtoull(value, &end, 0); ++ if (end - value != len) ++ cp->values.block_output = 0; ++ break; ++ case STATS_CPU: ++ cp->values.cpu = strtod(value, &end); ++ if (end - value != len) ++ cp->values.cpu = 0; ++ break; ++ case STATS_CPU_NANO: ++ cp->values.cpu_nano = strtoll(value, &end, 0); ++ if (end - value != len) ++ cp->values.cpu_nano = 0; ++ break; ++ case STATS_SYSTEM_NANO: ++ cp->values.system_nano = strtoll(value, &end, 0); ++ if (end - value != len) ++ cp->values.system_nano = 0; ++ break; ++ case STATS_MEM_USAGE: ++ cp->values.mem_usage = strtoll(value, &end, 0); ++ if (end - value != len) ++ cp->values.mem_usage = 0; ++ break; ++ case STATS_MEM_LIMIT: ++ cp->values.mem_limit = strtoll(value, &end, 0); ++ if (end - value != len) ++ cp->values.mem_limit = 0; ++ break; ++ case STATS_MEM_PERC: ++ cp->values.mem_perc = strtod(value, &end); ++ if (end - value != len) ++ cp->values.mem_perc = 0; ++ break; ++ case STATS_PIDS: ++ cp->values.nprocesses = strtoul(value, &end, 0); ++ if (end - value != len) ++ cp->values.nprocesses = 0; ++ break; ++ case STATS_ID: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ cp->id = podman_strings_insert(buffer); ++ break; ++ default: ++ break; ++ } ++} ++ ++/* ++ * Sample output: ++ * {"Error":null,"Stats":[{"ContainerID":"aff836906c5bc3b4c932ba546984752784617645639632dcf0cd348d5c5f0d82","Name":"bold_nash","PerCPU":null,"CPU":1.5856378300710223e-9,"CPUNano":25700000,"CPUSystemNano":17224,"SystemNano":1620798867976609176,"MemUsage":7237632,"MemLimit":16391106560,"MemPerc":0.04415584740118973,"NetInput":1468,"NetOutput":167816,"BlockInput":12435456,"BlockOutput":0,"PIDs":1}]} ++ */ ++ ++static void ++container_stats_create(jsonsl_t json, jsonsl_action_t action, ++ struct jsonsl_state_st *state, const jsonsl_char_t *at) ++{ ++ container_stats_parser_t *parser; ++ ++ if (state->level == 3 && state->type == JSONSL_T_OBJECT) { ++ /* new container, any previous one is stashed in indom cache */ ++ parser = (container_stats_parser_t *)json->data; ++ memset(&parser->values, 0, sizeof(container_stats_t)); ++ parser->id = -1; ++ } ++} ++ ++static void ++container_stats_complete(jsonsl_t json, jsonsl_action_t action, ++ struct jsonsl_state_st *state, const jsonsl_char_t *at) ++{ ++ container_stats_parser_t *parser; ++ ++ parser = (container_stats_parser_t *)json->data; ++ if ((state->level == 4) && ++ (state->type == JSONSL_T_STRING || state->type == JSONSL_T_SPECIAL)) { ++ const char *value = at - (json->pos - state->pos_begin); ++ size_t bytes = json->pos - state->pos_begin; ++ if (state->type == JSONSL_T_STRING) /* skip enclosing quotes */ ++ value++, bytes--; ++ container_stats_value(parser, value, bytes); ++ } ++ else if (state->level == 4 && state->type == JSONSL_T_HKEY) { ++ const char *key = (at - (json->pos - state->pos_begin)) + 1; ++ size_t bytes = (json->pos - state->pos_begin) - 1; ++ container_stats_field(parser, key, bytes); ++ } ++ else if (state->level == 3 && state->type == JSONSL_T_OBJECT) { ++ container_stats_update(parser, at); ++ } ++} ++ ++/* ++ * Parse and refresh metric values relating to container info cluster ++ */ ++ ++static void ++container_info_add_labels(container_info_parser_t *ip, const char *value) ++{ ++ if (ip->values.labels == NULL) { ++ ip->values.labels = value - 2; ++ ip->values.nlabels = 1; ++ } else { ++ ip->values.nlabels++; ++ } ++} ++ ++static void ++container_info_end_labels(container_info_parser_t *ip, int bytes) ++{ ++ char labels[PM_MAXLABELJSONLEN]; ++ ++ if (ip->field == INFO_LABELS && ip->values.labels != NULL) { ++ pmsprintf(labels, sizeof(labels), ++ "{\"podman\":%.*s}", bytes, ip->values.labels); ++ ip->values.labelmap = podman_strings_insert(labels); ++ ip->values.labels = NULL; ++ } ++ ip->field = -1; /* end labels */ ++} ++ ++static void ++container_info_update(container_info_parser_t *ip, int level, const char *position) ++{ ++ if (level > 2) { /* labels complete */ ++ container_info_end_labels(ip, position - ip->values.labels + 1); ++ } else { /* container is complete */ ++ container_t *cp = NULL; ++ pmInDom indom = INDOM(CONTAINER_INDOM); ++ char *name = podman_strings_lookup(ip->id); ++ int sts = pmdaCacheLookupName(indom, name, NULL, (void **)&cp); ++ if (sts < 0 || cp == NULL) { ++ if ((cp = calloc(1, sizeof(*cp))) == NULL) ++ return; ++ if (pmDebugOptions.attr) ++ fprintf(stderr, "adding container %s (%u)\n", name, ip->id); ++ } ++ cp->flags |= STATE_INFO; ++ /* store the completed values into the cached structure */ ++ memcpy(&cp->info, &ip->values, sizeof(cp->info)); ++ pmdaCacheStore(indom, PMDA_CACHE_ADD, name, (void *)cp); ++ } ++} ++ ++static void ++container_info_field(container_info_parser_t *ip, int level, ++ const char *key, size_t len) ++{ ++ if (level >= 3 && ip->field == INFO_LABELS) { ++ container_info_add_labels(ip, key); ++ return; ++ } ++ if (level != 3) ++ return; ++ ++ ip->field = -1; ++ if (len == 5 && strncmp("Names", key, len) == 0) ++ ip->field = INFO_NAME; ++ else if (len == 6 && strncmp("Status", key, len) == 0) ++ ip->field = INFO_STATUS; ++ else if (len == 7 && strncmp("Command", key, len) == 0) ++ ip->field = INFO_COMMAND; ++ else if (len == 3 && strncmp("Pod", key, len) == 0) ++ ip->field = INFO_POD; ++ else if (len == 2 && strncmp("Id", key, len) == 0) ++ ip->field = INFO_ID; ++ else if (len == 6 && strncmp("Labels", key, len) == 0) ++ ip->field = INFO_LABELS; ++} ++ ++static void ++container_info_value(container_info_parser_t *ip, int level, ++ const char *value, size_t len) ++{ ++ char buffer[BUFSIZ]; ++ ++ if (level != 3) ++ return; ++ ++ switch (ip->field) { ++ case INFO_NAME: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ ip->values.name = podman_strings_insert(buffer); ++ break; ++ case INFO_COMMAND: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ ip->values.command = podman_strings_insert(buffer); ++ break; ++ case INFO_STATUS: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ ip->values.status = podman_strings_insert(buffer); ++ ip->values.running = (strncmp("Running", value, len) == 0); ++ break; ++ case INFO_IMAGE: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ ip->values.image = podman_strings_insert(buffer); ++ break; ++ case INFO_POD: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ ip->values.podid = podman_strings_insert(buffer); ++ break; ++ case INFO_ID: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ ip->id = podman_strings_insert(buffer); ++ break; ++ default: ++ break; ++ } ++} ++ ++/* ++ * Sample output: ++ * [{"AutoRemove":false,"Command":["bash"],"Created":"2021-05-12T10:29:51.438438116+10:00","CreatedAt":"","Exited":false,"ExitedAt":-62135596800,"ExitCode":0,"Id":"aff836906c5bc3b4c932ba546984752784617645639632dcf0cd348d5c5f0d82","Image":"registry.fedoraproject.org/fedora:latest","ImageID":"eb7134a03cd6bd8a3de99c16cf174d66ad2d93724bac3307795efcd8aaf914c5","IsInfra":false,"Labels":{"license":"MIT","name":"fedora","vendor":"Fedora Project","version":"32"},"Mounts":[],"Names":["bold_nash"],"Namespaces":{},"Networks":["podman"],"Pid":51085,"Pod":"","PodName":"","Ports":null,"Size":null,"StartedAt":1620779391,"State":"running","Status":""}] ++ */ ++ ++static void ++container_info_create(jsonsl_t json, jsonsl_action_t action, ++ struct jsonsl_state_st *state, const jsonsl_char_t *at) ++{ ++ container_info_parser_t *parser; ++ ++ if (state->level == 2 && state->type == JSONSL_T_OBJECT) { ++ /* new container, any previous one is stashed in indom cache */ ++ parser = (container_info_parser_t *)json->data; ++ memset(&parser->values, 0, sizeof(container_info_t)); ++ parser->id = -1; ++ } ++} ++ ++static void ++container_info_complete(jsonsl_t json, jsonsl_action_t action, ++ struct jsonsl_state_st *state, const jsonsl_char_t *at) ++{ ++ container_info_parser_t *parser; ++ ++ parser = (container_info_parser_t *)json->data; ++ if (state->type == JSONSL_T_STRING || state->type == JSONSL_T_SPECIAL) { ++ const char *value = at - (json->pos - state->pos_begin); ++ size_t bytes = json->pos - state->pos_begin; ++ if (state->type == JSONSL_T_STRING) /* skip enclosing quotes */ ++ value++, bytes--; ++ container_info_value(parser, state->level, value, bytes); ++ } ++ else if (state->type == JSONSL_T_HKEY) { ++ const char *key = (at - (json->pos - state->pos_begin)) + 1; ++ size_t bytes = (json->pos - state->pos_begin) - 1; ++ container_info_field(parser, state->level, key, bytes); ++ } ++ else if (state->type == JSONSL_T_OBJECT) { ++ container_info_update(parser, state->level, at); ++ } ++} ++ ++ ++/* ++ * Parse and refresh metric values relating to pod info cluster ++ */ ++ ++static void ++pod_info_add_labels(pod_info_parser_t *pp, const char *value) ++{ ++ if (pp->values.labels == NULL) { ++ pp->values.labels = value - 2; ++ pp->values.nlabels = 1; ++ } else { ++ pp->values.nlabels++; ++ } ++} ++ ++static void ++pod_info_end_labels(pod_info_parser_t *pp, int bytes) ++{ ++ char labels[PM_MAXLABELJSONLEN]; ++ ++ if (pp->field == POD_LABELS && pp->values.labels != NULL) { ++ pmsprintf(labels, sizeof(labels), ++ "{\"podman\":%.*s}", bytes, pp->values.labels); ++ pp->values.labelmap = podman_strings_insert(labels); ++ pp->values.labels = NULL; ++ } ++ pp->field = -1; /* end labels */ ++} ++ ++static void ++pod_info_update(pod_info_parser_t *ip, int level, const char *position) ++{ ++ if (level > 2) { /* labels are now complete */ ++ pod_info_end_labels(ip, position - ip->values.labels + 1); ++ } else { /* pod is complete */ ++ pod_t *pp = NULL; ++ pmInDom indom = INDOM(POD_INDOM); ++ char *name = podman_strings_lookup(ip->id); ++ int sts = pmdaCacheLookupName(indom, name, NULL, (void **)&pp); ++ if (sts < 0 || pp == NULL) { ++ if ((pp = calloc(1, sizeof(*pp))) == NULL) ++ return; ++ if (pmDebugOptions.attr) ++ fprintf(stderr, "adding pod %s (%u)\n", name, ip->id); ++ } ++ pp->flags |= STATE_POD; ++ /* store the completed pod values into the cached structure */ ++ memcpy(&pp->info, &ip->values, sizeof(pp->info)); ++ pmdaCacheStore(indom, PMDA_CACHE_ADD, name, (void *)pp); ++ } ++} ++ ++static void ++pod_info_field(pod_info_parser_t *pp, int level, const char *key, size_t len) ++{ ++ if (level >= 3 && pp->field == POD_LABELS) { ++ pod_info_add_labels(pp, key); ++ return; ++ } ++ if (level != 3) ++ return; ++ ++ pp->field = -1; ++ if (len == 2 && strncmp("Id", key, len) == 0) { ++ pod_info_e lastfield = pp->field; ++ if (pod_info_json->level >= 2) { ++ if (lastfield == POD_CONTAINERS) /* containers */ ++ pp->values.ncontainers++; ++ } else if (pod_info_json->level < 2) { /* pods */ ++ pp->field = POD_ID; ++ } ++ } ++ else if (len == 4 && strncmp("Name", key, len) == 0) ++ pp->field = POD_NAME; ++ else if (len == 6 && strncmp("Cgroup", key, len) == 0) ++ pp->field = POD_CGROUP; ++ else if (len == 6 && strncmp("Labels", key, len) == 0) ++ pp->field = POD_LABELS; ++ else if (len == 6 && strncmp("Status", key, len) == 0) ++ pp->field = POD_STATUS; ++ else if (len == 10 && strncmp("Containers", key, len) == 0) { ++ pp->field = POD_CONTAINERS; ++ pp->values.ncontainers = 0; ++ } ++} ++ ++static void ++pod_info_value(pod_info_parser_t *pp, int level, const char *value, size_t len) ++{ ++ char buffer[BUFSIZ]; ++ ++ if (level != 3) ++ return; ++ ++ switch (pp->field) { ++ case POD_NAME: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ pp->values.name = podman_strings_insert(buffer); ++ break; ++ case POD_CGROUP: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ pp->values.cgroup = podman_strings_insert(buffer); ++ break; ++ case POD_STATUS: ++ pmsprintf(buffer, sizeof(buffer), "%.*s", (int)len, value); ++ pp->values.status = podman_strings_insert(buffer); ++ pp->values.running = (strcmp(buffer, "Running") == 0); ++ break; ++ case POD_CONTAINERS: ++ pp->values.ncontainers = 0; ++ /* count Id fields in pod_info_containers */ ++ break; ++ default: ++ break; ++ } ++} ++ ++/* ++ * Sample output: ++ * [{"Cgroup":"user.slice","Containers":[{"Id":"527c6d322dd68e261630a3f46b3a7db3b1b79ceb0c09d8aeb36012fa8efa28b2","Names":"b9ab3ec058fc-infra","Status":"configured"}],"Created":"2021-05-11T15:26:25.325078296-07:00","Id":"b9ab3ec058fc50417bd68e79a40b0ff75d67c074ca37cba1c73a012c7bb40953","InfraId":"527c6d322dd68e261630a3f46b3a7db3b1b79ceb0c09d8aeb36012fa8efa28b2","Name":"pod001","Namespace":"","Networks":null,"Status":"Created","Labels":{}}] ++ */ ++ ++static void ++pod_info_create(jsonsl_t json, jsonsl_action_t action, ++ struct jsonsl_state_st *state, const jsonsl_char_t *at) ++{ ++ pod_info_parser_t *parser; ++ ++ if (state->level == 2 && state->type == JSONSL_T_OBJECT) { ++ /* new pod, any previous one is stashed in indom cache */ ++ parser = (pod_info_parser_t *)json->data; ++ memset(&parser->values, 0, sizeof(pod_info_t)); ++ parser->id = -1; ++ } ++} ++ ++static void ++pod_info_complete(jsonsl_t json, jsonsl_action_t action, ++ struct jsonsl_state_st *state, const jsonsl_char_t *at) ++{ ++ pod_info_parser_t *parser = (pod_info_parser_t *)json->data; ++ ++ if (state->type == JSONSL_T_STRING || state->type == JSONSL_T_SPECIAL) { ++ const char *value = at - (json->pos - state->pos_begin); ++ size_t bytes = json->pos - state->pos_begin; ++ if (state->type == JSONSL_T_STRING) /* skip quotes */ ++ value++, bytes--; ++ pod_info_value(parser, state->level, value, bytes); ++ } ++ else if (state->type == JSONSL_T_HKEY) { ++ const char *key = (at - (json->pos - state->pos_begin)) + 1; ++ size_t bytes = (json->pos - state->pos_begin) - 1; ++ pod_info_field(parser, state->level, key, bytes); ++ } ++ else if (state->type == JSONSL_T_OBJECT) { ++ pod_info_update(parser, state->level, at); ++ } ++} ++ ++/* ++ * Global setup and teardown routines ++ */ ++ ++int ++podman_parse_init(void) ++{ ++ if ((container_stats_json = jsonsl_new(16)) == 0) ++ return -ENOMEM; ++ ++ if ((container_info_json = jsonsl_new(16)) == 0) { ++ jsonsl_destroy(container_stats_json); ++ return -ENOMEM; ++ } ++ ++ if ((pod_info_json = jsonsl_new(16)) == 0) { ++ jsonsl_destroy(container_stats_json); ++ jsonsl_destroy(container_info_json); ++ return -ENOMEM; ++ } ++ ++ container_stats_json->data = &container_stats_parser; ++ container_stats_json->error_callback = log_error; ++ container_stats_json->action_callback_PUSH = container_stats_create; ++ container_stats_json->action_callback_POP = container_stats_complete; ++ jsonsl_enable_all_callbacks(container_stats_json); ++ ++ container_info_json->data = &container_info_parser; ++ container_info_json->error_callback = log_error; ++ container_info_json->action_callback_PUSH = container_info_create; ++ container_info_json->action_callback_POP = container_info_complete; ++ jsonsl_enable_all_callbacks(container_info_json); ++ ++ pod_info_json->data = &pod_info_parser; ++ pod_info_json->error_callback = log_error; ++ pod_info_json->action_callback_PUSH = pod_info_create; ++ pod_info_json->action_callback_POP = pod_info_complete; ++ jsonsl_enable_all_callbacks(pod_info_json); ++ ++ return 0; ++} ++ ++void ++podman_parse_end(void) ++{ ++ jsonsl_destroy(container_stats_json); ++ jsonsl_destroy(container_info_json); ++ jsonsl_destroy(pod_info_json); ++} ++ ++static void ++podman_http_parse(struct http_client *cp, ++ jsonsl_t json, const char *buffer, size_t length) ++{ ++ if (cp->parser.status_code == 200) { ++ jsonsl_reset(json); ++ jsonsl_feed(json, buffer, length); ++ } ++} ++ ++static char * ++podman_buffer(char *buffer, size_t *buflen) ++{ ++ size_t length = *buflen; ++ char *p; ++ ++ if (length == 0) ++ length = 256; ++ if (length >= UINT_MAX / 256) ++ return NULL; ++ ++ length *= 2; ++ if ((p = realloc(buffer, length)) != NULL) { ++ *buflen = length; ++ } else { ++ free(buffer); ++ *buflen = 0; ++ } ++ return p; ++} ++ ++static int ++podman_validate_socket(const char *path) ++{ ++ struct stat sbuf; ++ ++ if (stat(path, &sbuf) < 0) ++ return -ENOENT; ++ if (S_ISSOCK(sbuf.st_mode)) ++ return 0; ++ return -EINVAL; ++} ++ ++static void ++podman_http_fetch(const char *url, const char *query, jsonsl_t parser) ++{ ++ struct http_client *client; ++ static size_t jsonlen; ++ static char *json; ++ char type[64]; ++ int sts, len; ++ ++ if ((json == NULL) && ++ (json = podman_buffer(json, &jsonlen)) == NULL) ++ return; ++ ++ if ((client = pmhttpNewClient()) == NULL) ++ return; ++ ++retry: ++ len = pmsprintf(type, sizeof(type), "/v3.0.0/libpod/%s", query); ++ if ((sts = pmhttpClientFetch(client, url, json, jsonlen, type, len)) > 0) { ++ if (pmDebugOptions.attr) ++ fprintf(stderr, "podman_http_fetch: %.*s\n", sts, json); ++ podman_http_parse(client, parser, json, sts); ++ } else if (sts == -E2BIG) { ++ json = podman_buffer(json, &jsonlen); ++ goto retry; ++ } ++ pmhttpFreeClient(client); ++} ++ ++#define PODQUERY "pods/json" ++#define INFOQUERY "containers/json" ++#define STATSQUERY "containers/stats?stream=false" ++ ++static void ++podman_refresh_socket(const char *path, unsigned int need_refresh[]) ++{ ++ char url[MAXPATHLEN + 8]; ++ ++ if (podman_validate_socket(path) < 0) ++ return; ++ if (pmDebugOptions.attr) ++ fprintf(stderr, "refreshing on socket %s\n", path); ++ ++ /* Unix domain socket protocol and path (used for all requests) */ ++ pmsprintf(url, sizeof(url), "unix:/%s", path); ++ ++ if (need_refresh[CLUSTER_POD]) ++ podman_http_fetch(url, PODQUERY, pod_info_json); ++ ++ if (need_refresh[CLUSTER_INFO]) ++ podman_http_fetch(url, INFOQUERY, container_info_json); ++ ++ if (need_refresh[CLUSTER_STATS]) ++ podman_http_fetch(url, STATSQUERY, container_stats_json); ++} ++ ++/* ++ * Refresh instance domain and all values for given clusters. ++ * Algorith used is designed to produce a union of containers ++ * across all podman invocations (using root or rootless); so ++ * we make requests on /run/podman socket first, then iterate ++ * over all /run/user/.../podman sockets. ++ */ ++void ++podman_refresh(unsigned int need_refresh[]) ++{ ++ static const char sockpath[] = "podman/podman.sock"; ++ pmInDom containers = INDOM(CONTAINER_INDOM); ++ pmInDom pods = INDOM(POD_INDOM); ++ char dirpath[MAXPATHLEN]; ++ char path[MAXPATHLEN]; ++ DIR *rundir; ++ struct dirent *entry; ++ ++ if (need_refresh[CLUSTER_STATS] || need_refresh[CLUSTER_INFO]) ++ pmdaCacheOp(containers, PMDA_CACHE_INACTIVE); ++ if (need_refresh[CLUSTER_POD]) ++ pmdaCacheOp(pods, PMDA_CACHE_INACTIVE); ++ ++ /* first the root socket */ ++ pmsprintf(path, MAXPATHLEN, "%s/%s", podman_rundir, sockpath); ++ podman_refresh_socket(path, need_refresh); ++ ++ /* then any user sockets (rootless) */ ++ pmsprintf(dirpath, MAXPATHLEN, "%s/user", podman_rundir); ++ if ((rundir = opendir(dirpath)) == NULL) ++ return; ++ while ((entry = readdir(rundir)) != NULL) { ++ char *user = entry->d_name; ++ if (!isdigit(user[0]) || strcmp(user, "0") == 0) ++ continue; ++ pmsprintf(path, MAXPATHLEN, "%s/%s/%s", dirpath, user, sockpath); ++ podman_refresh_socket(path, need_refresh); ++ } ++ closedir(rundir); ++} +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/podman.h pcp-5.3.0/src/pmdas/podman/podman.h +--- pcp-5.3.0.orig/src/pmdas/podman/podman.h 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/podman.h 2021-05-14 13:18:32.125079150 +1000 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018 Red Hat. ++ * Copyright (c) 2018,2021 Red Hat. + * + * 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 +@@ -16,21 +16,20 @@ + + #include "pmapi.h" + #include "pmda.h" +-#include + + typedef struct { + uint32_t name; /* string mapping for name */ + uint32_t command; /* string mapping for running command */ + uint32_t status; /* string mapping for status */ +- int64_t rwsize; +- int64_t rootfssize; +- bool running; +- unsigned int labels; +- uint32_t *labelnames; /* string mappings for label names */ +- uint32_t *labelvalues; /* string mappings for label values */ ++ unsigned int running; ++ uint32_t labelmap; /* string mapping for labels */ ++ unsigned int nlabels; /* number of labels in labelmap */ ++ const char *labels; /* pointer to start of all labels */ ++ uint32_t image; /* string mapping for image name */ ++ uint32_t podid; /* string mapping for pod name */ + } container_info_t; + +-typedef struct container_stats { ++typedef struct { + int64_t net_input; + int64_t net_output; + int64_t block_input; +@@ -41,40 +40,40 @@ typedef struct container_stats { + int64_t mem_usage; + int64_t mem_limit; + double mem_perc; +- int64_t nprocesses; +- uint32_t name; /* string mapping for container name */ ++ uint32_t nprocesses; + } container_stats_t; + +-typedef enum state_flags { ++typedef enum { + STATE_NONE = 0x0, + STATE_INFO = 0x1, + STATE_STATS = 0x2, ++ STATE_POD = 0x4, + } state_flags_t; + +-typedef struct container { +- uint32_t id; /* string mapping for container hash */ +- uint32_t podmap; /* string mapping for pod hash (optional) */ ++typedef struct { + state_flags_t flags; + container_info_t info; + container_stats_t stats; + } container_t; + +-typedef struct pod_info { +- uint32_t id; /* string mapping for pod hash */ +- state_flags_t flags; ++typedef struct { + uint32_t name; /* string mapping for pod name */ + uint32_t cgroup; /* string mapping for cgroup name */ +- uint64_t rwsize; +- uint64_t rootfssize; +- bool running; +- unsigned int labels; +- uint32_t *labelnames; /* string mappings for label names */ +- uint32_t *labelvalues; /* string mappings for label values */ ++ unsigned int running; ++ uint32_t labelmap; /* string mapping for label names */ ++ unsigned int nlabels; /* number of labels in labelmap */ ++ const char *labels; /* pointer to start of all labels */ + uint32_t status; /* string mapping for status info */ +- uint32_t ncontainers; ++ unsigned int ncontainers; + } pod_info_t; + +-enum { ++typedef struct { ++ state_flags_t flags; ++ pod_info_t info; ++} pod_t; ++ ++typedef enum { ++ /* pmID item fields */ + STATS_NET_INPUT = 0, + STATS_NET_OUTPUT = 1, + STATS_BLOCK_INPUT = 2, +@@ -86,26 +85,39 @@ enum { + STATS_MEM_LIMIT = 8, + STATS_MEM_PERC = 9, + STATS_PIDS = 10, +- NUM_CONTAINER_STATS +-}; ++ NUM_CONTAINER_STATS, + +-enum { ++ /* internal fields */ ++ STATS_ID, ++} container_stats_e; ++ ++typedef enum { ++ /* pmID item fields */ + INFO_NAME = 0, + INFO_COMMAND = 1, + INFO_STATUS = 2, +- INFO_RWSIZE = 3, +- INFO_ROOTFSSIZE = 4, + INFO_RUNNING = 5, +- NUM_CONTAINER_INFO +-}; ++ INFO_IMAGE = 6, ++ INFO_POD = 7, ++ NUM_CONTAINER_INFO, ++ ++ /* internal fields */ ++ INFO_ID, ++ INFO_LABELS, ++} container_info_e; + +-enum { ++typedef enum { ++ /* pmID item fields */ + POD_NAME = 0, + POD_CGROUP = 1, + POD_STATUS = 2, + POD_CONTAINERS = 3, +- NUM_POD_INFO +-}; ++ NUM_POD_INFO, ++ ++ /* internal fields */ ++ POD_ID, ++ POD_LABELS, ++} pod_info_e; + + enum { + CLUSTER_STATS = 0, +@@ -123,16 +135,21 @@ enum { + + /* General routines */ + +-extern void podman_context_set_container(int, pmInDom, const char *, int); +-extern container_t *podman_context_container(int); +-extern void podman_context_end(int); +- +-extern void refresh_podman_containers(pmInDom, state_flags_t); +-extern void refresh_podman_container(pmInDom, char *, state_flags_t); +-extern void refresh_podman_pod_info(pmInDom, char *); +-extern void refresh_podman_pods_info(pmInDom); +- ++extern void podman_refresh(unsigned int[]); + extern char *podman_strings_lookup(int); + extern int podman_strings_insert(const char *); + ++/* Parsing routines */ ++ ++extern int podman_parse_init(void); ++extern void podman_parse_end(void); ++ ++/* Instance domains */ ++ ++extern pmdaIndom podman_indomtab[NUM_INDOMS]; ++#define INDOM(x) (podman_indomtab[x].it_indom) ++ ++/* System paths */ ++extern char *podman_rundir; ++ + #endif /* PCP_PODMAN_H */ +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/Remove pcp-5.3.0/src/pmdas/podman/Remove +--- pcp-5.3.0.orig/src/pmdas/podman/Remove 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/Remove 2021-05-14 13:18:32.124079167 +1000 +@@ -1,6 +1,6 @@ + #!/bin/sh + # +-# Copyright (c) 2018 Red Hat. ++# Copyright (c) 2018-2021 Red Hat. + # + # 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 +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/root_podman pcp-5.3.0/src/pmdas/podman/root_podman +--- pcp-5.3.0.orig/src/pmdas/podman/root_podman 2018-11-19 13:48:15.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/root_podman 2021-05-14 13:18:32.125079150 +1000 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018 Red Hat. ++ * Copyright (c) 2018,2021 Red Hat. + * + * 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 +@@ -37,9 +37,9 @@ podman.container { + name PODMAN:1:0 + command PODMAN:1:1 + status PODMAN:1:2 +- rwsize PODMAN:1:3 +- rootfssize PODMAN:1:4 + running PODMAN:1:5 ++ image PODMAN:1:6 ++ pod PODMAN:1:7 + } + + podman.container.stats { +diff -Naurp pcp-5.3.0.orig/src/pmdas/podman/varlink.c pcp-5.3.0/src/pmdas/podman/varlink.c +--- pcp-5.3.0.orig/src/pmdas/podman/varlink.c 2021-02-17 15:27:41.000000000 +1100 ++++ pcp-5.3.0/src/pmdas/podman/varlink.c 1970-01-01 10:00:00.000000000 +1000 +@@ -1,557 +0,0 @@ +-/* +- * Copyright (c) 2018 Red Hat. +- * +- * 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. +- */ +- +-#include "podman.h" +-#include +-#include +-#include +- +-typedef struct varlink { +- int epoll_fd; +- int signal_fd; +- VarlinkConnection *connection; +-} varlink_t; +- +-typedef struct varlink_reply { +- char *error; +- VarlinkObject *parameters; +-} varlink_reply_t; +- +-static inline int +-epoll_control(int epfd, int op, int fd, uint32_t events, void *ptr) +-{ +- struct epoll_event event = {.events = events, .data = {.ptr = ptr}}; +- +- return epoll_ctl(epfd, op, fd, &event); +-} +- +-static varlink_t * +-varlink_connect(void) +-{ +- static varlink_t varlink; +- static int setup; +- sigset_t mask; +- int sts; +- +- if (setup == 0) { +- if ((varlink.epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0) +- return NULL; +- sigemptyset(&mask); +- sigaddset(&mask, SIGTERM); +- sigaddset(&mask, SIGINT); +- sigaddset(&mask, SIGPIPE); +- sigprocmask(SIG_BLOCK, &mask, NULL); +- varlink.signal_fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); +- if (varlink.signal_fd < 0) +- return NULL; +- epoll_control(varlink.epoll_fd, EPOLL_CTL_ADD, varlink.signal_fd, EPOLLIN, NULL); +- setup = 1; +- } +- +- sts = varlink_connection_new(&varlink.connection, "unix:/run/podman/io.podman"); +- if (sts != 0) { +- fprintf(stderr, "Error connecting to varlink %s: %s\n", +- "unix:/run/podman/io.podman", +- varlink_error_string(-sts)); +- return NULL; +- } +- +- return &varlink; +-} +- +-static void +-varlink_disconnect(varlink_t *link) +-{ +- epoll_control(link->epoll_fd, EPOLL_CTL_DEL, +- varlink_connection_get_fd(link->connection), 0, NULL); +- varlink_connection_close(link->connection); +- varlink_connection_free(link->connection); +- link->connection = NULL; +-} +- +-static long +-varlink_reply_callback(VarlinkConnection *connection, const char *error, +- VarlinkObject *parameters, uint64_t flags, void *arg) +-{ +- varlink_reply_t *reply = (varlink_reply_t *)arg; +- +- if (error != NULL) { +- if ((reply->error = strdup(error)) == NULL) +- return -ENOMEM; +- } +- reply->parameters = varlink_object_ref(parameters); +- return 0; +-} +- +-static long +-varlink_connection_wait(varlink_t *link) +-{ +- struct epoll_event event; +- int sts, timeout = -1; +- +- if ((sts = varlink_connection_get_events(link->connection)) < 0) +- return sts; +- +- if ((sts = epoll_control(link->epoll_fd, EPOLL_CTL_ADD, +- varlink_connection_get_fd(link->connection), +- varlink_connection_get_events(link->connection), +- link->connection)) < 0 && errno != EEXIST) +- return sts; +- +- for (;;) { +- sts = epoll_wait(link->epoll_fd, &event, 1, timeout); +- if (sts < 0) { +- if (errno == EINTR) +- continue; +- return -errno; +- } +- if (sts == 0) +- return -ETIMEDOUT; +- if (event.data.ptr == link->connection) { +- epoll_control(link->epoll_fd, EPOLL_CTL_MOD, +- varlink_connection_get_fd(link->connection), +- varlink_connection_get_events(link->connection), +- link->connection); +- break; /* ready */ +- } +- if (event.data.ptr == NULL) { +- struct signalfd_siginfo info; +- long size; +- +- size = read(link->signal_fd, &info, sizeof(info)); +- if (size != sizeof(info)) +- continue; +- pmNotifyErr(LOG_ERR, "podman command interrupted\n"); +- return -EINTR; +- } +- } +- +- if ((sts = varlink_connection_process_events(link->connection, 0)) != 0) +- return sts; +- +- return 0; +-} +- +-static void +-refresh_container_info(VarlinkObject *info, container_info_t *ip) +-{ +- VarlinkArray *args; +- const char *temp; +- size_t bytes, length = 0; +- char cmd[BUFSIZ] = {0}; +- int i, sts, count; +- +- temp = NULL; +- varlink_object_get_string(info, "names", &temp); +- ip->name = temp? podman_strings_insert(temp) : -1; +- +- /* extract the command, stored as an array of strings */ +- sts = varlink_object_get_array(info, "command", &args); +- count = sts < 0? 0 : varlink_array_get_n_elements(args); +- for (i = 0; i < count; i++) { +- temp = NULL; +- varlink_array_get_string(args, i, &temp); +- bytes = temp? strlen(temp) : 0; +- if (bytes > 0 && bytes < sizeof(cmd) - length - 1) { +- strcat(cmd, temp); +- strcat(cmd, " "); +- } +- length += bytes + 1; +- } +- if (length > 0) { +- cmd[length-1] = '\0'; +- ip->command = podman_strings_insert(cmd); +- } else { +- ip->command = -1; +- } +- +- temp = NULL; +- varlink_object_get_string(info, "status", &temp); +- ip->status = temp? podman_strings_insert(temp) : -1; +- varlink_object_get_int(info, "rootfssize", &ip->rootfssize); +- varlink_object_get_int(info, "rwsize", &ip->rwsize); +- varlink_object_get_bool(info, "running", &ip->running); +-} +- +-static int +-varlink_container_info(varlink_t *link, char *name, container_info_t *ip) +-{ +- varlink_reply_t reply = {0}; +- VarlinkObject *info; +- int sts; +- +- if (pmDebugOptions.attr) +- fprintf(stderr, "refresh container info for %s\n", name); +- +- varlink_object_new(&reply.parameters); +- varlink_object_set_string(reply.parameters, "name", name); +- +- sts = varlink_connection_call(link->connection, +- "io.podman.GetContainer", +- reply.parameters, 0, varlink_reply_callback, &reply); +- varlink_object_unref(reply.parameters); +- if (sts != 0) +- return sts; +- +- if ((sts = varlink_connection_wait(link)) < 0) +- goto done; +- +- if (reply.error) { +- if (strcmp(reply.error, "io.podman.NoContainerRunning") != 0) +- fprintf(stderr, "Error: %s %s - %s\n", "io.podman.GetContainer", +- name, reply.error); +- free(reply.error); +- goto done; +- } +- +- sts = varlink_object_get_object(reply.parameters, "container", &info); +- if (sts != 0) +- goto done; +- +- refresh_container_info(info, ip); +- +-done: +- varlink_object_unref(reply.parameters); +- return sts; +-} +- +-static int +-varlink_container_stats(varlink_t *link, char *name, container_stats_t *cp) +-{ +- varlink_reply_t reply = {0}; +- VarlinkObject *stats; +- const char *temp; +- int sts; +- +- if (pmDebugOptions.attr) +- fprintf(stderr, "refresh container stats for %s\n", name); +- +- varlink_object_new(&reply.parameters); +- varlink_object_set_string(reply.parameters, "name", name); +- +- sts = varlink_connection_call(link->connection, +- "io.podman.GetContainerStats", +- reply.parameters, 0, varlink_reply_callback, &reply); +- varlink_object_unref(reply.parameters); +- if (sts != 0) +- return sts; +- +- if ((sts = varlink_connection_wait(link)) < 0) +- goto done; +- +- if (reply.error) { +- if (strcmp(reply.error, "io.podman.NoContainerRunning") != 0) +- fprintf(stderr, "Error: %s %s - %s\n", "io.podman.GetContainerStats", +- name, reply.error); +- free(reply.error); +- goto done; +- } +- +- sts = varlink_object_get_object(reply.parameters, "container", &stats); +- if (sts != 0) +- goto done; +- varlink_object_get_int(stats, "net_input", &cp->net_input); +- varlink_object_get_int(stats, "net_output", &cp->net_output); +- varlink_object_get_int(stats, "block_input", &cp->block_input); +- varlink_object_get_int(stats, "block_output", &cp->block_output); +- varlink_object_get_float(stats, "cpu", &cp->cpu); +- varlink_object_get_int(stats, "cpu_nano", &cp->cpu_nano); +- varlink_object_get_int(stats, "system_nano", &cp->system_nano); +- varlink_object_get_int(stats, "mem_usage", &cp->mem_usage); +- varlink_object_get_int(stats, "mem_limit", &cp->mem_limit); +- varlink_object_get_float(stats, "mem_perc", &cp->mem_perc); +- varlink_object_get_int(stats, "pids", &cp->nprocesses); +- varlink_object_get_string(stats, "name", &temp); +- cp->name = podman_strings_insert(temp); +- +-done: +- varlink_object_unref(reply.parameters); +- return sts; +-} +- +-void +-refresh_podman_container(pmInDom indom, char *name, state_flags_t flags) +-{ +- container_t *cp; +- varlink_t *link; +- int sts; +- +- if (pmDebugOptions.attr) +- fprintf(stderr, "refresh podman container %s\n", name); +- +- if ((link = varlink_connect()) == NULL) +- return; +- +- if ((sts = pmdaCacheLookupName(indom, name, NULL, (void **)&cp)) < 0) { +- if ((cp = calloc(1, sizeof(container_t))) == NULL) +- return; +- cp->id = podman_strings_insert(name); +- if (pmDebugOptions.attr) +- fprintf(stderr, "adding container %s (%u)\n", name, cp->id); +- } +- pmdaCacheStore(indom, PMDA_CACHE_ADD, name, (void *)cp); +- +- if (flags & STATE_INFO) { +- if ((sts = varlink_container_info(link, name, &cp->info)) == 0) +- cp->flags |= STATE_INFO; +- } +- if (flags & STATE_STATS) { +- if ((sts = varlink_container_stats(link, name, &cp->stats)) == 0) +- cp->flags |= STATE_STATS; +- } +-} +- +-static int +-varlink_container_list(varlink_t *link, pmInDom indom) +-{ +- container_t *cp; +- varlink_reply_t reply = {0}; +- VarlinkObject *state; +- VarlinkArray *list; +- const char *id; +- int i, sts, count = 0; +- +- if (pmDebugOptions.attr) +- fprintf(stderr, "list containers\n"); +- +- sts = varlink_connection_call(link->connection, "io.podman.ListContainers", +- reply.parameters, 0, varlink_reply_callback, &reply); +- if (sts != 0) +- return sts; +- +- if ((sts = varlink_connection_wait(link)) < 0) +- goto done; +- +- if (reply.error) { +- fprintf(stderr, "Error: %s - %s\n", "io.podman.ListContainers", +- reply.error); +- free(reply.error); +- goto done; +- } +- +- sts = varlink_object_get_array(reply.parameters, "containers", &list); +- if (sts < 0) +- goto done; +- +- count = varlink_array_get_n_elements(list); +- for (i = 0; i < count; i++) { +- varlink_array_get_object(list, i, &state); +- varlink_object_get_string(state, "id", &id); +- if ((sts = pmdaCacheLookupName(indom, id, NULL, (void **)&cp)) < 0) { +- if ((cp = calloc(1, sizeof(container_t))) == NULL) +- continue; +- cp->id = podman_strings_insert(id); +- if (pmDebugOptions.attr) +- fprintf(stderr, "adding container %s (%u)\n", id, cp->id); +- } +- pmdaCacheStore(indom, PMDA_CACHE_ADD, id, (void *)cp); +- refresh_container_info(state, &cp->info); +- cp->flags |= STATE_INFO; +- } +- +-done: +- varlink_object_unref(reply.parameters); +- return count; +-} +- +-static int +-varlink_pod_list(varlink_t *link, pmInDom indom) +-{ +- pod_info_t *pp; +- varlink_reply_t reply = {0}; +- VarlinkObject *state; +- VarlinkArray *list; +- const char *id, *temp; +- int i, sts, count = 0; +- +- if (pmDebugOptions.attr) +- fprintf(stderr, "list pods\n"); +- +- sts = varlink_connection_call(link->connection, "io.podman.ListPods", +- reply.parameters, 0, varlink_reply_callback, &reply); +- if (sts != 0) +- return sts; +- +- if ((sts = varlink_connection_wait(link)) < 0) +- goto done; +- +- if (reply.error) { +- fprintf(stderr, "Error: %s - %s\n", "io.podman.ListPods", reply.error); +- free(reply.error); +- goto done; +- } +- +- sts = varlink_object_get_array(reply.parameters, "pods", &list); +- if (sts < 0) +- goto done; +- +- count = varlink_array_get_n_elements(list); +- for (i = 0; i < count; i++) { +- varlink_array_get_object(list, i, &state); +- varlink_object_get_string(state, "id", &id); +- if ((sts = pmdaCacheLookupName(indom, id, NULL, (void **)&pp)) < 0) { +- if ((pp = calloc(1, sizeof(pod_info_t))) == NULL) +- continue; +- pp->id = podman_strings_insert(id); +- if (pmDebugOptions.attr) +- fprintf(stderr, "adding pod %s (%u)\n", id, pp->id); +- } +- pmdaCacheStore(indom, PMDA_CACHE_ADD, id, (void *)pp); +- +- temp = NULL; +- varlink_object_get_string(state, "name", &temp); +- pp->name = temp? podman_strings_insert(temp) : -1; +- temp = NULL; +- varlink_object_get_string(state, "cgroup", &temp); +- pp->cgroup = temp? podman_strings_insert(temp) : -1; +- temp = NULL; +- varlink_object_get_string(state, "status", &temp); +- pp->status = temp? podman_strings_insert(temp) : -1; +- temp = NULL; +- varlink_object_get_string(state, "numberofcontainers", &temp); +- pp->ncontainers = temp ? atoi(temp) : 0; +- +- pp->flags |= STATE_INFO; +- } +- +-done: +- varlink_object_unref(reply.parameters); +- return count; +-} +- +-void +-refresh_podman_containers(pmInDom indom, state_flags_t flags) +-{ +- container_t *cp; +- varlink_t *varlink; +- char *name; +- int inst, sts; +- +- pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); +- +- if ((varlink = varlink_connect()) == NULL) +- return; +- +- /* extract list of containers - this also provides all container 'info' */ +- sts = varlink_container_list(varlink, indom); +- if ((sts == 0) || (!(flags & STATE_STATS))) +- goto done; +- +- /* walk active entries, refreshing container 'stats' */ +- for (pmdaCacheOp(indom, PMDA_CACHE_WALK_REWIND);;) { +- if ((inst = pmdaCacheOp(indom, PMDA_CACHE_WALK_NEXT)) < 0) +- break; +- if (!pmdaCacheLookup(indom, inst, &name, (void **)&cp) || !cp) +- continue; +- if ((sts = varlink_container_stats(varlink, name, &cp->stats)) == 0) +- cp->flags |= STATE_STATS; +- } +- +-done: +- varlink_disconnect(varlink); +-} +- +-static int +-varlink_pod_info(varlink_t *link, char *name, pod_info_t *pp) +-{ +- varlink_reply_t reply = {0}; +- VarlinkObject *info; +- const char *temp; +- int sts; +- +- if (pmDebugOptions.attr) +- fprintf(stderr, "refresh pod info for %s\n", name); +- +- varlink_object_new(&reply.parameters); +- varlink_object_set_string(reply.parameters, "name", name); +- +- sts = varlink_connection_call(link->connection, +- "io.podman.GetPod", +- reply.parameters, 0, varlink_reply_callback, &reply); +- varlink_object_unref(reply.parameters); +- if (sts != 0) +- return sts; +- +- if ((sts = varlink_connection_wait(link)) < 0) +- goto done; +- +- if (reply.error) { +- if (strcmp(reply.error, "io.podman.NoPodRunning") != 0) +- fprintf(stderr, "Error: %s %s - %s\n", "io.podman.GetPod", +- name, reply.error); +- free(reply.error); +- goto done; +- } +- +- sts = varlink_object_get_object(reply.parameters, "container", &info); +- if (sts != 0) +- goto done; +- temp = NULL; +- varlink_object_get_string(info, "name", &temp); +- pp->name = temp? podman_strings_insert(temp) : -1; +- temp = NULL; +- varlink_object_get_string(info, "cgroup", &temp); +- pp->cgroup = temp? podman_strings_insert(temp) : -1; +- temp = NULL; +- varlink_object_get_string(info, "status", &temp); +- pp->status = temp? podman_strings_insert(temp) : -1; +- temp = NULL; +- varlink_object_get_string(info, "numberofcontainers", &temp); +- pp->ncontainers = temp? atoi(temp) : 0; +- +-done: +- varlink_object_unref(reply.parameters); +- return sts; +-} +- +-void +-refresh_podman_pod_info(pmInDom indom, char *name) +-{ +- pod_info_t *pp; +- varlink_t *link; +- int sts; +- +- if (pmDebugOptions.attr) +- fprintf(stderr, "refresh podman pod %s\n", name); +- +- if ((link = varlink_connect()) == NULL) +- return; +- +- if ((sts = pmdaCacheLookupName(indom, name, NULL, (void **)&pp)) < 0) { +- if ((pp = calloc(1, sizeof(pod_info_t))) == NULL) +- return; +- pp->id = podman_strings_insert(name); +- if (pmDebugOptions.attr) +- fprintf(stderr, "adding pod %s (%u)\n", name, pp->id); +- } +- pmdaCacheStore(indom, PMDA_CACHE_ADD, name, (void *)pp); +- +- if ((sts = varlink_pod_info(link, name, pp)) == 0) +- pp->flags |= STATE_INFO; +-} +- +-void +-refresh_podman_pods_info(pmInDom indom) +-{ +- varlink_t *varlink; +- +- pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); +- +- if ((varlink = varlink_connect()) == NULL) +- return; +- +- varlink_pod_list(varlink, indom); +- +- varlink_disconnect(varlink); +-} +diff -Naurp pcp-5.3.0.orig/src/selinux/pcpupstream.te.in pcp-5.3.0/src/selinux/pcpupstream.te.in +--- pcp-5.3.0.orig/src/selinux/pcpupstream.te.in 2021-03-23 12:33:35.000000000 +1100 ++++ pcp-5.3.0/src/selinux/pcpupstream.te.in 2021-05-14 13:18:32.125079150 +1000 +@@ -124,6 +124,9 @@ allow init_t system_cronjob_t:dbus send_ + #type=AVC msg=audit(XXX.4): avc: denied { execute execute_no_trans open read } for pid=YYYY comm="pmdaX" name="/" dev="tracefs" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:user_home_t:s0 tclass=file permissive=0 + allow pcp_pmcd_t user_home_t:file { execute execute_no_trans }; + ++#type=AVC msg=audit(XXX.90): avc: denied { getattr write } for pid=1514 comm="pmdapodman" path="/run/user/N/podman/podman.sock" dev="tmpfs" ino=228 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=sock_file permissive=0 ++allow pcp_pmcd_t user_tmp_t:sock_file { getattr write }; ++ + #type=AVC msg=audit(XXX.6): avc: denied { append getattr ioctl open read write } for pid=YYYY comm="pmdaX" name="/" dev="tracefs" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:debugfs_t:s0 tclass=file permissive=0 + allow pcp_pmcd_t debugfs_t:file { append getattr ioctl open read write }; + diff --git a/SPECS/pcp.spec b/SPECS/pcp.spec index 03e8e24..36c85a4 100644 --- a/SPECS/pcp.spec +++ b/SPECS/pcp.spec @@ -1,6 +1,6 @@ Name: pcp Version: 5.3.0 -Release: 3%{?dist} +Release: 4%{?dist} Summary: System-level performance monitoring and performance management License: GPLv2+ and LGPLv2+ and CC-BY URL: https://pcp.io @@ -9,6 +9,9 @@ URL: https://pcp.io Source0: %{artifactory}/pcp-source-release/pcp-%{version}.src.tar.gz Patch000: redhat-bugzilla-1950263.patch +Patch001: redhat-bugzilla-1615742.patch +Patch002: redhat-bugzilla-1615718.patch +Patch003: redhat-bugzilla-1956608.patch %if 0%{?fedora} >= 26 || 0%{?rhel} > 7 %global __python2 python2 @@ -44,12 +47,7 @@ Patch000: redhat-bugzilla-1950263.patch %endif %endif -# libvarlink and pmdapodman -%if 0%{?fedora} >= 28 || 0%{?rhel} > 7 %global disable_podman 0 -%else -%global disable_podman 1 -%endif # libchan, libhdr_histogram and pmdastatsd %if 0%{?fedora} >= 29 || 0%{?rhel} > 7 @@ -243,9 +241,6 @@ BuildRequires: python3-setuptools BuildRequires: ncurses-devel BuildRequires: readline-devel BuildRequires: cyrus-sasl-devel -%if !%{disable_podman} -BuildRequires: libvarlink-devel -%endif %if !%{disable_statsd} # ragel unavailable on RHEL8 %if 0%{?rhel} == 0 @@ -292,8 +287,6 @@ Requires: pcp-libs = %{version}-%{release} Requires: pcp-selinux = %{version}-%{release} %endif -Requires: pcp-libs = %{version}-%{release} - %global _confdir %{_sysconfdir}/pcp %global _logsdir %{_localstatedir}/log/pcp %global _pmnsdir %{_localstatedir}/lib/pcp/pmns @@ -893,12 +886,10 @@ License: GPLv2+ Summary: Performance Co-Pilot (PCP) metrics for podman containers URL: https://pcp.io Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} -Requires: libvarlink -BuildRequires: libvarlink-devel %description pmda-podman This package contains the PCP Performance Metrics Domain Agent (PMDA) for -collecting podman container and pod statistics through libvarlink. +collecting podman container and pod statistics via the podman REST API. %endif %if !%{disable_statsd} @@ -2250,6 +2241,9 @@ updated policy package. %prep %setup -q %patch000 -p1 +%patch001 -p1 +%patch002 -p1 +%patch003 -p1 %build # fix up build version @@ -3311,6 +3305,11 @@ PCP_LOG_DIR=%{_logsdir} %files zeroconf -f pcp-zeroconf-files.rpm %changelog +* Fri May 14 2021 Nathan Scott - 5.3.0-4 +- Improve pmchart duplicate archive diagnostics (BZ 1615718) +- Save pmchart users prefered archive locations (BZ 1615742) +- Remove libvarlink dependency from podman PMDA (BZ 1956608) + * Thu Apr 22 2021 Nathan Scott - 5.3.0-3 - Correct pcp-testsuite file permissions (BZ 1922040) @@ -3319,6 +3318,7 @@ PCP_LOG_DIR=%{_logsdir} * Fri Apr 16 2021 Nathan Scott - 5.3.0-1 - Allow pcp-atop to filter processes on state (BZ 1807046) +- Dynamically adjust the pmproxy open file limit (BZ 1954711) - Rebase to a more recent upstream version of PCP (BZ 1922040) - PCP scalability and memory footprint improvements (BZ 1942292)