commit f4f4152567976841536b340d6dc826929356a056 Author: CentOS Sources Date: Tue Nov 15 01:25:52 2022 -0500 import pcs-0.11.3-4.el9 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..103ac1c --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +SOURCES/backports-3.23.0.gem +SOURCES/dacite-1.6.0.tar.gz +SOURCES/daemons-1.4.1.gem +SOURCES/ethon-0.15.0.gem +SOURCES/eventmachine-1.2.7.gem +SOURCES/ffi-1.15.5.gem +SOURCES/mustermann-1.1.1.gem +SOURCES/open4-1.3.4-1.gem +SOURCES/pcs-0.11.3.tar.gz +SOURCES/pcs-web-ui-0.1.14.tar.gz +SOURCES/pcs-web-ui-node-modules-0.1.14.tar.xz +SOURCES/pyagentx-0.4.pcs.2.tar.gz +SOURCES/rack-2.2.3.1.gem +SOURCES/rack-protection-2.2.0.gem +SOURCES/rack-test-1.1.0.gem +SOURCES/ruby2_keywords-0.0.5.gem +SOURCES/sinatra-2.2.0.gem +SOURCES/thin-1.8.1.gem +SOURCES/tilt-2.0.10.gem +SOURCES/tornado-6.1.0.tar.gz +SOURCES/webrick-1.7.0.gem diff --git a/.pcs.metadata b/.pcs.metadata new file mode 100644 index 0000000..1000040 --- /dev/null +++ b/.pcs.metadata @@ -0,0 +1,21 @@ +0e11246385a9e0a4bc122b74fb74fe536a234f81 SOURCES/backports-3.23.0.gem +31546c37fbdc6270d5097687619e9c0db6f1c05c SOURCES/dacite-1.6.0.tar.gz +4795a8962cc1608bfec0d91fa4d438c7cfe90c62 SOURCES/daemons-1.4.1.gem +29697a34b8cd9df4a77c650e2a38d0a36cdeee8b SOURCES/ethon-0.15.0.gem +7a5b2896e210fac9759c786ee4510f265f75b481 SOURCES/eventmachine-1.2.7.gem +97632b7975067266c0b39596de0a4c86d9330658 SOURCES/ffi-1.15.5.gem +50a4e37904485810cb05e27d75c9783e5a8f3402 SOURCES/mustermann-1.1.1.gem +41a7fe9f8e3e02da5ae76c821b89c5b376a97746 SOURCES/open4-1.3.4-1.gem +c16c4623928ba85b0b94b8cbdec6396be85d3672 SOURCES/pcs-0.11.3.tar.gz +4f518dcca24972f19d3e377931595602106f049d SOURCES/pcs-web-ui-0.1.14.tar.gz +b3e77ed1e3bb07b8e0ed34ae80fc88b9be0f49a4 SOURCES/pcs-web-ui-node-modules-0.1.14.tar.xz +3176b2f2b332c2b6bf79fe882e83feecf3d3f011 SOURCES/pyagentx-0.4.pcs.2.tar.gz +be609467c819d263c138c417548431b81f8da216 SOURCES/rack-2.2.3.1.gem +21cfac2453436c6856da31e741bbfa59da4973e1 SOURCES/rack-protection-2.2.0.gem +b80bc5ca38a885e747271675ba91dd3d02136bf1 SOURCES/rack-test-1.1.0.gem +d017b9e4d1978e0b3ccc3e2a31493809e4693cd3 SOURCES/ruby2_keywords-0.0.5.gem +5f0d7e63f9d8683f39ad23afe7e00b99602b87cc SOURCES/sinatra-2.2.0.gem +1ac6292a98e17247b7bb847a35ff868605256f7b SOURCES/thin-1.8.1.gem +d265c822a6b228392d899e9eb5114613d65e6967 SOURCES/tilt-2.0.10.gem +c23c617c7a0205e465bebad5b8cdf289ae8402a2 SOURCES/tornado-6.1.0.tar.gz +10ba51035928541b7713415f1f2e3a41114972fc SOURCES/webrick-1.7.0.gem diff --git a/SOURCES/bz2026725-01-booth-sync-check-whether-etc-booth-exists.patch b/SOURCES/bz2026725-01-booth-sync-check-whether-etc-booth-exists.patch new file mode 100644 index 0000000..1a8dc60 --- /dev/null +++ b/SOURCES/bz2026725-01-booth-sync-check-whether-etc-booth-exists.patch @@ -0,0 +1,46 @@ +From f863c38497eb716141c9e585ddb418191e9fc2a4 Mon Sep 17 00:00:00 2001 +From: Tomas Jelinek +Date: Fri, 15 Jul 2022 15:55:57 +0200 +Subject: [PATCH 3/3] booth sync: check whether /etc/booth exists + +--- + pcsd/pcsd_file.rb | 6 +----- + pcsd/remote.rb | 4 ++++ + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/pcsd/pcsd_file.rb b/pcsd/pcsd_file.rb +index d82b55d2..394db59a 100644 +--- a/pcsd/pcsd_file.rb ++++ b/pcsd/pcsd_file.rb +@@ -112,12 +112,8 @@ module PcsdFile + end + end + +- def dir() +- return BOOTH_CONFIG_DIR +- end +- + def full_file_name() +- @full_file_name ||= File.join(self.dir, @file[:name]) ++ @full_file_name ||= File.join(BOOTH_CONFIG_DIR, @file[:name]) + end + end + +diff --git a/pcsd/remote.rb b/pcsd/remote.rb +index 854674eb..144d25f3 100644 +--- a/pcsd/remote.rb ++++ b/pcsd/remote.rb +@@ -2090,6 +2090,10 @@ def booth_set_config(params, request, auth_user) + check_permissions(auth_user, Permissions::WRITE) + data = check_request_data_for_json(params, auth_user) + ++ if not File.directory?(BOOTH_CONFIG_DIR) ++ raise "Configuration directory for booth '/etc/booth' is missing. Is booth installed?" ++ end ++ + PcsdExchangeFormat::validate_item_map_is_Hash('files', data) + PcsdExchangeFormat::validate_item_is_Hash('file', :config, data[:config]) + if data[:authfile] +-- +2.35.3 + diff --git a/SOURCES/bz2058243-01-code-formatting.patch b/SOURCES/bz2058243-01-code-formatting.patch new file mode 100644 index 0000000..7868ae8 --- /dev/null +++ b/SOURCES/bz2058243-01-code-formatting.patch @@ -0,0 +1,2491 @@ +From 8859f3450df675579d24e4bd3d5e12aeefbaef54 Mon Sep 17 00:00:00 2001 +From: Tomas Jelinek +Date: Thu, 14 Jul 2022 16:22:39 +0200 +Subject: [PATCH 1/3] code formatting + +--- + pcs_test/tier0/lib/commands/test_booth.py | 1684 +++++++++------------ + 1 file changed, 723 insertions(+), 961 deletions(-) + +diff --git a/pcs_test/tier0/lib/commands/test_booth.py b/pcs_test/tier0/lib/commands/test_booth.py +index 6dc0cf3e..2b20a199 100644 +--- a/pcs_test/tier0/lib/commands/test_booth.py ++++ b/pcs_test/tier0/lib/commands/test_booth.py +@@ -211,22 +211,23 @@ class ConfigSetup(TestCase, FixtureMixin): + ) + ) + self.env_assist.assert_reports( +- [fixture.error(reports.codes.BOOTH_EVEN_PEERS_NUM, number=4)] ++ [ ++ fixture.error(reports.codes.BOOTH_EVEN_PEERS_NUM, number=4), ++ ] + ) + + def fixture_config_success(self, instance_name="booth"): +- ( +- self.config.raw_file.write( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(instance_name), +- RANDOM_KEY, +- name="raw_file.write.key", +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- self.fixture_cfg_content(self.fixture_key_path(instance_name)), +- name="raw_file.write.cfg", +- ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(instance_name), ++ RANDOM_KEY, ++ name="raw_file.write.key", ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ self.fixture_cfg_content(self.fixture_key_path(instance_name)), ++ name="raw_file.write.cfg", + ) + + def test_success_default_instance(self): +@@ -248,19 +249,18 @@ class ConfigSetup(TestCase, FixtureMixin): + ) + + def test_files_exist_config(self): +- ( +- self.config.raw_file.write( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(), +- RANDOM_KEY, +- name="raw_file.write.key", +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content(), +- already_exists=True, +- name="raw_file.write.cfg", +- ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(), ++ RANDOM_KEY, ++ name="raw_file.write.key", ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content(), ++ already_exists=True, ++ name="raw_file.write.cfg", + ) + + self.env_assist.assert_raise_library_error( +@@ -283,14 +283,12 @@ class ConfigSetup(TestCase, FixtureMixin): + ) + + def test_files_exist_key(self): +- ( +- self.config.raw_file.write( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(), +- RANDOM_KEY, +- already_exists=True, +- name="raw_file.write.key", +- ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(), ++ RANDOM_KEY, ++ already_exists=True, ++ name="raw_file.write.key", + ) + + self.env_assist.assert_raise_library_error( +@@ -313,20 +311,19 @@ class ConfigSetup(TestCase, FixtureMixin): + ) + + def test_files_exist_forced(self): +- ( +- self.config.raw_file.write( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(), +- RANDOM_KEY, +- can_overwrite=True, +- name="raw_file.write.key", +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content(), +- can_overwrite=True, +- name="raw_file.write.cfg", +- ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(), ++ RANDOM_KEY, ++ can_overwrite=True, ++ name="raw_file.write.key", ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content(), ++ can_overwrite=True, ++ name="raw_file.write.cfg", + ) + + commands.config_setup( +@@ -337,7 +334,6 @@ class ConfigSetup(TestCase, FixtureMixin): + ) + + def _assert_write_config_error(self, error, booth_dir_exists): +- + self.config.raw_file.write( + file_type_codes.BOOTH_KEY, + self.fixture_key_path(), +@@ -444,11 +440,7 @@ class ConfigSetup(TestCase, FixtureMixin): + ) + env = self.env_assist.get_env() + +- commands.config_setup( +- env, +- self.sites, +- self.arbitrators, +- ) ++ commands.config_setup(env, self.sites, self.arbitrators) + + self.assertEqual( + env.get_booth_env(name="").export(), +@@ -491,38 +483,34 @@ class ConfigDestroy(TestCase, FixtureMixin): + self.env_assist, self.config = get_env_tools(self) + + def fixture_config_booth_not_used(self, instance_name="booth"): +- ( +- self.config.runner.cib.load() +- .services.is_running( +- "booth", instance=instance_name, return_value=False +- ) +- .services.is_enabled( +- "booth", instance=instance_name, return_value=False +- ) ++ self.config.runner.cib.load() ++ self.config.services.is_running( ++ "booth", instance=instance_name, return_value=False ++ ) ++ self.config.services.is_enabled( ++ "booth", instance=instance_name, return_value=False + ) + + def fixture_config_success(self, instance_name="booth"): + self.fixture_config_booth_not_used(instance_name) +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- content=self.fixture_cfg_content( +- self.fixture_key_path(instance_name) +- ), +- ) +- .raw_file.remove( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(instance_name), +- fail_if_file_not_found=False, +- name="raw_file.remove.key", +- ) +- .raw_file.remove( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- fail_if_file_not_found=True, +- name="raw_file.remove.cfg", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ content=self.fixture_cfg_content( ++ self.fixture_key_path(instance_name) ++ ), ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(instance_name), ++ fail_if_file_not_found=False, ++ name="raw_file.remove.key", ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ fail_if_file_not_found=True, ++ name="raw_file.remove.cfg", + ) + + def test_invalid_instance(self): +@@ -540,9 +528,7 @@ class ConfigDestroy(TestCase, FixtureMixin): + + def test_success_default_instance(self): + self.fixture_config_success() +- commands.config_destroy( +- self.env_assist.get_env(), +- ) ++ commands.config_destroy(self.env_assist.get_env()) + + def test_success_custom_instance(self): + instance_name = "my_booth" +@@ -553,23 +539,20 @@ class ConfigDestroy(TestCase, FixtureMixin): + + def test_success_no_booth_key(self): + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=bytes(), +- ).raw_file.remove( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- fail_if_file_not_found=True, +- name="raw_file.remove.cfg", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=bytes(), + ) +- +- commands.config_destroy( +- self.env_assist.get_env(), ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ fail_if_file_not_found=True, ++ name="raw_file.remove.cfg", + ) + ++ commands.config_destroy(self.env_assist.get_env()) ++ + def test_not_live_booth(self): + self.config.env.set_booth( + { +@@ -603,9 +586,7 @@ class ConfigDestroy(TestCase, FixtureMixin): + [ + fixture.error( + reports.codes.LIVE_ENVIRONMENT_REQUIRED, +- forbidden_options=[ +- file_type_codes.CIB, +- ], ++ forbidden_options=[file_type_codes.CIB], + ), + ], + expected_in_processor=False, +@@ -640,20 +621,16 @@ class ConfigDestroy(TestCase, FixtureMixin): + def test_booth_config_in_use(self): + instance_name = "booth" + +- ( +- self.config.runner.cib.load(resources=self.fixture_cib_resources()) +- .services.is_running( +- "booth", instance=instance_name, return_value=True +- ) +- .services.is_enabled( +- "booth", instance=instance_name, return_value=True +- ) ++ self.config.runner.cib.load(resources=self.fixture_cib_resources()) ++ self.config.services.is_running( ++ "booth", instance=instance_name, return_value=True ++ ) ++ self.config.services.is_enabled( ++ "booth", instance=instance_name, return_value=True + ) + + self.env_assist.assert_raise_library_error( +- lambda: commands.config_destroy( +- self.env_assist.get_env(), +- ), ++ lambda: commands.config_destroy(self.env_assist.get_env()), + ) + + self.env_assist.assert_reports( +@@ -682,18 +659,14 @@ class ConfigDestroy(TestCase, FixtureMixin): + def test_cannot_read_config(self): + error = "an error" + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- exception_msg=error, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ exception_msg=error, + ) + + self.env_assist.assert_raise_library_error( +- lambda: commands.config_destroy( +- self.env_assist.get_env(), +- ), ++ lambda: commands.config_destroy(self.env_assist.get_env()), + ) + self.env_assist.assert_reports( + [ +@@ -711,17 +684,16 @@ class ConfigDestroy(TestCase, FixtureMixin): + def test_cannot_read_config_forced(self): + error = "an error" + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- exception_msg=error, +- ).raw_file.remove( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- fail_if_file_not_found=True, +- name="raw_file.remove.cfg", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ exception_msg=error, ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ fail_if_file_not_found=True, ++ name="raw_file.remove.cfg", + ) + + commands.config_destroy( +@@ -742,18 +714,14 @@ class ConfigDestroy(TestCase, FixtureMixin): + + def test_config_parse_error(self): + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content="invalid config".encode("utf-8"), +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content="invalid config".encode("utf-8"), + ) + + self.env_assist.assert_raise_library_error( +- lambda: commands.config_destroy( +- self.env_assist.get_env(), +- ), ++ lambda: commands.config_destroy(self.env_assist.get_env()), + ) + self.env_assist.assert_reports( + [ +@@ -768,17 +736,16 @@ class ConfigDestroy(TestCase, FixtureMixin): + + def test_config_parse_error_forced(self): + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content="invalid config".encode("utf-8"), +- ).raw_file.remove( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- fail_if_file_not_found=True, +- name="raw_file.remove.cfg", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content="invalid config".encode("utf-8"), ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ fail_if_file_not_found=True, ++ name="raw_file.remove.cfg", + ) + + commands.config_destroy( +@@ -797,52 +764,45 @@ class ConfigDestroy(TestCase, FixtureMixin): + + def test_key_already_deleted(self): + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ) +- .raw_file.remove( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(), +- fail_if_file_not_found=False, +- file_not_found_exception=True, +- name="raw_file.remove.key", +- ) +- .raw_file.remove( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- fail_if_file_not_found=True, +- name="raw_file.remove.cfg", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), + ) +- +- commands.config_destroy( +- self.env_assist.get_env(), ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(), ++ fail_if_file_not_found=False, ++ file_not_found_exception=True, ++ name="raw_file.remove.key", ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ fail_if_file_not_found=True, ++ name="raw_file.remove.cfg", + ) + ++ commands.config_destroy(self.env_assist.get_env()) ++ + def test_cannot_delete_key(self): + error = "an error" + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ).raw_file.remove( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(), +- fail_if_file_not_found=False, +- exception_msg=error, +- name="raw_file.remove.key", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(), ++ fail_if_file_not_found=False, ++ exception_msg=error, ++ name="raw_file.remove.key", + ) + + self.env_assist.assert_raise_library_error( +- lambda: commands.config_destroy( +- self.env_assist.get_env(), +- ), ++ lambda: commands.config_destroy(self.env_assist.get_env()), + ) + self.env_assist.assert_reports( + [ +@@ -860,25 +820,23 @@ class ConfigDestroy(TestCase, FixtureMixin): + def test_cannot_delete_key_forced(self): + error = "an error" + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ) +- .raw_file.remove( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(), +- fail_if_file_not_found=False, +- exception_msg=error, +- name="raw_file.remove.key", +- ) +- .raw_file.remove( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- fail_if_file_not_found=True, +- name="raw_file.remove.cfg", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(), ++ fail_if_file_not_found=False, ++ exception_msg=error, ++ name="raw_file.remove.key", ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ fail_if_file_not_found=True, ++ name="raw_file.remove.cfg", + ) + + commands.config_destroy( +@@ -900,31 +858,27 @@ class ConfigDestroy(TestCase, FixtureMixin): + def test_cannot_delete_config_forced(self): + error = "an error" + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ) +- .raw_file.remove( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(), +- fail_if_file_not_found=False, +- name="raw_file.remove.key", +- ) +- .raw_file.remove( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- fail_if_file_not_found=True, +- exception_msg=error, +- name="raw_file.remove.cfg", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(), ++ fail_if_file_not_found=False, ++ name="raw_file.remove.key", ++ ) ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ fail_if_file_not_found=True, ++ exception_msg=error, ++ name="raw_file.remove.cfg", + ) + + self.env_assist.assert_raise_library_error( +- lambda: commands.config_destroy( +- self.env_assist.get_env(), +- ), ++ lambda: commands.config_destroy(self.env_assist.get_env()), + ) + self.env_assist.assert_reports( + [ +@@ -941,22 +895,19 @@ class ConfigDestroy(TestCase, FixtureMixin): + def test_keyfile_outside_of_booth_dir(self): + key_path = "/tmp/pcs_test/booth.key" + self.fixture_config_booth_not_used() +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=f"authfile = {key_path}".encode("utf-8"), +- ).raw_file.remove( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- fail_if_file_not_found=True, +- name="raw_file.remove.cfg", +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=f"authfile = {key_path}".encode("utf-8"), + ) +- +- commands.config_destroy( +- self.env_assist.get_env(), ++ self.config.raw_file.remove( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ fail_if_file_not_found=True, ++ name="raw_file.remove.cfg", + ) ++ ++ commands.config_destroy(self.env_assist.get_env()) + self.env_assist.assert_reports( + [ + fixture.warn( +@@ -987,29 +938,23 @@ class ConfigText(TestCase, FixtureMixin): + + def test_success_default_instance(self): + config_content = "my config content".encode("utf-8") +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=config_content, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=config_content, + ) + self.assertEqual( +- commands.config_text( +- self.env_assist.get_env(), +- ), ++ commands.config_text(self.env_assist.get_env()), + config_content, + ) + + def test_success_custom_instance(self): + instance_name = "my_booth" + config_content = "my config content".encode("utf-8") +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- content=config_content, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ content=config_content, + ) + self.assertEqual( + commands.config_text( +@@ -1029,9 +974,7 @@ class ConfigText(TestCase, FixtureMixin): + } + ) + self.env_assist.assert_raise_library_error( +- lambda: commands.config_text( +- self.env_assist.get_env(), +- ), ++ lambda: commands.config_text(self.env_assist.get_env()), + [ + fixture.error( + reports.codes.LIVE_ENVIRONMENT_REQUIRED, +@@ -1046,17 +989,13 @@ class ConfigText(TestCase, FixtureMixin): + + def test_cannot_read_config(self): + error = "an error" +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- exception_msg=error, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ exception_msg=error, + ) + self.env_assist.assert_raise_library_error( +- lambda: commands.config_text( +- self.env_assist.get_env(), +- ), ++ lambda: commands.config_text(self.env_assist.get_env()), + ) + self.env_assist.assert_reports( + [ +@@ -1073,12 +1012,10 @@ class ConfigText(TestCase, FixtureMixin): + def test_remote_success(self): + instance_name = "my_booth" + config_content = "my config content" +- ( +- self.config.http.booth.get_config( +- instance_name, +- config_data=config_content, +- node_labels=["node1"], +- ) ++ self.config.http.booth.get_config( ++ instance_name, ++ config_data=config_content, ++ node_labels=["node1"], + ) + self.assertEqual( + commands.config_text( +@@ -1095,22 +1032,19 @@ class ConfigText(TestCase, FixtureMixin): + server_error = ( + "some error like 'config does not exist' or 'instance name invalid'" + ) +- ( +- self.config.http.booth.get_config( +- instance_name, +- communication_list=[ +- dict( +- label=node_name, +- response_code=400, +- output=server_error, +- ) +- ], +- ) ++ self.config.http.booth.get_config( ++ instance_name, ++ communication_list=[ ++ dict( ++ label=node_name, ++ response_code=400, ++ output=server_error, ++ ) ++ ], + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_text( +- self.env_assist.get_env(), +- node_name=node_name, ++ self.env_assist.get_env(), node_name=node_name + ), + ) + self.env_assist.assert_reports( +@@ -1127,21 +1061,18 @@ class ConfigText(TestCase, FixtureMixin): + def test_remote_bad_response(self): + instance_name = "booth" + node_name = "node1" +- ( +- self.config.http.booth.get_config( +- instance_name, +- communication_list=[ +- dict( +- label=node_name, +- output="not a json", +- ) +- ], +- ) ++ self.config.http.booth.get_config( ++ instance_name, ++ communication_list=[ ++ dict( ++ label=node_name, ++ output="not a json", ++ ) ++ ], + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_text( +- self.env_assist.get_env(), +- node_name=node_name, ++ self.env_assist.get_env(), node_name=node_name + ), + ) + self.env_assist.assert_reports( +@@ -1157,23 +1088,20 @@ class ConfigText(TestCase, FixtureMixin): + instance_name = "booth" + node_name = "node1" + error = "an error" +- ( +- self.config.http.booth.get_config( +- instance_name, +- communication_list=[ +- dict( +- label=node_name, +- was_connected=False, +- errno=1, +- error_msg=error, +- ) +- ], +- ) ++ self.config.http.booth.get_config( ++ instance_name, ++ communication_list=[ ++ dict( ++ label=node_name, ++ was_connected=False, ++ errno=1, ++ error_msg=error, ++ ) ++ ], + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_text( +- self.env_assist.get_env(), +- node_name=node_name, ++ self.env_assist.get_env(), node_name=node_name + ), + ) + self.env_assist.assert_reports( +@@ -1208,22 +1136,21 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + ) + + def fixture_config_success(self, instance_name="booth"): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- content=self.fixture_cfg_content( +- self.fixture_key_path(instance_name) +- ), +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- self.fixture_cfg_content( +- self.fixture_key_path(instance_name), +- ticket_list=[["ticketA", []]], +- ), +- can_overwrite=True, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ content=self.fixture_cfg_content( ++ self.fixture_key_path(instance_name) ++ ), ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ self.fixture_cfg_content( ++ self.fixture_key_path(instance_name), ++ ticket_list=[["ticketA", []]], ++ ), ++ can_overwrite=True, + ) + + def test_success_default_instance(self): +@@ -1268,21 +1195,20 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + ) + + def test_success_ticket_options(self): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content( +- ticket_list=[ +- ["ticketA", [("retries", "10"), ("timeout", "20")]] +- ] +- ), +- can_overwrite=True, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content( ++ ticket_list=[ ++ ["ticketA", [("retries", "10"), ("timeout", "20")]] ++ ] ++ ), ++ can_overwrite=True, + ) + commands.config_ticket_add( + self.env_assist.get_env(), +@@ -1291,12 +1217,10 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + ) + + def test_ticket_already_exists(self): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(ticket_list=[["ticketA", []]]), +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(ticket_list=[["ticketA", []]]), + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_add( +@@ -1316,12 +1240,10 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + ) + + def test_validator_errors(self): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_add( +@@ -1356,19 +1278,16 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + ) + + def test_invalid_ticket_options_forced(self): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content( +- ticket_list=[["ticketA", [("a", "A")]]] +- ), +- can_overwrite=True, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content(ticket_list=[["ticketA", [("a", "A")]]]), ++ can_overwrite=True, + ) + commands.config_ticket_add( + self.env_assist.get_env(), +@@ -1399,12 +1318,10 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + ) + + def test_config_parse_error(self): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content="invalid config".encode("utf-8"), +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content="invalid config".encode("utf-8"), + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_add( +@@ -1425,12 +1342,10 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + + def test_cannot_read_config(self): + error = "an error" +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- exception_msg=error, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ exception_msg=error, + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_add( +@@ -1480,18 +1395,17 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + + def test_cannot_write_config(self): + error = "an error" +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content(ticket_list=[["ticketA", []]]), +- can_overwrite=True, +- exception_msg=error, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content(ticket_list=[["ticketA", []]]), ++ can_overwrite=True, ++ exception_msg=error, + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_add( +@@ -1532,46 +1446,40 @@ class ConfigTicketRemove(TestCase, FixtureMixin): + ) + + def fixture_config_success(self, instance_name="booth"): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- self.fixture_cfg_content( +- self.fixture_key_path(instance_name), +- ticket_list=[ +- ["ticketA", []], +- ["ticketB", []], +- ["ticketC", []], +- ], +- ), +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- self.fixture_cfg_content( +- self.fixture_key_path(instance_name), +- ticket_list=[ +- ["ticketA", []], +- ["ticketC", []], +- ], +- ), +- can_overwrite=True, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ self.fixture_cfg_content( ++ self.fixture_key_path(instance_name), ++ ticket_list=[ ++ ["ticketA", []], ++ ["ticketB", []], ++ ["ticketC", []], ++ ], ++ ), ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ self.fixture_cfg_content( ++ self.fixture_key_path(instance_name), ++ ticket_list=[ ++ ["ticketA", []], ++ ["ticketC", []], ++ ], ++ ), ++ can_overwrite=True, + ) + + def test_success_default_instance(self): + self.fixture_config_success() +- commands.config_ticket_remove( +- self.env_assist.get_env(), +- "ticketB", +- ) ++ commands.config_ticket_remove(self.env_assist.get_env(), "ticketB") + + def test_success_custom_instance(self): + instance_name = "my_booth" + self.fixture_config_success(instance_name=instance_name) + commands.config_ticket_remove( +- self.env_assist.get_env(), +- "ticketB", +- instance_name=instance_name, ++ self.env_assist.get_env(), "ticketB", instance_name=instance_name + ) + + def test_success_not_live(self): +@@ -1602,51 +1510,44 @@ class ConfigTicketRemove(TestCase, FixtureMixin): + ) + + def test_success_ticket_options(self): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content( +- ticket_list=[ +- ["ticketA", [("a1", "A1"), ("a2", "A2")]], +- ["ticketB", [("b1", "B1"), ("b2", "B2")]], +- ["ticketC", [("c1", "C1"), ("c2", "C2")]], +- ] +- ), +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content( +- ticket_list=[ +- ["ticketA", [("a1", "A1"), ("a2", "A2")]], +- ["ticketC", [("c1", "C1"), ("c2", "C2")]], +- ] +- ), +- can_overwrite=True, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content( ++ ticket_list=[ ++ ["ticketA", [("a1", "A1"), ("a2", "A2")]], ++ ["ticketB", [("b1", "B1"), ("b2", "B2")]], ++ ["ticketC", [("c1", "C1"), ("c2", "C2")]], ++ ] ++ ), + ) +- commands.config_ticket_remove( +- self.env_assist.get_env(), +- "ticketB", ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content( ++ ticket_list=[ ++ ["ticketA", [("a1", "A1"), ("a2", "A2")]], ++ ["ticketC", [("c1", "C1"), ("c2", "C2")]], ++ ] ++ ), ++ can_overwrite=True, + ) ++ commands.config_ticket_remove(self.env_assist.get_env(), "ticketB") + + def test_ticket_does_not_exist(self): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content( +- ticket_list=[ +- ["ticketA", []], +- ["ticketC", []], +- ] +- ), +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content( ++ ticket_list=[ ++ ["ticketA", []], ++ ["ticketC", []], ++ ] ++ ), + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_remove( +- self.env_assist.get_env(), +- "ticketB", ++ self.env_assist.get_env(), "ticketB" + ) + ) + self.env_assist.assert_reports( +@@ -1659,17 +1560,14 @@ class ConfigTicketRemove(TestCase, FixtureMixin): + ) + + def test_config_parse_error(self): +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content="invalid config".encode("utf-8"), +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content="invalid config".encode("utf-8"), + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_remove( +- self.env_assist.get_env(), +- "ticketB", ++ self.env_assist.get_env(), "ticketB" + ) + ) + self.env_assist.assert_reports( +@@ -1684,17 +1582,14 @@ class ConfigTicketRemove(TestCase, FixtureMixin): + + def test_cannot_read_config(self): + error = "an error" +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- exception_msg=error, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ exception_msg=error, + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_remove( +- self.env_assist.get_env(), +- "ticketB", ++ self.env_assist.get_env(), "ticketB" + ) + ) + self.env_assist.assert_reports( +@@ -1719,8 +1614,7 @@ class ConfigTicketRemove(TestCase, FixtureMixin): + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_remove( +- self.env_assist.get_env(), +- "ticketB", ++ self.env_assist.get_env(), "ticketB" + ) + ) + self.env_assist.assert_reports( +@@ -1737,27 +1631,25 @@ class ConfigTicketRemove(TestCase, FixtureMixin): + + def test_cannot_write_config(self): + error = "an error" +- ( +- self.config.raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content( +- ticket_list=[ +- ["ticketB", []], +- ] +- ), +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- self.fixture_cfg_content(), +- can_overwrite=True, +- exception_msg=error, +- ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content( ++ ticket_list=[ ++ ["ticketB", []], ++ ] ++ ), ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ self.fixture_cfg_content(), ++ can_overwrite=True, ++ exception_msg=error, + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_ticket_remove( +- self.env_assist.get_env(), +- "ticketB", ++ self.env_assist.get_env(), "ticketB" + ) + ) + self.env_assist.assert_reports( +@@ -1792,40 +1684,35 @@ class CreateInCluster(TestCase, FixtureMixin): + ) + + def fixture_config_success(self, instance_name="booth"): +- ( +- self.config.runner.cib.load() +- .raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- content=self.fixture_cfg_content( +- self.fixture_key_path(instance_name) +- ), +- ) +- .runner.pcmk.load_agent( +- agent_name="ocf:heartbeat:IPaddr2", +- name="runner.pcmk.load_agent.ipaddr2", +- ) +- .runner.pcmk.load_agent( +- agent_name="ocf:pacemaker:booth-site", +- name="runner.pcmk.load_agent.booth-site", +- ) +- .env.push_cib(resources=self.fixture_cib_booth_group(instance_name)) ++ self.config.runner.cib.load() ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ content=self.fixture_cfg_content( ++ self.fixture_key_path(instance_name) ++ ), ++ ) ++ self.config.runner.pcmk.load_agent( ++ agent_name="ocf:heartbeat:IPaddr2", ++ name="runner.pcmk.load_agent.ipaddr2", ++ ) ++ self.config.runner.pcmk.load_agent( ++ agent_name="ocf:pacemaker:booth-site", ++ name="runner.pcmk.load_agent.booth-site", ++ ) ++ self.config.env.push_cib( ++ resources=self.fixture_cib_booth_group(instance_name) + ) + + def test_success_default_instance(self): + self.fixture_config_success() +- commands.create_in_cluster( +- self.env_assist.get_env(), +- self.site_ip, +- ) ++ commands.create_in_cluster(self.env_assist.get_env(), self.site_ip) + + def test_success_custom_instance(self): + instance_name = "my_booth" + self.fixture_config_success(instance_name=instance_name) + commands.create_in_cluster( +- self.env_assist.get_env(), +- self.site_ip, +- instance_name=instance_name, ++ self.env_assist.get_env(), self.site_ip, instance_name=instance_name + ) + + def test_success_not_live_cib(self): +@@ -1833,29 +1720,24 @@ class CreateInCluster(TestCase, FixtureMixin): + env = dict(CIB_file=tmp_file) + with open(rc("cib-empty.xml")) as cib_file: + self.config.env.set_cib_data(cib_file.read(), cib_tempfile=tmp_file) +- ( +- self.config.runner.cib.load(env=env) +- .raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ) +- .runner.pcmk.load_agent( +- agent_name="ocf:heartbeat:IPaddr2", +- name="runner.pcmk.load_agent.ipaddr2", +- env=env, +- ) +- .runner.pcmk.load_agent( +- agent_name="ocf:pacemaker:booth-site", +- name="runner.pcmk.load_agent.booth-site", +- env=env, +- ) +- .env.push_cib(resources=self.fixture_cib_booth_group()) ++ self.config.runner.cib.load(env=env) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), + ) +- commands.create_in_cluster( +- self.env_assist.get_env(), +- self.site_ip, ++ self.config.runner.pcmk.load_agent( ++ agent_name="ocf:heartbeat:IPaddr2", ++ name="runner.pcmk.load_agent.ipaddr2", ++ env=env, + ) ++ self.config.runner.pcmk.load_agent( ++ agent_name="ocf:pacemaker:booth-site", ++ name="runner.pcmk.load_agent.booth-site", ++ env=env, ++ ) ++ self.config.env.push_cib(resources=self.fixture_cib_booth_group()) ++ commands.create_in_cluster(self.env_assist.get_env(), self.site_ip) + + def test_not_live_booth(self): + self.config.env.set_booth( +@@ -1867,8 +1749,7 @@ class CreateInCluster(TestCase, FixtureMixin): + ) + self.env_assist.assert_raise_library_error( + lambda: commands.create_in_cluster( +- self.env_assist.get_env(), +- self.site_ip, ++ self.env_assist.get_env(), self.site_ip + ), + [ + fixture.error( +@@ -1883,19 +1764,15 @@ class CreateInCluster(TestCase, FixtureMixin): + ) + + def test_booth_resource_already_created(self): +- ( +- self.config.runner.cib.load( +- resources=self.fixture_cib_booth_group() +- ).raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ) ++ self.config.runner.cib.load(resources=self.fixture_cib_booth_group()) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), + ) + self.env_assist.assert_raise_library_error( + lambda: commands.create_in_cluster( +- self.env_assist.get_env(), +- self.site_ip, ++ self.env_assist.get_env(), self.site_ip + ) + ) + self.env_assist.assert_reports( +@@ -1904,17 +1781,14 @@ class CreateInCluster(TestCase, FixtureMixin): + + def test_booth_config_does_not_exist(self): + error = "an error" +- ( +- self.config.runner.cib.load().raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- exception_msg=error, +- ) ++ self.config.runner.cib.load().raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ exception_msg=error, + ) + self.env_assist.assert_raise_library_error( + lambda: commands.create_in_cluster( +- self.env_assist.get_env(), +- self.site_ip, ++ self.env_assist.get_env(), self.site_ip + ) + ) + self.env_assist.assert_reports( +@@ -1959,28 +1833,25 @@ class CreateInCluster(TestCase, FixtureMixin): + ) + + def test_booth_agent_missing(self): +- ( +- self.config.runner.cib.load() +- .raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ) +- .runner.pcmk.load_agent( +- agent_name="ocf:heartbeat:IPaddr2", +- name="runner.pcmk.load_agent.ipaddr2", +- ) +- .runner.pcmk.load_agent( +- agent_name="ocf:pacemaker:booth-site", +- agent_is_missing=True, +- name="runner.pcmk.load_agent.booth-site", +- stderr=REASON, +- ) ++ self.config.runner.cib.load() ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ ) ++ self.config.runner.pcmk.load_agent( ++ agent_name="ocf:heartbeat:IPaddr2", ++ name="runner.pcmk.load_agent.ipaddr2", ++ ) ++ self.config.runner.pcmk.load_agent( ++ agent_name="ocf:pacemaker:booth-site", ++ agent_is_missing=True, ++ name="runner.pcmk.load_agent.booth-site", ++ stderr=REASON, + ) + self.env_assist.assert_raise_library_error( + lambda: commands.create_in_cluster( +- self.env_assist.get_env(), +- self.site_ip, ++ self.env_assist.get_env(), self.site_ip + ) + ) + self.env_assist.assert_reports( +@@ -1993,30 +1864,28 @@ class CreateInCluster(TestCase, FixtureMixin): + ), + ] + ) +- +- def test_agents_missing_forced(self): +- ( +- self.config.runner.cib.load() +- .raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- ) +- .runner.pcmk.load_agent( +- agent_name="ocf:heartbeat:IPaddr2", +- agent_is_missing=True, +- name="runner.pcmk.load_agent.ipaddr2", +- stderr=REASON, +- ) +- .runner.pcmk.load_agent( +- agent_name="ocf:pacemaker:booth-site", +- agent_is_missing=True, +- name="runner.pcmk.load_agent.booth-site", +- stderr=REASON, +- ) +- .env.push_cib( +- resources=self.fixture_cib_booth_group(default_operations=True) +- ) ++ ++ def test_agents_missing_forced(self): ++ self.config.runner.cib.load() ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ ) ++ self.config.runner.pcmk.load_agent( ++ agent_name="ocf:heartbeat:IPaddr2", ++ agent_is_missing=True, ++ name="runner.pcmk.load_agent.ipaddr2", ++ stderr=REASON, ++ ) ++ self.config.runner.pcmk.load_agent( ++ agent_name="ocf:pacemaker:booth-site", ++ agent_is_missing=True, ++ name="runner.pcmk.load_agent.booth-site", ++ stderr=REASON, ++ ) ++ self.config.env.push_cib( ++ resources=self.fixture_cib_booth_group(default_operations=True) + ) + commands.create_in_cluster( + self.env_assist.get_env(), +@@ -2061,10 +1930,9 @@ class RemoveFromCluster(TestCase, FixtureMixin): + self.resource_remove.assert_not_called() + + def test_success_default_instance(self): +- (self.config.runner.cib.load(resources=self.fixture_cib_booth_group())) ++ self.config.runner.cib.load(resources=self.fixture_cib_booth_group()) + commands.remove_from_cluster( +- self.env_assist.get_env(), +- self.resource_remove, ++ self.env_assist.get_env(), self.resource_remove + ) + self.resource_remove.assert_has_calls( + [ +@@ -2075,10 +1943,8 @@ class RemoveFromCluster(TestCase, FixtureMixin): + + def test_success_custom_instance(self): + instance_name = "my_booth" +- ( +- self.config.runner.cib.load( +- resources=self.fixture_cib_booth_group(instance_name) +- ) ++ self.config.runner.cib.load( ++ resources=self.fixture_cib_booth_group(instance_name) + ) + commands.remove_from_cluster( + self.env_assist.get_env(), +@@ -2099,16 +1965,12 @@ class RemoveFromCluster(TestCase, FixtureMixin): + cib_xml_man.append_to_first_tag_name( + "resources", self.fixture_cib_booth_group(wrap_in_resources=False) + ) +- ( +- self.config +- # This makes env.is_cib_live return False +- .env.set_cib_data(str(cib_xml_man), cib_tempfile=tmp_file) +- # This instructs the runner to actually return our mocked cib +- .runner.cib.load_content(str(cib_xml_man), env=env) +- ) ++ # This makes env.is_cib_live return False ++ self.config.env.set_cib_data(str(cib_xml_man), cib_tempfile=tmp_file) ++ # This instructs the runner to actually return our mocked cib ++ self.config.runner.cib.load_content(str(cib_xml_man), env=env) + commands.remove_from_cluster( +- self.env_assist.get_env(), +- self.resource_remove, ++ self.env_assist.get_env(), self.resource_remove + ) + self.resource_remove.assert_has_calls( + [ +@@ -2127,8 +1989,7 @@ class RemoveFromCluster(TestCase, FixtureMixin): + ) + self.env_assist.assert_raise_library_error( + lambda: commands.remove_from_cluster( +- self.env_assist.get_env(), +- self.resource_remove, ++ self.env_assist.get_env(), self.resource_remove + ), + [ + fixture.error( +@@ -2147,8 +2008,7 @@ class RemoveFromCluster(TestCase, FixtureMixin): + (self.config.runner.cib.load()) + self.env_assist.assert_raise_library_error( + lambda: commands.remove_from_cluster( +- self.env_assist.get_env(), +- self.resource_remove, ++ self.env_assist.get_env(), self.resource_remove + ), + ) + self.env_assist.assert_reports( +@@ -2162,15 +2022,10 @@ class RemoveFromCluster(TestCase, FixtureMixin): + self.resource_remove.assert_not_called() + + def test_more_booth_resources(self): +- ( +- self.config.runner.cib.load( +- resources=self.fixture_cib_more_resources() +- ) +- ) ++ self.config.runner.cib.load(resources=self.fixture_cib_more_resources()) + self.env_assist.assert_raise_library_error( + lambda: commands.remove_from_cluster( +- self.env_assist.get_env(), +- self.resource_remove, ++ self.env_assist.get_env(), self.resource_remove + ), + ) + self.env_assist.assert_reports( +@@ -2185,11 +2040,7 @@ class RemoveFromCluster(TestCase, FixtureMixin): + self.resource_remove.assert_not_called() + + def test_more_booth_resources_forced(self): +- ( +- self.config.runner.cib.load( +- resources=self.fixture_cib_more_resources() +- ) +- ) ++ self.config.runner.cib.load(resources=self.fixture_cib_more_resources()) + commands.remove_from_cluster( + self.env_assist.get_env(), + self.resource_remove, +@@ -2234,11 +2085,8 @@ class Restart(TestCase, FixtureMixin): + self.resource_restart.assert_not_called() + + def test_success_default_instance(self): +- (self.config.runner.cib.load(resources=self.fixture_cib_booth_group())) +- commands.restart( +- self.env_assist.get_env(), +- self.resource_restart, +- ) ++ self.config.runner.cib.load(resources=self.fixture_cib_booth_group()) ++ commands.restart(self.env_assist.get_env(), self.resource_restart) + self.resource_restart.assert_has_calls( + [ + mock.call(["booth-booth-service"]), +@@ -2247,10 +2095,8 @@ class Restart(TestCase, FixtureMixin): + + def test_success_custom_instance(self): + instance_name = "my_booth" +- ( +- self.config.runner.cib.load( +- resources=self.fixture_cib_booth_group(instance_name) +- ) ++ self.config.runner.cib.load( ++ resources=self.fixture_cib_booth_group(instance_name) + ) + commands.restart( + self.env_assist.get_env(), +@@ -2274,8 +2120,7 @@ class Restart(TestCase, FixtureMixin): + self.config.env.set_cib_data("") + self.env_assist.assert_raise_library_error( + lambda: commands.restart( +- self.env_assist.get_env(), +- self.resource_restart, ++ self.env_assist.get_env(), self.resource_restart + ), + [ + fixture.error( +@@ -2295,8 +2140,7 @@ class Restart(TestCase, FixtureMixin): + (self.config.runner.cib.load()) + self.env_assist.assert_raise_library_error( + lambda: commands.restart( +- self.env_assist.get_env(), +- self.resource_restart, ++ self.env_assist.get_env(), self.resource_restart + ), + ) + self.env_assist.assert_reports( +@@ -2310,15 +2154,10 @@ class Restart(TestCase, FixtureMixin): + self.resource_restart.assert_not_called() + + def test_more_booth_resources(self): +- ( +- self.config.runner.cib.load( +- resources=self.fixture_cib_more_resources() +- ) +- ) ++ self.config.runner.cib.load(resources=self.fixture_cib_more_resources()) + self.env_assist.assert_raise_library_error( + lambda: commands.restart( +- self.env_assist.get_env(), +- self.resource_restart, ++ self.env_assist.get_env(), self.resource_restart + ), + ) + self.env_assist.assert_reports( +@@ -2333,11 +2172,7 @@ class Restart(TestCase, FixtureMixin): + self.resource_restart.assert_not_called() + + def test_more_booth_resources_forced(self): +- ( +- self.config.runner.cib.load( +- resources=self.fixture_cib_more_resources() +- ) +- ) ++ self.config.runner.cib.load(resources=self.fixture_cib_more_resources()) + commands.restart( + self.env_assist.get_env(), + self.resource_restart, +@@ -2390,10 +2225,7 @@ class TicketGrantRevokeMixin(FixtureMixin): + ) + self.config.env.set_cib_data("") + self.env_assist.assert_raise_library_error( +- lambda: self.command( +- self.env_assist.get_env(), +- self.ticket, +- ), ++ lambda: self.command(self.env_assist.get_env(), self.ticket), + [ + fixture.error( + reports.codes.LIVE_ENVIRONMENT_REQUIRED, +@@ -2410,26 +2242,18 @@ class TicketGrantRevokeMixin(FixtureMixin): + def test_success_site_ip_specified(self): + self.get_booth_call()(self.ticket, self.site_ip) + self.command( +- self.env_assist.get_env(), +- self.ticket, +- site_ip=self.site_ip, ++ self.env_assist.get_env(), self.ticket, site_ip=self.site_ip + ) + + def test_success_site_ip_not_specified(self): + self.config.runner.cib.load(resources=self.fixture_cib_booth_group()) + self.get_booth_call()(self.ticket, self.site_ip) +- self.command( +- self.env_assist.get_env(), +- self.ticket, +- ) ++ self.command(self.env_assist.get_env(), self.ticket) + + def test_cannot_find_site_ip(self): + self.config.runner.cib.load() + self.env_assist.assert_raise_library_error( +- lambda: self.command( +- self.env_assist.get_env(), +- self.ticket, +- ), ++ lambda: self.command(self.env_assist.get_env(), self.ticket), + [ + fixture.error( + reports.codes.BOOTH_CANNOT_DETERMINE_LOCAL_SITE_IP, +@@ -2448,9 +2272,7 @@ class TicketGrantRevokeMixin(FixtureMixin): + ) + self.env_assist.assert_raise_library_error( + lambda: self.command( +- self.env_assist.get_env(), +- self.ticket, +- site_ip=self.site_ip, ++ self.env_assist.get_env(), self.ticket, site_ip=self.site_ip + ), + [ + fixture.error( +@@ -2496,34 +2318,30 @@ class ConfigSyncTest(TestCase, FixtureMixin): + self.fixture_key_path(instance_name) + ) + self.fixture_config_read_success(instance_name=instance_name) +- ( +- self.config.http.booth.send_config( +- instance_name, +- config_content.decode("utf-8"), +- authfile=os.path.basename(self.fixture_key_path(instance_name)), +- authfile_data=RANDOM_KEY, +- node_labels=self.node_list, +- ) ++ self.config.http.booth.send_config( ++ instance_name, ++ config_content.decode("utf-8"), ++ authfile=os.path.basename(self.fixture_key_path(instance_name)), ++ authfile_data=RANDOM_KEY, ++ node_labels=self.node_list, + ) + + def fixture_config_read_success(self, instance_name="booth"): + config_content = self.fixture_cfg_content( + self.fixture_key_path(instance_name) + ) +- ( +- self.config.corosync_conf.load() +- .raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(instance_name), +- content=config_content, +- name="raw_file.read.conf", +- ) +- .raw_file.read( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(instance_name), +- content=RANDOM_KEY, +- name="raw_file.read.key", +- ) ++ self.config.corosync_conf.load() ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(instance_name), ++ content=config_content, ++ name="raw_file.read.conf", ++ ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(instance_name), ++ content=RANDOM_KEY, ++ name="raw_file.read.key", + ) + + def fixture_reports_success(self, instance_name="booth"): +@@ -2552,30 +2370,23 @@ class ConfigSyncTest(TestCase, FixtureMixin): + + def test_success_default_instance(self): + self.fixture_config_success() +- commands.config_sync( +- self.env_assist.get_env(), +- ) ++ commands.config_sync(self.env_assist.get_env()) + self.env_assist.assert_reports(self.fixture_reports_success()) + + def test_success_custom_instance(self): + instance_name = "my_booth" + self.fixture_config_success(instance_name=instance_name) + commands.config_sync( +- self.env_assist.get_env(), +- instance_name=instance_name, ++ self.env_assist.get_env(), instance_name=instance_name + ) + self.env_assist.assert_reports( +- self.fixture_reports_success( +- instance_name=instance_name, +- ) ++ self.fixture_reports_success(instance_name=instance_name) + ) + + def test_not_live_cib(self): + self.config.env.set_cib_data("") + self.env_assist.assert_raise_library_error( +- lambda: commands.config_sync( +- self.env_assist.get_env(), +- ), ++ lambda: commands.config_sync(self.env_assist.get_env()), + [ + fixture.error( + reports.codes.LIVE_ENVIRONMENT_REQUIRED, +@@ -2596,56 +2407,45 @@ class ConfigSyncTest(TestCase, FixtureMixin): + "key_path": "some key path", + } + ) +- ( +- self.config.corosync_conf.load( +- node_name_list=self.node_list +- ).http.booth.send_config( +- instance_name, +- config_data.decode("utf-8"), +- authfile=os.path.basename(key_path), +- authfile_data=key_data, +- node_labels=self.node_list, +- ) ++ self.config.corosync_conf.load(node_name_list=self.node_list) ++ self.config.http.booth.send_config( ++ instance_name, ++ config_data.decode("utf-8"), ++ authfile=os.path.basename(key_path), ++ authfile_data=key_data, ++ node_labels=self.node_list, + ) + + def test_not_live_booth_default_instance(self): + self.fixture_config_success_not_live() +- commands.config_sync( +- self.env_assist.get_env(), +- ) ++ commands.config_sync(self.env_assist.get_env()) + self.env_assist.assert_reports(self.fixture_reports_success()) + + def test_not_live_booth_custom_instance(self): + instance_name = "my_booth" + self.fixture_config_success_not_live(instance_name=instance_name) + commands.config_sync( +- self.env_assist.get_env(), +- instance_name=instance_name, ++ self.env_assist.get_env(), instance_name=instance_name + ) + self.env_assist.assert_reports( +- self.fixture_reports_success( +- instance_name=instance_name, +- ) ++ self.fixture_reports_success(instance_name=instance_name) + ) + + def test_some_node_names_missing(self): + nodes = ["rh7-2"] + self.fixture_config_read_success() +- ( +- self.config.corosync_conf.load( +- filename="corosync-some-node-names.conf", +- instead="corosync_conf.load", +- ).http.booth.send_config( +- "booth", +- self.fixture_cfg_content().decode("utf-8"), +- authfile=os.path.basename(self.fixture_key_path()), +- authfile_data=RANDOM_KEY, +- node_labels=nodes, +- ) ++ self.config.corosync_conf.load( ++ filename="corosync-some-node-names.conf", ++ instead="corosync_conf.load", + ) +- commands.config_sync( +- self.env_assist.get_env(), ++ self.config.http.booth.send_config( ++ "booth", ++ self.fixture_cfg_content().decode("utf-8"), ++ authfile=os.path.basename(self.fixture_key_path()), ++ authfile_data=RANDOM_KEY, ++ node_labels=nodes, + ) ++ commands.config_sync(self.env_assist.get_env()) + self.env_assist.assert_reports( + [ + fixture.info(reports.codes.BOOTH_CONFIG_DISTRIBUTION_STARTED), +@@ -2666,11 +2466,9 @@ class ConfigSyncTest(TestCase, FixtureMixin): + + def test_all_node_names_missing(self): + self.fixture_config_read_success() +- ( +- self.config.corosync_conf.load( +- filename="corosync-no-node-names.conf", +- instead="corosync_conf.load", +- ) ++ self.config.corosync_conf.load( ++ filename="corosync-no-node-names.conf", ++ instead="corosync_conf.load", + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_sync(self.env_assist.get_env()) +@@ -2687,23 +2485,21 @@ class ConfigSyncTest(TestCase, FixtureMixin): + + def test_node_failure(self): + self.fixture_config_read_success() +- ( +- self.config.http.booth.send_config( +- "booth", +- self.fixture_cfg_content().decode("utf-8"), +- authfile=os.path.basename(self.fixture_key_path()), +- authfile_data=RANDOM_KEY, +- communication_list=[ +- dict( +- label=self.node_list[0], +- response_code=400, +- output=self.reason, +- ), +- dict( +- label=self.node_list[1], +- ), +- ], +- ) ++ self.config.http.booth.send_config( ++ "booth", ++ self.fixture_cfg_content().decode("utf-8"), ++ authfile=os.path.basename(self.fixture_key_path()), ++ authfile_data=RANDOM_KEY, ++ communication_list=[ ++ dict( ++ label=self.node_list[0], ++ response_code=400, ++ output=self.reason, ++ ), ++ dict( ++ label=self.node_list[1], ++ ), ++ ], + ) + self.env_assist.assert_raise_library_error( + lambda: commands.config_sync(self.env_assist.get_env()), [] +@@ -2728,23 +2524,21 @@ class ConfigSyncTest(TestCase, FixtureMixin): + + def test_node_failure_skip_offline(self): + self.fixture_config_read_success() +- ( +- self.config.http.booth.send_config( +- "booth", +- self.fixture_cfg_content().decode("utf-8"), +- authfile=os.path.basename(self.fixture_key_path()), +- authfile_data=RANDOM_KEY, +- communication_list=[ +- dict( +- label=self.node_list[0], +- response_code=400, +- output=self.reason, +- ), +- dict( +- label=self.node_list[1], +- ), +- ], +- ) ++ self.config.http.booth.send_config( ++ "booth", ++ self.fixture_cfg_content().decode("utf-8"), ++ authfile=os.path.basename(self.fixture_key_path()), ++ authfile_data=RANDOM_KEY, ++ communication_list=[ ++ dict( ++ label=self.node_list[0], ++ response_code=400, ++ output=self.reason, ++ ), ++ dict( ++ label=self.node_list[1], ++ ), ++ ], + ) + + commands.config_sync(self.env_assist.get_env(), skip_offline_nodes=True) +@@ -2767,24 +2561,22 @@ class ConfigSyncTest(TestCase, FixtureMixin): + + def test_node_offline(self): + self.fixture_config_read_success() +- ( +- self.config.http.booth.send_config( +- "booth", +- self.fixture_cfg_content().decode("utf-8"), +- authfile=os.path.basename(self.fixture_key_path()), +- authfile_data=RANDOM_KEY, +- communication_list=[ +- dict( +- label=self.node_list[0], +- errno=1, +- error_msg=self.reason, +- was_connected=False, +- ), +- dict( +- label=self.node_list[1], +- ), +- ], +- ) ++ self.config.http.booth.send_config( ++ "booth", ++ self.fixture_cfg_content().decode("utf-8"), ++ authfile=os.path.basename(self.fixture_key_path()), ++ authfile_data=RANDOM_KEY, ++ communication_list=[ ++ dict( ++ label=self.node_list[0], ++ errno=1, ++ error_msg=self.reason, ++ was_connected=False, ++ ), ++ dict( ++ label=self.node_list[1], ++ ), ++ ], + ) + + self.env_assist.assert_raise_library_error( +@@ -2810,24 +2602,22 @@ class ConfigSyncTest(TestCase, FixtureMixin): + + def test_node_offline_skip_offline(self): + self.fixture_config_read_success() +- ( +- self.config.http.booth.send_config( +- "booth", +- self.fixture_cfg_content().decode("utf-8"), +- authfile=os.path.basename(self.fixture_key_path()), +- authfile_data=RANDOM_KEY, +- communication_list=[ +- dict( +- label=self.node_list[0], +- errno=1, +- error_msg=self.reason, +- was_connected=False, +- ), +- dict( +- label=self.node_list[1], +- ), +- ], +- ) ++ self.config.http.booth.send_config( ++ "booth", ++ self.fixture_cfg_content().decode("utf-8"), ++ authfile=os.path.basename(self.fixture_key_path()), ++ authfile_data=RANDOM_KEY, ++ communication_list=[ ++ dict( ++ label=self.node_list[0], ++ errno=1, ++ error_msg=self.reason, ++ was_connected=False, ++ ), ++ dict( ++ label=self.node_list[1], ++ ), ++ ], + ) + + commands.config_sync(self.env_assist.get_env(), skip_offline_nodes=True) +@@ -2849,15 +2639,13 @@ class ConfigSyncTest(TestCase, FixtureMixin): + ) + + def test_config_not_accessible(self): +- ( +- self.config.corosync_conf.load().raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- exception_msg=self.reason, +- ) ++ self.config.corosync_conf.load().raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ exception_msg=self.reason, + ) + self.env_assist.assert_raise_library_error( +- lambda: commands.config_sync(self.env_assist.get_env()), ++ lambda: commands.config_sync(self.env_assist.get_env()) + ) + self.env_assist.assert_reports( + [ +@@ -2881,7 +2669,7 @@ class ConfigSyncTest(TestCase, FixtureMixin): + ) + (self.config.corosync_conf.load()) + self.env_assist.assert_raise_library_error( +- lambda: commands.config_sync(self.env_assist.get_env()), ++ lambda: commands.config_sync(self.env_assist.get_env()) + ) + self.env_assist.assert_reports( + [ +@@ -2896,15 +2684,13 @@ class ConfigSyncTest(TestCase, FixtureMixin): + ) + + def test_config_parse_error(self): +- ( +- self.config.corosync_conf.load().raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content="invalid config".encode("utf-8"), +- ) ++ self.config.corosync_conf.load().raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content="invalid config".encode("utf-8"), + ) + self.env_assist.assert_raise_library_error( +- lambda: commands.config_sync(self.env_assist.get_env()), ++ lambda: commands.config_sync(self.env_assist.get_env()) + ) + self.env_assist.assert_reports( + [ +@@ -2924,9 +2710,9 @@ class ConfigSyncTest(TestCase, FixtureMixin): + "key_path": "some key path", + } + ) +- (self.config.corosync_conf.load()) ++ self.config.corosync_conf.load() + self.env_assist.assert_raise_library_error( +- lambda: commands.config_sync(self.env_assist.get_env()), ++ lambda: commands.config_sync(self.env_assist.get_env()) + ) + self.env_assist.assert_reports( + [ +@@ -2939,23 +2725,21 @@ class ConfigSyncTest(TestCase, FixtureMixin): + ) + + def test_authfile_not_accessible(self): +- ( +- self.config.corosync_conf.load() +- .raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=self.fixture_cfg_content(), +- name="raw_file.read.conf", +- ) +- .raw_file.read( +- file_type_codes.BOOTH_KEY, +- self.fixture_key_path(), +- exception_msg=self.reason, +- name="raw_file.read.key", +- ) ++ self.config.corosync_conf.load() ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=self.fixture_cfg_content(), ++ name="raw_file.read.conf", ++ ) ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_KEY, ++ self.fixture_key_path(), ++ exception_msg=self.reason, ++ name="raw_file.read.key", + ) + self.env_assist.assert_raise_library_error( +- lambda: commands.config_sync(self.env_assist.get_env()), ++ lambda: commands.config_sync(self.env_assist.get_env()) + ) + self.env_assist.assert_reports( + [ +@@ -2977,9 +2761,9 @@ class ConfigSyncTest(TestCase, FixtureMixin): + "key_path": "some key path", + } + ) +- (self.config.corosync_conf.load()) ++ self.config.corosync_conf.load() + self.env_assist.assert_raise_library_error( +- lambda: commands.config_sync(self.env_assist.get_env()), ++ lambda: commands.config_sync(self.env_assist.get_env()) + ) + self.env_assist.assert_reports( + [ +@@ -2994,22 +2778,22 @@ class ConfigSyncTest(TestCase, FixtureMixin): + ) + + def test_no_authfile(self): +- ( +- self.config.corosync_conf.load() +- .raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=bytes(), +- ) +- .http.booth.send_config( +- "booth", +- bytes().decode("utf-8"), +- node_labels=self.node_list, +- ) ++ self.config.corosync_conf.load() ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=bytes(), ++ ) ++ self.config.http.booth.send_config( ++ "booth", ++ bytes().decode("utf-8"), ++ node_labels=self.node_list, + ) + commands.config_sync(self.env_assist.get_env()) + self.env_assist.assert_reports( +- [fixture.info(reports.codes.BOOTH_CONFIG_DISTRIBUTION_STARTED)] ++ [ ++ fixture.info(reports.codes.BOOTH_CONFIG_DISTRIBUTION_STARTED), ++ ] + + [ + fixture.info( + reports.codes.BOOTH_CONFIG_ACCEPTED_BY_NODE, +@@ -3022,18 +2806,14 @@ class ConfigSyncTest(TestCase, FixtureMixin): + + def test_authfile_not_in_booth_dir(self): + config_content = "authfile=/etc/my_booth.key" +- ( +- self.config.corosync_conf.load() +- .raw_file.read( +- file_type_codes.BOOTH_CONFIG, +- self.fixture_cfg_path(), +- content=config_content.encode("utf-8"), +- ) +- .http.booth.send_config( +- "booth", +- config_content, +- node_labels=self.node_list, +- ) ++ self.config.corosync_conf.load() ++ self.config.raw_file.read( ++ file_type_codes.BOOTH_CONFIG, ++ self.fixture_cfg_path(), ++ content=config_content.encode("utf-8"), ++ ) ++ self.config.http.booth.send_config( ++ "booth", config_content, node_labels=self.node_list + ) + commands.config_sync(self.env_assist.get_env()) + self.env_assist.assert_reports( +@@ -3096,9 +2876,7 @@ class EnableDisableStartStopMixin(FixtureMixin): + ) + self.config.env.set_cib_data("") + self.env_assist.assert_raise_library_error( +- lambda: self.command( +- self.env_assist.get_env(), +- ), ++ lambda: self.command(self.env_assist.get_env()), + [ + fixture.error( + reports.codes.LIVE_ENVIRONMENT_REQUIRED, +@@ -3114,9 +2892,7 @@ class EnableDisableStartStopMixin(FixtureMixin): + + def test_success_default_instance(self): + self.get_external_call()("booth", instance="booth") +- self.command( +- self.env_assist.get_env(), +- ) ++ self.command(self.env_assist.get_env()) + self.env_assist.assert_reports( + [ + fixture.info( +@@ -3149,9 +2925,7 @@ class EnableDisableStartStopMixin(FixtureMixin): + err_msg = "some stderr\nsome stdout" + self.get_external_call()("booth", instance="booth", failure_msg=err_msg) + self.env_assist.assert_raise_library_error( +- lambda: self.command( +- self.env_assist.get_env(), +- ), ++ lambda: self.command(self.env_assist.get_env()), + [ + fixture.error( + reports.codes.SERVICE_ACTION_FAILED, +@@ -3226,17 +3000,16 @@ class PullConfigBase(TestCase, FixtureMixin): + class PullConfigSuccess(PullConfigBase): + def setUp(self): + super().setUp() +- ( +- self.config.http.booth.get_config( +- self.name, +- self.config_data.decode("utf-8"), +- node_labels=[self.node_name], +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.config_path, +- self.config_data, +- can_overwrite=True, +- ) ++ self.config.http.booth.get_config( ++ self.name, ++ self.config_data.decode("utf-8"), ++ node_labels=[self.node_name], ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.config_path, ++ self.config_data, ++ can_overwrite=True, + ) + + def test_success(self): +@@ -3265,17 +3038,16 @@ class PullConfigSuccessCustomInstance(TestCase, FixtureMixin): + ] + + def test_success(self): +- ( +- self.config.http.booth.get_config( +- self.name, +- self.config_data.decode("utf-8"), +- node_labels=[self.node_name], +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.config_path, +- self.config_data, +- can_overwrite=True, +- ) ++ self.config.http.booth.get_config( ++ self.name, ++ self.config_data.decode("utf-8"), ++ node_labels=[self.node_name], ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.config_path, ++ self.config_data, ++ can_overwrite=True, + ) + commands.pull_config( + self.env_assist.get_env(), +@@ -3514,34 +3286,31 @@ class PullConfigWithAuthfile(PullConfigBase): + self.authfile = os.path.basename(self.authfile_path) + self.authfile_data = b"auth" + +- ( +- self.config.http.booth.get_config( +- self.name, +- self.config_data.decode("utf-8"), +- authfile=self.authfile, +- authfile_data=self.authfile_data, +- node_labels=[self.node_name], +- ) ++ self.config.http.booth.get_config( ++ self.name, ++ self.config_data.decode("utf-8"), ++ authfile=self.authfile, ++ authfile_data=self.authfile_data, ++ node_labels=[self.node_name], + ) + + + class PullConfigWithAuthfileSuccess(PullConfigWithAuthfile): + def setUp(self): + super().setUp() +- ( +- self.config.raw_file.write( +- file_type_codes.BOOTH_KEY, +- self.authfile_path, +- self.authfile_data, +- can_overwrite=True, +- name="raw_file.write.key", +- ).raw_file.write( +- file_type_codes.BOOTH_CONFIG, +- self.config_path, +- self.config_data, +- can_overwrite=True, +- name="raw_file.write.cfg", +- ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_KEY, ++ self.authfile_path, ++ self.authfile_data, ++ can_overwrite=True, ++ name="raw_file.write.key", ++ ) ++ self.config.raw_file.write( ++ file_type_codes.BOOTH_CONFIG, ++ self.config_path, ++ self.config_data, ++ can_overwrite=True, ++ name="raw_file.write.cfg", + ) + + def test_success(self): +@@ -3642,13 +3411,13 @@ class GetStatus(TestCase): + + def assert_success(self, instance_name=None): + inner_name = instance_name or "booth" +- ( +- self.config.runner.booth.status_daemon( +- inner_name, stdout="daemon status" +- ) +- .runner.booth.status_tickets(inner_name, stdout="tickets status") +- .runner.booth.status_peers(inner_name, stdout="peers status") ++ self.config.runner.booth.status_daemon( ++ inner_name, stdout="daemon status" + ) ++ self.config.runner.booth.status_tickets( ++ inner_name, stdout="tickets status" ++ ) ++ self.config.runner.booth.status_peers(inner_name, stdout="peers status") + self.assertEqual( + commands.get_status( + self.env_assist.get_env(), instance_name=instance_name +@@ -3667,10 +3436,8 @@ class GetStatus(TestCase): + self.assert_success(instance_name="my_booth") + + def test_daemon_status_failure(self): +- ( +- self.config.runner.booth.status_daemon( +- "booth", stdout="some output", stderr="some error", returncode=1 +- ) ++ self.config.runner.booth.status_daemon( ++ "booth", stdout="some output", stderr="some error", returncode=1 + ) + self.env_assist.assert_raise_library_error( + lambda: commands.get_status(self.env_assist.get_env()), +@@ -3684,12 +3451,9 @@ class GetStatus(TestCase): + ) + + def test_ticket_status_failure(self): +- ( +- self.config.runner.booth.status_daemon( +- "booth", stdout="daemon status" +- ).runner.booth.status_tickets( +- "booth", stdout="some output", stderr="some error", returncode=1 +- ) ++ self.config.runner.booth.status_daemon("booth", stdout="daemon status") ++ self.config.runner.booth.status_tickets( ++ "booth", stdout="some output", stderr="some error", returncode=1 + ) + self.env_assist.assert_raise_library_error( + lambda: commands.get_status(self.env_assist.get_env()), +@@ -3703,14 +3467,12 @@ class GetStatus(TestCase): + ) + + def test_peers_status_failure(self): +- ( +- self.config.runner.booth.status_daemon( +- "booth", stdout="daemon status" +- ) +- .runner.booth.status_tickets("booth", stdout="tickets status") +- .runner.booth.status_peers( +- "booth", stdout="some output", stderr="some error", returncode=1 +- ) ++ self.config.runner.booth.status_daemon("booth", stdout="daemon status") ++ self.config.runner.booth.status_tickets( ++ "booth", stdout="tickets status" ++ ) ++ self.config.runner.booth.status_peers( ++ "booth", stdout="some output", stderr="some error", returncode=1 + ) + self.env_assist.assert_raise_library_error( + lambda: commands.get_status(self.env_assist.get_env()), +-- +2.35.3 + diff --git a/SOURCES/bz2058243-02-make-booth-ticket-mode-value-case-insensitive.patch b/SOURCES/bz2058243-02-make-booth-ticket-mode-value-case-insensitive.patch new file mode 100644 index 0000000..212472d --- /dev/null +++ b/SOURCES/bz2058243-02-make-booth-ticket-mode-value-case-insensitive.patch @@ -0,0 +1,126 @@ +From de4845ea2d22c7dd9f4539360b44a900b1cea193 Mon Sep 17 00:00:00 2001 +From: Tomas Jelinek +Date: Thu, 14 Jul 2022 16:46:33 +0200 +Subject: [PATCH 2/3] make booth ticket mode value case insensitive + +--- + pcs/lib/booth/config_validators.py | 10 ++++++++ + pcs/lib/commands/booth.py | 14 +++++++++--- + pcs_test/tier0/lib/commands/test_booth.py | 28 ++++++++++++++++------- + 3 files changed, 41 insertions(+), 11 deletions(-) + +diff --git a/pcs/lib/booth/config_validators.py b/pcs/lib/booth/config_validators.py +index 99badc46..6c4a4ddc 100644 +--- a/pcs/lib/booth/config_validators.py ++++ b/pcs/lib/booth/config_validators.py +@@ -100,6 +100,16 @@ def remove_ticket(conf_facade, ticket_name): + return [] + + ++def ticket_options_normalization() -> validate.TypeNormalizeFunc: ++ return validate.option_value_normalization( ++ { ++ "mode": ( ++ lambda value: value.lower() if isinstance(value, str) else value ++ ) ++ } ++ ) ++ ++ + def validate_ticket_name(ticket_name: str) -> reports.ReportItemList: + if not __TICKET_NAME_RE.search(ticket_name): + return [ +diff --git a/pcs/lib/commands/booth.py b/pcs/lib/commands/booth.py +index e7891fbe..fc1454ce 100644 +--- a/pcs/lib/commands/booth.py ++++ b/pcs/lib/commands/booth.py +@@ -23,7 +23,10 @@ from pcs.common.reports.item import ( + ) + from pcs.common.services.errors import ManageServiceError + from pcs.common.str_tools import join_multilines +-from pcs.lib import tools ++from pcs.lib import ( ++ tools, ++ validate, ++) + from pcs.lib.booth import ( + config_files, + config_validators, +@@ -329,17 +332,22 @@ def config_ticket_add( + booth_env = env.get_booth_env(instance_name) + try: + booth_conf = booth_env.config.read_to_facade() ++ options_pairs = validate.values_to_pairs( ++ options, config_validators.ticket_options_normalization() ++ ) + report_processor.report_list( + config_validators.add_ticket( + booth_conf, + ticket_name, +- options, ++ options_pairs, + allow_unknown_options=allow_unknown_options, + ) + ) + if report_processor.has_errors: + raise LibraryError() +- booth_conf.add_ticket(ticket_name, options) ++ booth_conf.add_ticket( ++ ticket_name, validate.pairs_to_values(options_pairs) ++ ) + booth_env.config.write_facade(booth_conf, can_overwrite=True) + except RawFileError as e: + report_processor.report(raw_file_error_report(e)) +diff --git a/pcs_test/tier0/lib/commands/test_booth.py b/pcs_test/tier0/lib/commands/test_booth.py +index 2b20a199..12b169c2 100644 +--- a/pcs_test/tier0/lib/commands/test_booth.py ++++ b/pcs_test/tier0/lib/commands/test_booth.py +@@ -1194,7 +1194,7 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + }, + ) + +- def test_success_ticket_options(self): ++ def assert_success_ticket_options(self, options_command, options_config): + self.config.raw_file.read( + file_type_codes.BOOTH_CONFIG, + self.fixture_cfg_path(), +@@ -1203,17 +1203,29 @@ class ConfigTicketAdd(TestCase, FixtureMixin): + self.config.raw_file.write( + file_type_codes.BOOTH_CONFIG, + self.fixture_cfg_path(), +- self.fixture_cfg_content( +- ticket_list=[ +- ["ticketA", [("retries", "10"), ("timeout", "20")]] +- ] +- ), ++ self.fixture_cfg_content(ticket_list=[["ticketA", options_config]]), + can_overwrite=True, + ) + commands.config_ticket_add( +- self.env_assist.get_env(), +- "ticketA", ++ self.env_assist.get_env(), "ticketA", options_command ++ ) ++ ++ def test_success_ticket_options(self): ++ self.assert_success_ticket_options( + {"timeout": "20", "retries": "10"}, ++ [("retries", "10"), ("timeout", "20")], ++ ) ++ ++ def test_success_ticket_options_mode(self): ++ self.assert_success_ticket_options( ++ {"timeout": "20", "retries": "10", "mode": "manual"}, ++ [("mode", "manual"), ("retries", "10"), ("timeout", "20")], ++ ) ++ ++ def test_success_ticket_options_mode_case_insensitive(self): ++ self.assert_success_ticket_options( ++ {"timeout": "20", "retries": "10", "mode": "MaNuAl"}, ++ [("mode", "manual"), ("retries", "10"), ("timeout", "20")], + ) + + def test_ticket_already_exists(self): +-- +2.35.3 + diff --git a/SOURCES/bz2102663-01-fix-pcs-resource-restart-traceback.patch b/SOURCES/bz2102663-01-fix-pcs-resource-restart-traceback.patch new file mode 100644 index 0000000..20f2d50 --- /dev/null +++ b/SOURCES/bz2102663-01-fix-pcs-resource-restart-traceback.patch @@ -0,0 +1,24 @@ +From eeeaac9a46f3568e0a116048068ff99d0dccf25c Mon Sep 17 00:00:00 2001 +From: Tomas Jelinek +Date: Thu, 30 Jun 2022 14:49:16 +0200 +Subject: [PATCH] fix 'pcs resource restart' traceback + +--- + pcs/resource.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/pcs/resource.py b/pcs/resource.py +index eb59d703..8d402c22 100644 +--- a/pcs/resource.py ++++ b/pcs/resource.py +@@ -2596,7 +2596,6 @@ def resource_restart( + Options: + * --wait + """ +- del lib + modifiers.ensure_only_supported("--wait") + if not argv: + utils.err("You must specify a resource to restart") +-- +2.35.3 + diff --git a/SOURCES/bz2116841-01-fix-ruby-socket-permissions.patch b/SOURCES/bz2116841-01-fix-ruby-socket-permissions.patch new file mode 100644 index 0000000..186e8c2 --- /dev/null +++ b/SOURCES/bz2116841-01-fix-ruby-socket-permissions.patch @@ -0,0 +1,46 @@ +From efd5edbfc96a2d85ee0575beca8b163b4ab9179f Mon Sep 17 00:00:00 2001 +From: Tomas Jelinek +Date: Wed, 10 Aug 2022 14:47:53 +0200 +Subject: [PATCH] fix ruby socket permissions + +--- + pcsd/rserver.rb | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/pcsd/rserver.rb b/pcsd/rserver.rb +index e2c5e2a1..4fde639e 100644 +--- a/pcsd/rserver.rb ++++ b/pcsd/rserver.rb +@@ -7,6 +7,29 @@ require 'thin' + + require 'settings.rb' + ++# Replace Thin::Backends::UnixServer:connect ++# The only change is 'File.umask(0o777)' instead of 'File.umask(0)' to properly ++# set python-ruby socket permissions ++module Thin ++ module Backends ++ class UnixServer < Base ++ def connect ++ at_exit { remove_socket_file } # In case it crashes ++ old_umask = File.umask(0o077) ++ begin ++ EventMachine.start_unix_domain_server(@socket, UnixConnection, &method(:initialize_connection)) ++ # HACK EventMachine.start_unix_domain_server doesn't return the connection signature ++ # so we have to go in the internal stuff to find it. ++ @signature = EventMachine.instance_eval{@acceptors.keys.first} ++ ensure ++ File.umask(old_umask) ++ end ++ end ++ end ++ end ++end ++ ++ + def pack_response(response) + return [200, {}, [response.to_json.to_str]] + end +-- +2.37.3 + diff --git a/SOURCES/do-not-support-cluster-setup-with-udp-u-transport.patch b/SOURCES/do-not-support-cluster-setup-with-udp-u-transport.patch new file mode 100644 index 0000000..ab241a5 --- /dev/null +++ b/SOURCES/do-not-support-cluster-setup-with-udp-u-transport.patch @@ -0,0 +1,38 @@ +From 2a578689db8522971840dbb1644a21c341fe7d83 Mon Sep 17 00:00:00 2001 +From: Ivan Devat +Date: Tue, 20 Nov 2018 15:03:56 +0100 +Subject: [PATCH] do not support cluster setup with udp(u) transport in RHEL9 + +--- + pcs/pcs.8.in | 2 ++ + pcs/usage.py | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/pcs/pcs.8.in b/pcs/pcs.8.in +index 363515bb..4c2496aa 100644 +--- a/pcs/pcs.8.in ++++ b/pcs/pcs.8.in +@@ -457,6 +457,8 @@ By default, encryption is enabled with cipher=aes256 and hash=sha256. To disable + + Transports udp and udpu: + .br ++WARNING: These transports are not supported in RHEL 9. ++.br + These transports are limited to one address per node. They do not support traffic encryption nor compression. + .br + Transport options are: ip_version, netmtu +diff --git a/pcs/usage.py b/pcs/usage.py +index cfa2ac9c..519c853e 100644 +--- a/pcs/usage.py ++++ b/pcs/usage.py +@@ -1429,6 +1429,7 @@ Commands: + hash=sha256. To disable encryption, set cipher=none and hash=none. + + Transports udp and udpu: ++ WARNING: These transports are not supported in RHEL 9. + These transports are limited to one address per node. They do not + support traffic encryption nor compression. + Transport options are: +-- +2.35.1 + diff --git a/SPECS/pcs.spec b/SPECS/pcs.spec new file mode 100644 index 0000000..9713d3a --- /dev/null +++ b/SPECS/pcs.spec @@ -0,0 +1,1027 @@ +Name: pcs +Version: 0.11.3 +Release: 4%{?dist} +# https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/ +# https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses +# GPLv2: pcs +# ASL 2.0: tornado +# MIT: backports, dacite, daemons, ethon, mustermann, rack, rack-protection, +# rack-test, sinatra, tilt +# GPLv2 or Ruby: eventmachne +# (GPLv2 or Ruby) and BSD: thin +# BSD or Ruby: open4, ruby2_keywords, webrick +# BSD and MIT: ffi +License: GPLv2 and ASL 2.0 and MIT and BSD and (GPLv2 or Ruby) and (BSD or Ruby) +URL: https://github.com/ClusterLabs/pcs +Group: System Environment/Base +Summary: Pacemaker Configuration System +#building only for architectures with pacemaker and corosync available +ExclusiveArch: i686 x86_64 s390x ppc64le aarch64 + +%global version_or_commit %{version} +# %%global version_or_commit %%{version}.44-9da7 + +%global pcs_source_name %{name}-%{version_or_commit} + +# ui_commit can be determined by hash, tag or branch +%global ui_commit 0.1.14 +%global ui_modules_version 0.1.14 +%global ui_src_name pcs-web-ui-%{ui_commit} + +%global pcs_snmp_pkg_name pcs-snmp + +%global pyagentx_version 0.4.pcs.2 +%global tornado_version 6.1.0 +%global dacite_version 1.6.0 +%global version_rubygem_backports 3.23.0 +%global version_rubygem_daemons 1.4.1 +%global version_rubygem_ethon 0.15.0 +%global version_rubygem_eventmachine 1.2.7 +%global version_rubygem_ffi 1.15.5 +%global version_rubygem_mustermann 1.1.1 +%global version_rubygem_open4 1.3.4 +%global version_rubygem_rack 2.2.3.1 +%global version_rubygem_rack_protection 2.2.0 +%global version_rubygem_rack_test 1.1.0 +%global version_rubygem_ruby2_keywords 0.0.5 +%global version_rubygem_sinatra 2.2.0 +%global version_rubygem_thin 1.8.1 +%global version_rubygem_tilt 2.0.10 +%global version_rubygem_webrick 1.7.0 + +%global required_pacemaker_version 2.1.0 + +%global pcs_bundled_dir pcs_bundled +%global pcsd_public_dir pcsd/public +%global rubygem_bundle_dir pcsd/vendor/bundle +%global rubygem_cache_dir %{rubygem_bundle_dir}/cache + +# mangling shebang in /usr/lib/pcsd/vendor/bundle/ruby/gems/rack-2.0.5/test/cgi/test from /usr/bin/env ruby to #!/usr/bin/ruby +#*** ERROR: ./usr/lib/pcsd/vendor/bundle/ruby/gems/rack-2.0.5/test/cgi/test.ru has shebang which doesn't start with '/' (../../bin/rackup) +#mangling shebang in /usr/lib/pcsd/vendor/bundle/ruby/gems/rack-2.0.5/test/cgi/rackup_stub.rb from /usr/bin/env ruby to #!/usr/bin/ruby +#*** WARNING: ./usr/lib/pcsd/vendor/bundle/ruby/gems/rack-2.0.5/test/cgi/sample_rackup.ru is executable but has empty or no shebang, removing executable bit +#*** WARNING: ./usr/lib/pcsd/vendor/bundle/ruby/gems/rack-2.0.5/test/cgi/lighttpd.conf is executable but has empty or no shebang, removing executable bit +#*** ERROR: ambiguous python shebang in /usr/lib/pcsd/vendor/bundle/ruby/gems/ffi-1.9.25/ext/ffi_c/libffi/generate-darwin-source-and-headers.py: #!/usr/bin/env python. Change it to python3 (or python2) explicitly. +%undefine __brp_mangle_shebangs + +# https://fedoraproject.org/wiki/Changes/Avoid_usr_bin_python_in_RPM_Build#Python_bytecompilation +# Enforce python3 because bytecompilation of tornado produced warnings: +# DEPRECATION WARNING: python2 invoked with /usr/bin/python. +# Use /usr/bin/python3 or /usr/bin/python2 +# /usr/bin/python will be removed or switched to Python 3 in the future. +%global __python %{__python3} + +Source0: %{url}/archive/%{version_or_commit}/%{pcs_source_name}.tar.gz + +Source41: https://github.com/ondrejmular/pyagentx/archive/v%{pyagentx_version}/pyagentx-%{pyagentx_version}.tar.gz +Source42: https://github.com/tornadoweb/tornado/archive/v%{tornado_version}/tornado-%{tornado_version}.tar.gz +Source44: https://github.com/konradhalas/dacite/archive/v%{dacite_version}/dacite-%{dacite_version}.tar.gz + +Source81: https://rubygems.org/downloads/backports-%{version_rubygem_backports}.gem +Source82: https://rubygems.org/downloads/ethon-%{version_rubygem_ethon}.gem +Source83: https://rubygems.org/downloads/ffi-%{version_rubygem_ffi}.gem +Source86: https://rubygems.org/downloads/mustermann-%{version_rubygem_mustermann}.gem +# We needed to re-upload open4 rubygem because of issues with sources in gating. +# Unfortunately, there was no newer version available, therefore we had to +# change its 'version' ourselves. +Source87: https://rubygems.org/downloads/open4-%{version_rubygem_open4}.gem#/open4-%{version_rubygem_open4}-1.gem +Source88: https://rubygems.org/downloads/rack-%{version_rubygem_rack}.gem +Source89: https://rubygems.org/downloads/rack-protection-%{version_rubygem_rack_protection}.gem +Source90: https://rubygems.org/downloads/rack-test-%{version_rubygem_rack_test}.gem +Source91: https://rubygems.org/downloads/sinatra-%{version_rubygem_sinatra}.gem +Source92: https://rubygems.org/downloads/tilt-%{version_rubygem_tilt}.gem +Source93: https://rubygems.org/downloads/eventmachine-%{version_rubygem_eventmachine}.gem +Source94: https://rubygems.org/downloads/daemons-%{version_rubygem_daemons}.gem +Source95: https://rubygems.org/downloads/thin-%{version_rubygem_thin}.gem +Source96: https://rubygems.org/downloads/ruby2_keywords-%{version_rubygem_ruby2_keywords}.gem +Source97: https://rubygems.org/downloads/webrick-%{version_rubygem_webrick}.gem + +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 + +# Patches from upstream. +# They should come before downstream patches to avoid unnecessary conflicts. +# Z-streams are exception here: they can come from upstream but should be +# applied at the end to keep z-stream changes as straightforward as possible. +# Patch1: bzNUMBER-01-name.patch + +# Downstream patches do not come from upstream. They adapt pcs for specific +# RHEL needs. + +# pcs patches: <= 200 +Patch1: do-not-support-cluster-setup-with-udp-u-transport.patch +Patch2: bz2102663-01-fix-pcs-resource-restart-traceback.patch +Patch3: bz2058243-01-code-formatting.patch +Patch4: bz2058243-02-make-booth-ticket-mode-value-case-insensitive.patch +Patch5: bz2026725-01-booth-sync-check-whether-etc-booth-exists.patch +Patch6: bz2116841-01-fix-ruby-socket-permissions.patch + +# ui patches: >200 +# Patch201: bzNUMBER-01-name.patch + +# git for patches +BuildRequires: git-core +#printf from coreutils is used in makefile +BuildRequires: coreutils +# python for pcs +BuildRequires: python3 >= 3.9 +BuildRequires: python3-cryptography +BuildRequires: python3-dateutil >= 2.7.0 +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pycurl +BuildRequires: python3-pip +BuildRequires: python3-pyparsing +BuildRequires: python3-cryptography +BuildRequires: python3-lxml +# for building bundled python packages +BuildRequires: python3-wheel +# for bundled python dateutil +BuildRequires: python3-setuptools_scm +# gcc for compiling custom rubygems +BuildRequires: gcc +BuildRequires: gcc-c++ +# ruby and gems for pcsd +BuildRequires: ruby >= 2.5 +BuildRequires: ruby-devel +BuildRequires: rubygems +BuildRequires: rubygem-bundler +BuildRequires: rubygem-json +BuildRequires: rubygem-rexml +# ruby libraries for tests +BuildRequires: rubygem-test-unit +# for touching patch files (sanitization function) +BuildRequires: diffstat +# for post, preun and postun macros +BuildRequires: systemd +BuildRequires: make +# Red Hat logo for creating symlink of favicon +BuildRequires: redhat-logos +# for building web ui +BuildRequires: npm +# cluster stack packages for pkg-config +BuildRequires: booth +BuildRequires: corosync-qdevice-devel +BuildRequires: corosynclib-devel >= 3.0 +BuildRequires: fence-agents-common +BuildRequires: pacemaker-libs-devel >= %{required_pacemaker_version} +BuildRequires: resource-agents +BuildRequires: sbd + +# 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 +Requires: python3-setuptools +Requires: python3-pycurl +Requires: python3-pyparsing +Requires: python3-cryptography +# ruby and gems for pcsd +Requires: ruby >= 2.5 +Requires: rubygems +Requires: rubygem-json +Requires: rubygem-rexml +# for killall +Requires: psmisc +# cluster stack and related packages +Requires: pcmk-cluster-manager >= %{required_pacemaker_version} +Suggests: pacemaker >= %{required_pacemaker_version} +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 +# favicon Red Hat logo +Requires: redhat-logos +# needs logrotate for /etc/logrotate.d/pcsd +Requires: logrotate + +Provides: bundled(tornado) = %{tornado_version} +Provides: bundled(dacite) = %{dacite_version} +Provides: bundled(backports) = %{version_rubygem_backports} +Provides: bundled(daemons) = %{version_rubygem_daemons} +Provides: bundled(ethon) = %{version_rubygem_ethon} +Provides: bundled(eventmachine) = %{version_rubygem_eventmachine} +Provides: bundled(ffi) = %{version_rubygem_ffi} +Provides: bundled(mustermann) = %{version_rubygem_mustermann} +Provides: bundled(open4) = %{version_rubygem_open4} +Provides: bundled(rack) = %{version_rubygem_rack} +Provides: bundled(rack_protection) = %{version_rubygem_rack_protection} +Provides: bundled(rack_test) = %{version_rubygem_rack_test} +Provides: bundled(ruby2_keywords) = %{version_rubygem_ruby2_keywords} +Provides: bundled(sinatra) = %{version_rubygem_sinatra} +Provides: bundled(thin) = %{version_rubygem_thin} +Provides: bundled(tilt) = %{version_rubygem_tilt} +Provides: bundled(webrick) = %{version_rubygem_webrick} + +%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} +Group: System Environment/Base +Summary: Pacemaker cluster SNMP agent +# https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses +# GPLv2: pcs +# BSD-2-Clause: pyagentx +License: GPLv2 and BSD-2-Clause +URL: https://github.com/ClusterLabs/pcs + +# tar for unpacking pyagetx source tar ball +BuildRequires: tar + +Requires: pcs = %{version}-%{release} +Requires: pacemaker +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) + +%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 + +update_times(){ + # update_times ... + # set the access and modification times of each file_to_touch to the times + # of reference_file + + # put all args to file_list + file_list=("$@") + # first argument is reference_file: so take it and remove from file_list + reference_file=${file_list[0]} + unset file_list[0] + + for fname in ${file_list[@]}; do + # some files could be deleted by a patch therefore we test file for + # existance before touch to avoid exit with error: No such file or + # directory + # diffstat cannot create list of files without deleted files + test -e $fname && touch -r $reference_file $fname + done +} + +update_times_patch(){ + # update_times_patch + # set the access and modification times of each file in patch to the times + # of patch_file_name + + patch_file_name=$1 + + # diffstat + # -l lists only the filenames. No histogram is generated. + # -p override the logic that strips common pathnames, + # simulating the patch "-p" option. (Strip the smallest prefix containing + # num leading slashes from each file name found in the patch file) + update_times ${patch_file_name} `diffstat -p1 -l ${patch_file_name}` +} + +# documentation for setup/autosetup/autopatch: +# * 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 +%autopatch -p1 -m 201 +# update_times_patch %%{PATCH201} + +# patch pcs sources +%autosetup -S git -n %{pcs_source_name} -N +%autopatch -p1 -M 200 +update_times_patch %{PATCH1} +update_times_patch %{PATCH2} +update_times_patch %{PATCH3} +update_times_patch %{PATCH4} +update_times_patch %{PATCH5} +update_times_patch %{PATCH6} + +# prepare dirs/files necessary for building all bundles +# ----------------------------------------------------- +# 1) rubygems sources + +mkdir -p %{rubygem_cache_dir} +cp -f %SOURCE81 %{rubygem_cache_dir} +cp -f %SOURCE82 %{rubygem_cache_dir} +cp -f %SOURCE83 %{rubygem_cache_dir} +cp -f %SOURCE86 %{rubygem_cache_dir} +# For reason why we are renaming open4 rubygem, see comment of source +# definition above. +cp -f %SOURCE87 %{rubygem_cache_dir}/open4-%{version_rubygem_open4}.gem +cp -f %SOURCE88 %{rubygem_cache_dir} +cp -f %SOURCE89 %{rubygem_cache_dir} +cp -f %SOURCE90 %{rubygem_cache_dir} +cp -f %SOURCE91 %{rubygem_cache_dir} +cp -f %SOURCE92 %{rubygem_cache_dir} +cp -f %SOURCE93 %{rubygem_cache_dir} +cp -f %SOURCE94 %{rubygem_cache_dir} +cp -f %SOURCE95 %{rubygem_cache_dir} +cp -f %SOURCE96 %{rubygem_cache_dir} +cp -f %SOURCE97 %{rubygem_cache_dir} + + +# 2) prepare python bundles +mkdir -p %{pcs_bundled_dir}/src +cp -f %SOURCE41 rpm/ +cp -f %SOURCE42 rpm/ +cp -f %SOURCE44 rpm/ + +%build +%define debug_package %{nil} + +./autogen.sh +%{configure} --enable-local-build --enable-use-local-cache-only --enable-individual-bundling PYTHON=%{__python3} ruby_CFLAGS="%{optflags}" ruby_LIBS="%{build_ldflags}" +make all + +# build pcs-web-ui +make -C %{_builddir}/%{ui_src_name} build BUILD_USE_EXISTING_NODE_MODULES=true + +%install +rm -rf $RPM_BUILD_ROOT +pwd + +%make_install + +# install pcs-web-ui +cp -r %{_builddir}/%{ui_src_name}/build ${RPM_BUILD_ROOT}%{_libdir}/%{pcsd_public_dir}/ui + +# symlink favicon into pcsd directories +mkdir -p ${RPM_BUILD_ROOT}%{_libdir}/%{pcsd_public_dir}/images/ +ln -fs /etc/favicon.png ${RPM_BUILD_ROOT}%{_libdir}/%{pcsd_public_dir}/images/favicon.png + +# prepare license files +# some rubygems do not have a license file (ruby2_keywords, thin) +mv %{rubygem_bundle_dir}/gems/backports-%{version_rubygem_backports}/LICENSE.txt backports_LICENSE.txt +mv %{rubygem_bundle_dir}/gems/daemons-%{version_rubygem_daemons}/LICENSE daemons_LICENSE +mv %{rubygem_bundle_dir}/gems/ethon-%{version_rubygem_ethon}/LICENSE ethon_LICENSE +mv %{rubygem_bundle_dir}/gems/eventmachine-%{version_rubygem_eventmachine}/LICENSE eventmachine_LICENSE +mv %{rubygem_bundle_dir}/gems/eventmachine-%{version_rubygem_eventmachine}/GNU eventmachine_GNU +mv %{rubygem_bundle_dir}/gems/ffi-%{version_rubygem_ffi}/COPYING ffi_COPYING +mv %{rubygem_bundle_dir}/gems/ffi-%{version_rubygem_ffi}/LICENSE ffi_LICENSE +mv %{rubygem_bundle_dir}/gems/ffi-%{version_rubygem_ffi}/LICENSE.SPECS ffi_LICENSE.SPECS +mv %{rubygem_bundle_dir}/gems/mustermann-%{version_rubygem_mustermann}/LICENSE mustermann_LICENSE +mv %{rubygem_bundle_dir}/gems/open4-%{version_rubygem_open4}/LICENSE open4_LICENSE +mv %{rubygem_bundle_dir}/gems/rack-%{version_rubygem_rack}/MIT-LICENSE rack_MIT-LICENSE +mv %{rubygem_bundle_dir}/gems/rack-protection-%{version_rubygem_rack_protection}/License rack-protection_License +mv %{rubygem_bundle_dir}/gems/rack-test-%{version_rubygem_rack_test}/MIT-LICENSE.txt rack-test_MIT-LICENSE.txt +mv %{rubygem_bundle_dir}/gems/sinatra-%{version_rubygem_sinatra}/LICENSE sinatra_LICENSE +mv %{rubygem_bundle_dir}/gems/tilt-%{version_rubygem_tilt}/COPYING tilt_COPYING +mv %{rubygem_bundle_dir}/gems/webrick-%{version_rubygem_webrick}/LICENSE.txt webrick_LICENSE.txt + +cp %{pcs_bundled_dir}/src/pyagentx-*/LICENSE.txt pyagentx_LICENSE.txt +cp %{pcs_bundled_dir}/src/pyagentx-*/CONTRIBUTORS.txt pyagentx_CONTRIBUTORS.txt +cp %{pcs_bundled_dir}/src/pyagentx-*/README.md pyagentx_README.md + +cp %{pcs_bundled_dir}/src/tornado-*/LICENSE tornado_LICENSE +cp %{pcs_bundled_dir}/src/tornado-*/README.rst tornado_README.rst + +cp %{pcs_bundled_dir}/src/dacite-*/LICENSE dacite_LICENSE +cp %{pcs_bundled_dir}/src/dacite-*/README.md dacite_README.md + +# We are not building debug package for pcs but we need to add MiniDebuginfo +# to the bundled shared libraries from rubygem extensions in order to satisfy +# rpmdiff's binary stripping checker. +# Therefore we call find-debuginfo.sh script manually in order to strip +# binaries and add MiniDebugInfo with .gnu_debugdata section +/usr/lib/rpm/find-debuginfo.sh -j2 -m -i -S debugsourcefiles.list +# find-debuginfo.sh generated some files into /usr/lib/debug and +# /usr/src/debug/ that we don't want in the package +rm -rf $RPM_BUILD_ROOT%{_libdir}/debug +rm -rf $RPM_BUILD_ROOT/usr/lib/debug +rm -rf $RPM_BUILD_ROOT%{_prefix}/src/debug + +# We can remove files required for gem compilation +rm -rf $RPM_BUILD_ROOT%{_libdir}/%{rubygem_bundle_dir}/gems/eventmachine-%{version_rubygem_eventmachine}/ext +rm -rf $RPM_BUILD_ROOT%{_libdir}/%{rubygem_bundle_dir}/gems/ffi-%{version_rubygem_ffi}/ext +rm -rf $RPM_BUILD_ROOT%{_libdir}/%{rubygem_bundle_dir}/gems/thin-%{version_rubygem_thin}/ext + +%check +# 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. +# On the live system either UTF8 locale is set or the warning is emmited +# which breaks pcs. That is the correct behavior since with wrong locales it +# would be probably broken anyway. +# The main concern here is to make the tests pass. +# See https://fedoraproject.org/wiki/Changes/python3_c.utf-8_locale for details. +export PYTHONCOERCECLOCALE=0 + +run_all_tests(){ + #run pcs tests + + # disabled tests: + # + # pcs_test.tier0.lib.commands.test_resource_agent.DescribeAgentUtf8.test_describe + # For an unknown reason this test is failing in mock environment and + # passing outside the mock environment. + # TODO: Investigate the issue + + %{__python3} pcs_test/suite --tier0 -v --vanilla --all-but \ + pcs_test.tier0.lib.commands.test_resource_agent.DescribeAgentUtf8.test_describe \ + pcs_test.tier0.daemon.app.test_app_remote.SyncConfigMutualExclusive.test_get_not_locked \ + pcs_test.tier0.daemon.app.test_app_remote.SyncConfigMutualExclusive.test_post_not_locked \ + + test_result_python=$? + + #run pcsd tests and remove them + GEM_HOME=$RPM_BUILD_ROOT%{_libdir}/%{rubygem_bundle_dir} ruby \ + -I$RPM_BUILD_ROOT%{_libdir}/pcsd \ + -Ipcsd/test \ + pcsd/test/test_all_suite.rb + test_result_ruby=$? + + if [ $test_result_python -ne 0 ]; then + return $test_result_python + fi + return $test_result_ruby +} + +run_all_tests + +%posttrans +# Make sure the new version of the daemon is runnning. +# 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 + + +%post +%systemd_post pcsd.service +%systemd_post pcsd-ruby.service + +%post -n %{pcs_snmp_pkg_name} +%systemd_post pcs_snmp_agent.service + +%preun +%systemd_preun pcsd.service +%systemd_preun pcsd-ruby.service + +%preun -n %{pcs_snmp_pkg_name} +%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} +%systemd_postun_with_restart pcs_snmp_agent.service + +%files +%doc CHANGELOG.md +%doc README.md +%doc tornado_README.rst +%doc dacite_README.md +%license tornado_LICENSE +%license dacite_LICENSE +%license COPYING +# rugygem licenses +%license backports_LICENSE.txt +%license daemons_LICENSE +%license ethon_LICENSE +%license eventmachine_LICENSE +%license eventmachine_GNU +%license ffi_COPYING +%license ffi_LICENSE +%license ffi_LICENSE.SPECS +%license mustermann_LICENSE +%license open4_LICENSE +%license rack_MIT-LICENSE +%license rack-protection_License +%license rack-test_MIT-LICENSE.txt +%license sinatra_LICENSE +%license tilt_COPYING +%license webrick_LICENSE.txt +%{python3_sitelib}/* +%{_sbindir}/pcs +%{_sbindir}/pcsd +%{_libdir}/pcs/* +%{_libdir}/pcsd/* +%{_unitdir}/pcsd.service +%{_unitdir}/pcsd-ruby.service +%{_datadir}/bash-completion/completions/pcs +%{_sharedstatedir}/pcsd +%config(noreplace) %{_sysconfdir}/pam.d/pcsd +%dir %{_var}/log/pcsd +%config(noreplace) %{_sysconfdir}/logrotate.d/pcsd +%config(noreplace) %{_sysconfdir}/sysconfig/pcsd +%ghost %config(noreplace) %attr(0600,root,root) %{_sharedstatedir}/pcsd/cfgsync_ctl +%ghost %config(noreplace) %attr(0600,root,root) %{_sharedstatedir}/pcsd/known-hosts +%ghost %config(noreplace) %attr(0600,root,root) %{_sharedstatedir}/pcsd/pcsd.cookiesecret +%ghost %config(noreplace) %attr(0600,root,root) %{_sharedstatedir}/pcsd/pcsd.crt +%ghost %config(noreplace) %attr(0600,root,root) %{_sharedstatedir}/pcsd/pcsd.key +%ghost %config(noreplace) %attr(0644,root,root) %{_sharedstatedir}/pcsd/pcs_settings.conf +%ghost %config(noreplace) %attr(0644,root,root) %{_sharedstatedir}/pcsd/pcs_users.conf +%{_mandir}/man8/pcs.* +%{_mandir}/man8/pcsd.* +%exclude %{_libdir}/pcs/pcs_snmp_agent +%exclude %{_libdir}/pcs/%{pcs_bundled_dir}/packages/pyagentx* + + +%files -n %{pcs_snmp_pkg_name} +%{_libdir}/pcs/pcs_snmp_agent +%{_libdir}/pcs/%{pcs_bundled_dir}/packages/pyagentx* +%{_unitdir}/pcs_snmp_agent.service +%{_datadir}/snmp/mibs/PCMK-PCS*-MIB.txt +%{_mandir}/man8/pcs_snmp_agent.* +%config(noreplace) %{_sysconfdir}/sysconfig/pcs_snmp_agent +%doc CHANGELOG.md +%doc pyagentx_CONTRIBUTORS.txt +%doc pyagentx_README.md +%license COPYING +%license pyagentx_LICENSE.txt + +%changelog +* Mon Sep 05 2022 Miroslav Lisik - 0.11.3-4 +- Fixed ruby socket permissions +- Resolves: rhbz#2116841 + +* Thu Jul 28 2022 Miroslav Lisik - 0.11.3-3 +- Fixed booth ticket mode value case insensitive +- Fixed booth sync check whether /etc/booth exists +- Resolves: rhbz#2026725 rhbz#2058243 + +* Tue Jul 12 2022 Miroslav Lisik - 0.11.3-2 +- Fixed 'pcs resource restart' traceback +- Resolves: rhbz#2102663 + +* Fri Jun 24 2022 Miroslav Lisik - 0.11.3-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Updated pcs-web-ui +- Updated bundled rubygems: rack +- Resolves: rhbz#2059122 rhbz#2059177 rhbz#2059501 rhbz#2095695 rhbz#2096886 rhbz#2097730 rhbz#2097731 rhbz#2097732 rhbz#2097733 rhbz#2097778 + +* Thu May 19 2022 Miroslav Lisik - 0.11.2-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Updated pcs-web-ui +- Updated bundled rubygems: backports, daemons, ethon ffi, ruby2_keywords, thin +- Stopped bundling rubygem-rexml (use distribution package instead) +- Resolves: rhbz#1301204 rhbz#2024522 rhbz#2026725 rhbz#2029844 rhbz#2039884 rhbz#2053177 rhbz#2054671 rhbz#2058243 rhbz#2058246 rhbz#2058247 rhbz#2058251 rhbz#2058252 rhbz#2059142 rhbz#2059145 rhbz#2059148 rhbz#2059149 rhbz#2059501 rhbz#2064818 rhbz#2068457 rhbz#2076585 + +* Wed May 04 2022 Miroslav Lisik - 0.11.1-11 +- Updated bundled rubygems: sinatra, rack-protection +- Resolves: rhbz#2081334 + +* Tue Feb 01 2022 Miroslav Lisik - 0.11.1-10 +- Fixed snmp client +- Fixed translating resource roles in colocation constraint +- Resolves: rhbz#2048640 + +* Tue Jan 25 2022 Miroslav Lisik - 0.11.1-9 +- Fixed cluster destroy in web ui +- Fixed covscan issue in web ui +- Resolves: rhbz#2044409 + +* Fri Jan 14 2022 Miroslav Lisik - 0.11.1-8 +- Fixed 'pcs resource move' command +- Fixed removing of unavailable fence-scsi storage device +- Fixed ocf validation of ocf linbit drdb agent +- Fixed creating empty cib +- Updated pcs-web-ui +- Resolves: rhbz#1990787 rhbz#2033248 rhbz#2039883 rhbz#2040420 + +* Wed Dec 15 2021 Miroslav Lisik - 0.11.1-7 +- Fixed enabling corosync-qdevice +- Fixed resource update command when unable to get agent metadata +- Fixed revert of disallowing to clone a group with a stonith +- Resolves: rhbz#1811072 rhbz#2019836 rhbz#2032473 + +* Thu Dec 02 2021 Miroslav Lisik - 0.11.1-6 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Updated pcs web ui +- Resolves: rhbz#1990787 rhbz#1997019 rhbz#2012129 rhbz#2024542 rhbz#2027678 rhbz#2027679 + +* Thu Nov 18 2021 Miroslav Lisik - 0.11.1-5 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Resolves: rhbz#1990787 rhbz#2018969 rhbz#2019836 rhbz#2023752 rhbz#2012129 + +* Tue Nov 02 2021 Miroslav Lisik - 0.11.1-4 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Updated pcs web ui +- Enabled wui patching +- Resolves: rhbz#1811072 rhbz#1945305 rhbz#1997019 rhbz#2012129 + +* Thu Aug 26 2021 Miroslav Lisik - 0.11.1-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Resolves: rhbz#1283805 rhbz#1910644 rhbz#1910645 rhbz#1956703 rhbz#1956706 rhbz#1985981 rhbz#1991957 rhbz#1996062 rhbz#1996067 + +* Tue Aug 24 2021 Miroslav Lisik - 0.11.0.alpha.1-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Updated pcs web ui +- Resolves: rhbz#1283805 rhbz#1910644 rhbz#1910645 rhbz#1985981 rhbz#1991957 rhbz#1996067 + +* Thu Aug 19 2021 DJ Delorie - 0.10.9-2 +- Rebuilt for libffi 3.4.2 SONAME transition. + Related: rhbz#1891914 + +* Tue Aug 10 2021 Miroslav Lisik - 0.10.9-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Resolves: rhbz#1991957 + +* Mon Aug 09 2021 Mohan Boddu - 0.10.8-11 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Tue Jul 20 2021 Miroslav Lisik - 0.10.8-10 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Fixed web-ui build +- Fixed tests for pacemaker 2.1 +- Resolves: rhbz#1975440 rhbz#1922302 + +* Tue Jun 22 2021 Mohan Boddu - 0.10.8-9 +- Rebuilt for RHEL 9 BETA for openssl 3.0 + Related: rhbz#1971065 + +* Wed Jun 16 2021 Miroslav Lisik - 0.10.8-8 +- Rebuild with fixed gaiting tests +- Stopped bundling rubygem-json (use distribution package instead) +- Fixed patches +- Resolves: rhbz#1881064 + +* Tue Jun 15 2021 Miroslav Lisik - 0.10.8-7 +- Fixed License tag +- Rebuild with fixed dependency for gating tier0 tests +- Resolves: rhbz#1881064 + +* Thu Jun 10 2021 Miroslav Lisik - 0.10.8-6 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Removed clufter related commands +- Resolves: rhbz#1881064 + +* Wed Apr 28 2021 Miroslav Lisik - 0.10.8-5 +- Updated pcs web ui node modules +- Fixed build issue on low memory build hosts +- Resolves: rhbz#1951272 + +* Fri Apr 16 2021 Mohan Boddu - 0.10.8-4 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Thu Mar 04 2021 Miroslav Lisik - 0.10.8-3 +- Replace pyOpenSSL with python-cryptography +- Resolves: rhbz#1927404 + +* Fri Feb 19 2021 Miroslav Lisik - 0.10.8-2 +- Bundle rubygem depedencies and python3-tornado +- Resolves: rhbz#1929710 + +* Thu Feb 04 2021 Miroslav Lisik - 0.10.8-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Updated pcs-web-ui +- Updated bundled python dependency: dacite +- Changed BuildRequires from git to git-core +- Added conditional (Build)Requires: rubygem(rexml) +- Added conditional Requires: rubygem(webrick) + +* Tue Jan 26 2021 Fedora Release Engineering - 0.10.7-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Thu Jan 7 2021 Vít Ondruch - 0.10.7-3 +- Rebuilt for https://fedoraproject.org/wiki/Changes/Ruby_3.0 + +* Thu Nov 26 2020 Ondrej Mular - 0.10.7-2 +- Python 3.10 related fix + +* Wed Sep 30 2020 Miroslav Lisik - 0.10.7-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Added dependency on python packages pyparsing and dateutil +- Fixed virtual bundle provides for ember, handelbars, jquery and jquery-ui +- Removed dependency on python3-clufter + +* Tue Jul 28 2020 Fedora Release Engineering - 0.10.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jul 21 2020 Miroslav Lisik - 0.10.6-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Updated pcs-web-ui +- Stopped bundling tornado (use distribution package instead) +- Stopped bundling rubygem-tilt (use distribution package instead) +- Removed rubygem bundling +- Removed unneeded BuildRequires: execstack, gcc, gcc-c++ +- Excluded some tests for tornado daemon + +* Tue Jul 21 2020 Tom Stellard - 0.10.5-8 +- Use make macros +- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro + +* Wed Jul 15 2020 Ondrej Mular - 0.10.5-7 +- Use fixed upstream version of dacite with Python 3.9 support +- Split upstream tests in gating into tiers + +* Fri Jul 03 2020 Ondrej Mular - 0.10.5-6 +- Use patched version of dacite compatible with Python 3.9 +- Resolves: rhbz#1838327 + +* Tue May 26 2020 Miro Hrončok - 0.10.5-5 +- Rebuilt for Python 3.9 + +* Thu May 07 2020 Ondrej Mular - 0.10.5-4 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Run only tier0 tests in check section + +* Fri Apr 03 2020 Ondrej Mular - 0.10.5-3 +- Enable gating + +* Fri Mar 27 2020 Ondrej Mular - 0.10.5-2 +- Remove usage of deprecated module xml.etree.cElementTree +- Resolves: rhbz#1817695 + +* Wed Mar 18 2020 Miroslav Lisik - 0.10.5-1 +- Rebased to latest upstream sources (see CHANGELOG.md) + +* Wed Jan 29 2020 Fedora Release Engineering - 0.10.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Nov 28 2019 Miroslav Lisik - 0.10.4-1 +- Rebased to latest upstream sources (see CHANGELOG.md) + +* Thu Oct 03 2019 Miro Hrončok - 0.10.3-2 +- Rebuilt for Python 3.8.0rc1 (#1748018) + +* Fri Aug 23 2019 Ondrej Mular - 0.10.3-1 +- Rebased to latest upstream sources (see CHANGELOG.md) + +* Mon Aug 19 2019 Miro Hrončok - 0.10.2-3 +- Rebuilt for Python 3.8 + +* Fri Jul 26 2019 Fedora Release Engineering - 0.10.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Fri Jun 14 2019 Ondrej Mular - 0.10.2-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Added pam as required package +- An alternative webUI rebased to latest upstream sources +- Improved configuration files permissions in rpm + +* Tue Mar 19 2019 Tomas Jelinek - 0.10.1-4 +- Removed unused dependency rubygem-multi_json +- Removed files needed only for building rubygems from the package + +* Mon Feb 04 2019 Ivan Devát - 0.10.1-3 +- Corrected gem install flags + +* Fri Feb 01 2019 Fedora Release Engineering - 0.10.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Jan 09 2019 Ivan Devát - 0.10.1-1 +- Rebased to latest upstream sources (see CHANGELOG.md) + +* Tue Oct 09 2018 Ondrej Mular - 0.10.0.alpha.6-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Resolves: rhbz#1618911 + +* Fri Aug 31 2018 Ivan Devát - 0.10.0.alpha.2-3 +- Started bundling rubygem-tilt (rubygem-tilt is orphaned in fedora due to rubygem-prawn dependency) +- Enabled passing tests + +* Sat Aug 25 2018 Ivan Devát - 0.10.0.alpha.2-2 +- Fixed error with missing rubygem location during pcsd start +- Resolves: rhbz#1618911 + +* Thu Aug 02 2018 Ivan Devát - 0.10.0.alpha.2-1 +- Rebased to latest upstream sources (see CHANGELOG.md) + +* Wed Jul 25 2018 Ivan Devát - 0.9.164-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Fri Jul 13 2018 Fedora Release Engineering - 0.9.164-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue Jun 19 2018 Miro Hrončok - 0.9.164-2 +- Rebuilt for Python 3.7 + +* Mon Apr 09 2018 Ondrej Mular - 0.9.164-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Fixed: CVE-2018-1086, CVE-2018-1079 + +* Mon Feb 26 2018 Ivan Devát - 0.9.163-2 +- Fixed crash when adding a node to a cluster + +* Tue Feb 20 2018 Ivan Devát - 0.9.163-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- Adapted for Rack 2 and Sinatra 2 + +* Fri Feb 09 2018 Igor Gnatenko - 0.9.160-5 +- Escape macros in %%changelog + +* Thu Feb 08 2018 Fedora Release Engineering - 0.9.160-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Sat Jan 20 2018 Björn Esser - 0.9.160-3 +- Rebuilt for switch to libxcrypt + +* Fri Jan 05 2018 Mamoru TASAKA - 0.9.160-2 +- F-28: rebuild for ruby25 +- Workaround for gem install option + +* Wed Oct 18 2017 Ondrej Mular - 0.9.160-1 +- Rebased to latest upstream sources (see CHANGELOG.md) +- All pcs tests are temporarily disabled because of issues in pacemaker. + +* Thu Sep 14 2017 Ondrej Mular - 0.9.159-4 +- Bundle rubygem-rack-protection which is being updated to 2.0.0 in Fedora. +- Removed setuptools patch. +- Disabled debuginfo subpackage. + +* Thu Aug 03 2017 Fedora Release Engineering - 0.9.159-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 0.9.159-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Jul 12 2017 Ondrej Mular - 0.9.159-1 +- Rebased to latest upstream sources (see CHANGELOG.md) + +* Tue May 23 2017 Tomas Jelinek - 0.9.156-3 +- Fixed python locales issue preventing build-time tests to pass +- Bundle rubygem-tilt which is being retired from Fedora + +* Thu Mar 23 2017 Tomas Jelinek - 0.9.156-2 +- Fixed Cross-site scripting (XSS) vulnerability in web UI CVE-2017-2661 +- Re-added support for clufter as it is now available for Python 3 + +* Wed Feb 22 2017 Tomas Jelinek - 0.9.156-1 +- Rebased to latest upstream sources (see CHANGELOG.md) + +* Sat Feb 11 2017 Fedora Release Engineering - 0.9.155-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Jan 12 2017 Vít Ondruch - 0.9.155-2 +- Rebuilt for https://fedoraproject.org/wiki/Changes/Ruby_2.4 + +* Wed Jan 04 2017 Adam Williamson - 0.9.155-1 +- Latest release 0.9.155 +- Fix tests with Python 3.6 and lxml 3.7 +- Package the license as license, not doc +- Use -f param for rm when wiping test directories as they are nested now + +* Mon Dec 19 2016 Miro Hrončok +- Rebuild for Python 3.6 + +* Tue Oct 18 2016 Tomas Jelinek - 0.9.154-2 +- Fixed upgrading from pcs-0.9.150 + +* Thu Sep 22 2016 Tomas Jelinek - 0.9.154-1 +- Re-synced to upstream sources +- Spec file cleanup and fixes + +* Tue Jul 19 2016 Fedora Release Engineering - 0.9.150-2 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Mon Apr 11 2016 Tomas Jelinek - 0.9.150-1 +- Re-synced to upstream sources +- Make pcs depend on python3 +- Spec file cleanup + +* Tue Feb 23 2016 Tomas Jelinek - 0.9.149-2 +- Fixed rubygems issues which prevented pcsd from starting +- Added missing python-lxml dependency + +* Thu Feb 18 2016 Tomas Jelinek - 0.9.149-1 +- Re-synced to upstream sources +- Security fix for CVE-2016-0720, CVE-2016-0721 +- Fixed rubygems issues which prevented pcsd from starting +- Rubygems built with RELRO +- Spec file cleanup +- Fixed multilib .pyc/.pyo issue + +* Thu Feb 04 2016 Fedora Release Engineering - 0.9.144-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Tue Jan 12 2016 Vít Ondruch - 0.9.144-2 +- Rebuilt for https://fedoraproject.org/wiki/Changes/Ruby_2.3 + +* Fri Sep 18 2015 Tomas Jelinek - 0.9.144-1 +- Re-synced to upstream sources + +* Tue Jun 23 2015 Tomas Jelinek - 0.9.141-2 +- Added requirement for psmisc for killall + +* Tue Jun 23 2015 Tomas Jelinek - 0.9.141-1 +- Re-synced to upstream sources + +* Thu Jun 18 2015 Fedora Release Engineering - 0.9.140-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Fri Jun 05 2015 Tomas Jelinek - 0.9.140-1 +- Re-synced to upstream sources + +* Fri May 22 2015 Tomas Jelinek - 0.9.139-4 +- Fix for CVE-2015-1848, CVE-2015-3983 (sessions not signed) + +* Thu Mar 26 2015 Tomas Jelinek - 0.9.139-3 +- Add BuildRequires: systemd (rhbz#1206253) + +* Fri Feb 27 2015 Tomas Jelinek - 0.9.139-2 +- Reflect clufter inclusion (rhbz#1180723) + +* Thu Feb 19 2015 Tomas Jelinek - 0.9.139-1 +- Re-synced to upstream sources + +* Sat Jan 17 2015 Mamoru TASAKA - 0.9.115-5 +- Rebuild for https://fedoraproject.org/wiki/Changes/Ruby_2.2 + +* Sun Aug 17 2014 Fedora Release Engineering - 0.9.115-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Fri Jun 06 2014 Fedora Release Engineering - 0.9.115-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue May 06 2014 Tomas Jelinek - 0.9.115-2 +- Rebuild to fix ruby dependencies + +* Mon Apr 21 2014 Chris Feist - 0.9.115-1 +- Re-synced to upstream sources + +* Fri Dec 13 2013 Chris Feist - 0.9.102-1 +- Re-synced to upstream sources + +* Wed Jun 19 2013 Chris Feist - 0.9.48-1 +- Rebuild with upstream sources + +* Thu Jun 13 2013 Chris Feist - 0.9.44-5 +- Added fixes for building rpam with ruby-2.0.0 + +* Mon Jun 03 2013 Chris Feist - 0.9.44-4 +- Rebuild with upstream sources + +* Tue May 07 2013 Chris Feist - 0.9.41-2 +- Resynced to upstream sources + +* Fri Apr 19 2013 Chris Feist - 0.9.39-1 +- Fixed gem building +- Re-synced to upstream sources + +* Mon Mar 25 2013 Chris Feist - 0.9.36-4 +- Don't try to build gems at all + +* Mon Mar 25 2013 Chris Feist - 0.9.36-3 +- Removed all gems from build, will need to find pam package in the future + +* Mon Mar 25 2013 Chris Feist - 0.9.36-2 +- Removed duplicate libraries already present in fedora + +* Mon Mar 18 2013 Chris Feist - 0.9.36-1 +- Resynced to latest upstream + +* Mon Mar 11 2013 Chris Feist - 0.9.33-1 +- Resynched to latest upstream +- pcsd has been moved to /usr/lib to fix /usr/local packaging issues + +* Thu Feb 21 2013 Chris Feist - 0.9.32-1 +- Resynced to latest version of pcs/pcsd + +* Mon Nov 05 2012 Chris Feist - 0.9.27-3 +- Build on all archs + +* Thu Oct 25 2012 Chris Feist - 0.9.27-2 +- Resync to latest version of pcs +- Added pcsd daemon + +* Mon Oct 08 2012 Chris Feist - 0.9.26-1 +- Resync to latest version of pcs + +* Thu Sep 20 2012 Chris Feist - 0.9.24-1 +- Resync to latest version of pcs + +* Thu Sep 20 2012 Chris Feist - 0.9.23-1 +- Resync to latest version of pcs + +* Wed Sep 12 2012 Chris Feist - 0.9.22-1 +- Resync to latest version of pcs + +* Thu Sep 06 2012 Chris Feist - 0.9.19-1 +- Resync to latest version of pcs + +* Tue Aug 07 2012 Chris Feist - 0.9.12-1 +- Resync to latest version of pcs + +* Fri Jul 20 2012 Fedora Release Engineering - 0.9.3.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu May 24 2012 Chris Feist - 0.9.4-1 +- Resync to latest version of pcs +- Move cluster creation options to cluster sub command. + +* Mon May 07 2012 Chris Feist - 0.9.3.1-1 +- Resync to latest version of pcs which includes fixes to work with F17. + +* Mon Mar 19 2012 Chris Feist - 0.9.2.4-1 +- Resynced to latest version of pcs + +* Mon Jan 23 2012 Chris Feist - 0.9.1-1 +- Updated BuildRequires and %%doc section for fedora + +* Fri Jan 20 2012 Chris Feist - 0.9.0-2 +- Updated spec file for fedora specific changes + +* Mon Jan 16 2012 Chris Feist - 0.9.0-1 +- Initial Build