Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3151658
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/agents/ibm_powervs/fence_ibm_powervs.py b/agents/ibm_powervs/fence_ibm_powervs.py
index 73dfe0ab..f6f4fd83 100755
--- a/agents/ibm_powervs/fence_ibm_powervs.py
+++ b/agents/ibm_powervs/fence_ibm_powervs.py
@@ -1,299 +1,323 @@
#!@PYTHON@ -tt
import sys
-import pycurl, io, json
+import pycurl
+import io
+import json
import logging
import atexit
-import time
+
sys.path.append("@FENCEAGENTSLIBDIR@")
-from fencing import *
-from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS
+from fencing import all_opt, atexit_handler, check_input, process_input, show_docs, fence_action, fail, run_delay, EC_STATUS
state = {
"ACTIVE": "on",
"SHUTOFF": "off",
"HARD_REBOOT": "on",
"SOFT_REBOOT": "on",
"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"
-
- return res["access_token"]
+ try:
+ if options["--token"][0] == '@':
+ key_file = options["--token"][1:]
+ try:
+ with open(key_file, "r") as f:
+ # read the API key from a file
+ try:
+ keys = json.loads(f.read())
+ # data seems to be in json format
+ # return the value of the item with the key 'Apikey'
+ api_key = keys.get("Apikey", "")
+ if not api_key:
+ # backward compatibility: former key name was 'apikey'
+ api_key = keys.get("apikey", "")
+ except ValueError:
+ # data is text, return as is
+ api_key = f.read().strip()
+ except FileNotFoundError:
+ logging.debug("Failed: Cannot open file {}".format(key_file))
+ return "TOKEN_IS_MISSING_OR_WRONG"
+ else:
+ api_key = options["--token"]
+ command = "identity/token"
+ action = "grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey={}".format(api_key)
+ res = send_command(conn, command, "POST", action, printResult=False)
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ return "TOKEN_IS_MISSING_OR_WRONG"
+ 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 options["--verbose-level"] > 1:
logging.debug(json.dumps(r, indent=2))
- outlets[r["pvmInstanceID"]] = (r["serverName"], state[r["status"]])
+ outlets[r["pvmInstanceID"]] = (r["serverName"], state.get(r["status"], "unknown"))
return outlets
def get_power_status(conn, options):
outlets = {}
logging.debug("Info: getting power status for LPAR " + options["--plug"] + " instance " + options["--instance"])
try:
command = "cloud-instances/{}/pvm-instances/{}".format(
options["--instance"], options["--plug"])
res = send_command(conn, command)
outlets[res["pvmInstanceID"]] = (res["serverName"], state[res["status"]])
if options["--verbose-level"] > 1:
logging.debug(json.dumps(res, indent=2))
result = outlets[options["--plug"]][1]
logging.debug("Info: Status: {}".format(result))
except KeyError as e:
try:
result = get_list(conn, options)[options["--plug"]][1]
except KeyError as ex:
logging.debug("Failed: Unable to get status for {}".format(ex))
fail(EC_STATUS)
return result
def set_power_status(conn, options):
action = {
"on" : '{"action" : "start"}',
"off" : '{"action" : "immediate-shutdown"}',
}[options["--action"]]
logging.debug("Info: set power status to " + options["--action"] + " for LPAR " + options["--plug"] + " instance " + options["--instance"])
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 reboot_cycle(conn, options):
action = {
"reboot" : '{"action" : "hard-reboot"}',
}[options["--action"]]
logging.debug("Info: start reboot cycle with action " + options["--action"] + " for LPAR " + options["--plug"] + " instance " + options["--instance"])
try:
send_command(conn, "cloud-instances/{}/pvm-instances/{}/action".format(
options["--instance"], options["--plug"]), "POST", action)
except Exception as e:
result = get_power_status(conn, options)
logging.debug("Info: Status {}".format(result))
if result == "off":
return True
else:
logging.debug("Failed: Unable to cycle with {} for {}".format(options["--action"], e))
fail(EC_STATUS)
- return True
+ return True
def connect(opt, token):
conn = pycurl.Curl()
## setup correct URL
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"] < 3:
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(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["--api-type"] == "private":
+ conn.base_url = "https://private.iam.cloud.ibm.com/"
+ else:
+ 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, printResult=True):
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:
logging.error("send_command(): {}".format(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))
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))
if printResult:
logging.debug("result: {}\n".format(result))
return result
def define_new_opts():
all_opt["token"] = {
"getopt" : ":",
"longopt" : "token",
"help" : "--token=[token] API Token",
"required" : "1",
"shortdesc" : "API 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
}
all_opt["api-type"] = {
"getopt" : ":",
"longopt" : "api-type",
"help" : "--api-type=[public|private] API-type: 'public' (default) or 'private'",
"required" : "0",
"shortdesc" : "API-type (public|private)",
"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():
device_opt = [
"token",
"crn",
"instance",
"region",
"api-type",
"proxy",
"port",
"no_password",
"method",
]
atexit.register(atexit_handler)
define_new_opts()
all_opt["shell_timeout"]["default"] = "500"
- all_opt["power_timeout"]["default"] = "30"
- all_opt["power_wait"]["default"] = "1"
- all_opt["stonith_status_sleep"]["default"] = "2"
+ all_opt["power_timeout"]["default"] = "120"
+ all_opt["power_wait"]["default"] = "15"
+ all_opt["stonith_status_sleep"]["default"] = "10"
all_opt["api-type"]["default"] = "private"
all_opt["proxy"]["default"] = ""
options = check_input(device_opt, process_input(device_opt))
docs = {}
docs["shortdesc"] = "Fence agent for IBM PowerVS"
- docs["longdesc"] = """fence_ibm_powervs is a Power Fencing agent which can be \
-used with IBM PowerVS to fence virtual machines."""
+ docs["longdesc"] = """fence_ibm_powervs is a fencing agent for \
+IBM Power Virtual Server (IBM PowerVS) to fence virtual server instances."""
docs["vendorurl"] = "https://www.ibm.com"
show_docs(options, docs)
####
## Fence operations
####
run_delay(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, reboot_cycle)
sys.exit(result)
if __name__ == "__main__":
main()
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Feb 24, 8:22 AM (22 h, 19 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464067
Default Alt Text
(10 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment