From 3dc1535cc5a2cfd33ead5aaf5c91738fd4116224 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 15 Nov 2022 01:34:36 -0500 Subject: [PATCH] import fence-agents-4.10.0-30.el9 --- .fence-agents.metadata | 99 + .gitignore | 99 + SOURCES/bundled-pexpect.patch | 358 ++++ SOURCES/bundled-suds.patch | 10 + SOURCES/bz2000954-1-configure-fix-virt.patch | 24 + SOURCES/bz2000954-2-fence_kubevirt.patch | 160 ++ ..._kubevirt-get-namespace-from-context.patch | 102 + ..._arm-fix-sovereign-cloud-msi-support.patch | 139 ++ ...ence_amt_ws-fix-or-causing-dead-code.patch | 22 + ...bz2010709-2-fence_amt_ws-boot-option.patch | 32 + ...z2022334-fence_zvmip-add-disable-ssl.patch | 98 + ...2334-fence_zvmip-add-ssl-tls-support.patch | 136 ++ ...1-1-fence_openstack-add-ssl-insecure.patch | 72 + ...791-2-fence_openstack-cacert-default.patch | 59 + ...1935-1-fence_openstack-clouds-openrc.patch | 313 +++ ...1935-2-fence_openstack-clouds-openrc.patch | 171 ++ ...-source_env-dont-process-empty-lines.patch | 22 + ...2496-fence_ibm_vpc-fence_ibm_powervs.patch | 740 +++++++ SOURCES/bz2065114-fence_lpar-refactor.patch | 65 + ...20-1-all-agents-unify-ssl-parameters.patch | 291 +++ ...z2072420-2-fence_zvmip-connect-error.patch | 30 + SOURCES/bz2079889-fence_gce-update.patch | 410 ++++ ...2081235-fence_ibm_vpc-fix-parameters.patch | 65 + ...pc-fence_ilo_moonshot-import-logging.patch | 34 + ...2385-fence_ibm_vpc-add-proxy-support.patch | 62 + ...bm_powervs-proxy-private-api-servers.patch | 455 +++++ SOURCES/ha-cloud-support-aliyun.patch | 10 + SOURCES/ha-cloud-support-aws.patch | 10 + SOURCES/ha-cloud-support-azure.patch | 12 + SOURCES/ha-cloud-support-google.patch | 21 + SOURCES/requirements-aliyun.txt | 3 + SOURCES/requirements-aws.txt | 2 + SOURCES/requirements-azure.txt | 3 + SOURCES/requirements-common.txt | 2 + SOURCES/requirements-google.txt | 4 + SPECS/fence-agents.spec | 1743 +++++++++++++++++ 36 files changed, 5878 insertions(+) create mode 100644 .fence-agents.metadata create mode 100644 .gitignore create mode 100644 SOURCES/bundled-pexpect.patch create mode 100644 SOURCES/bundled-suds.patch create mode 100644 SOURCES/bz2000954-1-configure-fix-virt.patch create mode 100644 SOURCES/bz2000954-2-fence_kubevirt.patch create mode 100644 SOURCES/bz2000954-3-fence_kubevirt-get-namespace-from-context.patch create mode 100644 SOURCES/bz2010652-fence_azure_arm-fix-sovereign-cloud-msi-support.patch create mode 100644 SOURCES/bz2010709-1-fence_amt_ws-fix-or-causing-dead-code.patch create mode 100644 SOURCES/bz2010709-2-fence_amt_ws-boot-option.patch create mode 100644 SOURCES/bz2022334-fence_zvmip-add-disable-ssl.patch create mode 100644 SOURCES/bz2022334-fence_zvmip-add-ssl-tls-support.patch create mode 100644 SOURCES/bz2029791-1-fence_openstack-add-ssl-insecure.patch create mode 100644 SOURCES/bz2029791-2-fence_openstack-cacert-default.patch create mode 100644 SOURCES/bz2041933-bz2041935-1-fence_openstack-clouds-openrc.patch create mode 100644 SOURCES/bz2041933-bz2041935-2-fence_openstack-clouds-openrc.patch create mode 100644 SOURCES/bz2041933-bz2041935-3-fencing-source_env-dont-process-empty-lines.patch create mode 100644 SOURCES/bz2042496-fence_ibm_vpc-fence_ibm_powervs.patch create mode 100644 SOURCES/bz2065114-fence_lpar-refactor.patch create mode 100644 SOURCES/bz2072420-1-all-agents-unify-ssl-parameters.patch create mode 100644 SOURCES/bz2072420-2-fence_zvmip-connect-error.patch create mode 100644 SOURCES/bz2079889-fence_gce-update.patch create mode 100644 SOURCES/bz2081235-fence_ibm_vpc-fix-parameters.patch create mode 100644 SOURCES/bz2086559-fence_apc-fence_ilo_moonshot-import-logging.patch create mode 100644 SOURCES/bz2092385-fence_ibm_vpc-add-proxy-support.patch create mode 100644 SOURCES/bz2093216-fence_ibm_powervs-proxy-private-api-servers.patch create mode 100644 SOURCES/ha-cloud-support-aliyun.patch create mode 100644 SOURCES/ha-cloud-support-aws.patch create mode 100644 SOURCES/ha-cloud-support-azure.patch create mode 100644 SOURCES/ha-cloud-support-google.patch create mode 100644 SOURCES/requirements-aliyun.txt create mode 100644 SOURCES/requirements-aws.txt create mode 100644 SOURCES/requirements-azure.txt create mode 100644 SOURCES/requirements-common.txt create mode 100644 SOURCES/requirements-google.txt create mode 100644 SPECS/fence-agents.spec diff --git a/.fence-agents.metadata b/.fence-agents.metadata new file mode 100644 index 0000000..8cb773a --- /dev/null +++ b/.fence-agents.metadata @@ -0,0 +1,99 @@ +3297473a9d57e93ff378eab173990c1b64673c01 SOURCES/Jinja2-3.0.2.tar.gz +e1b766b2b1601fde67b3b19ed2f13b9746bb1cca SOURCES/MarkupSafe-2.0.1.tar.gz +e1fb5dc6f95a85e7d1f93c6701b331201e8b5479 SOURCES/PyJWT-2.1.0-py3-none-any.whl +53fc16036940089ceadd4127381e40fd6106a7ed SOURCES/PyYAML-5.1.tar.gz +b53cba68215f389dffaa51ee2afe10c943278646 SOURCES/adal-1.2.7-py2.py3-none-any.whl +bda476965c380701795849179ed91e9d8134ec7c SOURCES/aliyun-python-sdk-core-2.11.5.tar.gz +2a3e6ee5713a3cfb47e63a739cc9a05580d95dd6 SOURCES/aliyun_python_sdk_ecs-4.24.7-py2.py3-none-any.whl +32a9b6bff51343ab89221da66f6f67ba798ddcd6 SOURCES/aliyuncli-2.1.10-py2.py3-none-any.whl +459383a3bcb16956030e302008a0f140a5fec0fb SOURCES/awscli-2.2.15.tar.gz +a08c16f613cb0b9a9f8ce7cae782ea20c40ce2af SOURCES/awscrt-0.11.13-cp39-cp39-manylinux2014_x86_64.whl +70a8e279429feaa0ed39bf2da123e5d53c37b0e6 SOURCES/azure_common-1.1.27-py2.py3-none-any.whl +63fee5e61283d1c972abd3786ed609da6fd7ea5b SOURCES/azure_core-1.15.0-py2.py3-none-any.whl +584ff1897b56673bee12e77aec07e68ebe9f789b SOURCES/azure_mgmt_compute-21.0.0-py2.py3-none-any.whl +e20df6c9635f1db9a3c891b9239b4319d88b1747 SOURCES/azure_mgmt_core-1.2.2-py2.py3-none-any.whl +3bb341e87329c7507863f0ec53f8cb6e16d698d6 SOURCES/azure_mgmt_network-19.0.0-py2.py3-none-any.whl +6591882be0937b2b900eab4ec70feadf34f71738 SOURCES/boto3-1.17.102-py2.py3-none-any.whl +22507f43314ccb2dd203337e87ffafb385ba3627 SOURCES/botocore-1.20.102-py2.py3-none-any.whl +6ef53a76455b377b02b4774c32a04e241cdb24eb SOURCES/botocore-2.0.0dev123.zip +c953dcd6e69587e5b182d77255ed836172fea70a SOURCES/cachetools-4.2.2-py3-none-any.whl +0d12f48faa727f0979e9ad5c4c80dfa32b73caff SOURCES/cachetools-4.2.4.tar.gz +b13e22d55867e2ca5f92e5289cfdc21ba6e343aa SOURCES/certifi-2021.10.8.tar.gz +2fcaa39108a9c99700c6f3f4198fcaa47b8ed707 SOURCES/certifi-2021.5.30-py2.py3-none-any.whl +17953cc85717e0f4501dbc7b5fb8e75d67dcdcd3 SOURCES/cffi-1.14.5-cp39-cp39-manylinux1_x86_64.whl +96faab7de7e9a71b37f22adb64daf2898e967e3e SOURCES/chardet-3.0.4-py2.py3-none-any.whl +e9eb83c71c09b3c8249bd7d6d2619b65fff03874 SOURCES/chardet-4.0.0-py2.py3-none-any.whl +865df92e66e5dc7b940144cbad8115c07dc8784f SOURCES/charset-normalizer-2.0.7.tar.gz +a8ee91adf4644bbdccfc73ead88f4cd0df7e3552 SOURCES/colorama-0.3.3.tar.gz +444d5ea320f95cd6205535a1be2805598847191b SOURCES/colorama-0.4.3-py2.py3-none-any.whl +536a57d70d505e4de8595650603d7e2ecc58b34b SOURCES/cryptography-3.3.2-cp36-abi3-manylinux2010_x86_64.whl +4b50bebad4c5036c030a78cbb869d039bc91c4ec SOURCES/distro-1.5.0-py2.py3-none-any.whl +aafeddc912b74557754b2aaece3f1364be8e9f6a SOURCES/docutils-0.15.2-py3-none-any.whl +1ec823f807b73a377cdd47d12e2e34f046bfc889 SOURCES/fence-agents-4.10.0.tar.gz +f4e578dc0ed68d6667d7b36cdfc2647d55e9858f SOURCES/google-auth-2.3.0.tar.gz +ac160113ba8b78b0688edda9f9a088c0b4b5ded2 SOURCES/google_api_core-1.30.0-py2.py3-none-any.whl +4fd1eb2b927767158e91e369de441fd9221a82d9 SOURCES/google_api_python_client-1.12.8-py2.py3-none-any.whl +4a3a5ddc3d1ded24279b89d4ea0c8796f6c2598a SOURCES/google_auth-1.32.0-py2.py3-none-any.whl +9e513ce4e7b36b8e81c607be440e0d6e6afe9833 SOURCES/google_auth_httplib2-0.1.0-py2.py3-none-any.whl +dc553afa7a3f23b92ee9ecd27d0b15153c0e9f75 SOURCES/googleapis_common_protos-1.53.0-py2.py3-none-any.whl +74ec77d2e2ef6b2ef8503e6e398faa6f3ba298ae SOURCES/httplib2-0.19.1-py3-none-any.whl +999b6718b4d789d8ca0d2ddf7c07826154291825 SOURCES/idna-2.10-py2.py3-none-any.whl +08c0449533fc94462f78652dea209099754d9ee4 SOURCES/idna-3.3.tar.gz +240cc4206740fafacb74bbf0d0c4ff70e41c8a85 SOURCES/isodate-0.6.0-py2.py3-none-any.whl +68904717c48e95adb47d815178fff8d80f39b2ab SOURCES/jmespath-0.7.1-py2.py3-none-any.whl +d06a9547b1a87e9c51b0a7c708189d993f2e3d89 SOURCES/kubernetes-12.0.1.tar.gz +ba59fbd147307e7ef92a1fad259e7dc0b07e79e0 SOURCES/msrest-0.6.21-py2.py3-none-any.whl +3d65a50b68e3aa506b6af42be485ed2710afa9da SOURCES/msrestazure-0.6.4-py2.py3-none-any.whl +0b5ba4c47bdd7ff17ca4954349d7213a95d03f25 SOURCES/oauthlib-3.1.1-py2.py3-none-any.whl +f6efa66f6106b069b5c0e0cf8cc677e4e96c91ca SOURCES/oauthlib-3.1.1.tar.gz +570d69d8c108ebb8aee562389d13b07dfb61ce25 SOURCES/openshift-0.12.1.tar.gz +2b10cb7681bc678ba4ff3be524b28d783e4095ce SOURCES/packaging-20.9-py2.py3-none-any.whl +bccbc1bf76a9db46998eb8e1ffa2f2a2baf9237a SOURCES/packaging-21.2-py3-none-any.whl +0c3fc83ca045abeec9ce82bb7ee3e77f0390bca4 SOURCES/pexpect-4.8.0-py2.py3-none-any.whl +18659a0dea5600df33eab90dec1b597e2437aebd SOURCES/poetry-core-1.0.7.tar.gz +b09c4655a4c8bd24c54a078e960750ec9e8688d6 SOURCES/prompt_toolkit-2.0.10-py3-none-any.whl +5a90b79a9630873c7f2db79544c46146bb6af5e8 SOURCES/protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl +0827aaa6fdc3dc4256e06fa1c3991fb4ed20a693 SOURCES/ptyprocess-0.7.0-py2.py3-none-any.whl +c3c9f195dc89eb6d04828b881314743b548318d0 SOURCES/pyasn1-0.4.8-py2.py3-none-any.whl +e0fa19f8fda46a1fa2253477499b116b33f67175 SOURCES/pyasn1-0.4.8.tar.gz +43b89feb6864fe359aae89120627165219de313b SOURCES/pyasn1-modules-0.2.8.tar.gz +d77aa46abbcaccc4054a0777a191e427c785c65a SOURCES/pyasn1_modules-0.2.8-py2.py3-none-any.whl +a0df3ebc552b551f8e99a05cf0a29ce30bef62ee SOURCES/pycparser-2.20-py2.py3-none-any.whl +df33feb2a14904c0461b5dcc3ca31f910206e7bd SOURCES/pycryptodome-3.10.1-cp35-abi3-manylinux2010_x86_64.whl +c8307f47e3b75a2d02af72982a2dfefa3f56e407 SOURCES/pyparsing-2.4.7-py2.py3-none-any.whl +6082312a090f5be5e796e0854294da0738ec0379 SOURCES/pyparsing-3.0.1.tar.gz +24213006f983ada342ed86ea516028fdbb1ac66f SOURCES/pyroute2-0.6.4.tar.gz +a052fefd7a93e1e4b2ca87c6a6c242ae70f97489 SOURCES/pyroute2.core-0.6.4.tar.gz +e58f6fa56f1baf766ba147dbc9fbfc67fa92e234 SOURCES/pyroute2.ethtool-0.6.4.tar.gz +9de1b2825454872697339a63f4d6d06a5167fb73 SOURCES/pyroute2.ipdb-0.6.4.tar.gz +4ce5ab32674f3d2652e2f102b2502af4d499ba6a SOURCES/pyroute2.ipset-0.6.4.tar.gz +7dc3c981c9c991990647b74e670115395675fe04 SOURCES/pyroute2.ndb-0.6.4.tar.gz +281fe514b28e096f9deb1121ee8340976f47e8c0 SOURCES/pyroute2.nftables-0.6.4.tar.gz +7ecab830b1978fbd07d565872731268169847bc4 SOURCES/pyroute2.nslink-0.6.4.tar.gz +c2ba10c775b7a52a4b57cac4d4110a0c0f812a82 SOURCES/python-dateutil-2.8.2.tar.gz +1dc2fa004aa6517f1620e55d8a7b8e68a9cf2a47 SOURCES/python-string-utils-1.0.0.tar.gz +3005ff67df93ee276fb8631e17c677df852254ad SOURCES/python_dateutil-2.8.1-py2.py3-none-any.whl +b97c6966fb8fd273f0bc8533cf0dee4978b9f373 SOURCES/pytz-2021.1-py2.py3-none-any.whl +b1009d9fd6acadc64e1a3cecb6f0083fe047e753 SOURCES/requests-2.25.1-py2.py3-none-any.whl +8c7a89d183d3e9b70bf91ba5b75eccf7111b9d8d SOURCES/requests-2.26.0.tar.gz +f139aed770519b6a095b8fdc888d03955cbe9d8e SOURCES/requests-oauthlib-1.3.0.tar.gz +25d5667d7a61586f5ddaac7e08cc3053db3d8661 SOURCES/requests_oauthlib-1.3.0-py2.py3-none-any.whl +c0d5be2edf538122d35fe06c29d2d7a5f22f3117 SOURCES/rsa-4.7.2-py3-none-any.whl +e8a53067e03fe1b6682fd99a40a7359396a06daa SOURCES/rsa-4.7.2.tar.gz +abf532a0cc31ea224e3895f60025e7466b16d7ae SOURCES/ruamel.yaml-0.15.100.tar.gz +d1011ff44cd5a045de0460c1b79ec65592e86860 SOURCES/ruamel.yaml-0.17.16.tar.gz +27de97227bbbde5a9f571f9fad223578d7bdf7cc SOURCES/ruamel.yaml.clib-0.2.6.tar.gz +d7eb0ced8b9f12005ad6f13035689d5611f8a81a SOURCES/s3transfer-0.4.2-py2.py3-none-any.whl +0b0fcb339be89ae1b6360dbfb2be2075ae9f84c9 SOURCES/setuptools-57.0.0-py3-none-any.whl +d5354718cb8c9330d3abc27445467ce8a5ed9d70 SOURCES/setuptools-58.3.0.tar.gz +a4f02fddae697614e356cadfddb6241cc7737f38 SOURCES/setuptools_scm-6.3.2.tar.gz +79e6f2e4f9e24898f1896df379871b9c9922f147 SOURCES/six-1.16.0-py2.py3-none-any.whl +06fa0bb50f2a4e2917fd14c21e9d2d5508ce0163 SOURCES/six-1.16.0.tar.gz +47a980b20875d1a1714e921552b5bb0eda190f37 SOURCES/suds_community-0.8.5-py3-none-any.whl +b42b7960047441db7dc021cc20e14279bd836f8d SOURCES/tomli-1.0.1.tar.gz +83be56610e5f824bb05ff7a5618d6d4df9b6cc08 SOURCES/uritemplate-3.0.1-py2.py3-none-any.whl +206b17697417cbf5fc55f1e39c7ceb2197fe3e63 SOURCES/urllib3-1.26.6-py2.py3-none-any.whl +eb35c3fd8b0867ae988a15917d6b80e8bdf60222 SOURCES/urllib3-1.26.7.tar.gz +7126323614cada181bc8b06436e80ef372ff8656 SOURCES/wcwidth-0.1.9-py2.py3-none-any.whl +540f083782c584989c1a0f69ffd69ba7aae07db6 SOURCES/websocket-client-1.2.1.tar.gz +b6c48d8714e043524be7a869d1db0adcd8441cd4 SOURCES/wheel-0.37.0-py2.py3-none-any.whl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5857b7c --- /dev/null +++ b/.gitignore @@ -0,0 +1,99 @@ +SOURCES/Jinja2-3.0.2.tar.gz +SOURCES/MarkupSafe-2.0.1.tar.gz +SOURCES/PyJWT-2.1.0-py3-none-any.whl +SOURCES/PyYAML-5.1.tar.gz +SOURCES/adal-1.2.7-py2.py3-none-any.whl +SOURCES/aliyun-python-sdk-core-2.11.5.tar.gz +SOURCES/aliyun_python_sdk_ecs-4.24.7-py2.py3-none-any.whl +SOURCES/aliyuncli-2.1.10-py2.py3-none-any.whl +SOURCES/awscli-2.2.15.tar.gz +SOURCES/awscrt-0.11.13-cp39-cp39-manylinux2014_x86_64.whl +SOURCES/azure_common-1.1.27-py2.py3-none-any.whl +SOURCES/azure_core-1.15.0-py2.py3-none-any.whl +SOURCES/azure_mgmt_compute-21.0.0-py2.py3-none-any.whl +SOURCES/azure_mgmt_core-1.2.2-py2.py3-none-any.whl +SOURCES/azure_mgmt_network-19.0.0-py2.py3-none-any.whl +SOURCES/boto3-1.17.102-py2.py3-none-any.whl +SOURCES/botocore-1.20.102-py2.py3-none-any.whl +SOURCES/botocore-2.0.0dev123.zip +SOURCES/cachetools-4.2.2-py3-none-any.whl +SOURCES/cachetools-4.2.4.tar.gz +SOURCES/certifi-2021.10.8.tar.gz +SOURCES/certifi-2021.5.30-py2.py3-none-any.whl +SOURCES/cffi-1.14.5-cp39-cp39-manylinux1_x86_64.whl +SOURCES/chardet-3.0.4-py2.py3-none-any.whl +SOURCES/chardet-4.0.0-py2.py3-none-any.whl +SOURCES/charset-normalizer-2.0.7.tar.gz +SOURCES/colorama-0.3.3.tar.gz +SOURCES/colorama-0.4.3-py2.py3-none-any.whl +SOURCES/cryptography-3.3.2-cp36-abi3-manylinux2010_x86_64.whl +SOURCES/distro-1.5.0-py2.py3-none-any.whl +SOURCES/docutils-0.15.2-py3-none-any.whl +SOURCES/fence-agents-4.10.0.tar.gz +SOURCES/google-auth-2.3.0.tar.gz +SOURCES/google_api_core-1.30.0-py2.py3-none-any.whl +SOURCES/google_api_python_client-1.12.8-py2.py3-none-any.whl +SOURCES/google_auth-1.32.0-py2.py3-none-any.whl +SOURCES/google_auth_httplib2-0.1.0-py2.py3-none-any.whl +SOURCES/googleapis_common_protos-1.53.0-py2.py3-none-any.whl +SOURCES/httplib2-0.19.1-py3-none-any.whl +SOURCES/idna-2.10-py2.py3-none-any.whl +SOURCES/idna-3.3.tar.gz +SOURCES/isodate-0.6.0-py2.py3-none-any.whl +SOURCES/jmespath-0.7.1-py2.py3-none-any.whl +SOURCES/kubernetes-12.0.1.tar.gz +SOURCES/msrest-0.6.21-py2.py3-none-any.whl +SOURCES/msrestazure-0.6.4-py2.py3-none-any.whl +SOURCES/oauthlib-3.1.1-py2.py3-none-any.whl +SOURCES/oauthlib-3.1.1.tar.gz +SOURCES/openshift-0.12.1.tar.gz +SOURCES/packaging-20.9-py2.py3-none-any.whl +SOURCES/packaging-21.2-py3-none-any.whl +SOURCES/pexpect-4.8.0-py2.py3-none-any.whl +SOURCES/poetry-core-1.0.7.tar.gz +SOURCES/prompt_toolkit-2.0.10-py3-none-any.whl +SOURCES/protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl +SOURCES/ptyprocess-0.7.0-py2.py3-none-any.whl +SOURCES/pyasn1-0.4.8-py2.py3-none-any.whl +SOURCES/pyasn1-0.4.8.tar.gz +SOURCES/pyasn1-modules-0.2.8.tar.gz +SOURCES/pyasn1_modules-0.2.8-py2.py3-none-any.whl +SOURCES/pycparser-2.20-py2.py3-none-any.whl +SOURCES/pycryptodome-3.10.1-cp35-abi3-manylinux2010_x86_64.whl +SOURCES/pyparsing-2.4.7-py2.py3-none-any.whl +SOURCES/pyparsing-3.0.1.tar.gz +SOURCES/pyroute2-0.6.4.tar.gz +SOURCES/pyroute2.core-0.6.4.tar.gz +SOURCES/pyroute2.ethtool-0.6.4.tar.gz +SOURCES/pyroute2.ipdb-0.6.4.tar.gz +SOURCES/pyroute2.ipset-0.6.4.tar.gz +SOURCES/pyroute2.ndb-0.6.4.tar.gz +SOURCES/pyroute2.nftables-0.6.4.tar.gz +SOURCES/pyroute2.nslink-0.6.4.tar.gz +SOURCES/python-dateutil-2.8.2.tar.gz +SOURCES/python-string-utils-1.0.0.tar.gz +SOURCES/python_dateutil-2.8.1-py2.py3-none-any.whl +SOURCES/pytz-2021.1-py2.py3-none-any.whl +SOURCES/requests-2.25.1-py2.py3-none-any.whl +SOURCES/requests-2.26.0.tar.gz +SOURCES/requests-oauthlib-1.3.0.tar.gz +SOURCES/requests_oauthlib-1.3.0-py2.py3-none-any.whl +SOURCES/rsa-4.7.2-py3-none-any.whl +SOURCES/rsa-4.7.2.tar.gz +SOURCES/ruamel.yaml-0.15.100.tar.gz +SOURCES/ruamel.yaml-0.17.16.tar.gz +SOURCES/ruamel.yaml.clib-0.2.6.tar.gz +SOURCES/s3transfer-0.4.2-py2.py3-none-any.whl +SOURCES/setuptools-57.0.0-py3-none-any.whl +SOURCES/setuptools-58.3.0.tar.gz +SOURCES/setuptools_scm-6.3.2.tar.gz +SOURCES/six-1.16.0-py2.py3-none-any.whl +SOURCES/six-1.16.0.tar.gz +SOURCES/suds_community-0.8.5-py3-none-any.whl +SOURCES/tomli-1.0.1.tar.gz +SOURCES/uritemplate-3.0.1-py2.py3-none-any.whl +SOURCES/urllib3-1.26.6-py2.py3-none-any.whl +SOURCES/urllib3-1.26.7.tar.gz +SOURCES/wcwidth-0.1.9-py2.py3-none-any.whl +SOURCES/websocket-client-1.2.1.tar.gz +SOURCES/wheel-0.37.0-py2.py3-none-any.whl diff --git a/SOURCES/bundled-pexpect.patch b/SOURCES/bundled-pexpect.patch new file mode 100644 index 0000000..41f355d --- /dev/null +++ b/SOURCES/bundled-pexpect.patch @@ -0,0 +1,358 @@ +diff --color -uNr a/agents/azure_arm/fence_azure_arm.py b/agents/azure_arm/fence_azure_arm.py +--- a/agents/azure_arm/fence_azure_arm.py 2020-06-30 11:26:43.000000000 +0200 ++++ b/agents/azure_arm/fence_azure_arm.py 2021-06-03 13:16:16.547120822 +0200 +@@ -1,6 +1,11 @@ + #!@PYTHON@ -tt + +-import sys, re, pexpect ++import sys, re ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import logging + import atexit + import xml.etree.ElementTree as ET +diff --color -uNr a/agents/hpblade/fence_hpblade.py b/agents/hpblade/fence_hpblade.py +--- a/agents/hpblade/fence_hpblade.py 2019-08-16 10:55:11.000000000 +0200 ++++ b/agents/hpblade/fence_hpblade.py 2021-06-03 13:16:16.547120822 +0200 +@@ -8,7 +8,11 @@ + ##### + + import sys, re +-import pexpect ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +diff --color -uNr a/agents/ilo/fence_ilo.py b/agents/ilo/fence_ilo.py +--- a/agents/ilo/fence_ilo.py 2019-02-04 09:45:05.000000000 +0100 ++++ b/agents/ilo/fence_ilo.py 2021-06-03 13:16:16.547120822 +0200 +@@ -11,7 +11,12 @@ + ## iLO2 / firmware 1.50 / RIBCL 2.22 + ##### + +-import sys, re, pexpect ++import sys, re ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import atexit + from xml.sax.saxutils import quoteattr + sys.path.append("@FENCEAGENTSLIBDIR@") +diff --color -uNr a/agents/ldom/fence_ldom.py b/agents/ldom/fence_ldom.py +--- a/agents/ldom/fence_ldom.py 2019-02-04 09:45:05.000000000 +0100 ++++ b/agents/ldom/fence_ldom.py 2021-06-03 13:16:16.547120822 +0200 +@@ -7,7 +7,12 @@ + ## + ##### + +-import sys, re, pexpect ++import sys, re ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +diff --color -uNr a/agents/Makefile.am b/agents/Makefile.am +--- a/agents/Makefile.am 2021-03-16 12:26:37.000000000 +0100 ++++ b/agents/Makefile.am 2021-06-03 13:16:16.547120822 +0200 +@@ -112,10 +112,10 @@ + cisco_mds/fence_cisco_mds.delay-check: cisco_mds/fence_cisco_mds + $(eval INPUT=$(subst .delay-check,,$@)) + FENCE_TEST_ARGS_CISCO_MDS=$$(printf '$(FENCE_TEST_ARGS)' | sed 's#port=1#port=fc1/1#'); \ +- test `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib /usr/bin/time -p \ ++ test `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common /usr/bin/time -p \ + sh -c "printf 'delay=10\n $$FENCE_TEST_ARGS_CISCO_MDS' | $(PYTHON) ./$(INPUT)" 2>&1 |\ + awk -F"[. ]" -vOFS= '/real/ {print $$2,$$3}'` -ge 1000 || ( \ +- PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib /usr/bin/time -p \ ++ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common /usr/bin/time -p \ + sh -c "printf "delay=0\n $$FENCE_TEST_ARGS_CISCO_MDS" | $(PYTHON) ./$(INPUT)"; false ) + + include $(top_srcdir)/make/fencebuild.mk +diff --color -uNr a/agents/netio/fence_netio.py b/agents/netio/fence_netio.py +--- a/agents/netio/fence_netio.py 2019-02-04 09:45:05.000000000 +0100 ++++ b/agents/netio/fence_netio.py 2021-06-03 13:16:16.547120822 +0200 +@@ -1,6 +1,11 @@ + #!@PYTHON@ -tt + +-import sys, re, pexpect ++import sys, re ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +diff --color -uNr a/agents/raritan/fence_raritan.py b/agents/raritan/fence_raritan.py +--- a/agents/raritan/fence_raritan.py 2019-08-16 10:55:11.000000000 +0200 ++++ b/agents/raritan/fence_raritan.py 2021-06-03 13:16:16.547120822 +0200 +@@ -1,6 +1,11 @@ + #!@PYTHON@ -tt + +-import sys, re, pexpect ++import sys, re ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +diff --color -uNr a/agents/sanbox2/fence_sanbox2.py b/agents/sanbox2/fence_sanbox2.py +--- a/agents/sanbox2/fence_sanbox2.py 2019-02-11 13:05:48.000000000 +0100 ++++ b/agents/sanbox2/fence_sanbox2.py 2021-06-03 13:16:16.547120822 +0200 +@@ -8,7 +8,12 @@ + ## +-----------------+---------------------------+ + ##### + +-import sys, re, pexpect ++import sys, re ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import logging + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") +diff --color -uNr a/agents/vmware/fence_vmware.py b/agents/vmware/fence_vmware.py +--- a/agents/vmware/fence_vmware.py 2019-02-04 09:45:05.000000000 +0100 ++++ b/agents/vmware/fence_vmware.py 2021-06-03 13:16:16.547120822 +0200 +@@ -22,7 +22,12 @@ + # VMware vCenter 4.0.0 + # + +-import sys, re, pexpect ++import sys, re ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import logging + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") +diff --color -uNr a/agents/wti/fence_wti.py b/agents/wti/fence_wti.py +--- a/agents/wti/fence_wti.py 2019-02-04 09:45:05.000000000 +0100 ++++ b/agents/wti/fence_wti.py 2021-06-03 13:17:33.435380703 +0200 +@@ -11,12 +11,21 @@ + ## WTI IPS-800-CE v1.40h (no username) ('list' tested) + ##### + +-import sys, re, pexpect ++import sys, re ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass + import atexit + import time + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +-from fencing import fspawn, fail, fail_usage, EC_LOGIN_DENIED ++from fencing import fail, fail_usage, EC_LOGIN_DENIED ++try: ++ from fencing import fspawn ++except ImportError: ++ pass + + def get_listing(conn, options, listing_command): + listing = "" +diff --color -uNr a/lib/fencing.py.py b/lib/fencing.py.py +--- a/lib/fencing.py.py 2021-06-03 10:34:00.000000000 +0200 ++++ b/lib/fencing.py.py 2021-06-03 13:16:16.548120826 +0200 +@@ -1,7 +1,12 @@ + #!@PYTHON@ -tt + + import sys, getopt, time, os, uuid, pycurl, stat +-import pexpect, re, syslog ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass ++import re, syslog + import logging + import subprocess + import threading +@@ -491,29 +496,32 @@ + "snmpset_path", "snmpget_path", "snmpwalk_path"] + } + +-class fspawn(pexpect.spawn): +- def __init__(self, options, command, **kwargs): +- if sys.version_info[0] > 2: +- kwargs.setdefault('encoding', 'utf-8') +- logging.info("Running command: %s", command) +- pexpect.spawn.__init__(self, command, **kwargs) +- self.opt = options +- +- def log_expect(self, pattern, timeout): +- result = self.expect(pattern, timeout if timeout != 0 else None) +- logging.debug("Received: %s", self.before + self.after) +- return result +- +- def read_nonblocking(self, size, timeout): +- return pexpect.spawn.read_nonblocking(self, size=100, timeout=timeout if timeout != 0 else None) +- +- def send(self, message): +- logging.debug("Sent: %s", message) +- return pexpect.spawn.send(self, message) +- +- # send EOL according to what was detected in login process (telnet) +- def send_eol(self, message): +- return self.send(message + self.opt["eol"]) ++try: ++ class fspawn(pexpect.spawn): ++ def __init__(self, options, command, **kwargs): ++ if sys.version_info[0] > 2: ++ kwargs.setdefault('encoding', 'utf-8') ++ logging.info("Running command: %s", command) ++ pexpect.spawn.__init__(self, command, **kwargs) ++ self.opt = options ++ ++ def log_expect(self, pattern, timeout): ++ result = self.expect(pattern, timeout if timeout != 0 else None) ++ logging.debug("Received: %s", self.before + self.after) ++ return result ++ ++ def read_nonblocking(self, size, timeout): ++ return pexpect.spawn.read_nonblocking(self, size=100, timeout=timeout if timeout != 0 else None) ++ ++ def send(self, message): ++ logging.debug("Sent: %s", message) ++ return pexpect.spawn.send(self, message) ++ ++ # send EOL according to what was detected in login process (telnet) ++ def send_eol(self, message): ++ return self.send(message + self.opt["eol"]) ++except: ++ pass + + def frun(command, timeout=30, withexitstatus=False, events=None, + extra_args=None, logfile=None, cwd=None, env=None, **kwargs): +diff --color -uNr a/lib/fencing_snmp.py.py b/lib/fencing_snmp.py.py +--- a/lib/fencing_snmp.py.py 2019-02-04 09:45:05.000000000 +0100 ++++ b/lib/fencing_snmp.py.py 2021-06-03 13:16:16.548120826 +0200 +@@ -2,7 +2,13 @@ + + # For example of use please see fence_cisco_mds + +-import re, pexpect ++import sys ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') ++try: ++ import pexpect ++except: ++ pass ++import re + import logging + from fencing import * + from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay, frun +diff --color -uNr a/make/agentpycheck.mk b/make/agentpycheck.mk +--- a/make/agentpycheck.mk 2020-06-30 11:26:43.000000000 +0200 ++++ b/make/agentpycheck.mk 2021-06-03 13:16:16.548120826 +0200 +@@ -9,34 +9,34 @@ + + %.xml-check: %.8 + $(eval INPUT=$(subst .xml-check,,$(@F))) +- for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ ++ for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ + TEMPFILE=$$(mktemp); \ +- PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$$x -o metadata | $(AWK) $(AWK_VAL) > $$TEMPFILE && \ ++ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(@D)/$$x -o metadata | $(AWK) $(AWK_VAL) > $$TEMPFILE && \ + diff $$TEMPFILE $(DATADIR)/$$x.xml || exit 1 && \ + rm $$TEMPFILE; \ + done + + %.xml-upload: %.8 + $(eval INPUT=$(subst .xml-upload,,$(@F))) +- for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ +- PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$$x -o metadata | $(AWK) $(AWK_VAL) > $(DATADIR)/$$x.xml; \ ++ for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ ++ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(@D)/$$x -o metadata | $(AWK) $(AWK_VAL) > $(DATADIR)/$$x.xml; \ + done + + # If test will fail, rerun fence agents to show problems + %.delay-check: % + $(eval INPUT=$(subst .delay-check,,$(@F))) +- for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ +- test `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib /usr/bin/time -p \ ++ for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ ++ test `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common /usr/bin/time -p \ + sh -c "printf 'delay=10\n $(FENCE_TEST_ARGS)' | $(PYTHON) $(@D)/$$x" 2>&1 |\ + awk -F"[. ]" -vOFS= '/real/ {print $$2,$$3}'` -ge 1000 || ( \ +- PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib /usr/bin/time -p \ ++ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common /usr/bin/time -p \ + sh -c "printf 'delay=0\n $(FENCE_TEST_ARGS)' | $(PYTHON) $(@D)/$$x"; false ); \ + done + + %.rng-check: % + $(eval INPUT=$(subst .rng-check,,$(@F))) +- for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ +- PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$$x -o metadata | \ ++ for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ ++ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(@D)/$$x -o metadata | \ + xsltproc ${abs_top_srcdir}/lib/fence2rng.xsl - | \ + sed -e 's/ rha:description=/ description=/g' -e 's/ rha:name=/ name=/g' | \ + xmllint --nsclean --noout -; \ +diff --color -uNr a/make/fencebuild.mk b/make/fencebuild.mk +--- a/make/fencebuild.mk 2021-03-16 09:32:22.000000000 +0100 ++++ b/make/fencebuild.mk 2021-06-03 13:16:16.548120826 +0200 +@@ -34,10 +34,10 @@ + > $@ + + if [ 0 -eq `echo "$(@)" | grep fence_ > /dev/null 2>&1; echo $$?` ]; then \ +- PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(top_srcdir)/lib/check_used_options.py $@; \ ++ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(top_srcdir)/lib/check_used_options.py $@; \ + else true ; fi + +- for x in `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ ++for x in `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $(@) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ + cp -f $(@) $(@D)/$$x; \ + $(MAKE) $(@D)/$$x.8; \ + done +@@ -64,7 +64,7 @@ + fi + for p in $(TARGET); do \ + dir=`dirname $$p`; \ +- for x in `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $$p -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ ++ for x in `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $$p -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \ + echo " $(INSTALL_SCRIPT) $$dir/$$x '$(DESTDIR)$(sbindir)'"; \ + $(INSTALL_SCRIPT) $$dir/$$x "$(DESTDIR)$(sbindir)" || exit $$?; \ + echo " $(INSTALL_DATA) '$$dir/$$x.8' '$(DESTDIR)$(man8dir)'"; \ +@@ -74,7 +74,7 @@ + + uninstall-hook: $(TARGET) + files=`for p in $(TARGET); do \ +- for x in \`PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $$p -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"\`; do \ ++ for x in \`PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib:$(abs_top_builddir)/support/common $(PYTHON) $$p -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"\`; do \ + echo " rm -f '$(DESTDIR)$(sbindir)/$$x'"; \ + rm -f "$(DESTDIR)$(sbindir)/$$x"; \ + echo " rm -f '$(DESTDIR)$(man8dir)/$$x.8'"; \ +diff --color -uNr a/make/fenceman.mk b/make/fenceman.mk +--- a/make/fenceman.mk 2021-03-11 16:10:15.000000000 +0100 ++++ b/make/fenceman.mk 2021-06-03 13:16:16.548120826 +0200 +@@ -1,6 +1,6 @@ + %.8: % $(top_srcdir)/lib/fence2man.xsl + set -e && \ +- PYTHONPATH=$(abs_srcdir)/lib:$(abs_builddir)/../lib:$(abs_builddir)/lib \ ++ PYTHONPATH=$(abs_srcdir)/lib:$(abs_builddir)/../lib:$(abs_builddir)/lib:$(abs_top_builddir)/support/common \ + $(PYTHON) $* -o manpage > $(@D)/.$(@F).tmp && \ + xmllint --noout --relaxng $(top_srcdir)/lib/metadata.rng $(@D)/.$(@F).tmp && \ + xsltproc $(top_srcdir)/lib/fence2man.xsl $(@D)/.$(@F).tmp > $@ diff --git a/SOURCES/bundled-suds.patch b/SOURCES/bundled-suds.patch new file mode 100644 index 0000000..b8a6ba1 --- /dev/null +++ b/SOURCES/bundled-suds.patch @@ -0,0 +1,10 @@ +--- a/agents/vmware_soap/fence_vmware_soap.py 2021-08-24 15:38:05.145039598 +0200 ++++ b/agents/vmware_soap/fence_vmware_soap.py 2021-08-24 15:37:51.885003751 +0200 +@@ -1,6 +1,7 @@ + #!@PYTHON@ -tt + + import sys ++sys.path.insert(0, '/usr/lib/fence-agents/support/common') + import shutil, tempfile, suds + import logging, requests + import atexit, signal diff --git a/SOURCES/bz2000954-1-configure-fix-virt.patch b/SOURCES/bz2000954-1-configure-fix-virt.patch new file mode 100644 index 0000000..de556a4 --- /dev/null +++ b/SOURCES/bz2000954-1-configure-fix-virt.patch @@ -0,0 +1,24 @@ +From 52de83b30a8eea638b01f649f4884f50417121c0 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 8 Nov 2021 09:55:11 +0100 +Subject: [PATCH] configure: fix --with-agents to not match *virt in regex + +--- + configure.ac | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 7aa51e75d..76aec7186 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -173,8 +173,8 @@ if echo "$AGENTS_LIST" | grep -q -E "all|zvm( |$)"; then + fi + + FENCE_VIRT=0 +-if echo "$AGENTS_LIST" | grep -q -E "all|virt( |$)"; then +- AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/virt( |$)//") ++if echo "$AGENTS_LIST" | grep -q -E "all|(^| )virt( |$)"; then ++ AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/(^| )virt( |$)//") + case "$host_os" in + *bsd*) + ;; diff --git a/SOURCES/bz2000954-2-fence_kubevirt.patch b/SOURCES/bz2000954-2-fence_kubevirt.patch new file mode 100644 index 0000000..f7de84a --- /dev/null +++ b/SOURCES/bz2000954-2-fence_kubevirt.patch @@ -0,0 +1,160 @@ +--- fence-agents-4.10.0/agents/kubevirt/fence_kubevirt.py 2021-07-08 13:09:05.000000000 +0200 ++++ /home/oalbrigt/rhpkg/fence-agents-8.6/fence-agents-4.2.1/agents/kubevirt/fence_kubevirt.py 2021-11-02 15:35:46.217440426 +0100 +@@ -2,24 +2,25 @@ + + import sys + import logging ++import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +-from fencing import fail, fail_usage, run_delay, EC_STATUS ++from fencing import fail, fail_usage, run_delay, EC_STATUS, EC_FETCH_VM_UUID + + try: ++ sys.path.insert(0, '/usr/lib/fence-agents/bundled/kubevirt') + from kubernetes.client.exceptions import ApiException + except ImportError: + logging.error("Couldn\'t import kubernetes.client.exceptions.ApiException - not found or not accessible") + +-API_VERSION='kubevirt.io/v1' +- + def get_nodes_list(conn, options): + logging.debug("Starting list/monitor operation") + result = {} + try: ++ apiversion = options.get("--apiversion") + namespace = options.get("--namespace") + include_uninitialized = True +- vm_api = conn.resources.get(api_version=API_VERSION, kind='VirtualMachine') ++ vm_api = conn.resources.get(api_version=apiversion, kind='VirtualMachine') + vm_list = vm_api.get(namespace=namespace) + for vm in vm_list.items: + result[vm.metadata.name] = ("", None) +@@ -30,18 +31,21 @@ + def get_power_status(conn, options): + logging.debug("Starting get status operation") + try: ++ apiversion = options.get("--apiversion") + namespace = options.get("--namespace") + name = options.get("--plug") +- vmi_api = conn.resources.get(api_version=API_VERSION, ++ vmi_api = conn.resources.get(api_version=apiversion, + kind='VirtualMachineInstance') + vmi = vmi_api.get(name=name, namespace=namespace) +- if vmi is not None: +- phase = vmi.status.phase +- if phase == "Running": +- return "on" +- return "off" ++ return translate_status(vmi.status.phase) + except ApiException as e: + if e.status == 404: ++ try: ++ vm_api = conn.resources.get(api_version=apiversion, kind='VirtualMachine') ++ vm = vm_api.get(name=name, namespace=namespace) ++ except ApiException as e: ++ logging.error("VM %s doesn't exist", name) ++ fail(EC_FETCH_VM_UUID) + return "off" + logging.error("Failed to get power status, with API Exception: %s", e) + fail(EC_STATUS) +@@ -49,38 +53,53 @@ + logging.error("Failed to get power status, with Exception: %s", e) + fail(EC_STATUS) + ++def translate_status(instance_status): ++ if instance_status == "Running": ++ return "on" ++ return "unknown" ++ + def set_power_status(conn, options): + logging.debug("Starting set status operation") + try: ++ apiversion= options.get("--apiversion") + namespace = options.get("--namespace") + name = options.get("--plug") + action = 'start' if options["--action"] == "on" else 'stop' +- virtctl_vm_action(conn, action, namespace, name) ++ virtctl_vm_action(conn, action, namespace, name, apiversion) + except Exception as e: + logging.error("Failed to set power status, with Exception: %s", e) + fail(EC_STATUS) + + def define_new_opts(): +- all_opt["namespace"] = { +- "getopt" : ":", +- "longopt" : "namespace", +- "help" : "--namespace=[namespace] Namespace of the KubeVirt machine", +- "shortdesc" : "Namespace of the KubeVirt machine.", +- "required" : "1", +- "order" : 2 +- } +- all_opt["kubeconfig"] = { +- "getopt" : ":", +- "longopt" : "kubeconfig", +- "help" : "--kubeconfig=[kubeconfig] Kubeconfig file path", +- "shortdesc": "Kubeconfig file path", +- "required": "0", +- "order": 4 +- } ++ all_opt["namespace"] = { ++ "getopt" : ":", ++ "longopt" : "namespace", ++ "help" : "--namespace=[namespace] Namespace of the KubeVirt machine", ++ "shortdesc" : "Namespace of the KubeVirt machine.", ++ "required" : "1", ++ "order" : 2 ++ } ++ all_opt["kubeconfig"] = { ++ "getopt" : ":", ++ "longopt" : "kubeconfig", ++ "help" : "--kubeconfig=[kubeconfig] Kubeconfig file path", ++ "shortdesc": "Kubeconfig file path", ++ "required": "0", ++ "order": 4 ++ } ++ all_opt["apiversion"] = { ++ "getopt" : ":", ++ "longopt" : "apiversion", ++ "help" : "--apiversion=[apiversion] Version of the KubeVirt API", ++ "shortdesc" : "Version of the KubeVirt API.", ++ "required" : "0", ++ "default" : "kubevirt.io/v1", ++ "order" : 5 ++ } + +-def virtctl_vm_action(conn, action, namespace, name): ++def virtctl_vm_action(conn, action, namespace, name, apiversion): + path = '/apis/subresources.{api_version}/namespaces/{namespace}/virtualmachines/{name}/{action}' +- path = path.format(api_version=API_VERSION, namespace=namespace, name=name, action=action) ++ path = path.format(api_version=apiversion, namespace=namespace, name=name, action=action) + return conn.request('put', path, header_params={'accept': '*/*'}) + + def validate_options(required_options_list, options): +@@ -92,8 +111,13 @@ + def main(): + conn = None + +- device_opt = ["port", "namespace", "kubeconfig", "separator", "no_password"] ++ device_opt = ["port", "namespace", "kubeconfig", "ssl_insecure", "no_password", "apiversion"] ++ ++ atexit.register(atexit_handler) + define_new_opts() ++ ++ all_opt["power_timeout"]["default"] = "40" ++ + options = check_input(device_opt, process_input(device_opt)) + + docs = {} +@@ -106,6 +130,11 @@ + + validate_options(['--namespace'], options) + ++ # Disable insecure-certificate-warning message ++ if "--ssl-insecure" in options: ++ import urllib3 ++ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) ++ + try: + from kubernetes import config + from openshift.dynamic import DynamicClient diff --git a/SOURCES/bz2000954-3-fence_kubevirt-get-namespace-from-context.patch b/SOURCES/bz2000954-3-fence_kubevirt-get-namespace-from-context.patch new file mode 100644 index 0000000..799bf31 --- /dev/null +++ b/SOURCES/bz2000954-3-fence_kubevirt-get-namespace-from-context.patch @@ -0,0 +1,102 @@ +From 647841dea9d93922779a4aa7d0b5f52f5bc2b4e9 Mon Sep 17 00:00:00 2001 +From: Dan Kenigsberg +Date: Thu, 13 Jan 2022 14:57:26 +0200 +Subject: [PATCH] fence_kubevirt: take default namespace from context + +If --namespace is not provided to kubectl, a default one is taken from +kubeconfig context. Let fence_kubevirt behave similarly. + +Signed-off-by: Dan Kenigsberg +--- + agents/kubevirt/fence_kubevirt.py | 24 +++++++++++++----------- + tests/data/metadata/fence_kubevirt.xml | 2 +- + 2 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/agents/kubevirt/fence_kubevirt.py b/agents/kubevirt/fence_kubevirt.py +index 8392b75a0..8c27a0334 100755 +--- a/agents/kubevirt/fence_kubevirt.py ++++ b/agents/kubevirt/fence_kubevirt.py +@@ -12,12 +12,21 @@ + except ImportError: + logging.error("Couldn\'t import kubernetes.client.exceptions.ApiException - not found or not accessible") + ++def _get_namespace(options): ++ from kubernetes import config ++ ++ ns = options.get("--namespace") ++ if ns is None: ++ ns = config.kube_config.list_kube_config_contexts()[1]['context']['namespace'] ++ ++ return ns ++ + def get_nodes_list(conn, options): + logging.debug("Starting list/monitor operation") + result = {} + try: + apiversion = options.get("--apiversion") +- namespace = options.get("--namespace") ++ namespace = _get_namespace(options) + include_uninitialized = True + vm_api = conn.resources.get(api_version=apiversion, kind='VirtualMachine') + vm_list = vm_api.get(namespace=namespace) +@@ -31,7 +40,7 @@ def get_power_status(conn, options): + logging.debug("Starting get status operation") + try: + apiversion = options.get("--apiversion") +- namespace = options.get("--namespace") ++ namespace = _get_namespace(options) + name = options.get("--plug") + vmi_api = conn.resources.get(api_version=apiversion, + kind='VirtualMachineInstance') +@@ -61,7 +70,7 @@ def set_power_status(conn, options): + logging.debug("Starting set status operation") + try: + apiversion= options.get("--apiversion") +- namespace = options.get("--namespace") ++ namespace = _get_namespace(options) + name = options.get("--plug") + action = 'start' if options["--action"] == "on" else 'stop' + virtctl_vm_action(conn, action, namespace, name, apiversion) +@@ -75,7 +84,7 @@ def define_new_opts(): + "longopt" : "namespace", + "help" : "--namespace=[namespace] Namespace of the KubeVirt machine", + "shortdesc" : "Namespace of the KubeVirt machine.", +- "required" : "1", ++ "required" : "0", + "order" : 2 + } + all_opt["kubeconfig"] = { +@@ -101,11 +110,6 @@ def virtctl_vm_action(conn, action, namespace, name, apiversion): + path = path.format(api_version=apiversion, namespace=namespace, name=name, action=action) + return conn.request('put', path, header_params={'accept': '*/*'}) + +-def validate_options(required_options_list, options): +- for required_option in required_options_list: +- if required_option not in options: +- fail_usage("Failed: %s option must be provided" % required_option) +- + # Main agent method + def main(): + conn = None +@@ -127,8 +131,6 @@ def main(): + + run_delay(options) + +- validate_options(['--namespace'], options) +- + # Disable insecure-certificate-warning message + if "--ssl-insecure" in options: + import urllib3 +diff --git a/tests/data/metadata/fence_kubevirt.xml b/tests/data/metadata/fence_kubevirt.xml +index 24e975587..ccb20c224 100644 +--- a/tests/data/metadata/fence_kubevirt.xml ++++ b/tests/data/metadata/fence_kubevirt.xml +@@ -23,7 +23,7 @@ + + Use SSL connection without verifying certificate + +- ++ + + + Namespace of the KubeVirt machine. diff --git a/SOURCES/bz2010652-fence_azure_arm-fix-sovereign-cloud-msi-support.patch b/SOURCES/bz2010652-fence_azure_arm-fix-sovereign-cloud-msi-support.patch new file mode 100644 index 0000000..4077484 --- /dev/null +++ b/SOURCES/bz2010652-fence_azure_arm-fix-sovereign-cloud-msi-support.patch @@ -0,0 +1,139 @@ +From e339f304d4423a0e661d915f72ba88553b21d74a Mon Sep 17 00:00:00 2001 +From: MSSedusch +Date: Tue, 28 Sep 2021 12:23:37 +0000 +Subject: [PATCH 1/2] add support for sovereign clouds and MSI + +--- + lib/azure_fence.py.py | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/lib/azure_fence.py.py b/lib/azure_fence.py.py +index 1f38bd4ea..75b63fdad 100644 +--- a/lib/azure_fence.py.py ++++ b/lib/azure_fence.py.py +@@ -286,11 +286,11 @@ def get_azure_credentials(config): + credentials = None + cloud_environment = get_azure_cloud_environment(config) + if config.UseMSI and cloud_environment: +- from msrestazure.azure_active_directory import MSIAuthentication +- credentials = MSIAuthentication(cloud_environment=cloud_environment) ++ from azure.identity import ManagedIdentityCredential ++ credentials = ManagedIdentityCredential(cloud_environment=cloud_environment) + elif config.UseMSI: +- from msrestazure.azure_active_directory import MSIAuthentication +- credentials = MSIAuthentication() ++ from azure.identity import ManagedIdentityCredential ++ credentials = ManagedIdentityCredential() + elif cloud_environment: + try: + # try to use new libraries ClientSecretCredential (azure.identity, based on azure.core) +@@ -340,7 +340,8 @@ def get_azure_compute_client(config): + compute_client = ComputeManagementClient( + credentials, + config.SubscriptionId, +- base_url=cloud_environment.endpoints.resource_manager ++ base_url=cloud_environment.endpoints.resource_manager, ++ credential_scopes=[cloud_environment.endpoints.resource_manager + "/.default"] + ) + else: + compute_client = ComputeManagementClient( +@@ -359,7 +360,8 @@ def get_azure_network_client(config): + network_client = NetworkManagementClient( + credentials, + config.SubscriptionId, +- base_url=cloud_environment.endpoints.resource_manager ++ base_url=cloud_environment.endpoints.resource_manager, ++ credential_scopes=[cloud_environment.endpoints.resource_manager + "/.default"] + ) + else: + network_client = NetworkManagementClient( + +From f08f02a7561e78dd9c95c66ccdcf6246c5ee7d6a Mon Sep 17 00:00:00 2001 +From: MSSedusch +Date: Fri, 1 Oct 2021 15:28:39 +0000 +Subject: [PATCH 2/2] compatiblity fix + +--- + lib/azure_fence.py.py | 54 ++++++++++++++++++++++++++++++------------- + 1 file changed, 38 insertions(+), 16 deletions(-) + +diff --git a/lib/azure_fence.py.py b/lib/azure_fence.py.py +index 75b63fdad..5ca71eb42 100644 +--- a/lib/azure_fence.py.py ++++ b/lib/azure_fence.py.py +@@ -286,11 +286,19 @@ def get_azure_credentials(config): + credentials = None + cloud_environment = get_azure_cloud_environment(config) + if config.UseMSI and cloud_environment: +- from azure.identity import ManagedIdentityCredential +- credentials = ManagedIdentityCredential(cloud_environment=cloud_environment) ++ try: ++ from azure.identity import ManagedIdentityCredential ++ credentials = ManagedIdentityCredential(cloud_environment=cloud_environment) ++ except ImportError: ++ from msrestazure.azure_active_directory import MSIAuthentication ++ credentials = MSIAuthentication(cloud_environment=cloud_environment) + elif config.UseMSI: +- from azure.identity import ManagedIdentityCredential +- credentials = ManagedIdentityCredential() ++ try: ++ from azure.identity import ManagedIdentityCredential ++ credentials = ManagedIdentityCredential() ++ except ImportError: ++ from msrestazure.azure_active_directory import MSIAuthentication ++ credentials = MSIAuthentication() + elif cloud_environment: + try: + # try to use new libraries ClientSecretCredential (azure.identity, based on azure.core) +@@ -337,12 +345,19 @@ def get_azure_compute_client(config): + credentials = get_azure_credentials(config) + + if cloud_environment: +- compute_client = ComputeManagementClient( +- credentials, +- config.SubscriptionId, +- base_url=cloud_environment.endpoints.resource_manager, +- credential_scopes=[cloud_environment.endpoints.resource_manager + "/.default"] +- ) ++ try: ++ compute_client = ComputeManagementClient( ++ credentials, ++ config.SubscriptionId, ++ base_url=cloud_environment.endpoints.resource_manager, ++ credential_scopes=[cloud_environment.endpoints.resource_manager + "/.default"] ++ ) ++ except TypeError: ++ compute_client = ComputeManagementClient( ++ credentials, ++ config.SubscriptionId, ++ base_url=cloud_environment.endpoints.resource_manager ++ ) + else: + compute_client = ComputeManagementClient( + credentials, +@@ -357,12 +372,19 @@ def get_azure_network_client(config): + credentials = get_azure_credentials(config) + + if cloud_environment: +- network_client = NetworkManagementClient( +- credentials, +- config.SubscriptionId, +- base_url=cloud_environment.endpoints.resource_manager, +- credential_scopes=[cloud_environment.endpoints.resource_manager + "/.default"] +- ) ++ try: ++ network_client = NetworkManagementClient( ++ credentials, ++ config.SubscriptionId, ++ base_url=cloud_environment.endpoints.resource_manager, ++ credential_scopes=[cloud_environment.endpoints.resource_manager + "/.default"] ++ ) ++ except TypeError: ++ network_client = NetworkManagementClient( ++ credentials, ++ config.SubscriptionId, ++ base_url=cloud_environment.endpoints.resource_manager ++ ) + else: + network_client = NetworkManagementClient( + credentials, diff --git a/SOURCES/bz2010709-1-fence_amt_ws-fix-or-causing-dead-code.patch b/SOURCES/bz2010709-1-fence_amt_ws-fix-or-causing-dead-code.patch new file mode 100644 index 0000000..bdbeab0 --- /dev/null +++ b/SOURCES/bz2010709-1-fence_amt_ws-fix-or-causing-dead-code.patch @@ -0,0 +1,22 @@ +From 06855a8227fa91f6216119daa3d32d5858c62837 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 27 Sep 2021 12:05:41 +0200 +Subject: [PATCH] fence_amt_ws: fix "or" causing dead code + +--- + agents/amt_ws/fence_amt_ws.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/agents/amt_ws/fence_amt_ws.py b/agents/amt_ws/fence_amt_ws.py +index 23c8a61a4..122cec309 100755 +--- a/agents/amt_ws/fence_amt_ws.py ++++ b/agents/amt_ws/fence_amt_ws.py +@@ -148,7 +148,7 @@ def set_boot_order(_, client, options): + + if options["--boot-option"] == "pxe": + device = "Intel(r) AMT: Force PXE Boot" +- elif options["--boot-option"] == "hd" or "hdsafe": ++ elif options["--boot-option"] in ["hd", "hdsafe"]: + device = "Intel(r) AMT: Force Hard-drive Boot" + elif options["--boot-option"] == "cd": + device = "Intel(r) AMT: Force CD/DVD Boot" diff --git a/SOURCES/bz2010709-2-fence_amt_ws-boot-option.patch b/SOURCES/bz2010709-2-fence_amt_ws-boot-option.patch new file mode 100644 index 0000000..dd37fef --- /dev/null +++ b/SOURCES/bz2010709-2-fence_amt_ws-boot-option.patch @@ -0,0 +1,32 @@ +From 9812473270e9a404c632358c1debfa4a1fb440fe Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Wed, 20 Oct 2021 15:46:42 +0200 +Subject: [PATCH] fence_amt_ws: fix --boot-option (choices are uppercased while + getting parsed) + +--- + agents/amt_ws/fence_amt_ws.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/agents/amt_ws/fence_amt_ws.py b/agents/amt_ws/fence_amt_ws.py +index 122cec309..5e7452a97 100755 +--- a/agents/amt_ws/fence_amt_ws.py ++++ b/agents/amt_ws/fence_amt_ws.py +@@ -146,13 +146,13 @@ def set_boot_order(_, client, options): + wsman = 'http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd' + namespace = CIM_BootConfigSetting + +- if options["--boot-option"] == "pxe": ++ if options["--boot-option"] == "PXE": + device = "Intel(r) AMT: Force PXE Boot" +- elif options["--boot-option"] in ["hd", "hdsafe"]: ++ elif options["--boot-option"] in ["HD", "HDSAFE"]: + device = "Intel(r) AMT: Force Hard-drive Boot" +- elif options["--boot-option"] == "cd": ++ elif options["--boot-option"] == "CD": + device = "Intel(r) AMT: Force CD/DVD Boot" +- elif options["--boot-option"] == "diag": ++ elif options["--boot-option"] == "DIAG": + device = "Intel(r) AMT: Force Diagnostic Boot" + else: + logging.error('Boot device: %s not supported.', \ diff --git a/SOURCES/bz2022334-fence_zvmip-add-disable-ssl.patch b/SOURCES/bz2022334-fence_zvmip-add-disable-ssl.patch new file mode 100644 index 0000000..916391d --- /dev/null +++ b/SOURCES/bz2022334-fence_zvmip-add-disable-ssl.patch @@ -0,0 +1,98 @@ +From 90c4f78e005ca4141039d1dce032b5f2c2ff4783 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 10 Feb 2022 12:22:58 +0100 +Subject: [PATCH 1/2] fencing: add ability to set bool parameters to 0 or false + +--- + lib/fencing.py.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/fencing.py.py b/lib/fencing.py.py +index 55e38c407..696388d55 100644 +--- a/lib/fencing.py.py ++++ b/lib/fencing.py.py +@@ -1502,6 +1502,8 @@ def _parse_input_stdin(avail_opt): + opt["--"+all_opt[name]["longopt"].rstrip(":")] = value + elif value.lower() in ["1", "yes", "on", "true"]: + opt["--"+all_opt[name]["longopt"]] = "1" ++ elif value.lower() in ["0", "no", "off", "false"]: ++ opt["--"+all_opt[name]["longopt"]] = "0" + else: + logging.warning("Parse error: Ignoring option '%s' because it does not have value\n", name) + + +From 249abc8e5620fb1a3d97a0af6db34b1f2cbf3ae5 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 10 Feb 2022 12:27:02 +0100 +Subject: [PATCH 2/2] fence_zvmip: add --disable-ssl + +--- + agents/zvm/fence_zvmip.py | 18 +++++++++++++++++- + tests/data/metadata/fence_zvmip.xml | 7 ++++++- + 2 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/agents/zvm/fence_zvmip.py b/agents/zvm/fence_zvmip.py +index 96021b13e..e8f849eda 100644 +--- a/agents/zvm/fence_zvmip.py ++++ b/agents/zvm/fence_zvmip.py +@@ -156,11 +156,24 @@ def get_list_of_images(options, command, data_as_plug): + conn.close() + return (return_code, reason_code, images) + ++def define_new_opts(): ++ all_opt["disable_ssl"] = { ++ "getopt" : "", ++ "longopt" : "disable-ssl", ++ "help" : "--disable-ssl Don't use SSL connection", ++ "required" : "0", ++ "shortdesc" : "Don't use SSL", ++ "order": 2 ++ } ++ + def main(): + device_opt = ["ipaddr", "login", "passwd", "port", "method", "missing_as_off", +- "inet4_only", "inet6_only", "ssl"] ++ "inet4_only", "inet6_only", "ssl", "disable_ssl"] + + atexit.register(atexit_handler) ++ define_new_opts() ++ ++ all_opt["ssl"]["help"] = "-z, --ssl Use SSL connection with verifying certificate (Default)" + + all_opt["ipport"]["default"] = "44444" + all_opt["shell_timeout"]["default"] = "5" +@@ -168,6 +181,9 @@ def main(): + all_opt["ssl"]["default"] = "1" + options = check_input(device_opt, process_input(device_opt), other_conditions=True) + ++ if "--disable-ssl" in options or options["--ssl"] == "0": ++ del options["--ssl"] ++ + if len(options.get("--plug", "")) > 8: + fail_usage("Failed: Name of image can not be longer than 8 characters") + +diff --git a/tests/data/metadata/fence_zvmip.xml b/tests/data/metadata/fence_zvmip.xml +index f32fc159d..0b7ba4785 100644 +--- a/tests/data/metadata/fence_zvmip.xml ++++ b/tests/data/metadata/fence_zvmip.xml +@@ -94,7 +94,7 @@ to access the system's directory manager. + + + +- Use SSL connection with verifying certificate ++ Use SSL connection with verifying certificate (Default) + + + +@@ -111,6 +111,11 @@ to access the system's directory manager. + + Login name + ++ ++ ++ ++ Don't use SSL ++ + + + diff --git a/SOURCES/bz2022334-fence_zvmip-add-ssl-tls-support.patch b/SOURCES/bz2022334-fence_zvmip-add-ssl-tls-support.patch new file mode 100644 index 0000000..71607bc --- /dev/null +++ b/SOURCES/bz2022334-fence_zvmip-add-ssl-tls-support.patch @@ -0,0 +1,136 @@ +From 81be3c529ec1165f3135b4f14fbec2a19403cfbe Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 27 Aug 2021 08:53:36 +0200 +Subject: [PATCH 1/2] fence_zvmip: add ssl/tls support + +--- + agents/zvm/fence_zvmip.py | 20 ++++++++++++++++---- + tests/data/metadata/fence_zvmip.xml | 19 +++++++++++++++++++ + 2 files changed, 35 insertions(+), 4 deletions(-) + +diff --git a/agents/zvm/fence_zvmip.py b/agents/zvm/fence_zvmip.py +index 001106a44..874eb699f 100644 +--- a/agents/zvm/fence_zvmip.py ++++ b/agents/zvm/fence_zvmip.py +@@ -26,12 +26,22 @@ def open_socket(options): + except socket.gaierror: + fail(EC_LOGIN_DENIED) + +- conn = socket.socket() ++ if "--ssl" in options: ++ import ssl ++ sock = socket.socket() ++ sslcx = ssl.create_default_context() ++ if "--ssl-insecure" in options: ++ sslcx.check_hostname = False ++ sslcx.verify_mode = ssl.CERT_NONE ++ conn = sslcx.wrap_socket(sock, server_hostname=options["--ip"]) ++ else: ++ conn = socket.socket() + conn.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + conn.settimeout(float(options["--shell-timeout"]) or None) + try: + conn.connect(addr) +- except socket.error: ++ except socket.error as e: ++ logging.debug(e) + fail(EC_LOGIN_DENIED) + + return conn +@@ -122,11 +132,12 @@ def get_list_of_images(options, command, data_as_plug): + images = set() + + if output_len > 3*INT4: ++ recvflag = socket.MSG_WAITALL if "--ssl" not in options else 0 + array_len = struct.unpack("!i", conn.recv(INT4))[0] + data = "" + + while True: +- read_data = conn.recv(1024, socket.MSG_WAITALL).decode("UTF-8") ++ read_data = conn.recv(1024, recvflag).decode("UTF-8") + data += read_data + if array_len == len(data): + break +@@ -146,7 +157,8 @@ def get_list_of_images(options, command, data_as_plug): + return (return_code, reason_code, images) + + def main(): +- device_opt = ["ipaddr", "login", "passwd", "port", "method", "missing_as_off", "inet4_only", "inet6_only"] ++ device_opt = ["ipaddr", "login", "passwd", "port", "method", "missing_as_off", ++ "inet4_only", "inet6_only", "ssl"] + + atexit.register(atexit_handler) + +diff --git a/tests/data/metadata/fence_zvmip.xml b/tests/data/metadata/fence_zvmip.xml +index f84115c08..d91192946 100644 +--- a/tests/data/metadata/fence_zvmip.xml ++++ b/tests/data/metadata/fence_zvmip.xml +@@ -91,6 +91,21 @@ to access the system's directory manager. + + Physical plug number on device, UUID or identification of machine + ++ ++ ++ ++ Use SSL connection with verifying certificate ++ ++ ++ ++ ++ Use SSL connection without verifying certificate ++ ++ ++ ++ ++ Use SSL connection with verifying certificate ++ + + + +@@ -181,6 +196,10 @@ to access the system's directory manager. + + Count of attempts to retry power on + ++ ++ ++ Path to gnutls-cli binary ++ + + + + +From 8021e698095c5bd0ef33ee5f56fc448e946cb92c Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Wed, 10 Nov 2021 16:31:24 +0100 +Subject: [PATCH 2/2] fence_zvmip: use ssl by default + +--- + agents/zvm/fence_zvmip.py | 1 + + tests/data/metadata/fence_zvmip.xml | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/agents/zvm/fence_zvmip.py b/agents/zvm/fence_zvmip.py +index 874eb699f..96021b13e 100644 +--- a/agents/zvm/fence_zvmip.py ++++ b/agents/zvm/fence_zvmip.py +@@ -165,6 +165,7 @@ def main(): + all_opt["ipport"]["default"] = "44444" + all_opt["shell_timeout"]["default"] = "5" + all_opt["missing_as_off"]["default"] = "1" ++ all_opt["ssl"]["default"] = "1" + options = check_input(device_opt, process_input(device_opt), other_conditions=True) + + if len(options.get("--plug", "")) > 8: +diff --git a/tests/data/metadata/fence_zvmip.xml b/tests/data/metadata/fence_zvmip.xml +index d91192946..f32fc159d 100644 +--- a/tests/data/metadata/fence_zvmip.xml ++++ b/tests/data/metadata/fence_zvmip.xml +@@ -93,7 +93,7 @@ to access the system's directory manager. + + + +- ++ + Use SSL connection with verifying certificate + + diff --git a/SOURCES/bz2029791-1-fence_openstack-add-ssl-insecure.patch b/SOURCES/bz2029791-1-fence_openstack-add-ssl-insecure.patch new file mode 100644 index 0000000..e616cc8 --- /dev/null +++ b/SOURCES/bz2029791-1-fence_openstack-add-ssl-insecure.patch @@ -0,0 +1,72 @@ +From f79436d3a5e4cf279be0974e9633ad8994a017f7 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 6 Dec 2021 12:59:31 +0100 +Subject: [PATCH] fence_openstack: add --ssl-insecure + +--- + agents/openstack/fence_openstack.py | 7 +++++-- + tests/data/metadata/fence_openstack.xml | 5 +++++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/agents/openstack/fence_openstack.py b/agents/openstack/fence_openstack.py +index c480596c1..c2d9df160 100755 +--- a/agents/openstack/fence_openstack.py ++++ b/agents/openstack/fence_openstack.py +@@ -89,7 +89,7 @@ def set_power_status(conn, options): + + + def nova_login(username, password, projectname, auth_url, user_domain_name, +- project_domain_name, cacert, apitimeout): ++ project_domain_name, ssl_insecure, cacert, apitimeout): + legacy_import = False + + try: +@@ -127,7 +127,7 @@ def nova_login(username, password, projectname, auth_url, user_domain_name, + cacert=cacert, + ) + +- session = ksc_session.Session(auth=auth, verify=cacert, timeout=apitimeout) ++ session = ksc_session.Session(auth=auth, verify=False if ssl_insecure else cacert, timeout=apitimeout) + nova = client.Client("2", session=session, timeout=apitimeout) + apiversion = None + try: +@@ -220,6 +220,7 @@ def main(): + "port", + "no_port", + "uuid", ++ "ssl_insecure", + "cacert", + "apitimeout", + ] +@@ -268,6 +269,7 @@ def main(): + fail_usage("Failed: You have to set the Keystone service endpoint for authorization") + user_domain_name = options["--user-domain-name"] + project_domain_name = options["--project-domain-name"] ++ ssl_insecure = "--ssl-insecure" in options + cacert = options["--cacert"] + apitimeout = options["--apitimeout"] + try: +@@ -278,6 +280,7 @@ def main(): + auth_url, + user_domain_name, + project_domain_name, ++ ssl_insecure, + cacert, + apitimeout, + ) +diff --git a/tests/data/metadata/fence_openstack.xml b/tests/data/metadata/fence_openstack.xml +index 84503bbe0..926d18c3d 100644 +--- a/tests/data/metadata/fence_openstack.xml ++++ b/tests/data/metadata/fence_openstack.xml +@@ -43,6 +43,11 @@ + + UUID of the node to be fenced. + ++ ++ ++ ++ Use SSL connection without verifying certificate ++ + + + diff --git a/SOURCES/bz2029791-2-fence_openstack-cacert-default.patch b/SOURCES/bz2029791-2-fence_openstack-cacert-default.patch new file mode 100644 index 0000000..419ce33 --- /dev/null +++ b/SOURCES/bz2029791-2-fence_openstack-cacert-default.patch @@ -0,0 +1,59 @@ +From b7032d16a07997ecab3b2c11a6436b3fa21f9043 Mon Sep 17 00:00:00 2001 +From: "Fabio M. Di Nitto" +Date: Thu, 6 Jan 2022 12:53:28 +0100 +Subject: [PATCH] fence_openstack: relax ssl cacert default + +allow the agent to use Base OS defaults vs forcing a specific file +to increase portability. + +Signed-off-by: Fabio M. Di Nitto +--- + agents/openstack/fence_openstack.py | 12 +++++++++--- + tests/data/metadata/fence_openstack.xml | 2 +- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/agents/openstack/fence_openstack.py b/agents/openstack/fence_openstack.py +index c2d9df160..36b353b52 100755 +--- a/agents/openstack/fence_openstack.py ++++ b/agents/openstack/fence_openstack.py +@@ -127,7 +127,13 @@ def nova_login(username, password, projectname, auth_url, user_domain_name, + cacert=cacert, + ) + +- session = ksc_session.Session(auth=auth, verify=False if ssl_insecure else cacert, timeout=apitimeout) ++ caverify=True ++ if ssl_insecure: ++ caverify=False ++ elif cacert: ++ caverify=cacert ++ ++ session = ksc_session.Session(auth=auth, verify=caverify, timeout=apitimeout) + nova = client.Client("2", session=session, timeout=apitimeout) + apiversion = None + try: +@@ -189,10 +195,10 @@ def define_new_opts(): + all_opt["cacert"] = { + "getopt": ":", + "longopt": "cacert", +- "help": "--cacert=[cacert] Path to the PEM file with trusted authority certificates", ++ "help": "--cacert=[cacert] Path to the PEM file with trusted authority certificates (override global CA trust)", + "required": "0", + "shortdesc": "SSL X.509 certificates file", +- "default": "/etc/pki/tls/certs/ca-bundle.crt", ++ "default": "", + "order": 7, + } + all_opt["apitimeout"] = { +diff --git a/tests/data/metadata/fence_openstack.xml b/tests/data/metadata/fence_openstack.xml +index 926d18c3d..c8dc2e60f 100644 +--- a/tests/data/metadata/fence_openstack.xml ++++ b/tests/data/metadata/fence_openstack.xml +@@ -100,7 +100,7 @@ + + + +- ++ + SSL X.509 certificates file + + diff --git a/SOURCES/bz2041933-bz2041935-1-fence_openstack-clouds-openrc.patch b/SOURCES/bz2041933-bz2041935-1-fence_openstack-clouds-openrc.patch new file mode 100644 index 0000000..06363d8 --- /dev/null +++ b/SOURCES/bz2041933-bz2041935-1-fence_openstack-clouds-openrc.patch @@ -0,0 +1,313 @@ +From 2f741df2ce73da85bbd205d861b527aa141d9776 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 14 Jan 2022 14:47:41 +0100 +Subject: [PATCH 1/2] fencing: add source_env() + +--- + lib/fencing.py.py | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/lib/fencing.py.py b/lib/fencing.py.py +index d85b23568..55e38c407 100644 +--- a/lib/fencing.py.py ++++ b/lib/fencing.py.py +@@ -1143,6 +1143,14 @@ def fence_logout(conn, logout_string, sleep=0): + except pexpect.ExceptionPexpect: + pass + ++def source_env(env_file): ++ # POSIX: name shall not contain '=', value doesn't contain '\0' ++ output = subprocess.check_output("source {} && env -0".format(env_file), shell=True, ++ executable="/bin/sh") ++ # replace env ++ os.environ.clear() ++ os.environ.update(line.partition('=')[::2] for line in output.decode("utf-8").split('\0')) ++ + # Convert array of format [[key1, value1], [key2, value2], ... [keyN, valueN]] to dict, where key is + # in format a.b.c.d...z and returned dict has key only z + def array_to_dict(array): + +From fe2183a97e0a5734702e9cba8da21f01afd8f577 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 14 Jan 2022 14:54:10 +0100 +Subject: [PATCH 2/2] fence_openstack: add support for reading config from + clouds.yaml and openrc + +--- + agents/openstack/fence_openstack.py | 116 ++++++++++++++++++++---- + tests/data/metadata/fence_openstack.xml | 32 +++++-- + 2 files changed, 126 insertions(+), 22 deletions(-) + mode change 100755 => 100644 agents/openstack/fence_openstack.py + +diff --git a/agents/openstack/fence_openstack.py b/agents/openstack/fence_openstack.py +old mode 100755 +new mode 100644 +index 36b353b52..d3a4be3aa +--- a/agents/openstack/fence_openstack.py ++++ b/agents/openstack/fence_openstack.py +@@ -8,7 +8,7 @@ + + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +-from fencing import fail_usage, run_delay ++from fencing import fail_usage, run_delay, source_env + + try: + from novaclient import client +@@ -26,6 +26,23 @@ def translate_status(instance_status): + return "off" + return "unknown" + ++def get_cloud(options): ++ import os, yaml ++ ++ clouds_yaml = os.path.expanduser("~/.config/openstack/clouds.yaml") ++ if os.path.exists(clouds_yaml): ++ with open(clouds_yaml, "r") as yaml_stream: ++ try: ++ clouds = yaml.safe_load(yaml_stream) ++ except yaml.YAMLError as exc: ++ fail_usage("Failed: Unable to read: " + clouds_yaml) ++ ++ cloud = clouds.get("clouds").get(options["--cloud"]) ++ if not cloud: ++ fail_usage("Cloud: {} not found.".format(options["--cloud"])) ++ ++ return cloud ++ + + def get_nodes_list(conn, options): + logging.info("Running %s action", options["--action"]) +@@ -153,7 +170,7 @@ def define_new_opts(): + "getopt": ":", + "longopt": "auth-url", + "help": "--auth-url=[authurl] Keystone Auth URL", +- "required": "1", ++ "required": "0", + "shortdesc": "Keystone Auth URL", + "order": 2, + } +@@ -161,7 +178,7 @@ def define_new_opts(): + "getopt": ":", + "longopt": "project-name", + "help": "--project-name=[project] Tenant Or Project Name", +- "required": "1", ++ "required": "0", + "shortdesc": "Keystone Project", + "default": "admin", + "order": 3, +@@ -184,13 +201,38 @@ def define_new_opts(): + "default": "Default", + "order": 5, + } ++ all_opt["clouds-yaml"] = { ++ "getopt": ":", ++ "longopt": "clouds-yaml", ++ "help": "--clouds-yaml=[clouds-yaml] Path to the clouds.yaml config file", ++ "required": "0", ++ "shortdesc": "clouds.yaml config file", ++ "default": "~/.config/openstack/clouds.yaml", ++ "order": 6, ++ } ++ all_opt["cloud"] = { ++ "getopt": ":", ++ "longopt": "cloud", ++ "help": "--cloud=[cloud] Openstack cloud (from clouds.yaml).", ++ "required": "0", ++ "shortdesc": "Cloud from clouds.yaml", ++ "order": 7, ++ } ++ all_opt["openrc"] = { ++ "getopt": ":", ++ "longopt": "openrc", ++ "help": "--openrc=[openrc] Path to the openrc config file", ++ "required": "0", ++ "shortdesc": "openrc config file", ++ "order": 8, ++ } + all_opt["uuid"] = { + "getopt": ":", + "longopt": "uuid", + "help": "--uuid=[uuid] Replaced by -n, --plug", + "required": "0", + "shortdesc": "Replaced by port/-n/--plug", +- "order": 6, ++ "order": 9, + } + all_opt["cacert"] = { + "getopt": ":", +@@ -199,7 +241,7 @@ def define_new_opts(): + "required": "0", + "shortdesc": "SSL X.509 certificates file", + "default": "", +- "order": 7, ++ "order": 10, + } + all_opt["apitimeout"] = { + "getopt": ":", +@@ -209,7 +251,7 @@ def define_new_opts(): + "shortdesc": "Timeout in seconds to use for API calls, default is 60.", + "required": "0", + "default": 60, +- "order": 8, ++ "order": 11, + } + + +@@ -218,11 +260,16 @@ def main(): + + device_opt = [ + "login", ++ "no_login", + "passwd", ++ "no_password", + "auth-url", + "project-name", + "user-domain-name", + "project-domain-name", ++ "clouds-yaml", ++ "cloud", ++ "openrc", + "port", + "no_port", + "uuid", +@@ -265,19 +312,56 @@ def main(): + + run_delay(options) + +- username = options["--username"] +- password = options["--password"] +- projectname = options["--project-name"] +- auth_url = None +- try: +- auth_url = options["--auth-url"] +- except KeyError: +- fail_usage("Failed: You have to set the Keystone service endpoint for authorization") +- user_domain_name = options["--user-domain-name"] +- project_domain_name = options["--project-domain-name"] ++ if options.get("--clouds-yaml"): ++ if not os.path.exists(os.path.expanduser(options["--clouds-yaml"])): ++ fail_usage("Failed: {} does not exist".format(options.get("--clouds-yaml"))) ++ if not options.get("--cloud"): ++ fail_usage("Failed: \"cloud\" not specified") ++ cloud = get_cloud(options) ++ username = cloud.get("username") ++ password = cloud.get("password") ++ projectname = cloud.get("project_name") ++ auth_url = None ++ try: ++ auth_url = cloud.get("auth_url") ++ except KeyError: ++ fail_usage("Failed: You have to set the Keystone service endpoint for authorization") ++ user_domain_name = cloud.get("user_domain_name") ++ project_domain_name = cloud.get("project_domain_name") ++ caverify = cloud.get("verify") ++ if caverify in [True, False]: ++ options["--ssl-insecure"] = caverify ++ else: ++ options["--cacert"] = caverify ++ if options.get("--openrc") and os.path.exists(os.path.expanduser(options["--openrc"])): ++ source_env(options["--openrc"]) ++ env = os.environ ++ username = env.get("OS_USERNAME") ++ password = env.get("OS_PASSWORD") ++ projectname = env.get("OS_PROJECT_NAME") ++ auth_url = None ++ try: ++ auth_url = env["OS_AUTH_URL"] ++ except KeyError: ++ fail_usage("Failed: You have to set the Keystone service endpoint for authorization") ++ user_domain_name = env.get("OS_USER_DOMAIN_NAME") ++ project_domain_name = env.get("OS_PROJECT_DOMAIN_NAME") ++ else: ++ username = options["--username"] ++ password = options["--password"] ++ projectname = options["--project-name"] ++ auth_url = None ++ try: ++ auth_url = options["--auth-url"] ++ except KeyError: ++ fail_usage("Failed: You have to set the Keystone service endpoint for authorization") ++ user_domain_name = options["--user-domain-name"] ++ project_domain_name = options["--project-domain-name"] ++ + ssl_insecure = "--ssl-insecure" in options + cacert = options["--cacert"] + apitimeout = options["--apitimeout"] ++ + try: + conn = nova_login( + username, +diff --git a/tests/data/metadata/fence_openstack.xml b/tests/data/metadata/fence_openstack.xml +index c8dc2e60f..55a57b4d7 100644 +--- a/tests/data/metadata/fence_openstack.xml ++++ b/tests/data/metadata/fence_openstack.xml +@@ -8,7 +8,7 @@ + + Fencing action + +- ++ + + + Login name +@@ -48,27 +48,27 @@ + + Use SSL connection without verifying certificate + +- ++ + + + Login name + +- ++ + + + Keystone Auth URL + +- ++ + + + Keystone Auth URL + +- ++ + + + Keystone Project + +- ++ + + + Keystone Project +@@ -93,6 +93,26 @@ + + Keystone Project Domain Name + ++ ++ ++ ++ clouds.yaml config file ++ ++ ++ ++ ++ clouds.yaml config file ++ ++ ++ ++ ++ Cloud from clouds.yaml ++ ++ ++ ++ ++ openrc config file ++ + + + diff --git a/SOURCES/bz2041933-bz2041935-2-fence_openstack-clouds-openrc.patch b/SOURCES/bz2041933-bz2041935-2-fence_openstack-clouds-openrc.patch new file mode 100644 index 0000000..6daa2bb --- /dev/null +++ b/SOURCES/bz2041933-bz2041935-2-fence_openstack-clouds-openrc.patch @@ -0,0 +1,171 @@ +From 7d9572ec947d23fa18ac530f07fe33ba148c9634 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 17 Jan 2022 14:32:53 +0100 +Subject: [PATCH] fence_openstack: fix issues with new clouds.yaml/openrc + parameters - hardcoded clouds.yaml paths to work like the openstack cli + client (used by the resource agents) + +--- + agents/openstack/fence_openstack.py | 55 +++++++++++-------------- + tests/data/metadata/fence_openstack.xml | 10 ----- + 2 files changed, 25 insertions(+), 40 deletions(-) + +diff --git a/agents/openstack/fence_openstack.py b/agents/openstack/fence_openstack.py +index d3a4be3aa..666016d78 100644 +--- a/agents/openstack/fence_openstack.py ++++ b/agents/openstack/fence_openstack.py +@@ -3,6 +3,7 @@ + import atexit + import logging + import sys ++import os + + import urllib3 + +@@ -27,9 +28,15 @@ def translate_status(instance_status): + return "unknown" + + def get_cloud(options): +- import os, yaml ++ import yaml + +- clouds_yaml = os.path.expanduser("~/.config/openstack/clouds.yaml") ++ clouds_yaml = "~/.config/openstack/clouds.yaml" ++ if not os.path.exists(os.path.expanduser(clouds_yaml)): ++ clouds_yaml = "/etc/openstack/clouds.yaml" ++ if not os.path.exists(os.path.expanduser(clouds_yaml)): ++ fail_usage("Failed: ~/.config/openstack/clouds.yaml and /etc/openstack/clouds.yaml does not exist") ++ ++ clouds_yaml = os.path.expanduser(clouds_yaml) + if os.path.exists(clouds_yaml): + with open(clouds_yaml, "r") as yaml_stream: + try: +@@ -201,22 +208,13 @@ def define_new_opts(): + "default": "Default", + "order": 5, + } +- all_opt["clouds-yaml"] = { +- "getopt": ":", +- "longopt": "clouds-yaml", +- "help": "--clouds-yaml=[clouds-yaml] Path to the clouds.yaml config file", +- "required": "0", +- "shortdesc": "clouds.yaml config file", +- "default": "~/.config/openstack/clouds.yaml", +- "order": 6, +- } + all_opt["cloud"] = { + "getopt": ":", + "longopt": "cloud", +- "help": "--cloud=[cloud] Openstack cloud (from clouds.yaml).", ++ "help": "--cloud=[cloud] Openstack cloud (from ~/.config/openstack/clouds.yaml or /etc/openstack/clouds.yaml).", + "required": "0", + "shortdesc": "Cloud from clouds.yaml", +- "order": 7, ++ "order": 6, + } + all_opt["openrc"] = { + "getopt": ":", +@@ -224,7 +222,7 @@ def define_new_opts(): + "help": "--openrc=[openrc] Path to the openrc config file", + "required": "0", + "shortdesc": "openrc config file", +- "order": 8, ++ "order": 7, + } + all_opt["uuid"] = { + "getopt": ":", +@@ -232,7 +230,7 @@ def define_new_opts(): + "help": "--uuid=[uuid] Replaced by -n, --plug", + "required": "0", + "shortdesc": "Replaced by port/-n/--plug", +- "order": 9, ++ "order": 8, + } + all_opt["cacert"] = { + "getopt": ":", +@@ -241,7 +239,7 @@ def define_new_opts(): + "required": "0", + "shortdesc": "SSL X.509 certificates file", + "default": "", +- "order": 10, ++ "order": 9, + } + all_opt["apitimeout"] = { + "getopt": ":", +@@ -251,7 +249,7 @@ def define_new_opts(): + "shortdesc": "Timeout in seconds to use for API calls, default is 60.", + "required": "0", + "default": 60, +- "order": 11, ++ "order": 10, + } + + +@@ -267,7 +265,6 @@ def main(): + "project-name", + "user-domain-name", + "project-domain-name", +- "clouds-yaml", + "cloud", + "openrc", + "port", +@@ -312,28 +309,26 @@ def main(): + + run_delay(options) + +- if options.get("--clouds-yaml"): +- if not os.path.exists(os.path.expanduser(options["--clouds-yaml"])): +- fail_usage("Failed: {} does not exist".format(options.get("--clouds-yaml"))) +- if not options.get("--cloud"): +- fail_usage("Failed: \"cloud\" not specified") ++ if options.get("--cloud"): + cloud = get_cloud(options) +- username = cloud.get("username") +- password = cloud.get("password") +- projectname = cloud.get("project_name") ++ username = cloud.get("auth").get("username") ++ password = cloud.get("auth").get("password") ++ projectname = cloud.get("auth").get("project_name") + auth_url = None + try: +- auth_url = cloud.get("auth_url") ++ auth_url = cloud.get("auth").get("auth_url") + except KeyError: + fail_usage("Failed: You have to set the Keystone service endpoint for authorization") +- user_domain_name = cloud.get("user_domain_name") +- project_domain_name = cloud.get("project_domain_name") ++ user_domain_name = cloud.get("auth").get("user_domain_name") ++ project_domain_name = cloud.get("auth").get("project_domain_name") + caverify = cloud.get("verify") + if caverify in [True, False]: + options["--ssl-insecure"] = caverify + else: + options["--cacert"] = caverify +- if options.get("--openrc") and os.path.exists(os.path.expanduser(options["--openrc"])): ++ elif options.get("--openrc"): ++ if not os.path.exists(os.path.expanduser(options["--openrc"])): ++ fail_usage("Failed: {} does not exist".format(options.get("--openrc"))) + source_env(options["--openrc"]) + env = os.environ + username = env.get("OS_USERNAME") +diff --git a/tests/data/metadata/fence_openstack.xml b/tests/data/metadata/fence_openstack.xml +index 55a57b4d7..67b2191b7 100644 +--- a/tests/data/metadata/fence_openstack.xml ++++ b/tests/data/metadata/fence_openstack.xml +@@ -93,16 +93,6 @@ + + Keystone Project Domain Name + +- +- +- +- clouds.yaml config file +- +- +- +- +- clouds.yaml config file +- + + + diff --git a/SOURCES/bz2041933-bz2041935-3-fencing-source_env-dont-process-empty-lines.patch b/SOURCES/bz2041933-bz2041935-3-fencing-source_env-dont-process-empty-lines.patch new file mode 100644 index 0000000..8803895 --- /dev/null +++ b/SOURCES/bz2041933-bz2041935-3-fencing-source_env-dont-process-empty-lines.patch @@ -0,0 +1,22 @@ +From fbca33a536413565108374dd4ed3237b6f7896bd Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 15 Aug 2022 10:40:19 +0200 +Subject: [PATCH] fencing: source_env(): dont process empty lines + +--- + lib/fencing.py.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/fencing.py.py b/lib/fencing.py.py +index fc3679e33..940bd01d1 100644 +--- a/lib/fencing.py.py ++++ b/lib/fencing.py.py +@@ -1264,7 +1264,7 @@ def source_env(env_file): + executable="/bin/sh") + # replace env + os.environ.clear() +- os.environ.update(line.partition('=')[::2] for line in output.decode("utf-8").split('\0')) ++ os.environ.update(line.partition('=')[::2] for line in output.decode("utf-8").split('\0') if not re.match("^\s*$", line)) + + # Convert array of format [[key1, value1], [key2, value2], ... [keyN, valueN]] to dict, where key is + # in format a.b.c.d...z and returned dict has key only z diff --git a/SOURCES/bz2042496-fence_ibm_vpc-fence_ibm_powervs.patch b/SOURCES/bz2042496-fence_ibm_vpc-fence_ibm_powervs.patch new file mode 100644 index 0000000..d68612c --- /dev/null +++ b/SOURCES/bz2042496-fence_ibm_vpc-fence_ibm_powervs.patch @@ -0,0 +1,740 @@ +From 3078e4d55d3bad2bbf9309785fdb2b53afac8d65 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 13 Jul 2021 13:39:33 +0200 +Subject: [PATCH] fence_ibm_vpc/fence_ibm_powervs: new fence agents + +--- + agents/ibm_powervs/fence_ibm_powervs.py | 202 +++++++++++++++++++ + agents/ibm_vpc/fence_ibm_vpc.py | 230 ++++++++++++++++++++++ + tests/data/metadata/fence_ibm_powervs.xml | 134 +++++++++++++ + tests/data/metadata/fence_ibm_vpc.xml | 134 +++++++++++++ + 5 files changed, 724 insertions(+) + create mode 100755 agents/ibm_powervs/fence_ibm_powervs.py + create mode 100755 agents/ibm_vpc/fence_ibm_vpc.py + create mode 100644 tests/data/metadata/fence_ibm_powervs.xml + create mode 100644 tests/data/metadata/fence_ibm_vpc.xml + +diff --git a/agents/ibm_powervs/fence_ibm_powervs.py b/agents/ibm_powervs/fence_ibm_powervs.py +new file mode 100755 +index 000000000..6649771ea +--- /dev/null ++++ b/agents/ibm_powervs/fence_ibm_powervs.py +@@ -0,0 +1,202 @@ ++#!@PYTHON@ -tt ++ ++import sys ++import pycurl, io, json ++import logging ++import atexit ++sys.path.append("@FENCEAGENTSLIBDIR@") ++from fencing import * ++from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS ++ ++state = { ++ "ACTIVE": "on", ++ "SHUTOFF": "off", ++ "ERROR": "unknown" ++} ++ ++def get_list(conn, options): ++ outlets = {} ++ ++ try: ++ command = "cloud-instances/{}/pvm-instances".format(options["--instance"]) ++ res = send_command(conn, command) ++ except Exception as e: ++ logging.debug("Failed: {}".format(e)) ++ return outlets ++ ++ for r in res["pvmInstances"]: ++ if "--verbose" in options: ++ logging.debug(json.dumps(r, indent=2)) ++ outlets[r["pvmInstanceID"]] = (r["serverName"], state[r["status"]]) ++ ++ return outlets ++ ++def get_power_status(conn, options): ++ try: ++ command = "cloud-instances/{}/pvm-instances/{}".format( ++ options["--instance"], options["--plug"]) ++ res = send_command(conn, command) ++ result = get_list(conn, options)[options["--plug"]][1] ++ except KeyError as e: ++ logging.debug("Failed: Unable to get status for {}".format(e)) ++ fail(EC_STATUS) ++ ++ return result ++ ++def set_power_status(conn, options): ++ action = { ++ "on" : '{"action" : "start"}', ++ "off" : '{"action" : "immediate-shutdown"}', ++ }[options["--action"]] ++ ++ try: ++ send_command(conn, "cloud-instances/{}/pvm-instances/{}/action".format( ++ options["--instance"], options["--plug"]), "POST", action) ++ except Exception as e: ++ logging.debug("Failed: Unable to set power to {} for {}".format(options["--action"], e)) ++ fail(EC_STATUS) ++ ++def connect(opt): ++ conn = pycurl.Curl() ++ ++ ## setup correct URL ++ conn.base_url = "https://" + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/" ++ ++ if opt["--verbose-level"] > 1: ++ conn.setopt(pycurl.VERBOSE, 1) ++ ++ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) ++ conn.setopt(pycurl.SSL_VERIFYPEER, 1) ++ conn.setopt(pycurl.SSL_VERIFYHOST, 2) ++ ++ # set auth token for later requests ++ conn.setopt(pycurl.HTTPHEADER, [ ++ "Content-Type: application/json", ++ "Authorization: Bearer {}".format(opt["--token"]), ++ "CRN: {}".format(opt["--crn"]), ++ "User-Agent: curl", ++ ]) ++ ++ return conn ++ ++def disconnect(conn): ++ conn.close() ++ ++def send_command(conn, command, method="GET", action=None): ++ url = conn.base_url + command ++ ++ conn.setopt(pycurl.URL, url.encode("ascii")) ++ ++ web_buffer = io.BytesIO() ++ ++ if method == "GET": ++ conn.setopt(pycurl.POST, 0) ++ if method == "POST": ++ conn.setopt(pycurl.POSTFIELDS, action) ++ if method == "DELETE": ++ conn.setopt(pycurl.CUSTOMREQUEST, "DELETE") ++ ++ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write) ++ ++ try: ++ conn.perform() ++ except Exception as e: ++ raise(e) ++ ++ rc = conn.getinfo(pycurl.HTTP_CODE) ++ result = web_buffer.getvalue().decode("UTF-8") ++ ++ web_buffer.close() ++ ++ if rc != 200: ++ if len(result) > 0: ++ raise Exception("{}: {}".format(rc, ++ result["value"]["messages"][0]["default_message"])) ++ else: ++ raise Exception("Remote returned {} for request to {}".format(rc, url)) ++ ++ if len(result) > 0: ++ result = json.loads(result) ++ ++ logging.debug("url: {}".format(url)) ++ logging.debug("method: {}".format(method)) ++ logging.debug("response code: {}".format(rc)) ++ logging.debug("result: {}\n".format(result)) ++ ++ return result ++ ++def define_new_opts(): ++ all_opt["token"] = { ++ "getopt" : ":", ++ "longopt" : "token", ++ "help" : "--token=[token] Bearer Token", ++ "required" : "1", ++ "shortdesc" : "Bearer Token", ++ "order" : 0 ++ } ++ all_opt["crn"] = { ++ "getopt" : ":", ++ "longopt" : "crn", ++ "help" : "--crn=[crn] CRN", ++ "required" : "1", ++ "shortdesc" : "CRN", ++ "order" : 0 ++ } ++ all_opt["instance"] = { ++ "getopt" : ":", ++ "longopt" : "instance", ++ "help" : "--instance=[instance] PowerVS Instance", ++ "required" : "1", ++ "shortdesc" : "PowerVS Instance", ++ "order" : 0 ++ } ++ all_opt["region"] = { ++ "getopt" : ":", ++ "longopt" : "region", ++ "help" : "--region=[region] Region", ++ "required" : "1", ++ "shortdesc" : "Region", ++ "order" : 0 ++ } ++ ++ ++def main(): ++ device_opt = [ ++ "token", ++ "crn", ++ "instance", ++ "region", ++ "port", ++ "no_password", ++ ] ++ ++ atexit.register(atexit_handler) ++ define_new_opts() ++ ++ all_opt["shell_timeout"]["default"] = "15" ++ all_opt["power_timeout"]["default"] = "30" ++ all_opt["power_wait"]["default"] = "1" ++ ++ options = check_input(device_opt, process_input(device_opt)) ++ ++ docs = {} ++ docs["shortdesc"] = "Fence agent for IBM PowerVS" ++ docs["longdesc"] = """fence_ibm_powervs is an I/O Fencing agent which can be \ ++used with IBM PowerVS to fence virtual machines.""" ++ docs["vendorurl"] = "https://www.ibm.com" ++ show_docs(options, docs) ++ ++ #### ++ ## Fence operations ++ #### ++ run_delay(options) ++ ++ conn = connect(options) ++ atexit.register(disconnect, conn) ++ ++ result = fence_action(conn, options, set_power_status, get_power_status, get_list) ++ ++ sys.exit(result) ++ ++if __name__ == "__main__": ++ main() +diff --git a/agents/ibm_vpc/fence_ibm_vpc.py b/agents/ibm_vpc/fence_ibm_vpc.py +new file mode 100755 +index 000000000..9f84f7b2d +--- /dev/null ++++ b/agents/ibm_vpc/fence_ibm_vpc.py +@@ -0,0 +1,230 @@ ++#!@PYTHON@ -tt ++ ++import sys ++import pycurl, io, json ++import logging ++import atexit ++sys.path.append("@FENCEAGENTSLIBDIR@") ++from fencing import * ++from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS ++ ++state = { ++ "running": "on", ++ "stopped": "off", ++ "starting": "unknown", ++ "stopping": "unknown", ++ "restarting": "unknown", ++ "pending": "unknown", ++} ++ ++def get_list(conn, options): ++ outlets = {} ++ ++ try: ++ command = "instances?version=2021-05-25&generation=2&limit={}".format(options["--limit"]) ++ res = send_command(conn, command) ++ except Exception as e: ++ logging.debug("Failed: Unable to get list: {}".format(e)) ++ return outlets ++ ++ for r in res["instances"]: ++ if options["--verbose-level"] > 1: ++ logging.debug("Node:\n{}".format(json.dumps(r, indent=2))) ++ logging.debug("Status: " + state[r["status"]]) ++ outlets[r["id"]] = (r["name"], state[r["status"]]) ++ ++ return outlets ++ ++def get_power_status(conn, options): ++ try: ++ command = "instances/{}?version=2021-05-25&generation=2".format(options["--plug"]) ++ res = send_command(conn, command) ++ result = state[res["status"]] ++ if options["--verbose-level"] > 1: ++ logging.debug("Result:\n{}".format(json.dumps(res, indent=2))) ++ logging.debug("Status: " + result) ++ except Exception as e: ++ logging.debug("Failed: Unable to get status for {}: {}".format(options["--plug"], e)) ++ fail(EC_STATUS) ++ ++ return result ++ ++def set_power_status(conn, options): ++ action = { ++ "on" : '{"type" : "start"}', ++ "off" : '{"type" : "stop"}', ++ }[options["--action"]] ++ ++ try: ++ command = "instances/{}/actions?version=2021-05-25&generation=2".format(options["--plug"]) ++ send_command(conn, command, "POST", action, 201) ++ except Exception as e: ++ logging.debug("Failed: Unable to set power to {} for {}".format(options["--action"], e)) ++ fail(EC_STATUS) ++ ++def get_bearer_token(conn, options): ++ token = None ++ try: ++ conn.setopt(pycurl.HTTPHEADER, [ ++ "Content-Type: application/x-www-form-urlencoded", ++ "User-Agent: curl", ++ ]) ++ token = send_command(conn, "https://iam.cloud.ibm.com/identity/token", "POST", "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey={}".format(options["--apikey"]))["access_token"] ++ except Exception: ++ logging.error("Failed: Unable to authenticate") ++ fail(EC_LOGIN_DENIED) ++ ++ return token ++ ++def connect(opt): ++ conn = pycurl.Curl() ++ ++ ## setup correct URL ++ conn.base_url = "https://" + opt["--region"] + ".iaas.cloud.ibm.com/v1/" ++ ++ if opt["--verbose-level"] > 1: ++ conn.setopt(pycurl.VERBOSE, 1) ++ ++ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) ++ conn.setopt(pycurl.SSL_VERIFYPEER, 1) ++ conn.setopt(pycurl.SSL_VERIFYHOST, 2) ++ ++ # get bearer token ++ bearer_token = get_bearer_token(conn, opt) ++ ++ # set auth token for later requests ++ conn.setopt(pycurl.HTTPHEADER, [ ++ "Content-Type: application/json", ++ "Authorization: Bearer {}".format(bearer_token), ++ "User-Agent: curl", ++ ]) ++ ++ return conn ++ ++def disconnect(conn): ++ conn.close() ++ ++def send_command(conn, command, method="GET", action=None, expected_rc=200): ++ if not command.startswith("https"): ++ url = conn.base_url + command ++ else: ++ url = command ++ ++ conn.setopt(pycurl.URL, url.encode("ascii")) ++ ++ web_buffer = io.BytesIO() ++ ++ if method == "GET": ++ conn.setopt(pycurl.POST, 0) ++ if method == "POST": ++ conn.setopt(pycurl.POSTFIELDS, action) ++ if method == "DELETE": ++ conn.setopt(pycurl.CUSTOMREQUEST, "DELETE") ++ ++ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write) ++ ++ try: ++ conn.perform() ++ except Exception as e: ++ raise(e) ++ ++ rc = conn.getinfo(pycurl.HTTP_CODE) ++ result = web_buffer.getvalue().decode("UTF-8") ++ ++ web_buffer.close() ++ ++ # actions (start/stop/reboot) report 201 when they've been created ++ if rc != expected_rc: ++ logging.debug("rc: {}, result: {}".format(rc, result)) ++ if len(result) > 0: ++ raise Exception("{}: {}".format(rc, ++ result["value"]["messages"][0]["default_message"])) ++ else: ++ raise Exception("Remote returned {} for request to {}".format(rc, url)) ++ ++ if len(result) > 0: ++ result = json.loads(result) ++ ++ logging.debug("url: {}".format(url)) ++ logging.debug("method: {}".format(method)) ++ logging.debug("response code: {}".format(rc)) ++ logging.debug("result: {}\n".format(result)) ++ ++ return result ++ ++def define_new_opts(): ++ all_opt["apikey"] = { ++ "getopt" : ":", ++ "longopt" : "apikey", ++ "help" : "--apikey=[key] API Key", ++ "required" : "1", ++ "shortdesc" : "API Key", ++ "order" : 0 ++ } ++ all_opt["instance"] = { ++ "getopt" : ":", ++ "longopt" : "instance", ++ "help" : "--instance=[instance] Cloud Instance", ++ "required" : "1", ++ "shortdesc" : "Cloud Instance", ++ "order" : 0 ++ } ++ all_opt["region"] = { ++ "getopt" : ":", ++ "longopt" : "region", ++ "help" : "--region=[region] Region", ++ "required" : "1", ++ "shortdesc" : "Region", ++ "order" : 0 ++ } ++ all_opt["limit"] = { ++ "getopt" : ":", ++ "longopt" : "limit", ++ "help" : "--limit=[number] Limit number of nodes returned by API", ++ "required" : "1", ++ "default": 50, ++ "shortdesc" : "Number of nodes returned by API", ++ "order" : 0 ++ } ++ ++ ++def main(): ++ device_opt = [ ++ "apikey", ++ "instance", ++ "region", ++ "limit", ++ "port", ++ "no_password", ++ ] ++ ++ atexit.register(atexit_handler) ++ define_new_opts() ++ ++ all_opt["shell_timeout"]["default"] = "15" ++ all_opt["power_timeout"]["default"] = "30" ++ all_opt["power_wait"]["default"] = "1" ++ ++ options = check_input(device_opt, process_input(device_opt)) ++ ++ docs = {} ++ docs["shortdesc"] = "Fence agent for IBM Cloud VPC" ++ docs["longdesc"] = """fence_ibm_vpc is an I/O Fencing agent which can be \ ++used with IBM Cloud VPC to fence virtual machines.""" ++ docs["vendorurl"] = "https://www.ibm.com" ++ show_docs(options, docs) ++ ++ #### ++ ## Fence operations ++ #### ++ run_delay(options) ++ ++ conn = connect(options) ++ atexit.register(disconnect, conn) ++ ++ result = fence_action(conn, options, set_power_status, get_power_status, get_list) ++ ++ sys.exit(result) ++ ++if __name__ == "__main__": ++ main() +diff --git a/tests/data/metadata/fence_ibm_powervs.xml b/tests/data/metadata/fence_ibm_powervs.xml +new file mode 100644 +index 000000000..fe86331bd +--- /dev/null ++++ b/tests/data/metadata/fence_ibm_powervs.xml +@@ -0,0 +1,134 @@ ++ ++ ++fence_ibm_powervs is an I/O Fencing agent which can be used with IBM PowerVS to fence virtual machines. ++https://www.ibm.com ++ ++ ++ ++ ++ CRN ++ ++ ++ ++ ++ PowerVS Instance ++ ++ ++ ++ ++ Region ++ ++ ++ ++ ++ Bearer Token ++ ++ ++ ++ ++ Fencing action ++ ++ ++ ++ ++ Physical plug number on device, UUID or identification of machine ++ ++ ++ ++ ++ Physical plug number on device, UUID or identification of machine ++ ++ ++ ++ ++ Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. ++ ++ ++ ++ ++ Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity. ++ ++ ++ ++ ++ Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin). ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ Display version information and exit ++ ++ ++ ++ ++ Display help and exit ++ ++ ++ ++ ++ Separator for CSV created by 'list' operation ++ ++ ++ ++ ++ Wait X seconds before fencing is started ++ ++ ++ ++ ++ Disable timeout (true/false) (default: true when run from Pacemaker 2.0+) ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after login ++ ++ ++ ++ ++ Test X seconds for status change after ON/OFF ++ ++ ++ ++ ++ Wait X seconds after issuing ON/OFF ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after issuing command ++ ++ ++ ++ ++ Sleep X seconds between status calls during a STONITH action ++ ++ ++ ++ ++ Count of attempts to retry power on ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/data/metadata/fence_ibm_vpc.xml b/tests/data/metadata/fence_ibm_vpc.xml +new file mode 100644 +index 000000000..926efcaa0 +--- /dev/null ++++ b/tests/data/metadata/fence_ibm_vpc.xml +@@ -0,0 +1,134 @@ ++ ++ ++fence_ibm_vpc is an I/O Fencing agent which can be used with IBM Cloud VPC to fence virtual machines. ++https://www.ibm.com ++ ++ ++ ++ ++ API Key ++ ++ ++ ++ ++ Cloud Instance ++ ++ ++ ++ ++ Number of nodes returned by API ++ ++ ++ ++ ++ Region ++ ++ ++ ++ ++ Fencing action ++ ++ ++ ++ ++ Physical plug number on device, UUID or identification of machine ++ ++ ++ ++ ++ Physical plug number on device, UUID or identification of machine ++ ++ ++ ++ ++ Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. ++ ++ ++ ++ ++ Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity. ++ ++ ++ ++ ++ Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin). ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ Display version information and exit ++ ++ ++ ++ ++ Display help and exit ++ ++ ++ ++ ++ Separator for CSV created by 'list' operation ++ ++ ++ ++ ++ Wait X seconds before fencing is started ++ ++ ++ ++ ++ Disable timeout (true/false) (default: true when run from Pacemaker 2.0+) ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after login ++ ++ ++ ++ ++ Test X seconds for status change after ON/OFF ++ ++ ++ ++ ++ Wait X seconds after issuing ON/OFF ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after issuing command ++ ++ ++ ++ ++ Sleep X seconds between status calls during a STONITH action ++ ++ ++ ++ ++ Count of attempts to retry power on ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ diff --git a/SOURCES/bz2065114-fence_lpar-refactor.patch b/SOURCES/bz2065114-fence_lpar-refactor.patch new file mode 100644 index 0000000..599a22c --- /dev/null +++ b/SOURCES/bz2065114-fence_lpar-refactor.patch @@ -0,0 +1,65 @@ +From e3dff8570b70f0c19eca84cf02f0aadd68e16599 Mon Sep 17 00:00:00 2001 +From: Thomas Renninger +Date: Fri, 25 Feb 2022 14:05:42 +0100 +Subject: [PATCH] fence_lpar: fix missing import logging, use fail_usage + +and slightly re-factor code to avoid duplicate code lines. +Should be cleanup only, no functional change. +--- + agents/lpar/fence_lpar.py | 39 ++++++++++++++++++--------------------- + 1 file changed, 18 insertions(+), 21 deletions(-) + +diff --git a/agents/lpar/fence_lpar.py b/agents/lpar/fence_lpar.py +index ad18c6191..2046b0e4e 100644 +--- a/agents/lpar/fence_lpar.py ++++ b/agents/lpar/fence_lpar.py +@@ -28,31 +28,28 @@ def _normalize_status(status): + + def get_power_status(conn, options): + if options["--hmc-version"] == "3": +- conn.send("lssyscfg -r lpar -m " + options["--managed"] + " -n " + options["--plug"] + " -F name,state\n") +- +- # First line (command) may cause parsing issues if long +- conn.readline() +- conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) +- +- try: +- status = re.compile("^" + options["--plug"] + ",(.*?),.*$", +- re.IGNORECASE | re.MULTILINE).search(conn.before).group(1) +- except AttributeError as e: +- logging.error("Failed: {}".format(str(e))) +- fail(EC_STATUS_HMC) ++ command = "lssyscfg -r lpar -m " + options["--managed"] + " -n " + options["--plug"] + " -F name,state\n" + elif options["--hmc-version"] in ["4", "IVM"]: +- conn.send("lssyscfg -r lpar -m "+ options["--managed"] + +- " --filter 'lpar_names=" + options["--plug"] + "'\n") ++ command = "lssyscfg -r lpar -m "+ options["--managed"] + \ ++ " --filter 'lpar_names=" + options["--plug"] + "'\n" ++ else: ++ # Bad HMC Version cannot be reached ++ fail(EC_STATUS_HMC) + +- # First line (command) may cause parsing issues if long +- conn.readline() +- conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) ++ conn.send(command) ++ # First line (command) may cause parsing issues if long ++ conn.readline() ++ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) + +- try: ++ try: ++ if options["--hmc-version"] == "3": ++ status = re.compile("^" + options["--plug"] + ",(.*?),.*$", ++ re.IGNORECASE | re.MULTILINE).search(conn.before).group(1) ++ elif options["--hmc-version"] in ["4", "IVM"]: + status = re.compile(",state=(.*?),", re.IGNORECASE).search(conn.before).group(1) +- except AttributeError as e: +- logging.error("Failed: {}".format(str(e))) +- fail(EC_STATUS_HMC) ++ except AttributeError as e: ++ fail_usage("Command on HMC failed: {}\n{}".format(command, str(e)), False) ++ fail(EC_STATUS_HMC) + + return _normalize_status(status) + diff --git a/SOURCES/bz2072420-1-all-agents-unify-ssl-parameters.patch b/SOURCES/bz2072420-1-all-agents-unify-ssl-parameters.patch new file mode 100644 index 0000000..6f8f0af --- /dev/null +++ b/SOURCES/bz2072420-1-all-agents-unify-ssl-parameters.patch @@ -0,0 +1,291 @@ +From 999f2f8b4dc7d258679daf8c3f13d9b317ff4435 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 7 Apr 2022 13:11:12 +0200 +Subject: [PATCH] all agents: unify ssl parameters to avoid having to use --ssl + when using --ssl-secure/--ssl-insecure for some agents + +THIS MIGHT BREAK SETUPS USING fence_docker or fence_pve! +--- + agents/cisco_ucs/fence_cisco_ucs.py | 9 +++++---- + agents/docker/fence_docker.py | 9 ++++++--- + agents/ibmz/fence_ibmz.py | 4 ++-- + agents/rhevm/fence_rhevm.py | 8 ++++---- + agents/skalar/fence_skalar.py | 2 +- + agents/vmware_rest/fence_vmware_rest.py | 8 ++++---- + agents/vmware_soap/fence_vmware_soap.py | 2 +- + agents/vmware_vcloud/fence_vmware_vcloud.py | 4 ++-- + agents/zvm/fence_zvmip.py | 8 +++++--- + lib/fencing.py.py | 6 ++++++ + tests/data/metadata/fence_docker.xml | 4 ++-- + 13 files changed, 64 insertions(+), 31 deletions(-) + +diff --git a/agents/cisco_ucs/fence_cisco_ucs.py b/agents/cisco_ucs/fence_cisco_ucs.py +index 2280dbbc7..b85379a73 100644 +--- a/agents/cisco_ucs/fence_cisco_ucs.py ++++ b/agents/cisco_ucs/fence_cisco_ucs.py +@@ -99,7 +99,7 @@ def get_list(conn, options): + + def send_command(opt, command, timeout): + ## setup correct URL +- if "--ssl" in opt or "--ssl-secure" in opt or "--ssl-insecure" in opt: ++ if "--ssl-secure" in opt or "--ssl-insecure" in opt: + url = "https:" + else: + url = "http:" +@@ -114,13 +114,14 @@ def send_command(opt, command, timeout): + conn.setopt(pycurl.POSTFIELDS, command.encode("ascii")) + conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write) + conn.setopt(pycurl.TIMEOUT, timeout) +- if "--ssl" in opt or "--ssl-secure" in opt: ++ ++ if "--ssl-secure" in opt: + conn.setopt(pycurl.SSL_VERIFYPEER, 1) + conn.setopt(pycurl.SSL_VERIFYHOST, 2) +- +- if "--ssl-insecure" in opt: ++ elif "--ssl-insecure" in opt: + conn.setopt(pycurl.SSL_VERIFYPEER, 0) + conn.setopt(pycurl.SSL_VERIFYHOST, 0) ++ + conn.perform() + result = web_buffer.getvalue().decode() + +diff --git a/agents/docker/fence_docker.py b/agents/docker/fence_docker.py +index fef87da86..004402518 100644 +--- a/agents/docker/fence_docker.py ++++ b/agents/docker/fence_docker.py +@@ -43,7 +43,7 @@ def get_list(conn, options): + + + def send_cmd(options, cmd, post = False): +- url = "http%s://%s:%s/v%s/%s" % ("s" if "--ssl" in options else "", options["--ip"], options["--ipport"], options["--api-version"], cmd) ++ url = "http%s://%s:%s/v%s/%s" % ("s" if "--ssl-secure" in options or "--ssl-insecure" in options else "", options["--ip"], options["--ipport"], options["--api-version"], cmd) + conn = pycurl.Curl() + output_buffer = io.BytesIO() + if logging.getLogger().getEffectiveLevel() < logging.WARNING: +@@ -55,7 +55,8 @@ def send_cmd(options, cmd, post = False): + conn.setopt(pycurl.POSTFIELDSIZE, 0) + conn.setopt(pycurl.WRITEFUNCTION, output_buffer.write) + conn.setopt(pycurl.TIMEOUT, int(options["--shell-timeout"])) +- if "--ssl" in options: ++ ++ if "--ssl-secure" in options: + if not (set(("--tlscert", "--tlskey", "--tlscacert")) <= set(options)): + fail_usage("Failed. If --ssl option is used, You have to also \ + specify: --tlscert, --tlskey and --tlscacert") +@@ -63,7 +64,7 @@ def send_cmd(options, cmd, post = False): + conn.setopt(pycurl.SSLCERT, options["--tlscert"]) + conn.setopt(pycurl.SSLKEY, options["--tlskey"]) + conn.setopt(pycurl.CAINFO, options["--tlscacert"]) +- else: ++ elif "--ssl-insecure" in options: + conn.setopt(pycurl.SSL_VERIFYPEER, 0) + conn.setopt(pycurl.SSL_VERIFYHOST, 0) + +@@ -136,6 +137,8 @@ def main(): + + device_opt = ["ipaddr", "no_password", "no_login", "port", "method", "web", "tlscert", "tlskey", "tlscacert", "ssl", "api_version"] + ++ all_opt["ssl"]["default"] = "1" ++ + options = check_input(device_opt, process_input(device_opt)) + + docs = { } +diff --git a/agents/ibmz/fence_ibmz.py b/agents/ibmz/fence_ibmz.py +index 47408ccf4..d477adeb9 100644 +--- a/agents/ibmz/fence_ibmz.py ++++ b/agents/ibmz/fence_ibmz.py +@@ -534,7 +534,7 @@ def main(): + requests_log.propagate = True + if "--verbose" in options: + requests_log.setLevel(logging.DEBUG) +- if "--ssl-secure" not in options: ++ if "--ssl-insecure" in options: + urllib3.disable_warnings( + category=urllib3.exceptions.InsecureRequestWarning) + +@@ -548,7 +548,7 @@ def main(): + 'connect_timeout': int(options['--connect-timeout']), + 'read_timeout': int(options['--read-timeout']), + 'port': int(options['--ipport']), +- 'ssl_verify': bool('--ssl-secure' in options), ++ 'ssl_verify': bool('--ssl-insecure' not in options), + } + try: + conn = APIClient(hmc_address, hmc_userid, hmc_password, config) +diff --git a/agents/rhevm/fence_rhevm.py b/agents/rhevm/fence_rhevm.py +index 25aecbe58..5f74d06f6 100644 +--- a/agents/rhevm/fence_rhevm.py ++++ b/agents/rhevm/fence_rhevm.py +@@ -85,7 +85,7 @@ def send_command(opt, command, method="GET"): + logging.debug("auto-detected API version: " + opt["--api-version"]) + + ## setup correct URL +- if "--ssl" in opt or "--ssl-secure" in opt or "--ssl-insecure" in opt: ++ if "--ssl-secure" in opt or "--ssl-insecure" in opt: + url = "https:" + else: + url = "http:" +@@ -126,11 +126,11 @@ def send_command(opt, command, method="GET"): + conn.setopt(pycurl.COOKIEJAR, cookie_file) + + conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) +- if "--ssl" in opt or "--ssl-secure" in opt: ++ ++ if "--ssl-secure" in opt: + conn.setopt(pycurl.SSL_VERIFYPEER, 1) + conn.setopt(pycurl.SSL_VERIFYHOST, 2) +- +- if "--ssl-insecure" in opt: ++ elif "--ssl-insecure" in opt: + conn.setopt(pycurl.SSL_VERIFYPEER, 0) + conn.setopt(pycurl.SSL_VERIFYHOST, 0) + +diff --git a/agents/skalar/fence_skalar.py b/agents/skalar/fence_skalar.py +index 959527411..0e11d83f9 100644 +--- a/agents/skalar/fence_skalar.py ++++ b/agents/skalar/fence_skalar.py +@@ -200,7 +200,7 @@ def main(): + run_delay(options) + + proto = "https://" +- if "--ssl" in options or "--ssl-secure" in options: ++ if "--ssl-secure" in options: + ssl_verify = True + elif "--ssl-insecure" in options: + ssl_verify = False +diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py +index e49fd5663..4b884fc62 100644 +--- a/agents/vmware_rest/fence_vmware_rest.py ++++ b/agents/vmware_rest/fence_vmware_rest.py +@@ -69,7 +69,7 @@ def connect(opt): + conn = pycurl.Curl() + + ## setup correct URL +- if "--ssl" in opt or "--ssl-secure" in opt or "--ssl-insecure" in opt: ++ if "--ssl-secure" in opt or "--ssl-insecure" in opt: + conn.base_url = "https:" + else: + conn.base_url = "http:" +@@ -89,11 +89,11 @@ def connect(opt): + conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"]) + + conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) +- if "--ssl" in opt or "--ssl-secure" in opt: ++ ++ if "--ssl-secure" in opt: + conn.setopt(pycurl.SSL_VERIFYPEER, 1) + conn.setopt(pycurl.SSL_VERIFYHOST, 2) +- +- if "--ssl-insecure" in opt: ++ elif "--ssl-insecure" in opt: + conn.setopt(pycurl.SSL_VERIFYPEER, 0) + conn.setopt(pycurl.SSL_VERIFYHOST, 0) + +diff --git a/agents/vmware_soap/fence_vmware_soap.py b/agents/vmware_soap/fence_vmware_soap.py +index 2cd45e0b3..51fb0f147 100644 +--- a/agents/vmware_soap/fence_vmware_soap.py ++++ b/agents/vmware_soap/fence_vmware_soap.py +@@ -34,7 +34,7 @@ def send(self, request): + def soap_login(options): + run_delay(options) + +- if "--ssl" in options or "--ssl-secure" in options or "--ssl-insecure" in options: ++ if "--ssl-secure" in options or "--ssl-insecure" in options: + if "--ssl-insecure" in options: + import ssl + import urllib3 +diff --git a/agents/vmware_vcloud/fence_vmware_vcloud.py b/agents/vmware_vcloud/fence_vmware_vcloud.py +index 42372a83d..7626b82bb 100644 +--- a/agents/vmware_vcloud/fence_vmware_vcloud.py ++++ b/agents/vmware_vcloud/fence_vmware_vcloud.py +@@ -60,7 +60,7 @@ def connect(opt): + conn = pycurl.Curl() + + ## setup correct URL +- if "--ssl" in opt or "--ssl-secure" in opt or "--ssl-insecure" in opt: ++ if "--ssl-secure" in opt or "--ssl-insecure" in opt: + conn.base_url = "https:" + else: + conn.base_url = "http:" +@@ -76,7 +76,7 @@ def connect(opt): + conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"]) + + conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) +- if "--ssl" in opt or "--ssl-secure" in opt: ++ if "--ssl-secure" in opt: + conn.setopt(pycurl.SSL_VERIFYPEER, 1) + conn.setopt(pycurl.SSL_VERIFYHOST, 2) + elif "--ssl-insecure" in opt: +diff --git a/agents/zvm/fence_zvmip.py b/agents/zvm/fence_zvmip.py +index e8f849eda..90ca95d45 100644 +--- a/agents/zvm/fence_zvmip.py ++++ b/agents/zvm/fence_zvmip.py +@@ -26,7 +26,7 @@ def open_socket(options): + except socket.gaierror: + fail(EC_LOGIN_DENIED) + +- if "--ssl" in options: ++ if "--ssl-secure" in options or "--ssl-insecure" in options: + import ssl + sock = socket.socket() + sslcx = ssl.create_default_context() +@@ -132,7 +132,7 @@ def get_list_of_images(options, command, data_as_plug): + images = set() + + if output_len > 3*INT4: +- recvflag = socket.MSG_WAITALL if "--ssl" not in options else 0 ++ recvflag = socket.MSG_WAITALL if "--ssl-secure" not in options and "--ssl-insecure" not in options else 0 + array_len = struct.unpack("!i", conn.recv(INT4))[0] + data = "" + +@@ -182,7 +182,9 @@ def main(): + options = check_input(device_opt, process_input(device_opt), other_conditions=True) + + if "--disable-ssl" in options or options["--ssl"] == "0": +- del options["--ssl"] ++ for k in ["--ssl", "--ssl-secure", "--ssl-insecure"]: ++ if k in options: ++ del options[k] + + if len(options.get("--plug", "")) > 8: + fail_usage("Failed: Name of image can not be longer than 8 characters") +diff --git a/lib/fencing.py.py b/lib/fencing.py.py +index 696388d55..b746ede8b 100644 +--- a/lib/fencing.py.py ++++ b/lib/fencing.py.py +@@ -789,6 +789,12 @@ def check_input(device_opt, opt, other_conditions = False): + if "--password-script" in options: + options["--password"] = os.popen(options["--password-script"]).read().rstrip() + ++ if "--ssl-secure" in options or "--ssl-insecure" in options: ++ options["--ssl"] = "" ++ ++ if "--ssl" in options and "--ssl-insecure" not in options: ++ options["--ssl-secure"] = "" ++ + if os.environ.get("PCMK_service") == "pacemaker-fenced" and "--disable-timeout" not in options: + options["--disable-timeout"] = "1" + +diff --git a/tests/data/metadata/fence_docker.xml b/tests/data/metadata/fence_docker.xml +index 723e72280..51c7c470a 100644 +--- a/tests/data/metadata/fence_docker.xml ++++ b/tests/data/metadata/fence_docker.xml +@@ -20,7 +20,7 @@ + + + +- ++ + TCP/UDP port to use for connection with device + + +@@ -43,7 +43,7 @@ + + + +- ++ + Use SSL connection with verifying certificate + + diff --git a/SOURCES/bz2072420-2-fence_zvmip-connect-error.patch b/SOURCES/bz2072420-2-fence_zvmip-connect-error.patch new file mode 100644 index 0000000..1a1bd97 --- /dev/null +++ b/SOURCES/bz2072420-2-fence_zvmip-connect-error.patch @@ -0,0 +1,30 @@ +From 6430104318b4bf349425b08636183bf839812e04 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 31 May 2022 08:55:25 +0200 +Subject: [PATCH] fence_zvmip: show unable to connect error instead of full + stacktrace, e.g. when not using --ssl for SSL devices + +--- + agents/zvm/fence_zvmip.py | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/agents/zvm/fence_zvmip.py b/agents/zvm/fence_zvmip.py +index 90ca95d45..4f538e10d 100644 +--- a/agents/zvm/fence_zvmip.py ++++ b/agents/zvm/fence_zvmip.py +@@ -127,8 +127,13 @@ def get_list_of_images(options, command, data_as_plug): + + conn.send(packet) + +- request_id = struct.unpack("!i", conn.recv(INT4))[0] +- (output_len, request_id, return_code, reason_code) = struct.unpack("!iiii", conn.recv(INT4 * 4)) ++ try: ++ request_id = struct.unpack("!i", conn.recv(INT4))[0] ++ (output_len, request_id, return_code, reason_code) = struct.unpack("!iiii", conn.recv(INT4 * 4)) ++ except struct.error: ++ logging.debug(sys.exc_info()) ++ fail_usage("Failed: Unable to connect to {} port: {} SSL: {} \n".format(options["--ip"], options["--ipport"], bool("--ssl" in options))) ++ + images = set() + + if output_len > 3*INT4: diff --git a/SOURCES/bz2079889-fence_gce-update.patch b/SOURCES/bz2079889-fence_gce-update.patch new file mode 100644 index 0000000..97e5193 --- /dev/null +++ b/SOURCES/bz2079889-fence_gce-update.patch @@ -0,0 +1,410 @@ +--- fence-agents-4.10.0/agents/gce/fence_gce.py 2022-04-29 10:13:50.317888041 +0200 ++++ fence-agents-4.10.0/agents/gce/fence_gce.py2 2022-04-29 10:17:54.813248566 +0200 +@@ -2,10 +2,10 @@ + + # + # Requires the googleapiclient and oauth2client +-# RHEL 7.x: google-api-python-client==1.6.7 python-gflags==2.0 pyasn1==0.4.8 rsa==3.4.2 +-# RHEL 8.x: nothing additional needed +-# SLES 12.x: python-google-api-python-client python-oauth2client python-oauth2client-gce +-# SLES 15.x: python3-google-api-python-client python3-oauth2client python3-oauth2client-gce ++# RHEL 7.x: google-api-python-client==1.6.7 python-gflags==2.0 pyasn1==0.4.8 rsa==3.4.2 pysocks==1.7.1 httplib2==0.19.0 ++# RHEL 8.x: pysocks==1.7.1 httplib2==0.19.0 ++# SLES 12.x: python-google-api-python-client python-oauth2client python-oauth2client-gce pysocks==1.7.1 httplib2==0.19.0 ++# SLES 15.x: python3-google-api-python-client python3-oauth2client pysocks==1.7.1 httplib2==0.19.0 + # + + import atexit +@@ -27,7 +27,7 @@ + import urllib2 as urlrequest + sys.path.append("@FENCEAGENTSLIBDIR@") + +-from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action ++from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action, run_command + try: + sys.path.insert(0, '/usr/lib/fence-agents/support/google') + import httplib2 +@@ -42,6 +42,19 @@ + + METADATA_SERVER = 'http://metadata.google.internal/computeMetadata/v1/' + METADATA_HEADERS = {'Metadata-Flavor': 'Google'} ++INSTANCE_LINK = 'https://www.googleapis.com/compute/v1/projects/{}/zones/{}/instances/{}' ++ ++def run_on_fail(options): ++ if "--runonfail" in options: ++ run_command(options, options["--runonfail"]) ++ ++def fail_fence_agent(options, message): ++ run_on_fail(options) ++ fail_usage(message) ++ ++def raise_fence_agent(options, message): ++ run_on_fail(options) ++ raise Exception(message) + + # + # Will use baremetalsolution setting or the environment variable +@@ -66,7 +79,7 @@ + { + "matchlength": 4, + "match": "https://compute.googleapis.com/compute/v1/projects/(.*)/zones/(.*)/instances/(.*)/reset(.*)", +- "replace": "https://baremetalsolution.googleapis.com/v1alpha1/projects/\\1/locations/\\2/instances/\\3:resetInstance\\4" ++ "replace": "https://baremetalsolution.googleapis.com/v1/projects/\\1/locations/\\2/instances/\\3:resetInstance\\4" + }) + for uri_replacement in uri_replacements: + # each uri_replacement should have matchlength, match, and replace +@@ -121,14 +134,17 @@ + + def get_nodes_list(conn, options): + result = {} ++ if "--zone" not in options: ++ fail_fence_agent(options, "Failed: get_nodes_list: Please specify the --zone in the command") + try: +- instanceList = retry_api_execute(options, conn.instances().list( +- project=options["--project"], +- zone=options["--zone"])) +- for instance in instanceList["items"]: +- result[instance["id"]] = (instance["name"], translate_status(instance["status"])) ++ for zone in options["--zone"].split(","): ++ instanceList = retry_api_execute(options, conn.instances().list( ++ project=options["--project"], ++ zone=zone)) ++ for instance in instanceList["items"]: ++ result[instance["id"]] = (instance["name"], translate_status(instance["status"])) + except Exception as err: +- fail_usage("Failed: get_nodes_list: {}".format(str(err))) ++ fail_fence_agent(options, "Failed: get_nodes_list: {}".format(str(err))) + + return result + +@@ -142,23 +158,54 @@ + return "off" + else: + return "on" ++ # If zone is not listed for an entry we attempt to get it automatically ++ instance = options["--plug"] ++ zone = get_zone(conn, options, instance) if "--plugzonemap" not in options else options["--plugzonemap"][instance] ++ instance_status = get_instance_power_status(conn, options, instance, zone) ++ # If any of the instances do not match the intended status we return the ++ # the opposite status so that the fence agent can change it. ++ if instance_status != options.get("--action"): ++ return instance_status ++ ++ return options.get("--action") ++ ++ ++def get_instance_power_status(conn, options, instance, zone): + try: +- instance = retry_api_execute(options, conn.instances().get( +- project=options["--project"], +- zone=options["--zone"], +- instance=options["--plug"])) ++ instance = retry_api_execute( ++ options, ++ conn.instances().get(project=options["--project"], zone=zone, instance=instance)) + return translate_status(instance["status"]) + except Exception as err: +- fail_usage("Failed: get_power_status: {}".format(str(err))) ++ fail_fence_agent(options, "Failed: get_instance_power_status: {}".format(str(err))) + + +-def wait_for_operation(conn, options, operation): ++def check_for_existing_operation(conn, options, instance, zone, operation_type): ++ logging.debug("check_for_existing_operation") ++ if "--baremetalsolution" in options: ++ # There is no API for checking in progress operations ++ return False ++ ++ project = options["--project"] ++ target_link = INSTANCE_LINK.format(project, zone, instance) ++ query_filter = '(targetLink = "{}") AND (operationType = "{}") AND (status = "RUNNING")'.format(target_link, operation_type) ++ result = retry_api_execute( ++ options, ++ conn.zoneOperations().list(project=project, zone=zone, filter=query_filter, maxResults=1)) ++ ++ if "items" in result and result["items"]: ++ logging.info("Existing %s operation found", operation_type) ++ return result["items"][0] ++ ++ ++def wait_for_operation(conn, options, zone, operation): + if 'name' not in operation: + logging.warning('Cannot wait for operation to complete, the' + ' requested operation will continue asynchronously') +- return ++ return False ++ ++ wait_time = 0 + project = options["--project"] +- zone = options["--zone"] + while True: + result = retry_api_execute(options, conn.zoneOperations().get( + project=project, +@@ -166,56 +213,93 @@ + operation=operation['name'])) + if result['status'] == 'DONE': + if 'error' in result: +- raise Exception(result['error']) +- return ++ raise_fence_agent(options, result['error']) ++ return True ++ ++ if "--errortimeout" in options and wait_time > int(options["--errortimeout"]): ++ raise_fence_agent(options, "Operation did not complete before the timeout.") ++ ++ if "--warntimeout" in options and wait_time > int(options["--warntimeout"]): ++ logging.warning("Operation did not complete before the timeout.") ++ if "--runonwarn" in options: ++ run_command(options, options["--runonwarn"]) ++ return False ++ ++ wait_time = wait_time + 1 + time.sleep(1) + + + def set_power_status(conn, options): +- logging.debug("set_power_status"); ++ logging.debug("set_power_status") ++ instance = options["--plug"] ++ # If zone is not listed for an entry we attempt to get it automatically ++ zone = get_zone(conn, options, instance) if "--plugzonemap" not in options else options["--plugzonemap"][instance] ++ set_instance_power_status(conn, options, instance, zone, options["--action"]) ++ ++ ++def set_instance_power_status(conn, options, instance, zone, action): ++ logging.info("Setting power status of %s in zone %s", instance, zone) ++ project = options["--project"] ++ + try: +- if options["--action"] == "off": +- logging.info("Issuing poweroff of %s in zone %s" % (options["--plug"], options["--zone"])) +- operation = retry_api_execute(options, conn.instances().stop( +- project=options["--project"], +- zone=options["--zone"], +- instance=options["--plug"])) ++ if action == "off": ++ logging.info("Issuing poweroff of %s in zone %s", instance, zone) ++ operation = check_for_existing_operation(conn, options, instance, zone, "stop") ++ if operation and "--earlyexit" in options: ++ return ++ if not operation: ++ operation = retry_api_execute( ++ options, ++ conn.instances().stop(project=project, zone=zone, instance=instance)) + logging.info("Poweroff command completed, waiting for the operation to complete") +- wait_for_operation(conn, options, operation) +- logging.info("Poweroff of %s in zone %s complete" % (options["--plug"], options["--zone"])) +- elif options["--action"] == "on": +- logging.info("Issuing poweron of %s in zone %s" % (options["--plug"], options["--zone"])) +- operation = retry_api_execute(options, conn.instances().start( +- project=options["--project"], +- zone=options["--zone"], +- instance=options["--plug"])) +- wait_for_operation(conn, options, operation) +- logging.info("Poweron of %s in zone %s complete" % (options["--plug"], options["--zone"])) ++ if wait_for_operation(conn, options, zone, operation): ++ logging.info("Poweroff of %s in zone %s complete", instance, zone) ++ elif action == "on": ++ logging.info("Issuing poweron of %s in zone %s", instance, zone) ++ operation = check_for_existing_operation(conn, options, instance, zone, "start") ++ if operation and "--earlyexit" in options: ++ return ++ if not operation: ++ operation = retry_api_execute( ++ options, ++ conn.instances().start(project=project, zone=zone, instance=instance)) ++ if wait_for_operation(conn, options, zone, operation): ++ logging.info("Poweron of %s in zone %s complete", instance, zone) + except Exception as err: +- fail_usage("Failed: set_power_status: {}".format(str(err))) +- ++ fail_fence_agent(options, "Failed: set_instance_power_status: {}".format(str(err))) + + def power_cycle(conn, options): +- logging.debug("power_cycle"); ++ logging.debug("power_cycle") ++ instance = options["--plug"] ++ # If zone is not listed for an entry we attempt to get it automatically ++ zone = get_zone(conn, options, instance) if "--plugzonemap" not in options else options["--plugzonemap"][instance] ++ return power_cycle_instance(conn, options, instance, zone) ++ ++ ++def power_cycle_instance(conn, options, instance, zone): ++ logging.info("Issuing reset of %s in zone %s", instance, zone) ++ project = options["--project"] ++ + try: +- logging.info('Issuing reset of %s in zone %s' % (options["--plug"], options["--zone"])) +- operation = retry_api_execute(options, conn.instances().reset( +- project=options["--project"], +- zone=options["--zone"], +- instance=options["--plug"])) +- logging.info("Reset command completed, waiting for the operation to complete") +- wait_for_operation(conn, options, operation) +- logging.info('Reset of %s in zone %s complete' % (options["--plug"], options["--zone"])) ++ operation = check_for_existing_operation(conn, options, instance, zone, "reset") ++ if operation and "--earlyexit" in options: ++ return True ++ if not operation: ++ operation = retry_api_execute( ++ options, ++ conn.instances().reset(project=project, zone=zone, instance=instance)) ++ logging.info("Reset command sent, waiting for the operation to complete") ++ if wait_for_operation(conn, options, zone, operation): ++ logging.info("Reset of %s in zone %s complete", instance, zone) + return True + except Exception as err: +- logging.error("Failed: power_cycle: {}".format(str(err))) +- return False ++ logging.exception("Failed: power_cycle") ++ raise err + + +-def get_zone(conn, options): ++def get_zone(conn, options, instance): + logging.debug("get_zone"); + project = options['--project'] +- instance = options['--plug'] + fl = 'name="%s"' % instance + request = replace_api_uri(options, conn.instances().aggregatedList(project=project, filter=fl)) + while request is not None: +@@ -227,7 +311,7 @@ + return inst['zone'].split("/")[-1] + request = replace_api_uri(options, conn.instances().aggregatedList_next( + previous_request=request, previous_response=response)) +- raise Exception("Unable to find instance %s" % (instance)) ++ raise_fence_agent(options, "Unable to find instance %s" % (instance)) + + + def get_metadata(metadata_key, params=None, timeout=None): +@@ -326,13 +410,21 @@ + "required" : "0", + "order" : 9 + } ++ all_opt["plugzonemap"] = { ++ "getopt" : ":", ++ "longopt" : "plugzonemap", ++ "help" : "--plugzonemap=[plugzonemap] Comma separated zone map when fencing multiple plugs", ++ "shortdesc" : "Comma separated zone map when fencing multiple plugs.", ++ "required" : "0", ++ "order" : 10 ++ } + all_opt["proxyhost"] = { + "getopt" : ":", + "longopt" : "proxyhost", + "help" : "--proxyhost=[proxy_host] The proxy host to use, if one is needed to access the internet (Example: 10.122.0.33)", + "shortdesc" : "If a proxy is used for internet access, the proxy host should be specified.", + "required" : "0", +- "order" : 10 ++ "order" : 11 + } + all_opt["proxyport"] = { + "getopt" : ":", +@@ -341,7 +433,49 @@ + "help" : "--proxyport=[proxy_port] The proxy port to use, if one is needed to access the internet (Example: 3127)", + "shortdesc" : "If a proxy is used for internet access, the proxy port should be specified.", + "required" : "0", +- "order" : 11 ++ "order" : 12 ++ } ++ all_opt["earlyexit"] = { ++ "getopt" : "", ++ "longopt" : "earlyexit", ++ "help" : "--earlyexit Return early if reset is already in progress", ++ "shortdesc" : "If an existing reset operation is detected, the fence agent will return before the operation completes with a 0 return code.", ++ "required" : "0", ++ "order" : 13 ++ } ++ all_opt["warntimeout"] = { ++ "getopt" : ":", ++ "type" : "second", ++ "longopt" : "warntimeout", ++ "help" : "--warntimeout=[warn_timeout] Timeout seconds before logging a warning and returning a 0 status code", ++ "shortdesc" : "If the operation is not completed within the timeout, the cluster operations are allowed to continue.", ++ "required" : "0", ++ "order" : 14 ++ } ++ all_opt["errortimeout"] = { ++ "getopt" : ":", ++ "type" : "second", ++ "longopt" : "errortimeout", ++ "help" : "--errortimeout=[error_timeout] Timeout seconds before failing and returning a non-zero status code", ++ "shortdesc" : "If the operation is not completed within the timeout, cluster is notified of the operation failure.", ++ "required" : "0", ++ "order" : 15 ++ } ++ all_opt["runonwarn"] = { ++ "getopt" : ":", ++ "longopt" : "runonwarn", ++ "help" : "--runonwarn=[run_on_warn] If a timeout occurs and warning is generated, run the supplied command", ++ "shortdesc" : "If a timeout would occur while running the agent, then the supplied command is run.", ++ "required" : "0", ++ "order" : 16 ++ } ++ all_opt["runonfail"] = { ++ "getopt" : ":", ++ "longopt" : "runonfail", ++ "help" : "--runonfail=[run_on_fail] If a failure occurs, run the supplied command", ++ "shortdesc" : "If a failure would occur while running the agent, then the supplied command is run.", ++ "required" : "0", ++ "order" : 17 + } + + +@@ -350,7 +484,8 @@ + + device_opt = ["port", "no_password", "zone", "project", "stackdriver-logging", + "method", "baremetalsolution", "apitimeout", "retries", "retrysleep", +- "serviceaccount", "proxyhost", "proxyport"] ++ "serviceaccount", "plugzonemap", "proxyhost", "proxyport", "earlyexit", ++ "warntimeout", "errortimeout", "runonwarn", "runonfail"] + + atexit.register(atexit_handler) + +@@ -431,22 +566,39 @@ + conn = googleapiclient.discovery.build( + 'compute', 'v1', credentials=credentials, cache_discovery=False) + except Exception as err: +- fail_usage("Failed: Create GCE compute v1 connection: {}".format(str(err))) ++ fail_fence_agent(options, "Failed: Create GCE compute v1 connection: {}".format(str(err))) + + # Get project and zone + if not options.get("--project"): + try: + options["--project"] = get_metadata('project/project-id') + except Exception as err: +- fail_usage("Failed retrieving GCE project. Please provide --project option: {}".format(str(err))) ++ fail_fence_agent(options, "Failed retrieving GCE project. Please provide --project option: {}".format(str(err))) + + if "--baremetalsolution" in options: + options["--zone"] = "none" +- if not options.get("--zone"): +- try: +- options["--zone"] = get_zone(conn, options) +- except Exception as err: +- fail_usage("Failed retrieving GCE zone. Please provide --zone option: {}".format(str(err))) ++ ++ # Populates zone automatically if missing from the command ++ zones = [] if not "--zone" in options else options["--zone"].split(",") ++ options["--plugzonemap"] = {} ++ if "--plug" in options: ++ for i, instance in enumerate(options["--plug"].split(",")): ++ if len(zones) == 1: ++ # If only one zone is specified, use it across all plugs ++ options["--plugzonemap"][instance] = zones[0] ++ continue ++ ++ if len(zones) - 1 >= i: ++ # If we have enough zones specified with the --zone flag use the zone at ++ # the same index as the plug ++ options["--plugzonemap"][instance] = zones[i] ++ continue ++ ++ try: ++ # In this case we do not have a zone specified so we attempt to detect it ++ options["--plugzonemap"][instance] = get_zone(conn, options, instance) ++ except Exception as err: ++ fail_fence_agent(options, "Failed retrieving GCE zone. Please provide --zone option: {}".format(str(err))) + + # Operate the fencing device + result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list, power_cycle) diff --git a/SOURCES/bz2081235-fence_ibm_vpc-fix-parameters.patch b/SOURCES/bz2081235-fence_ibm_vpc-fix-parameters.patch new file mode 100644 index 0000000..5e031ad --- /dev/null +++ b/SOURCES/bz2081235-fence_ibm_vpc-fix-parameters.patch @@ -0,0 +1,65 @@ +From d0254345472c9415af1e06e9e8df2fe0ce464db0 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 2 May 2022 11:14:42 +0200 +Subject: [PATCH] fence_ibm_vpc: remove unused instance parameter and make + limit optional + +--- + agents/ibm_vpc/fence_ibm_vpc.py | 11 +---------- + tests/data/metadata/fence_ibm_vpc.xml | 7 +------ + 2 files changed, 2 insertions(+), 16 deletions(-) + +diff --git a/agents/ibm_vpc/fence_ibm_vpc.py b/agents/ibm_vpc/fence_ibm_vpc.py +index 9f84f7b2d..9e38e8301 100755 +--- a/agents/ibm_vpc/fence_ibm_vpc.py ++++ b/agents/ibm_vpc/fence_ibm_vpc.py +@@ -161,14 +161,6 @@ def define_new_opts(): + "shortdesc" : "API Key", + "order" : 0 + } +- all_opt["instance"] = { +- "getopt" : ":", +- "longopt" : "instance", +- "help" : "--instance=[instance] Cloud Instance", +- "required" : "1", +- "shortdesc" : "Cloud Instance", +- "order" : 0 +- } + all_opt["region"] = { + "getopt" : ":", + "longopt" : "region", +@@ -181,7 +173,7 @@ def define_new_opts(): + "getopt" : ":", + "longopt" : "limit", + "help" : "--limit=[number] Limit number of nodes returned by API", +- "required" : "1", ++ "required" : "0", + "default": 50, + "shortdesc" : "Number of nodes returned by API", + "order" : 0 +@@ -191,7 +183,6 @@ def define_new_opts(): + def main(): + device_opt = [ + "apikey", +- "instance", + "region", + "limit", + "port", +diff --git a/tests/data/metadata/fence_ibm_vpc.xml b/tests/data/metadata/fence_ibm_vpc.xml +index 926efcaa0..ee7151673 100644 +--- a/tests/data/metadata/fence_ibm_vpc.xml ++++ b/tests/data/metadata/fence_ibm_vpc.xml +@@ -8,12 +8,7 @@ + + API Key + +- +- +- +- Cloud Instance +- +- ++ + + + Number of nodes returned by API diff --git a/SOURCES/bz2086559-fence_apc-fence_ilo_moonshot-import-logging.patch b/SOURCES/bz2086559-fence_apc-fence_ilo_moonshot-import-logging.patch new file mode 100644 index 0000000..dbbde08 --- /dev/null +++ b/SOURCES/bz2086559-fence_apc-fence_ilo_moonshot-import-logging.patch @@ -0,0 +1,34 @@ +From 6ea2c6b5d1cc51e93fa7084d76d9272512461e58 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 16 May 2022 11:01:21 +0200 +Subject: [PATCH] fence_apc/fence_ilo_moonshot: add missing "import logging" + +--- + agents/apc/fence_apc.py | 1 + + agents/ilo_moonshot/fence_ilo_moonshot.py | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/agents/apc/fence_apc.py b/agents/apc/fence_apc.py +index 901aad25e..3ea0f37d6 100644 +--- a/agents/apc/fence_apc.py ++++ b/agents/apc/fence_apc.py +@@ -15,6 +15,7 @@ + ##### + + import sys, re, time ++import logging + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +diff --git a/agents/ilo_moonshot/fence_ilo_moonshot.py b/agents/ilo_moonshot/fence_ilo_moonshot.py +index 6f5cca320..1923eeb1c 100644 +--- a/agents/ilo_moonshot/fence_ilo_moonshot.py ++++ b/agents/ilo_moonshot/fence_ilo_moonshot.py +@@ -1,6 +1,7 @@ + #!@PYTHON@ -tt + + import sys ++import logging + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * diff --git a/SOURCES/bz2092385-fence_ibm_vpc-add-proxy-support.patch b/SOURCES/bz2092385-fence_ibm_vpc-add-proxy-support.patch new file mode 100644 index 0000000..39a2e2e --- /dev/null +++ b/SOURCES/bz2092385-fence_ibm_vpc-add-proxy-support.patch @@ -0,0 +1,62 @@ +From be409554bbc99df2bba22cb01e8a6df634af896d Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 31 May 2022 15:46:40 +0200 +Subject: [PATCH] fence_ibm_vpc: add proxy support + +--- + agents/ibm_vpc/fence_ibm_vpc.py | 11 +++++++++++ + tests/data/metadata/fence_ibm_vpc.xml | 5 +++++ + 2 files changed, 16 insertions(+) + +diff --git a/agents/ibm_vpc/fence_ibm_vpc.py b/agents/ibm_vpc/fence_ibm_vpc.py +index 9e38e8301..3da3ce056 100755 +--- a/agents/ibm_vpc/fence_ibm_vpc.py ++++ b/agents/ibm_vpc/fence_ibm_vpc.py +@@ -88,6 +88,7 @@ def connect(opt): + conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) + conn.setopt(pycurl.SSL_VERIFYPEER, 1) + conn.setopt(pycurl.SSL_VERIFYHOST, 2) ++ conn.setopt(pycurl.PROXY, "{}".format(opt["--proxy"])) + + # get bearer token + bearer_token = get_bearer_token(conn, opt) +@@ -169,6 +170,15 @@ def define_new_opts(): + "shortdesc" : "Region", + "order" : 0 + } ++ all_opt["proxy"] = { ++ "getopt" : ":", ++ "longopt" : "proxy", ++ "help" : "--proxy=[http://:] Proxy: 'http://:'", ++ "required" : "0", ++ "default": "", ++ "shortdesc" : "Network proxy", ++ "order" : 0 ++ } + all_opt["limit"] = { + "getopt" : ":", + "longopt" : "limit", +@@ -185,6 +195,7 @@ def main(): + "apikey", + "region", + "limit", ++ "proxy", + "port", + "no_password", + ] +diff --git a/tests/data/metadata/fence_ibm_vpc.xml b/tests/data/metadata/fence_ibm_vpc.xml +index ee7151673..09da0e303 100644 +--- a/tests/data/metadata/fence_ibm_vpc.xml ++++ b/tests/data/metadata/fence_ibm_vpc.xml +@@ -13,6 +13,11 @@ + + Number of nodes returned by API + ++ ++ ++ ++ Network proxy ++ + + + diff --git a/SOURCES/bz2093216-fence_ibm_powervs-proxy-private-api-servers.patch b/SOURCES/bz2093216-fence_ibm_powervs-proxy-private-api-servers.patch new file mode 100644 index 0000000..36f07fc --- /dev/null +++ b/SOURCES/bz2093216-fence_ibm_powervs-proxy-private-api-servers.patch @@ -0,0 +1,455 @@ +From 98fec5c6d55369ad681abc0cde0d8677835957ab Mon Sep 17 00:00:00 2001 +From: Arnold Beilmann +Date: Thu, 5 May 2022 15:26:22 +0200 +Subject: [PATCH 1/2] modified for PowerVS + +--- + agents/ibm_powervs/fence_ibm_powervs.py | 108 +++++++++++++++++++----- + 1 file changed, 89 insertions(+), 19 deletions(-) + +diff --git a/agents/ibm_powervs/fence_ibm_powervs.py b/agents/ibm_powervs/fence_ibm_powervs.py +index 6649771ea..727009220 100755 +--- a/agents/ibm_powervs/fence_ibm_powervs.py ++++ b/agents/ibm_powervs/fence_ibm_powervs.py +@@ -1,10 +1,11 @@ +-#!@PYTHON@ -tt ++#!/usr/libexec/platform-python -tt + + import sys + import pycurl, io, json + import logging + import atexit +-sys.path.append("@FENCEAGENTSLIBDIR@") ++import time ++sys.path.append("/usr/share/fence") + from fencing import * + from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS + +@@ -14,16 +15,30 @@ + "ERROR": "unknown" + } + ++def get_token(conn, options): ++ ++ try: ++ command = "identity/token" ++ action = "grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey={}".format(options["--token"]) ++ res = send_command(conn, command, "POST", action, printResult=False) ++ except Exception as e: ++ logging.debug("Failed: {}".format(e)) ++ return "TOKEN_IS_MISSING_OR_WRONG" ++ ++ #if "--verbose" in options: ++ # logging.debug(json.dumps(res, indent=2)) ++ ++ return res["access_token"] ++ + def get_list(conn, options): + outlets = {} +- ++ + try: + command = "cloud-instances/{}/pvm-instances".format(options["--instance"]) + res = send_command(conn, command) + except Exception as e: + logging.debug("Failed: {}".format(e)) + return outlets +- + for r in res["pvmInstances"]: + if "--verbose" in options: + logging.debug(json.dumps(r, indent=2)) +@@ -32,6 +47,7 @@ def get_list(conn, options): + return outlets + + def get_power_status(conn, options): ++ + try: + command = "cloud-instances/{}/pvm-instances/{}".format( + options["--instance"], options["--plug"]) +@@ -40,10 +56,11 @@ def get_power_status(conn, options): + except KeyError as e: + logging.debug("Failed: Unable to get status for {}".format(e)) + fail(EC_STATUS) +- ++ + return result + + def set_power_status(conn, options): ++ + action = { + "on" : '{"action" : "start"}', + "off" : '{"action" : "immediate-shutdown"}', +@@ -56,35 +73,63 @@ def set_power_status(conn, options): + logging.debug("Failed: Unable to set power to {} for {}".format(options["--action"], e)) + fail(EC_STATUS) + +-def connect(opt): ++def connect(opt, token): + conn = pycurl.Curl() + + ## setup correct URL +- conn.base_url = "https://" + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/" ++ conn.base_url = "https://private." + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/" ++ if opt["--api-type"] == "public": ++ conn.base_url = "https://" + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/" + + if opt["--verbose-level"] > 1: +- conn.setopt(pycurl.VERBOSE, 1) ++ conn.setopt(pycurl.VERBOSE, 0) + ++ conn.setopt(pycurl.CONNECTTIMEOUT,int(opt["--shell-timeout"])) + conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) + conn.setopt(pycurl.SSL_VERIFYPEER, 1) + conn.setopt(pycurl.SSL_VERIFYHOST, 2) ++ conn.setopt(pycurl.PROXY, "{}".format(opt["--proxy"])) + + # set auth token for later requests + conn.setopt(pycurl.HTTPHEADER, [ + "Content-Type: application/json", +- "Authorization: Bearer {}".format(opt["--token"]), ++ "Authorization: Bearer {}".format(token), + "CRN: {}".format(opt["--crn"]), + "User-Agent: curl", + ]) ++ ++ return conn ++ ++def auth_connect(opt): ++ conn = pycurl.Curl() ++ ++ # setup correct URL ++ conn.base_url = "https://iam.cloud.ibm.com/" ++ ++ if opt["--verbose-level"] > 1: ++ conn.setopt(pycurl.VERBOSE, 1) ++ ++ conn.setopt(pycurl.CONNECTTIMEOUT,int(opt["--shell-timeout"])) ++ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) ++ conn.setopt(pycurl.SSL_VERIFYPEER, 1) ++ conn.setopt(pycurl.SSL_VERIFYHOST, 2) ++ conn.setopt(pycurl.PROXY, "{}".format(opt["--proxy"])) ++ ++ # set auth token for later requests ++ conn.setopt(pycurl.HTTPHEADER, [ ++ "Content-type: application/x-www-form-urlencoded", ++ "Accept: application/json", ++ "User-Agent: curl", ++ ]) + + return conn + + def disconnect(conn): + conn.close() + +-def send_command(conn, command, method="GET", action=None): ++def send_command(conn, command, method="GET", action=None, printResult=True): + url = conn.base_url + command +- ++ + conn.setopt(pycurl.URL, url.encode("ascii")) + + web_buffer = io.BytesIO() +@@ -99,8 +144,10 @@ def send_command(conn, command, method="GET", action=None): + conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write) + + try: ++ time.sleep(3) + conn.perform() + except Exception as e: ++ logging.error("ADD_DEBUG: {}".format(e)) + raise(e) + + rc = conn.getinfo(pycurl.HTTP_CODE) +@@ -110,8 +157,7 @@ def send_command(conn, command, method="GET", action=None): + + if rc != 200: + if len(result) > 0: +- raise Exception("{}: {}".format(rc, +- result["value"]["messages"][0]["default_message"])) ++ raise Exception("{}: {}".format(rc,result)) + else: + raise Exception("Remote returned {} for request to {}".format(rc, url)) + +@@ -121,7 +167,8 @@ def send_command(conn, command, method="GET", action=None): + logging.debug("url: {}".format(url)) + logging.debug("method: {}".format(method)) + logging.debug("response code: {}".format(rc)) +- logging.debug("result: {}\n".format(result)) ++ if printResult: ++ logging.debug("result: {}\n".format(result)) + + return result + +@@ -129,9 +176,9 @@ def define_new_opts(): + all_opt["token"] = { + "getopt" : ":", + "longopt" : "token", +- "help" : "--token=[token] Bearer Token", ++ "help" : "--token=[token] API Token", + "required" : "1", +- "shortdesc" : "Bearer Token", ++ "shortdesc" : "API Token", + "order" : 0 + } + all_opt["crn"] = { +@@ -158,6 +205,22 @@ def define_new_opts(): + "shortdesc" : "Region", + "order" : 0 + } ++ all_opt["api-type"] = { ++ "getopt" : ":", ++ "longopt" : "api-type", ++ "help" : "--api-type=[private|public] API-type: 'private' (default) or 'public'", ++ "required" : "0", ++ "shortdesc" : "API-type (private|public)", ++ "order" : 0 ++ } ++ all_opt["proxy"] = { ++ "getopt" : ":", ++ "longopt" : "proxy", ++ "help" : "--proxy=[http://:] Proxy: 'http://:'", ++ "required" : "0", ++ "shortdesc" : "Network proxy", ++ "order" : 0 ++ } + + + def main(): +@@ -166,6 +229,8 @@ def main(): + "crn", + "instance", + "region", ++ "api-type", ++ "proxy", + "port", + "no_password", + ] +@@ -173,9 +238,11 @@ def main(): + atexit.register(atexit_handler) + define_new_opts() + +- all_opt["shell_timeout"]["default"] = "15" ++ all_opt["shell_timeout"]["default"] = "500" + all_opt["power_timeout"]["default"] = "30" + all_opt["power_wait"]["default"] = "1" ++ all_opt["api-type"]["default"] = "private" ++ all_opt["proxy"]["default"] = "" + + options = check_input(device_opt, process_input(device_opt)) + +@@ -190,8 +257,11 @@ def main(): + ## Fence operations + #### + run_delay(options) +- +- conn = connect(options) ++ ++ auth_conn = auth_connect(options) ++ token = get_token(auth_conn, options) ++ disconnect(auth_conn) ++ conn = connect(options, token) + atexit.register(disconnect, conn) + + result = fence_action(conn, options, set_power_status, get_power_status, get_list) + +From fbe9a539ac8f40686a8027b7e768d9f7b799e485 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Fri, 6 May 2022 11:22:47 +0200 +Subject: [PATCH 2/2] fence_ibm_powervs: cleanup and fixes + +--- + agents/ibm_powervs/fence_ibm_powervs.py | 37 ++++++++++------------- + tests/data/metadata/fence_ibm_powervs.xml | 19 ++++++++++-- + 2 files changed, 33 insertions(+), 23 deletions(-) + +diff --git a/agents/ibm_powervs/fence_ibm_powervs.py b/agents/ibm_powervs/fence_ibm_powervs.py +index 727009220..819ab8896 100755 +--- a/agents/ibm_powervs/fence_ibm_powervs.py ++++ b/agents/ibm_powervs/fence_ibm_powervs.py +@@ -1,11 +1,11 @@ +-#!/usr/libexec/platform-python -tt ++#!@PYTHON@ -tt + + import sys + import pycurl, io, json + import logging + import atexit + import time +-sys.path.append("/usr/share/fence") ++sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * + from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS + +@@ -16,7 +16,6 @@ + } + + def get_token(conn, options): +- + try: + command = "identity/token" + action = "grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey={}".format(options["--token"]) +@@ -25,20 +24,18 @@ def get_token(conn, options): + logging.debug("Failed: {}".format(e)) + return "TOKEN_IS_MISSING_OR_WRONG" + +- #if "--verbose" in options: +- # logging.debug(json.dumps(res, indent=2)) +- + return res["access_token"] + + def get_list(conn, options): + outlets = {} +- ++ + try: + command = "cloud-instances/{}/pvm-instances".format(options["--instance"]) + res = send_command(conn, command) + except Exception as e: + logging.debug("Failed: {}".format(e)) + return outlets ++ + for r in res["pvmInstances"]: + if "--verbose" in options: + logging.debug(json.dumps(r, indent=2)) +@@ -47,7 +44,6 @@ def get_list(conn, options): + return outlets + + def get_power_status(conn, options): +- + try: + command = "cloud-instances/{}/pvm-instances/{}".format( + options["--instance"], options["--plug"]) +@@ -56,11 +52,10 @@ def get_power_status(conn, options): + except KeyError as e: + logging.debug("Failed: Unable to get status for {}".format(e)) + fail(EC_STATUS) +- ++ + return result + + def set_power_status(conn, options): +- + action = { + "on" : '{"action" : "start"}', + "off" : '{"action" : "immediate-shutdown"}', +@@ -77,11 +72,11 @@ def connect(opt, token): + conn = pycurl.Curl() + + ## setup correct URL +- conn.base_url = "https://private." + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/" +- if opt["--api-type"] == "public": +- conn.base_url = "https://" + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/" ++ conn.base_url = "https://" + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/" ++ if opt["--api-type"] == "private": ++ conn.base_url = "https://private." + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/" + +- if opt["--verbose-level"] > 1: ++ if opt["--verbose-level"] < 3: + conn.setopt(pycurl.VERBOSE, 0) + + conn.setopt(pycurl.CONNECTTIMEOUT,int(opt["--shell-timeout"])) +@@ -129,7 +124,7 @@ def disconnect(conn): + + def send_command(conn, command, method="GET", action=None, printResult=True): + url = conn.base_url + command +- ++ + conn.setopt(pycurl.URL, url.encode("ascii")) + + web_buffer = io.BytesIO() +@@ -144,10 +139,9 @@ def send_command(conn, command, method="GET", action=None, printResult=True): + conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write) + + try: +- time.sleep(3) + conn.perform() + except Exception as e: +- logging.error("ADD_DEBUG: {}".format(e)) ++ logging.error("send_command(): {}".format(e)) + raise(e) + + rc = conn.getinfo(pycurl.HTTP_CODE) +@@ -208,9 +202,9 @@ def define_new_opts(): + all_opt["api-type"] = { + "getopt" : ":", + "longopt" : "api-type", +- "help" : "--api-type=[private|public] API-type: 'private' (default) or 'public'", ++ "help" : "--api-type=[public|private] API-type: 'public' (default) or 'private'", + "required" : "0", +- "shortdesc" : "API-type (private|public)", ++ "shortdesc" : "API-type (public|private)", + "order" : 0 + } + all_opt["proxy"] = { +@@ -238,9 +232,10 @@ def main(): + atexit.register(atexit_handler) + define_new_opts() + +- all_opt["shell_timeout"]["default"] = "500" ++ all_opt["shell_timeout"]["default"] = "15" + all_opt["power_timeout"]["default"] = "30" + all_opt["power_wait"]["default"] = "1" ++ all_opt["stonith_status_sleep"]["default"] = "3" + all_opt["api-type"]["default"] = "private" + all_opt["proxy"]["default"] = "" + +@@ -257,7 +252,7 @@ def main(): + ## Fence operations + #### + run_delay(options) +- ++ + auth_conn = auth_connect(options) + token = get_token(auth_conn, options) + disconnect(auth_conn) +diff --git a/tests/data/metadata/fence_ibm_powervs.xml b/tests/data/metadata/fence_ibm_powervs.xml +index fe86331bd..81cea4379 100644 +--- a/tests/data/metadata/fence_ibm_powervs.xml ++++ b/tests/data/metadata/fence_ibm_powervs.xml +@@ -3,6 +3,16 @@ + fence_ibm_powervs is an I/O Fencing agent which can be used with IBM PowerVS to fence virtual machines. + https://www.ibm.com + ++ ++ ++ ++ API-type (public|private) ++ ++ ++ ++ ++ API-type (public|private) ++ + + + +@@ -13,6 +23,11 @@ + + PowerVS Instance + ++ ++ ++ ++ Network proxy ++ + + + +@@ -21,7 +36,7 @@ + + + +- Bearer Token ++ API Token + + + +@@ -110,7 +125,7 @@ + + + +- ++ + Sleep X seconds between status calls during a STONITH action + + diff --git a/SOURCES/ha-cloud-support-aliyun.patch b/SOURCES/ha-cloud-support-aliyun.patch new file mode 100644 index 0000000..5f310f1 --- /dev/null +++ b/SOURCES/ha-cloud-support-aliyun.patch @@ -0,0 +1,10 @@ +--- a/agents/aliyun/fence_aliyun.py 2021-02-08 16:27:46.587068911 +0100 ++++ b/agents/aliyun/fence_aliyun.py 2021-02-08 16:27:41.368054268 +0100 +@@ -9,6 +9,7 @@ + from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay + + try: ++ sys.path.insert(0, '/usr/lib/fence-agents/support/aliyun') + from aliyunsdkcore import client + from aliyunsdkcore.auth.credentials import EcsRamRoleCredential + from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest diff --git a/SOURCES/ha-cloud-support-aws.patch b/SOURCES/ha-cloud-support-aws.patch new file mode 100644 index 0000000..f4939dd --- /dev/null +++ b/SOURCES/ha-cloud-support-aws.patch @@ -0,0 +1,10 @@ +--- a/agents/aws/fence_aws.py 2021-02-08 13:31:49.748362643 +0100 ++++ b/agents/aws/fence_aws.py 2021-02-08 13:31:46.836356513 +0100 +@@ -11,6 +11,7 @@ + from requests import HTTPError + + try: ++ sys.path.insert(0, '/usr/lib/fence-agents/support/aws') + import boto3 + from botocore.exceptions import ConnectionError, ClientError, EndpointConnectionError, NoRegionError + except ImportError: diff --git a/SOURCES/ha-cloud-support-azure.patch b/SOURCES/ha-cloud-support-azure.patch new file mode 100644 index 0000000..f8290f5 --- /dev/null +++ b/SOURCES/ha-cloud-support-azure.patch @@ -0,0 +1,12 @@ +--- fence-agents-4.7.1/lib/azure_fence.py.py 2021-02-08 16:52:32.955244393 +0100 ++++ fence-agents-4.7.1/lib/azure_fence.py.py.modif 2021-02-08 16:52:28.150234151 +0100 +@@ -1,6 +1,9 @@ + import logging, re, time + from fencing import fail_usage + ++import sys ++sys.path.insert(0, '/usr/lib/fence-agents/support/azure') ++ + FENCE_SUBNET_NAME = "fence-subnet" + FENCE_INBOUND_RULE_NAME = "FENCE_DENY_ALL_INBOUND" + FENCE_INBOUND_RULE_DIRECTION = "Inbound" diff --git a/SOURCES/ha-cloud-support-google.patch b/SOURCES/ha-cloud-support-google.patch new file mode 100644 index 0000000..5335073 --- /dev/null +++ b/SOURCES/ha-cloud-support-google.patch @@ -0,0 +1,21 @@ +diff --color -uNr a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py +--- a/agents/gce/fence_gce.py 2021-06-03 13:10:44.752999470 +0200 ++++ b/agents/gce/fence_gce.py 2021-06-03 13:10:36.512971619 +0200 +@@ -9,7 +9,6 @@ + # + + import atexit +-import httplib2 + import logging + import json + import re +@@ -30,6 +29,8 @@ + + from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action + try: ++ sys.path.insert(0, '/usr/lib/fence-agents/support/google') ++ import httplib2 + import googleapiclient.discovery + import socks + try: +Binary files a/agents/gce/.fence_gce.py.swp and b/agents/gce/.fence_gce.py.swp differ diff --git a/SOURCES/requirements-aliyun.txt b/SOURCES/requirements-aliyun.txt new file mode 100644 index 0000000..3cf97ac --- /dev/null +++ b/SOURCES/requirements-aliyun.txt @@ -0,0 +1,3 @@ +aliyun-python-sdk-ecs +# for resource-agents-cloud +aliyuncli>=2.1.5 diff --git a/SOURCES/requirements-aws.txt b/SOURCES/requirements-aws.txt new file mode 100644 index 0000000..f702bb0 --- /dev/null +++ b/SOURCES/requirements-aws.txt @@ -0,0 +1,2 @@ +boto3 +jmespath<1.0.0 diff --git a/SOURCES/requirements-azure.txt b/SOURCES/requirements-azure.txt new file mode 100644 index 0000000..3aa79bc --- /dev/null +++ b/SOURCES/requirements-azure.txt @@ -0,0 +1,3 @@ +azure-mgmt-compute +azure-mgmt-network +msrestazure diff --git a/SOURCES/requirements-common.txt b/SOURCES/requirements-common.txt new file mode 100644 index 0000000..15ed87c --- /dev/null +++ b/SOURCES/requirements-common.txt @@ -0,0 +1,2 @@ +pexpect +suds-community diff --git a/SOURCES/requirements-google.txt b/SOURCES/requirements-google.txt new file mode 100644 index 0000000..4ef59ba --- /dev/null +++ b/SOURCES/requirements-google.txt @@ -0,0 +1,4 @@ +google-api-python-client==1.12.8 +chardet<4.0 +# for gcp-vpc-move-route +pyroute2 diff --git a/SPECS/fence-agents.spec b/SPECS/fence-agents.spec new file mode 100644 index 0000000..735d249 --- /dev/null +++ b/SPECS/fence-agents.spec @@ -0,0 +1,1743 @@ +# Copyright 2004-2011 Red Hat, Inc. +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions +# of the GNU General Public License v.2. + +# keep around ready for later user +## global alphatag git0a6184070 + +# bundles +%global bundled_lib_dir bundled +# kubevirt +%global openshift openshift +%global openshift_version 0.12.1 +%global ruamelyamlclib ruamel.yaml.clib +%global ruamelyamlclib_version 0.2.6 +%global kubernetes kubernetes +%global kubernetes_version 12.0.1 +%global certifi certifi +%global certifi_version 2021.10.8 +%global googleauth google-auth +%global googleauth_version 2.3.0 +%global cachetools cachetools +%global cachetools_version 4.2.4 +%global pyasn1modules pyasn1-modules +%global pyasn1modules_version 0.2.8 +%global pyasn1 pyasn1 +%global pyasn1_version 0.4.8 +%global dateutil dateutil +%global dateutil_version 2.8.2 +%global pyyaml PyYAML +%global pyyaml_version 5.1 +%global six six +%global six_version 1.16.0 +%global urllib3 urllib3 +%global urllib3_version 1.26.7 +%global websocketclient websocket-client +%global websocketclient_version 1.2.1 +%global jinja2 Jinja2 +%global jinja2_version 3.0.2 +%global markupsafe MarkupSafe +%global markupsafe_version 2.0.1 +%global stringutils string-utils +%global stringutils_version 1.0.0 +%global requests requests +%global requests_version 2.26.0 +%global chrstnormalizer charset-normalizer +%global chrstnormalizer_version 2.0.7 +%global idna idna +%global idna_version 3.3 +%global reqstsoauthlib requests-oauthlib +%global reqstsoauthlib_version 1.3.0 +%global oauthlib oauthlib +%global oauthlib_version 3.1.1 +%global ruamelyaml ruamel.yaml +%global ruamelyaml_version 0.17.16 +%global setuptools setuptools +%global setuptools_version 58.3.0 + +Name: fence-agents +Summary: Set of unified programs capable of host isolation ("fencing") +Version: 4.10.0 +Release: 30%{?alphatag:.%{alphatag}}%{?dist} +License: GPLv2+ and LGPLv2+ +URL: https://github.com/ClusterLabs/fence-agents +Source0: https://fedorahosted.org/releases/f/e/fence-agents/%{name}-%{version}.tar.gz +### HA support requirements-*.txt ### +Source100: requirements-aliyun.txt +Source101: requirements-aws.txt +Source102: requirements-azure.txt +Source103: requirements-google.txt +Source104: requirements-common.txt +### HA support libs/utils ### +# awscli 2+ is only available from github (and needs to be renamed from aws-cli... to awscli) +Source900: awscli-2.2.15.tar.gz +# From awscli's requirements.txt: https://github.com/boto/botocore/zipball/v2#egg=botocore +Source901: botocore-2.0.0dev123.zip +# update with ./update-ha-support.sh and replace lines below with output +### BEGIN ### +# aliyun +Source1000: aliyun-python-sdk-core-2.11.5.tar.gz +Source1001: aliyun_python_sdk_ecs-4.24.7-py2.py3-none-any.whl +Source1002: aliyuncli-2.1.10-py2.py3-none-any.whl +Source1003: cffi-1.14.5-cp39-cp39-manylinux1_x86_64.whl +Source1004: colorama-0.3.3.tar.gz +Source1005: jmespath-0.7.1-py2.py3-none-any.whl +Source1006: pycryptodome-3.10.1-cp35-abi3-manylinux2010_x86_64.whl +Source1007: pycparser-2.20-py2.py3-none-any.whl +# awscli +Source1008: awscrt-0.11.13-cp39-cp39-manylinux2014_x86_64.whl +Source1009: colorama-0.4.3-py2.py3-none-any.whl +Source1010: cryptography-3.3.2-cp36-abi3-manylinux2010_x86_64.whl +Source1011: distro-1.5.0-py2.py3-none-any.whl +Source1012: docutils-0.15.2-py3-none-any.whl +Source1013: prompt_toolkit-2.0.10-py3-none-any.whl +Source1014: ruamel.yaml-0.15.100.tar.gz +Source1015: six-1.16.0-py2.py3-none-any.whl +Source1016: wcwidth-0.1.9-py2.py3-none-any.whl +# aws +Source1017: boto3-1.17.102-py2.py3-none-any.whl +Source1018: botocore-1.20.102-py2.py3-none-any.whl +Source1019: python_dateutil-2.8.1-py2.py3-none-any.whl +Source1020: s3transfer-0.4.2-py2.py3-none-any.whl +Source1021: urllib3-1.26.6-py2.py3-none-any.whl +# azure +Source1022: adal-1.2.7-py2.py3-none-any.whl +Source1023: azure_common-1.1.27-py2.py3-none-any.whl +Source1024: azure_core-1.15.0-py2.py3-none-any.whl +Source1025: azure_mgmt_compute-21.0.0-py2.py3-none-any.whl +Source1026: azure_mgmt_core-1.2.2-py2.py3-none-any.whl +Source1027: azure_mgmt_network-19.0.0-py2.py3-none-any.whl +Source1028: certifi-2021.5.30-py2.py3-none-any.whl +Source1029: chardet-4.0.0-py2.py3-none-any.whl +Source1030: idna-2.10-py2.py3-none-any.whl +Source1031: isodate-0.6.0-py2.py3-none-any.whl +Source1032: msrest-0.6.21-py2.py3-none-any.whl +Source1033: msrestazure-0.6.4-py2.py3-none-any.whl +Source1034: oauthlib-3.1.1-py2.py3-none-any.whl +Source1035: PyJWT-2.1.0-py3-none-any.whl +Source1036: requests-2.25.1-py2.py3-none-any.whl +Source1037: requests_oauthlib-1.3.0-py2.py3-none-any.whl +# google +Source1038: cachetools-4.2.2-py3-none-any.whl +Source1039: chardet-3.0.4-py2.py3-none-any.whl +Source1040: google_api_core-1.30.0-py2.py3-none-any.whl +Source1041: google_api_python_client-1.12.8-py2.py3-none-any.whl +Source1042: googleapis_common_protos-1.53.0-py2.py3-none-any.whl +Source1043: google_auth-1.32.0-py2.py3-none-any.whl +Source1044: google_auth_httplib2-0.1.0-py2.py3-none-any.whl +Source1045: httplib2-0.19.1-py3-none-any.whl +Source1046: packaging-20.9-py2.py3-none-any.whl +Source1047: protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl +Source1048: pyasn1-0.4.8-py2.py3-none-any.whl +Source1049: pyasn1_modules-0.2.8-py2.py3-none-any.whl +Source1050: pyparsing-2.4.7-py2.py3-none-any.whl +Source1051: pyroute2-0.6.4.tar.gz +Source1052: pyroute2.core-0.6.4.tar.gz +Source1053: pyroute2.ethtool-0.6.4.tar.gz +Source1054: pyroute2.ipdb-0.6.4.tar.gz +Source1055: pyroute2.ipset-0.6.4.tar.gz +Source1056: pyroute2.ndb-0.6.4.tar.gz +Source1057: pyroute2.nftables-0.6.4.tar.gz +Source1058: pyroute2.nslink-0.6.4.tar.gz +Source1059: pytz-2021.1-py2.py3-none-any.whl +Source1060: rsa-4.7.2-py3-none-any.whl +Source1061: setuptools-57.0.0-py3-none-any.whl +Source1062: uritemplate-3.0.1-py2.py3-none-any.whl +# common (pexpect / suds) +Source1063: pexpect-4.8.0-py2.py3-none-any.whl +Source1064: ptyprocess-0.7.0-py2.py3-none-any.whl +Source1065: suds_community-0.8.5-py3-none-any.whl +### END ### +# kubevirt +## pip download --no-binary :all: openshift "ruamel.yaml.clib>=0.1.2" +### BEGIN +Source1066: %{openshift}-%{openshift_version}.tar.gz +Source1067: %{ruamelyamlclib}-%{ruamelyamlclib_version}.tar.gz +Source1068: %{kubernetes}-%{kubernetes_version}.tar.gz +Source1069: %{certifi}-%{certifi_version}.tar.gz +Source1070: %{googleauth}-%{googleauth_version}.tar.gz +Source1071: %{cachetools}-%{cachetools_version}.tar.gz +Source1072: %{pyasn1modules}-%{pyasn1modules_version}.tar.gz +Source1073: %{pyasn1}-%{pyasn1_version}.tar.gz +Source1074: python-%{dateutil}-%{dateutil_version}.tar.gz +Source1075: %{pyyaml}-%{pyyaml_version}.tar.gz +## rsa is dependency for "pip install", +## but gets removed to use cryptography lib instead +Source1076: rsa-4.7.2.tar.gz +Source1077: %{six}-%{six_version}.tar.gz +Source1078: %{urllib3}-%{urllib3_version}.tar.gz +Source1079: %{websocketclient}-%{websocketclient_version}.tar.gz +Source1080: %{jinja2}-%{jinja2_version}.tar.gz +Source1081: %{markupsafe}-%{markupsafe_version}.tar.gz +Source1082: python-%{stringutils}-%{stringutils_version}.tar.gz +Source1083: %{requests}-%{requests_version}.tar.gz +Source1084: %{chrstnormalizer}-%{chrstnormalizer_version}.tar.gz +Source1085: %{idna}-%{idna_version}.tar.gz +Source1086: %{reqstsoauthlib}-%{reqstsoauthlib_version}.tar.gz +Source1087: %{oauthlib}-%{oauthlib_version}.tar.gz +Source1088: %{ruamelyaml}-%{ruamelyaml_version}.tar.gz +Source1089: %{setuptools}-%{setuptools_version}.tar.gz +## required for installation +Source1090: setuptools_scm-6.3.2.tar.gz +Source1091: packaging-21.2-py3-none-any.whl +Source1092: poetry-core-1.0.7.tar.gz +Source1093: pyparsing-3.0.1.tar.gz +Source1094: tomli-1.0.1.tar.gz +Source1095: wheel-0.37.0-py2.py3-none-any.whl +### END + +Patch0: ha-cloud-support-aliyun.patch +Patch1: ha-cloud-support-aws.patch +Patch2: ha-cloud-support-azure.patch +Patch3: ha-cloud-support-google.patch +Patch4: bundled-pexpect.patch +Patch5: bundled-suds.patch +Patch6: bz2010652-fence_azure_arm-fix-sovereign-cloud-msi-support.patch +Patch7: bz2010709-1-fence_amt_ws-fix-or-causing-dead-code.patch +Patch8: bz2010709-2-fence_amt_ws-boot-option.patch +Patch9: bz2000954-1-configure-fix-virt.patch +Patch10: bz2000954-2-fence_kubevirt.patch +Patch11: bz2022334-fence_zvmip-add-ssl-tls-support.patch +Patch12: bz2029791-1-fence_openstack-add-ssl-insecure.patch +Patch13: bz2029791-2-fence_openstack-cacert-default.patch +Patch14: bz2000954-3-fence_kubevirt-get-namespace-from-context.patch +Patch15: bz2041933-bz2041935-1-fence_openstack-clouds-openrc.patch +Patch16: bz2041933-bz2041935-2-fence_openstack-clouds-openrc.patch +Patch17: bz2042496-fence_ibm_vpc-fence_ibm_powervs.patch +Patch18: bz2022334-fence_zvmip-add-disable-ssl.patch +Patch19: bz2065114-fence_lpar-refactor.patch +Patch20: bz2072420-1-all-agents-unify-ssl-parameters.patch +Patch21: bz2079889-fence_gce-update.patch +Patch22: bz2081235-fence_ibm_vpc-fix-parameters.patch +Patch23: bz2086559-fence_apc-fence_ilo_moonshot-import-logging.patch +Patch24: bz2072420-2-fence_zvmip-connect-error.patch +Patch25: bz2092385-fence_ibm_vpc-add-proxy-support.patch +Patch26: bz2093216-fence_ibm_powervs-proxy-private-api-servers.patch +Patch27: bz2041933-bz2041935-3-fencing-source_env-dont-process-empty-lines.patch + +%global supportedagents amt_ws apc apc_snmp bladecenter brocade cisco_mds cisco_ucs compute drac5 eaton_snmp emerson eps evacuate hpblade ibmblade ibm_powervs ibm_vpc ifmib ilo ilo_moonshot ilo_mp ilo_ssh intelmodular ipdu ipmilan kdump kubevirt lpar mpath redfish rhevm rsa rsb sbd scsi vmware_rest vmware_soap wti +%ifarch x86_64 +%global testagents virsh heuristics_ping aliyun aws azure_arm gce openstack virt +%endif +%ifarch ppc64le +%global testagents virsh heuristics_ping openstack +%endif +%ifarch s390x +%global testagents virsh zvm heuristics_ping +%endif +%ifnarch x86_64 ppc64le s390x +%global testagents virsh heuristics_ping +%endif + +# skipped: pve, raritan, rcd-serial, virsh +%global allfenceagents %(cat < 7 || 0%{?rhel} > 7 || 0%{?suse_version} +BuildRequires: python3-devel python3-pip +# wheel for HA support subpackages +BuildRequires: python3-wheel +BuildRequires: python3-pycurl python3-requests +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 +BuildRequires: openwsman-python3 +%endif +%if 0%{?suse_version} +BuildRequires: python3-openwsman +%endif +%else +BuildRequires: python-devel +BuildRequires: python-pycurl python-requests +BuildRequires: openwsman-python +%endif + +# fence-virt +%if 0%{?suse_version} +%define nss_devel mozilla-nss-devel +%define nspr_devel mozilla-nspr-devel +%define systemd_units systemd +%else +%define nss_devel nss-devel +%define nspr_devel nspr-devel +%define systemd_units systemd-units +%endif + +BuildRequires: corosynclib-devel libvirt-devel +BuildRequires: libxml2-devel %{nss_devel} %{nspr_devel} +BuildRequires: flex bison libuuid-devel +BuildRequires: %{systemd_units} + + +# turn off the brp-python-bytecompile script +# (for F28+ or equivalent, the latter is the preferred form) +%global __os_install_post %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompilespace:.*$!!g') +#undefine __brp_python_bytecompile + +%prep +%setup -q -n %{name}-%{version}%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}} +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 -F2 +%patch15 -p1 -F1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 + +# prevent compilation of something that won't get used anyway +sed -i.orig 's|FENCE_ZVM=1|FENCE_ZVM=0|' configure.ac + +%build +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version} + export PYTHON="%{__python3}" +%endif + +# support libs +%ifarch x86_64 +LIBS="%{_sourcedir}/requirements-*.txt" +echo "awscli" >> %{_sourcedir}/requirements-awscli.txt +%endif +%ifnarch x86_64 +LIBS="%{_sourcedir}/requirements-common.txt" +%endif +for x in $LIBS; do + %{__python3} -m pip install --target support/$(echo $x | sed -E "s/.*requirements-(.*).txt/\1/") --no-index --find-links %{_sourcedir} -r $x +done + +# fix incorrect #! detected by CI +%ifarch x86_64 +sed -i -e "/^#\!\/Users/c#\!%{__python3}" support/aws/bin/jp support/aliyun/bin/jp support/awscli/bin/jp +%endif + +%ifarch x86_64 +sed -i -e "/^import awscli.clidriver/isys.path.insert(0, '/usr/lib/%{name}/support/awscli')" support/awscli/bin/aws +%endif + +./autogen.sh +%{configure} --disable-libvirt-qmf-plugin PYTHONPATH="support/aliyun:support/aws:support/azure:support/google:support/common" --with-agents='%{supportedagents} %{testagents}' +CFLAGS="$(echo '%{optflags}')" make %{_smp_mflags} + +%install +rm -rf %{buildroot} + +# support libs +mkdir -p %{buildroot}%{_usr}/lib/%{name} +mv support %{buildroot}%{_usr}/lib/%{name} + +export PYTHONPATH=%{buildroot}%{_usr}/lib/%{name}/support +make install DESTDIR=%{buildroot} +mkdir -p %{buildroot}/%{_unitdir}/ +%ifarch x86_64 +install -m 0644 agents/virt/fence_virtd.service %{buildroot}/%{_unitdir}/ +%endif +# bytecompile Python source code in a non-standard location +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 +%py_byte_compile %{__python3} %{buildroot}%{_datadir}/fence +%endif +# XXX unsure if /usr/sbin/fence_* should be compiled as well + +# kubevirt +%{__python3} -m pip install --user --no-index --find-links %{_sourcedir} setuptools-scm +%{__python3} -m pip install --target %{buildroot}/usr/lib/fence-agents/%{bundled_lib_dir}/kubevirt --no-index --find-links %{_sourcedir} openshift +rm -rf %{buildroot}/usr/lib/fence-agents/%{bundled_lib_dir}/kubevirt/rsa* + +## tree fix up +# fix libfence permissions +chmod 0755 %{buildroot}%{_datadir}/fence/*.py +# remove docs +rm -rf %{buildroot}/usr/share/doc/fence-agents +# remove .a files +rm -f %{buildroot}/%{_libdir}/%{name}/*.*a +rm -f %{buildroot}/%{_libdir}/fence-virt/*.*a + +%post +ccs_update_schema > /dev/null 2>&1 ||: +# https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd +if [ $1 -eq 1 ] ; then + # Initial installation + /bin/systemctl daemon-reload >/dev/null 2>&1 || : +fi + +%preun +# https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd +if [ $1 -eq 0 ] ; then + # Package removal, not upgrade + /bin/systemctl --no-reload disable fence_virtd.service &> /dev/null || : + /bin/systemctl stop fence_virtd.service &> /dev/null || : +fi + +%postun +# https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd +/bin/systemctl daemon-reload &> /dev/null || : +if [ $1 -ge 1 ] ; then + # Package upgrade, not uninstall + /bin/systemctl try-restart fence_virtd.service &> /dev/null || : +fi + +%triggerun -- fence_virtd < 0.3.0-1 +# https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Packages_migrating_to_a_systemd_unit_file_from_a_SysV_initscript +/usr/bin/systemd-sysv-convert --save fence_virtd &> /dev/null || : +/sbin/chkconfig --del fence_virtd &> /dev/null || : +/bin/systemctl daemon-reload >/dev/null 2>&1 || : +/bin/systemctl try-restart fence_virtd.service &> /dev/null || : + +%description +A collection of executables to handle isolation ("fencing") of possibly +misbehaving hosts by the means of remote power management, blocking +network, storage, or similar. They operate through a unified interface +(calling conventions) devised for the original Red Hat clustering solution. + +%package common +License: GPLv2+ and LGPLv2+ +Summary: Common base for Fence Agents +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version} +Requires: python3-pycurl +%else +Requires: python-pycurl +%endif +# pexpect / suds +Provides: bundled(python-pexpect) = 4.8.0 +Provides: bundled(python-ptyprocess) = 0.7.0 +Provides: bundled(python-suds) = 0.8.5 +BuildArch: noarch +%description common +A collection of executables to handle isolation ("fencing") of possibly +misbehaving hosts by the means of remote power management, blocking +network, storage, or similar. + +This package contains support files including the Python fencing library. +%files common +%doc doc/COPYING.* doc/COPYRIGHT doc/README.licence +%{_datadir}/fence +%exclude %{_datadir}/fence/azure_fence.* +%exclude %{_datadir}/fence/__pycache__/azure_fence.* +%exclude %{_datadir}/fence/XenAPI.* +%exclude %{_datadir}/fence/__pycache__/XenAPI.* +%{_datadir}/cluster +%exclude %{_datadir}/cluster/fence_mpath_check* +%exclude %{_datadir}/cluster/fence_scsi_check* +%{_datadir}/pkgconfig/%{name}.pc +%exclude %{_sbindir}/* +%exclude %{_mandir}/man8/* +%dir %{_usr}/lib/%{name} +%{_usr}/lib/%{name}/support/common + +%ifarch x86_64 +%package -n ha-cloud-support +License: GPLv2+ and LGPLv2+ +Summary: Support libraries for HA Cloud agents +# aliyun +Provides: bundled(python-aliyun-python-sdk-core) = 2.11.5 +Provides: bundled(python-aliyun-python-sdk-ecs) = 4.24.7 +Provides: bundled(aliyuncli) = 2.1.10 +Provides: bundled(python-cffi) = 1.14.5 +Provides: bundled(python-colorama) = 0.3.3 +Provides: bundled(python-jmespath) = 0.7.1 +Provides: bundled(python-pycryptodome) = 3.10.1 +Provides: bundled(python-pycparser) = 2.20 +# awscli +Provides: bundled(awscli) = 2.2.15 +Provides: bundled(python-awscrt) = 0.11.13 +Provides: bundled(python-colorama) = 0.4.3 +Provides: bundled(python-cryptography) = 3.3.2 +Provides: bundled(python-distro) = 1.5.0 +Provides: bundled(python-docutils) = 0.15.2 +Provides: bundled(python-prompt-toolkit) = 2.0.10 +Provides: bundled(python-ruamel-yaml) = 0.15.100 +Provides: bundled(python-six) = 1.16.0 +Provides: bundled(python-wcwidth) = 0.1.9 +# aws +Provides: bundled(python-boto3) = 1.17.102 +Provides: bundled(python-botocore) = 1.20.102 +Provides: bundled(python-dateutil) = 2.8.1 +Provides: bundled(python-s3transfer) = 0.4.2 +Provides: bundled(python-urllib3) = 1.26.6 +# azure +Provides: bundled(python-adal) = 1.2.7 +Provides: bundled(python-azure-common) = 1.1.27 +Provides: bundled(python-azure-core) = 1.15.0 +Provides: bundled(python-azure-mgmt-compute) = 21.0.0 +Provides: bundled(python-azure-mgmt-core) = 1.2.2 +Provides: bundled(python-azure-mgmt-network) = 19.0.0 +Provides: bundled(python-certifi) = 2021.5.30 +Provides: bundled(python-chardet) = 4.0.0 +Provides: bundled(python-idna) = 2.10 +Provides: bundled(python-isodate) = 0.6.0 +Provides: bundled(python-msrest) = 0.6.21 +Provides: bundled(python-msrestazure) = 0.6.4 +Provides: bundled(python-oauthlib) = 3.1.1 +Provides: bundled(python-PyJWT) = 2.1.0 +Provides: bundled(python-requests) = 2.25.1 +Provides: bundled(python-requests-oauthlib) = 1.3.0 +# google +Provides: bundled(python-cachetools) = 4.2.2 +Provides: bundled(python-chardet) = 3.0.4 +Provides: bundled(python-google-api-core) = 1.30.0 +Provides: bundled(python-google-api-client) = 1.12.8 +Provides: bundled(python-googleapis-common-protos) = 1.53.0 +Provides: bundled(python-google-auth) = 1.32.0 +Provides: bundled(python-google-auth-httplib2) = 0.1.0 +Provides: bundled(python-httplib2) = 0.19.1 +Provides: bundled(python-packaging) = 20.9 +Provides: bundled(python-protobuf) = 3.17.3 +Provides: bundled(python-pyasn1) = 0.4.8 +Provides: bundled(python-pyasn1-modules) = 0.2.8 +Provides: bundled(python-pyparsing) = 2.4.7 +Provides: bundled(python-pyroute2) = 0.6.4 +Provides: bundled(python-pyroute2-core) = 0.6.4 +Provides: bundled(python-pyroute2-ethtool) = 0.6.4 +Provides: bundled(python-pyroute2-ipdb) = 0.6.4 +Provides: bundled(python-pyroute2-ipset) = 0.6.4 +Provides: bundled(python-pyroute2-ndb) = 0.6.4 +Provides: bundled(python-pyroute2-nftables) = 0.6.4 +Provides: bundled(python-pyroute2-nslink) = 0.6.4 +Provides: bundled(python-pytz) = 2021.1 +Provides: bundled(python-rsa) = 4.7.2 +Provides: bundled(python-setuptools) = 57.0.0 +Provides: bundled(python-uritemplate) = 3.0.1 +%description -n ha-cloud-support +Support libraries for Fence Agents. +%files -n ha-cloud-support +%dir %{_usr}/lib/%{name} +%{_usr}/lib/%{name}/support +%exclude %{_usr}/lib/%{name}/support/common +%endif + +%package all +License: GPLv2+ and LGPLv2+ and ASL 2.0 +Summary: Set of unified programs capable of host isolation ("fencing") +Requires: %{allfenceagents} +%ifarch ppc64le +Requires: fence-agents-lpar >= %{version}-%{release} +%endif +%ifarch s390x +Requires: fence-agents-zvm >= %{version}-%{release} +%endif +Provides: fence-agents = %{version}-%{release} +Obsoletes: fence-agents < 3.1.13 +%description all +A collection of executables to handle isolation ("fencing") of possibly +misbehaving hosts by the means of remote power management, blocking +network, storage, or similar. + +This package serves as a catch-all for all supported fence agents. +%files all + +%ifarch x86_64 +%package aliyun +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Alibaba Cloud (Aliyun) +Requires: fence-agents-common >= %{version}-%{release} +Requires: ha-cloud-support = %{version}-%{release} +Requires: python3-jmespath >= 0.9.0 +Obsoletes: %{name} < %{version}-%{release} +%description aliyun +The fence-agents-aliyun package contains a fence agent for Alibaba Cloud (Aliyun) instances. +%files aliyun +%defattr(-,root,root,-) +%{_sbindir}/fence_aliyun +%{_mandir}/man8/fence_aliyun.8* +%endif + +%package amt-ws +License: ASL 2.0 +Summary: Fence agent for Intel AMT (WS-Man) devices +Requires: fence-agents-common = %{version}-%{release} +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version} +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 +Requires: openwsman-python3 +%endif +%if 0%{?suse_version} +Requires: python3-openwsman +%endif +%else +Requires: openwsman-python +%endif +BuildArch: noarch +%description amt-ws +Fence agent for AMT (WS-Man) devices. +%files amt-ws +%{_sbindir}/fence_amt_ws +%{_mandir}/man8/fence_amt_ws.8* + +%package apc +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for APC devices +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description apc +Fence agent for APC devices that are accessed via telnet or SSH. +%files apc +%{_sbindir}/fence_apc +%{_mandir}/man8/fence_apc.8* + +%package apc-snmp +License: GPLv2+ and LGPLv2+ +Summary: Fence agents for APC devices (SNMP) +Requires: net-snmp-utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description apc-snmp +Fence agents for APC devices that are accessed via the SNMP protocol. +%files apc-snmp +%{_sbindir}/fence_apc_snmp +%{_mandir}/man8/fence_apc_snmp.8* +%{_sbindir}/fence_tripplite_snmp +%{_mandir}/man8/fence_tripplite_snmp.8* + +%ifarch x86_64 +%package aws +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Amazon AWS +Requires: fence-agents-common = %{version}-%{release} +Requires: ha-cloud-support = %{version}-%{release} +Obsoletes: fence-agents < 3.1.13 +%description aws +Fence agent for Amazon AWS instances. +%files aws +%{_sbindir}/fence_aws +%{_mandir}/man8/fence_aws.8* +%endif + +%ifarch x86_64 +%package azure-arm +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Azure Resource Manager +Requires: fence-agents-common = %{version}-%{release} +Requires: ha-cloud-support = %{version}-%{release} +Obsoletes: fence-agents < 3.1.13 +%description azure-arm +Fence agent for Azure Resource Manager instances. +%files azure-arm +%{_sbindir}/fence_azure_arm +%{_datadir}/fence/azure_fence.py* +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 +%{_datadir}/fence/__pycache__/azure_fence.* +%endif +%{_mandir}/man8/fence_azure_arm.8* +%endif + +%package bladecenter +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for IBM BladeCenter +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description bladecenter +Fence agent for IBM BladeCenter devices that are accessed +via telnet or SSH. +%files bladecenter +%{_sbindir}/fence_bladecenter +%{_mandir}/man8/fence_bladecenter.8* + +%package brocade +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Brocade switches +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description brocade +Fence agent for Brocade devices that are accessed via telnet or SSH. +%files brocade +%{_sbindir}/fence_brocade +%{_mandir}/man8/fence_brocade.8* + +%package cisco-mds +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Cisco MDS 9000 series +Requires: net-snmp-utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description cisco-mds +Fence agent for Cisco MDS 9000 series devices that are accessed +via the SNMP protocol. +%files cisco-mds +%{_sbindir}/fence_cisco_mds +%{_mandir}/man8/fence_cisco_mds.8* + +%package cisco-ucs +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Cisco UCS series +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version} +Requires: python3-pycurl +%else +Requires: python-pycurl +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description cisco-ucs +Fence agent for Cisco UCS series devices that are accessed +via the SNMP protocol. +%files cisco-ucs +%{_sbindir}/fence_cisco_ucs +%{_mandir}/man8/fence_cisco_ucs.8* + +%ifarch x86_64 ppc64le +%package compute +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Nova compute nodes +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version} +Requires: python3-requests +%else +Requires: python-requests +%endif +Requires: fence-agents-common = %{version}-%{release} +Obsoletes: ha-openstack-support <= %{version}-%{release} +%description compute +Fence agent for Nova compute nodes. +%files compute +%{_sbindir}/fence_compute +%{_sbindir}/fence_evacuate +%{_mandir}/man8/fence_compute.8* +%{_mandir}/man8/fence_evacuate.8* +%endif + +%package drac5 +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Dell DRAC 5 +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description drac5 +Fence agent for Dell DRAC 5 series devices that are accessed +via telnet or SSH. +%files drac5 +%{_sbindir}/fence_drac5 +%{_mandir}/man8/fence_drac5.8* + +%package eaton-snmp +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Eaton network power switches +Requires: net-snmp-utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description eaton-snmp +Fence agent for Eaton network power switches that are accessed +via the SNMP protocol. +%files eaton-snmp +%{_sbindir}/fence_eaton_snmp +%{_mandir}/man8/fence_eaton_snmp.8* + +%package emerson +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Emerson devices (SNMP) +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description emerson +Fence agent for Emerson devices that are accessed via +the SNMP protocol. +%files emerson +%{_sbindir}/fence_emerson +%{_mandir}/man8/fence_emerson.8* + +%package eps +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for ePowerSwitch 8M+ power switches +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description eps +Fence agent for ePowerSwitch 8M+ power switches that are accessed +via the HTTP(s) protocol. +%files eps +%{_sbindir}/fence_eps +%{_mandir}/man8/fence_eps.8* + +%ifarch x86_64 +%package gce +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for GCE (Google Cloud Engine) +Requires: fence-agents-common = %{version}-%{release} +Requires: ha-cloud-support = %{version}-%{release} +Obsoletes: fence-agents < 3.1.13 +%description gce +Fence agent for GCE (Google Cloud Engine) instances. +%files gce +%{_sbindir}/fence_gce +%{_mandir}/man8/fence_gce.8* +%endif + +%package heuristics-ping +License: GPLv2+ and LGPLv2+ +Summary: Pseudo fence agent to affect other agents based on ping-heuristics +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +Obsoletes: fence-agents < 3.1.13 +%description heuristics-ping +Fence pseudo agent used to affect other agents based on +ping-heuristics. +%files heuristics-ping +%{_sbindir}/fence_heuristics_ping +%{_mandir}/man8/fence_heuristics_ping.8* + +%package hpblade +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for HP BladeSystem devices +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description hpblade +Fence agent for HP BladeSystem devices that are accessed via telnet +or SSH. +%files hpblade +%{_sbindir}/fence_hpblade +%{_mandir}/man8/fence_hpblade.8* + +%package ibmblade +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for IBM BladeCenter +Requires: net-snmp-utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ibmblade +Fence agent for IBM BladeCenter devices that are accessed +via the SNMP protocol. +%files ibmblade +%{_sbindir}/fence_ibmblade +%{_mandir}/man8/fence_ibmblade.8* + +%package ibm-powervs +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for IBM PowerVS +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ibm-powervs +Fence agent for IBM PowerVS that are accessed via REST API. +%files ibm-powervs +%{_sbindir}/fence_ibm_powervs +%{_mandir}/man8/fence_ibm_powervs.8* + +%package ibm-vpc +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for IBM Cloud VPC +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ibm-vpc +Fence agent for IBM Cloud VPC that are accessed via REST API. +%files ibm-vpc +%{_sbindir}/fence_ibm_vpc +%{_mandir}/man8/fence_ibm_vpc.8* + +%package ifmib +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for devices with IF-MIB interfaces +Requires: net-snmp-utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ifmib +Fence agent for IF-MIB interfaces that are accessed via +the SNMP protocol. +%files ifmib +%{_sbindir}/fence_ifmib +%{_mandir}/man8/fence_ifmib.8* + +%package ilo2 +License: GPLv2+ and LGPLv2+ +Summary: Fence agents for HP iLO2 devices +Requires: gnutls-utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ilo2 +Fence agents for HP iLO2 devices that are accessed via +the HTTP(s) protocol. +%files ilo2 +%{_sbindir}/fence_ilo +%{_sbindir}/fence_ilo2 +%{_mandir}/man8/fence_ilo.8* +%{_mandir}/man8/fence_ilo2.8* + +%package ilo-moonshot +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for HP iLO Moonshot devices +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ilo-moonshot +Fence agent for HP iLO Moonshot devices that are accessed +via telnet or SSH. +%files ilo-moonshot +%{_sbindir}/fence_ilo_moonshot +%{_mandir}/man8/fence_ilo_moonshot.8* + +%package ilo-mp +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for HP iLO MP devices +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ilo-mp +Fence agent for HP iLO MP devices that are accessed via telnet or SSH. +%files ilo-mp +%{_sbindir}/fence_ilo_mp +%{_mandir}/man8/fence_ilo_mp.8* + +%package ilo-ssh +License: GPLv2+ and LGPLv2+ +Summary: Fence agents for HP iLO devices over SSH +Requires: openssh-clients +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ilo-ssh +Fence agents for HP iLO devices that are accessed via telnet or SSH. +%files ilo-ssh +%{_sbindir}/fence_ilo_ssh +%{_mandir}/man8/fence_ilo_ssh.8* +%{_sbindir}/fence_ilo3_ssh +%{_mandir}/man8/fence_ilo3_ssh.8* +%{_sbindir}/fence_ilo4_ssh +%{_mandir}/man8/fence_ilo4_ssh.8* +%{_sbindir}/fence_ilo5_ssh +%{_mandir}/man8/fence_ilo5_ssh.8* + +%package intelmodular +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for devices with Intel Modular interfaces +Requires: net-snmp-utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description intelmodular +Fence agent for Intel Modular interfaces that are accessed +via the SNMP protocol. +%files intelmodular +%{_sbindir}/fence_intelmodular +%{_mandir}/man8/fence_intelmodular.8* + +%package ipdu +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for IBM iPDU network power switches +Requires: net-snmp-utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ipdu +Fence agent for IBM iPDU network power switches that are accessed +via the SNMP protocol. +%files ipdu +%{_sbindir}/fence_ipdu +%{_mandir}/man8/fence_ipdu.8* + +%package ipmilan +License: GPLv2+ and LGPLv2+ +Summary: Fence agents for devices with IPMI interface +Requires: /usr/bin/ipmitool +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description ipmilan +Fence agents for devices with IPMI interface. +%files ipmilan +%{_sbindir}/fence_ipmilan +%{_mandir}/man8/fence_ipmilan.8* +%{_sbindir}/fence_idrac +%{_mandir}/man8/fence_idrac.8* +%{_sbindir}/fence_ilo3 +%{_mandir}/man8/fence_ilo3.8* +%{_sbindir}/fence_ilo4 +%{_mandir}/man8/fence_ilo4.8* +%{_sbindir}/fence_ilo5 +%{_mandir}/man8/fence_ilo5.8* +%{_sbindir}/fence_ipmilanplus +%{_mandir}/man8/fence_ipmilanplus.8* +%{_sbindir}/fence_imm +%{_mandir}/man8/fence_imm.8* + +%package kdump +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for use with kdump crash recovery service +Requires: fence-agents-common = %{version}-%{release} +# this cannot be noarch since it's compiled +%description kdump +Fence agent for use with kdump crash recovery service. +%files kdump +%{_sbindir}/fence_kdump +%{_libexecdir}/fence_kdump_send +%{_mandir}/man8/fence_kdump.8* +%{_mandir}/man8/fence_kdump_send.8* + +%package kubevirt +License: GPLv2+ and LGPLv2+ and ASL 2.0 and BSD and BSD-2-Clause and BSD-3-Clause and ISC and MIT and MPL-2.0 +Summary: Fence agent for KubeVirt platform +Requires: fence-agents-common = %{version}-%{release} +Provides: bundled(python3-%{openshift}) = %{openshift_version} +Provides: bundled(python3-%{ruamelyamlclib}) = %{ruamelyamlclib_version} +Provides: bundled(python3-%{kubernetes}) = %{kubernetes_version} +Provides: bundled(python3-%{certifi}) = %{certifi_version} +Provides: bundled(python3-%{googleauth}) = %{googleauth_version} +Provides: bundled(python3-%{cachetools}) = %{cachetools_version} +Provides: bundled(python3-%{pyasn1modules}) = %{pyasn1modules_version} +Provides: bundled(python3-%{pyasn1}) = %{pyasn1_version} +Provides: bundled(python3-%{dateutil}) = %{dateutil_version} +Provides: bundled(python3-%{pyyaml}) = %{pyyaml_version} +Provides: bundled(python3-%{six}) = %{six_version} +Provides: bundled(python3-%{urllib3}) = %{urllib3_version} +Provides: bundled(python3-%{websocketclient}) = %{websocketclient_version} +Provides: bundled(python3-%{jinja2}) = %{jinja2_version} +Provides: bundled(python3-%{markupsafe}) = %{markupsafe_version} +Provides: bundled(python3-%{stringutils}) = %{stringutils_version} +Provides: bundled(python3-%{requests}) = %{requests_version} +Provides: bundled(python3-%{chrstnormalizer}) = %{chrstnormalizer_version} +Provides: bundled(python3-%{idna}) = %{idna_version} +Provides: bundled(python3-%{reqstsoauthlib}) = %{reqstsoauthlib_version} +Provides: bundled(python3-%{oauthlib}) = %{oauthlib_version} +Provides: bundled(python3-%{ruamelyaml}) = %{ruamelyaml_version} +Provides: bundled(python3-%{setuptools}) = %{setuptools_version} +%description kubevirt +Fence agent for KubeVirt platform. +%files kubevirt +%{_sbindir}/fence_kubevirt +%{_mandir}/man8/fence_kubevirt.8* +# bundled libraries +/usr/lib/fence-agents/%{bundled_lib_dir}/kubevirt + +%package lpar +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for IBM LPAR +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description lpar +Fence agent for IBM LPAR devices that are accessed via telnet or SSH. +%files lpar +%{_sbindir}/fence_lpar +%{_mandir}/man8/fence_lpar.8* + +%package mpath +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for reservations over Device Mapper Multipath +Requires: device-mapper-multipath +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description mpath +Fence agent for SCSI persistent reservation over +Device Mapper Multipath. +%files mpath +%{_sbindir}/fence_mpath +%{_datadir}/cluster/fence_mpath_check* +%{_mandir}/man8/fence_mpath.8* + +%ifarch x86_64 ppc64le +%package openstack +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for OpenStack's Nova service +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version} +Requires: python3-requests +%else +Requires: python-requests +%endif +Requires: fence-agents-common = %{version}-%{release} +Obsoletes: ha-openstack-support <= %{version}-%{release} +%description openstack +Fence agent for OpenStack's Nova service. +%files openstack +%{_sbindir}/fence_openstack +%{_mandir}/man8/fence_openstack.8* +%endif + +%package redfish +License: GPLv2+ and LGPLv2+ +Group: System Environment/Base +Summary: Fence agent for Redfish +Requires: fence-agents-common >= %{version}-%{release} +%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version} +Requires: python3-requests +%else +Requires: python-requests +%endif +Obsoletes: fence-agents < 3.1.13 +%description redfish +The fence-agents-redfish package contains a fence agent for Redfish +%files redfish +%defattr(-,root,root,-) +%{_sbindir}/fence_redfish +%{_mandir}/man8/fence_redfish.8* + +%package rhevm +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for RHEV-M +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description rhevm +Fence agent for RHEV-M via REST API. +%files rhevm +%{_sbindir}/fence_rhevm +%{_mandir}/man8/fence_rhevm.8* + +%package rsa +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for IBM RSA II +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description rsa +Fence agent for IBM RSA II devices that are accessed +via telnet or SSH. +%files rsa +%{_sbindir}/fence_rsa +%{_mandir}/man8/fence_rsa.8* + +%package rsb +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for Fujitsu RSB +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description rsb +Fence agent for Fujitsu RSB devices that are accessed +via telnet or SSH. +%files rsb +%{_sbindir}/fence_rsb +%{_mandir}/man8/fence_rsb.8* + +%package sbd +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for SBD (storage-based death) +Requires: sbd +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description sbd +Fence agent for SBD (storage-based death). +%files sbd +%{_sbindir}/fence_sbd +%{_mandir}/man8/fence_sbd.8* + +%package scsi +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for SCSI persistent reservations +Requires: sg3_utils +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description scsi +Fence agent for SCSI persistent reservations. +%files scsi +%{_sbindir}/fence_scsi +%{_datadir}/cluster/fence_scsi_check +%{_datadir}/cluster/fence_scsi_check_hardreboot +%{_mandir}/man8/fence_scsi.8* + +# skipped from allfenceagents +%package virsh +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for virtual machines based on libvirt +Requires: openssh-clients /usr/bin/virsh +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description virsh +Fence agent for virtual machines that are accessed via SSH. +%files virsh +%{_sbindir}/fence_virsh +%{_mandir}/man8/fence_virsh.8* + +%package vmware-rest +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for VMWare with REST API +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +Obsoletes: fence-agents < 3.1.13 +%description vmware-rest +Fence agent for VMWare with REST API. +%files vmware-rest +%{_sbindir}/fence_vmware_rest +%{_mandir}/man8/fence_vmware_rest.8* + +%package vmware-soap +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for VMWare with SOAP API v4.1+ +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description vmware-soap +Fence agent for VMWare with SOAP API v4.1+. +%files vmware-soap +%{_sbindir}/fence_vmware_soap +%{_mandir}/man8/fence_vmware_soap.8* + +%package wti +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for WTI Network power switches +Requires: openssh-clients +%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} +%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8) +Requires: telnet +%else +Recommends: telnet +%endif +%endif +Requires: fence-agents-common = %{version}-%{release} +BuildArch: noarch +%description wti +Fence agent for WTI network power switches that are accessed +via telnet or SSH. +%files wti +%{_sbindir}/fence_wti +%{_mandir}/man8/fence_wti.8* + +%ifarch s390x +%package zvm +License: GPLv2+ and LGPLv2+ +Summary: Fence agent for IBM z/VM over IP +Requires: fence-agents-common = %{version}-%{release} +%description zvm +Fence agent for IBM z/VM over IP. +%files zvm +%{_sbindir}/fence_zvmip +%{_mandir}/man8/fence_zvmip.8* +%endif + +# fence-virt + +%ifarch x86_64 +%package -n fence-virt +Summary: A pluggable fencing framework for virtual machines +Requires(post): systemd-sysv %{systemd_units} +Requires(preun): %{systemd_units} +Requires(postun): %{systemd_units} +%description -n fence-virt +Fencing agent for virtual machines. +%files -n fence-virt +%doc agents/virt/docs/* +%{_sbindir}/fence_virt +%{_sbindir}/fence_xvm +%{_mandir}/man8/fence_virt.* +%{_mandir}/man8/fence_xvm.* + +%package -n fence-virtd +Summary: Daemon which handles requests from fence-virt +%description -n fence-virtd +This package provides the host server framework, fence_virtd, +for fence_virt. The fence_virtd host daemon is resposible for +processing fencing requests from virtual machines and routing +the requests to the appropriate physical machine for action. +%files -n fence-virtd +%{_sbindir}/fence_virtd +%{_unitdir}/fence_virtd.service +%config(noreplace) %{_sysconfdir}/fence_virt.conf +%dir %{_libdir}/fence-virt +%{_libdir}/fence-virt/vsock.so +%{_mandir}/man5/fence_virt.conf.* +%{_mandir}/man8/fence_virtd.* + +%package -n fence-virtd-multicast +Summary: Multicast listener for fence-virtd +Requires: fence-virtd +%description -n fence-virtd-multicast +Provides multicast listener capability for fence-virtd. +%files -n fence-virtd-multicast +%{_libdir}/fence-virt/multicast.so + +%package -n fence-virtd-serial +Summary: Serial VMChannel listener for fence-virtd +Requires: libvirt >= 0.6.2 +Requires: fence-virtd +%description -n fence-virtd-serial +Provides serial VMChannel listener capability for fence-virtd. +%files -n fence-virtd-serial +%{_libdir}/fence-virt/serial.so + +%package -n fence-virtd-tcp +Summary: TCP listener for fence-virtd +Requires: fence-virtd +%description -n fence-virtd-tcp +Provides TCP listener capability for fence-virtd. +%files -n fence-virtd-tcp +%{_libdir}/fence-virt/tcp.so + +%package -n fence-virtd-libvirt +Summary: Libvirt backend for fence-virtd +Requires: libvirt >= 0.6.0 +Requires: fence-virtd +%description -n fence-virtd-libvirt +Provides fence_virtd with a connection to libvirt to fence +virtual machines. Useful for running a cluster of virtual +machines on a desktop. +%files -n fence-virtd-libvirt +%{_libdir}/fence-virt/virt.so + +%package -n fence-virtd-cpg +Summary: CPG/libvirt backend for fence-virtd +Requires: corosynclib +Requires: fence-virtd +%description -n fence-virtd-cpg +Provides fence_virtd with a connection to libvirt to fence +virtual machines. Uses corosync CPG to keep track of VM +locations to allow for non-local VMs to be fenced when VMs +are located on corosync cluster nodes. +%files -n fence-virtd-cpg +%{_libdir}/fence-virt/cpg.so +%endif + +%changelog +* Tue Aug 16 2022 Oyvind Albrigtsen - 4.10.0-30 +- fence_openstack: add support for reading config from clouds.yaml + and openrc + Resolves: rhbz#2041933, rhbz#2041935 + +* Wed Jun 22 2022 Oyvind Albrigtsen - 4.10.0-27 +- fence_ibm_powervs: add support for proxy, private API servers and + get token via API key + Resolves: rhbz#2093216 + +* Wed Jun 1 2022 Oyvind Albrigtsen - 4.10.0-26 +- fence_ibm_vpc: add proxy support + Resolves: rhbz#2092385 + +* Tue May 31 2022 Oyvind Albrigtsen - 4.10.0-25 +- all agents: unify ssl parameters to avoid having to use --ssl when + using --ssl-secure/--ssl-insecure for some agents + Resolves: rhbz#2072420 + +* Tue May 17 2022 Oyvind Albrigtsen - 4.10.0-24 +- fence_apc/fence_ilo_moonshot: add missing "import logging" + Resolves: rhbz#2086559 + +* Thu May 5 2022 Oyvind Albrigtsen - 4.10.0-23 +- fence_ibm_vpc: remove unused instance parameter and make limit + optional + Resolves: rhbz#2081235 + +* Fri Apr 29 2022 Oyvind Albrigtsen - 4.10.0-22 +- fence_gce: update fence agent + Resolves: rhbz#2079889 + +* Wed Apr 6 2022 Oyvind Albrigtsen - 4.10.0-21 +- fence_lpar: refactor to avoid duplicate code + Resolves: rhbz#2065114 + +* Wed Mar 30 2022 Oyvind Albrigtsen - 4.10.0-20 +- fence_azure_arm: fix sovereign cloud and MSI support + Resolves: rhbz#2010652 + +* Mon Mar 7 2022 Oyvind Albrigtsen - 4.10.0-19 +- fence_ibm_vpc: new fence agent + Resolves: rhbz#2061321 + +* Fri Feb 11 2022 Oyvind Albrigtsen - 4.10.0-18 +- fence_zvmip: add SSL/TLS support + Resolves: rhbz#2022334 + +* Mon Feb 7 2022 Oyvind Albrigtsen - 4.10.0-17 +- fence_ibm_powervs: new fence agent + Resolves: rhbz#2042496 + +* Mon Jan 17 2022 Oyvind Albrigtsen - 4.10.0-15 +- fence_kubevirt: new fence agent + Resolves: rhbz#2000954 + +* Tue Jan 11 2022 Oyvind Albrigtsen - 4.10.0-14 +- fence_openstack: add --ssl-insecure + Resolves: rhbz#2029791 + +* Thu Dec 2 2021 Oyvind Albrigtsen - 4.10.0-13 +- fence_amt_ws: fix "or" causing dead code + Resolves: rhbz#2010709 + +* Tue Aug 31 2021 Oyvind Albrigtsen - 4.10.0-9 +- Only build fence-virt subpackages for x86_64 arch + Resolves: rhbz#1965988 + +* Tue Aug 31 2021 Oyvind Albrigtsen - 4.10.0-8 +- OpenStack agents: add dependency + Resolves: rhbz#1857247 + +* Wed Aug 25 2021 Oyvind Albrigtsen - 4.10.0-7 +- remove suds dependency + Resolves: rhbz#1989149 + +* Mon Aug 09 2021 Mohan Boddu - 4.10.0-4 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Mon Jul 26 2021 Oyvind Albrigtsen - 4.10.0-2 +- new upstream release + Resolves: rhbz#1984803 + +* Wed Jul 7 2021 Oyvind Albrigtsen - 4.9.0-5 +- Remove "BuildArch: noarch" for arch-specific subpackages + Resolves: rhbz#1979827 + +* Fri Jun 4 2021 Oyvind Albrigtsen - 4.9.0-1 +- Rebase and add fence-virt subpackages + Resolves: rhbz#1965988 + +* Tue May 18 2021 Oyvind Albrigtsen - 4.7.1-10 +- remove pexpect dependency + Resolves: rhbz#1961551 + +* Thu Apr 15 2021 Mohan Boddu - 4.7.1-9 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Tue Mar 23 2021 Oyvind Albrigtsen - 4.7.1-8 +- cloud agents: only build for x86_64 + +* Thu Mar 4 2021 Oyvind Albrigtsen - 4.7.1-5 +- update HA cloud support package + +* Mon Feb 15 2021 Oyvind Albrigtsen - 4.7.1-4 +- create HA cloud support package + +* Thu Feb 11 2021 Oyvind Albrigtsen - 4.7.1-3 +- add aliyun subpackage +- fence-agents-mpath: add missing fence_mpath_check* + +* Mon Feb 8 2021 Oyvind Albrigtsen - 4.7.1-1 +- new upstream release + +* Wed Dec 9 2020 Oyvind Albrigtsen - 4.7.0-1 +- new upstream release + +* Sat Aug 01 2020 Fedora Release Engineering - 4.5.2-4 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 4.5.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jan 28 2020 Fedora Release Engineering - 4.5.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Wed Oct 23 2019 Oyvind Albrigtsen - 4.5.2-1 +- new upstream release +- added openstack subpackage +- spec improvements based on upstream spec-file + +* Tue Sep 24 2019 Oyvind Albrigtsen - 4.5.1-1 +- new upstream release + +* Thu Jul 25 2019 Fedora Release Engineering - 4.4.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Tue Jun 4 2019 Oyvind Albrigtsen - 4.4.0-1 +- new upstream release + +* Thu Jan 31 2019 Fedora Release Engineering - 4.3.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Jan 16 2019 Oyvind Albrigtsen - 4.3.3-2 +- fence-agents-scsi: add missing fence-agents-common dependency + +* Mon Dec 3 2018 Oyvind Albrigtsen - 4.3.3-1 +- new upstream release + +* Fri Oct 5 2018 Oyvind Albrigtsen - 4.3.0-1 +- new upstream release + +* Wed Sep 19 2018 Oyvind Albrigtsen - 4.2.1-6 +- Fix missing fence-agents-all subpackage after spec improvements + +* Wed Aug 22 2018 Oyvind Albrigtsen - 4.2.1-5 +- Python 3: fix has_key() issues + +* Mon Aug 20 2018 Jan Pokorný - 4.2.1-4 +- mark non-compiled packages properly as noarch, restructure excludes +- move azure_fence.py and XenAPI.py to respective subpackages from -common +- sanitize allfenceagents internally defined enumeration +- sanitize BuildRequires with respect to packaging guidelines +- bytecompile native Python modules and ship these bytecodes properly +- only refer to Python binary symbolically, drop buildroot cleanup +- cleanup package summaries/descriptions, order agent subpackages properly + +* Fri Jul 13 2018 Fedora Release Engineering - 4.2.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Mon Jun 18 2018 Oyvind Albrigtsen - 4.2.1-2 +- fence_vmware_soap: fix python3-suds issue + +* Thu May 31 2018 Oyvind Albrigtsen - 4.2.1-1 +- new upstream release + +* Fri May 25 2018 Oyvind Albrigtsen - 4.2.0-2 +- fence_scsi: fix Python 3 encoding issue + +* Thu May 17 2018 Oyvind Albrigtsen - 4.2.0-1 +- new upstream release + +* Thu Feb 15 2018 Oyvind Albrigtsen - 4.1.1-1 +- new upstream release +- fence_vmware_soap / fence_ovh: use Python 2 till python3-suds bug + is fixed + +* Fri Feb 9 2018 Oyvind Albrigtsen - 4.1.0-2 +- new upstream release + +* Wed Feb 07 2018 Fedora Release Engineering - 4.0.24-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Jan 11 2018 Iryna Shcherbina - 4.0.24-14 +- Cleanup no longer needed Python 2 dependencies + +* Tue Nov 07 2017 Troy Dawson - 4.0.24-13 +- Cleanup spec file conditionals + +* Tue Aug 29 2017 Oyvind Albrigtsen - 4.0.24-12 +- fence-agents-common: remove fence_scsi_check files +- fence-scsi: add "fence_scsi_check_hardreboot" + +* Thu Aug 3 2017 Oyvind Albrigtsen - 4.0.24-10 +- fence_zvm: fix "uintptr_t" undeclared + +* Thu Aug 3 2017 Oyvind Albrigtsen - 4.0.24-9 +- Fix encoding for pexpect with Python 3.6 + Resolves: rhbz#1473908 + +* Wed Aug 02 2017 Fedora Release Engineering - 4.0.24-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 4.0.24-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Fri Feb 10 2017 Fedora Release Engineering - 4.0.24-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Fri Dec 23 2016 Oyvind Albrigtsen - 4.0.24-5 +- Fix to build in Python 3 only environment + +* Mon Dec 19 2016 Miro Hrončok - 4.0.24-4 +- Rebuild for Python 3.6 + +* Wed Sep 21 2016 Marek Grac - 4.0.24-4 +- Remove Obsoletes that are no longer valid + +* Fri Sep 2 2016 Oyvind Albrigtsen - 4.0.24-2 +- fence-agents-common: add dependency on python3-pycurl + +* Fri Aug 26 2016 Oyvind Albrigtsen - 4.0.24-1 +- new upstream release + +* Wed Jul 13 2016 Oyvind Albrigtsen - 4.0.23-2 +- fix build issue on s390 + +* Tue Jul 12 2016 Oyvind Albrigtsen - 4.0.23-1 +- new upstream release +- new package fence-agents-amt-ws +- new package fence-agents-compute +- new package fence-agents-drac +- new package fence-agents-hds-cb +- new package fence-agents-mpath +- new package fence-agents-sanbox2 +- new package fence-agents-sbd +- new package fence-agents-vbox +- new package fence-agents-vmware +- new package fence-agents-xenapi + +* Wed Feb 03 2016 Fedora Release Engineering - 4.0.20-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Tue Aug 11 2015 Marek Grac - 4.0.20-1 +- new upstream release +- new package fence-agents-rcd-serial + +* Wed Jun 17 2015 Fedora Release Engineering - 4.0.16-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Thu Mar 05 2015 Marek Grac - 4.0.16-1 +- new upstream release + +* Mon Feb 09 2015 Marek Grac - 4.0.15-1 +- new upstream release + +* Thu Jan 08 2015 Marek Grac - 4.0.14-1 +- new upstream release +- new packages fence-agents-zvm and fence-agents-emerson + +* Thu Oct 16 2014 Marek Grac - 4.0.12-1 +- new upstream release +- new package fence-agents-ilo-ssh + +* Wed Aug 27 2014 Marek Grac - 4.0.10 +- new upstream release +- new package fence-agents-ilo-moonshot + +* Sat Jun 07 2014 Fedora Release Engineering - 4.0.9-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Fri May 16 2014 Marek Grac - 4.0.9 +- new upstream release +- new package fence-agents-pve + +* Mon Apr 07 2014 Marek Grac - 4.0.8-1 +- new upstream release +- new package fence-agents-raritan + +* Wed Feb 26 2014 Marek Grac - 4.0.7-3 +- requires a specific version of fence-agents-common + +* Mon Feb 17 2014 Marek Grac - 4.0.7-2 +- new upstream release +- changed dependancy from nss/nspr to gnutls-utils + +* Fri Jan 10 2014 Marek Grac - 4.0.4-4 +- new upstream release +- new package fence-agents-amt + +* Mon Oct 07 2013 Marek Grac - 4.0.4-3 +- new upstream release +- new package fence-agents-netio + +* Tue Sep 03 2013 Marek Grac - 4.0.3-1 +- new upstream release +- new packages fence-agents-brocade and fence-agents-ovh + +* Sat Aug 03 2013 Fedora Release Engineering - 4.0.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Thu Jul 18 2013 Petr Pisar - 4.0.1-2 +- Perl 5.18 rebuild + +* Mon Jul 01 2013 Marek Grac - 4.0.1-1 +- new upstream release + +* Mon Jun 24 2013 Marek Grac - 4.0.0-5 +- fence-agents-all should provide fence-agent for clean update path + +* Wed Apr 03 2013 Marek Grac - 4.0.0-4 +- minor changes in spec file + +* Thu Mar 21 2013 Marek Grac - 4.0.0-3 +- minor changes in spec file + +* Mon Mar 18 2013 Marek Grac - 4.0.0-2 +- minor changes in spec file + +* Mon Mar 11 2013 Marek Grac - 4.0.0-1 +- new upstream release +- introducing subpackages + +