From 11e6bb08f8385f191db3cbd4a00efac9ad6129aa Mon Sep 17 00:00:00 2001 From: Python Maint Date: Wed, 28 Jun 2023 11:42:02 +0200 Subject: [PATCH 01/26] Rebuilt for Python 3.12 --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 18a7eea..53fe036 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.11.6 -Release: 1%{?dist} +Release: 2%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -409,6 +409,9 @@ run_all_tests %license pyagentx_LICENSE.txt %changelog +* Wed Jun 28 2023 Python Maint - 0.11.6-2 +- Rebuilt for Python 3.12 + * Wed Jun 21 2023 Michal Pospisil - 0.11.6-1 - Rebased to the latest upstream sources (see CHANGELOG.md) - Updated pcs-web-ui From 2d244b8d72130f12800523bc895a137d01c0a2b1 Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Mon, 10 Jul 2023 12:51:55 -0400 Subject: [PATCH 02/26] Fix build with Python 3.12 Patch submitted upstream: https://github.com/ClusterLabs/pcs/pull/713 --- ...tatransferObjectTest-for-Python-3.12.patch | 39 +++++++++++++++++++ pcs.spec | 3 ++ 2 files changed, 42 insertions(+) create mode 100644 0001-Fix-DatatransferObjectTest-for-Python-3.12.patch diff --git a/0001-Fix-DatatransferObjectTest-for-Python-3.12.patch b/0001-Fix-DatatransferObjectTest-for-Python-3.12.patch new file mode 100644 index 0000000..0792a4d --- /dev/null +++ b/0001-Fix-DatatransferObjectTest-for-Python-3.12.patch @@ -0,0 +1,39 @@ +From c878e1d06d834f0beb5579158ea5b98c42965058 Mon Sep 17 00:00:00 2001 +From: Yaakov Selkowitz +Date: Mon, 10 Jul 2023 12:56:41 -0400 +Subject: [PATCH] Fix DatatransferObjectTest for Python 3.12 + +This fixes a test error when run with Python 3.12: +``` +Traceback (most recent call last): + File "pcs_test/tier0/common/interface/test_dto.py", line 41, in test_has_all_subclasses_are_dataclasses + _import_all(pcs.__path__) + File "pcs_test/tier0/common/interface/test_dto.py", line 31, in _import_all + loader.find_module(module_name).load_module(module_name) + ^^^^^^^^^^^^^^^^^^ +AttributeError: 'FileFinder' object has no attribute 'find_module' +``` +Instead, use the spec-based APIs introduced in 3.4: + +https://docs.python.org/3.12/library/importlib.html#importlib.machinery.FileFinder +https://docs.python.org/3.12/library/importlib.html#importlib.machinery.ModuleSpec +--- + pcs_test/tier0/common/interface/test_dto.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pcs_test/tier0/common/interface/test_dto.py b/pcs_test/tier0/common/interface/test_dto.py +index 4c3dcb8b..977f35c9 100644 +--- a/pcs_test/tier0/common/interface/test_dto.py ++++ b/pcs_test/tier0/common/interface/test_dto.py +@@ -28,7 +28,7 @@ def _import_all(_path): + if module_name.startswith("_pcs.snmp."): + continue + del is_pkg +- loader.find_module(module_name).load_module(module_name) ++ loader.find_spec(module_name).loader.load_module(module_name) + + + def _all_subclasses(cls): +-- +2.41.0 + diff --git a/pcs.spec b/pcs.spec index 53fe036..0e9b28a 100644 --- a/pcs.spec +++ b/pcs.spec @@ -48,6 +48,9 @@ Source101: https://github.com/ClusterLabs/pcs-web-ui/releases/download/%{ui_comm # pcs patches: <= 200 # Patch0: name.patch +# https://github.com/ClusterLabs/pcs/pull/713 +Patch0: 0001-Fix-DatatransferObjectTest-for-Python-3.12.patch + # ui patches: >200 # Patch201: name-web-ui.patch From d102aae88e73826d3efdc1c7a56e649d219b3054 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 20 Jul 2023 18:51:05 +0000 Subject: [PATCH 03/26] Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 0e9b28a..30180fe 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.11.6 -Release: 2%{?dist} +Release: 3%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -412,6 +412,9 @@ run_all_tests %license pyagentx_LICENSE.txt %changelog +* Thu Jul 20 2023 Fedora Release Engineering - 0.11.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + * Wed Jun 28 2023 Python Maint - 0.11.6-2 - Rebuilt for Python 3.12 From 3a06ce659fefdbc9876f96e91b6e19303f798d0b Mon Sep 17 00:00:00 2001 From: Michal Pospisil Date: Fri, 19 Jan 2024 13:39:10 +0100 Subject: [PATCH 04/26] pcs-0.11.7-1 - Rebased to the latest upstream sources (see CHANGELOG.md) - Updated pcs-web-ui to 0.1.18 - TLS cipher setting in pcsd now follows system-wide crypto policies by default - Added cockpit-pcs-web-ui subpackage that adds pcs-web-ui as a Cockpit application - Removed BuildRequires: python3-distro - was used to bundle dateutil - Replaced STI tests with fmf tests for gating - Change to prepare-env.sh script for rpm 4.19+ that creates SPECPARTS directories - Workaround used for distro in autotools --- .fmf/version | 1 + .gitignore | 3 + ...tatransferObjectTest-for-Python-3.12.patch | 39 ------ gating.fmf | 48 +++++++ ...-AppStream-metainfo-more-descriptive.patch | 82 +++++++++++ pcs.spec | 130 +++++++++++++----- prepare-env.sh | 18 +++ sources | 6 +- tests/tests.yml | 72 ---------- 9 files changed, 250 insertions(+), 149 deletions(-) create mode 100644 .fmf/version delete mode 100644 0001-Fix-DatatransferObjectTest-for-Python-3.12.patch create mode 100644 gating.fmf create mode 100644 make-AppStream-metainfo-more-descriptive.patch create mode 100755 prepare-env.sh delete mode 100644 tests/tests.yml diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/.gitignore b/.gitignore index 9ed2ce5..99144f3 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,6 @@ /pcs-web-ui-node-modules-0.1.17.tar.xz /pcs-web-ui-0.1.17.tar.gz /dacite-1.8.1.tar.gz +/pcs-0.11.7.tar.gz +/pcs-web-ui-0.1.18.tar.gz +/pcs-web-ui-node-modules-0.1.18.tar.xz diff --git a/0001-Fix-DatatransferObjectTest-for-Python-3.12.patch b/0001-Fix-DatatransferObjectTest-for-Python-3.12.patch deleted file mode 100644 index 0792a4d..0000000 --- a/0001-Fix-DatatransferObjectTest-for-Python-3.12.patch +++ /dev/null @@ -1,39 +0,0 @@ -From c878e1d06d834f0beb5579158ea5b98c42965058 Mon Sep 17 00:00:00 2001 -From: Yaakov Selkowitz -Date: Mon, 10 Jul 2023 12:56:41 -0400 -Subject: [PATCH] Fix DatatransferObjectTest for Python 3.12 - -This fixes a test error when run with Python 3.12: -``` -Traceback (most recent call last): - File "pcs_test/tier0/common/interface/test_dto.py", line 41, in test_has_all_subclasses_are_dataclasses - _import_all(pcs.__path__) - File "pcs_test/tier0/common/interface/test_dto.py", line 31, in _import_all - loader.find_module(module_name).load_module(module_name) - ^^^^^^^^^^^^^^^^^^ -AttributeError: 'FileFinder' object has no attribute 'find_module' -``` -Instead, use the spec-based APIs introduced in 3.4: - -https://docs.python.org/3.12/library/importlib.html#importlib.machinery.FileFinder -https://docs.python.org/3.12/library/importlib.html#importlib.machinery.ModuleSpec ---- - pcs_test/tier0/common/interface/test_dto.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pcs_test/tier0/common/interface/test_dto.py b/pcs_test/tier0/common/interface/test_dto.py -index 4c3dcb8b..977f35c9 100644 ---- a/pcs_test/tier0/common/interface/test_dto.py -+++ b/pcs_test/tier0/common/interface/test_dto.py -@@ -28,7 +28,7 @@ def _import_all(_path): - if module_name.startswith("_pcs.snmp."): - continue - del is_pkg -- loader.find_module(module_name).load_module(module_name) -+ loader.find_spec(module_name).loader.load_module(module_name) - - - def _all_subclasses(cls): --- -2.41.0 - diff --git a/gating.fmf b/gating.fmf new file mode 100644 index 0000000..f452957 --- /dev/null +++ b/gating.fmf @@ -0,0 +1,48 @@ +summary: PCS gating test plan +description: Runs upstream tier0, tier1 and smoke tests + +discover: + how: shell + dist-git-source: true + tests: + # Workaround until tmt supports patching sources + - name: Patch sources and run autotools + test: ./prepare-env.sh + duration: 30m + - name: Tier 0 tests + test: ./builddir/pcs-*/pcs_test/suite --tier0 -v --vanilla --installed + duration: 10m + - name: Tier 1 tests + test: ./builddir/pcs-*/pcs_test/suite --tier1 -v --vanilla --installed + duration: 2h + - name: Smoke tests + test: | + systemctl start pcsd + ./builddir/pcs-*/pcs_test/smoke.sh + duration: 10m +prepare: + - name: Install packages + how: install + package: + - autoconf + - automake + - make + - rpm-build + - ruby-devel + - git-core + - booth-site + - fence-agents-apc + - fence-agents-ipmilan + - fence-agents-scsi + - fence-virt + - openssl + - pcs + - pcs-snmp + - python3-pip + - python3-setuptools_scm + - python3-wheel + - rubygem-json + - rubygem-test-unit + - wget +execute: + how: tmt diff --git a/make-AppStream-metainfo-more-descriptive.patch b/make-AppStream-metainfo-more-descriptive.patch new file mode 100644 index 0000000..f9dd2a2 --- /dev/null +++ b/make-AppStream-metainfo-more-descriptive.patch @@ -0,0 +1,82 @@ +From 9923d48095ac7a1376b108a0a3e722d3090fcea6 Mon Sep 17 00:00:00 2001 +From: Michal Pospisil +Date: Thu, 18 Jan 2024 16:52:59 +0100 +Subject: [PATCH] make AppStream metainfo more descriptive + +--- + ...g.clusterlabs.cockpit_pcs_web_ui.metainfo.xml | 16 ++++++++++++++++ + .../app/org.clusterlabs.pcs_web_ui.metainfo.xml | 16 ---------------- + packages/app/package-lock.json | 4 ++-- + 3 files changed, 18 insertions(+), 18 deletions(-) + create mode 100644 packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml + delete mode 100644 packages/app/org.clusterlabs.pcs_web_ui.metainfo.xml + +diff --git a/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml b/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml +new file mode 100644 +index 00000000..a27525a9 +--- /dev/null ++++ b/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml +@@ -0,0 +1,16 @@ ++ ++ ++ org.clusterlabs.cockpit_pcs_web_ui ++ CC0-1.0 ++ HA Cluster Management ++ Manage Pacemaker based clusters ++ ++

++ Application for managing Pacemaker based clusters. Uses Pacemaker/Corosync ++ Configuration System (pcs) in the background. ++

++
++ cockpit.desktop ++ ha-cluster ++ https://github.com/ClusterLabs/pcs-web-ui ++
+diff --git a/packages/app/org.clusterlabs.pcs_web_ui.metainfo.xml b/packages/app/org.clusterlabs.pcs_web_ui.metainfo.xml +deleted file mode 100644 +index 83add879..00000000 +--- a/packages/app/org.clusterlabs.pcs_web_ui.metainfo.xml ++++ /dev/null +@@ -1,16 +0,0 @@ +- +- +- org.clusterlabs.pcs_web_ui +- CC0-1.0 +- Pcs Web UI +- Manage pacemaker based clusters. +- +-

+- Pcs Web UI is an application that allows you to easily view, modify and +- create pacemaker based clusters. +-

+-
+- cockpit.desktop +- ha-cluster +-
+- +diff --git a/packages/app/package-lock.json b/packages/app/package-lock.json +index 4bf1e89e..2f4049a5 100644 +--- a/packages/app/package-lock.json ++++ b/packages/app/package-lock.json +@@ -3830,7 +3830,7 @@ + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001563", +- "resolved": "https://repository.engineering.redhat.com/nexus/repository/registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", ++ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", + "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", + "dev": true, + "funding": [ +@@ -12590,7 +12590,7 @@ + }, + "caniuse-lite": { + "version": "1.0.30001563", +- "resolved": "https://repository.engineering.redhat.com/nexus/repository/registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", ++ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", + "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", + "dev": true + }, +-- +2.43.0 + diff --git a/pcs.spec b/pcs.spec index 30180fe..ef43a4e 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs -Version: 0.11.6 -Release: 3%{?dist} +Version: 0.11.7 +Release: 1%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -17,12 +17,10 @@ BuildArch: noarch %global pcs_source_name %{name}-%{version_or_commit} # ui_commit can be determined by hash, tag or branch -%global ui_commit 0.1.17 -%global ui_modules_version 0.1.17 +%global ui_commit 0.1.18 +%global ui_modules_version 0.1.18 %global ui_src_name pcs-web-ui-%{ui_commit} -%global pcs_snmp_pkg_name pcs-snmp - %global pyagentx_version 0.4.pcs.2 %global dacite_version 1.8.1 @@ -30,6 +28,13 @@ BuildArch: noarch %global pcs_bundled_dir pcs_bundled %global pcsd_public_dir pcsd/public +%global ui_build_dir_standalone build_standalone +%global ui_build_dir_cockpit build_cockpit +%global ui_cockpit_dest ha-cluster +%global ui_appstream_metainfo org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml + +%global pkg_pcs_snmp pcs-snmp +%global pkg_cockpit_ha_cluster cockpit-ha-cluster # prepend v for folder in GitHub link when using tagged tarball %if "%{version}" == "%{version_or_commit}" @@ -48,11 +53,9 @@ Source101: https://github.com/ClusterLabs/pcs-web-ui/releases/download/%{ui_comm # pcs patches: <= 200 # Patch0: name.patch -# https://github.com/ClusterLabs/pcs/pull/713 -Patch0: 0001-Fix-DatatransferObjectTest-for-Python-3.12.patch - # ui patches: >200 # Patch201: name-web-ui.patch +Patch201: make-AppStream-metainfo-more-descriptive.patch # git for patches BuildRequires: git-core @@ -73,8 +76,8 @@ BuildRequires: python3-lxml # for building bundled python packages BuildRequires: python3-wheel # for bundled python dateutil +# dateutil was unbundled in Fedora but our autotools still check for it BuildRequires: python3-setuptools_scm -BuildRequires: python3-distro # ruby and gems for pcsd BuildRequires: ruby >= 2.5.0 BuildRequires: ruby-devel @@ -106,11 +109,7 @@ BuildRequires: pam BuildRequires: nss-tools # for building web ui -%if 0%{?fedora} < 37 -BuildRequires: npm -%else BuildRequires: nodejs-npm -%endif # cluster stack packages for pkg-config BuildRequires: booth @@ -121,6 +120,10 @@ BuildRequires: pacemaker-libs-devel >= %{required_pacemaker_version} BuildRequires: resource-agents BuildRequires: sbd +# for validating cockpit-ha-cluster metainfo +BuildRequires: libappstream-glib + + # python and libraries for pcs, setuptools for pcs entrypoint Requires: python3 >= 3.9 Requires: python3-cryptography @@ -171,12 +174,9 @@ Requires: nss-tools Provides: bundled(dacite) = %{dacite_version} -%description -pcs is a corosync and pacemaker configuration tool. It permits users to -easily view, modify and create pacemaker based clusters. -# pcs-snmp package definition -%package -n %{pcs_snmp_pkg_name} +# pcs-snmp subpackage definition +%package -n %{pkg_pcs_snmp} Group: System Environment/Base Summary: Pacemaker cluster SNMP agent # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses @@ -195,8 +195,31 @@ Requires: net-snmp Provides: bundled(pyagentx) = %{pyagentx_version} -%description -n %{pcs_snmp_pkg_name} -SNMP agent that provides information about pacemaker cluster to the master agent (snmpd) +# cockpit-ha-cluster subpackage definition +%package -n %{pkg_cockpit_ha_cluster} +Group: System Environment/Base +Summary: Cockpit application for managing Pacemaker based clusters +License: GPL-2.0-only AND CC0-1.0 +URL: https://github.com/ClusterLabs/pcs-web-ui + +BuildRequires: make +BuildRequires: npm + +Requires: pcs = %{version}-%{release} +Requires: cockpit-bridge + + +%description +pcs is a corosync and pacemaker configuration tool. It permits users to +easily view, modify and create pacemaker based clusters. + +%description -n %{pkg_pcs_snmp} +SNMP agent that provides information about pacemaker cluster to the master agent +(snmpd). + +%description -n %{pkg_cockpit_ha_cluster} +Cockpit application for managing Pacemaker based clusters. Uses +Pacemaker/Corosync Configuration System (pcs) in the background. %prep @@ -263,34 +286,55 @@ mkdir -p %{pcs_bundled_dir}/src cp -f %SOURCE41 rpm/ cp -f %SOURCE42 rpm/ + %build %define debug_package %{nil} # Booth authfile fix support -# Fedora 35, 36: set and unset # Fedora 37, 38, ELN = RHEL10: unset only # Fedora 39+: no booth build options -%if 0%{?fedora} <= 36 - %define booth_build_options --enable-booth-enable-authfile-set --enable-booth-enable-authfile-unset -%elif 0%{?fedora} <= 38 || 0%{?eln} +%if 0%{?fedora} <= 38 || 0%{?eln} %define booth_build_options --enable-booth-enable-authfile-unset %endif ./autogen.sh -%{configure} --enable-local-build --enable-use-local-cache-only --enable-individual-bundling %{?booth_build_options} --with-pcs-lib-dir="%{_prefix}/lib" PYTHON=%{__python3} +%{configure} --enable-local-build --enable-use-local-cache-only \ + --enable-individual-bundling %{?booth_build_options} \ + --with-pcsd-default-cipherlist='PROFILE=SYSTEM' \ + --with-pcs-lib-dir="%{_prefix}/lib" PYTHON=%{__python3} make all # build pcs-web-ui -BUILD_USE_CURRENT_NODE_MODULES=true make -C %{_builddir}/%{ui_src_name} build +export BUILD_USE_CURRENT_NODE_MODULES=true + +## standalone +export BUILD_DIR=%{_builddir}/%{ui_src_name}/%{ui_build_dir_standalone} +make -C %{_builddir}/%{ui_src_name} build + +## cockpit +export BUILD_DIR=%{_builddir}/%{ui_src_name}/%{ui_build_dir_cockpit} +export BUILD_FOR_COCKPIT=true +make -C %{_builddir}/%{ui_src_name} build + %install rm -rf $RPM_BUILD_ROOT pwd -%make_install -# install pcs-web-ui -make -C %{_builddir}/%{ui_src_name} _install PCSD_DIR=${RPM_BUILD_ROOT}%{_prefix}/lib/pcsd +%make_install +# install standalone pcs-web-ui +cp -r %{_builddir}/%{ui_src_name}/%{ui_build_dir_standalone} \ + ${RPM_BUILD_ROOT}%{_prefix}/lib/%{pcsd_public_dir}/ui + +# install cockpit pcs-web-ui +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/cockpit/%{ui_cockpit_dest} +mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/metainfo +cp -r %{_builddir}/%{ui_src_name}/%{ui_build_dir_cockpit}/* \ + ${RPM_BUILD_ROOT}%{_datadir}/cockpit/%{ui_cockpit_dest} + +cp -r %{_builddir}/%{ui_src_name}/packages/app/%{ui_appstream_metainfo} \ + ${RPM_BUILD_ROOT}%{_datadir}/metainfo/ # prepare license files cp %{pcs_bundled_dir}/src/pyagentx-*/LICENSE.txt pyagentx_LICENSE.txt @@ -300,7 +344,11 @@ cp %{pcs_bundled_dir}/src/pyagentx-*/README.md pyagentx_README.md cp %{pcs_bundled_dir}/src/dacite-*/LICENSE dacite_LICENSE cp %{pcs_bundled_dir}/src/dacite-*/README.md dacite_README.md + %check +# Run validation of cockpit metainfo +appstream-util validate-relax --nonet ${RPM_BUILD_ROOT}%{_datadir}/metainfo/%{ui_appstream_metainfo} + # In the building environment LC_CTYPE is set to C which causes tests to fail # due to python prints a warning about it to stderr. The following environment # variable disables the warning. @@ -349,21 +397,21 @@ run_all_tests %systemd_post pcsd.service %systemd_post pcsd-ruby.service -%post -n %{pcs_snmp_pkg_name} +%post -n %{pkg_pcs_snmp} %systemd_post pcs_snmp_agent.service %preun %systemd_preun pcsd.service %systemd_preun pcsd-ruby.service -%preun -n %{pcs_snmp_pkg_name} +%preun -n %{pkg_pcs_snmp} %systemd_preun pcs_snmp_agent.service %postun %systemd_postun_with_restart pcsd.service %systemd_postun_with_restart pcsd-ruby.service -%postun -n %{pcs_snmp_pkg_name} +%postun -n %{pkg_pcs_snmp} %systemd_postun_with_restart pcs_snmp_agent.service %files @@ -396,9 +444,10 @@ run_all_tests %{_mandir}/man8/pcsd.* %exclude %{_prefix}/lib/pcs/pcs_snmp_agent %exclude %{_prefix}/lib/pcs/%{pcs_bundled_dir}/packages/pyagentx* +%exclude %{_datadir}/cockpit +%exclude %{_datadir}/metainfo/%{ui_appstream_metainfo} - -%files -n %{pcs_snmp_pkg_name} +%files -n %{pkg_pcs_snmp} %{_prefix}/lib/pcs/pcs_snmp_agent %{_prefix}/lib/pcs/%{pcs_bundled_dir}/packages/pyagentx* %{_unitdir}/pcs_snmp_agent.service @@ -411,7 +460,18 @@ run_all_tests %license COPYING %license pyagentx_LICENSE.txt +%files -n %{pkg_cockpit_ha_cluster} +%{_datadir}/cockpit/%{ui_cockpit_dest} +%{_datadir}/metainfo/%{ui_appstream_metainfo} + + %changelog +* Mon Jan 8 2024 Michal Pospisil - 0.11.7-1 +- Rebased to the latest upstream sources (see CHANGELOG.md) +- Updated pcs-web-ui to 0.1.18 +- TLS cipher setting in pcsd now follows system-wide crypto policies by default +- Added cockpit-ha-cluster subpackage that adds pcs-web-ui as a Cockpit application + * Thu Jul 20 2023 Fedora Release Engineering - 0.11.6-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild diff --git a/prepare-env.sh b/prepare-env.sh new file mode 100755 index 0000000..a0405b7 --- /dev/null +++ b/prepare-env.sh @@ -0,0 +1,18 @@ +set -eo xtrace +# Rpmbuild expects patches in the _sourcedir +find *.patch &> /dev/null && mv *.patch $TMT_SOURCE_DIR +mkdir builddir +rpmbuild -bp pcs.spec --nodeps --define "_sourcedir $TMT_SOURCE_DIR" \ + --define "_builddir $(pwd)/builddir" +# Remove *SPECPARTS folders generated by rpmbuild +rm -rfv builddir/*SPECPARTS +# Remove pcs-web-ui in builddir for "cd pcs-*" to have exactly one match +rm -rf builddir/pcs-web-ui-* +cd builddir/pcs-* +# Run autotools, use bundled dependencies from the system +export PYTHONPATH=/usr/lib/pcs/pcs_bundled/packages/ +export GEM_HOME=/usr/lib/pcsd/vendor/bundle/ +./autogen.sh +./configure --with-pcs-lib-dir=/usr/lib --with-distro=fedora +# Remove pcs sources to make sure tests are not using any of those files +rm -rf pcs diff --git a/sources b/sources index 02e35b4..27bf1eb 100644 --- a/sources +++ b/sources @@ -1,5 +1,5 @@ SHA512 (pyagentx-0.4.pcs.2.tar.gz) = d4194fec9a3e5fefe3793d49b7fec1feafef294c7e613a06046c2993daeefc5cb39d7c5b2b402ff83e49b2d976953f862264288c758c0be09d997b5323cc558a -SHA512 (pcs-0.11.6.tar.gz) = ea439808070b171d02e1d6e071bd083fb4c4e30d92c2e637810c89cbb5feec2c56aabfbcda4c25eccb7ab46df2cd56f192dbd6a29f4c7c1fe7aca5a82f4a42ef -SHA512 (pcs-web-ui-node-modules-0.1.17.tar.xz) = 51f47be3b28a378542ebe862a333e8883bbcf4e40a2aea685986b9d17db91dab01cb3b58c9ffba56f335bedfe0a9477ebb1ff93824228ed5348f864afad5b98d -SHA512 (pcs-web-ui-0.1.17.tar.gz) = a5dd551c47040d9c9a2f714a83b835aaf5cca8d5dd05c83f641ddecdb7d99ac82a3b265df508c0ec1bc51ea572210d6255d79631f4680205c6302cb89460d14c SHA512 (dacite-1.8.1.tar.gz) = 4b40c0bdcf5490bcc77de9e7f04b7267642bcfd41e4168607a5457f38abe3ad4b3041d8a23cb43af76de14eabee45f900ad5ddf7af8f70a2be4850bccc2d3af1 +SHA512 (pcs-0.11.7.tar.gz) = 29d61bb945b25ced67e3a05f742ab6f557da8c4d3e8ee04db8caa9a51bb1c64e64cd5382f801173d95e9d62c53a52ad86f823c475ba790cb86b777a1eff658cc +SHA512 (pcs-web-ui-0.1.18.tar.gz) = edbe88d113e967b2d3f345e74e8c4409b013fb8474fe70a8813a1aba5ea8b4deb61a3bb8c4cd4b4d1a9dc9e67216e518ee5bf832a25188e95173317533d7bf69 +SHA512 (pcs-web-ui-node-modules-0.1.18.tar.xz) = 237ff976d67a7bf881e45334261af1da32c6330fbf9e7436dcf33e63c9373f85f36db52622676f77e27bb6a853c046223cfe0cca25de68bd004c6535aa077fd7 diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index 098eec7..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,72 +0,0 @@ -- hosts: localhost - tags: - - classic - vars: - # standard-test-basic directory for tests are relative to {{ tenv_workdir }} - tenv_workdir: /var/test - pre_tasks: - - import_role: - name: standard-test-source - vars: - fetch_only: True - - name: Copy files including source to test environment - synchronize: - src: "{{ playbook_dir }}/.." - dest: "{{ tenv_workdir }}" - mode: push - ssh_args: "-o UserKnownHostsFile=/dev/null" - - name: Start pcsd - systemd: - state: started - name: pcsd - daemon_reload: yes - - roles: - # roles documentation: - # https://pagure.io/standard-test-roles/blob/master/f/roles/standard-test-source - - role: standard-test-basic - required_packages: - - autoconf - - automake - - make - - rpm-build - - ruby-devel - - git-core - - booth-site - - fence-agents-apc - - fence-agents-ipmilan - - fence-agents-scsi - - fence-virt - - pcs - - python3-pip - - python3-setuptools_scm - - python3-wheel - - rubygem-test-unit - - wget - required_services: - - pcsd - tests: - # dir: . -> dot means tests dir in distgit - - prepare-source: - dir: ./ - run: rpmbuild -bp {{tenv_workdir}}/*.spec --nodeps --define "_sourcedir {{tenv_workdir}}" --define "_builddir {{tenv_workdir}}/source" - # pcs-web-ui sources are deleted because there are conflicts during move of sources - # pcs-web-ui sources aren't needed during testing - - flatten-source: - dir: ./ - run: rm -rf {{tenv_workdir}}/source/pcs-web-ui-*; shopt -s dotglob; mv {{tenv_workdir}}/source/*/* {{tenv_workdir}}/source - - build_sources: - dir: ./source - run: "export PYTHONPATH=/usr/lib/pcs/pcs_bundled/packages/; ./autogen.sh && ./configure --enable-tests-only --with-pcs-lib-dir=/usr/lib" - - remove_sources: - dir: ./source - run: rm -rfv pcs - - run_upstream_tier0_tests: - dir: ./source - run: pcs_test/suite --tier0 -v --vanilla --installed - - run_upstream_tier1_tests: - dir: ./source - run: pcs_test/suite --tier1 -v --vanilla --installed - - run_smoke_tests: - dir: ./source - run: pcs_test/smoke.sh From b68e4b6701e459e7043bf0b1b7c626c56f17ae39 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 25 Jan 2024 12:20:13 +0000 Subject: [PATCH 05/26] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index ef43a4e..b585e07 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.11.7 -Release: 1%{?dist} +Release: 2%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -466,6 +466,9 @@ run_all_tests %changelog +* Thu Jan 25 2024 Fedora Release Engineering - 0.11.7-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Mon Jan 8 2024 Michal Pospisil - 0.11.7-1 - Rebased to the latest upstream sources (see CHANGELOG.md) - Updated pcs-web-ui to 0.1.18 From 655b3251b0cc81838d61f33d7726aae001233f22 Mon Sep 17 00:00:00 2001 From: Michal Pospisil Date: Mon, 5 Feb 2024 10:51:21 +0100 Subject: [PATCH 06/26] pcs-0.11.7-3 - Fixed a bug preventing the Cockpit Application from being installed from Cockpit --- metainfo-fix-outdated-extends-id.patch | 25 +++++++++++++++++++++++++ pcs.spec | 8 +++++++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 metainfo-fix-outdated-extends-id.patch diff --git a/metainfo-fix-outdated-extends-id.patch b/metainfo-fix-outdated-extends-id.patch new file mode 100644 index 0000000..a9e2106 --- /dev/null +++ b/metainfo-fix-outdated-extends-id.patch @@ -0,0 +1,25 @@ +From c55cac8220da78b87b7c84c4049280bc05bf1753 Mon Sep 17 00:00:00 2001 +From: Michal Pospisil +Date: Fri, 2 Feb 2024 18:47:54 +0100 +Subject: [PATCH] metainfo: fix outdated extends id + +--- + packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml b/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml +index a27525a9..0924545c 100644 +--- a/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml ++++ b/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml +@@ -10,7 +10,7 @@ + Configuration System (pcs) in the background. +

+ +- cockpit.desktop ++ org.cockpit_project.cockpit + ha-cluster + https://github.com/ClusterLabs/pcs-web-ui + +-- +2.43.0 + diff --git a/pcs.spec b/pcs.spec index b585e07..26e73ce 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.11.7 -Release: 2%{?dist} +Release: 3%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -56,6 +56,7 @@ Source101: https://github.com/ClusterLabs/pcs-web-ui/releases/download/%{ui_comm # ui patches: >200 # Patch201: name-web-ui.patch Patch201: make-AppStream-metainfo-more-descriptive.patch +Patch202: metainfo-fix-outdated-extends-id.patch # git for patches BuildRequires: git-core @@ -269,6 +270,8 @@ update_times_patch(){ %autosetup -D -T -b 100 -a 101 -S git -n %{ui_src_name} -N %autopatch -p1 -m 201 # update_times_patch %%{PATCH201} +update_times_patch %%{PATCH201} +update_times_patch %%{PATCH202} # patch pcs sources %autosetup -S git -n %{pcs_source_name} -N @@ -466,6 +469,9 @@ run_all_tests %changelog +* Mon Feb 5 2024 Michal Pospisil - 0.11.7-3 +- Fixed a bug preventing the Cockpit Application from being installed from Cockpit + * Thu Jan 25 2024 Fedora Release Engineering - 0.11.7-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From 43ad5326868650ba4d67bc8e6cbeebf742e9210b Mon Sep 17 00:00:00 2001 From: Python Maint Date: Sun, 9 Jun 2024 03:06:50 +0200 Subject: [PATCH 07/26] Rebuilt for Python 3.13 --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 26e73ce..8992259 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.11.7 -Release: 3%{?dist} +Release: 4%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -469,6 +469,9 @@ run_all_tests %changelog +* Sun Jun 09 2024 Python Maint - 0.11.7-4 +- Rebuilt for Python 3.13 + * Mon Feb 5 2024 Michal Pospisil - 0.11.7-3 - Fixed a bug preventing the Cockpit Application from being installed from Cockpit From 232b9c52ef6fbe0c1bdd20e431685ae213082ca5 Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Sun, 23 Jun 2024 22:34:41 -0400 Subject: [PATCH 08/26] Drop eln macro usage The %eln macro should only be used where absolutely necessary and with approval from ELN SIG. ELN builds also define the %rhel macro, set to the next version to be branched, which covers almost all cases. Fedora 38 is EOL, so there is no further need to conditionalize for it. --- pcs.spec | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/pcs.spec b/pcs.spec index 8992259..a21e5be 100644 --- a/pcs.spec +++ b/pcs.spec @@ -94,7 +94,7 @@ BuildRequires: rubygem-rack-protection BuildRequires: rubygem-rack-test BuildRequires: rubygem-sinatra BuildRequires: rubygem-tilt -%if 0%{?fedora} || 0%{?eln} || 0%{?rhel} >= 9 +%if 0%{?fedora} || 0%{?rhel} >= 9 BuildRequires: rubygem(rexml) %endif # ruby libraries for tests @@ -148,7 +148,7 @@ Requires: rubygem-rack-protection Requires: rubygem-rack-test Requires: rubygem-sinatra Requires: rubygem-tilt -%if 0%{?fedora} || 0%{?eln} || 0%{?rhel} >= 9 +%if 0%{?fedora} || 0%{?rhel} >= 9 Requires: rubygem(rexml) %endif # for killall @@ -293,16 +293,9 @@ cp -f %SOURCE42 rpm/ %build %define debug_package %{nil} -# Booth authfile fix support -# Fedora 37, 38, ELN = RHEL10: unset only -# Fedora 39+: no booth build options -%if 0%{?fedora} <= 38 || 0%{?eln} - %define booth_build_options --enable-booth-enable-authfile-unset -%endif - ./autogen.sh %{configure} --enable-local-build --enable-use-local-cache-only \ - --enable-individual-bundling %{?booth_build_options} \ + --enable-individual-bundling \ --with-pcsd-default-cipherlist='PROFILE=SYSTEM' \ --with-pcs-lib-dir="%{_prefix}/lib" PYTHON=%{__python3} make all From 234d9718a93d91a44c7bdf6cbc827561bbf26c40 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 18 Jul 2024 21:39:00 +0000 Subject: [PATCH 09/26] Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index a21e5be..ec3f7f2 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.11.7 -Release: 4%{?dist} +Release: 5%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -462,6 +462,9 @@ run_all_tests %changelog +* Thu Jul 18 2024 Fedora Release Engineering - 0.11.7-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + * Sun Jun 09 2024 Python Maint - 0.11.7-4 - Rebuilt for Python 3.13 From 9fee6b2969387ab9c94929717ffb0a1e66a7f9cf Mon Sep 17 00:00:00 2001 From: Michal Pospisil Date: Mon, 29 Jul 2024 20:04:33 +0200 Subject: [PATCH 10/26] pcs-0.11.8-1 - Rebased to the latest sources (see CHANGELOG.md) - Updated pcs-web-ui to 0.1.20 - Removed extraneous Requires and BuildRequires --- .gitignore | 3 + ...-AppStream-metainfo-more-descriptive.patch | 82 - metainfo-fix-outdated-extends-id.patch | 25 - overhaul-fence-agents-mocking.patch | 3687 +++++++++++++++++ pcs.spec | 40 +- prepare-env.sh | 2 +- sources | 6 +- 7 files changed, 3715 insertions(+), 130 deletions(-) delete mode 100644 make-AppStream-metainfo-more-descriptive.patch delete mode 100644 metainfo-fix-outdated-extends-id.patch create mode 100644 overhaul-fence-agents-mocking.patch diff --git a/.gitignore b/.gitignore index 99144f3..26b9e4d 100644 --- a/.gitignore +++ b/.gitignore @@ -115,3 +115,6 @@ /pcs-0.11.7.tar.gz /pcs-web-ui-0.1.18.tar.gz /pcs-web-ui-node-modules-0.1.18.tar.xz +/pcs-0.11.8.tar.gz +/pcs-web-ui-0.1.20.tar.gz +/pcs-web-ui-node-modules-0.1.20.tar.xz diff --git a/make-AppStream-metainfo-more-descriptive.patch b/make-AppStream-metainfo-more-descriptive.patch deleted file mode 100644 index f9dd2a2..0000000 --- a/make-AppStream-metainfo-more-descriptive.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 9923d48095ac7a1376b108a0a3e722d3090fcea6 Mon Sep 17 00:00:00 2001 -From: Michal Pospisil -Date: Thu, 18 Jan 2024 16:52:59 +0100 -Subject: [PATCH] make AppStream metainfo more descriptive - ---- - ...g.clusterlabs.cockpit_pcs_web_ui.metainfo.xml | 16 ++++++++++++++++ - .../app/org.clusterlabs.pcs_web_ui.metainfo.xml | 16 ---------------- - packages/app/package-lock.json | 4 ++-- - 3 files changed, 18 insertions(+), 18 deletions(-) - create mode 100644 packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml - delete mode 100644 packages/app/org.clusterlabs.pcs_web_ui.metainfo.xml - -diff --git a/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml b/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml -new file mode 100644 -index 00000000..a27525a9 ---- /dev/null -+++ b/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml -@@ -0,0 +1,16 @@ -+ -+ -+ org.clusterlabs.cockpit_pcs_web_ui -+ CC0-1.0 -+ HA Cluster Management -+ Manage Pacemaker based clusters -+ -+

-+ Application for managing Pacemaker based clusters. Uses Pacemaker/Corosync -+ Configuration System (pcs) in the background. -+

-+
-+ cockpit.desktop -+ ha-cluster -+ https://github.com/ClusterLabs/pcs-web-ui -+
-diff --git a/packages/app/org.clusterlabs.pcs_web_ui.metainfo.xml b/packages/app/org.clusterlabs.pcs_web_ui.metainfo.xml -deleted file mode 100644 -index 83add879..00000000 ---- a/packages/app/org.clusterlabs.pcs_web_ui.metainfo.xml -+++ /dev/null -@@ -1,16 +0,0 @@ -- -- -- org.clusterlabs.pcs_web_ui -- CC0-1.0 -- Pcs Web UI -- Manage pacemaker based clusters. -- --

-- Pcs Web UI is an application that allows you to easily view, modify and -- create pacemaker based clusters. --

--
-- cockpit.desktop -- ha-cluster --
-- -diff --git a/packages/app/package-lock.json b/packages/app/package-lock.json -index 4bf1e89e..2f4049a5 100644 ---- a/packages/app/package-lock.json -+++ b/packages/app/package-lock.json -@@ -3830,7 +3830,7 @@ - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001563", -- "resolved": "https://repository.engineering.redhat.com/nexus/repository/registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", -+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", - "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", - "dev": true, - "funding": [ -@@ -12590,7 +12590,7 @@ - }, - "caniuse-lite": { - "version": "1.0.30001563", -- "resolved": "https://repository.engineering.redhat.com/nexus/repository/registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", -+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", - "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", - "dev": true - }, --- -2.43.0 - diff --git a/metainfo-fix-outdated-extends-id.patch b/metainfo-fix-outdated-extends-id.patch deleted file mode 100644 index a9e2106..0000000 --- a/metainfo-fix-outdated-extends-id.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c55cac8220da78b87b7c84c4049280bc05bf1753 Mon Sep 17 00:00:00 2001 -From: Michal Pospisil -Date: Fri, 2 Feb 2024 18:47:54 +0100 -Subject: [PATCH] metainfo: fix outdated extends id - ---- - packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml b/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml -index a27525a9..0924545c 100644 ---- a/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml -+++ b/packages/app/org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml -@@ -10,7 +10,7 @@ - Configuration System (pcs) in the background. -

- -- cockpit.desktop -+ org.cockpit_project.cockpit - ha-cluster - https://github.com/ClusterLabs/pcs-web-ui - --- -2.43.0 - diff --git a/overhaul-fence-agents-mocking.patch b/overhaul-fence-agents-mocking.patch new file mode 100644 index 0000000..967e96a --- /dev/null +++ b/overhaul-fence-agents-mocking.patch @@ -0,0 +1,3687 @@ +From 96671c6b44e6a599c72bddb384167e7266418e26 Mon Sep 17 00:00:00 2001 +From: Tomas Jelinek +Date: Wed, 24 Jul 2024 14:38:31 +0200 +Subject: [PATCH] tests: overhaul fence agents mocking + +* add a stonith_admin mock to support validating instance atributes by + agents +* rename agents to make it clear we're working with mocks and to show + what each mock is used for +* create custom metedata for agents to fit usecases in tests +* tier1 tests do not require fence agents to be installed in the system, + all is mocked now +--- + .gitignore | 1 + + configure.ac | 1 + + pcs_test/Makefile.am | 11 +- + .../tier1/cib_resource/test_clone_unclone.py | 2 +- + .../tier1/cib_resource/test_stonith_create.py | 169 ++- + .../test_stonith_enable_disable.py | 39 +- + pcs_test/tier1/legacy/test_resource.py | 8 +- + pcs_test/tier1/legacy/test_stonith.py | 1007 +++++------------ + pcs_test/tier1/test_status.py | 20 +- + pcs_test/tools/bin_mock/__init__.py | 4 + + .../stonith__fence_apc_metadata.xml | 277 ----- + .../stonith__fence_ilo_metadata.xml | 269 ----- + ...stonith__fence_pcsmock_action_metadata.xml | 31 + + ...stonith__fence_pcsmock_method_metadata.xml | 32 + + ...tonith__fence_pcsmock_minimal_metadata.xml | 22 + + ...stonith__fence_pcsmock_params_metadata.xml | 107 ++ + ...nith__fence_pcsmock_unfencing_metadata.xml | 22 + + .../stonith__fence_scsi_metadata.xml | 182 --- + .../stonith__fence_xvm_metadata.xml | 120 -- + .../tools/bin_mock/pcmk/crm_resource_mock.py | 28 +- + pcs_test/tools/bin_mock/pcmk/stonith_admin.in | 5 + + .../tools/bin_mock/pcmk/stonith_admin_mock.py | 60 + + 22 files changed, 710 insertions(+), 1707 deletions(-) + delete mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml + delete mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml + create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml + create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml + create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml + create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml + create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml + delete mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml + delete mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml + create mode 100755 pcs_test/tools/bin_mock/pcmk/stonith_admin.in + create mode 100644 pcs_test/tools/bin_mock/pcmk/stonith_admin_mock.py + +diff --git a/.gitignore b/.gitignore +index b08138ea..6b39468d 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -32,6 +32,7 @@ pcs_test/smoke.sh + pcs_test/tools/bin_mock/pcmk/crm_resource + pcs_test/tools/bin_mock/pcmk/pacemaker_metadata + pcs_test/tools/bin_mock/pcmk/pacemaker-fenced ++pcs_test/tools/bin_mock/pcmk/stonith_admin + pcs_test/resources/*.tmp + pcs_test/resources/temp*.xml + pcs_test/resources/temp* +diff --git a/configure.ac b/configure.ac +index 6ca44faa..71bbd1b3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -629,6 +629,7 @@ AC_CONFIG_FILES([pcs_test/pcs_for_tests], [chmod +x pcs_test/pcs_for_tests]) + AC_CONFIG_FILES([pcs_test/suite], [chmod +x pcs_test/suite]) + AC_CONFIG_FILES([pcs_test/tools/bin_mock/pcmk/crm_resource], [chmod +x pcs_test/tools/bin_mock/pcmk/crm_resource]) + AC_CONFIG_FILES([pcs_test/tools/bin_mock/pcmk/pacemaker-fenced], [chmod +x pcs_test/tools/bin_mock/pcmk/pacemaker-fenced]) ++AC_CONFIG_FILES([pcs_test/tools/bin_mock/pcmk/stonith_admin], [chmod +x pcs_test/tools/bin_mock/pcmk/stonith_admin]) + AC_CONFIG_FILES([pcsd/pcsd], [chmod +x pcsd/pcsd]) + AC_CONFIG_FILES([scripts/pcsd.sh], [chmod +x scripts/pcsd.sh]) + +diff --git a/pcs_test/Makefile.am b/pcs_test/Makefile.am +index 4ca7d1ee..85dece70 100644 +--- a/pcs_test/Makefile.am ++++ b/pcs_test/Makefile.am +@@ -415,18 +415,19 @@ EXTRA_DIST = \ + tools/bin_mock/pcmk/crm_resource.d/ocf__pacemaker__remote_metadata.xml \ + tools/bin_mock/pcmk/crm_resource.d/ocf__pacemaker__Stateful_metadata.xml \ + tools/bin_mock/pcmk/crm_resource.d/ocf__pacemaker__SystemHealth_metadata.xml \ +- tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml \ +- tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml \ +- tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml \ +- tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml \ ++ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml \ ++ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml \ ++ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml \ ++ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml \ ++ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml \ + tools/bin_mock/pcmk/crm_resource.d/systemd__test@a__b_metadata.xml \ + tools/bin_mock/pcmk/crm_resource_mock.py \ +- tools/bin_mock/pcmk/pacemaker-fenced \ + tools/bin_mock/pcmk/pacemaker_metadata.d/pacemaker_based.xml \ + tools/bin_mock/pcmk/pacemaker_metadata.d/pacemaker_controld.xml \ + tools/bin_mock/pcmk/pacemaker_metadata.d/pacemaker_fenced.xml \ + tools/bin_mock/pcmk/pacemaker_metadata.d/pacemaker_schedulerd.xml \ + tools/bin_mock/pcmk/pacemaker_metadata.py \ ++ tools/bin_mock/pcmk/stonith_admin_mock.py \ + tools/case_analysis.py \ + tools/check/__init__.py \ + tools/check/test_misc.py \ +diff --git a/pcs_test/tier1/cib_resource/test_clone_unclone.py b/pcs_test/tier1/cib_resource/test_clone_unclone.py +index 9a4c0185..3f991c23 100644 +--- a/pcs_test/tier1/cib_resource/test_clone_unclone.py ++++ b/pcs_test/tier1/cib_resource/test_clone_unclone.py +@@ -34,7 +34,7 @@ FIXTURE_PRIMITIVE_FOR_CLONE = _get_primitive_fixture("C") + FIXTURE_CLONE = f"""{FIXTURE_PRIMITIVE_FOR_CLONE}""" + + FIXTURE_STONITH_FOR_CLONE = """ +- ++ + + +diff --git a/pcs_test/tier1/cib_resource/test_stonith_create.py b/pcs_test/tier1/cib_resource/test_stonith_create.py +index a42c3dd6..9b43a1a2 100644 +--- a/pcs_test/tier1/cib_resource/test_stonith_create.py ++++ b/pcs_test/tier1/cib_resource/test_stonith_create.py +@@ -1,5 +1,3 @@ +-import re +- + from pcs_test.tier1.cib_resource.common import ResourceTest + from pcs_test.tools.bin_mock import get_mock_settings + from pcs_test.tools.misc import is_minimum_pacemaker_version +@@ -12,12 +10,17 @@ ERRORS_HAVE_OCCURRED = ( + + + class PlainStonith(ResourceTest): ++ def setUp(self): ++ super().setUp() ++ self.pcs_runner.mock_settings = get_mock_settings( ++ "crm_resource_exec", "stonith_admin_exec" ++ ) ++ + def test_simplest(self): +- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") + self.assert_effect( +- "stonith create S fence_xvm".split(), ++ "stonith create S fence_pcsmock_minimal".split(), + """ +- ++ + + +- ++ + + +@@ -117,16 +81,18 @@ class PlainStonith(ResourceTest): + + + """, +- stderr_full=error, +- stderr_regexp=error_re, ++ stderr_full=( ++ "Warning: Agent 'stonith:absent' is not installed or " ++ "does not provide valid metadata: " ++ "pcs mock error message: unable to load agent metadata\n" ++ ), + ) + + def test_disabled_puts_target_role_stopped(self): +- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") + self.assert_effect( +- "stonith create S fence_xvm --disabled".split(), ++ "stonith create S fence_pcsmock_minimal --disabled".split(), + """ +- ++ + + +- ++ + + +- ++ + + +- ++ + + +- ++ + + + +- ++ + + + +- ++ + + + + +- ++ + + + +- ++ + + + + +- ++ + + + +- ++ + + + + +- ++ + + + + +- ++ + + +- ++ + + +- ++ + + + +- ++ + + + """ + +- self.assert_effect("stonith create S fence_xvm".split(), result_xml) ++ self.assert_effect( ++ "stonith create S fence_pcsmock_minimal".split(), result_xml ++ ) + self.assert_effect("stonith enable S".split(), result_xml) + + + class Disable(ResourceTest): ++ def setUp(self): ++ super().setUp() ++ self.pcs_runner.mock_settings = get_mock_settings( ++ "crm_resource_exec", "stonith_admin_exec" ++ ) ++ + def test_disable_enabled_stonith(self): +- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") + self.assert_effect( +- "stonith create S fence_xvm".split(), ++ "stonith create S fence_pcsmock_minimal".split(), + """ +- ++ + + +- ++ + + +- ++ + + + """ + self.assert_effect( +- "stonith create S fence_xvm --disabled".split(), result_xml ++ "stonith create S fence_pcsmock_minimal --disabled".split(), ++ result_xml, + ) + self.assert_effect("stonith disable S".split(), result_xml) +diff --git a/pcs_test/tier1/legacy/test_resource.py b/pcs_test/tier1/legacy/test_resource.py +index c6709682..ec7bed01 100644 +--- a/pcs_test/tier1/legacy/test_resource.py ++++ b/pcs_test/tier1/legacy/test_resource.py +@@ -138,8 +138,8 @@ class ResourceDescribe(TestCase, AssertPcsMixin): + "resource describe ocf:pacemaker:nonexistent".split(), + ( + "Error: Agent 'ocf:pacemaker:nonexistent' is not installed or does " +- "not provide valid metadata: Metadata query for " +- "ocf:pacemaker:nonexistent failed: Input/output error\n" ++ "not provide valid metadata: " ++ "pcs mock error message: unable to load agent metadata\n" + + ERRORS_HAVE_OCCURRED + ), + ) +@@ -5018,8 +5018,8 @@ class UpdateInstanceAttrs( + agent = "ocf:pacemaker:nonexistent" + message = ( + f"Agent '{agent}' is not installed or does " +- "not provide valid metadata: Metadata query for " +- f"{agent} failed: Input/output error" ++ "not provide valid metadata: " ++ "pcs mock error message: unable to load agent metadata" + ) + self.assert_pcs_success( + f"resource create --force D0 {agent}".split(), +diff --git a/pcs_test/tier1/legacy/test_stonith.py b/pcs_test/tier1/legacy/test_stonith.py +index 6d0bff24..d8d1f4e0 100644 +--- a/pcs_test/tier1/legacy/test_stonith.py ++++ b/pcs_test/tier1/legacy/test_stonith.py +@@ -40,12 +40,12 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + + def test_success(self): + self.assert_pcs_success( +- "stonith describe fence_apc".split(), ++ "stonith describe fence_pcsmock_params".split(), + stdout_start=dedent( + """\ +- fence_apc - Fence agent for APC over telnet/ssh ++ fence_pcsmock_params - Mock agent for pcs tests - agent with various params + +- fence_apc is an I/O Fencing agent which can be used with the APC network power switch. It logs into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions. ++ This is an agent with params for pcs tests + + Stonith options: + """ +@@ -54,7 +54,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + + def test_full(self): + self.assert_pcs_success( +- "stonith describe fence_apc --full".split(), ++ "stonith describe fence_pcsmock_params --full".split(), + stdout_regexp=".*pcmk_list_retries.*", + ) + +@@ -63,10 +63,9 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "stonith describe fence_noexist".split(), + ( + "Error: Agent 'stonith:fence_noexist' is not installed or does not " +- "provide valid metadata: Agent fence_noexist not found or does " +- "not support meta-data: Invalid argument (22), " +- "Metadata query for stonith:fence_noexist failed: Input/output " +- "error\n" + ERRORS_HAVE_OCCURRED ++ "provide valid metadata: " ++ "pcs mock error message: unable to load agent metadata\n" ++ + ERRORS_HAVE_OCCURRED + ), + ) + +@@ -85,17 +84,17 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + def test_pcsd_interface(self): + self.maxDiff = None + stdout, stderr, returncode = self.pcs_runner.run( +- "stonith get_fence_agent_info stonith:fence_apc".split() ++ "stonith get_fence_agent_info stonith:fence_pcsmock_params".split() + ) + self.assertEqual( + json.loads(stdout), + { +- "name": "stonith:fence_apc", ++ "name": "stonith:fence_pcsmock_params", + "standard": "stonith", + "provider": None, +- "type": "fence_apc", +- "shortdesc": "Fence agent for APC over telnet/ssh", +- "longdesc": "fence_apc is an I/O Fencing agent which can be used with the APC network power switch. It logs into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.", ++ "type": "fence_pcsmock_params", ++ "shortdesc": "Mock agent for pcs tests - agent with various params", ++ "longdesc": "This is an agent with params for pcs tests", + "parameters": [ + { + "name": "action", +@@ -115,81 +114,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "unique_group": None, + "reloadable": False, + }, +- { +- "name": "cmd_prompt", +- "shortdesc": "Force Python regex for command prompt", +- "longdesc": None, +- "type": "string", +- "default": "['\\n>', '\\napc>']", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": True, +- "deprecated_by": ["command_prompt"], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "command_prompt", +- "shortdesc": "Force Python regex for command prompt", +- "longdesc": None, +- "type": "string", +- "default": "['\\n>', '\\napc>']", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "identity_file", +- "shortdesc": "Identity file (private key) for SSH", +- "longdesc": None, +- "type": "string", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "inet4_only", +- "shortdesc": "Forces agent to use IPv4 addresses only", +- "longdesc": None, +- "type": "boolean", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "inet6_only", +- "shortdesc": "Forces agent to use IPv6 addresses only", +- "longdesc": None, +- "type": "boolean", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, + { + "name": "ip", + "shortdesc": "IP address or hostname of fencing device", +@@ -220,21 +144,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "unique_group": None, + "reloadable": False, + }, +- { +- "name": "ipport", +- "shortdesc": "TCP/UDP port to use for connection with device", +- "longdesc": None, +- "type": "integer", +- "default": "23", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, + { + "name": "login", + "shortdesc": "Login name", +@@ -265,21 +174,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "unique_group": None, + "reloadable": False, + }, +- { +- "name": "passwd_script", +- "shortdesc": "Script to run to retrieve password", +- "longdesc": None, +- "type": "string", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": True, +- "deprecated_by": ["password_script"], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, + { + "name": "password", + "shortdesc": "Login password or passphrase", +@@ -295,51 +189,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "unique_group": None, + "reloadable": False, + }, +- { +- "name": "password_script", +- "shortdesc": "Script to run to retrieve password", +- "longdesc": None, +- "type": "string", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "plug", +- "shortdesc": "Physical plug number on device, UUID or identification of machine", +- "longdesc": None, +- "type": "string", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "port", +- "shortdesc": "Physical plug number on device, UUID or identification of machine", +- "longdesc": None, +- "type": "string", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": True, +- "deprecated_by": ["plug"], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, + { + "name": "secure", + "shortdesc": "Use SSH connection", +@@ -370,36 +219,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "unique_group": None, + "reloadable": False, + }, +- { +- "name": "ssh_options", +- "shortdesc": "SSH options to use", +- "longdesc": None, +- "type": "string", +- "default": "-1 -c blowfish", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "switch", +- "shortdesc": "Physical switch number on device", +- "longdesc": None, +- "type": "string", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, + { + "name": "username", + "shortdesc": "Login name", +@@ -415,21 +234,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "unique_group": None, + "reloadable": False, + }, +- { +- "name": "quiet", +- "shortdesc": "Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.", +- "longdesc": None, +- "type": "boolean", +- "default": None, +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, + { + "name": "verbose", + "shortdesc": "Verbose mode", +@@ -475,141 +279,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "unique_group": None, + "reloadable": False, + }, +- { +- "name": "separator", +- "shortdesc": "Separator for CSV created by 'list' operation", +- "longdesc": None, +- "type": "string", +- "default": ",", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "delay", +- "shortdesc": "Wait X seconds before fencing is started", +- "longdesc": None, +- "type": "second", +- "default": "0", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "login_timeout", +- "shortdesc": "Wait X seconds for cmd prompt after login", +- "longdesc": None, +- "type": "second", +- "default": "5", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "power_timeout", +- "shortdesc": "Test X seconds for status change after ON/OFF", +- "longdesc": None, +- "type": "second", +- "default": "20", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "power_wait", +- "shortdesc": "Wait X seconds after issuing ON/OFF", +- "longdesc": None, +- "type": "second", +- "default": "0", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "shell_timeout", +- "shortdesc": "Wait X seconds for cmd prompt after issuing command", +- "longdesc": None, +- "type": "second", +- "default": "3", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "retry_on", +- "shortdesc": "Count of attempts to retry power on", +- "longdesc": None, +- "type": "integer", +- "default": "1", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "ssh_path", +- "shortdesc": "Path to ssh binary", +- "longdesc": None, +- "type": "string", +- "default": "/usr/bin/ssh", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, +- { +- "name": "telnet_path", +- "shortdesc": "Path to telnet binary", +- "longdesc": None, +- "type": "string", +- "default": "/usr/bin/telnet", +- "enum_values": None, +- "required": False, +- "advanced": False, +- "deprecated": False, +- "deprecated_by": [], +- "deprecated_desc": None, +- "unique_group": None, +- "reloadable": False, +- }, + { + "name": "pcmk_host_argument", + "shortdesc": "An alternate parameter to supply instead of 'port'", +@@ -1018,17 +687,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "on_target": False, + }, + { +- "name": "status", +- "timeout": None, +- "interval": None, +- "role": None, +- "start-delay": None, +- "OCF_CHECK_LEVEL": None, +- "automatic": False, +- "on_target": False, +- }, +- { +- "name": "list", ++ "name": "metadata", + "timeout": None, + "interval": None, + "role": None, +@@ -1038,7 +697,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "on_target": False, + }, + { +- "name": "list-status", ++ "name": "status", + "timeout": None, + "interval": None, + "role": None, +@@ -1058,7 +717,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "on_target": False, + }, + { +- "name": "metadata", ++ "name": "list", + "timeout": None, + "interval": None, + "role": None, +@@ -1068,7 +727,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "on_target": False, + }, + { +- "name": "manpage", ++ "name": "list-status", + "timeout": None, + "interval": None, + "role": None, +@@ -1078,8 +737,8 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "on_target": False, + }, + { +- "name": "validate-all", +- "timeout": None, ++ "name": "stop", ++ "timeout": "20s", + "interval": None, + "role": None, + "start-delay": None, +@@ -1088,7 +747,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "on_target": False, + }, + { +- "name": "stop", ++ "name": "start", + "timeout": "20s", + "interval": None, + "role": None, +@@ -1098,8 +757,8 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): + "on_target": False, + }, + { +- "name": "start", +- "timeout": "20s", ++ "name": "validate-all", ++ "timeout": None, + "interval": None, + "role": None, + "start-delay": None, +@@ -1133,7 +792,9 @@ class StonithTest(TestCase, AssertPcsMixin): + self.temp_corosync_conf = get_tmp_file("tier1_test_stonith") + write_file_to_tmpfile(rc("corosync.conf"), self.temp_corosync_conf) + self.pcs_runner = PcsRunner(self.temp_cib.name) +- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") ++ self.pcs_runner.mock_settings = get_mock_settings( ++ "crm_resource_exec", "stonith_admin_exec" ++ ) + self.pcs_runner.mock_settings["corosync_conf_file"] = ( + self.temp_corosync_conf.name + ) +@@ -1142,16 +803,14 @@ class StonithTest(TestCase, AssertPcsMixin): + self.temp_cib.close() + self.temp_corosync_conf.close() + +- @skip_unless_crm_rule() +- def test_stonith_creation(self): ++ def test_stonith_creation_nonexistent_agent(self): + self.assert_pcs_fail( + "stonith create test1 fence_noexist".split(), + ( + "Error: Agent 'stonith:fence_noexist' is not installed or does not " +- "provide valid metadata: Agent fence_noexist not found or does " +- "not support meta-data: Invalid argument (22), " +- "Metadata query for stonith:fence_noexist failed: Input/output " +- "error, use --force to override\n" + ERRORS_HAVE_OCCURRED ++ "provide valid metadata: " ++ "pcs mock error message: unable to load agent metadata, " ++ "use --force to override\n" + ERRORS_HAVE_OCCURRED + ), + ) + +@@ -1159,67 +818,33 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith create test1 fence_noexist --force".split(), + stderr_full=( + "Warning: Agent 'stonith:fence_noexist' is not installed or does not " +- "provide valid metadata: Agent fence_noexist not found or does " +- "not support meta-data: Invalid argument (22), " +- "Metadata query for stonith:fence_noexist failed: Input/output " +- "error\n" +- ), +- ) +- +- self.assert_pcs_fail( +- "stonith create test2 fence_apc".split(), +- ( +- "Error: stonith option 'ip' or 'ipaddr' (deprecated) has to be " +- "specified, use --force to override\n" +- "Error: stonith option 'username' or 'login' (deprecated) has " +- "to be specified, use --force to override\n" +- + ERRORS_HAVE_OCCURRED ++ "provide valid metadata: " ++ "pcs mock error message: unable to load agent metadata\n" + ), + ) + + self.assert_pcs_success( +- "stonith create test2 fence_apc --force".split(), +- stderr_start=( +- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " +- "specified\n" +- "Warning: stonith option 'username' or 'login' (deprecated) has to " +- "be specified\n" +- ), +- ) +- +- self.assert_pcs_fail( +- "stonith create test3 fence_apc bad_argument=test".split(), +- stderr_start=( +- "Error: invalid stonith option 'bad_argument', allowed options are:" +- ), +- ) +- +- self.assert_pcs_fail( +- "stonith create test9 fence_apc pcmk_status_action=xxx".split(), +- ( +- "Error: stonith option 'ip' or 'ipaddr' (deprecated) has to be " +- "specified, use --force to override\n" +- "Error: stonith option 'username' or 'login' (deprecated) has " +- "to be specified, use --force to override\n" +- + ERRORS_HAVE_OCCURRED ++ "stonith config".split(), ++ dedent( ++ """\ ++ Resource: test1 (class=stonith type=fence_noexist) ++ Operations: ++ monitor: test1-monitor-interval-60s ++ interval=60s ++ """ + ), + ) + ++ def test_stonith_creation_pcmk_status_action(self): + self.assert_pcs_success( +- "stonith create test9 fence_apc pcmk_status_action=xxx --force".split(), +- stderr_start=( +- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " +- "specified\n" +- "Warning: stonith option 'username' or 'login' (deprecated) has to " +- "be specified\n" +- ), ++ "stonith create test9 fence_pcsmock_minimal pcmk_status_action=xxx".split(), + ) + + self.assert_pcs_success( + "stonith config test9".split(), + dedent( + """\ +- Resource: test9 (class=stonith type=fence_apc) ++ Resource: test9 (class=stonith type=fence_pcsmock_minimal) + Attributes: test9-instance_attributes + pcmk_status_action=xxx + Operations: +@@ -1229,34 +854,12 @@ class StonithTest(TestCase, AssertPcsMixin): + ), + ) + +- self.assert_pcs_success( +- "stonith delete test9".split(), +- stderr_full="Deleting Resource - test9\n", +- ) +- +- self.assert_pcs_fail( +- "stonith create test3 fence_ilo ip=test".split(), +- ( +- "Error: stonith option 'username' or 'login' (deprecated) has " +- "to be specified, use --force to override\n" +- + ERRORS_HAVE_OCCURRED +- ), +- ) +- +- self.assert_pcs_success( +- "stonith create test3 fence_ilo ip=test --force".split(), +- stderr_start=( +- "Warning: stonith option 'username' or 'login' (deprecated) " +- "has to be specified\n" +- ), +- ) +- ++ def test_stonith_creation_pcmk_params(self): + # Testing that pcmk_host_check, pcmk_host_list & pcmk_host_map are + # allowed for stonith agents + self.assert_pcs_success( + ( +- "stonith create apc-fencing fence_apc ip=morph-apc username=apc " +- "password=apc switch=1 " ++ "stonith create fencing fence_pcsmock_minimal " + "pcmk_host_map=buzz-01:1;buzz-02:2;buzz-03:3;buzz-04:4;buzz-05:5 " + "pcmk_host_check=static-list " + "pcmk_host_list=buzz-01,buzz-02,buzz-03,buzz-04,buzz-05" +@@ -1264,77 +867,105 @@ class StonithTest(TestCase, AssertPcsMixin): + ) + + self.assert_pcs_fail( +- "resource config apc-fencing".split(), ++ "resource config fencing".split(), + ( +- "Warning: Unable to find resource 'apc-fencing'\n" ++ "Warning: Unable to find resource 'fencing'\n" + "Error: No resource found\n" + ), + ) + + self.assert_pcs_success( +- "stonith config apc-fencing".split(), ++ "stonith config fencing".split(), + dedent( + """\ +- Resource: apc-fencing (class=stonith type=fence_apc) +- Attributes: apc-fencing-instance_attributes +- ip=morph-apc +- password=apc ++ Resource: fencing (class=stonith type=fence_pcsmock_minimal) ++ Attributes: fencing-instance_attributes + pcmk_host_check=static-list + pcmk_host_list=buzz-01,buzz-02,buzz-03,buzz-04,buzz-05 + pcmk_host_map=buzz-01:1;buzz-02:2;buzz-03:3;buzz-04:4;buzz-05:5 +- switch=1 +- username=apc + Operations: +- monitor: apc-fencing-monitor-interval-60s ++ monitor: fencing-monitor-interval-60s + interval=60s + """ + ), + ) + ++ def test_stonith_creation_pcmk_host_list(self): ++ self.assert_pcs_success( ++ [ ++ "stonith", ++ "create", ++ "F1", ++ "fence_pcsmock_minimal", ++ "pcmk_host_list=nodea nodeb", ++ ], ++ ) ++ + self.assert_pcs_success( +- "stonith remove apc-fencing".split(), +- stderr_full="Deleting Resource - apc-fencing\n", ++ "stonith config F1".split(), ++ dedent( ++ """\ ++ Resource: F1 (class=stonith type=fence_pcsmock_minimal) ++ Attributes: F1-instance_attributes ++ pcmk_host_list="nodea nodeb" ++ Operations: ++ monitor: F1-monitor-interval-60s ++ interval=60s ++ """ ++ ), + ) + ++ def test_stonith_creation(self): + self.assert_pcs_fail( ++ "stonith create test2 fence_pcsmock_params".split(), + ( +- "stonith create apc-fencing fence_apc ip=morph-apc username=apc " +- "--agent-validation" +- ).split(), +- stderr_start="Error: Validation result from agent", ++ "Error: stonith option 'ip' or 'ipaddr' (deprecated) has to be " ++ "specified, use --force to override\n" ++ "Error: stonith option 'username' or 'login' (deprecated) has " ++ "to be specified, use --force to override\n" ++ + ERRORS_HAVE_OCCURRED ++ ), + ) + + self.assert_pcs_success( +- ( +- "stonith create apc-fencing fence_apc ip=morph-apc username=apc " +- "--agent-validation --force" +- ).split(), +- stderr_start="Warning: Validation result from agent", ++ "stonith create test2 fence_pcsmock_params --force".split(), ++ stderr_start=( ++ "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " ++ "specified\n" ++ "Warning: stonith option 'username' or 'login' (deprecated) has to " ++ "be specified\n" ++ ), + ) + +- self.assert_pcs_success( +- "stonith remove apc-fencing".split(), +- stderr_full="Deleting Resource - apc-fencing\n", ++ self.assert_pcs_fail( ++ "stonith create test3 fence_pcsmock_params bad_argument=test".split(), ++ stderr_start=( ++ "Error: invalid stonith option 'bad_argument', allowed options are:" ++ ), + ) + + self.assert_pcs_fail( +- "stonith update test3 bad_ipaddr=test username=login".split(), +- stderr_regexp=( +- "^Error: invalid stonith option 'bad_ipaddr', allowed options" +- " are: [^\n]+, use --force to override\n$" ++ "stonith create test3 fence_pcsmock_params ip=test".split(), ++ ( ++ "Error: stonith option 'username' or 'login' (deprecated) has " ++ "to be specified, use --force to override\n" ++ + ERRORS_HAVE_OCCURRED + ), + ) + + self.assert_pcs_success( +- "stonith update test3 username=testA --agent-validation".split(), +- stderr_start="Warning: The resource was misconfigured before the update,", ++ "stonith create test3 fence_pcsmock_params ip=test --force".split(), ++ stderr_start=( ++ "Warning: stonith option 'username' or 'login' (deprecated) " ++ "has to be specified\n" ++ ), + ) + + self.assert_pcs_success( + "stonith config test2".split(), + dedent( + """\ +- Resource: test2 (class=stonith type=fence_apc) ++ Resource: test2 (class=stonith type=fence_pcsmock_params) + Operations: + monitor: test2-monitor-interval-60s + interval=60s +@@ -1346,18 +977,13 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith config".split(), + dedent( + """\ +- Resource: test1 (class=stonith type=fence_noexist) +- Operations: +- monitor: test1-monitor-interval-60s +- interval=60s +- Resource: test2 (class=stonith type=fence_apc) ++ Resource: test2 (class=stonith type=fence_pcsmock_params) + Operations: + monitor: test2-monitor-interval-60s + interval=60s +- Resource: test3 (class=stonith type=fence_ilo) ++ Resource: test3 (class=stonith type=fence_pcsmock_params) + Attributes: test3-instance_attributes + ip=test +- username=testA + Operations: + monitor: test3-monitor-interval-60s + interval=60s +@@ -1370,23 +996,16 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith", + "create", + "test-fencing", +- "fence_apc", ++ "fence_pcsmock_minimal", + "pcmk_host_list=rhel7-node1 rhel7-node2", + "op", + "monitor", + "interval=61s", +- "--force", + ], +- stderr_start=( +- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to " +- "be specified\n" +- "Warning: stonith option 'username' or 'login' (deprecated) has to " +- "be specified\n" +- ), + ) + + self.assert_pcs_success( +- "config show".split(), ++ "config".split(), + dedent( + """\ + Cluster Name: test99 +@@ -1395,22 +1014,17 @@ class StonithTest(TestCase, AssertPcsMixin): + Pacemaker Nodes: + + Stonith Devices: +- Resource: test1 (class=stonith type=fence_noexist) +- Operations: +- monitor: test1-monitor-interval-60s +- interval=60s +- Resource: test2 (class=stonith type=fence_apc) ++ Resource: test2 (class=stonith type=fence_pcsmock_params) + Operations: + monitor: test2-monitor-interval-60s + interval=60s +- Resource: test3 (class=stonith type=fence_ilo) ++ Resource: test3 (class=stonith type=fence_pcsmock_params) + Attributes: test3-instance_attributes + ip=test +- username=testA + Operations: + monitor: test3-monitor-interval-60s + interval=60s +- Resource: test-fencing (class=stonith type=fence_apc) ++ Resource: test-fencing (class=stonith type=fence_pcsmock_minimal) + Attributes: test-fencing-instance_attributes + pcmk_host_list="rhel7-node1 rhel7-node2" + Operations: +@@ -1420,10 +1034,81 @@ class StonithTest(TestCase, AssertPcsMixin): + ), + ) + ++ def test_stonith_agent_validation(self): ++ self.pcs_runner.mock_settings = get_mock_settings( ++ "crm_resource_exec", "stonith_admin_exec" ++ ) ++ self.assert_pcs_fail( ++ ( ++ "stonith create fencing fence_pcsmock_params " ++ "ip=is_invalid=True username=apc " ++ "--agent-validation" ++ ).split(), ++ stderr_full=( ++ "Error: Validation result from agent (use --force to override):\n" ++ " pcsmock validation failure\n" + ERRORS_HAVE_OCCURRED ++ ), ++ ) ++ ++ self.assert_pcs_success( ++ ( ++ "stonith create fencing fence_pcsmock_params " ++ "ip=is_invalid=True username=apc " ++ "--agent-validation --force" ++ ).split(), ++ stderr_full=( ++ "Warning: Validation result from agent:\n" ++ " pcsmock validation failure\n" ++ ), ++ ) ++ ++ self.assert_pcs_success( ++ "stonith config".split(), ++ dedent( ++ """\ ++ Resource: fencing (class=stonith type=fence_pcsmock_params) ++ Attributes: fencing-instance_attributes ++ ip="is_invalid=True" ++ username=apc ++ Operations: ++ monitor: fencing-monitor-interval-60s ++ interval=60s ++ """ ++ ), ++ ) ++ ++ self.assert_pcs_fail( ++ "stonith update fencing bad_ipaddr=test username=login".split(), ++ stderr_regexp=( ++ "^Error: invalid stonith option 'bad_ipaddr', allowed options" ++ " are: [^\n]+, use --force to override\n$" ++ ), ++ ) ++ ++ self.assert_pcs_success( ++ "stonith update fencing username=testA --agent-validation".split(), ++ stderr_start="Warning: The resource was misconfigured before the update,", ++ ) ++ ++ self.assert_pcs_success( ++ "stonith config".split(), ++ dedent( ++ """\ ++ Resource: fencing (class=stonith type=fence_pcsmock_params) ++ Attributes: fencing-instance_attributes ++ ip="is_invalid=True" ++ username=testA ++ Operations: ++ monitor: fencing-monitor-interval-60s ++ interval=60s ++ """ ++ ), ++ ) ++ + def test_stonith_create_requires_either_new_or_deprecated(self): + # 'ipaddr' and 'login' are obsoleted by 'ip' and 'username' + self.assert_pcs_fail( +- "stonith create test2 fence_apc".split(), ++ "stonith create test2 fence_pcsmock_params".split(), + ( + "Error: stonith option 'ip' or 'ipaddr' (deprecated) has to be " + "specified, use --force to override\n" +@@ -1436,7 +1121,7 @@ class StonithTest(TestCase, AssertPcsMixin): + def test_stonith_create_deprecated_and_obsoleting(self): + # 'ipaddr' and 'login' are obsoleted by 'ip' and 'username' + self.assert_pcs_success( +- "stonith create S fence_apc ip=i login=l password=1234".split(), ++ "stonith create S fence_pcsmock_params ip=i login=l password=1234".split(), + stderr_full=( + "Warning: stonith option 'login' is deprecated and might be " + "removed in a future release, therefore it should not be " +@@ -1447,7 +1132,7 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith config S".split(), + dedent( + """\ +- Resource: S (class=stonith type=fence_apc) ++ Resource: S (class=stonith type=fence_pcsmock_params) + Attributes: S-instance_attributes + ip=i + login=l +@@ -1466,7 +1151,7 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith", + "create", + "S", +- "fence_apc", ++ "fence_pcsmock_params", + "ip=i1", + "login=l", + "ipaddr=i2", +@@ -1486,7 +1171,7 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith config S".split(), + dedent( + """\ +- Resource: S (class=stonith type=fence_apc) ++ Resource: S (class=stonith type=fence_pcsmock_params) + Attributes: S-instance_attributes + ip=i1 + ipaddr=i2 +@@ -1501,65 +1186,62 @@ class StonithTest(TestCase, AssertPcsMixin): + ) + + def test_stonith_create_provides_unfencing(self): +- self.assert_pcs_success_ignore_output( +- ("stonith", "create", "f1", "fence_scsi", "--force") ++ self.assert_pcs_success( ++ ("stonith", "create", "f1", "fence_pcsmock_unfencing") + ) +- self.assert_pcs_success_ignore_output( ++ self.assert_pcs_success( + ( + "stonith", + "create", + "f2", +- "fence_scsi", ++ "fence_pcsmock_unfencing", + "meta", + "provides=unfencing", +- "--force", + ) + ) +- self.assert_pcs_success_ignore_output( ++ self.assert_pcs_success( + ( + "stonith", + "create", + "f3", +- "fence_scsi", ++ "fence_pcsmock_unfencing", + "meta", + "provides=something", +- "--force", + ) + ) +- self.assert_pcs_success_ignore_output( ++ self.assert_pcs_success( + ( + "stonith", + "create", + "f4", +- "fence_xvm", ++ "fence_pcsmock_minimal", + "meta", + "provides=something", +- "--force", + ) + ) + self.assert_pcs_success( + "stonith config".split(), + dedent( + """\ +- Resource: f1 (class=stonith type=fence_scsi) ++ Resource: f1 (class=stonith type=fence_pcsmock_unfencing) + Meta Attributes: f1-meta_attributes + provides=unfencing + Operations: + monitor: f1-monitor-interval-60s + interval=60s +- Resource: f2 (class=stonith type=fence_scsi) ++ Resource: f2 (class=stonith type=fence_pcsmock_unfencing) + Meta Attributes: f2-meta_attributes + provides=unfencing + Operations: + monitor: f2-monitor-interval-60s + interval=60s +- Resource: f3 (class=stonith type=fence_scsi) ++ Resource: f3 (class=stonith type=fence_pcsmock_unfencing) + Meta Attributes: f3-meta_attributes + provides=unfencing + Operations: + monitor: f3-monitor-interval-60s + interval=60s +- Resource: f4 (class=stonith type=fence_xvm) ++ Resource: f4 (class=stonith type=fence_pcsmock_minimal) + Meta Attributes: f4-meta_attributes + provides=something + Operations: +@@ -1571,7 +1253,7 @@ class StonithTest(TestCase, AssertPcsMixin): + + def test_stonith_create_action(self): + self.assert_pcs_fail( +- "stonith create test fence_apc ip=i username=u action=a".split(), ++ "stonith create test fence_pcsmock_action action=a".split(), + ( + "Error: stonith option 'action' is deprecated and might be " + "removed in a future release, therefore it should not be" +@@ -1581,7 +1263,7 @@ class StonithTest(TestCase, AssertPcsMixin): + ) + + self.assert_pcs_success( +- "stonith create test fence_apc ip=i username=u action=a --force".split(), ++ "stonith create test fence_pcsmock_action action=a --force".split(), + stderr_start=( + "Warning: stonith option 'action' is deprecated and might be " + "removed in a future release, therefore it should not be " +@@ -1593,11 +1275,9 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith config".split(), + dedent( + """\ +- Resource: test (class=stonith type=fence_apc) ++ Resource: test (class=stonith type=fence_pcsmock_action) + Attributes: test-instance_attributes + action=a +- ip=i +- username=u + Operations: + monitor: test-monitor-interval-60s + interval=60s +@@ -1607,24 +1287,20 @@ class StonithTest(TestCase, AssertPcsMixin): + + def test_stonith_create_action_empty(self): + self.assert_pcs_fail( +- "stonith create test fence_apc ip=i username=u action=".split(), ++ "stonith create test fence_pcsmock_action action=".split(), + "Error: action cannot be empty\n" + ERRORS_HAVE_OCCURRED, + ) + + def test_stonith_update_action(self): + self.assert_pcs_success( +- "stonith create test fence_apc ip=i username=u password=1234".split() ++ "stonith create test fence_pcsmock_action".split() + ) + + self.assert_pcs_success( + "stonith config".split(), + dedent( + """\ +- Resource: test (class=stonith type=fence_apc) +- Attributes: test-instance_attributes +- ip=i +- password=1234 +- username=u ++ Resource: test (class=stonith type=fence_pcsmock_action) + Operations: + monitor: test-monitor-interval-60s + interval=60s +@@ -1655,12 +1331,9 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith config".split(), + dedent( + """\ +- Resource: test (class=stonith type=fence_apc) ++ Resource: test (class=stonith type=fence_pcsmock_action) + Attributes: test-instance_attributes + action=a +- ip=i +- password=1234 +- username=u + Operations: + monitor: test-monitor-interval-60s + interval=60s +@@ -1674,11 +1347,7 @@ class StonithTest(TestCase, AssertPcsMixin): + "stonith config".split(), + dedent( + """\ +- Resource: test (class=stonith type=fence_apc) +- Attributes: test-instance_attributes +- ip=i +- password=1234 +- username=u ++ Resource: test (class=stonith type=fence_pcsmock_action) + Operations: + monitor: test-monitor-interval-60s + interval=60s +@@ -1697,74 +1366,29 @@ class StonithTest(TestCase, AssertPcsMixin): + "Error: must specify one (and only one) node to confirm fenced\n", + ) + +- def test_pcmk_host_list(self): +- self.assert_pcs_success( +- [ +- "stonith", +- "create", +- "F1", +- "fence_apc", +- "pcmk_host_list=nodea nodeb", +- "--force", +- ], +- stderr_start=( +- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " +- "specified\n" +- "Warning: stonith option 'username' or 'login' (deprecated) has to " +- "be specified\n" +- ), +- ) +- +- self.assert_pcs_success( +- "stonith config F1".split(), +- dedent( +- """\ +- Resource: F1 (class=stonith type=fence_apc) +- Attributes: F1-instance_attributes +- pcmk_host_list="nodea nodeb" +- Operations: +- monitor: F1-monitor-interval-60s +- interval=60s +- """ +- ), +- ) +- + def test_stonith_delete_removes_level(self): + shutil.copyfile(rc("cib-empty-with3nodes.xml"), self.temp_cib.name) + +- deprecated_warnings = ( +- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " +- "specified\n" +- "Warning: stonith option 'username' or 'login' (deprecated) has to " +- "be specified\n" +- ) + self.assert_pcs_success( +- "stonith create n1-ipmi fence_apc --force".split(), +- stderr_start=deprecated_warnings, ++ "stonith create n1-ipmi fence_pcsmock_minimal".split(), + ) + self.assert_pcs_success( +- "stonith create n2-ipmi fence_apc --force".split(), +- stderr_start=deprecated_warnings, ++ "stonith create n2-ipmi fence_pcsmock_minimal".split(), + ) + self.assert_pcs_success( +- "stonith create n1-apc1 fence_apc --force".split(), +- stderr_start=deprecated_warnings, ++ "stonith create n1-apc1 fence_pcsmock_minimal".split(), + ) + self.assert_pcs_success( +- "stonith create n1-apc2 fence_apc --force".split(), +- stderr_start=deprecated_warnings, ++ "stonith create n1-apc2 fence_pcsmock_minimal".split(), + ) + self.assert_pcs_success( +- "stonith create n2-apc1 fence_apc --force".split(), +- stderr_start=deprecated_warnings, ++ "stonith create n2-apc1 fence_pcsmock_minimal".split(), + ) + self.assert_pcs_success( +- "stonith create n2-apc2 fence_apc --force".split(), +- stderr_start=deprecated_warnings, ++ "stonith create n2-apc2 fence_pcsmock_minimal".split(), + ) + self.assert_pcs_success( +- "stonith create n2-apc3 fence_apc --force".split(), +- stderr_start=deprecated_warnings, ++ "stonith create n2-apc3 fence_pcsmock_minimal".split(), + ) + self.assert_pcs_success_all( + [ +@@ -1780,13 +1404,13 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- * n1-ipmi\t(stonith:fence_apc):\tStopped +- * n2-ipmi\t(stonith:fence_apc):\tStopped +- * n1-apc1\t(stonith:fence_apc):\tStopped +- * n1-apc2\t(stonith:fence_apc):\tStopped +- * n2-apc1\t(stonith:fence_apc):\tStopped +- * n2-apc2\t(stonith:fence_apc):\tStopped +- * n2-apc3\t(stonith:fence_apc):\tStopped ++ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-apc2\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1804,13 +1428,13 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- n1-ipmi\t(stonith:fence_apc):\tStopped +- n2-ipmi\t(stonith:fence_apc):\tStopped +- n1-apc1\t(stonith:fence_apc):\tStopped +- n1-apc2\t(stonith:fence_apc):\tStopped +- n2-apc1\t(stonith:fence_apc):\tStopped +- n2-apc2\t(stonith:fence_apc):\tStopped +- n2-apc3\t(stonith:fence_apc):\tStopped ++ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-apc2\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1833,12 +1457,12 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- * n1-ipmi\t(stonith:fence_apc):\tStopped +- * n2-ipmi\t(stonith:fence_apc):\tStopped +- * n1-apc1\t(stonith:fence_apc):\tStopped +- * n1-apc2\t(stonith:fence_apc):\tStopped +- * n2-apc1\t(stonith:fence_apc):\tStopped +- * n2-apc3\t(stonith:fence_apc):\tStopped ++ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1856,12 +1480,12 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- n1-ipmi\t(stonith:fence_apc):\tStopped +- n2-ipmi\t(stonith:fence_apc):\tStopped +- n1-apc1\t(stonith:fence_apc):\tStopped +- n1-apc2\t(stonith:fence_apc):\tStopped +- n2-apc1\t(stonith:fence_apc):\tStopped +- n2-apc3\t(stonith:fence_apc):\tStopped ++ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1884,11 +1508,11 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- * n1-ipmi\t(stonith:fence_apc):\tStopped +- * n2-ipmi\t(stonith:fence_apc):\tStopped +- * n1-apc1\t(stonith:fence_apc):\tStopped +- * n1-apc2\t(stonith:fence_apc):\tStopped +- * n2-apc3\t(stonith:fence_apc):\tStopped ++ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1906,11 +1530,11 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- n1-ipmi\t(stonith:fence_apc):\tStopped +- n2-ipmi\t(stonith:fence_apc):\tStopped +- n1-apc1\t(stonith:fence_apc):\tStopped +- n1-apc2\t(stonith:fence_apc):\tStopped +- n2-apc3\t(stonith:fence_apc):\tStopped ++ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1933,10 +1557,10 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- * n1-ipmi\t(stonith:fence_apc):\tStopped +- * n2-ipmi\t(stonith:fence_apc):\tStopped +- * n1-apc1\t(stonith:fence_apc):\tStopped +- * n1-apc2\t(stonith:fence_apc):\tStopped ++ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1953,10 +1577,10 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- n1-ipmi\t(stonith:fence_apc):\tStopped +- n2-ipmi\t(stonith:fence_apc):\tStopped +- n1-apc1\t(stonith:fence_apc):\tStopped +- n1-apc2\t(stonith:fence_apc):\tStopped ++ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1978,9 +1602,9 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- * n1-ipmi\t(stonith:fence_apc):\tStopped +- * n2-ipmi\t(stonith:fence_apc):\tStopped +- * n1-apc2\t(stonith:fence_apc):\tStopped ++ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -1997,9 +1621,9 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- n1-ipmi\t(stonith:fence_apc):\tStopped +- n2-ipmi\t(stonith:fence_apc):\tStopped +- n1-apc2\t(stonith:fence_apc):\tStopped ++ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -2021,8 +1645,8 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- * n1-ipmi\t(stonith:fence_apc):\tStopped +- * n2-ipmi\t(stonith:fence_apc):\tStopped ++ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -2038,8 +1662,8 @@ class StonithTest(TestCase, AssertPcsMixin): + ["stonith"], + outdent( + """\ +- n1-ipmi\t(stonith:fence_apc):\tStopped +- n2-ipmi\t(stonith:fence_apc):\tStopped ++ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped ++ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped + + Fencing Levels: + Target: rh7-1 +@@ -2058,11 +1682,8 @@ class StonithTest(TestCase, AssertPcsMixin): + ) + + self.pcs_runner.corosync_conf_opt = None +- self.assert_pcs_success_ignore_output( +- ( +- "stonith create test_stonith fence_apc ip=i username=u " +- "pcmk_host_argument=node1 --force" +- ).split() ++ self.assert_pcs_success( ++ "stonith create test_stonith fence_pcsmock_minimal".split() + ) + + self.pcs_runner.corosync_conf_opt = self.temp_corosync_conf.name +@@ -2092,16 +1713,16 @@ _fixture_stonith_level_cache_lock = Lock() + + class StonithLevelTestCibFixture(CachedCibFixture): + def _fixture_stonith_resource(self, name): +- self.assert_pcs_success_ignore_output( ++ self._pcs_runner.mock_settings = get_mock_settings( ++ "crm_resource_exec", "stonith_admin_exec" ++ ) ++ self.assert_pcs_success( + [ + "stonith", + "create", + name, +- "fence_apc", ++ "fence_pcsmock_minimal", + "pcmk_host_list=rh7-1 rh7-2", +- "ip=i", +- "username=u", +- "--force", + ] + ) + +@@ -2136,7 +1757,9 @@ class LevelTestsBase(TestCase, AssertPcsMixin): + self.temp_cib = get_tmp_file("tier1_test_stonith_level") + write_file_to_tmpfile(rc("cib-empty-withnodes.xml"), self.temp_cib) + self.pcs_runner = PcsRunner(self.temp_cib.name) +- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") ++ self.pcs_runner.mock_settings = get_mock_settings( ++ "crm_resource_exec", "stonith_admin_exec" ++ ) + self.config = "" + self.config_lines = [] + +@@ -2144,16 +1767,13 @@ class LevelTestsBase(TestCase, AssertPcsMixin): + self.temp_cib.close() + + def fixture_stonith_resource(self, name): +- self.assert_pcs_success_ignore_output( ++ self.assert_pcs_success( + [ + "stonith", + "create", + name, +- "fence_apc", ++ "fence_pcsmock_minimal", + "pcmk_host_list=rh7-1 rh7-2", +- "ip=i", +- "username=u", +- "--force", + ] + ) + +@@ -2597,17 +2217,17 @@ class LevelConfig(LevelTestsBase): + if PCMK_2_0_3_PLUS: + result = outdent( + """\ +- * F1\t(stonith:fence_apc):\tStopped +- * F2\t(stonith:fence_apc):\tStopped +- * F3\t(stonith:fence_apc):\tStopped ++ * F1\t(stonith:fence_pcsmock_minimal):\tStopped ++ * F2\t(stonith:fence_pcsmock_minimal):\tStopped ++ * F3\t(stonith:fence_pcsmock_minimal):\tStopped + """ + ) + else: + result = outdent( + """\ +- F1\t(stonith:fence_apc):\tStopped +- F2\t(stonith:fence_apc):\tStopped +- F3\t(stonith:fence_apc):\tStopped ++ F1\t(stonith:fence_pcsmock_minimal):\tStopped ++ F2\t(stonith:fence_pcsmock_minimal):\tStopped ++ F3\t(stonith:fence_pcsmock_minimal):\tStopped + """ + ) + self.assert_pcs_success( +@@ -2628,27 +2248,21 @@ class LevelConfig(LevelTestsBase): + indent( + dedent( + """ +- Resource: F1 (class=stonith type=fence_apc) ++ Resource: F1 (class=stonith type=fence_pcsmock_minimal) + Attributes: F1-instance_attributes +- ip=i + pcmk_host_list="rh7-1 rh7-2" +- username=u + Operations: + monitor: F1-monitor-interval-60s + interval=60s +- Resource: F2 (class=stonith type=fence_apc) ++ Resource: F2 (class=stonith type=fence_pcsmock_minimal) + Attributes: F2-instance_attributes +- ip=i + pcmk_host_list="rh7-1 rh7-2" +- username=u + Operations: + monitor: F2-monitor-interval-60s + interval=60s +- Resource: F3 (class=stonith type=fence_apc) ++ Resource: F3 (class=stonith type=fence_pcsmock_minimal) + Attributes: F3-instance_attributes +- ip=i + pcmk_host_list="rh7-1 rh7-2" +- username=u + Operations: + monitor: F3-monitor-interval-60s + interval=60s +@@ -3383,26 +2997,19 @@ class LevelVerify(LevelTestsBase): + + + class StonithUpdate(ResourceTest): +- # added in fence-agents-all-4.11.0 +- agent_secure_warning = ( +- "(" +- "Warning: Validation result from agent:\n" +- " WARNING:root:Parse error: Ignoring option 'secure' because it does " +- "not have value\n" +- ")?" +- ) +- + def setUp(self): + super().setUp() +- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") ++ self.pcs_runner.mock_settings = get_mock_settings( ++ "crm_resource_exec", "stonith_admin_exec" ++ ) + self.fixture_create_stonith() + + def fixture_create_stonith(self): + self.assert_effect( +- "stonith create S fence_apc ip=i login=l ssh=0 debug=d password=1234".split(), ++ "stonith create S fence_pcsmock_params ip=i login=l ssh=0 debug=d password=1234".split(), + """ + +- ++ + + + + """, +- stderr_regexp=( ++ stderr_full=( + "Warning: stonith option 'login' is deprecated and might be " + "removed in a future release, therefore it should not " + "be used, use 'username' instead\n" + "Warning: stonith option 'debug' is deprecated and might be " + "removed in a future release, therefore it should not " + "be used, use 'debug_file' instead\n" +- + self.agent_secure_warning + ), + ) + +@@ -3444,7 +3050,7 @@ class StonithUpdate(ResourceTest): + "stonith update S debug=D".split(), + """ + +- ++ + + + + """, +- stderr_regexp=( ++ stderr_full=( + "Warning: stonith option 'debug' is deprecated and might be " + "removed in a future release, therefore it should not " + "be used, use 'debug_file' instead\n" +- + self.agent_secure_warning + ), + ) + +@@ -3483,7 +3088,7 @@ class StonithUpdate(ResourceTest): + "stonith update S debug=".split(), + """ + +- ++ + + + + """, +- stderr_regexp=self.agent_secure_warning, + ) + + def test_unset_deprecated_required_param(self): +@@ -3521,7 +3125,7 @@ class StonithUpdate(ResourceTest): + "stonith update S ssh=1".split(), + """ + +- ++ + + +- ++ + + +- ++ + + + + """, +- stderr_regexp=self.agent_secure_warning, + ) + + def test_unset_obsoleting_required_set_deprecated(self): +@@ -3625,7 +3228,7 @@ class StonithUpdate(ResourceTest): + "stonith update S ip= ipaddr=I".split(), + """ + +- ++ + + + + """, +- stderr_regexp=( ++ stderr_full=( + "Warning: stonith option 'ipaddr' is deprecated and might be " + "removed in a future release, therefore it should not " +- "be used, use 'ip' instead\n" + self.agent_secure_warning ++ "be used, use 'ip' instead\n" + ), + ) + +@@ -3663,7 +3266,7 @@ class StonithUpdate(ResourceTest): + "stonith update S ip=I1 ipaddr=I2".split(), + """ + +- ++ + + + + """, +- stderr_regexp=( ++ stderr_full=( + "Warning: stonith option 'ipaddr' is deprecated and might be " + "removed in a future release, therefore it should not " +- "be used, use 'ip' instead\n" + self.agent_secure_warning ++ "be used, use 'ip' instead\n" + ), + ) +diff --git a/pcs_test/tier1/test_status.py b/pcs_test/tier1/test_status.py +index 4d472208..f6780c60 100644 +--- a/pcs_test/tier1/test_status.py ++++ b/pcs_test/tier1/test_status.py +@@ -27,6 +27,9 @@ class StonithWarningTest(TestCase, AssertPcsMixin): + self.temp_cib = get_tmp_file("tier0_statust_stonith_warning") + write_file_to_tmpfile(self.empty_cib, self.temp_cib) + self.pcs_runner = PcsRunner(self.temp_cib.name) ++ self.pcs_runner.mock_settings = get_mock_settings( ++ "crm_resource_exec", "stonith_admin_exec" ++ ) + + def tearDown(self): + self.temp_cib.close() +@@ -34,8 +37,7 @@ class StonithWarningTest(TestCase, AssertPcsMixin): + def fixture_stonith_action(self): + self.assert_pcs_success( + ( +- "stonith create Sa fence_apc ip=i username=u action=reboot " +- "--force" ++ "stonith create Sa fence_pcsmock_action action=reboot --force" + ).split(), + stderr_start=( + "Warning: stonith option 'action' is deprecated and might be " +@@ -45,15 +47,8 @@ class StonithWarningTest(TestCase, AssertPcsMixin): + ) + + def fixture_stonith_cycle(self): +- self.assert_pcs_success_ignore_output( +- ( +- "stonith", +- "create", +- "Sc", +- "fence_ipmilan", +- "method=cycle", +- "--force", +- ) ++ self.assert_pcs_success( ++ "stonith create Sc fence_pcsmock_method method=cycle".split() + ) + + def fixture_resource(self): +@@ -208,14 +203,13 @@ class StonithWarningTest(TestCase, AssertPcsMixin): + + def test_no_stonith_warning_when_stonith_in_group(self): + self.assert_pcs_success( +- "stonith create S fence_xvm --group G".split(), ++ "stonith create S fence_pcsmock_minimal --group G".split(), + stderr_full=( + "Deprecation Warning: Option to group stonith resource is " + "deprecated and will be removed in a future release.\n" + ), + ) + self.pcs_runner.corosync_conf_opt = self.corosync_conf +- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") + if PCMK_2_0_3_PLUS: + self.assert_pcs_success( + ["status"], +diff --git a/pcs_test/tools/bin_mock/__init__.py b/pcs_test/tools/bin_mock/__init__.py +index 653bf81b..9bef8e64 100644 +--- a/pcs_test/tools/bin_mock/__init__.py ++++ b/pcs_test/tools/bin_mock/__init__.py +@@ -8,10 +8,14 @@ CRM_RESOURCE_BIN = os.path.abspath( + PACEMAKER_FENCED_BIN = os.path.abspath( + os.path.join(BIN_MOCK_DIR, "pcmk/pacemaker-fenced") + ) ++STONITH_ADMIN_BIN = os.path.abspath( ++ os.path.join(BIN_MOCK_DIR, "pcmk/stonith_admin") ++) + + MOCK_SETTINGS = { + "crm_resource_exec": CRM_RESOURCE_BIN, + "pacemaker_fenced_exec": PACEMAKER_FENCED_BIN, ++ "stonith_admin_exec": STONITH_ADMIN_BIN, + } + + +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml +deleted file mode 100644 +index 6d159b4f..00000000 +--- a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml ++++ /dev/null +@@ -1,277 +0,0 @@ +- +- +- fence_apc is an I/O Fencing agent which can be used with the APC network power switch. It logs into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions. +- +- +- http://www.apc.com +- +- +- +- +- +- +- Fencing action +- +- +- +- +- +- +- Force Python regex for command prompt +- +- +- +- +- +- +- Force Python regex for command prompt +- +- +- +- +- +- +- Identity file (private key) for SSH +- +- +- +- +- +- +- Forces agent to use IPv4 addresses only +- +- +- +- +- +- +- Forces agent to use IPv6 addresses only +- +- +- +- +- +- +- IP address or hostname of fencing device +- +- +- +- +- +- +- IP address or hostname of fencing device +- +- +- +- +- +- +- TCP/UDP port to use for connection with device +- +- +- +- +- +- +- Login name +- +- +- +- +- +- +- Login password or passphrase +- +- +- +- +- +- +- Script to run to retrieve password +- +- +- +- +- +- +- Login password or passphrase +- +- +- +- +- +- +- Script to run to retrieve password +- +- +- +- +- +- +- Physical plug number on device, UUID or identification of machine +- +- +- +- +- +- +- Physical plug number on device, UUID or identification of machine +- +- +- +- +- +- +- Use SSH connection +- +- +- +- +- +- +- Use SSH connection +- +- +- +- +- +- +- SSH options to use +- +- +- +- +- +- +- Physical switch number on device +- +- +- +- +- +- +- Login name +- +- +- +- +- +- +- Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. +- +- +- +- +- +- +- Verbose mode +- +- +- +- +- +- +- Write debug information to given file +- +- +- +- +- +- +- Write debug information to given file +- +- +- +- +- +- +- Display version information and exit +- +- +- +- +- +- +- Display help and exit +- +- +- +- +- +- +- Separator for CSV created by 'list' operation +- +- +- +- +- +- +- Wait X seconds before fencing is started +- +- +- +- +- +- +- Wait X seconds for cmd prompt after login +- +- +- +- +- +- +- Test X seconds for status change after ON/OFF +- +- +- +- +- +- +- Wait X seconds after issuing ON/OFF +- +- +- +- +- +- +- Wait X seconds for cmd prompt after issuing command +- +- +- +- +- +- +- Count of attempts to retry power on +- +- +- +- +- +- +- Path to ssh binary +- +- +- +- +- +- +- Path to telnet binary +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml +deleted file mode 100644 +index 5c6e1c3b..00000000 +--- a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml ++++ /dev/null +@@ -1,269 +0,0 @@ +- +- +- +- fence_ilo is an I/O Fencing agent used for HP servers with the Integrated Light Out (iLO) PCI card.The agent opens an SSL connection to the iLO card. Once the SSL connection is established, the agent is able to communicate with the iLO card through an XML stream. +- +- +- http://www.hp.com +- +- +- +- +- +- +- Fencing action +- +- +- +- +- +- +- Forces agent to use IPv4 addresses only +- +- +- +- +- +- +- Forces agent to use IPv6 addresses only +- +- +- +- +- +- +- IP address or hostname of fencing device +- +- +- +- +- +- +- IP address or hostname of fencing device +- +- +- +- +- +- +- TCP/UDP port to use for connection with device +- +- +- +- +- +- +- Login name +- +- +- +- +- +- +- Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up. +- +- +- +- +- +- +- Login password or passphrase +- +- +- +- +- +- +- Script to run to retrieve password +- +- +- +- +- +- +- Login password or passphrase +- +- +- +- +- +- +- Script to run to retrieve password +- +- +- +- +- +- +- IP address or hostname of fencing device (together with --port-as-ip) +- +- +- +- +- +- +- IP address or hostname of fencing device (together with --port-as-ip) +- +- +- +- +- +- +- Force ribcl version to use +- +- +- +- +- +- +- Force ribcl version to use +- +- +- +- +- +- +- Use SSL connection with verifying certificate +- +- +- +- +- +- +- Use SSL connection without verifying certificate +- +- +- +- +- +- +- Use SSL connection with verifying certificate +- +- +- +- +- +- +- Disable TLS negotiation and force TLS1.0. This should only be used for devices that do not support TLS1.1 and up. +- +- +- +- +- +- +- Login name +- +- +- +- +- +- +- Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. +- +- +- +- +- +- +- Verbose mode +- +- +- +- +- +- +- Write debug information to given file +- +- +- +- +- +- +- Write debug information to given file +- +- +- +- +- +- +- Display version information and exit +- +- +- +- +- +- +- Display help and exit +- +- +- +- +- +- +- Wait X seconds before fencing is started +- +- +- +- +- +- +- Wait X seconds for cmd prompt after login +- +- +- +- +- +- +- Make "port/plug" to be an alias to IP address +- +- +- +- +- +- +- Test X seconds for status change after ON/OFF +- +- +- +- +- +- +- Wait X seconds after issuing ON/OFF +- +- +- +- +- +- +- Wait X seconds for cmd prompt after issuing command +- +- +- +- +- +- +- Count of attempts to retry power on +- +- +- +- +- +- +- Path to gnutls-cli binary +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml +new file mode 100644 +index 00000000..fd40fa87 +--- /dev/null ++++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml +@@ -0,0 +1,31 @@ ++ ++ ++ This is an agent with action parameter for pcs tests ++ ++ ++ ++ ++ ++ ++ Fencing action (null, off, on, [reboot], status, list, list-status, monitor, validate-all, metadata) ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml +new file mode 100644 +index 00000000..cdccdd9c +--- /dev/null ++++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml +@@ -0,0 +1,32 @@ ++ ++ ++ This is an agent with method parameter for pcs tests ++ ++ ++ ++ ++ ++ ++ Method to fence ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml +new file mode 100644 +index 00000000..c9fa8008 +--- /dev/null ++++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml +@@ -0,0 +1,22 @@ ++ ++ ++ This is a minimalistic agent for pcs tests ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml +new file mode 100644 +index 00000000..088ca985 +--- /dev/null ++++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml +@@ -0,0 +1,107 @@ ++ ++ ++ This is an agent with params for pcs tests ++ ++ ++ ++ ++ ++ ++ Fencing action ++ ++ ++ ++ ++ ++ ++ IP address or hostname of fencing device ++ ++ ++ ++ ++ ++ ++ IP address or hostname of fencing device ++ ++ ++ ++ ++ ++ ++ Login name ++ ++ ++ ++ ++ ++ ++ Login password or passphrase ++ ++ ++ ++ ++ ++ ++ Login password or passphrase ++ ++ ++ ++ ++ ++ ++ Use SSH connection ++ ++ ++ ++ ++ ++ ++ Use SSH connection ++ ++ ++ ++ ++ ++ ++ Login name ++ ++ ++ ++ ++ ++ ++ Verbose mode ++ ++ ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml +new file mode 100644 +index 00000000..db211744 +--- /dev/null ++++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml +@@ -0,0 +1,22 @@ ++ ++ ++ This is an agent which provides unfencing for pcs tests ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml +deleted file mode 100644 +index 259a1593..00000000 +--- a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml ++++ /dev/null +@@ -1,182 +0,0 @@ +- +- +- fence_scsi is an I/O fencing agent that uses SCSI-3 persistent reservations to control access to shared storage devices. These devices must support SCSI-3 persistent reservations (SPC-3 or greater) as well as the "preempt-and-abort" subcommand. +-The fence_scsi agent works by having each node in the cluster register a unique key with the SCSI device(s). Once registered, a single node will become the reservation holder by creating a "write exclusive, registrants only" reservation on the device(s). The result is that only registered nodes may write to the device(s). When a node failure occurs, the fence_scsi agent will remove the key belonging to the failed node from the device(s). The failed node will no longer be able to write to the device(s). A manual reboot is required. +- +- +- +- +- +- +- +- Fencing action +- +- +- +- +- +- +- Use the APTPL flag for registrations. This option is only used for the 'on' action. +- +- +- +- +- +- +- List of devices to use for current operation. Devices can be comma-separated list of raw devices (eg. /dev/sdc). Each device must support SCSI-3 persistent reservations. +- +- +- +- +- +- +- Key to use for the current operation. This key should be unique to a node. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s). +- +- +- +- +- +- +- Name of the node to be fenced. The node name is used to generate the key value used for the current operation. This option will be ignored when used with the -k option. +- +- +- +- +- +- +- Name of the node to be fenced. The node name is used to generate the key value used for the current operation. This option will be ignored when used with the -k option. +- +- +- +- +- +- +- Log output (stdout and stderr) to file +- +- +- +- +- +- +- Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. +- +- +- +- +- +- +- Verbose mode +- +- +- +- +- +- +- Write debug information to given file +- +- +- +- +- +- +- Write debug information to given file +- +- +- +- +- +- +- Display version information and exit +- +- +- +- +- +- +- Display help and exit +- +- +- +- +- +- +- Wait X seconds before fencing is started +- +- +- +- +- +- +- Wait X seconds for cmd prompt after login +- +- +- +- +- +- +- Test X seconds for status change after ON/OFF +- +- +- +- +- +- +- Wait X seconds after issuing ON/OFF +- +- +- +- +- +- +- Wait X seconds for cmd prompt after issuing command +- +- +- +- +- +- +- Count of attempts to retry power on +- +- +- +- +- +- +- Path to corosync-cmapctl binary +- +- +- +- +- +- +- Path to sg_persist binary +- +- +- +- +- +- +- Path to sg_turs binary +- +- +- +- +- +- +- Path to vgs binary +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml +deleted file mode 100644 +index d359854e..00000000 +--- a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml ++++ /dev/null +@@ -1,120 +0,0 @@ +- +- +- fence_xvm is an I/O Fencing agent which can be used withvirtual machines. +- +- +- +- +- +- +- Specify (stdin) or increment (command line) debug level +- +- +- +- +- +- +- IP Family ([auto], ipv4, ipv6) +- +- +- +- +- +- +- Multicast address (default=225.0.0.12 / ff05::3:1) +- +- +- +- +- +- +- TCP, Multicast, or VMChannel IP port (default=1229) +- +- +- +- +- +- +- Multicast retransmit time (in 1/10sec; default=20) +- +- +- +- +- +- +- Authentication (none, sha1, [sha256], sha512) +- +- +- +- +- +- +- Packet hash strength (none, sha1, [sha256], sha512) +- +- +- +- +- +- +- Shared key file (default=/etc/cluster/fence_xvm.key) +- +- +- +- +- +- +- Virtual Machine (domain name) to fence +- +- +- +- +- +- +- Treat [domain] as UUID instead of domain name. This is provided for compatibility with older fence_xvmd installations. +- +- +- +- +- +- +- Fencing action (null, off, on, [reboot], status, list, list-status, monitor, validate-all, metadata) +- +- +- +- +- +- +- Fencing timeout (in seconds; default=30) +- +- +- +- +- +- +- Fencing delay (in seconds; default=0) +- +- +- +- +- +- +- Virtual Machine (domain name) to fence (deprecated; use port) +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource_mock.py b/pcs_test/tools/bin_mock/pcmk/crm_resource_mock.py +index f1d8d069..58cf25e6 100644 +--- a/pcs_test/tools/bin_mock/pcmk/crm_resource_mock.py ++++ b/pcs_test/tools/bin_mock/pcmk/crm_resource_mock.py +@@ -26,7 +26,6 @@ def get_arg_values(argv, name): + + + def main(): +- # pylint: disable=too-many-branches + argv = sys.argv[1:] + if not argv: + raise AssertionError() +@@ -52,10 +51,11 @@ def main(): + "ocf:pacemaker:remote", + "ocf:pacemaker:Stateful", + "ocf:pacemaker:SystemHealth", +- "stonith:fence_apc", +- "stonith:fence_ilo", +- "stonith:fence_scsi", +- "stonith:fence_xvm", ++ "stonith:fence_pcsmock_action", ++ "stonith:fence_pcsmock_method", ++ "stonith:fence_pcsmock_minimal", ++ "stonith:fence_pcsmock_params", ++ "stonith:fence_pcsmock_unfencing", + "systemd:test@a:b", + ) + # known_agents_map = {item.lower()} +@@ -63,21 +63,11 @@ def main(): + write_local_file_to_stdout( + "{}_metadata.xml".format(arg.replace(":", "__")) + ) +- elif arg == "ocf:pacemaker:nonexistent": +- sys.stderr.write( +- "Metadata query for ocf:pacemaker:nonexistent failed: " +- "Input/output error\n" +- ) +- raise SystemExit(5) +- elif arg == "stonith:fence_noexist": ++ else: + sys.stderr.write( +- "Agent fence_noexist not found or does not support meta-data: " +- "Invalid argument (22)\nMetadata query for " +- "stonith:fence_noexist failed: Input/output error\n" ++ "pcs mock error message: unable to load agent metadata" + ) +- raise SystemExit(5) +- else: +- raise AssertionError() ++ raise SystemExit(1) + elif arg in option_file_map: + if argv: + raise AssertionError() +@@ -100,7 +90,7 @@ def main(): + is_invalid = "fake=is_invalid=True" in argv + output = "" + if is_invalid: +- output = """Validation failure""" ++ output = """pcsmock validation failure""" + stdout = """ + + +diff --git a/pcs_test/tools/bin_mock/pcmk/stonith_admin.in b/pcs_test/tools/bin_mock/pcmk/stonith_admin.in +new file mode 100755 +index 00000000..bf48b5c4 +--- /dev/null ++++ b/pcs_test/tools/bin_mock/pcmk/stonith_admin.in +@@ -0,0 +1,5 @@ ++#!@PYTHON@ ++ ++from stonith_admin_mock import main ++ ++main() +diff --git a/pcs_test/tools/bin_mock/pcmk/stonith_admin_mock.py b/pcs_test/tools/bin_mock/pcmk/stonith_admin_mock.py +new file mode 100644 +index 00000000..133097b5 +--- /dev/null ++++ b/pcs_test/tools/bin_mock/pcmk/stonith_admin_mock.py +@@ -0,0 +1,60 @@ ++import os.path ++import sys ++from textwrap import dedent ++ ++CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) ++DATA_DIR = os.path.join(CURRENT_DIR, "{}.d".format(sys.argv[0])) ++ ++ ++def get_arg_values(argv, name): ++ values = [] ++ next_value = len(argv) ++ for i, value in enumerate(argv): ++ if value == name: ++ next_value = i + 1 ++ elif i == next_value: ++ values.append(value) ++ return values ++ ++ ++def main(): ++ argv = sys.argv[1:] ++ if not argv: ++ raise AssertionError() ++ ++ arg = argv.pop(0) ++ ++ if arg == "--validate": ++ if get_arg_values(argv, "--output-as")[0] != "xml": ++ raise AssertionError() ++ is_invalid = False ++ for arg in argv: ++ if "=" in arg and arg.split("=", 1)[1] == "is_invalid=True": ++ is_invalid = True ++ break ++ output = "" ++ if is_invalid: ++ output = """pcsmock validation failure""" ++ cmd_str = " ".join(sys.argv) ++ agent_type = get_arg_values(argv, "--agent")[0] ++ stdout = dedent( ++ f""" ++ ++ ++ ++ {output} ++ ++ ++ ++ ++ """ ++ ) ++ sys.stdout.write(stdout) ++ if is_invalid: ++ raise SystemExit(1) ++ else: ++ raise AssertionError() ++ ++ ++if __name__ == "__main__": ++ main() +-- +2.45.2 + diff --git a/pcs.spec b/pcs.spec index ec3f7f2..2e39495 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs -Version: 0.11.7 -Release: 5%{?dist} +Version: 0.11.8 +Release: 1%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -17,8 +17,8 @@ BuildArch: noarch %global pcs_source_name %{name}-%{version_or_commit} # ui_commit can be determined by hash, tag or branch -%global ui_commit 0.1.18 -%global ui_modules_version 0.1.18 +%global ui_commit 0.1.20 +%global ui_modules_version 0.1.20 %global ui_src_name pcs-web-ui-%{ui_commit} %global pyagentx_version 0.4.pcs.2 @@ -52,14 +52,16 @@ Source101: https://github.com/ClusterLabs/pcs-web-ui/releases/download/%{ui_comm # pcs patches: <= 200 # Patch0: name.patch +Patch0: overhaul-fence-agents-mocking.patch # ui patches: >200 # Patch201: name-web-ui.patch -Patch201: make-AppStream-metainfo-more-descriptive.patch -Patch202: metainfo-fix-outdated-extends-id.patch # git for patches BuildRequires: git-core +# for building pcs tarballs +BuildRequires: autoconf +BuildRequires: automake BuildRequires: make # printf from coreutils is used in makefile, head is used in spec BuildRequires: coreutils @@ -76,9 +78,6 @@ BuildRequires: python3-cryptography BuildRequires: python3-lxml # for building bundled python packages BuildRequires: python3-wheel -# for bundled python dateutil -# dateutil was unbundled in Fedora but our autotools still check for it -BuildRequires: python3-setuptools_scm # ruby and gems for pcsd BuildRequires: ruby >= 2.5.0 BuildRequires: ruby-devel @@ -113,20 +112,20 @@ BuildRequires: nss-tools BuildRequires: nodejs-npm # cluster stack packages for pkg-config -BuildRequires: booth -BuildRequires: corosync-qdevice-devel -BuildRequires: corosynclib-devel >= 3.0 -BuildRequires: fence-agents-common +# corosync has different package names on distributions but all provide +# corosync-devel +# corosync and pacemaker need versions and it's not working in virtual provides +BuildRequires: corosync-devel >= 3.0 BuildRequires: pacemaker-libs-devel >= %{required_pacemaker_version} -BuildRequires: resource-agents -BuildRequires: sbd +BuildRequires: pkgconfig(booth) +BuildRequires: pkgconfig(corosync-qdevice) +BuildRequires: pkgconfig(sbd) # for validating cockpit-ha-cluster metainfo BuildRequires: libappstream-glib # python and libraries for pcs, setuptools for pcs entrypoint -Requires: python3 >= 3.9 Requires: python3-cryptography Requires: python3-dateutil >= 2.7.0 Requires: python3-lxml @@ -204,7 +203,7 @@ License: GPL-2.0-only AND CC0-1.0 URL: https://github.com/ClusterLabs/pcs-web-ui BuildRequires: make -BuildRequires: npm +BuildRequires: nodejs-npm Requires: pcs = %{version}-%{release} Requires: cockpit-bridge @@ -270,13 +269,12 @@ update_times_patch(){ %autosetup -D -T -b 100 -a 101 -S git -n %{ui_src_name} -N %autopatch -p1 -m 201 # update_times_patch %%{PATCH201} -update_times_patch %%{PATCH201} -update_times_patch %%{PATCH202} # patch pcs sources %autosetup -S git -n %{pcs_source_name} -N %autopatch -p1 -M 200 # update_times_patch %%{PATCH0} +update_times_patch %{PATCH0} # generate .tarball-version if building from an untagged commit, not a released version # autogen uses git-version-gen which uses .tarball-version for generating version number @@ -462,6 +460,10 @@ run_all_tests %changelog +* Tue Aug 6 2024 Michal Pospíšil - 0.11.8-1 +- Rebased to the latest sources (see CHANGELOG.md) +- Updated pcs-web-ui to 0.1.20 + * Thu Jul 18 2024 Fedora Release Engineering - 0.11.7-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild diff --git a/prepare-env.sh b/prepare-env.sh index a0405b7..dc1b377 100755 --- a/prepare-env.sh +++ b/prepare-env.sh @@ -13,6 +13,6 @@ cd builddir/pcs-* export PYTHONPATH=/usr/lib/pcs/pcs_bundled/packages/ export GEM_HOME=/usr/lib/pcsd/vendor/bundle/ ./autogen.sh -./configure --with-pcs-lib-dir=/usr/lib --with-distro=fedora +./configure --with-pcs-lib-dir=/usr/lib # Remove pcs sources to make sure tests are not using any of those files rm -rf pcs diff --git a/sources b/sources index 27bf1eb..7582c05 100644 --- a/sources +++ b/sources @@ -1,5 +1,5 @@ SHA512 (pyagentx-0.4.pcs.2.tar.gz) = d4194fec9a3e5fefe3793d49b7fec1feafef294c7e613a06046c2993daeefc5cb39d7c5b2b402ff83e49b2d976953f862264288c758c0be09d997b5323cc558a SHA512 (dacite-1.8.1.tar.gz) = 4b40c0bdcf5490bcc77de9e7f04b7267642bcfd41e4168607a5457f38abe3ad4b3041d8a23cb43af76de14eabee45f900ad5ddf7af8f70a2be4850bccc2d3af1 -SHA512 (pcs-0.11.7.tar.gz) = 29d61bb945b25ced67e3a05f742ab6f557da8c4d3e8ee04db8caa9a51bb1c64e64cd5382f801173d95e9d62c53a52ad86f823c475ba790cb86b777a1eff658cc -SHA512 (pcs-web-ui-0.1.18.tar.gz) = edbe88d113e967b2d3f345e74e8c4409b013fb8474fe70a8813a1aba5ea8b4deb61a3bb8c4cd4b4d1a9dc9e67216e518ee5bf832a25188e95173317533d7bf69 -SHA512 (pcs-web-ui-node-modules-0.1.18.tar.xz) = 237ff976d67a7bf881e45334261af1da32c6330fbf9e7436dcf33e63c9373f85f36db52622676f77e27bb6a853c046223cfe0cca25de68bd004c6535aa077fd7 +SHA512 (pcs-0.11.8.tar.gz) = 2705b612c602e9052405e448dc189f632f0266bf0d8381981a1dca709f3e851e90745bc02c2f9dfaa9e84d9ab0f3f1287467388d7d584e7e9e5ec4a46b8c2076 +SHA512 (pcs-web-ui-0.1.20.tar.gz) = 83117eafbe694b133228dfd8d7de30a7cc58693b8844f7d1af9c12c02618a7af8dd10c374b56c3e722d84c5691488f25bfc3389f22954935a2e6dd42b16c7b2c +SHA512 (pcs-web-ui-node-modules-0.1.20.tar.xz) = 94cd6a306a6784c3decc351b1469efe98beadd43efbfa7848ccc6146be32f704281432669589e2c666b431a32bd6caf101fa08fb05deaab2b58a8cda8b40b85d From dd5c28916c180b3435e82277fb59350bc109cc35 Mon Sep 17 00:00:00 2001 From: Michal Pospisil Date: Tue, 30 Jul 2024 17:53:10 +0200 Subject: [PATCH 11/26] rpm induced gating changes Changes to builddir structure in RPM 4.20 broke the old script for patching sources. Luckily, we can now patch sources with tmt. Gone is also list of packages needed for testing, build dependencies will be installed by tmt instead. Name of the gating plan was changed to remove confusion with gating.yaml. The prepare script was also renamed to better reflect what it does. The prepare script should be run in prepare, but TMT_SOURCE_DIR doesn't exist in that step yet. The workaround is to run the prepre script before every test to allow for running all tests by itself. However, the script can only run once because it removes pcs folder which breaks autotools. This is done by creating a stamp file that prevents the script from running if it already ran. --- gating.fmf | 48 ------------------------------------------------ plan-gating.fmf | 32 ++++++++++++++++++++++++++++++++ prepare-env.sh | 18 ------------------ prepare-tests.sh | 22 ++++++++++++++++++++++ 4 files changed, 54 insertions(+), 66 deletions(-) delete mode 100644 gating.fmf create mode 100644 plan-gating.fmf delete mode 100755 prepare-env.sh create mode 100755 prepare-tests.sh diff --git a/gating.fmf b/gating.fmf deleted file mode 100644 index f452957..0000000 --- a/gating.fmf +++ /dev/null @@ -1,48 +0,0 @@ -summary: PCS gating test plan -description: Runs upstream tier0, tier1 and smoke tests - -discover: - how: shell - dist-git-source: true - tests: - # Workaround until tmt supports patching sources - - name: Patch sources and run autotools - test: ./prepare-env.sh - duration: 30m - - name: Tier 0 tests - test: ./builddir/pcs-*/pcs_test/suite --tier0 -v --vanilla --installed - duration: 10m - - name: Tier 1 tests - test: ./builddir/pcs-*/pcs_test/suite --tier1 -v --vanilla --installed - duration: 2h - - name: Smoke tests - test: | - systemctl start pcsd - ./builddir/pcs-*/pcs_test/smoke.sh - duration: 10m -prepare: - - name: Install packages - how: install - package: - - autoconf - - automake - - make - - rpm-build - - ruby-devel - - git-core - - booth-site - - fence-agents-apc - - fence-agents-ipmilan - - fence-agents-scsi - - fence-virt - - openssl - - pcs - - pcs-snmp - - python3-pip - - python3-setuptools_scm - - python3-wheel - - rubygem-json - - rubygem-test-unit - - wget -execute: - how: tmt diff --git a/plan-gating.fmf b/plan-gating.fmf new file mode 100644 index 0000000..78d1116 --- /dev/null +++ b/plan-gating.fmf @@ -0,0 +1,32 @@ +summary: PCS gating test plan +description: Runs upstream tier0, tier1 and smoke tests + +discover: + dist-git-source: true + dist-git-install-builddeps: true + how: shell + tests: + - name: tier0 + test: | + ./prepare-tests.sh + $TMT_SOURCE_DIR/pcs-*/pcs_test/suite --tier0 -v --vanilla --installed + duration: 10m + tier: 0 + tag: fast + - name: tier1 + test: | + ./prepare-tests.sh + $TMT_SOURCE_DIR/pcs-*/pcs_test/suite --tier1 -v --vanilla --installed + duration: 2h + tier: 1 + - name: smoke + test: | + systemctl start pcsd + ./prepare-tests.sh + $TMT_SOURCE_DIR/pcs-*/pcs_test/smoke.sh + duration: 10m + tier: smoke + tag: fast + +execute: + how: tmt diff --git a/prepare-env.sh b/prepare-env.sh deleted file mode 100755 index dc1b377..0000000 --- a/prepare-env.sh +++ /dev/null @@ -1,18 +0,0 @@ -set -eo xtrace -# Rpmbuild expects patches in the _sourcedir -find *.patch &> /dev/null && mv *.patch $TMT_SOURCE_DIR -mkdir builddir -rpmbuild -bp pcs.spec --nodeps --define "_sourcedir $TMT_SOURCE_DIR" \ - --define "_builddir $(pwd)/builddir" -# Remove *SPECPARTS folders generated by rpmbuild -rm -rfv builddir/*SPECPARTS -# Remove pcs-web-ui in builddir for "cd pcs-*" to have exactly one match -rm -rf builddir/pcs-web-ui-* -cd builddir/pcs-* -# Run autotools, use bundled dependencies from the system -export PYTHONPATH=/usr/lib/pcs/pcs_bundled/packages/ -export GEM_HOME=/usr/lib/pcsd/vendor/bundle/ -./autogen.sh -./configure --with-pcs-lib-dir=/usr/lib -# Remove pcs sources to make sure tests are not using any of those files -rm -rf pcs diff --git a/prepare-tests.sh b/prepare-tests.sh new file mode 100755 index 0000000..5ecdf1c --- /dev/null +++ b/prepare-tests.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -eo xtrace +cd $TMT_SOURCE_DIR +# Use stamp file to abort if this script already ran +if [ -e tests-prepared-stamp ]; then exit 0; fi +# RPM 4.20 changed the builddir structure - unpacked sources go to *-build but +# tmt copies them back to pcs-*, so the pcs-*-build folder is empty +# Remove pcs-web-ui, pcs-*-build for "cd pcs-*" to have exactly one match +rm -rf pcs-web-ui-* pcs-*-build +cd pcs-*/ +# Run autotools, use bundled dependencies from the system +export PYTHONPATH=/usr/lib/pcs/pcs_bundled/packages/ +export GEM_HOME=/usr/lib/pcsd/vendor/bundle/ +# We need to use cd pcs-* because when pcs-web-ui starts using autotools, running +# autogen and configure with expanded TMT_SOURCE_DIR will match that too +./autogen.sh +./configure --enable-local-build --enable-use-local-cache-only \ + --enable-individual-bundling --with-pcs-lib-dir=/usr/lib +# Remove pcs sources to make sure tests are not using any of those files +rm -rf pcs +touch ../tests-prepared-stamp From a62e4a77c3379f24fa8fdba428082af85a22fed7 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 17 Jan 2025 22:35:25 +0000 Subject: [PATCH 12/26] Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 2e39495..9ee7b5d 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.11.8 -Release: 1%{?dist} +Release: 2%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -460,6 +460,9 @@ run_all_tests %changelog +* Fri Jan 17 2025 Fedora Release Engineering - 0.11.8-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + * Tue Aug 6 2024 Michal Pospíšil - 0.11.8-1 - Rebased to the latest sources (see CHANGELOG.md) - Updated pcs-web-ui to 0.1.20 From c3de7d7354c394a603fda984e4fff0596f7dcf36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Mon, 3 Feb 2025 22:21:46 +0100 Subject: [PATCH 13/26] - Rebased pcs to the newest major version (see CHANGELOG.md) Resolves: rhbz#2341012 - New subpackage pcs-web-ui - enables standalone web UI when the subpackage is installed on the system (default), uninstall the subpackage to disable the web UI - Updated standalone web UI and HA Cluster Management Cockpit application to pcs-web-ui 0.1.22 - Fixes for compatibility with Ruby 3.4 Resolves: rhbz#2331005 - Support tilde in version - for correct sorting of prerelease upstream version by RPM - %{version} expands with the tilde, use %{clean_version} to get upstream version - Added pkgconfig file for pcs - Added previously omitted autotools as build dependencies - Changed BuildRequires for cluster stack components to use pkgconfig virtual provides to prevent breakage if pkgconfig is ever moved to a different package - Removed BuildRequires: nodejs-npm from main package and fixed the name in cockpit-ha-cluster subpackage - the idea is that BuildRequires become Requires of the srpm which are then used during the main build phase when subpackages are built (so BuildRequires are effectively inherited by this logic) - Removed Requires: python3-setuptools. With overhauled setup, new setuptools create entrypoints that do not import setuptools. - Removed Requires: rubygem-rack-test - this is a build requirement. - Improved BuildRequires for systemd scriptlet macros according to packaging guidelines - Replaced ${RPM_BUILD_ROOT} in favor of %buildroot to match the upstream spec - Revamped and unified tarball version management between pcs and pcs-web-ui - version numbers are needed for untagged releases, as git-version-gen takes the version from a git tag present in official released tarballs. To build an unreleased version of pcs, a commit hash is declared in a macro and .tarball-version is generated from rpm version and the hash. For tagged releases, .tarball-version is not generated but rpm version is used for file names and such. Pcs-web-ui uses a different version than pcs, so the rpm version cannot be used. Instead, pcs-web-ui version always has to be declared in the spec file anyway, so it will now serve as the fallback version for generating the .tarball-version for pcs-web-ui. - Added BuildRequires: pkgconf as autotools need to process pc files from cluster packages - Removal of all %post macros for all subpackages, because these are run automatically by systemd via %filetriggerin [1]. The need to restart is from now on indicated by running %posttrans systemd macros which set restart markers, see systemd 248 release notes [2]. This is implementation of a Fedora change proposal [3]. There are %posttrans and %postun macros for pcs-web-ui subpackage since pcsd needs to be restarted to start/stop providing webui or update webui on its installation/update/uninstall. - The path to webui_public_dir passed to pcs-web-ui autotools is hardcoded. The pcs.pc file is not available since pcs is built in the same SRPM. It is not possible to get the path from compiled pc file after running configure from pcs because the %files section is not shell interpreted. It only accepts RPM macros which are replaced by the preprocessor before pcs is compiled. Technically, %files accept a file with paths and pkg-config could be run manually after pcs is compiled outputiing the directory to a temporary file. This hack is too ugly. Another solution would be to hardcode the paths both to pcs and ps-web-ui via autotools. This however doesn;t change the structure of the pcs tarball and is not safe either. - Stopped using sbindir macro due to: https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin [1] https://src.fedoraproject.org/rpms/systemd/blob/1ffa7bf7c74e09fa42525f17e9da5f51c72ada02/f/triggers.systemd [2] https://github.com/systemd/systemd/blob/v248-rc1/NEWS#L360 [3] https://fedoraproject.org/wiki/Changes/Restart_services_at_end_of_rpm_transaction --- .gitignore | 3 + ...lones-by-agent-name-in-resource-tree.patch | 82 + ...-on-systems-with-merged-bin-and-sbin.patch | 66 + overhaul-fence-agents-mocking.patch | 3687 ----------------- pcs.spec | 275 +- ruby-3.4-compatibility.patch | 233 ++ show-info-page-instead-of-webui.patch | 148 + sources | 6 +- 8 files changed, 711 insertions(+), 3789 deletions(-) create mode 100644 fix-filter-clones-by-agent-name-in-resource-tree.patch create mode 100644 fix-install-on-systems-with-merged-bin-and-sbin.patch delete mode 100644 overhaul-fence-agents-mocking.patch create mode 100644 ruby-3.4-compatibility.patch create mode 100644 show-info-page-instead-of-webui.patch diff --git a/.gitignore b/.gitignore index 26b9e4d..b5a80bb 100644 --- a/.gitignore +++ b/.gitignore @@ -118,3 +118,6 @@ /pcs-0.11.8.tar.gz /pcs-web-ui-0.1.20.tar.gz /pcs-web-ui-node-modules-0.1.20.tar.xz +/pcs-0.12.0.tar.gz +/pcs-web-ui-0.1.22.tar.gz +/pcs-web-ui-node-modules-0.1.22.tar.xz diff --git a/fix-filter-clones-by-agent-name-in-resource-tree.patch b/fix-filter-clones-by-agent-name-in-resource-tree.patch new file mode 100644 index 0000000..2ddaf01 --- /dev/null +++ b/fix-filter-clones-by-agent-name-in-resource-tree.patch @@ -0,0 +1,82 @@ +From e949ae0e2fc350ed1e74ce48b50ac812efd92f30 Mon Sep 17 00:00:00 2001 +From: Ivan Devat +Date: Mon, 20 Jan 2025 12:13:25 +0100 +Subject: [PATCH] fix: filter clones by agent name in resource tree + +--- + .../src/app/view/cluster/resources/tree/filter.ts | 13 +++++++------ + .../test/src/test/scenes/resources/tree.test.ts | 14 +++++++++++--- + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/packages/app/src/app/view/cluster/resources/tree/filter.ts b/packages/app/src/app/view/cluster/resources/tree/filter.ts +index 118e6cc2..b047a094 100644 +--- a/packages/app/src/app/view/cluster/resources/tree/filter.ts ++++ b/packages/app/src/app/view/cluster/resources/tree/filter.ts +@@ -1,4 +1,4 @@ +-import {Resource} from "app/view/cluster/types"; ++import type {FenceDevice, Resource} from "app/view/cluster/types"; + + type Group = Extract; + type Clone = Extract; +@@ -14,13 +14,14 @@ const createResourceFilter = (filter: string) => { + const match = (searchable: string) => + searchable.toLowerCase().includes(filter.toLowerCase()); + ++ const matchPrimitive = (primitive: Primitive | FenceDevice) => ++ match(primitive.id) || match(primitive.agentName); ++ + const filterPrimitive = (primitive: Primitive) => +- match(primitive.id) || match(primitive.agentName) ? primitive : null; ++ matchPrimitive(primitive) ? primitive : null; + + const filterGroup = (group: Group): Group | null => { +- const primitives = group.resources.filter( +- primitive => match(primitive.id) || match(primitive.agentName), +- ); ++ const primitives = group.resources.filter(matchPrimitive); + return match(group.id) || primitives.length > 0 + ? {...group, resources: primitives} + : null; +@@ -34,7 +35,7 @@ const createResourceFilter = (filter: string) => { + : null; + } + +- if (match(clone.member.id)) { ++ if (matchPrimitive(clone.member)) { + return clone; + } + +diff --git a/packages/test/src/test/scenes/resources/tree.test.ts b/packages/test/src/test/scenes/resources/tree.test.ts +index f9b118f8..19190955 100644 +--- a/packages/test/src/test/scenes/resources/tree.test.ts ++++ b/packages/test/src/test/scenes/resources/tree.test.ts +@@ -19,7 +19,15 @@ const resourceList = [ + "Clone1", + cs.group("Group2", [cs.primitive("ResourceD"), cs.primitive("ResourceE")]), + ), +- cs.clone("Clone2", cs.primitive("ResourceF")), ++ cs.clone( ++ "Clone2", ++ cs.primitive("ResourceF", { ++ agentname: "ocf:heartbeat:apache", ++ provider: "heartbeat", ++ class: "ocf", ++ type: "apache", ++ }), ++ ), + ]; + + const primitiveItem = (id: string) => +@@ -129,7 +137,7 @@ describe("Resource tree filter", () => { + await isAbsent(groupItem("Group2")); + await isAbsent(primitiveItem("ResourceD")); + await isAbsent(primitiveItem("ResourceE")); +- await isAbsent(cloneItem("Clone2")); +- await isAbsent(primitiveItem("ResourceF")); ++ await isVisible(cloneItem("Clone2")); ++ await isVisible(primitiveItem("ResourceF")); + }); + }); +-- +2.48.1 + diff --git a/fix-install-on-systems-with-merged-bin-and-sbin.patch b/fix-install-on-systems-with-merged-bin-and-sbin.patch new file mode 100644 index 0000000..d75367d --- /dev/null +++ b/fix-install-on-systems-with-merged-bin-and-sbin.patch @@ -0,0 +1,66 @@ +From 5745b7d6fac794a1bf13bad6376958acc6aa714d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= +Date: Mon, 20 Jan 2025 18:00:16 +0100 +Subject: [PATCH 3/3] fix install on systems with merged bin and sbin + +Fedora 42 is planning to symlink the /usr/sbin to /usr/bin directory. To +prevent installation failures, pcs and pcsd binary (entry point) will no +longer be moved to /usr/sbin when such a system is detected. + +Based on: https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin +--- + Makefile.am | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index f552a8b1e..53d3bb364 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -168,6 +168,10 @@ endif + # * Pip installs scripts into bin directory and that cannot be changed, so the + # files are moved manually. Some of the folders do not exist in DESTDIR or + # prefix locations, so they need to be created first, otherwise mv fails ++# * For systems where sbin and bin is merged, autotools should have correctly ++# defined the bindir and SBINDIR macros. If this isn't true, configure can be ++# run with --sbindir equal to bindir. It is assumed that setuptools also use ++# bindir location to output entry point script. + install-exec-local: install_python_embedded_mods stamps/install_ruby_deps_local + if $$(${PYTHON} -c "import sys; exit(sys.base_prefix == sys.prefix)"); then \ + echo "WARNING: Virtual environment is activated, shebangs in Python " \ +@@ -182,10 +186,12 @@ install-exec-local: install_python_embedded_mods stamps/install_ruby_deps_local + ${PIP} ${pipopts} install ${pipinstallopts} \ + --root=$(or ${DESTDIR}, /) \ + --prefix=${prefix} ${EXTRA_SETUP_OPTS} . +- mv ${DESTDIR}/$(prefix)/bin/pcs ${DESTDIR}/$(SBINDIR)/ || \ +- mv ${DESTDIR}/$(prefix)/local/bin/pcs ${DESTDIR}/${prefix}/local/sbin/ +- mv ${DESTDIR}/$(prefix)/bin/pcsd ${DESTDIR}/$(SBINDIR)/ || \ +- mv ${DESTDIR}/$(prefix)/local/bin/pcsd ${DESTDIR}/${prefix}/local/sbin/ ++ if test "${DESTDIR}/$(prefix)/bin/" != "${DESTDIR}/$(SBINDIR)/"; then \ ++ mv ${DESTDIR}/$(prefix)/bin/pcs ${DESTDIR}/$(SBINDIR)/ || \ ++ mv ${DESTDIR}/$(prefix)/local/bin/pcs ${DESTDIR}/${prefix}/local/sbin/; \ ++ mv ${DESTDIR}/$(prefix)/bin/pcsd ${DESTDIR}/$(SBINDIR)/ || \ ++ mv ${DESTDIR}/$(prefix)/local/bin/pcsd ${DESTDIR}/${prefix}/local/sbin/; \ ++ fi + mv ${DESTDIR}/$(prefix)/bin/pcs_internal ${DESTDIR}/$(LIB_DIR)/pcs/ || \ + mv ${DESTDIR}/$(prefix)/local/bin/pcs_internal ${DESTDIR}/${LIB_DIR}/pcs/ + mv ${DESTDIR}/$(prefix)/bin/pcs_snmp_agent ${DESTDIR}/$(LIB_DIR)/pcs/ || \ +@@ -209,10 +215,12 @@ install-exec-local: install_python_embedded_mods stamps/install_ruby_deps_local + # which are untouched by make install. + uninstall-local: + rm -rf ${DESTDIR}/$(PCS_BUNDLED_DIR) +- find ${DESTDIR}/$(prefix)/local/sbin -name pcs -type f -delete || \ +- rm -fv ${DESTDIR}/$(SBINDIR)/pcs +- find ${DESTDIR}/$(prefix)/local/sbin -name pcsd -type f -delete || \ +- rm -fv ${DESTDIR}/$(SBINDIR)/pcsd ++ if test "${DESTDIR}/$(prefix)/bin/" != "${DESTDIR}/$(SBINDIR)/"; then \ ++ find ${DESTDIR}/$(prefix)/local/sbin -name pcs -type f -delete || \ ++ rm -fv ${DESTDIR}/$(SBINDIR)/pcs; \ ++ find ${DESTDIR}/$(prefix)/local/sbin -name pcsd -type f -delete || \ ++ rm -fv ${DESTDIR}/$(SBINDIR)/pcsd; \ ++ fi + rm -fv ${DESTDIR}/$(LIB_DIR)/pcs/pcs_internal + rm -fv ${DESTDIR}/$(LIB_DIR)/pcs/pcs_snmp_agent + sitelib=${DESTDIR}/${prefix}/local/lib/python*/dist-packages; \ +-- +2.48.1 + diff --git a/overhaul-fence-agents-mocking.patch b/overhaul-fence-agents-mocking.patch deleted file mode 100644 index 967e96a..0000000 --- a/overhaul-fence-agents-mocking.patch +++ /dev/null @@ -1,3687 +0,0 @@ -From 96671c6b44e6a599c72bddb384167e7266418e26 Mon Sep 17 00:00:00 2001 -From: Tomas Jelinek -Date: Wed, 24 Jul 2024 14:38:31 +0200 -Subject: [PATCH] tests: overhaul fence agents mocking - -* add a stonith_admin mock to support validating instance atributes by - agents -* rename agents to make it clear we're working with mocks and to show - what each mock is used for -* create custom metedata for agents to fit usecases in tests -* tier1 tests do not require fence agents to be installed in the system, - all is mocked now ---- - .gitignore | 1 + - configure.ac | 1 + - pcs_test/Makefile.am | 11 +- - .../tier1/cib_resource/test_clone_unclone.py | 2 +- - .../tier1/cib_resource/test_stonith_create.py | 169 ++- - .../test_stonith_enable_disable.py | 39 +- - pcs_test/tier1/legacy/test_resource.py | 8 +- - pcs_test/tier1/legacy/test_stonith.py | 1007 +++++------------ - pcs_test/tier1/test_status.py | 20 +- - pcs_test/tools/bin_mock/__init__.py | 4 + - .../stonith__fence_apc_metadata.xml | 277 ----- - .../stonith__fence_ilo_metadata.xml | 269 ----- - ...stonith__fence_pcsmock_action_metadata.xml | 31 + - ...stonith__fence_pcsmock_method_metadata.xml | 32 + - ...tonith__fence_pcsmock_minimal_metadata.xml | 22 + - ...stonith__fence_pcsmock_params_metadata.xml | 107 ++ - ...nith__fence_pcsmock_unfencing_metadata.xml | 22 + - .../stonith__fence_scsi_metadata.xml | 182 --- - .../stonith__fence_xvm_metadata.xml | 120 -- - .../tools/bin_mock/pcmk/crm_resource_mock.py | 28 +- - pcs_test/tools/bin_mock/pcmk/stonith_admin.in | 5 + - .../tools/bin_mock/pcmk/stonith_admin_mock.py | 60 + - 22 files changed, 710 insertions(+), 1707 deletions(-) - delete mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml - delete mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml - create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml - create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml - create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml - create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml - create mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml - delete mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml - delete mode 100644 pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml - create mode 100755 pcs_test/tools/bin_mock/pcmk/stonith_admin.in - create mode 100644 pcs_test/tools/bin_mock/pcmk/stonith_admin_mock.py - -diff --git a/.gitignore b/.gitignore -index b08138ea..6b39468d 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -32,6 +32,7 @@ pcs_test/smoke.sh - pcs_test/tools/bin_mock/pcmk/crm_resource - pcs_test/tools/bin_mock/pcmk/pacemaker_metadata - pcs_test/tools/bin_mock/pcmk/pacemaker-fenced -+pcs_test/tools/bin_mock/pcmk/stonith_admin - pcs_test/resources/*.tmp - pcs_test/resources/temp*.xml - pcs_test/resources/temp* -diff --git a/configure.ac b/configure.ac -index 6ca44faa..71bbd1b3 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -629,6 +629,7 @@ AC_CONFIG_FILES([pcs_test/pcs_for_tests], [chmod +x pcs_test/pcs_for_tests]) - AC_CONFIG_FILES([pcs_test/suite], [chmod +x pcs_test/suite]) - AC_CONFIG_FILES([pcs_test/tools/bin_mock/pcmk/crm_resource], [chmod +x pcs_test/tools/bin_mock/pcmk/crm_resource]) - AC_CONFIG_FILES([pcs_test/tools/bin_mock/pcmk/pacemaker-fenced], [chmod +x pcs_test/tools/bin_mock/pcmk/pacemaker-fenced]) -+AC_CONFIG_FILES([pcs_test/tools/bin_mock/pcmk/stonith_admin], [chmod +x pcs_test/tools/bin_mock/pcmk/stonith_admin]) - AC_CONFIG_FILES([pcsd/pcsd], [chmod +x pcsd/pcsd]) - AC_CONFIG_FILES([scripts/pcsd.sh], [chmod +x scripts/pcsd.sh]) - -diff --git a/pcs_test/Makefile.am b/pcs_test/Makefile.am -index 4ca7d1ee..85dece70 100644 ---- a/pcs_test/Makefile.am -+++ b/pcs_test/Makefile.am -@@ -415,18 +415,19 @@ EXTRA_DIST = \ - tools/bin_mock/pcmk/crm_resource.d/ocf__pacemaker__remote_metadata.xml \ - tools/bin_mock/pcmk/crm_resource.d/ocf__pacemaker__Stateful_metadata.xml \ - tools/bin_mock/pcmk/crm_resource.d/ocf__pacemaker__SystemHealth_metadata.xml \ -- tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml \ -- tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml \ -- tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml \ -- tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml \ -+ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml \ -+ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml \ -+ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml \ -+ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml \ -+ tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml \ - tools/bin_mock/pcmk/crm_resource.d/systemd__test@a__b_metadata.xml \ - tools/bin_mock/pcmk/crm_resource_mock.py \ -- tools/bin_mock/pcmk/pacemaker-fenced \ - tools/bin_mock/pcmk/pacemaker_metadata.d/pacemaker_based.xml \ - tools/bin_mock/pcmk/pacemaker_metadata.d/pacemaker_controld.xml \ - tools/bin_mock/pcmk/pacemaker_metadata.d/pacemaker_fenced.xml \ - tools/bin_mock/pcmk/pacemaker_metadata.d/pacemaker_schedulerd.xml \ - tools/bin_mock/pcmk/pacemaker_metadata.py \ -+ tools/bin_mock/pcmk/stonith_admin_mock.py \ - tools/case_analysis.py \ - tools/check/__init__.py \ - tools/check/test_misc.py \ -diff --git a/pcs_test/tier1/cib_resource/test_clone_unclone.py b/pcs_test/tier1/cib_resource/test_clone_unclone.py -index 9a4c0185..3f991c23 100644 ---- a/pcs_test/tier1/cib_resource/test_clone_unclone.py -+++ b/pcs_test/tier1/cib_resource/test_clone_unclone.py -@@ -34,7 +34,7 @@ FIXTURE_PRIMITIVE_FOR_CLONE = _get_primitive_fixture("C") - FIXTURE_CLONE = f"""{FIXTURE_PRIMITIVE_FOR_CLONE}""" - - FIXTURE_STONITH_FOR_CLONE = """ -- -+ - - -diff --git a/pcs_test/tier1/cib_resource/test_stonith_create.py b/pcs_test/tier1/cib_resource/test_stonith_create.py -index a42c3dd6..9b43a1a2 100644 ---- a/pcs_test/tier1/cib_resource/test_stonith_create.py -+++ b/pcs_test/tier1/cib_resource/test_stonith_create.py -@@ -1,5 +1,3 @@ --import re -- - from pcs_test.tier1.cib_resource.common import ResourceTest - from pcs_test.tools.bin_mock import get_mock_settings - from pcs_test.tools.misc import is_minimum_pacemaker_version -@@ -12,12 +10,17 @@ ERRORS_HAVE_OCCURRED = ( - - - class PlainStonith(ResourceTest): -+ def setUp(self): -+ super().setUp() -+ self.pcs_runner.mock_settings = get_mock_settings( -+ "crm_resource_exec", "stonith_admin_exec" -+ ) -+ - def test_simplest(self): -- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") - self.assert_effect( -- "stonith create S fence_xvm".split(), -+ "stonith create S fence_pcsmock_minimal".split(), - """ -- -+ - - -- -+ - - -@@ -117,16 +81,18 @@ class PlainStonith(ResourceTest): - - - """, -- stderr_full=error, -- stderr_regexp=error_re, -+ stderr_full=( -+ "Warning: Agent 'stonith:absent' is not installed or " -+ "does not provide valid metadata: " -+ "pcs mock error message: unable to load agent metadata\n" -+ ), - ) - - def test_disabled_puts_target_role_stopped(self): -- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") - self.assert_effect( -- "stonith create S fence_xvm --disabled".split(), -+ "stonith create S fence_pcsmock_minimal --disabled".split(), - """ -- -+ - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - - -- -+ - - - -- -+ - - - - -- -+ - - - -- -+ - - - - -- -+ - - - -- -+ - - - - -- -+ - - - - -- -+ - - -- -+ - - -- -+ - - - -- -+ - - - """ - -- self.assert_effect("stonith create S fence_xvm".split(), result_xml) -+ self.assert_effect( -+ "stonith create S fence_pcsmock_minimal".split(), result_xml -+ ) - self.assert_effect("stonith enable S".split(), result_xml) - - - class Disable(ResourceTest): -+ def setUp(self): -+ super().setUp() -+ self.pcs_runner.mock_settings = get_mock_settings( -+ "crm_resource_exec", "stonith_admin_exec" -+ ) -+ - def test_disable_enabled_stonith(self): -- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") - self.assert_effect( -- "stonith create S fence_xvm".split(), -+ "stonith create S fence_pcsmock_minimal".split(), - """ -- -+ - - -- -+ - - -- -+ - - - """ - self.assert_effect( -- "stonith create S fence_xvm --disabled".split(), result_xml -+ "stonith create S fence_pcsmock_minimal --disabled".split(), -+ result_xml, - ) - self.assert_effect("stonith disable S".split(), result_xml) -diff --git a/pcs_test/tier1/legacy/test_resource.py b/pcs_test/tier1/legacy/test_resource.py -index c6709682..ec7bed01 100644 ---- a/pcs_test/tier1/legacy/test_resource.py -+++ b/pcs_test/tier1/legacy/test_resource.py -@@ -138,8 +138,8 @@ class ResourceDescribe(TestCase, AssertPcsMixin): - "resource describe ocf:pacemaker:nonexistent".split(), - ( - "Error: Agent 'ocf:pacemaker:nonexistent' is not installed or does " -- "not provide valid metadata: Metadata query for " -- "ocf:pacemaker:nonexistent failed: Input/output error\n" -+ "not provide valid metadata: " -+ "pcs mock error message: unable to load agent metadata\n" - + ERRORS_HAVE_OCCURRED - ), - ) -@@ -5018,8 +5018,8 @@ class UpdateInstanceAttrs( - agent = "ocf:pacemaker:nonexistent" - message = ( - f"Agent '{agent}' is not installed or does " -- "not provide valid metadata: Metadata query for " -- f"{agent} failed: Input/output error" -+ "not provide valid metadata: " -+ "pcs mock error message: unable to load agent metadata" - ) - self.assert_pcs_success( - f"resource create --force D0 {agent}".split(), -diff --git a/pcs_test/tier1/legacy/test_stonith.py b/pcs_test/tier1/legacy/test_stonith.py -index 6d0bff24..d8d1f4e0 100644 ---- a/pcs_test/tier1/legacy/test_stonith.py -+++ b/pcs_test/tier1/legacy/test_stonith.py -@@ -40,12 +40,12 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - - def test_success(self): - self.assert_pcs_success( -- "stonith describe fence_apc".split(), -+ "stonith describe fence_pcsmock_params".split(), - stdout_start=dedent( - """\ -- fence_apc - Fence agent for APC over telnet/ssh -+ fence_pcsmock_params - Mock agent for pcs tests - agent with various params - -- fence_apc is an I/O Fencing agent which can be used with the APC network power switch. It logs into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions. -+ This is an agent with params for pcs tests - - Stonith options: - """ -@@ -54,7 +54,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - - def test_full(self): - self.assert_pcs_success( -- "stonith describe fence_apc --full".split(), -+ "stonith describe fence_pcsmock_params --full".split(), - stdout_regexp=".*pcmk_list_retries.*", - ) - -@@ -63,10 +63,9 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "stonith describe fence_noexist".split(), - ( - "Error: Agent 'stonith:fence_noexist' is not installed or does not " -- "provide valid metadata: Agent fence_noexist not found or does " -- "not support meta-data: Invalid argument (22), " -- "Metadata query for stonith:fence_noexist failed: Input/output " -- "error\n" + ERRORS_HAVE_OCCURRED -+ "provide valid metadata: " -+ "pcs mock error message: unable to load agent metadata\n" -+ + ERRORS_HAVE_OCCURRED - ), - ) - -@@ -85,17 +84,17 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - def test_pcsd_interface(self): - self.maxDiff = None - stdout, stderr, returncode = self.pcs_runner.run( -- "stonith get_fence_agent_info stonith:fence_apc".split() -+ "stonith get_fence_agent_info stonith:fence_pcsmock_params".split() - ) - self.assertEqual( - json.loads(stdout), - { -- "name": "stonith:fence_apc", -+ "name": "stonith:fence_pcsmock_params", - "standard": "stonith", - "provider": None, -- "type": "fence_apc", -- "shortdesc": "Fence agent for APC over telnet/ssh", -- "longdesc": "fence_apc is an I/O Fencing agent which can be used with the APC network power switch. It logs into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.", -+ "type": "fence_pcsmock_params", -+ "shortdesc": "Mock agent for pcs tests - agent with various params", -+ "longdesc": "This is an agent with params for pcs tests", - "parameters": [ - { - "name": "action", -@@ -115,81 +114,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "unique_group": None, - "reloadable": False, - }, -- { -- "name": "cmd_prompt", -- "shortdesc": "Force Python regex for command prompt", -- "longdesc": None, -- "type": "string", -- "default": "['\\n>', '\\napc>']", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": True, -- "deprecated_by": ["command_prompt"], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "command_prompt", -- "shortdesc": "Force Python regex for command prompt", -- "longdesc": None, -- "type": "string", -- "default": "['\\n>', '\\napc>']", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "identity_file", -- "shortdesc": "Identity file (private key) for SSH", -- "longdesc": None, -- "type": "string", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "inet4_only", -- "shortdesc": "Forces agent to use IPv4 addresses only", -- "longdesc": None, -- "type": "boolean", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "inet6_only", -- "shortdesc": "Forces agent to use IPv6 addresses only", -- "longdesc": None, -- "type": "boolean", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, - { - "name": "ip", - "shortdesc": "IP address or hostname of fencing device", -@@ -220,21 +144,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "unique_group": None, - "reloadable": False, - }, -- { -- "name": "ipport", -- "shortdesc": "TCP/UDP port to use for connection with device", -- "longdesc": None, -- "type": "integer", -- "default": "23", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, - { - "name": "login", - "shortdesc": "Login name", -@@ -265,21 +174,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "unique_group": None, - "reloadable": False, - }, -- { -- "name": "passwd_script", -- "shortdesc": "Script to run to retrieve password", -- "longdesc": None, -- "type": "string", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": True, -- "deprecated_by": ["password_script"], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, - { - "name": "password", - "shortdesc": "Login password or passphrase", -@@ -295,51 +189,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "unique_group": None, - "reloadable": False, - }, -- { -- "name": "password_script", -- "shortdesc": "Script to run to retrieve password", -- "longdesc": None, -- "type": "string", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "plug", -- "shortdesc": "Physical plug number on device, UUID or identification of machine", -- "longdesc": None, -- "type": "string", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "port", -- "shortdesc": "Physical plug number on device, UUID or identification of machine", -- "longdesc": None, -- "type": "string", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": True, -- "deprecated_by": ["plug"], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, - { - "name": "secure", - "shortdesc": "Use SSH connection", -@@ -370,36 +219,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "unique_group": None, - "reloadable": False, - }, -- { -- "name": "ssh_options", -- "shortdesc": "SSH options to use", -- "longdesc": None, -- "type": "string", -- "default": "-1 -c blowfish", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "switch", -- "shortdesc": "Physical switch number on device", -- "longdesc": None, -- "type": "string", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, - { - "name": "username", - "shortdesc": "Login name", -@@ -415,21 +234,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "unique_group": None, - "reloadable": False, - }, -- { -- "name": "quiet", -- "shortdesc": "Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.", -- "longdesc": None, -- "type": "boolean", -- "default": None, -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, - { - "name": "verbose", - "shortdesc": "Verbose mode", -@@ -475,141 +279,6 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "unique_group": None, - "reloadable": False, - }, -- { -- "name": "separator", -- "shortdesc": "Separator for CSV created by 'list' operation", -- "longdesc": None, -- "type": "string", -- "default": ",", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "delay", -- "shortdesc": "Wait X seconds before fencing is started", -- "longdesc": None, -- "type": "second", -- "default": "0", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "login_timeout", -- "shortdesc": "Wait X seconds for cmd prompt after login", -- "longdesc": None, -- "type": "second", -- "default": "5", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "power_timeout", -- "shortdesc": "Test X seconds for status change after ON/OFF", -- "longdesc": None, -- "type": "second", -- "default": "20", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "power_wait", -- "shortdesc": "Wait X seconds after issuing ON/OFF", -- "longdesc": None, -- "type": "second", -- "default": "0", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "shell_timeout", -- "shortdesc": "Wait X seconds for cmd prompt after issuing command", -- "longdesc": None, -- "type": "second", -- "default": "3", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "retry_on", -- "shortdesc": "Count of attempts to retry power on", -- "longdesc": None, -- "type": "integer", -- "default": "1", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "ssh_path", -- "shortdesc": "Path to ssh binary", -- "longdesc": None, -- "type": "string", -- "default": "/usr/bin/ssh", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, -- { -- "name": "telnet_path", -- "shortdesc": "Path to telnet binary", -- "longdesc": None, -- "type": "string", -- "default": "/usr/bin/telnet", -- "enum_values": None, -- "required": False, -- "advanced": False, -- "deprecated": False, -- "deprecated_by": [], -- "deprecated_desc": None, -- "unique_group": None, -- "reloadable": False, -- }, - { - "name": "pcmk_host_argument", - "shortdesc": "An alternate parameter to supply instead of 'port'", -@@ -1018,17 +687,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "on_target": False, - }, - { -- "name": "status", -- "timeout": None, -- "interval": None, -- "role": None, -- "start-delay": None, -- "OCF_CHECK_LEVEL": None, -- "automatic": False, -- "on_target": False, -- }, -- { -- "name": "list", -+ "name": "metadata", - "timeout": None, - "interval": None, - "role": None, -@@ -1038,7 +697,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "on_target": False, - }, - { -- "name": "list-status", -+ "name": "status", - "timeout": None, - "interval": None, - "role": None, -@@ -1058,7 +717,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "on_target": False, - }, - { -- "name": "metadata", -+ "name": "list", - "timeout": None, - "interval": None, - "role": None, -@@ -1068,7 +727,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "on_target": False, - }, - { -- "name": "manpage", -+ "name": "list-status", - "timeout": None, - "interval": None, - "role": None, -@@ -1078,8 +737,8 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "on_target": False, - }, - { -- "name": "validate-all", -- "timeout": None, -+ "name": "stop", -+ "timeout": "20s", - "interval": None, - "role": None, - "start-delay": None, -@@ -1088,7 +747,7 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "on_target": False, - }, - { -- "name": "stop", -+ "name": "start", - "timeout": "20s", - "interval": None, - "role": None, -@@ -1098,8 +757,8 @@ class StonithDescribeTest(TestCase, AssertPcsMixin): - "on_target": False, - }, - { -- "name": "start", -- "timeout": "20s", -+ "name": "validate-all", -+ "timeout": None, - "interval": None, - "role": None, - "start-delay": None, -@@ -1133,7 +792,9 @@ class StonithTest(TestCase, AssertPcsMixin): - self.temp_corosync_conf = get_tmp_file("tier1_test_stonith") - write_file_to_tmpfile(rc("corosync.conf"), self.temp_corosync_conf) - self.pcs_runner = PcsRunner(self.temp_cib.name) -- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") -+ self.pcs_runner.mock_settings = get_mock_settings( -+ "crm_resource_exec", "stonith_admin_exec" -+ ) - self.pcs_runner.mock_settings["corosync_conf_file"] = ( - self.temp_corosync_conf.name - ) -@@ -1142,16 +803,14 @@ class StonithTest(TestCase, AssertPcsMixin): - self.temp_cib.close() - self.temp_corosync_conf.close() - -- @skip_unless_crm_rule() -- def test_stonith_creation(self): -+ def test_stonith_creation_nonexistent_agent(self): - self.assert_pcs_fail( - "stonith create test1 fence_noexist".split(), - ( - "Error: Agent 'stonith:fence_noexist' is not installed or does not " -- "provide valid metadata: Agent fence_noexist not found or does " -- "not support meta-data: Invalid argument (22), " -- "Metadata query for stonith:fence_noexist failed: Input/output " -- "error, use --force to override\n" + ERRORS_HAVE_OCCURRED -+ "provide valid metadata: " -+ "pcs mock error message: unable to load agent metadata, " -+ "use --force to override\n" + ERRORS_HAVE_OCCURRED - ), - ) - -@@ -1159,67 +818,33 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith create test1 fence_noexist --force".split(), - stderr_full=( - "Warning: Agent 'stonith:fence_noexist' is not installed or does not " -- "provide valid metadata: Agent fence_noexist not found or does " -- "not support meta-data: Invalid argument (22), " -- "Metadata query for stonith:fence_noexist failed: Input/output " -- "error\n" -- ), -- ) -- -- self.assert_pcs_fail( -- "stonith create test2 fence_apc".split(), -- ( -- "Error: stonith option 'ip' or 'ipaddr' (deprecated) has to be " -- "specified, use --force to override\n" -- "Error: stonith option 'username' or 'login' (deprecated) has " -- "to be specified, use --force to override\n" -- + ERRORS_HAVE_OCCURRED -+ "provide valid metadata: " -+ "pcs mock error message: unable to load agent metadata\n" - ), - ) - - self.assert_pcs_success( -- "stonith create test2 fence_apc --force".split(), -- stderr_start=( -- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " -- "specified\n" -- "Warning: stonith option 'username' or 'login' (deprecated) has to " -- "be specified\n" -- ), -- ) -- -- self.assert_pcs_fail( -- "stonith create test3 fence_apc bad_argument=test".split(), -- stderr_start=( -- "Error: invalid stonith option 'bad_argument', allowed options are:" -- ), -- ) -- -- self.assert_pcs_fail( -- "stonith create test9 fence_apc pcmk_status_action=xxx".split(), -- ( -- "Error: stonith option 'ip' or 'ipaddr' (deprecated) has to be " -- "specified, use --force to override\n" -- "Error: stonith option 'username' or 'login' (deprecated) has " -- "to be specified, use --force to override\n" -- + ERRORS_HAVE_OCCURRED -+ "stonith config".split(), -+ dedent( -+ """\ -+ Resource: test1 (class=stonith type=fence_noexist) -+ Operations: -+ monitor: test1-monitor-interval-60s -+ interval=60s -+ """ - ), - ) - -+ def test_stonith_creation_pcmk_status_action(self): - self.assert_pcs_success( -- "stonith create test9 fence_apc pcmk_status_action=xxx --force".split(), -- stderr_start=( -- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " -- "specified\n" -- "Warning: stonith option 'username' or 'login' (deprecated) has to " -- "be specified\n" -- ), -+ "stonith create test9 fence_pcsmock_minimal pcmk_status_action=xxx".split(), - ) - - self.assert_pcs_success( - "stonith config test9".split(), - dedent( - """\ -- Resource: test9 (class=stonith type=fence_apc) -+ Resource: test9 (class=stonith type=fence_pcsmock_minimal) - Attributes: test9-instance_attributes - pcmk_status_action=xxx - Operations: -@@ -1229,34 +854,12 @@ class StonithTest(TestCase, AssertPcsMixin): - ), - ) - -- self.assert_pcs_success( -- "stonith delete test9".split(), -- stderr_full="Deleting Resource - test9\n", -- ) -- -- self.assert_pcs_fail( -- "stonith create test3 fence_ilo ip=test".split(), -- ( -- "Error: stonith option 'username' or 'login' (deprecated) has " -- "to be specified, use --force to override\n" -- + ERRORS_HAVE_OCCURRED -- ), -- ) -- -- self.assert_pcs_success( -- "stonith create test3 fence_ilo ip=test --force".split(), -- stderr_start=( -- "Warning: stonith option 'username' or 'login' (deprecated) " -- "has to be specified\n" -- ), -- ) -- -+ def test_stonith_creation_pcmk_params(self): - # Testing that pcmk_host_check, pcmk_host_list & pcmk_host_map are - # allowed for stonith agents - self.assert_pcs_success( - ( -- "stonith create apc-fencing fence_apc ip=morph-apc username=apc " -- "password=apc switch=1 " -+ "stonith create fencing fence_pcsmock_minimal " - "pcmk_host_map=buzz-01:1;buzz-02:2;buzz-03:3;buzz-04:4;buzz-05:5 " - "pcmk_host_check=static-list " - "pcmk_host_list=buzz-01,buzz-02,buzz-03,buzz-04,buzz-05" -@@ -1264,77 +867,105 @@ class StonithTest(TestCase, AssertPcsMixin): - ) - - self.assert_pcs_fail( -- "resource config apc-fencing".split(), -+ "resource config fencing".split(), - ( -- "Warning: Unable to find resource 'apc-fencing'\n" -+ "Warning: Unable to find resource 'fencing'\n" - "Error: No resource found\n" - ), - ) - - self.assert_pcs_success( -- "stonith config apc-fencing".split(), -+ "stonith config fencing".split(), - dedent( - """\ -- Resource: apc-fencing (class=stonith type=fence_apc) -- Attributes: apc-fencing-instance_attributes -- ip=morph-apc -- password=apc -+ Resource: fencing (class=stonith type=fence_pcsmock_minimal) -+ Attributes: fencing-instance_attributes - pcmk_host_check=static-list - pcmk_host_list=buzz-01,buzz-02,buzz-03,buzz-04,buzz-05 - pcmk_host_map=buzz-01:1;buzz-02:2;buzz-03:3;buzz-04:4;buzz-05:5 -- switch=1 -- username=apc - Operations: -- monitor: apc-fencing-monitor-interval-60s -+ monitor: fencing-monitor-interval-60s - interval=60s - """ - ), - ) - -+ def test_stonith_creation_pcmk_host_list(self): -+ self.assert_pcs_success( -+ [ -+ "stonith", -+ "create", -+ "F1", -+ "fence_pcsmock_minimal", -+ "pcmk_host_list=nodea nodeb", -+ ], -+ ) -+ - self.assert_pcs_success( -- "stonith remove apc-fencing".split(), -- stderr_full="Deleting Resource - apc-fencing\n", -+ "stonith config F1".split(), -+ dedent( -+ """\ -+ Resource: F1 (class=stonith type=fence_pcsmock_minimal) -+ Attributes: F1-instance_attributes -+ pcmk_host_list="nodea nodeb" -+ Operations: -+ monitor: F1-monitor-interval-60s -+ interval=60s -+ """ -+ ), - ) - -+ def test_stonith_creation(self): - self.assert_pcs_fail( -+ "stonith create test2 fence_pcsmock_params".split(), - ( -- "stonith create apc-fencing fence_apc ip=morph-apc username=apc " -- "--agent-validation" -- ).split(), -- stderr_start="Error: Validation result from agent", -+ "Error: stonith option 'ip' or 'ipaddr' (deprecated) has to be " -+ "specified, use --force to override\n" -+ "Error: stonith option 'username' or 'login' (deprecated) has " -+ "to be specified, use --force to override\n" -+ + ERRORS_HAVE_OCCURRED -+ ), - ) - - self.assert_pcs_success( -- ( -- "stonith create apc-fencing fence_apc ip=morph-apc username=apc " -- "--agent-validation --force" -- ).split(), -- stderr_start="Warning: Validation result from agent", -+ "stonith create test2 fence_pcsmock_params --force".split(), -+ stderr_start=( -+ "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " -+ "specified\n" -+ "Warning: stonith option 'username' or 'login' (deprecated) has to " -+ "be specified\n" -+ ), - ) - -- self.assert_pcs_success( -- "stonith remove apc-fencing".split(), -- stderr_full="Deleting Resource - apc-fencing\n", -+ self.assert_pcs_fail( -+ "stonith create test3 fence_pcsmock_params bad_argument=test".split(), -+ stderr_start=( -+ "Error: invalid stonith option 'bad_argument', allowed options are:" -+ ), - ) - - self.assert_pcs_fail( -- "stonith update test3 bad_ipaddr=test username=login".split(), -- stderr_regexp=( -- "^Error: invalid stonith option 'bad_ipaddr', allowed options" -- " are: [^\n]+, use --force to override\n$" -+ "stonith create test3 fence_pcsmock_params ip=test".split(), -+ ( -+ "Error: stonith option 'username' or 'login' (deprecated) has " -+ "to be specified, use --force to override\n" -+ + ERRORS_HAVE_OCCURRED - ), - ) - - self.assert_pcs_success( -- "stonith update test3 username=testA --agent-validation".split(), -- stderr_start="Warning: The resource was misconfigured before the update,", -+ "stonith create test3 fence_pcsmock_params ip=test --force".split(), -+ stderr_start=( -+ "Warning: stonith option 'username' or 'login' (deprecated) " -+ "has to be specified\n" -+ ), - ) - - self.assert_pcs_success( - "stonith config test2".split(), - dedent( - """\ -- Resource: test2 (class=stonith type=fence_apc) -+ Resource: test2 (class=stonith type=fence_pcsmock_params) - Operations: - monitor: test2-monitor-interval-60s - interval=60s -@@ -1346,18 +977,13 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith config".split(), - dedent( - """\ -- Resource: test1 (class=stonith type=fence_noexist) -- Operations: -- monitor: test1-monitor-interval-60s -- interval=60s -- Resource: test2 (class=stonith type=fence_apc) -+ Resource: test2 (class=stonith type=fence_pcsmock_params) - Operations: - monitor: test2-monitor-interval-60s - interval=60s -- Resource: test3 (class=stonith type=fence_ilo) -+ Resource: test3 (class=stonith type=fence_pcsmock_params) - Attributes: test3-instance_attributes - ip=test -- username=testA - Operations: - monitor: test3-monitor-interval-60s - interval=60s -@@ -1370,23 +996,16 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith", - "create", - "test-fencing", -- "fence_apc", -+ "fence_pcsmock_minimal", - "pcmk_host_list=rhel7-node1 rhel7-node2", - "op", - "monitor", - "interval=61s", -- "--force", - ], -- stderr_start=( -- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to " -- "be specified\n" -- "Warning: stonith option 'username' or 'login' (deprecated) has to " -- "be specified\n" -- ), - ) - - self.assert_pcs_success( -- "config show".split(), -+ "config".split(), - dedent( - """\ - Cluster Name: test99 -@@ -1395,22 +1014,17 @@ class StonithTest(TestCase, AssertPcsMixin): - Pacemaker Nodes: - - Stonith Devices: -- Resource: test1 (class=stonith type=fence_noexist) -- Operations: -- monitor: test1-monitor-interval-60s -- interval=60s -- Resource: test2 (class=stonith type=fence_apc) -+ Resource: test2 (class=stonith type=fence_pcsmock_params) - Operations: - monitor: test2-monitor-interval-60s - interval=60s -- Resource: test3 (class=stonith type=fence_ilo) -+ Resource: test3 (class=stonith type=fence_pcsmock_params) - Attributes: test3-instance_attributes - ip=test -- username=testA - Operations: - monitor: test3-monitor-interval-60s - interval=60s -- Resource: test-fencing (class=stonith type=fence_apc) -+ Resource: test-fencing (class=stonith type=fence_pcsmock_minimal) - Attributes: test-fencing-instance_attributes - pcmk_host_list="rhel7-node1 rhel7-node2" - Operations: -@@ -1420,10 +1034,81 @@ class StonithTest(TestCase, AssertPcsMixin): - ), - ) - -+ def test_stonith_agent_validation(self): -+ self.pcs_runner.mock_settings = get_mock_settings( -+ "crm_resource_exec", "stonith_admin_exec" -+ ) -+ self.assert_pcs_fail( -+ ( -+ "stonith create fencing fence_pcsmock_params " -+ "ip=is_invalid=True username=apc " -+ "--agent-validation" -+ ).split(), -+ stderr_full=( -+ "Error: Validation result from agent (use --force to override):\n" -+ " pcsmock validation failure\n" + ERRORS_HAVE_OCCURRED -+ ), -+ ) -+ -+ self.assert_pcs_success( -+ ( -+ "stonith create fencing fence_pcsmock_params " -+ "ip=is_invalid=True username=apc " -+ "--agent-validation --force" -+ ).split(), -+ stderr_full=( -+ "Warning: Validation result from agent:\n" -+ " pcsmock validation failure\n" -+ ), -+ ) -+ -+ self.assert_pcs_success( -+ "stonith config".split(), -+ dedent( -+ """\ -+ Resource: fencing (class=stonith type=fence_pcsmock_params) -+ Attributes: fencing-instance_attributes -+ ip="is_invalid=True" -+ username=apc -+ Operations: -+ monitor: fencing-monitor-interval-60s -+ interval=60s -+ """ -+ ), -+ ) -+ -+ self.assert_pcs_fail( -+ "stonith update fencing bad_ipaddr=test username=login".split(), -+ stderr_regexp=( -+ "^Error: invalid stonith option 'bad_ipaddr', allowed options" -+ " are: [^\n]+, use --force to override\n$" -+ ), -+ ) -+ -+ self.assert_pcs_success( -+ "stonith update fencing username=testA --agent-validation".split(), -+ stderr_start="Warning: The resource was misconfigured before the update,", -+ ) -+ -+ self.assert_pcs_success( -+ "stonith config".split(), -+ dedent( -+ """\ -+ Resource: fencing (class=stonith type=fence_pcsmock_params) -+ Attributes: fencing-instance_attributes -+ ip="is_invalid=True" -+ username=testA -+ Operations: -+ monitor: fencing-monitor-interval-60s -+ interval=60s -+ """ -+ ), -+ ) -+ - def test_stonith_create_requires_either_new_or_deprecated(self): - # 'ipaddr' and 'login' are obsoleted by 'ip' and 'username' - self.assert_pcs_fail( -- "stonith create test2 fence_apc".split(), -+ "stonith create test2 fence_pcsmock_params".split(), - ( - "Error: stonith option 'ip' or 'ipaddr' (deprecated) has to be " - "specified, use --force to override\n" -@@ -1436,7 +1121,7 @@ class StonithTest(TestCase, AssertPcsMixin): - def test_stonith_create_deprecated_and_obsoleting(self): - # 'ipaddr' and 'login' are obsoleted by 'ip' and 'username' - self.assert_pcs_success( -- "stonith create S fence_apc ip=i login=l password=1234".split(), -+ "stonith create S fence_pcsmock_params ip=i login=l password=1234".split(), - stderr_full=( - "Warning: stonith option 'login' is deprecated and might be " - "removed in a future release, therefore it should not be " -@@ -1447,7 +1132,7 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith config S".split(), - dedent( - """\ -- Resource: S (class=stonith type=fence_apc) -+ Resource: S (class=stonith type=fence_pcsmock_params) - Attributes: S-instance_attributes - ip=i - login=l -@@ -1466,7 +1151,7 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith", - "create", - "S", -- "fence_apc", -+ "fence_pcsmock_params", - "ip=i1", - "login=l", - "ipaddr=i2", -@@ -1486,7 +1171,7 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith config S".split(), - dedent( - """\ -- Resource: S (class=stonith type=fence_apc) -+ Resource: S (class=stonith type=fence_pcsmock_params) - Attributes: S-instance_attributes - ip=i1 - ipaddr=i2 -@@ -1501,65 +1186,62 @@ class StonithTest(TestCase, AssertPcsMixin): - ) - - def test_stonith_create_provides_unfencing(self): -- self.assert_pcs_success_ignore_output( -- ("stonith", "create", "f1", "fence_scsi", "--force") -+ self.assert_pcs_success( -+ ("stonith", "create", "f1", "fence_pcsmock_unfencing") - ) -- self.assert_pcs_success_ignore_output( -+ self.assert_pcs_success( - ( - "stonith", - "create", - "f2", -- "fence_scsi", -+ "fence_pcsmock_unfencing", - "meta", - "provides=unfencing", -- "--force", - ) - ) -- self.assert_pcs_success_ignore_output( -+ self.assert_pcs_success( - ( - "stonith", - "create", - "f3", -- "fence_scsi", -+ "fence_pcsmock_unfencing", - "meta", - "provides=something", -- "--force", - ) - ) -- self.assert_pcs_success_ignore_output( -+ self.assert_pcs_success( - ( - "stonith", - "create", - "f4", -- "fence_xvm", -+ "fence_pcsmock_minimal", - "meta", - "provides=something", -- "--force", - ) - ) - self.assert_pcs_success( - "stonith config".split(), - dedent( - """\ -- Resource: f1 (class=stonith type=fence_scsi) -+ Resource: f1 (class=stonith type=fence_pcsmock_unfencing) - Meta Attributes: f1-meta_attributes - provides=unfencing - Operations: - monitor: f1-monitor-interval-60s - interval=60s -- Resource: f2 (class=stonith type=fence_scsi) -+ Resource: f2 (class=stonith type=fence_pcsmock_unfencing) - Meta Attributes: f2-meta_attributes - provides=unfencing - Operations: - monitor: f2-monitor-interval-60s - interval=60s -- Resource: f3 (class=stonith type=fence_scsi) -+ Resource: f3 (class=stonith type=fence_pcsmock_unfencing) - Meta Attributes: f3-meta_attributes - provides=unfencing - Operations: - monitor: f3-monitor-interval-60s - interval=60s -- Resource: f4 (class=stonith type=fence_xvm) -+ Resource: f4 (class=stonith type=fence_pcsmock_minimal) - Meta Attributes: f4-meta_attributes - provides=something - Operations: -@@ -1571,7 +1253,7 @@ class StonithTest(TestCase, AssertPcsMixin): - - def test_stonith_create_action(self): - self.assert_pcs_fail( -- "stonith create test fence_apc ip=i username=u action=a".split(), -+ "stonith create test fence_pcsmock_action action=a".split(), - ( - "Error: stonith option 'action' is deprecated and might be " - "removed in a future release, therefore it should not be" -@@ -1581,7 +1263,7 @@ class StonithTest(TestCase, AssertPcsMixin): - ) - - self.assert_pcs_success( -- "stonith create test fence_apc ip=i username=u action=a --force".split(), -+ "stonith create test fence_pcsmock_action action=a --force".split(), - stderr_start=( - "Warning: stonith option 'action' is deprecated and might be " - "removed in a future release, therefore it should not be " -@@ -1593,11 +1275,9 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith config".split(), - dedent( - """\ -- Resource: test (class=stonith type=fence_apc) -+ Resource: test (class=stonith type=fence_pcsmock_action) - Attributes: test-instance_attributes - action=a -- ip=i -- username=u - Operations: - monitor: test-monitor-interval-60s - interval=60s -@@ -1607,24 +1287,20 @@ class StonithTest(TestCase, AssertPcsMixin): - - def test_stonith_create_action_empty(self): - self.assert_pcs_fail( -- "stonith create test fence_apc ip=i username=u action=".split(), -+ "stonith create test fence_pcsmock_action action=".split(), - "Error: action cannot be empty\n" + ERRORS_HAVE_OCCURRED, - ) - - def test_stonith_update_action(self): - self.assert_pcs_success( -- "stonith create test fence_apc ip=i username=u password=1234".split() -+ "stonith create test fence_pcsmock_action".split() - ) - - self.assert_pcs_success( - "stonith config".split(), - dedent( - """\ -- Resource: test (class=stonith type=fence_apc) -- Attributes: test-instance_attributes -- ip=i -- password=1234 -- username=u -+ Resource: test (class=stonith type=fence_pcsmock_action) - Operations: - monitor: test-monitor-interval-60s - interval=60s -@@ -1655,12 +1331,9 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith config".split(), - dedent( - """\ -- Resource: test (class=stonith type=fence_apc) -+ Resource: test (class=stonith type=fence_pcsmock_action) - Attributes: test-instance_attributes - action=a -- ip=i -- password=1234 -- username=u - Operations: - monitor: test-monitor-interval-60s - interval=60s -@@ -1674,11 +1347,7 @@ class StonithTest(TestCase, AssertPcsMixin): - "stonith config".split(), - dedent( - """\ -- Resource: test (class=stonith type=fence_apc) -- Attributes: test-instance_attributes -- ip=i -- password=1234 -- username=u -+ Resource: test (class=stonith type=fence_pcsmock_action) - Operations: - monitor: test-monitor-interval-60s - interval=60s -@@ -1697,74 +1366,29 @@ class StonithTest(TestCase, AssertPcsMixin): - "Error: must specify one (and only one) node to confirm fenced\n", - ) - -- def test_pcmk_host_list(self): -- self.assert_pcs_success( -- [ -- "stonith", -- "create", -- "F1", -- "fence_apc", -- "pcmk_host_list=nodea nodeb", -- "--force", -- ], -- stderr_start=( -- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " -- "specified\n" -- "Warning: stonith option 'username' or 'login' (deprecated) has to " -- "be specified\n" -- ), -- ) -- -- self.assert_pcs_success( -- "stonith config F1".split(), -- dedent( -- """\ -- Resource: F1 (class=stonith type=fence_apc) -- Attributes: F1-instance_attributes -- pcmk_host_list="nodea nodeb" -- Operations: -- monitor: F1-monitor-interval-60s -- interval=60s -- """ -- ), -- ) -- - def test_stonith_delete_removes_level(self): - shutil.copyfile(rc("cib-empty-with3nodes.xml"), self.temp_cib.name) - -- deprecated_warnings = ( -- "Warning: stonith option 'ip' or 'ipaddr' (deprecated) has to be " -- "specified\n" -- "Warning: stonith option 'username' or 'login' (deprecated) has to " -- "be specified\n" -- ) - self.assert_pcs_success( -- "stonith create n1-ipmi fence_apc --force".split(), -- stderr_start=deprecated_warnings, -+ "stonith create n1-ipmi fence_pcsmock_minimal".split(), - ) - self.assert_pcs_success( -- "stonith create n2-ipmi fence_apc --force".split(), -- stderr_start=deprecated_warnings, -+ "stonith create n2-ipmi fence_pcsmock_minimal".split(), - ) - self.assert_pcs_success( -- "stonith create n1-apc1 fence_apc --force".split(), -- stderr_start=deprecated_warnings, -+ "stonith create n1-apc1 fence_pcsmock_minimal".split(), - ) - self.assert_pcs_success( -- "stonith create n1-apc2 fence_apc --force".split(), -- stderr_start=deprecated_warnings, -+ "stonith create n1-apc2 fence_pcsmock_minimal".split(), - ) - self.assert_pcs_success( -- "stonith create n2-apc1 fence_apc --force".split(), -- stderr_start=deprecated_warnings, -+ "stonith create n2-apc1 fence_pcsmock_minimal".split(), - ) - self.assert_pcs_success( -- "stonith create n2-apc2 fence_apc --force".split(), -- stderr_start=deprecated_warnings, -+ "stonith create n2-apc2 fence_pcsmock_minimal".split(), - ) - self.assert_pcs_success( -- "stonith create n2-apc3 fence_apc --force".split(), -- stderr_start=deprecated_warnings, -+ "stonith create n2-apc3 fence_pcsmock_minimal".split(), - ) - self.assert_pcs_success_all( - [ -@@ -1780,13 +1404,13 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- * n1-ipmi\t(stonith:fence_apc):\tStopped -- * n2-ipmi\t(stonith:fence_apc):\tStopped -- * n1-apc1\t(stonith:fence_apc):\tStopped -- * n1-apc2\t(stonith:fence_apc):\tStopped -- * n2-apc1\t(stonith:fence_apc):\tStopped -- * n2-apc2\t(stonith:fence_apc):\tStopped -- * n2-apc3\t(stonith:fence_apc):\tStopped -+ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-apc2\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1804,13 +1428,13 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- n1-ipmi\t(stonith:fence_apc):\tStopped -- n2-ipmi\t(stonith:fence_apc):\tStopped -- n1-apc1\t(stonith:fence_apc):\tStopped -- n1-apc2\t(stonith:fence_apc):\tStopped -- n2-apc1\t(stonith:fence_apc):\tStopped -- n2-apc2\t(stonith:fence_apc):\tStopped -- n2-apc3\t(stonith:fence_apc):\tStopped -+ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-apc2\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1833,12 +1457,12 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- * n1-ipmi\t(stonith:fence_apc):\tStopped -- * n2-ipmi\t(stonith:fence_apc):\tStopped -- * n1-apc1\t(stonith:fence_apc):\tStopped -- * n1-apc2\t(stonith:fence_apc):\tStopped -- * n2-apc1\t(stonith:fence_apc):\tStopped -- * n2-apc3\t(stonith:fence_apc):\tStopped -+ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1856,12 +1480,12 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- n1-ipmi\t(stonith:fence_apc):\tStopped -- n2-ipmi\t(stonith:fence_apc):\tStopped -- n1-apc1\t(stonith:fence_apc):\tStopped -- n1-apc2\t(stonith:fence_apc):\tStopped -- n2-apc1\t(stonith:fence_apc):\tStopped -- n2-apc3\t(stonith:fence_apc):\tStopped -+ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1884,11 +1508,11 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- * n1-ipmi\t(stonith:fence_apc):\tStopped -- * n2-ipmi\t(stonith:fence_apc):\tStopped -- * n1-apc1\t(stonith:fence_apc):\tStopped -- * n1-apc2\t(stonith:fence_apc):\tStopped -- * n2-apc3\t(stonith:fence_apc):\tStopped -+ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1906,11 +1530,11 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- n1-ipmi\t(stonith:fence_apc):\tStopped -- n2-ipmi\t(stonith:fence_apc):\tStopped -- n1-apc1\t(stonith:fence_apc):\tStopped -- n1-apc2\t(stonith:fence_apc):\tStopped -- n2-apc3\t(stonith:fence_apc):\tStopped -+ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-apc3\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1933,10 +1557,10 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- * n1-ipmi\t(stonith:fence_apc):\tStopped -- * n2-ipmi\t(stonith:fence_apc):\tStopped -- * n1-apc1\t(stonith:fence_apc):\tStopped -- * n1-apc2\t(stonith:fence_apc):\tStopped -+ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1953,10 +1577,10 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- n1-ipmi\t(stonith:fence_apc):\tStopped -- n2-ipmi\t(stonith:fence_apc):\tStopped -- n1-apc1\t(stonith:fence_apc):\tStopped -- n1-apc2\t(stonith:fence_apc):\tStopped -+ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc1\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1978,9 +1602,9 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- * n1-ipmi\t(stonith:fence_apc):\tStopped -- * n2-ipmi\t(stonith:fence_apc):\tStopped -- * n1-apc2\t(stonith:fence_apc):\tStopped -+ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -1997,9 +1621,9 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- n1-ipmi\t(stonith:fence_apc):\tStopped -- n2-ipmi\t(stonith:fence_apc):\tStopped -- n1-apc2\t(stonith:fence_apc):\tStopped -+ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n1-apc2\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -2021,8 +1645,8 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- * n1-ipmi\t(stonith:fence_apc):\tStopped -- * n2-ipmi\t(stonith:fence_apc):\tStopped -+ * n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ * n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -2038,8 +1662,8 @@ class StonithTest(TestCase, AssertPcsMixin): - ["stonith"], - outdent( - """\ -- n1-ipmi\t(stonith:fence_apc):\tStopped -- n2-ipmi\t(stonith:fence_apc):\tStopped -+ n1-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped -+ n2-ipmi\t(stonith:fence_pcsmock_minimal):\tStopped - - Fencing Levels: - Target: rh7-1 -@@ -2058,11 +1682,8 @@ class StonithTest(TestCase, AssertPcsMixin): - ) - - self.pcs_runner.corosync_conf_opt = None -- self.assert_pcs_success_ignore_output( -- ( -- "stonith create test_stonith fence_apc ip=i username=u " -- "pcmk_host_argument=node1 --force" -- ).split() -+ self.assert_pcs_success( -+ "stonith create test_stonith fence_pcsmock_minimal".split() - ) - - self.pcs_runner.corosync_conf_opt = self.temp_corosync_conf.name -@@ -2092,16 +1713,16 @@ _fixture_stonith_level_cache_lock = Lock() - - class StonithLevelTestCibFixture(CachedCibFixture): - def _fixture_stonith_resource(self, name): -- self.assert_pcs_success_ignore_output( -+ self._pcs_runner.mock_settings = get_mock_settings( -+ "crm_resource_exec", "stonith_admin_exec" -+ ) -+ self.assert_pcs_success( - [ - "stonith", - "create", - name, -- "fence_apc", -+ "fence_pcsmock_minimal", - "pcmk_host_list=rh7-1 rh7-2", -- "ip=i", -- "username=u", -- "--force", - ] - ) - -@@ -2136,7 +1757,9 @@ class LevelTestsBase(TestCase, AssertPcsMixin): - self.temp_cib = get_tmp_file("tier1_test_stonith_level") - write_file_to_tmpfile(rc("cib-empty-withnodes.xml"), self.temp_cib) - self.pcs_runner = PcsRunner(self.temp_cib.name) -- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") -+ self.pcs_runner.mock_settings = get_mock_settings( -+ "crm_resource_exec", "stonith_admin_exec" -+ ) - self.config = "" - self.config_lines = [] - -@@ -2144,16 +1767,13 @@ class LevelTestsBase(TestCase, AssertPcsMixin): - self.temp_cib.close() - - def fixture_stonith_resource(self, name): -- self.assert_pcs_success_ignore_output( -+ self.assert_pcs_success( - [ - "stonith", - "create", - name, -- "fence_apc", -+ "fence_pcsmock_minimal", - "pcmk_host_list=rh7-1 rh7-2", -- "ip=i", -- "username=u", -- "--force", - ] - ) - -@@ -2597,17 +2217,17 @@ class LevelConfig(LevelTestsBase): - if PCMK_2_0_3_PLUS: - result = outdent( - """\ -- * F1\t(stonith:fence_apc):\tStopped -- * F2\t(stonith:fence_apc):\tStopped -- * F3\t(stonith:fence_apc):\tStopped -+ * F1\t(stonith:fence_pcsmock_minimal):\tStopped -+ * F2\t(stonith:fence_pcsmock_minimal):\tStopped -+ * F3\t(stonith:fence_pcsmock_minimal):\tStopped - """ - ) - else: - result = outdent( - """\ -- F1\t(stonith:fence_apc):\tStopped -- F2\t(stonith:fence_apc):\tStopped -- F3\t(stonith:fence_apc):\tStopped -+ F1\t(stonith:fence_pcsmock_minimal):\tStopped -+ F2\t(stonith:fence_pcsmock_minimal):\tStopped -+ F3\t(stonith:fence_pcsmock_minimal):\tStopped - """ - ) - self.assert_pcs_success( -@@ -2628,27 +2248,21 @@ class LevelConfig(LevelTestsBase): - indent( - dedent( - """ -- Resource: F1 (class=stonith type=fence_apc) -+ Resource: F1 (class=stonith type=fence_pcsmock_minimal) - Attributes: F1-instance_attributes -- ip=i - pcmk_host_list="rh7-1 rh7-2" -- username=u - Operations: - monitor: F1-monitor-interval-60s - interval=60s -- Resource: F2 (class=stonith type=fence_apc) -+ Resource: F2 (class=stonith type=fence_pcsmock_minimal) - Attributes: F2-instance_attributes -- ip=i - pcmk_host_list="rh7-1 rh7-2" -- username=u - Operations: - monitor: F2-monitor-interval-60s - interval=60s -- Resource: F3 (class=stonith type=fence_apc) -+ Resource: F3 (class=stonith type=fence_pcsmock_minimal) - Attributes: F3-instance_attributes -- ip=i - pcmk_host_list="rh7-1 rh7-2" -- username=u - Operations: - monitor: F3-monitor-interval-60s - interval=60s -@@ -3383,26 +2997,19 @@ class LevelVerify(LevelTestsBase): - - - class StonithUpdate(ResourceTest): -- # added in fence-agents-all-4.11.0 -- agent_secure_warning = ( -- "(" -- "Warning: Validation result from agent:\n" -- " WARNING:root:Parse error: Ignoring option 'secure' because it does " -- "not have value\n" -- ")?" -- ) -- - def setUp(self): - super().setUp() -- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") -+ self.pcs_runner.mock_settings = get_mock_settings( -+ "crm_resource_exec", "stonith_admin_exec" -+ ) - self.fixture_create_stonith() - - def fixture_create_stonith(self): - self.assert_effect( -- "stonith create S fence_apc ip=i login=l ssh=0 debug=d password=1234".split(), -+ "stonith create S fence_pcsmock_params ip=i login=l ssh=0 debug=d password=1234".split(), - """ - -- -+ - - - - """, -- stderr_regexp=( -+ stderr_full=( - "Warning: stonith option 'login' is deprecated and might be " - "removed in a future release, therefore it should not " - "be used, use 'username' instead\n" - "Warning: stonith option 'debug' is deprecated and might be " - "removed in a future release, therefore it should not " - "be used, use 'debug_file' instead\n" -- + self.agent_secure_warning - ), - ) - -@@ -3444,7 +3050,7 @@ class StonithUpdate(ResourceTest): - "stonith update S debug=D".split(), - """ - -- -+ - - - - """, -- stderr_regexp=( -+ stderr_full=( - "Warning: stonith option 'debug' is deprecated and might be " - "removed in a future release, therefore it should not " - "be used, use 'debug_file' instead\n" -- + self.agent_secure_warning - ), - ) - -@@ -3483,7 +3088,7 @@ class StonithUpdate(ResourceTest): - "stonith update S debug=".split(), - """ - -- -+ - - - - """, -- stderr_regexp=self.agent_secure_warning, - ) - - def test_unset_deprecated_required_param(self): -@@ -3521,7 +3125,7 @@ class StonithUpdate(ResourceTest): - "stonith update S ssh=1".split(), - """ - -- -+ - - -- -+ - - -- -+ - - - - """, -- stderr_regexp=self.agent_secure_warning, - ) - - def test_unset_obsoleting_required_set_deprecated(self): -@@ -3625,7 +3228,7 @@ class StonithUpdate(ResourceTest): - "stonith update S ip= ipaddr=I".split(), - """ - -- -+ - - - - """, -- stderr_regexp=( -+ stderr_full=( - "Warning: stonith option 'ipaddr' is deprecated and might be " - "removed in a future release, therefore it should not " -- "be used, use 'ip' instead\n" + self.agent_secure_warning -+ "be used, use 'ip' instead\n" - ), - ) - -@@ -3663,7 +3266,7 @@ class StonithUpdate(ResourceTest): - "stonith update S ip=I1 ipaddr=I2".split(), - """ - -- -+ - - - - """, -- stderr_regexp=( -+ stderr_full=( - "Warning: stonith option 'ipaddr' is deprecated and might be " - "removed in a future release, therefore it should not " -- "be used, use 'ip' instead\n" + self.agent_secure_warning -+ "be used, use 'ip' instead\n" - ), - ) -diff --git a/pcs_test/tier1/test_status.py b/pcs_test/tier1/test_status.py -index 4d472208..f6780c60 100644 ---- a/pcs_test/tier1/test_status.py -+++ b/pcs_test/tier1/test_status.py -@@ -27,6 +27,9 @@ class StonithWarningTest(TestCase, AssertPcsMixin): - self.temp_cib = get_tmp_file("tier0_statust_stonith_warning") - write_file_to_tmpfile(self.empty_cib, self.temp_cib) - self.pcs_runner = PcsRunner(self.temp_cib.name) -+ self.pcs_runner.mock_settings = get_mock_settings( -+ "crm_resource_exec", "stonith_admin_exec" -+ ) - - def tearDown(self): - self.temp_cib.close() -@@ -34,8 +37,7 @@ class StonithWarningTest(TestCase, AssertPcsMixin): - def fixture_stonith_action(self): - self.assert_pcs_success( - ( -- "stonith create Sa fence_apc ip=i username=u action=reboot " -- "--force" -+ "stonith create Sa fence_pcsmock_action action=reboot --force" - ).split(), - stderr_start=( - "Warning: stonith option 'action' is deprecated and might be " -@@ -45,15 +47,8 @@ class StonithWarningTest(TestCase, AssertPcsMixin): - ) - - def fixture_stonith_cycle(self): -- self.assert_pcs_success_ignore_output( -- ( -- "stonith", -- "create", -- "Sc", -- "fence_ipmilan", -- "method=cycle", -- "--force", -- ) -+ self.assert_pcs_success( -+ "stonith create Sc fence_pcsmock_method method=cycle".split() - ) - - def fixture_resource(self): -@@ -208,14 +203,13 @@ class StonithWarningTest(TestCase, AssertPcsMixin): - - def test_no_stonith_warning_when_stonith_in_group(self): - self.assert_pcs_success( -- "stonith create S fence_xvm --group G".split(), -+ "stonith create S fence_pcsmock_minimal --group G".split(), - stderr_full=( - "Deprecation Warning: Option to group stonith resource is " - "deprecated and will be removed in a future release.\n" - ), - ) - self.pcs_runner.corosync_conf_opt = self.corosync_conf -- self.pcs_runner.mock_settings = get_mock_settings("crm_resource_exec") - if PCMK_2_0_3_PLUS: - self.assert_pcs_success( - ["status"], -diff --git a/pcs_test/tools/bin_mock/__init__.py b/pcs_test/tools/bin_mock/__init__.py -index 653bf81b..9bef8e64 100644 ---- a/pcs_test/tools/bin_mock/__init__.py -+++ b/pcs_test/tools/bin_mock/__init__.py -@@ -8,10 +8,14 @@ CRM_RESOURCE_BIN = os.path.abspath( - PACEMAKER_FENCED_BIN = os.path.abspath( - os.path.join(BIN_MOCK_DIR, "pcmk/pacemaker-fenced") - ) -+STONITH_ADMIN_BIN = os.path.abspath( -+ os.path.join(BIN_MOCK_DIR, "pcmk/stonith_admin") -+) - - MOCK_SETTINGS = { - "crm_resource_exec": CRM_RESOURCE_BIN, - "pacemaker_fenced_exec": PACEMAKER_FENCED_BIN, -+ "stonith_admin_exec": STONITH_ADMIN_BIN, - } - - -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml -deleted file mode 100644 -index 6d159b4f..00000000 ---- a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_apc_metadata.xml -+++ /dev/null -@@ -1,277 +0,0 @@ -- -- -- fence_apc is an I/O Fencing agent which can be used with the APC network power switch. It logs into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions. -- -- -- http://www.apc.com -- -- -- -- -- -- -- Fencing action -- -- -- -- -- -- -- Force Python regex for command prompt -- -- -- -- -- -- -- Force Python regex for command prompt -- -- -- -- -- -- -- Identity file (private key) for SSH -- -- -- -- -- -- -- Forces agent to use IPv4 addresses only -- -- -- -- -- -- -- Forces agent to use IPv6 addresses only -- -- -- -- -- -- -- IP address or hostname of fencing device -- -- -- -- -- -- -- IP address or hostname of fencing device -- -- -- -- -- -- -- TCP/UDP port to use for connection with device -- -- -- -- -- -- -- Login name -- -- -- -- -- -- -- Login password or passphrase -- -- -- -- -- -- -- Script to run to retrieve password -- -- -- -- -- -- -- Login password or passphrase -- -- -- -- -- -- -- Script to run to retrieve password -- -- -- -- -- -- -- Physical plug number on device, UUID or identification of machine -- -- -- -- -- -- -- Physical plug number on device, UUID or identification of machine -- -- -- -- -- -- -- Use SSH connection -- -- -- -- -- -- -- Use SSH connection -- -- -- -- -- -- -- SSH options to use -- -- -- -- -- -- -- Physical switch number on device -- -- -- -- -- -- -- Login name -- -- -- -- -- -- -- Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. -- -- -- -- -- -- -- Verbose mode -- -- -- -- -- -- -- Write debug information to given file -- -- -- -- -- -- -- Write debug information to given file -- -- -- -- -- -- -- Display version information and exit -- -- -- -- -- -- -- Display help and exit -- -- -- -- -- -- -- Separator for CSV created by 'list' operation -- -- -- -- -- -- -- Wait X seconds before fencing is started -- -- -- -- -- -- -- Wait X seconds for cmd prompt after login -- -- -- -- -- -- -- Test X seconds for status change after ON/OFF -- -- -- -- -- -- -- Wait X seconds after issuing ON/OFF -- -- -- -- -- -- -- Wait X seconds for cmd prompt after issuing command -- -- -- -- -- -- -- Count of attempts to retry power on -- -- -- -- -- -- -- Path to ssh binary -- -- -- -- -- -- -- Path to telnet binary -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml -deleted file mode 100644 -index 5c6e1c3b..00000000 ---- a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_ilo_metadata.xml -+++ /dev/null -@@ -1,269 +0,0 @@ -- -- -- -- fence_ilo is an I/O Fencing agent used for HP servers with the Integrated Light Out (iLO) PCI card.The agent opens an SSL connection to the iLO card. Once the SSL connection is established, the agent is able to communicate with the iLO card through an XML stream. -- -- -- http://www.hp.com -- -- -- -- -- -- -- Fencing action -- -- -- -- -- -- -- Forces agent to use IPv4 addresses only -- -- -- -- -- -- -- Forces agent to use IPv6 addresses only -- -- -- -- -- -- -- IP address or hostname of fencing device -- -- -- -- -- -- -- IP address or hostname of fencing device -- -- -- -- -- -- -- TCP/UDP port to use for connection with device -- -- -- -- -- -- -- Login name -- -- -- -- -- -- -- Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up. -- -- -- -- -- -- -- Login password or passphrase -- -- -- -- -- -- -- Script to run to retrieve password -- -- -- -- -- -- -- Login password or passphrase -- -- -- -- -- -- -- Script to run to retrieve password -- -- -- -- -- -- -- IP address or hostname of fencing device (together with --port-as-ip) -- -- -- -- -- -- -- IP address or hostname of fencing device (together with --port-as-ip) -- -- -- -- -- -- -- Force ribcl version to use -- -- -- -- -- -- -- Force ribcl version to use -- -- -- -- -- -- -- Use SSL connection with verifying certificate -- -- -- -- -- -- -- Use SSL connection without verifying certificate -- -- -- -- -- -- -- Use SSL connection with verifying certificate -- -- -- -- -- -- -- Disable TLS negotiation and force TLS1.0. This should only be used for devices that do not support TLS1.1 and up. -- -- -- -- -- -- -- Login name -- -- -- -- -- -- -- Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. -- -- -- -- -- -- -- Verbose mode -- -- -- -- -- -- -- Write debug information to given file -- -- -- -- -- -- -- Write debug information to given file -- -- -- -- -- -- -- Display version information and exit -- -- -- -- -- -- -- Display help and exit -- -- -- -- -- -- -- Wait X seconds before fencing is started -- -- -- -- -- -- -- Wait X seconds for cmd prompt after login -- -- -- -- -- -- -- Make "port/plug" to be an alias to IP address -- -- -- -- -- -- -- Test X seconds for status change after ON/OFF -- -- -- -- -- -- -- Wait X seconds after issuing ON/OFF -- -- -- -- -- -- -- Wait X seconds for cmd prompt after issuing command -- -- -- -- -- -- -- Count of attempts to retry power on -- -- -- -- -- -- -- Path to gnutls-cli binary -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml -new file mode 100644 -index 00000000..fd40fa87 ---- /dev/null -+++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_action_metadata.xml -@@ -0,0 +1,31 @@ -+ -+ -+ This is an agent with action parameter for pcs tests -+ -+ -+ -+ -+ -+ -+ Fencing action (null, off, on, [reboot], status, list, list-status, monitor, validate-all, metadata) -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml -new file mode 100644 -index 00000000..cdccdd9c ---- /dev/null -+++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_method_metadata.xml -@@ -0,0 +1,32 @@ -+ -+ -+ This is an agent with method parameter for pcs tests -+ -+ -+ -+ -+ -+ -+ Method to fence -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml -new file mode 100644 -index 00000000..c9fa8008 ---- /dev/null -+++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_minimal_metadata.xml -@@ -0,0 +1,22 @@ -+ -+ -+ This is a minimalistic agent for pcs tests -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml -new file mode 100644 -index 00000000..088ca985 ---- /dev/null -+++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_params_metadata.xml -@@ -0,0 +1,107 @@ -+ -+ -+ This is an agent with params for pcs tests -+ -+ -+ -+ -+ -+ -+ Fencing action -+ -+ -+ -+ -+ -+ -+ IP address or hostname of fencing device -+ -+ -+ -+ -+ -+ -+ IP address or hostname of fencing device -+ -+ -+ -+ -+ -+ -+ Login name -+ -+ -+ -+ -+ -+ -+ Login password or passphrase -+ -+ -+ -+ -+ -+ -+ Login password or passphrase -+ -+ -+ -+ -+ -+ -+ Use SSH connection -+ -+ -+ -+ -+ -+ -+ Use SSH connection -+ -+ -+ -+ -+ -+ -+ Login name -+ -+ -+ -+ -+ -+ -+ Verbose mode -+ -+ -+ -+ -+ -+ -+ Write debug information to given file -+ -+ -+ -+ -+ -+ -+ Write debug information to given file -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml -new file mode 100644 -index 00000000..db211744 ---- /dev/null -+++ b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_pcsmock_unfencing_metadata.xml -@@ -0,0 +1,22 @@ -+ -+ -+ This is an agent which provides unfencing for pcs tests -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml -deleted file mode 100644 -index 259a1593..00000000 ---- a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_scsi_metadata.xml -+++ /dev/null -@@ -1,182 +0,0 @@ -- -- -- fence_scsi is an I/O fencing agent that uses SCSI-3 persistent reservations to control access to shared storage devices. These devices must support SCSI-3 persistent reservations (SPC-3 or greater) as well as the "preempt-and-abort" subcommand. --The fence_scsi agent works by having each node in the cluster register a unique key with the SCSI device(s). Once registered, a single node will become the reservation holder by creating a "write exclusive, registrants only" reservation on the device(s). The result is that only registered nodes may write to the device(s). When a node failure occurs, the fence_scsi agent will remove the key belonging to the failed node from the device(s). The failed node will no longer be able to write to the device(s). A manual reboot is required. -- -- -- -- -- -- -- -- Fencing action -- -- -- -- -- -- -- Use the APTPL flag for registrations. This option is only used for the 'on' action. -- -- -- -- -- -- -- List of devices to use for current operation. Devices can be comma-separated list of raw devices (eg. /dev/sdc). Each device must support SCSI-3 persistent reservations. -- -- -- -- -- -- -- Key to use for the current operation. This key should be unique to a node. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s). -- -- -- -- -- -- -- Name of the node to be fenced. The node name is used to generate the key value used for the current operation. This option will be ignored when used with the -k option. -- -- -- -- -- -- -- Name of the node to be fenced. The node name is used to generate the key value used for the current operation. This option will be ignored when used with the -k option. -- -- -- -- -- -- -- Log output (stdout and stderr) to file -- -- -- -- -- -- -- Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. -- -- -- -- -- -- -- Verbose mode -- -- -- -- -- -- -- Write debug information to given file -- -- -- -- -- -- -- Write debug information to given file -- -- -- -- -- -- -- Display version information and exit -- -- -- -- -- -- -- Display help and exit -- -- -- -- -- -- -- Wait X seconds before fencing is started -- -- -- -- -- -- -- Wait X seconds for cmd prompt after login -- -- -- -- -- -- -- Test X seconds for status change after ON/OFF -- -- -- -- -- -- -- Wait X seconds after issuing ON/OFF -- -- -- -- -- -- -- Wait X seconds for cmd prompt after issuing command -- -- -- -- -- -- -- Count of attempts to retry power on -- -- -- -- -- -- -- Path to corosync-cmapctl binary -- -- -- -- -- -- -- Path to sg_persist binary -- -- -- -- -- -- -- Path to sg_turs binary -- -- -- -- -- -- -- Path to vgs binary -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml b/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml -deleted file mode 100644 -index d359854e..00000000 ---- a/pcs_test/tools/bin_mock/pcmk/crm_resource.d/stonith__fence_xvm_metadata.xml -+++ /dev/null -@@ -1,120 +0,0 @@ -- -- -- fence_xvm is an I/O Fencing agent which can be used withvirtual machines. -- -- -- -- -- -- -- Specify (stdin) or increment (command line) debug level -- -- -- -- -- -- -- IP Family ([auto], ipv4, ipv6) -- -- -- -- -- -- -- Multicast address (default=225.0.0.12 / ff05::3:1) -- -- -- -- -- -- -- TCP, Multicast, or VMChannel IP port (default=1229) -- -- -- -- -- -- -- Multicast retransmit time (in 1/10sec; default=20) -- -- -- -- -- -- -- Authentication (none, sha1, [sha256], sha512) -- -- -- -- -- -- -- Packet hash strength (none, sha1, [sha256], sha512) -- -- -- -- -- -- -- Shared key file (default=/etc/cluster/fence_xvm.key) -- -- -- -- -- -- -- Virtual Machine (domain name) to fence -- -- -- -- -- -- -- Treat [domain] as UUID instead of domain name. This is provided for compatibility with older fence_xvmd installations. -- -- -- -- -- -- -- Fencing action (null, off, on, [reboot], status, list, list-status, monitor, validate-all, metadata) -- -- -- -- -- -- -- Fencing timeout (in seconds; default=30) -- -- -- -- -- -- -- Fencing delay (in seconds; default=0) -- -- -- -- -- -- -- Virtual Machine (domain name) to fence (deprecated; use port) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -diff --git a/pcs_test/tools/bin_mock/pcmk/crm_resource_mock.py b/pcs_test/tools/bin_mock/pcmk/crm_resource_mock.py -index f1d8d069..58cf25e6 100644 ---- a/pcs_test/tools/bin_mock/pcmk/crm_resource_mock.py -+++ b/pcs_test/tools/bin_mock/pcmk/crm_resource_mock.py -@@ -26,7 +26,6 @@ def get_arg_values(argv, name): - - - def main(): -- # pylint: disable=too-many-branches - argv = sys.argv[1:] - if not argv: - raise AssertionError() -@@ -52,10 +51,11 @@ def main(): - "ocf:pacemaker:remote", - "ocf:pacemaker:Stateful", - "ocf:pacemaker:SystemHealth", -- "stonith:fence_apc", -- "stonith:fence_ilo", -- "stonith:fence_scsi", -- "stonith:fence_xvm", -+ "stonith:fence_pcsmock_action", -+ "stonith:fence_pcsmock_method", -+ "stonith:fence_pcsmock_minimal", -+ "stonith:fence_pcsmock_params", -+ "stonith:fence_pcsmock_unfencing", - "systemd:test@a:b", - ) - # known_agents_map = {item.lower()} -@@ -63,21 +63,11 @@ def main(): - write_local_file_to_stdout( - "{}_metadata.xml".format(arg.replace(":", "__")) - ) -- elif arg == "ocf:pacemaker:nonexistent": -- sys.stderr.write( -- "Metadata query for ocf:pacemaker:nonexistent failed: " -- "Input/output error\n" -- ) -- raise SystemExit(5) -- elif arg == "stonith:fence_noexist": -+ else: - sys.stderr.write( -- "Agent fence_noexist not found or does not support meta-data: " -- "Invalid argument (22)\nMetadata query for " -- "stonith:fence_noexist failed: Input/output error\n" -+ "pcs mock error message: unable to load agent metadata" - ) -- raise SystemExit(5) -- else: -- raise AssertionError() -+ raise SystemExit(1) - elif arg in option_file_map: - if argv: - raise AssertionError() -@@ -100,7 +90,7 @@ def main(): - is_invalid = "fake=is_invalid=True" in argv - output = "" - if is_invalid: -- output = """Validation failure""" -+ output = """pcsmock validation failure""" - stdout = """ - - -diff --git a/pcs_test/tools/bin_mock/pcmk/stonith_admin.in b/pcs_test/tools/bin_mock/pcmk/stonith_admin.in -new file mode 100755 -index 00000000..bf48b5c4 ---- /dev/null -+++ b/pcs_test/tools/bin_mock/pcmk/stonith_admin.in -@@ -0,0 +1,5 @@ -+#!@PYTHON@ -+ -+from stonith_admin_mock import main -+ -+main() -diff --git a/pcs_test/tools/bin_mock/pcmk/stonith_admin_mock.py b/pcs_test/tools/bin_mock/pcmk/stonith_admin_mock.py -new file mode 100644 -index 00000000..133097b5 ---- /dev/null -+++ b/pcs_test/tools/bin_mock/pcmk/stonith_admin_mock.py -@@ -0,0 +1,60 @@ -+import os.path -+import sys -+from textwrap import dedent -+ -+CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) -+DATA_DIR = os.path.join(CURRENT_DIR, "{}.d".format(sys.argv[0])) -+ -+ -+def get_arg_values(argv, name): -+ values = [] -+ next_value = len(argv) -+ for i, value in enumerate(argv): -+ if value == name: -+ next_value = i + 1 -+ elif i == next_value: -+ values.append(value) -+ return values -+ -+ -+def main(): -+ argv = sys.argv[1:] -+ if not argv: -+ raise AssertionError() -+ -+ arg = argv.pop(0) -+ -+ if arg == "--validate": -+ if get_arg_values(argv, "--output-as")[0] != "xml": -+ raise AssertionError() -+ is_invalid = False -+ for arg in argv: -+ if "=" in arg and arg.split("=", 1)[1] == "is_invalid=True": -+ is_invalid = True -+ break -+ output = "" -+ if is_invalid: -+ output = """pcsmock validation failure""" -+ cmd_str = " ".join(sys.argv) -+ agent_type = get_arg_values(argv, "--agent")[0] -+ stdout = dedent( -+ f""" -+ -+ -+ -+ {output} -+ -+ -+ -+ -+ """ -+ ) -+ sys.stdout.write(stdout) -+ if is_invalid: -+ raise SystemExit(1) -+ else: -+ raise AssertionError() -+ -+ -+if __name__ == "__main__": -+ main() --- -2.45.2 - diff --git a/pcs.spec b/pcs.spec index 9ee7b5d..1cee4c9 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs -Version: 0.11.8 -Release: 2%{?dist} +Version: 0.12.0 +Release: 1%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -11,33 +11,52 @@ Group: System Environment/Base Summary: Pacemaker/Corosync Configuration System BuildArch: noarch -# When specifying a commit, use its long hash -%global version_or_commit %{version} -# %%global version_or_commit 10069ca47e5c9f4ac1abd8bc4cd99281ead047b7 +# Remove a tilde used by RPM to get the correct upstream version +%global clean_version %(echo %{version} | sed 's/~//') + +# To build an official pcs release, comment out branch_or_commit +# Use long commit hash or branch name to build an unreleased version +# %%global branch_or_commit 1353dfbb3af82d77f4de17a3fa4cbde185bb2b2d +%if 0%{?branch_or_commit:1} + %global version_or_commit %{branch_or_commit} +%else + %global version_or_commit %{clean_version} +%endif %global pcs_source_name %{name}-%{version_or_commit} -# ui_commit can be determined by hash, tag or branch -%global ui_commit 0.1.20 -%global ui_modules_version 0.1.20 -%global ui_src_name pcs-web-ui-%{ui_commit} +# To build an official pcs-web-ui release, comment out ui_branch_or_commit +# Last tagged version, also used as fallback version for untagged tarballs +%global ui_version 0.1.22 +%global ui_modules_version 0.1.22 +# Use long commit hash or branch name to build an unreleased version +# %%global ui_branch_or_commit 34372d1268f065ed186546f55216aaa2d7e76b54 +%if 0%{?ui_branch_or_commit:1} + %global ui_version_or_commit %{ui_branch_or_commit} +%else + %global ui_version_or_commit %{ui_version} +%endif +%global ui_src_name pcs-web-ui-%{ui_version_or_commit} + %global pyagentx_version 0.4.pcs.2 %global dacite_version 1.8.1 -%global required_pacemaker_version 2.1.0 +%global required_pacemaker_version 3.0.0 %global pcs_bundled_dir pcs_bundled -%global pcsd_public_dir pcsd/public -%global ui_build_dir_standalone build_standalone -%global ui_build_dir_cockpit build_cockpit -%global ui_cockpit_dest ha-cluster -%global ui_appstream_metainfo org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml +%global pcsd_webui_dir %{_prefix}/lib/pcsd/public/ui + +%global cockpit_dir %{_datadir}/cockpit/ +%global metainfo_dir %{_datadir}/metainfo +%global ui_metainfo_name org.clusterlabs.cockpit_pcs_web_ui.metainfo.xml +%global ui_metainfo %{metainfo_dir}/%{ui_metainfo_name} %global pkg_pcs_snmp pcs-snmp +%global pkg_pcs_web_ui pcs-web-ui %global pkg_cockpit_ha_cluster cockpit-ha-cluster # prepend v for folder in GitHub link when using tagged tarball -%if "%{version}" == "%{version_or_commit}" +%if "%{clean_version}" == "%{version_or_commit}" %global v_prefix v %endif @@ -47,15 +66,31 @@ Source0: %{url}/archive/%{?v_prefix}%{version_or_commit}/%{pcs_source_name}.tar. Source41: https://github.com/ondrejmular/pyagentx/archive/v%{pyagentx_version}/pyagentx-%{pyagentx_version}.tar.gz Source42: https://github.com/konradhalas/dacite/archive/v%{dacite_version}/dacite-%{dacite_version}.tar.gz -Source100: https://github.com/ClusterLabs/pcs-web-ui/archive/%{ui_commit}/%{ui_src_name}.tar.gz -Source101: https://github.com/ClusterLabs/pcs-web-ui/releases/download/%{ui_commit}/pcs-web-ui-node-modules-%{ui_modules_version}.tar.xz +Source100: https://github.com/ClusterLabs/pcs-web-ui/archive/%{ui_version_or_commit}/%{ui_src_name}.tar.gz +Source101: https://github.com/ClusterLabs/pcs-web-ui/releases/download/%{ui_version_or_commit}/pcs-web-ui-node-modules-%{ui_modules_version}.tar.xz + # pcs patches: <= 200 -# Patch0: name.patch -Patch0: overhaul-fence-agents-mocking.patch +# Patch1: name.patch +Patch1: show-info-page-instead-of-webui.patch +Patch2: ruby-3.4-compatibility.patch +Patch3: fix-install-on-systems-with-merged-bin-and-sbin.patch # ui patches: >200 # Patch201: name-web-ui.patch +Patch201: fix-filter-clones-by-agent-name-in-resource-tree.patch + + +# Split pcs to pcs and pcs-web-ui, all packages that replace pcs must obsolete +# the old monolithic package +# https://docs.fedoraproject.org/en-US/packaging-guidelines/#_one_to_many_replacement +Obsoletes: pcs < 0.12.0 +# Web UI is an add-on that doesn't need to be installed for pcs to function. +# Upgrades from before 0.12 will install it thanks to Obsoletes. But it will +# be possible to uninstall web UI to disable it and then it will not be +# installed during upgrades because it is a weak dependency. +Recommends: %{pkg_pcs_web_ui} == %{version}-%{release} + # git for patches BuildRequires: git-core @@ -65,8 +100,9 @@ BuildRequires: automake BuildRequires: make # printf from coreutils is used in makefile, head is used in spec BuildRequires: coreutils +# find is used in Makefile and also somewhere else +BuildRequires: findutils # python for pcs -BuildRequires: python3 >= 3.9 BuildRequires: python3-dateutil >= 2.7.0 BuildRequires: python3-devel BuildRequires: python3-setuptools @@ -100,16 +136,16 @@ BuildRequires: rubygem(rexml) BuildRequires: rubygem-test-unit # for touching patch files (sanitization function) BuildRequires: diffstat -# for post, preun and postun macros -BuildRequires: systemd +# for systemd scriptlet macros +BuildRequires: systemd-rpm-macros # pam is used for authentication inside daemon (python ctypes) # needed for tier0 tests during build BuildRequires: pam # for working with qdevice certificates (certutil) - used in configure.ac BuildRequires: nss-tools +# pcs now provides a pc file +BuildRequires: pkgconfig -# for building web ui -BuildRequires: nodejs-npm # cluster stack packages for pkg-config # corosync has different package names on distributions but all provide @@ -129,12 +165,11 @@ BuildRequires: libappstream-glib Requires: python3-cryptography Requires: python3-dateutil >= 2.7.0 Requires: python3-lxml -Requires: python3-setuptools Requires: python3-pycurl Requires: python3-pyparsing Requires: python3-tornado # ruby and gems for pcsd -Requires: ruby >= 2.5.0 +Requires: ruby >= 3.3.0 Requires: rubygem-backports Requires: rubygem-childprocess Requires: rubygem-ethon @@ -144,7 +179,6 @@ Requires: rubygem-mustermann Requires: rubygem-puma Requires: rubygem-rack Requires: rubygem-rack-protection -Requires: rubygem-rack-test Requires: rubygem-sinatra Requires: rubygem-tilt %if 0%{?fedora} || 0%{?rhel} >= 9 @@ -159,10 +193,6 @@ Requires: (corosync >= 3.0 if pacemaker) # pcs enables corosync encryption by default so we require libknet1-plugins-all Requires: (libknet1-plugins-all if corosync) Requires: pacemaker-cli >= %{required_pacemaker_version} -# for post, preun and postun macros -Requires(post): systemd -Requires(preun): systemd -Requires(postun): systemd # pam is used for authentication inside daemon (python ctypes) # more details: https://bugzilla.redhat.com/show_bug.cgi?id=1717113 Requires: pam @@ -174,7 +204,6 @@ Requires: nss-tools Provides: bundled(dacite) = %{dacite_version} - # pcs-snmp subpackage definition %package -n %{pkg_pcs_snmp} Group: System Environment/Base @@ -195,6 +224,22 @@ Requires: net-snmp Provides: bundled(pyagentx) = %{pyagentx_version} +# pcs-web-ui subpackage definition +%package -n %{pkg_pcs_web_ui} +Summary: Standalone web UI for Pacemaker/Corosync Configuration System +# https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ +# https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses +# GPL-2.0-only: pcs +License: GPL-2.0-only +URL: https://github.com/ClusterLabs/pcs + +# Split pcs to pcs and pcs-web-ui, all packages that replace pcs must obsolete +# the old monolithic package +# https://docs.fedoraproject.org/en-US/packaging-guidelines/#_one_to_many_replacement +Obsoletes: pcs < 0.12.0 + +Requires: pcs = %{version}-%{release} + # cockpit-ha-cluster subpackage definition %package -n %{pkg_cockpit_ha_cluster} Group: System Environment/Base @@ -209,20 +254,26 @@ Requires: pcs = %{version}-%{release} Requires: cockpit-bridge + %description -pcs is a corosync and pacemaker configuration tool. It permits users to -easily view, modify and create pacemaker based clusters. +pcs is a configuration tool for Corosync and Pacemaker. It permits users to +easily view, modify and create high availability clusters based on Pacemaker. +This package contains the pcs command-line utility and its server pcsd. + +%description -n %{pkg_pcs_web_ui} +Provides standalone web UI for Pacemaker/Corosync Configuration System (pcs). %description -n %{pkg_pcs_snmp} -SNMP agent that provides information about pacemaker cluster to the master agent +SNMP agent that provides information about Pacemaker cluster to the main agent (snmpd). %description -n %{pkg_cockpit_ha_cluster} Cockpit application for managing Pacemaker based clusters. Uses Pacemaker/Corosync Configuration System (pcs) in the background. -%prep + +%prep # -- following is inspired by python-simplejon.el5 -- # Update timestamps on the files touched by a patch, to avoid non-equal # .pyc/.pyo files across the multilib peers within a build @@ -266,20 +317,36 @@ update_times_patch(){ # * http://ftp.rpm.org/max-rpm/s1-rpm-inside-macros.html # * https://rpm-software-management.github.io/rpm/manual/autosetup.html # patch web-ui sources -%autosetup -D -T -b 100 -a 101 -S git -n %{ui_src_name} -N +# -n — Set Name of Build Directory +# -T — Do Not Perform Default Archive Unpacking +# -b — Unpack The nth Sources Before Changing Directory +# -a — Unpack The nth Sources After Changing Directory +# -N — disables automatic patch application, use autopatch to apply patches +# +# 1. unpack sources (-b 0) +# 2. then cd into sources tree (the setup macro itself) +# 3. then unpack node_modules into sources tree (-a 1). +%autosetup -T -b 100 -a 101 -N -n %{ui_src_name} %autopatch -p1 -m 201 # update_times_patch %%{PATCH201} +update_times_patch %{PATCH201} # patch pcs sources %autosetup -S git -n %{pcs_source_name} -N %autopatch -p1 -M 200 -# update_times_patch %%{PATCH0} -update_times_patch %{PATCH0} +# update_times_patch %%{PATCH1} +update_times_patch %{PATCH1} +update_times_patch %{PATCH2} +update_times_patch %{PATCH3} # generate .tarball-version if building from an untagged commit, not a released version # autogen uses git-version-gen which uses .tarball-version for generating version number -%if "%{version}" != "%{version_or_commit}" - echo "%version+$(echo "%{version_or_commit}" | head -c 8)" > %{_builddir}/%{pcs_source_name}/.tarball-version +%if "%{clean_version}" != "%{version_or_commit}" + echo "%{clean_version}+$(echo "%{version_or_commit}" | head -c 8)" > %{_builddir}/%{pcs_source_name}/.tarball-version +%endif + +%if "x%{?ui_branch_or_commit}" != "x" + echo "%{ui_version}+$(echo "%{ui_branch_or_commit}" | head -c 8)" > %{_builddir}/%{ui_src_name}/.tarball-version %endif # prepare dirs/files necessary for building python bundles @@ -288,47 +355,41 @@ cp -f %SOURCE41 rpm/ cp -f %SOURCE42 rpm/ + %build %define debug_package %{nil} +# We left off by setting up pcs, so we are in its directory now ./autogen.sh %{configure} --enable-local-build --enable-use-local-cache-only \ - --enable-individual-bundling \ + --enable-individual-bundling --enable-webui \ --with-pcsd-default-cipherlist='PROFILE=SYSTEM' \ --with-pcs-lib-dir="%{_prefix}/lib" PYTHON=%{__python3} make all -# build pcs-web-ui -export BUILD_USE_CURRENT_NODE_MODULES=true +# Web UI installation +# Switch to web ui folder first +cd ../%{ui_src_name} +./autogen.sh +%{configure} \ + --with-pcsd-webui-dir=%{pcsd_webui_dir} \ + --with-cockpit-dir=%{cockpit_dir} \ + --with-metainfo-dir=%{metainfo_dir} +make all -## standalone -export BUILD_DIR=%{_builddir}/%{ui_src_name}/%{ui_build_dir_standalone} -make -C %{_builddir}/%{ui_src_name} build - -## cockpit -export BUILD_DIR=%{_builddir}/%{ui_src_name}/%{ui_build_dir_cockpit} -export BUILD_FOR_COCKPIT=true -make -C %{_builddir}/%{ui_src_name} build %install -rm -rf $RPM_BUILD_ROOT +rm -rf %{buildroot} pwd - +# Install cockpit pcs-web-ui +cd ../%{ui_src_name} %make_install -# install standalone pcs-web-ui -cp -r %{_builddir}/%{ui_src_name}/%{ui_build_dir_standalone} \ - ${RPM_BUILD_ROOT}%{_prefix}/lib/%{pcsd_public_dir}/ui -# install cockpit pcs-web-ui -mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/cockpit/%{ui_cockpit_dest} -mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/metainfo -cp -r %{_builddir}/%{ui_src_name}/%{ui_build_dir_cockpit}/* \ - ${RPM_BUILD_ROOT}%{_datadir}/cockpit/%{ui_cockpit_dest} - -cp -r %{_builddir}/%{ui_src_name}/packages/app/%{ui_appstream_metainfo} \ - ${RPM_BUILD_ROOT}%{_datadir}/metainfo/ +# Install pcs +cd ../%{pcs_source_name} +%make_install # prepare license files cp %{pcs_bundled_dir}/src/pyagentx-*/LICENSE.txt pyagentx_LICENSE.txt @@ -339,9 +400,10 @@ cp %{pcs_bundled_dir}/src/dacite-*/LICENSE dacite_LICENSE cp %{pcs_bundled_dir}/src/dacite-*/README.md dacite_README.md + %check # Run validation of cockpit metainfo -appstream-util validate-relax --nonet ${RPM_BUILD_ROOT}%{_datadir}/metainfo/%{ui_appstream_metainfo} +appstream-util validate-relax --nonet %{buildroot}%{_datadir}/metainfo/%{ui_metainfo_name} # In the building environment LC_CTYPE is set to C which causes tests to fail # due to python prints a warning about it to stderr. The following environment @@ -366,7 +428,7 @@ run_all_tests(){ #run pcsd tests and remove them ruby \ - -I$RPM_BUILD_ROOT%{_prefix}/lib/pcsd \ + -I%{buildroot}%{_prefix}/lib/pcsd \ -Ipcsd/test \ pcsd/test/test_all_suite.rb test_result_ruby=$? @@ -379,34 +441,31 @@ run_all_tests(){ run_all_tests + +# Mark pcsd and pcs_snmp_agent for restart after upgrade %posttrans -# Make sure the new version of the daemon is running. -# Also, make sure to start pcsd-ruby if it hasn't been started or even -# installed before. This is done by restarting pcsd.service. -%{_bindir}/systemctl daemon-reload -%{_bindir}/systemctl try-restart pcsd.service +%systemd_posttrans_with_restart pcsd.service + +%posttrans -n %{pkg_pcs_snmp} +%systemd_posttrans_with_restart pcs_snmp_agent.service + +# Restart pcsd if it is running to reload the Tornado app so it detects +# presence or absence of the webui backend handler on install/update +# of pcs-web-ui that contains it +# Systemd will not pick-up on this change because pcs-web-ui doesn't contain +# a unit file that would mark it for restart +# https://fedoraproject.org/wiki/Changes/Restart_services_at_end_of_rpm_transaction +%posttrans -n %{pkg_pcs_web_ui} +systemctl try-restart pcsd.service + +# Runs only on pcs-web-ui uninstall +# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/ +%postun -n %{pkg_pcs_web_ui} +if [ $1 -eq 0 ] ; then + systemctl try-restart pcsd.service +fi -%post -%systemd_post pcsd.service -%systemd_post pcsd-ruby.service - -%post -n %{pkg_pcs_snmp} -%systemd_post pcs_snmp_agent.service - -%preun -%systemd_preun pcsd.service -%systemd_preun pcsd-ruby.service - -%preun -n %{pkg_pcs_snmp} -%systemd_preun pcs_snmp_agent.service - -%postun -%systemd_postun_with_restart pcsd.service -%systemd_postun_with_restart pcsd-ruby.service - -%postun -n %{pkg_pcs_snmp} -%systemd_postun_with_restart pcs_snmp_agent.service %files %doc CHANGELOG.md @@ -415,9 +474,10 @@ run_all_tests %license dacite_LICENSE %license COPYING %{python3_sitelib}/* -%{_sbindir}/pcs -%{_sbindir}/pcsd +%{_bindir}/pcs +%{_bindir}/pcsd %{_prefix}/lib/pcs/* +%{_prefix}/lib/pkgconfig/pcs.pc %{_prefix}/lib/pcsd/* %{_unitdir}/pcsd.service %{_unitdir}/pcsd-ruby.service @@ -438,8 +498,16 @@ run_all_tests %{_mandir}/man8/pcsd.* %exclude %{_prefix}/lib/pcs/pcs_snmp_agent %exclude %{_prefix}/lib/pcs/%{pcs_bundled_dir}/packages/pyagentx* -%exclude %{_datadir}/cockpit -%exclude %{_datadir}/metainfo/%{ui_appstream_metainfo} +%exclude %{cockpit_dir} +%exclude %{ui_metainfo} +%exclude %{python3_sitelib}/pcs/daemon/app/webui +%exclude %{pcsd_webui_dir} + +%files -n %{pkg_pcs_web_ui} +%doc CHANGELOG.md +%license COPYING +%{python3_sitelib}/pcs/daemon/app/webui +%{pcsd_webui_dir} %files -n %{pkg_pcs_snmp} %{_prefix}/lib/pcs/pcs_snmp_agent @@ -455,11 +523,20 @@ run_all_tests %license pyagentx_LICENSE.txt %files -n %{pkg_cockpit_ha_cluster} -%{_datadir}/cockpit/%{ui_cockpit_dest} -%{_datadir}/metainfo/%{ui_appstream_metainfo} +%{cockpit_dir} +%{ui_metainfo} + %changelog +* Mon Jan 27 2025 Michal Pospíšil - 0.12.0-1 +- Rebased pcs to the newest major version (see CHANGELOG.md) + Resolves: rhbz#2341012 +- New subpackage pcs-web-ui - enables standalone web UI when the subpackage is installed on the system (default), uninstall the subpackage to disable the web UI +- Updated standalone web UI and HA Cluster Management Cockpit application to pcs-web-ui 0.1.22 +- Fixes for compatibility with Ruby 3.4 + Resolves: rhbz#2331005 + * Fri Jan 17 2025 Fedora Release Engineering - 0.11.8-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild diff --git a/ruby-3.4-compatibility.patch b/ruby-3.4-compatibility.patch new file mode 100644 index 0000000..7d0288c --- /dev/null +++ b/ruby-3.4-compatibility.patch @@ -0,0 +1,233 @@ +From 33e8a769b48410b854f33ffb483f58340cd2c9d8 Mon Sep 17 00:00:00 2001 +From: Tomas Jelinek +Date: Tue, 14 Jan 2025 13:33:11 +0100 +Subject: [PATCH 2/3] fix for ruby 3.4+ + +fixes the following issue: +pcs/pcsd/corosyncconf.rb:114: warning: literal string will be frozen in the future +--- + pcsd/corosyncconf.rb | 2 +- + pcsd/test/test_cfgsync.rb | 16 +++++++++++++-- + pcsd/test/test_config.rb | 42 +++++++++++++++++++++++---------------- + 3 files changed, 40 insertions(+), 20 deletions(-) + +diff --git a/pcsd/corosyncconf.rb b/pcsd/corosyncconf.rb +index bcb6df295..4f7a7154c 100644 +--- a/pcsd/corosyncconf.rb ++++ b/pcsd/corosyncconf.rb +@@ -111,7 +111,7 @@ module CorosyncConf + + + def CorosyncConf::parse_string(conf_text) +- conf_text = conf_text.force_encoding("utf-8") ++ conf_text = String.new(conf_text, encoding: Encoding::UTF_8) + root = Section.new('') + self.parse_section(conf_text.split("\n"), root) + return root +diff --git a/pcsd/test/test_cfgsync.rb b/pcsd/test/test_cfgsync.rb +index 143e170c1..2a00b0654 100644 +--- a/pcsd/test/test_cfgsync.rb ++++ b/pcsd/test/test_cfgsync.rb +@@ -153,9 +153,22 @@ class TestPcsdSettings < Test::Unit::TestCase + assert_equal(3, cfg.version) + assert_equal('b35f951a228ac0734d4c1e45fe73c03b18bca380', cfg.hash) + ++ # rubygem-json shipped with ruby 3.4 changed the way JSON.pretty_generate ++ # works a bit. This results in different strings produced by the gem in ++ # ruby older that 3.4 compared to ruby 3.4+. By examining the output of ++ # JSON.pretty_generate, we can figure out which version of the gem we run ++ # against and use the correct hash for the produced string. ++ # https://bugzilla.redhat.com/show_bug.cgi?id=2331005 ++ old_rubygem = JSON.pretty_generate([]) == "[\n\n]" ++ if old_rubygem ++ expected_hash = '26579b79a27f9f56e1acd398eb761d2eb1872c6d' ++ else ++ expected_hash = 'db2b44331c63c25874ec30398fa82decd740fef4' ++ end ++ + cfg.version = 4 + assert_equal(4, cfg.version) +- assert_equal('26579b79a27f9f56e1acd398eb761d2eb1872c6d', cfg.hash) ++ assert_equal(expected_hash, cfg.hash) + + cfg.text = '{ + "format_version": 2, +@@ -1174,4 +1187,3 @@ class TestGetFailedNodesFromSyncResponses < Test::Unit::TestCase + ) + end + end +- +diff --git a/pcsd/test/test_config.rb b/pcsd/test/test_config.rb +index a580b24fa..2f36ffd22 100644 +--- a/pcsd/test/test_config.rb ++++ b/pcsd/test/test_config.rb +@@ -5,6 +5,14 @@ require 'pcsd_test_utils.rb' + require 'config.rb' + require 'permissions.rb' + ++def assert_equal_json(json1, json2) ++ # https://bugzilla.redhat.com/show_bug.cgi?id=2331005 ++ assert_equal( ++ JSON.pretty_generate(JSON.parse(json1)), ++ JSON.pretty_generate(JSON.parse(json2)) ++ ) ++end ++ + class TestConfig < Test::Unit::TestCase + def setup + $logger = MockLogger.new +@@ -56,7 +64,7 @@ class TestConfig < Test::Unit::TestCase + cfg = PCSConfig.new(text) + assert_equal(0, cfg.clusters.length) + assert_equal([], $logger.log) +- assert_equal(fixture_nil_config, cfg.text) ++ assert_equal_json(fixture_nil_config, cfg.text) + end + + def test_parse_empty() +@@ -64,7 +72,7 @@ class TestConfig < Test::Unit::TestCase + cfg = PCSConfig.new(text) + assert_equal(0, cfg.clusters.length) + assert_equal([], $logger.log) +- assert_equal(fixture_empty_config, cfg.text) ++ assert_equal_json(fixture_empty_config, cfg.text) + end + + def test_parse_whitespace() +@@ -72,7 +80,7 @@ class TestConfig < Test::Unit::TestCase + cfg = PCSConfig.new(text) + assert_equal(0, cfg.clusters.length) + assert_equal([], $logger.log) +- assert_equal(fixture_empty_config, cfg.text) ++ assert_equal_json(fixture_empty_config, cfg.text) + end + + def test_parse_hash_empty() +@@ -82,7 +90,7 @@ class TestConfig < Test::Unit::TestCase + [['error', 'Unable to parse pcs_settings file: invalid file format']], + $logger.log + ) +- assert_equal(fixture_empty_config, cfg.text) ++ assert_equal_json(fixture_empty_config, cfg.text) + end + + def test_parse_hash_no_version() +@@ -104,7 +112,7 @@ class TestConfig < Test::Unit::TestCase + [['error', 'Unable to parse pcs_settings file: invalid file format']], + $logger.log + ) +- assert_equal(fixture_empty_config, cfg.text) ++ assert_equal_json(fixture_empty_config, cfg.text) + end + + def test_parse_malformed() +@@ -129,14 +137,14 @@ class TestConfig < Test::Unit::TestCase + /Unable to parse pcs_settings file: (\d+: )?unexpected token/, + $logger.log[0][1] + ) +- assert_equal(fixture_empty_config, cfg.text) ++ assert_equal_json(fixture_empty_config, cfg.text) + end + + def test_parse_format1_empty() + text = '[]' + cfg = PCSConfig.new(text) + assert_equal(0, cfg.clusters.length) +- assert_equal( ++ assert_equal_json( + '{ + "format_version": 2, + "data_version": 0, +@@ -177,7 +185,7 @@ class TestConfig < Test::Unit::TestCase + assert_equal(1, cfg.clusters.length) + assert_equal("cluster71", cfg.clusters[0].name) + assert_equal(["rh71-node1", "rh71-node2"], cfg.clusters[0].nodes) +- assert_equal( ++ assert_equal_json( + '{ + "format_version": 2, + "data_version": 0, +@@ -218,7 +226,7 @@ class TestConfig < Test::Unit::TestCase + assert_equal(2, cfg.format_version) + assert_equal(0, cfg.data_version) + assert_equal(0, cfg.clusters.length) +- assert_equal(fixture_empty_config, cfg.text) ++ assert_equal_json(fixture_empty_config, cfg.text) + end + + def test_parse_format2_one_cluster() +@@ -247,7 +255,7 @@ class TestConfig < Test::Unit::TestCase + assert_equal(1, cfg.clusters.length) + assert_equal("cluster71", cfg.clusters[0].name) + assert_equal(["rh71-node1", "rh71-node2"], cfg.clusters[0].nodes) +- assert_equal(text, cfg.text) ++ assert_equal_json(text, cfg.text) + end + + def test_parse_format2_two_clusters() +@@ -318,7 +326,7 @@ class TestConfig < Test::Unit::TestCase + ] + } + }' +- assert_equal(out_text, cfg.text) ++ assert_equal_json(out_text, cfg.text) + end + + def test_parse_format2_bad_cluster() +@@ -347,7 +355,7 @@ class TestConfig < Test::Unit::TestCase + assert_equal(1, cfg.clusters.length) + assert_equal("cluster71", cfg.clusters[0].name) + assert_equal(["rh71-node1", "rh71-node2"], cfg.clusters[0].nodes) +- assert_equal( ++ assert_equal_json( + '{ + "format_version": 2, + "data_version": 9, +@@ -475,7 +483,7 @@ class TestConfig < Test::Unit::TestCase + } + }' + cfg = PCSConfig.new(text) +- assert_equal(out_text, cfg.text) ++ assert_equal_json(out_text, cfg.text) + + perms = cfg.permissions_local + assert_equal(false, perms.allows?('user1', [], Permissions::FULL)) +@@ -684,7 +692,7 @@ class TestCfgKnownHosts < Test::Unit::TestCase + assert_equal(1, cfg.format_version) + assert_equal(0, cfg.data_version) + assert_equal(0, cfg.known_hosts.length) +- assert_equal(fixture_empty_config(), cfg.text) ++ assert_equal_json(fixture_empty_config(), cfg.text) + end + + def assert_known_host(host, name, token, dest_list) +@@ -765,7 +773,7 @@ class TestCfgKnownHosts < Test::Unit::TestCase + ], + cfg.known_hosts['node1'].dest_list + ) +- assert_equal(text, cfg.text) ++ assert_equal_json(text, cfg.text) + end + + def test_parse_format1_complex() +@@ -825,7 +833,7 @@ class TestCfgKnownHosts < Test::Unit::TestCase + {'addr' => '10.0.2.2', 'port' => 2235} + ] + ) +- assert_equal(text, cfg.text) ++ assert_equal_json(text, cfg.text) + end + + def test_parse_format1_error() +@@ -888,7 +896,7 @@ class TestCfgKnownHosts < Test::Unit::TestCase + {'addr' => '10.0.1.3', 'port' => 2224} + ] + ) +- assert_equal( ++ assert_equal_json( + cfg.text, + '{ + "format_version": 1, +-- +2.48.1 + diff --git a/show-info-page-instead-of-webui.patch b/show-info-page-instead-of-webui.patch new file mode 100644 index 0000000..3d8721f --- /dev/null +++ b/show-info-page-instead-of-webui.patch @@ -0,0 +1,148 @@ +From a6b07bfb9d23462e856429ddc175e8588ad5aacb Mon Sep 17 00:00:00 2001 +From: Ivan Devat +Date: Tue, 5 Nov 2024 16:35:02 +0100 +Subject: [PATCH 1/3] show info page instead of webui + +--- + pcs/Makefile.am | 1 + + pcs/daemon/app/webui_info_handler.py | 31 ++++++++++++++++++++++++++++ + pcs/daemon/run.py | 4 +++- + pcs_test/smoke.sh.in | 4 ++-- + pcsd/public/ui_instructions.html | 24 ++++++++++----------- + 5 files changed, 48 insertions(+), 16 deletions(-) + create mode 100644 pcs/daemon/app/webui_info_handler.py + +diff --git a/pcs/Makefile.am b/pcs/Makefile.am +index 7a734dc15..45d5801fd 100644 +--- a/pcs/Makefile.am ++++ b/pcs/Makefile.am +@@ -206,6 +206,7 @@ EXTRA_DIST = \ + daemon/app/webui/core.py \ + daemon/app/webui/session.py \ + daemon/app/webui/sinatra_ui.py \ ++ daemon/app/webui_info_handler.py \ + daemon/async_tasks/__init__.py \ + daemon/async_tasks/scheduler.py \ + daemon/async_tasks/task.py \ +diff --git a/pcs/daemon/app/webui_info_handler.py b/pcs/daemon/app/webui_info_handler.py +new file mode 100644 +index 000000000..3ab8275bf +--- /dev/null ++++ b/pcs/daemon/app/webui_info_handler.py +@@ -0,0 +1,31 @@ ++from pcs.daemon.app.common import ( ++ BaseHandler, ++ RoutesType, ++) ++ ++ ++class _WebuiInfoHandler(BaseHandler): ++ __path = None ++ ++ def initialize(self, path): ++ self.__path = path ++ ++ def get(self): ++ self.set_status(404) ++ self.render(self.__path) ++ ++ ++def get_routes(path: str) -> RoutesType: ++ return [ ++ # The following two rules can be compressed into one: r"/(ui/?)?". ++ # However, the content of the parentheses used here should be captured ++ # and passed in to the handler’s get method as an argument. ++ # Unfortunately, it seems that tornado version 6.4.1 don't pass this ++ # argument (unlike version 6.3.3). Maybe it's a bug (it needs further ++ # inspection). These rules are a safe way to avoid surprises. ++ # Moreover, the captured parameter is irrelevant to the functionality ++ # of the handler. ++ (r"/", _WebuiInfoHandler, dict(path=path)), ++ (r"/ui/?", _WebuiInfoHandler, dict(path=path)), ++ (r"/ui/.*", _WebuiInfoHandler, dict(path=path)), ++ ] +diff --git a/pcs/daemon/run.py b/pcs/daemon/run.py +index e0090fc1c..e80eecfec 100644 +--- a/pcs/daemon/run.py ++++ b/pcs/daemon/run.py +@@ -35,6 +35,7 @@ from pcs.daemon.app import capabilities as capabilities_app + from pcs.daemon.app import ( + sinatra_remote, + sinatra_ui, ++ webui_info_handler, + ) + + try: +@@ -142,7 +143,8 @@ def configure_app( + # Even with disabled (standalone) webui the following routes must be + # provided because they can be used via unix socket from cockpit. + routes.extend( +- sinatra_ui.get_routes(auth_provider, ruby_pcsd_wrapper) ++ webui_info_handler.get_routes(webui_fallback) ++ + sinatra_ui.get_routes(auth_provider, ruby_pcsd_wrapper) + ) + + return Application( +diff --git a/pcs_test/smoke.sh.in b/pcs_test/smoke.sh.in +index fdfe8be2c..a9bb83447 100755 +--- a/pcs_test/smoke.sh.in ++++ b/pcs_test/smoke.sh.in +@@ -71,10 +71,10 @@ if [ "$webui_http_code_response" = "200" ]; then + curl --insecure --cookie ${cookie_file} --header "X-Requested-With: XMLHttpRequest" --data "hidden[hidden_input]=&config[stonith-enabled]=false" https://localhost:2224/managec/${cluster_name}/update_cluster_settings > "${output_file}" + cat "${output_file}"; echo "" + [ "$(cat ${output_file})" = "Update Successful" ] +-elif [ "$webui_http_code_response" = "401" ]; then ++elif [ "$webui_http_code_response" = "404" ]; then + curl --insecure https://localhost:2224/ui/ > "${output_file}" + cat "${output_file}"; echo "" +- [ "$(cat "${output_file}")" = '{"notauthorized":"true"}' ] ++ grep "HA cluster management has been moved" "${output_file}" + else + echo "Unexpected response from https://localhost:2224/ui/ - http code: '${webui_http_code_response}'" + exit 1 +diff --git a/pcsd/public/ui_instructions.html b/pcsd/public/ui_instructions.html +index a120ed3d4..b9c1c3152 100644 +--- a/pcsd/public/ui_instructions.html ++++ b/pcsd/public/ui_instructions.html +@@ -1,27 +1,25 @@ + + + +- Pcs WebUI instructions ++ Web UI is disabled + + + +-

Pcs WebUI instructions

++

Package pcs-web-ui is not installed

+

+- WebUI is not a part of pcs repository but it has its own +- repository. ++ Since Fedora 42, pcsd web UI is distributed with pcs as pcs-web-ui ++ package. This
package can be uninstalled to disable the web UI. +

+

+- You can clone WebUI repository +- and build the web application into pcs by: ++ To re-enable pcsd web UI, install the pcs-web-ui RPM package. +

+-

+-    $ npm install
+-    $ npm run build
+-    $ mv ./build [/path/to/]pcs/pcsd/public/ui
+-  
+

+- For more details, see instructions in +- README.md. ++ Another option is to try pcsd web UI as an application for ++ Cockpit ++ - a web-based
graphical interface for servers. The HA Cluster Management ++ application can be
installed from within the Applications pane in ++ Cockpit or by installing the
cockpit-ha-cluster RPM ++ package. +

+ + +-- +2.48.1 + diff --git a/sources b/sources index 7582c05..c4e246f 100644 --- a/sources +++ b/sources @@ -1,5 +1,5 @@ SHA512 (pyagentx-0.4.pcs.2.tar.gz) = d4194fec9a3e5fefe3793d49b7fec1feafef294c7e613a06046c2993daeefc5cb39d7c5b2b402ff83e49b2d976953f862264288c758c0be09d997b5323cc558a SHA512 (dacite-1.8.1.tar.gz) = 4b40c0bdcf5490bcc77de9e7f04b7267642bcfd41e4168607a5457f38abe3ad4b3041d8a23cb43af76de14eabee45f900ad5ddf7af8f70a2be4850bccc2d3af1 -SHA512 (pcs-0.11.8.tar.gz) = 2705b612c602e9052405e448dc189f632f0266bf0d8381981a1dca709f3e851e90745bc02c2f9dfaa9e84d9ab0f3f1287467388d7d584e7e9e5ec4a46b8c2076 -SHA512 (pcs-web-ui-0.1.20.tar.gz) = 83117eafbe694b133228dfd8d7de30a7cc58693b8844f7d1af9c12c02618a7af8dd10c374b56c3e722d84c5691488f25bfc3389f22954935a2e6dd42b16c7b2c -SHA512 (pcs-web-ui-node-modules-0.1.20.tar.xz) = 94cd6a306a6784c3decc351b1469efe98beadd43efbfa7848ccc6146be32f704281432669589e2c666b431a32bd6caf101fa08fb05deaab2b58a8cda8b40b85d +SHA512 (pcs-0.12.0.tar.gz) = 7b4a1c7589fabe301f7ffd15a7f13954bfe958f3c02d90ae30a07afb50b8cabe8fafdc0dc62b10f0561a1a615157d4433f732245ccaca2003f9ce8c1a032439e +SHA512 (pcs-web-ui-0.1.22.tar.gz) = cb97ffba625326ab3857b9c22b4400907177a5ea88769ae611cc9315758c1ceca7e16a1b92d43fc594911fcde6003d3beadb388c6bdd5c1bcc67d699c49c9b2c +SHA512 (pcs-web-ui-node-modules-0.1.22.tar.xz) = b1db7d8c04e942baf8a99f115cbda31a84f562c7deeee5f1371e5ddf5fb5e73ce084ede1f0da7083b2d0114228f58006599f1b9a29dd3a5202b3119e41f74d69 From 0ab16a578c8c3a58efb96c901327910efc109e65 Mon Sep 17 00:00:00 2001 From: Python Maint Date: Tue, 3 Jun 2025 23:35:19 +0200 Subject: [PATCH 14/26] Rebuilt for Python 3.14 --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 1cee4c9..f01a919 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.12.0 -Release: 1%{?dist} +Release: 2%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -529,6 +529,9 @@ fi %changelog +* Tue Jun 03 2025 Python Maint - 0.12.0-2 +- Rebuilt for Python 3.14 + * Mon Jan 27 2025 Michal Pospíšil - 0.12.0-1 - Rebased pcs to the newest major version (see CHANGELOG.md) Resolves: rhbz#2341012 From db939b82741e14bad7811b43bef3883321b05476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Fri, 18 Jul 2025 17:19:31 +0200 Subject: [PATCH 15/26] fix URL of pcs-web-ui package --- pcs.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index f01a919..b6514c5 100644 --- a/pcs.spec +++ b/pcs.spec @@ -231,7 +231,7 @@ Summary: Standalone web UI for Pacemaker/Corosync Configuration System # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs License: GPL-2.0-only -URL: https://github.com/ClusterLabs/pcs +URL: https://github.com/ClusterLabs/pcs-web-ui # Split pcs to pcs and pcs-web-ui, all packages that replace pcs must obsolete # the old monolithic package From 825b1756acd99d7dda76c814814e902a0265d4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Fri, 18 Jul 2025 18:55:45 +0200 Subject: [PATCH 16/26] depend on rackup with rack 3+ Since rack 3, rack handlers were moved to a new gem called rackup. As a part of update to rack 3 in Fedora, a new package rubygem-rackup is included [1]. No upstream changes are needed, we already have a mechanism to require rackup when rack >= 3. Resolves: rhbz#2372462 [1] https://bugzilla.redhat.com/show_bug.cgi?id=2338474 --- pcs.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pcs.spec b/pcs.spec index b6514c5..ee26861 100644 --- a/pcs.spec +++ b/pcs.spec @@ -125,6 +125,7 @@ BuildRequires: rubygem-json BuildRequires: rubygem-mustermann BuildRequires: rubygem-puma BuildRequires: rubygem-rack +BuildRequires: (rubygem-rackup if rubygem-rack >= 3.0.0) BuildRequires: rubygem-rack-protection BuildRequires: rubygem-rack-test BuildRequires: rubygem-sinatra @@ -178,6 +179,7 @@ Requires: rubygem-json Requires: rubygem-mustermann Requires: rubygem-puma Requires: rubygem-rack +Requires: (rubygem-rackup if rubygem-rack >= 3.0.0) Requires: rubygem-rack-protection Requires: rubygem-sinatra Requires: rubygem-tilt From 959addae3b271e7c7823380db0f493bc5bf167c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Tue, 22 Jul 2025 17:48:55 +0200 Subject: [PATCH 17/26] use virtual provides for rack and rackup This fixes commit 825b175. Dnf5 cannot resolve the rpm name for some reason. Switching to virtual provides rubygem(rack) instead of rubygem-rack solves the issue. As a troubleshooting attempt, I also tried a different approach to declaring the dependency with "and" and "or". This provides a more complete picture and is less hacky than the if boolean dependency [1]. This might have something to do with how provides are defined: rpm -qP -p ./rubygem-rack-3.1.16-1.fc43.noarch.rpm rubygem(rack) = 3.1.16 rubygem-rack = 1:3.1.16-1.fc43 [1] https://rpm-software-management.github.io/rpm/manual/boolean_dependencies.html --- pcs.spec | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pcs.spec b/pcs.spec index ee26861..be69448 100644 --- a/pcs.spec +++ b/pcs.spec @@ -124,8 +124,7 @@ BuildRequires: rubygem-ffi BuildRequires: rubygem-json BuildRequires: rubygem-mustermann BuildRequires: rubygem-puma -BuildRequires: rubygem-rack -BuildRequires: (rubygem-rackup if rubygem-rack >= 3.0.0) +BuildRequires: (rubygem(rack) < 3 or (rubygem(rack) >= 3 and rubygem(rackup))) BuildRequires: rubygem-rack-protection BuildRequires: rubygem-rack-test BuildRequires: rubygem-sinatra @@ -178,8 +177,7 @@ Requires: rubygem-ffi Requires: rubygem-json Requires: rubygem-mustermann Requires: rubygem-puma -Requires: rubygem-rack -Requires: (rubygem-rackup if rubygem-rack >= 3.0.0) +Requires: (rubygem(rack) < 3 or (rubygem(rack) >= 3 and rubygem(rackup))) Requires: rubygem-rack-protection Requires: rubygem-sinatra Requires: rubygem-tilt From 2cc50341f9b2c87d6054b83f26bdafb3526bf236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Fri, 18 Jul 2025 19:21:38 +0200 Subject: [PATCH 18/26] package licenses and docs for pcs-web-ui Pcs-web-ui added a changelog upstream, so I'm adding it downstream as well. It turns out that I forgot to package the readme and license before, so adding them too. In Fedora, I have to copy the files to the cockpit package and pcs-web-ui package since they both include the pcs-web-ui upstream code. For pcs, readme and changelog are installed via automake variable `dist_doc_DATA` [1] which gets automatically converted to its own target ran during `make install`. The target installs it to %docdir/%TARNAME (automake variables). This happens to align with RPM default of %_docdir/%name (spec macros). This is rendered completely useless as these later get replaced by RPM anyway. The path is therefore /usr/share/doc/pcs. RPM %doc directive has two modes. If there is a relative path, the %doc directive runs a script that goes into builddir/BUILD/ and copies the file to %_docdir. If there is an absolute path, the file is only marked as a doc file in the RPM database. The same goes for %license directive, except for it getting copied to %_defaultlicensedir. [2][3] The problem arises for pcs-web-ui files as they neither come from the pcs tarball nor are to be owned by the pcs package. Additionally, the package name changes for different downstreams. Because the package name changes, it is not desirable to install the files in the upstream Makefile which is not aware of RPM package names. I made a decision to handle file copying entirely in the specfile for these reasons. It seems like for relative paths, RPM searches the Source0 tarball, but ours are located in Source100. Therefore, I explicitly used %_docdir and %_defaultlicensedir in %install and %files. [1]: https://www.gnu.org/software/automake/manual/html_node/amhello_0027s-Makefile_002eam-Setup-Explained.html [2]: https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ [3]: https://web.archive.org/web/20160927094629/https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s05s03.html --- pcs.spec | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pcs.spec b/pcs.spec index be69448..6f3b298 100644 --- a/pcs.spec +++ b/pcs.spec @@ -387,6 +387,22 @@ pwd cd ../%{ui_src_name} %make_install +# prepare pcs-web-ui files (not needed for pcs as pcs installs them in Makefile) +mkdir -p %{buildroot}/%{_defaultlicensedir}/%{pkg_cockpit_ha_cluster} +mkdir -p %{buildroot}/%{_defaultlicensedir}/%{pkg_pcs_web_ui} + +cp COPYING %{buildroot}/%{_defaultlicensedir}/%{pkg_cockpit_ha_cluster}/COPYING_WUI.md +mv COPYING %{buildroot}/%{_defaultlicensedir}/%{pkg_pcs_web_ui}/COPYING_WUI.md + +mkdir -p %{buildroot}/%{_docdir}/%{pkg_cockpit_ha_cluster} +mkdir -p %{buildroot}/%{_docdir}/%{pkg_pcs_web_ui} + +cp CHANGELOG.md %{buildroot}/%{_docdir}/%{pkg_cockpit_ha_cluster}/CHANGELOG_WUI.md +mv CHANGELOG.md %{buildroot}/%{_docdir}/%{pkg_pcs_web_ui}/CHANGELOG_WUI.md + +cp README.md %{buildroot}/%{_docdir}/%{pkg_cockpit_ha_cluster}/README_WUI.md +mv README.md %{buildroot}/%{_docdir}/%{pkg_pcs_web_ui}/README_WUI.md + # Install pcs cd ../%{pcs_source_name} %make_install @@ -505,7 +521,10 @@ fi %files -n %{pkg_pcs_web_ui} %doc CHANGELOG.md +%doc %{_docdir}/%{pkg_pcs_web_ui}/CHANGELOG_WUI.md +%doc %{_docdir}/%{pkg_pcs_web_ui}/README_WUI.md %license COPYING +%license %{_defaultlicensedir}/%{pkg_pcs_web_ui}/COPYING_WUI.md %{python3_sitelib}/pcs/daemon/app/webui %{pcsd_webui_dir} @@ -523,6 +542,9 @@ fi %license pyagentx_LICENSE.txt %files -n %{pkg_cockpit_ha_cluster} +%doc %{_docdir}/%{pkg_cockpit_ha_cluster}/CHANGELOG_WUI.md +%doc %{_docdir}/%{pkg_cockpit_ha_cluster}/README_WUI.md +%license %{_defaultlicensedir}/%{pkg_cockpit_ha_cluster}/COPYING_WUI.md %{cockpit_dir} %{ui_metainfo} From 2f443108e09898bd1707800bc5421ff3d1f0fa78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Fri, 18 Jul 2025 19:24:24 +0200 Subject: [PATCH 19/26] add --enable-webui switch to tests The switch alters the test suite behavior - we want it enabled since we want pcsd to support webui in standalone mode if the user chooses to install pcs-web-ui package. --- prepare-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prepare-tests.sh b/prepare-tests.sh index 5ecdf1c..aeb9a8b 100755 --- a/prepare-tests.sh +++ b/prepare-tests.sh @@ -15,7 +15,7 @@ export GEM_HOME=/usr/lib/pcsd/vendor/bundle/ # We need to use cd pcs-* because when pcs-web-ui starts using autotools, running # autogen and configure with expanded TMT_SOURCE_DIR will match that too ./autogen.sh -./configure --enable-local-build --enable-use-local-cache-only \ +./configure --enable-webui --enable-local-build --enable-use-local-cache-only \ --enable-individual-bundling --with-pcs-lib-dir=/usr/lib # Remove pcs sources to make sure tests are not using any of those files rm -rf pcs From 1351fa3026887960773e0f7c0b32c8738241392d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Fri, 18 Jul 2025 19:59:36 +0200 Subject: [PATCH 20/26] report pcs-web-ui version and simplify version macros The original goal was to report the pcs-web-ui upstream version through rpm to simplify reporting bugs upstream because subpackages inherit the pcs version from the main package. When pcs-web-ui is built from unreleased version, I needed a mechanism to include the git revision in the version string. This mechanism already existed for generating .tarball-version. I didn't want to duplicate the code so I moved it to a macro. With this approach I was also able to simplify conditions for generating .tarball-version file. On top of that, as I was adding the new tarball_version macro, I noticed that the if conditions could be simplified by updating the existing variables instead of using the else branch. --- pcs.spec | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pcs.spec b/pcs.spec index 6f3b298..f8a2234 100644 --- a/pcs.spec +++ b/pcs.spec @@ -17,10 +17,10 @@ BuildArch: noarch # To build an official pcs release, comment out branch_or_commit # Use long commit hash or branch name to build an unreleased version # %%global branch_or_commit 1353dfbb3af82d77f4de17a3fa4cbde185bb2b2d +%global version_or_commit %{clean_version} %if 0%{?branch_or_commit:1} %global version_or_commit %{branch_or_commit} -%else - %global version_or_commit %{clean_version} + %global tarball_version %{clean_version}+%(echo %{branch_or_commit} | head -c 8) %endif %global pcs_source_name %{name}-%{version_or_commit} @@ -30,10 +30,10 @@ BuildArch: noarch %global ui_modules_version 0.1.22 # Use long commit hash or branch name to build an unreleased version # %%global ui_branch_or_commit 34372d1268f065ed186546f55216aaa2d7e76b54 +%global ui_version_or_commit %{ui_version} %if 0%{?ui_branch_or_commit:1} %global ui_version_or_commit %{ui_branch_or_commit} -%else - %global ui_version_or_commit %{ui_version} + %global ui_tarball_version %{ui_version}-%(echo %{ui_branch_or_commit} | head -c 8) %endif %global ui_src_name pcs-web-ui-%{ui_version_or_commit} @@ -240,6 +240,8 @@ Obsoletes: pcs < 0.12.0 Requires: pcs = %{version}-%{release} +Provides: bundled(pcs-web-ui) = %{!?ui_tarball_version:%{ui_version}}%{?ui_tarball_version} + # cockpit-ha-cluster subpackage definition %package -n %{pkg_cockpit_ha_cluster} Group: System Environment/Base @@ -253,6 +255,8 @@ BuildRequires: nodejs-npm Requires: pcs = %{version}-%{release} Requires: cockpit-bridge +Provides: bundled(pcs-web-ui) = %{!?ui_tarball_version:%{ui_version}}%{?ui_tarball_version} + %description @@ -341,12 +345,12 @@ update_times_patch %{PATCH3} # generate .tarball-version if building from an untagged commit, not a released version # autogen uses git-version-gen which uses .tarball-version for generating version number -%if "%{clean_version}" != "%{version_or_commit}" - echo "%{clean_version}+$(echo "%{version_or_commit}" | head -c 8)" > %{_builddir}/%{pcs_source_name}/.tarball-version +%if 0%{?tarball_version:1} + echo %{tarball_version} > %{_builddir}/%{pcs_source_name}/.tarball-version %endif -%if "x%{?ui_branch_or_commit}" != "x" - echo "%{ui_version}+$(echo "%{ui_branch_or_commit}" | head -c 8)" > %{_builddir}/%{ui_src_name}/.tarball-version +%if 0%{?ui_tarball_version:1} + echo %{ui_tarball_version} > %{_builddir}/%{ui_src_name}/.tarball-version %endif # prepare dirs/files necessary for building python bundles From 8cd0772e80be89ad4eae4cabe1440cb04682da28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Fri, 18 Jul 2025 20:31:50 +0200 Subject: [PATCH 21/26] pcs-0.12.1-1 - Rebased pcs to the newest major version (see CHANGELOG.md) Resolves: rhbz#2371770 - Updated standalone web UI and HA Cluster Management Cockpit application to pcs-web-ui 0.1.23 (see CHANGELOG_WUI.md) - There is now a changelog for the HA Cluster Management Cockpit application and the standalone web UI in both packages - Updated bundled Python dependency dacite --- .gitignore | 4 + ...lones-by-agent-name-in-resource-tree.patch | 82 ------ ...-on-systems-with-merged-bin-and-sbin.patch | 66 ----- fix-pcsd-not-starting-with-older-rack.patch | 32 +++ pcs.spec | 26 +- ruby-3.4-compatibility.patch | 233 ------------------ show-info-page-instead-of-webui.patch | 20 +- sources | 8 +- 8 files changed, 66 insertions(+), 405 deletions(-) delete mode 100644 fix-filter-clones-by-agent-name-in-resource-tree.patch delete mode 100644 fix-install-on-systems-with-merged-bin-and-sbin.patch create mode 100644 fix-pcsd-not-starting-with-older-rack.patch delete mode 100644 ruby-3.4-compatibility.patch diff --git a/.gitignore b/.gitignore index b5a80bb..fbe8060 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,7 @@ /pcs-0.12.0.tar.gz /pcs-web-ui-0.1.22.tar.gz /pcs-web-ui-node-modules-0.1.22.tar.xz +/dacite-1.9.2.tar.gz +/pcs-0.12.1.tar.gz +/pcs-web-ui-0.1.23.tar.gz +/pcs-web-ui-node-modules-0.1.23.tar.xz diff --git a/fix-filter-clones-by-agent-name-in-resource-tree.patch b/fix-filter-clones-by-agent-name-in-resource-tree.patch deleted file mode 100644 index 2ddaf01..0000000 --- a/fix-filter-clones-by-agent-name-in-resource-tree.patch +++ /dev/null @@ -1,82 +0,0 @@ -From e949ae0e2fc350ed1e74ce48b50ac812efd92f30 Mon Sep 17 00:00:00 2001 -From: Ivan Devat -Date: Mon, 20 Jan 2025 12:13:25 +0100 -Subject: [PATCH] fix: filter clones by agent name in resource tree - ---- - .../src/app/view/cluster/resources/tree/filter.ts | 13 +++++++------ - .../test/src/test/scenes/resources/tree.test.ts | 14 +++++++++++--- - 2 files changed, 18 insertions(+), 9 deletions(-) - -diff --git a/packages/app/src/app/view/cluster/resources/tree/filter.ts b/packages/app/src/app/view/cluster/resources/tree/filter.ts -index 118e6cc2..b047a094 100644 ---- a/packages/app/src/app/view/cluster/resources/tree/filter.ts -+++ b/packages/app/src/app/view/cluster/resources/tree/filter.ts -@@ -1,4 +1,4 @@ --import {Resource} from "app/view/cluster/types"; -+import type {FenceDevice, Resource} from "app/view/cluster/types"; - - type Group = Extract; - type Clone = Extract; -@@ -14,13 +14,14 @@ const createResourceFilter = (filter: string) => { - const match = (searchable: string) => - searchable.toLowerCase().includes(filter.toLowerCase()); - -+ const matchPrimitive = (primitive: Primitive | FenceDevice) => -+ match(primitive.id) || match(primitive.agentName); -+ - const filterPrimitive = (primitive: Primitive) => -- match(primitive.id) || match(primitive.agentName) ? primitive : null; -+ matchPrimitive(primitive) ? primitive : null; - - const filterGroup = (group: Group): Group | null => { -- const primitives = group.resources.filter( -- primitive => match(primitive.id) || match(primitive.agentName), -- ); -+ const primitives = group.resources.filter(matchPrimitive); - return match(group.id) || primitives.length > 0 - ? {...group, resources: primitives} - : null; -@@ -34,7 +35,7 @@ const createResourceFilter = (filter: string) => { - : null; - } - -- if (match(clone.member.id)) { -+ if (matchPrimitive(clone.member)) { - return clone; - } - -diff --git a/packages/test/src/test/scenes/resources/tree.test.ts b/packages/test/src/test/scenes/resources/tree.test.ts -index f9b118f8..19190955 100644 ---- a/packages/test/src/test/scenes/resources/tree.test.ts -+++ b/packages/test/src/test/scenes/resources/tree.test.ts -@@ -19,7 +19,15 @@ const resourceList = [ - "Clone1", - cs.group("Group2", [cs.primitive("ResourceD"), cs.primitive("ResourceE")]), - ), -- cs.clone("Clone2", cs.primitive("ResourceF")), -+ cs.clone( -+ "Clone2", -+ cs.primitive("ResourceF", { -+ agentname: "ocf:heartbeat:apache", -+ provider: "heartbeat", -+ class: "ocf", -+ type: "apache", -+ }), -+ ), - ]; - - const primitiveItem = (id: string) => -@@ -129,7 +137,7 @@ describe("Resource tree filter", () => { - await isAbsent(groupItem("Group2")); - await isAbsent(primitiveItem("ResourceD")); - await isAbsent(primitiveItem("ResourceE")); -- await isAbsent(cloneItem("Clone2")); -- await isAbsent(primitiveItem("ResourceF")); -+ await isVisible(cloneItem("Clone2")); -+ await isVisible(primitiveItem("ResourceF")); - }); - }); --- -2.48.1 - diff --git a/fix-install-on-systems-with-merged-bin-and-sbin.patch b/fix-install-on-systems-with-merged-bin-and-sbin.patch deleted file mode 100644 index d75367d..0000000 --- a/fix-install-on-systems-with-merged-bin-and-sbin.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 5745b7d6fac794a1bf13bad6376958acc6aa714d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= -Date: Mon, 20 Jan 2025 18:00:16 +0100 -Subject: [PATCH 3/3] fix install on systems with merged bin and sbin - -Fedora 42 is planning to symlink the /usr/sbin to /usr/bin directory. To -prevent installation failures, pcs and pcsd binary (entry point) will no -longer be moved to /usr/sbin when such a system is detected. - -Based on: https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin ---- - Makefile.am | 24 ++++++++++++++++-------- - 1 file changed, 16 insertions(+), 8 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index f552a8b1e..53d3bb364 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -168,6 +168,10 @@ endif - # * Pip installs scripts into bin directory and that cannot be changed, so the - # files are moved manually. Some of the folders do not exist in DESTDIR or - # prefix locations, so they need to be created first, otherwise mv fails -+# * For systems where sbin and bin is merged, autotools should have correctly -+# defined the bindir and SBINDIR macros. If this isn't true, configure can be -+# run with --sbindir equal to bindir. It is assumed that setuptools also use -+# bindir location to output entry point script. - install-exec-local: install_python_embedded_mods stamps/install_ruby_deps_local - if $$(${PYTHON} -c "import sys; exit(sys.base_prefix == sys.prefix)"); then \ - echo "WARNING: Virtual environment is activated, shebangs in Python " \ -@@ -182,10 +186,12 @@ install-exec-local: install_python_embedded_mods stamps/install_ruby_deps_local - ${PIP} ${pipopts} install ${pipinstallopts} \ - --root=$(or ${DESTDIR}, /) \ - --prefix=${prefix} ${EXTRA_SETUP_OPTS} . -- mv ${DESTDIR}/$(prefix)/bin/pcs ${DESTDIR}/$(SBINDIR)/ || \ -- mv ${DESTDIR}/$(prefix)/local/bin/pcs ${DESTDIR}/${prefix}/local/sbin/ -- mv ${DESTDIR}/$(prefix)/bin/pcsd ${DESTDIR}/$(SBINDIR)/ || \ -- mv ${DESTDIR}/$(prefix)/local/bin/pcsd ${DESTDIR}/${prefix}/local/sbin/ -+ if test "${DESTDIR}/$(prefix)/bin/" != "${DESTDIR}/$(SBINDIR)/"; then \ -+ mv ${DESTDIR}/$(prefix)/bin/pcs ${DESTDIR}/$(SBINDIR)/ || \ -+ mv ${DESTDIR}/$(prefix)/local/bin/pcs ${DESTDIR}/${prefix}/local/sbin/; \ -+ mv ${DESTDIR}/$(prefix)/bin/pcsd ${DESTDIR}/$(SBINDIR)/ || \ -+ mv ${DESTDIR}/$(prefix)/local/bin/pcsd ${DESTDIR}/${prefix}/local/sbin/; \ -+ fi - mv ${DESTDIR}/$(prefix)/bin/pcs_internal ${DESTDIR}/$(LIB_DIR)/pcs/ || \ - mv ${DESTDIR}/$(prefix)/local/bin/pcs_internal ${DESTDIR}/${LIB_DIR}/pcs/ - mv ${DESTDIR}/$(prefix)/bin/pcs_snmp_agent ${DESTDIR}/$(LIB_DIR)/pcs/ || \ -@@ -209,10 +215,12 @@ install-exec-local: install_python_embedded_mods stamps/install_ruby_deps_local - # which are untouched by make install. - uninstall-local: - rm -rf ${DESTDIR}/$(PCS_BUNDLED_DIR) -- find ${DESTDIR}/$(prefix)/local/sbin -name pcs -type f -delete || \ -- rm -fv ${DESTDIR}/$(SBINDIR)/pcs -- find ${DESTDIR}/$(prefix)/local/sbin -name pcsd -type f -delete || \ -- rm -fv ${DESTDIR}/$(SBINDIR)/pcsd -+ if test "${DESTDIR}/$(prefix)/bin/" != "${DESTDIR}/$(SBINDIR)/"; then \ -+ find ${DESTDIR}/$(prefix)/local/sbin -name pcs -type f -delete || \ -+ rm -fv ${DESTDIR}/$(SBINDIR)/pcs; \ -+ find ${DESTDIR}/$(prefix)/local/sbin -name pcsd -type f -delete || \ -+ rm -fv ${DESTDIR}/$(SBINDIR)/pcsd; \ -+ fi - rm -fv ${DESTDIR}/$(LIB_DIR)/pcs/pcs_internal - rm -fv ${DESTDIR}/$(LIB_DIR)/pcs/pcs_snmp_agent - sitelib=${DESTDIR}/${prefix}/local/lib/python*/dist-packages; \ --- -2.48.1 - diff --git a/fix-pcsd-not-starting-with-older-rack.patch b/fix-pcsd-not-starting-with-older-rack.patch new file mode 100644 index 0000000..e18f4ef --- /dev/null +++ b/fix-pcsd-not-starting-with-older-rack.patch @@ -0,0 +1,32 @@ +From a2899ef0e20bb638f47e74077281e73f4f18faf3 Mon Sep 17 00:00:00 2001 +From: Miroslav Lisik +Date: Thu, 10 Jul 2025 19:48:28 +0200 +Subject: [PATCH 2/2] fix ruby NameError exception in pcsd/pcsd.rb occuring + with older rack + +--- + pcsd/pcsd.rb | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/pcsd/pcsd.rb b/pcsd/pcsd.rb +index e8ae9f106..c9f668851 100644 +--- a/pcsd/pcsd.rb ++++ b/pcsd/pcsd.rb +@@ -74,9 +74,11 @@ configure do + CAPABILITIES_PCSD = capabilities_pcsd.freeze + end + +-error Rack::QueryParser::QueryLimitError do +- $logger.warn(env['sinatra.error'].message) +- return 400, env['sinatra.error'].message ++if Rack.const_defined?(:QueryParser) and Rack::QueryParser.const_defined?(:QueryLimitError) ++ error Rack::QueryParser::QueryLimitError do ++ $logger.warn(env['sinatra.error'].message) ++ return 400, env['sinatra.error'].message ++ end + end + + get '/remote/?:command?' do +-- +2.50.1 + diff --git a/pcs.spec b/pcs.spec index f8a2234..04e5dd6 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs -Version: 0.12.0 -Release: 2%{?dist} +Version: 0.12.1 +Release: 1%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -26,8 +26,8 @@ BuildArch: noarch # To build an official pcs-web-ui release, comment out ui_branch_or_commit # Last tagged version, also used as fallback version for untagged tarballs -%global ui_version 0.1.22 -%global ui_modules_version 0.1.22 +%global ui_version 0.1.23 +%global ui_modules_version 0.1.23 # Use long commit hash or branch name to build an unreleased version # %%global ui_branch_or_commit 34372d1268f065ed186546f55216aaa2d7e76b54 %global ui_version_or_commit %{ui_version} @@ -39,7 +39,7 @@ BuildArch: noarch %global pyagentx_version 0.4.pcs.2 -%global dacite_version 1.8.1 +%global dacite_version 1.9.2 %global required_pacemaker_version 3.0.0 @@ -73,12 +73,10 @@ Source101: https://github.com/ClusterLabs/pcs-web-ui/releases/download/%{ui_vers # pcs patches: <= 200 # Patch1: name.patch Patch1: show-info-page-instead-of-webui.patch -Patch2: ruby-3.4-compatibility.patch -Patch3: fix-install-on-systems-with-merged-bin-and-sbin.patch +Patch2: fix-pcsd-not-starting-with-older-rack.patch # ui patches: >200 # Patch201: name-web-ui.patch -Patch201: fix-filter-clones-by-agent-name-in-resource-tree.patch # Split pcs to pcs and pcs-web-ui, all packages that replace pcs must obsolete @@ -333,7 +331,6 @@ update_times_patch(){ %autosetup -T -b 100 -a 101 -N -n %{ui_src_name} %autopatch -p1 -m 201 # update_times_patch %%{PATCH201} -update_times_patch %{PATCH201} # patch pcs sources %autosetup -S git -n %{pcs_source_name} -N @@ -341,7 +338,6 @@ update_times_patch %{PATCH201} # update_times_patch %%{PATCH1} update_times_patch %{PATCH1} update_times_patch %{PATCH2} -update_times_patch %{PATCH3} # generate .tarball-version if building from an untagged commit, not a released version # autogen uses git-version-gen which uses .tarball-version for generating version number @@ -555,6 +551,16 @@ fi %changelog +* Fri Jul 18 2025 Michal Pospíšil - 0.12.1-1 +- Rebased pcs to the newest major version (see CHANGELOG.md) + Resolves: rhbz#2371770 +- Updated standalone web UI and HA Cluster Management Cockpit application to pcs-web-ui 0.1.23 (see CHANGELOG_WUI.md) +- There is now a changelog for the HA Cluster Management Cockpit application and the standalone web UI in both packages +- The upstream version of pcs-web-ui can now be queried through RPM in both packages - see bundled(pcs-web-ui) +- Updated bundled Python dependency dacite +- Compatibility with rubygem-rack >= 3 + Resolves: rhbz#2372462 + * Tue Jun 03 2025 Python Maint - 0.12.0-2 - Rebuilt for Python 3.14 diff --git a/ruby-3.4-compatibility.patch b/ruby-3.4-compatibility.patch deleted file mode 100644 index 7d0288c..0000000 --- a/ruby-3.4-compatibility.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 33e8a769b48410b854f33ffb483f58340cd2c9d8 Mon Sep 17 00:00:00 2001 -From: Tomas Jelinek -Date: Tue, 14 Jan 2025 13:33:11 +0100 -Subject: [PATCH 2/3] fix for ruby 3.4+ - -fixes the following issue: -pcs/pcsd/corosyncconf.rb:114: warning: literal string will be frozen in the future ---- - pcsd/corosyncconf.rb | 2 +- - pcsd/test/test_cfgsync.rb | 16 +++++++++++++-- - pcsd/test/test_config.rb | 42 +++++++++++++++++++++++---------------- - 3 files changed, 40 insertions(+), 20 deletions(-) - -diff --git a/pcsd/corosyncconf.rb b/pcsd/corosyncconf.rb -index bcb6df295..4f7a7154c 100644 ---- a/pcsd/corosyncconf.rb -+++ b/pcsd/corosyncconf.rb -@@ -111,7 +111,7 @@ module CorosyncConf - - - def CorosyncConf::parse_string(conf_text) -- conf_text = conf_text.force_encoding("utf-8") -+ conf_text = String.new(conf_text, encoding: Encoding::UTF_8) - root = Section.new('') - self.parse_section(conf_text.split("\n"), root) - return root -diff --git a/pcsd/test/test_cfgsync.rb b/pcsd/test/test_cfgsync.rb -index 143e170c1..2a00b0654 100644 ---- a/pcsd/test/test_cfgsync.rb -+++ b/pcsd/test/test_cfgsync.rb -@@ -153,9 +153,22 @@ class TestPcsdSettings < Test::Unit::TestCase - assert_equal(3, cfg.version) - assert_equal('b35f951a228ac0734d4c1e45fe73c03b18bca380', cfg.hash) - -+ # rubygem-json shipped with ruby 3.4 changed the way JSON.pretty_generate -+ # works a bit. This results in different strings produced by the gem in -+ # ruby older that 3.4 compared to ruby 3.4+. By examining the output of -+ # JSON.pretty_generate, we can figure out which version of the gem we run -+ # against and use the correct hash for the produced string. -+ # https://bugzilla.redhat.com/show_bug.cgi?id=2331005 -+ old_rubygem = JSON.pretty_generate([]) == "[\n\n]" -+ if old_rubygem -+ expected_hash = '26579b79a27f9f56e1acd398eb761d2eb1872c6d' -+ else -+ expected_hash = 'db2b44331c63c25874ec30398fa82decd740fef4' -+ end -+ - cfg.version = 4 - assert_equal(4, cfg.version) -- assert_equal('26579b79a27f9f56e1acd398eb761d2eb1872c6d', cfg.hash) -+ assert_equal(expected_hash, cfg.hash) - - cfg.text = '{ - "format_version": 2, -@@ -1174,4 +1187,3 @@ class TestGetFailedNodesFromSyncResponses < Test::Unit::TestCase - ) - end - end -- -diff --git a/pcsd/test/test_config.rb b/pcsd/test/test_config.rb -index a580b24fa..2f36ffd22 100644 ---- a/pcsd/test/test_config.rb -+++ b/pcsd/test/test_config.rb -@@ -5,6 +5,14 @@ require 'pcsd_test_utils.rb' - require 'config.rb' - require 'permissions.rb' - -+def assert_equal_json(json1, json2) -+ # https://bugzilla.redhat.com/show_bug.cgi?id=2331005 -+ assert_equal( -+ JSON.pretty_generate(JSON.parse(json1)), -+ JSON.pretty_generate(JSON.parse(json2)) -+ ) -+end -+ - class TestConfig < Test::Unit::TestCase - def setup - $logger = MockLogger.new -@@ -56,7 +64,7 @@ class TestConfig < Test::Unit::TestCase - cfg = PCSConfig.new(text) - assert_equal(0, cfg.clusters.length) - assert_equal([], $logger.log) -- assert_equal(fixture_nil_config, cfg.text) -+ assert_equal_json(fixture_nil_config, cfg.text) - end - - def test_parse_empty() -@@ -64,7 +72,7 @@ class TestConfig < Test::Unit::TestCase - cfg = PCSConfig.new(text) - assert_equal(0, cfg.clusters.length) - assert_equal([], $logger.log) -- assert_equal(fixture_empty_config, cfg.text) -+ assert_equal_json(fixture_empty_config, cfg.text) - end - - def test_parse_whitespace() -@@ -72,7 +80,7 @@ class TestConfig < Test::Unit::TestCase - cfg = PCSConfig.new(text) - assert_equal(0, cfg.clusters.length) - assert_equal([], $logger.log) -- assert_equal(fixture_empty_config, cfg.text) -+ assert_equal_json(fixture_empty_config, cfg.text) - end - - def test_parse_hash_empty() -@@ -82,7 +90,7 @@ class TestConfig < Test::Unit::TestCase - [['error', 'Unable to parse pcs_settings file: invalid file format']], - $logger.log - ) -- assert_equal(fixture_empty_config, cfg.text) -+ assert_equal_json(fixture_empty_config, cfg.text) - end - - def test_parse_hash_no_version() -@@ -104,7 +112,7 @@ class TestConfig < Test::Unit::TestCase - [['error', 'Unable to parse pcs_settings file: invalid file format']], - $logger.log - ) -- assert_equal(fixture_empty_config, cfg.text) -+ assert_equal_json(fixture_empty_config, cfg.text) - end - - def test_parse_malformed() -@@ -129,14 +137,14 @@ class TestConfig < Test::Unit::TestCase - /Unable to parse pcs_settings file: (\d+: )?unexpected token/, - $logger.log[0][1] - ) -- assert_equal(fixture_empty_config, cfg.text) -+ assert_equal_json(fixture_empty_config, cfg.text) - end - - def test_parse_format1_empty() - text = '[]' - cfg = PCSConfig.new(text) - assert_equal(0, cfg.clusters.length) -- assert_equal( -+ assert_equal_json( - '{ - "format_version": 2, - "data_version": 0, -@@ -177,7 +185,7 @@ class TestConfig < Test::Unit::TestCase - assert_equal(1, cfg.clusters.length) - assert_equal("cluster71", cfg.clusters[0].name) - assert_equal(["rh71-node1", "rh71-node2"], cfg.clusters[0].nodes) -- assert_equal( -+ assert_equal_json( - '{ - "format_version": 2, - "data_version": 0, -@@ -218,7 +226,7 @@ class TestConfig < Test::Unit::TestCase - assert_equal(2, cfg.format_version) - assert_equal(0, cfg.data_version) - assert_equal(0, cfg.clusters.length) -- assert_equal(fixture_empty_config, cfg.text) -+ assert_equal_json(fixture_empty_config, cfg.text) - end - - def test_parse_format2_one_cluster() -@@ -247,7 +255,7 @@ class TestConfig < Test::Unit::TestCase - assert_equal(1, cfg.clusters.length) - assert_equal("cluster71", cfg.clusters[0].name) - assert_equal(["rh71-node1", "rh71-node2"], cfg.clusters[0].nodes) -- assert_equal(text, cfg.text) -+ assert_equal_json(text, cfg.text) - end - - def test_parse_format2_two_clusters() -@@ -318,7 +326,7 @@ class TestConfig < Test::Unit::TestCase - ] - } - }' -- assert_equal(out_text, cfg.text) -+ assert_equal_json(out_text, cfg.text) - end - - def test_parse_format2_bad_cluster() -@@ -347,7 +355,7 @@ class TestConfig < Test::Unit::TestCase - assert_equal(1, cfg.clusters.length) - assert_equal("cluster71", cfg.clusters[0].name) - assert_equal(["rh71-node1", "rh71-node2"], cfg.clusters[0].nodes) -- assert_equal( -+ assert_equal_json( - '{ - "format_version": 2, - "data_version": 9, -@@ -475,7 +483,7 @@ class TestConfig < Test::Unit::TestCase - } - }' - cfg = PCSConfig.new(text) -- assert_equal(out_text, cfg.text) -+ assert_equal_json(out_text, cfg.text) - - perms = cfg.permissions_local - assert_equal(false, perms.allows?('user1', [], Permissions::FULL)) -@@ -684,7 +692,7 @@ class TestCfgKnownHosts < Test::Unit::TestCase - assert_equal(1, cfg.format_version) - assert_equal(0, cfg.data_version) - assert_equal(0, cfg.known_hosts.length) -- assert_equal(fixture_empty_config(), cfg.text) -+ assert_equal_json(fixture_empty_config(), cfg.text) - end - - def assert_known_host(host, name, token, dest_list) -@@ -765,7 +773,7 @@ class TestCfgKnownHosts < Test::Unit::TestCase - ], - cfg.known_hosts['node1'].dest_list - ) -- assert_equal(text, cfg.text) -+ assert_equal_json(text, cfg.text) - end - - def test_parse_format1_complex() -@@ -825,7 +833,7 @@ class TestCfgKnownHosts < Test::Unit::TestCase - {'addr' => '10.0.2.2', 'port' => 2235} - ] - ) -- assert_equal(text, cfg.text) -+ assert_equal_json(text, cfg.text) - end - - def test_parse_format1_error() -@@ -888,7 +896,7 @@ class TestCfgKnownHosts < Test::Unit::TestCase - {'addr' => '10.0.1.3', 'port' => 2224} - ] - ) -- assert_equal( -+ assert_equal_json( - cfg.text, - '{ - "format_version": 1, --- -2.48.1 - diff --git a/show-info-page-instead-of-webui.patch b/show-info-page-instead-of-webui.patch index 3d8721f..9125cd1 100644 --- a/show-info-page-instead-of-webui.patch +++ b/show-info-page-instead-of-webui.patch @@ -1,7 +1,7 @@ -From a6b07bfb9d23462e856429ddc175e8588ad5aacb Mon Sep 17 00:00:00 2001 +From e7fa056f582c992d3d2b289911be20440fb839ac Mon Sep 17 00:00:00 2001 From: Ivan Devat Date: Tue, 5 Nov 2024 16:35:02 +0100 -Subject: [PATCH 1/3] show info page instead of webui +Subject: [PATCH 1/2] show info page instead of webui --- pcs/Makefile.am | 1 + @@ -13,10 +13,10 @@ Subject: [PATCH 1/3] show info page instead of webui create mode 100644 pcs/daemon/app/webui_info_handler.py diff --git a/pcs/Makefile.am b/pcs/Makefile.am -index 7a734dc15..45d5801fd 100644 +index 1297473ff..8d4b93073 100644 --- a/pcs/Makefile.am +++ b/pcs/Makefile.am -@@ -206,6 +206,7 @@ EXTRA_DIST = \ +@@ -219,6 +219,7 @@ EXTRA_DIST = \ daemon/app/webui/core.py \ daemon/app/webui/session.py \ daemon/app/webui/sinatra_ui.py \ @@ -62,18 +62,18 @@ index 000000000..3ab8275bf + (r"/ui/.*", _WebuiInfoHandler, dict(path=path)), + ] diff --git a/pcs/daemon/run.py b/pcs/daemon/run.py -index e0090fc1c..e80eecfec 100644 +index 558315c23..cfe9999fc 100644 --- a/pcs/daemon/run.py +++ b/pcs/daemon/run.py -@@ -35,6 +35,7 @@ from pcs.daemon.app import capabilities as capabilities_app - from pcs.daemon.app import ( +@@ -33,6 +33,7 @@ from pcs.daemon.app import ( + auth, sinatra_remote, sinatra_ui, + webui_info_handler, ) + from pcs.daemon.app import capabilities as capabilities_app - try: -@@ -142,7 +143,8 @@ def configure_app( +@@ -168,7 +169,8 @@ def configure_app( # noqa: PLR0913 # Even with disabled (standalone) webui the following routes must be # provided because they can be used via unix socket from cockpit. routes.extend( @@ -144,5 +144,5 @@ index a120ed3d4..b9c1c3152 100644 -- -2.48.1 +2.50.1 diff --git a/sources b/sources index c4e246f..c6784fc 100644 --- a/sources +++ b/sources @@ -1,5 +1,5 @@ SHA512 (pyagentx-0.4.pcs.2.tar.gz) = d4194fec9a3e5fefe3793d49b7fec1feafef294c7e613a06046c2993daeefc5cb39d7c5b2b402ff83e49b2d976953f862264288c758c0be09d997b5323cc558a -SHA512 (dacite-1.8.1.tar.gz) = 4b40c0bdcf5490bcc77de9e7f04b7267642bcfd41e4168607a5457f38abe3ad4b3041d8a23cb43af76de14eabee45f900ad5ddf7af8f70a2be4850bccc2d3af1 -SHA512 (pcs-0.12.0.tar.gz) = 7b4a1c7589fabe301f7ffd15a7f13954bfe958f3c02d90ae30a07afb50b8cabe8fafdc0dc62b10f0561a1a615157d4433f732245ccaca2003f9ce8c1a032439e -SHA512 (pcs-web-ui-0.1.22.tar.gz) = cb97ffba625326ab3857b9c22b4400907177a5ea88769ae611cc9315758c1ceca7e16a1b92d43fc594911fcde6003d3beadb388c6bdd5c1bcc67d699c49c9b2c -SHA512 (pcs-web-ui-node-modules-0.1.22.tar.xz) = b1db7d8c04e942baf8a99f115cbda31a84f562c7deeee5f1371e5ddf5fb5e73ce084ede1f0da7083b2d0114228f58006599f1b9a29dd3a5202b3119e41f74d69 +SHA512 (dacite-1.9.2.tar.gz) = 69513bc1acd43e45a208ce4b4186072f92d9057a6a88c77d56f21405fbed7964d94fe4f6a37c99754a793caa2bd0584664dfab69169ef0d3564bb09d37769e59 +SHA512 (pcs-0.12.1.tar.gz) = 4f17a8d9c15b8c9208c94a264f5f79f03abc451e3f4ae4ba0fb338055a26407d4961466dd8f3565f6882c2c00f1d6a1ec8fd15dadcb0cf1a5586d37c56c77238 +SHA512 (pcs-web-ui-0.1.23.tar.gz) = 6bc709926f26a02d33fb3865d15a1cf15db51a07dd9b25c63f33277c427c3403c189e2ac5e7adc795b254ad0bdb50f1bc4be70f1385bc8522ca502142d41fc26 +SHA512 (pcs-web-ui-node-modules-0.1.23.tar.xz) = f39dd1fd391f10b874b5fec34da1a2f2496d66b31af736ee1dfc2ef6e0b518efd03053fd00312c84e10a33ffda492e12d48a898a21efb6241e5459828e500e80 From 5830580f12e717de68581b50eca3c37f0398579f Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 25 Jul 2025 00:03:19 +0000 Subject: [PATCH 22/26] Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 04e5dd6..99e6c90 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.12.1 -Release: 1%{?dist} +Release: 2%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -551,6 +551,9 @@ fi %changelog +* Fri Jul 25 2025 Fedora Release Engineering - 0.12.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + * Fri Jul 18 2025 Michal Pospíšil - 0.12.1-1 - Rebased pcs to the newest major version (see CHANGELOG.md) Resolves: rhbz#2371770 From 096aab967fd057eee595319516871b334f5a33e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Wed, 30 Jul 2025 12:41:05 +0200 Subject: [PATCH 23/26] pcs-0.12.1-3 - Remove BuildRequires: python3-wheel when using setuptools 71+ --- do-not-require-wheel.patch | 63 ++++++++++++++++++++++++++++++++++++++ pcs.spec | 8 ++++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 do-not-require-wheel.patch diff --git a/do-not-require-wheel.patch b/do-not-require-wheel.patch new file mode 100644 index 0000000..2aab9ce --- /dev/null +++ b/do-not-require-wheel.patch @@ -0,0 +1,63 @@ +From 72588f150e89b6f06810321245a13157b7e00b09 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= +Date: Tue, 29 Jul 2025 23:42:00 +0200 +Subject: [PATCH] Do not require wheel when setuptools is new enough + +Current version of setuptools creates wheels on its own. +--- + README.md | 2 +- + configure.ac | 7 +++++-- + rpm/pcs.spec.in | 2 +- + 3 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/README.md b/README.md +index a06143eba..636485be6 100644 +--- a/README.md ++++ b/README.md +@@ -47,7 +47,7 @@ Apart from the dependencies listed above, these are also required for + installation: + + * python development files (packages python3-devel, python3-setuptools 66.1+, +- python3-pip, python3-wheel) ++ python3-pip, python3-wheel if python3-setuptools < 71) + * ruby development files (package ruby-devel) + * rubygems + * rubygem bundler (package rubygem-bundler or ruby-bundler or bundler) +diff --git a/configure.ac b/configure.ac +index 4e7d36599..0a782bfa7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -347,12 +347,15 @@ AC_SUBST([PYAGENTX_VERSION]) + + # pip 19.0 required for PEP517 support + PCS_CHECK_PYMOD([pip], [>= 23.0]) +-# pip builds a wheel first +-PCS_CHECK_PYMOD([wheel]) + + if test "x$tests_only" != "xyes"; then + # setuptools 61.0.0 required for PEP621 support + PCS_CHECK_PYMOD([setuptools], [>= 66.1]) ++ # wheel is required if setuptools < 71 ++ AC_PIP_MODULE([setuptools], [>= 71], [], [], [need_wheel=yes]) ++ if test "x$need_wheel" = "xyes"; then ++ PCS_CHECK_PYMOD([wheel]) ++ fi + PCS_CHECK_PYMOD([cryptography]) + PCS_CHECK_PYMOD([lxml]) + PCS_CHECK_PYMOD([pyparsing], [>= 3.0.0]) +diff --git a/rpm/pcs.spec.in b/rpm/pcs.spec.in +index 55881a398..639a3e974 100644 +--- a/rpm/pcs.spec.in ++++ b/rpm/pcs.spec.in +@@ -86,7 +86,7 @@ BuildRequires: python%{python3_version}-pip >= 23 + BuildRequires: python%{python3_version}-setuptools >= 66.1 + + # for building wheel during make install +-BuildRequires: python%{python3_version}-wheel ++BuildRequires: (python%{python3_version}-wheel if python%{python3_version}-setuptools < 71) + + # for bundling dateutil + %if "@cirpmworkarounds@" != "yes" +-- +2.50.1 + diff --git a/pcs.spec b/pcs.spec index 99e6c90..3e3ff3b 100644 --- a/pcs.spec +++ b/pcs.spec @@ -74,6 +74,7 @@ Source101: https://github.com/ClusterLabs/pcs-web-ui/releases/download/%{ui_vers # Patch1: name.patch Patch1: show-info-page-instead-of-webui.patch Patch2: fix-pcsd-not-starting-with-older-rack.patch +Patch3: do-not-require-wheel.patch # ui patches: >200 # Patch201: name-web-ui.patch @@ -111,7 +112,8 @@ BuildRequires: python3-tornado BuildRequires: python3-cryptography BuildRequires: python3-lxml # for building bundled python packages -BuildRequires: python3-wheel +# setuptools 71+ builds wheels by itself +BuildRequires: (python3-wheel if python3-setuptools < 71) # ruby and gems for pcsd BuildRequires: ruby >= 2.5.0 BuildRequires: ruby-devel @@ -338,6 +340,7 @@ update_times_patch(){ # update_times_patch %%{PATCH1} update_times_patch %{PATCH1} update_times_patch %{PATCH2} +update_times_patch %{PATCH3} # generate .tarball-version if building from an untagged commit, not a released version # autogen uses git-version-gen which uses .tarball-version for generating version number @@ -551,6 +554,9 @@ fi %changelog +* Wed Jul 30 2025 Michal Pospíšil - 0.12.1-3 +- Remove BuildRequires: python3-wheel when using setuptools 71+ + * Fri Jul 25 2025 Fedora Release Engineering - 0.12.1-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild From 2e5063b78abf3b6acc41428dbbb95a2f3111e74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Posp=C3=AD=C5=A1il?= Date: Wed, 30 Jul 2025 18:11:15 +0200 Subject: [PATCH 24/26] bump release Forgotten to bump release in previous commit (096aab9). --- pcs.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 3e3ff3b..69ba743 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.12.1 -Release: 2%{?dist} +Release: 3%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs From 267ae8ba0ca1fb829a6f4050ce96c597d0d2fcef Mon Sep 17 00:00:00 2001 From: Python Maint Date: Fri, 15 Aug 2025 13:05:31 +0200 Subject: [PATCH 25/26] Rebuilt for Python 3.14.0rc2 bytecode --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 69ba743..43caafe 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.12.1 -Release: 3%{?dist} +Release: 4%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -554,6 +554,9 @@ fi %changelog +* Fri Aug 15 2025 Python Maint - 0.12.1-4 +- Rebuilt for Python 3.14.0rc2 bytecode + * Wed Jul 30 2025 Michal Pospíšil - 0.12.1-3 - Remove BuildRequires: python3-wheel when using setuptools 71+ From 97846a528fa0e0e0c8c79df2eca2ffcd3f2414e3 Mon Sep 17 00:00:00 2001 From: Python Maint Date: Fri, 19 Sep 2025 12:36:02 +0200 Subject: [PATCH 26/26] Rebuilt for Python 3.14.0rc3 bytecode --- pcs.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pcs.spec b/pcs.spec index 43caafe..aa227b2 100644 --- a/pcs.spec +++ b/pcs.spec @@ -1,6 +1,6 @@ Name: pcs Version: 0.12.1 -Release: 4%{?dist} +Release: 5%{?dist} # https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ # https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses # GPL-2.0-only: pcs @@ -554,6 +554,9 @@ fi %changelog +* Fri Sep 19 2025 Python Maint - 0.12.1-5 +- Rebuilt for Python 3.14.0rc3 bytecode + * Fri Aug 15 2025 Python Maint - 0.12.1-4 - Rebuilt for Python 3.14.0rc2 bytecode