commit
3dc1535cc5
@ -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
|
@ -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
|
@ -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 > $@
|
@ -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
|
@ -0,0 +1,24 @@
|
||||
From 52de83b30a8eea638b01f649f4884f50417121c0 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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*)
|
||||
;;
|
@ -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
|
@ -0,0 +1,102 @@
|
||||
From 647841dea9d93922779a4aa7d0b5f52f5bc2b4e9 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Kenigsberg <danken@redhat.com>
|
||||
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 <danken@redhat.com>
|
||||
---
|
||||
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 @@
|
||||
<content type="boolean" />
|
||||
<shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="namespace" unique="0" required="1">
|
||||
+ <parameter name="namespace" unique="0" required="0">
|
||||
<getopt mixed="--namespace=[namespace]" />
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">Namespace of the KubeVirt machine.</shortdesc>
|
@ -0,0 +1,139 @@
|
||||
From e339f304d4423a0e661d915f72ba88553b21d74a Mon Sep 17 00:00:00 2001
|
||||
From: MSSedusch <sedusch@microsoft.com>
|
||||
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 <sedusch@microsoft.com>
|
||||
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,
|
@ -0,0 +1,22 @@
|
||||
From 06855a8227fa91f6216119daa3d32d5858c62837 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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"
|
@ -0,0 +1,32 @@
|
||||
From 9812473270e9a404c632358c1debfa4a1fb440fe Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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.', \
|
@ -0,0 +1,98 @@
|
||||
From 90c4f78e005ca4141039d1dce032b5f2c2ff4783 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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 <oalbrigt@redhat.com>
|
||||
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.
|
||||
<parameter name="ssl" unique="0" required="0">
|
||||
<getopt mixed="-z, --ssl" />
|
||||
<content type="boolean" default="1" />
|
||||
- <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
|
||||
+ <shortdesc lang="en">Use SSL connection with verifying certificate (Default)</shortdesc>
|
||||
</parameter>
|
||||
<parameter name="ssl_insecure" unique="0" required="0">
|
||||
<getopt mixed="--ssl-insecure" />
|
||||
@@ -111,6 +111,11 @@ to access the system's directory manager.
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">Login name</shortdesc>
|
||||
</parameter>
|
||||
+ <parameter name="disable_ssl" unique="0" required="0">
|
||||
+ <getopt mixed="--disable-ssl" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Don't use SSL</shortdesc>
|
||||
+ </parameter>
|
||||
<parameter name="quiet" unique="0" required="0">
|
||||
<getopt mixed="-q, --quiet" />
|
||||
<content type="boolean" />
|
@ -0,0 +1,136 @@
|
||||
From 81be3c529ec1165f3135b4f14fbec2a19403cfbe Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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.
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
|
||||
</parameter>
|
||||
+ <parameter name="ssl" unique="0" required="0">
|
||||
+ <getopt mixed="-z, --ssl" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="ssl_insecure" unique="0" required="0">
|
||||
+ <getopt mixed="--ssl-insecure" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="ssl_secure" unique="0" required="0">
|
||||
+ <getopt mixed="--ssl-secure" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
|
||||
+ </parameter>
|
||||
<parameter name="username" unique="0" required="1" obsoletes="login">
|
||||
<getopt mixed="-l, --username=[name]" />
|
||||
<content type="string" />
|
||||
@@ -181,6 +196,10 @@ to access the system's directory manager.
|
||||
<content type="integer" default="1" />
|
||||
<shortdesc lang="en">Count of attempts to retry power on</shortdesc>
|
||||
</parameter>
|
||||
+ <parameter name="gnutlscli_path" unique="0" required="0">
|
||||
+ <getopt mixed="--gnutlscli-path=[path]" />
|
||||
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
|
||||
+ </parameter>
|
||||
</parameters>
|
||||
<actions>
|
||||
<action name="on" automatic="0"/>
|
||||
|
||||
From 8021e698095c5bd0ef33ee5f56fc448e946cb92c Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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.
|
||||
</parameter>
|
||||
<parameter name="ssl" unique="0" required="0">
|
||||
<getopt mixed="-z, --ssl" />
|
||||
- <content type="boolean" />
|
||||
+ <content type="boolean" default="1" />
|
||||
<shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
|
||||
</parameter>
|
||||
<parameter name="ssl_insecure" unique="0" required="0">
|
@ -0,0 +1,72 @@
|
||||
From f79436d3a5e4cf279be0974e9633ad8994a017f7 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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 @@
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">UUID of the node to be fenced.</shortdesc>
|
||||
</parameter>
|
||||
+ <parameter name="ssl_insecure" unique="0" required="0">
|
||||
+ <getopt mixed="--ssl-insecure" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
|
||||
+ </parameter>
|
||||
<parameter name="username" unique="0" required="1" obsoletes="login">
|
||||
<getopt mixed="-l, --username=[name]" />
|
||||
<content type="string" />
|
@ -0,0 +1,59 @@
|
||||
From b7032d16a07997ecab3b2c11a6436b3fa21f9043 Mon Sep 17 00:00:00 2001
|
||||
From: "Fabio M. Di Nitto" <fdinitto@redhat.com>
|
||||
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 <fdinitto@redhat.com>
|
||||
---
|
||||
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 @@
|
||||
</parameter>
|
||||
<parameter name="cacert" unique="0" required="0">
|
||||
<getopt mixed="--cacert=[cacert]" />
|
||||
- <content type="string" default="/etc/pki/tls/certs/ca-bundle.crt" />
|
||||
+ <content type="string" default="" />
|
||||
<shortdesc lang="en">SSL X.509 certificates file</shortdesc>
|
||||
</parameter>
|
||||
<parameter name="apitimeout" unique="0" required="0">
|
@ -0,0 +1,313 @@
|
||||
From 2f741df2ce73da85bbd205d861b527aa141d9776 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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 <oalbrigt@redhat.com>
|
||||
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 @@
|
||||
<content type="string" default="reboot" />
|
||||
<shortdesc lang="en">Fencing action</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="login" unique="0" required="1" deprecated="1">
|
||||
+ <parameter name="login" unique="0" required="0" deprecated="1">
|
||||
<getopt mixed="-l, --username=[name]" />
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">Login name</shortdesc>
|
||||
@@ -48,27 +48,27 @@
|
||||
<content type="boolean" />
|
||||
<shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="username" unique="0" required="1" obsoletes="login">
|
||||
+ <parameter name="username" unique="0" required="0" obsoletes="login">
|
||||
<getopt mixed="-l, --username=[name]" />
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">Login name</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="auth-url" unique="0" required="1" deprecated="1">
|
||||
+ <parameter name="auth-url" unique="0" required="0" deprecated="1">
|
||||
<getopt mixed="--auth-url=[authurl]" />
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">Keystone Auth URL</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="auth_url" unique="0" required="1" obsoletes="auth-url">
|
||||
+ <parameter name="auth_url" unique="0" required="0" obsoletes="auth-url">
|
||||
<getopt mixed="--auth-url=[authurl]" />
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">Keystone Auth URL</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="project-name" unique="0" required="1" deprecated="1">
|
||||
+ <parameter name="project-name" unique="0" required="0" deprecated="1">
|
||||
<getopt mixed="--project-name=[project]" />
|
||||
<content type="string" default="admin" />
|
||||
<shortdesc lang="en">Keystone Project</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="project_name" unique="0" required="1" obsoletes="project-name">
|
||||
+ <parameter name="project_name" unique="0" required="0" obsoletes="project-name">
|
||||
<getopt mixed="--project-name=[project]" />
|
||||
<content type="string" default="admin" />
|
||||
<shortdesc lang="en">Keystone Project</shortdesc>
|
||||
@@ -93,6 +93,26 @@
|
||||
<content type="string" default="Default" />
|
||||
<shortdesc lang="en">Keystone Project Domain Name</shortdesc>
|
||||
</parameter>
|
||||
+ <parameter name="clouds-yaml" unique="0" required="0" deprecated="1">
|
||||
+ <getopt mixed="--clouds-yaml=[clouds-yaml]" />
|
||||
+ <content type="string" default="~/.config/openstack/clouds.yaml" />
|
||||
+ <shortdesc lang="en">clouds.yaml config file</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="clouds_yaml" unique="0" required="0" obsoletes="clouds-yaml">
|
||||
+ <getopt mixed="--clouds-yaml=[clouds-yaml]" />
|
||||
+ <content type="string" default="~/.config/openstack/clouds.yaml" />
|
||||
+ <shortdesc lang="en">clouds.yaml config file</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="cloud" unique="0" required="0">
|
||||
+ <getopt mixed="--cloud=[cloud]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Cloud from clouds.yaml</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="openrc" unique="0" required="0">
|
||||
+ <getopt mixed="--openrc=[openrc]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">openrc config file</shortdesc>
|
||||
+ </parameter>
|
||||
<parameter name="uuid" unique="0" required="0">
|
||||
<getopt mixed="--uuid=[uuid]" />
|
||||
<content type="string" />
|
@ -0,0 +1,171 @@
|
||||
From 7d9572ec947d23fa18ac530f07fe33ba148c9634 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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 @@
|
||||
<content type="string" default="Default" />
|
||||
<shortdesc lang="en">Keystone Project Domain Name</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="clouds-yaml" unique="0" required="0" deprecated="1">
|
||||
- <getopt mixed="--clouds-yaml=[clouds-yaml]" />
|
||||
- <content type="string" default="~/.config/openstack/clouds.yaml" />
|
||||
- <shortdesc lang="en">clouds.yaml config file</shortdesc>
|
||||
- </parameter>
|
||||
- <parameter name="clouds_yaml" unique="0" required="0" obsoletes="clouds-yaml">
|
||||
- <getopt mixed="--clouds-yaml=[clouds-yaml]" />
|
||||
- <content type="string" default="~/.config/openstack/clouds.yaml" />
|
||||
- <shortdesc lang="en">clouds.yaml config file</shortdesc>
|
||||
- </parameter>
|
||||
<parameter name="cloud" unique="0" required="0">
|
||||
<getopt mixed="--cloud=[cloud]" />
|
||||
<content type="string" />
|
@ -0,0 +1,22 @@
|
||||
From fbca33a536413565108374dd4ed3237b6f7896bd Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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
|
@ -0,0 +1,740 @@
|
||||
From 3078e4d55d3bad2bbf9309785fdb2b53afac8d65 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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 @@
|
||||
+<?xml version="1.0" ?>
|
||||
+<resource-agent name="fence_ibm_powervs" shortdesc="Fence agent for IBM PowerVS" >
|
||||
+<longdesc>fence_ibm_powervs is an I/O Fencing agent which can be used with IBM PowerVS to fence virtual machines.</longdesc>
|
||||
+<vendor-url>https://www.ibm.com</vendor-url>
|
||||
+<parameters>
|
||||
+ <parameter name="crn" unique="0" required="1">
|
||||
+ <getopt mixed="--crn=[crn]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">CRN</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="instance" unique="0" required="1">
|
||||
+ <getopt mixed="--instance=[instance]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">PowerVS Instance</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="region" unique="0" required="1">
|
||||
+ <getopt mixed="--region=[region]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Region</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="token" unique="0" required="1">
|
||||
+ <getopt mixed="--token=[token]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Bearer Token</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="action" unique="0" required="1">
|
||||
+ <getopt mixed="-o, --action=[action]" />
|
||||
+ <content type="string" default="reboot" />
|
||||
+ <shortdesc lang="en">Fencing action</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
|
||||
+ <getopt mixed="-n, --plug=[id]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="port" unique="0" required="1" deprecated="1">
|
||||
+ <getopt mixed="-n, --plug=[id]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="quiet" unique="0" required="0">
|
||||
+ <getopt mixed="-q, --quiet" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="verbose" unique="0" required="0">
|
||||
+ <getopt mixed="-v, --verbose" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="verbose_level" unique="0" required="0">
|
||||
+ <getopt mixed="--verbose-level" />
|
||||
+ <content type="integer" />
|
||||
+ <shortdesc lang="en">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).</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="debug" unique="0" required="0" deprecated="1">
|
||||
+ <getopt mixed="-D, --debug-file=[debugfile]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
|
||||
+ <getopt mixed="-D, --debug-file=[debugfile]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="version" unique="0" required="0">
|
||||
+ <getopt mixed="-V, --version" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Display version information and exit</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="help" unique="0" required="0">
|
||||
+ <getopt mixed="-h, --help" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Display help and exit</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="separator" unique="0" required="0">
|
||||
+ <getopt mixed="-C, --separator=[char]" />
|
||||
+ <content type="string" default="," />
|
||||
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="delay" unique="0" required="0">
|
||||
+ <getopt mixed="--delay=[seconds]" />
|
||||
+ <content type="second" default="0" />
|
||||
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="disable_timeout" unique="0" required="0">
|
||||
+ <getopt mixed="--disable-timeout=[true/false]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="login_timeout" unique="0" required="0">
|
||||
+ <getopt mixed="--login-timeout=[seconds]" />
|
||||
+ <content type="second" default="5" />
|
||||
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="power_timeout" unique="0" required="0">
|
||||
+ <getopt mixed="--power-timeout=[seconds]" />
|
||||
+ <content type="second" default="30" />
|
||||
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="power_wait" unique="0" required="0">
|
||||
+ <getopt mixed="--power-wait=[seconds]" />
|
||||
+ <content type="second" default="1" />
|
||||
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="shell_timeout" unique="0" required="0">
|
||||
+ <getopt mixed="--shell-timeout=[seconds]" />
|
||||
+ <content type="second" default="15" />
|
||||
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="stonith_status_sleep" unique="0" required="0">
|
||||
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
|
||||
+ <content type="second" default="1" />
|
||||
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="retry_on" unique="0" required="0">
|
||||
+ <getopt mixed="--retry-on=[attempts]" />
|
||||
+ <content type="integer" default="1" />
|
||||
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
|
||||
+ </parameter>
|
||||
+</parameters>
|
||||
+<actions>
|
||||
+ <action name="on" automatic="0"/>
|
||||
+ <action name="off" />
|
||||
+ <action name="reboot" />
|
||||
+ <action name="status" />
|
||||
+ <action name="list" />
|
||||
+ <action name="list-status" />
|
||||
+ <action name="monitor" />
|
||||
+ <action name="metadata" />
|
||||
+ <action name="manpage" />
|
||||
+ <action name="validate-all" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
||||
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 @@
|
||||
+<?xml version="1.0" ?>
|
||||
+<resource-agent name="fence_ibm_vpc" shortdesc="Fence agent for IBM Cloud VPC" >
|
||||
+<longdesc>fence_ibm_vpc is an I/O Fencing agent which can be used with IBM Cloud VPC to fence virtual machines.</longdesc>
|
||||
+<vendor-url>https://www.ibm.com</vendor-url>
|
||||
+<parameters>
|
||||
+ <parameter name="apikey" unique="0" required="1">
|
||||
+ <getopt mixed="--apikey=[key]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">API Key</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="instance" unique="0" required="1">
|
||||
+ <getopt mixed="--instance=[instance]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Cloud Instance</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="limit" unique="0" required="1">
|
||||
+ <getopt mixed="--limit=[number]" />
|
||||
+ <content type="string" default="50" />
|
||||
+ <shortdesc lang="en">Number of nodes returned by API</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="region" unique="0" required="1">
|
||||
+ <getopt mixed="--region=[region]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Region</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="action" unique="0" required="1">
|
||||
+ <getopt mixed="-o, --action=[action]" />
|
||||
+ <content type="string" default="reboot" />
|
||||
+ <shortdesc lang="en">Fencing action</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
|
||||
+ <getopt mixed="-n, --plug=[id]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="port" unique="0" required="1" deprecated="1">
|
||||
+ <getopt mixed="-n, --plug=[id]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="quiet" unique="0" required="0">
|
||||
+ <getopt mixed="-q, --quiet" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="verbose" unique="0" required="0">
|
||||
+ <getopt mixed="-v, --verbose" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="verbose_level" unique="0" required="0">
|
||||
+ <getopt mixed="--verbose-level" />
|
||||
+ <content type="integer" />
|
||||
+ <shortdesc lang="en">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).</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="debug" unique="0" required="0" deprecated="1">
|
||||
+ <getopt mixed="-D, --debug-file=[debugfile]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
|
||||
+ <getopt mixed="-D, --debug-file=[debugfile]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="version" unique="0" required="0">
|
||||
+ <getopt mixed="-V, --version" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Display version information and exit</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="help" unique="0" required="0">
|
||||
+ <getopt mixed="-h, --help" />
|
||||
+ <content type="boolean" />
|
||||
+ <shortdesc lang="en">Display help and exit</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="separator" unique="0" required="0">
|
||||
+ <getopt mixed="-C, --separator=[char]" />
|
||||
+ <content type="string" default="," />
|
||||
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="delay" unique="0" required="0">
|
||||
+ <getopt mixed="--delay=[seconds]" />
|
||||
+ <content type="second" default="0" />
|
||||
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="disable_timeout" unique="0" required="0">
|
||||
+ <getopt mixed="--disable-timeout=[true/false]" />
|
||||
+ <content type="string" />
|
||||
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="login_timeout" unique="0" required="0">
|
||||
+ <getopt mixed="--login-timeout=[seconds]" />
|
||||
+ <content type="second" default="5" />
|
||||
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="power_timeout" unique="0" required="0">
|
||||
+ <getopt mixed="--power-timeout=[seconds]" />
|
||||
+ <content type="second" default="30" />
|
||||
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="power_wait" unique="0" required="0">
|
||||
+ <getopt mixed="--power-wait=[seconds]" />
|
||||
+ <content type="second" default="1" />
|
||||
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="shell_timeout" unique="0" required="0">
|
||||
+ <getopt mixed="--shell-timeout=[seconds]" />
|
||||
+ <content type="second" default="15" />
|
||||
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="stonith_status_sleep" unique="0" required="0">
|
||||
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
|
||||
+ <content type="second" default="1" />
|
||||
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="retry_on" unique="0" required="0">
|
||||
+ <getopt mixed="--retry-on=[attempts]" />
|
||||
+ <content type="integer" default="1" />
|
||||
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
|
||||
+ </parameter>
|
||||
+</parameters>
|
||||
+<actions>
|
||||
+ <action name="on" automatic="0"/>
|
||||
+ <action name="off" />
|
||||
+ <action name="reboot" />
|
||||
+ <action name="status" />
|
||||
+ <action name="list" />
|
||||
+ <action name="list-status" />
|
||||
+ <action name="monitor" />
|
||||
+ <action name="metadata" />
|
||||
+ <action name="manpage" />
|
||||
+ <action name="validate-all" />
|
||||
+</actions>
|
||||
+</resource-agent>
|
@ -0,0 +1,65 @@
|
||||
From e3dff8570b70f0c19eca84cf02f0aadd68e16599 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Renninger <trenn@suse.com>
|
||||
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)
|
||||
|
@ -0,0 +1,291 @@
|
||||
From 999f2f8b4dc7d258679daf8c3f13d9b317ff4435 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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 @@
|
||||
</parameter>
|
||||
<parameter name="ipport" unique="0" required="0">
|
||||
<getopt mixed="-u, --ipport=[port]" />
|
||||
- <content type="integer" default="80" />
|
||||
+ <content type="integer" default="443" />
|
||||
<shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
|
||||
</parameter>
|
||||
<parameter name="method" unique="0" required="0">
|
||||
@@ -43,7 +43,7 @@
|
||||
</parameter>
|
||||
<parameter name="ssl" unique="0" required="0">
|
||||
<getopt mixed="-z, --ssl" />
|
||||
- <content type="boolean" />
|
||||
+ <content type="boolean" default="1" />
|
||||
<shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
|
||||
</parameter>
|
||||
<parameter name="ssl_insecure" unique="0" required="0">
|
@ -0,0 +1,30 @@
|
||||
From 6430104318b4bf349425b08636183bf839812e04 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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:
|
@ -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)
|
@ -0,0 +1,65 @@
|
||||
From d0254345472c9415af1e06e9e8df2fe0ce464db0 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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 @@
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">API Key</shortdesc>
|
||||
</parameter>
|
||||
- <parameter name="instance" unique="0" required="1">
|
||||
- <getopt mixed="--instance=[instance]" />
|
||||
- <content type="string" />
|
||||
- <shortdesc lang="en">Cloud Instance</shortdesc>
|
||||
- </parameter>
|
||||
- <parameter name="limit" unique="0" required="1">
|
||||
+ <parameter name="limit" unique="0" required="0">
|
||||
<getopt mixed="--limit=[number]" />
|
||||
<content type="string" default="50" />
|
||||
<shortdesc lang="en">Number of nodes returned by API</shortdesc>
|
@ -0,0 +1,34 @@
|
||||
From 6ea2c6b5d1cc51e93fa7084d76d9272512461e58 Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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 *
|
@ -0,0 +1,62 @@
|
||||
From be409554bbc99df2bba22cb01e8a6df634af896d Mon Sep 17 00:00:00 2001
|
||||
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
|
||||
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://<URL>:<PORT>] Proxy: 'http://<URL>:<PORT>'",
|
||||
+ "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 @@
|
||||
<content type="string" default="50" />
|
||||
<shortdesc lang="en">Number of nodes returned by API</shortdesc>
|
||||
</parameter>
|
||||
+ <parameter name="proxy" unique="0" required="0">
|
||||
+ <getopt mixed="--proxy=[http://<URL>:<PORT>]" />
|
||||
+ <content type="string" default="" />
|
||||
+ <shortdesc lang="en">Network proxy</shortdesc>
|
||||
+ </parameter>
|
||||
<parameter name="region" unique="0" required="1">
|
||||
<getopt mixed="--region=[region]" />
|
||||
<content type="string" />
|
@ -0,0 +1,455 @@
|
||||
From 98fec5c6d55369ad681abc0cde0d8677835957ab Mon Sep 17 00:00:00 2001
|
||||
From: Arnold Beilmann <arnoldbeilmann@macbook-pro.speedport.ip>
|
||||
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://<URL>:<PORT>] Proxy: 'http://<URL>:<PORT>'",
|
||||
+ "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 <oalbrigt@redhat.com>
|
||||
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 @@
|
||||
<longdesc>fence_ibm_powervs is an I/O Fencing agent which can be used with IBM PowerVS to fence virtual machines.</longdesc>
|
||||
<vendor-url>https://www.ibm.com</vendor-url>
|
||||
<parameters>
|
||||
+ <parameter name="api-type" unique="0" required="0" deprecated="1">
|
||||
+ <getopt mixed="--api-type=[public|private]" />
|
||||
+ <content type="string" default="private" />
|
||||
+ <shortdesc lang="en">API-type (public|private)</shortdesc>
|
||||
+ </parameter>
|
||||
+ <parameter name="api_type" unique="0" required="0" obsoletes="api-type">
|
||||
+ <getopt mixed="--api-type=[public|private]" />
|
||||
+ <content type="string" default="private" />
|
||||
+ <shortdesc lang="en">API-type (public|private)</shortdesc>
|
||||
+ </parameter>
|
||||
<parameter name="crn" unique="0" required="1">
|
||||
<getopt mixed="--crn=[crn]" />
|
||||
<content type="string" />
|
||||
@@ -13,6 +23,11 @@
|
||||
<content type="string" />
|
||||
<shortdesc lang="en">PowerVS Instance</shortdesc>
|
||||
</parameter>
|
||||
+ <parameter name="proxy" unique="0" required="0">
|
||||
+ <getopt mixed="--proxy=[http://<URL>:<PORT>]" />
|
||||
+ <content type="string" default="" />
|
||||
+ <shortdesc lang="en">Network proxy</shortdesc>
|
||||
+ </parameter>
|
||||
<parameter name="region" unique="0" required="1">
|
||||
<getopt mixed="--region=[region]" />
|
||||
<content type="string" />
|
||||
@@ -21,7 +36,7 @@
|
||||
<parameter name="token" unique="0" required="1">
|
||||
<getopt mixed="--token=[token]" />
|
||||
<content type="string" />
|
||||
- <shortdesc lang="en">Bearer Token</shortdesc>
|
||||
+ <shortdesc lang="en">API Token</shortdesc>
|
||||
</parameter>
|
||||
<parameter name="action" unique="0" required="1">
|
||||
<getopt mixed="-o, --action=[action]" />
|
||||
@@ -110,7 +125,7 @@
|
||||
</parameter>
|
||||
<parameter name="stonith_status_sleep" unique="0" required="0">
|
||||
<getopt mixed="--stonith-status-sleep=[seconds]" />
|
||||
- <content type="second" default="1" />
|
||||
+ <content type="second" default="3" />
|
||||
<shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
|
||||
</parameter>
|
||||
<parameter name="retry_on" unique="0" required="0">
|
@ -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
|
@ -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:
|
@ -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"
|
@ -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
|
@ -0,0 +1,3 @@
|
||||
aliyun-python-sdk-ecs
|
||||
# for resource-agents-cloud
|
||||
aliyuncli>=2.1.5
|
@ -0,0 +1,2 @@
|
||||
boto3
|
||||
jmespath<1.0.0
|
@ -0,0 +1,3 @@
|
||||
azure-mgmt-compute
|
||||
azure-mgmt-network
|
||||
msrestazure
|
@ -0,0 +1,2 @@
|
||||
pexpect
|
||||
suds-community
|
@ -0,0 +1,4 @@
|
||||
google-api-python-client==1.12.8
|
||||
chardet<4.0
|
||||
# for gcp-vpc-move-route
|
||||
pyroute2
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue