From 8beee3c3d832b320df9bcf7345e535ceffe6ef0e Mon Sep 17 00:00:00 2001 From: Cymen Vig Date: Sun, 6 May 2018 20:13:00 +0000 Subject: [PATCH 1/6] Add fence agent for OVH Cloud (REST API) --- agents/ovh_cloud_rest/fence_ovh_cloud_rest.py | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 agents/ovh_cloud_rest/fence_ovh_cloud_rest.py diff --git a/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py b/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py new file mode 100644 index 000000000..7e1f0f5df --- /dev/null +++ b/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py @@ -0,0 +1,124 @@ +#!@PYTHON@ -tt + +import sys +import time +import atexit +sys.path.append("@FENCEAGENTSLIBDIR@") +from fencing import * +from fencing import fail_usage, run_command, run_delay +import ovh + +POLL_INTERVAL_SECONDS = 1 + +def define_new_opts(): + all_opt["application_key"] = { + "getopt" : "k:", + "longopt" : "application-key", + "help" : "-k, --application-key=[application-key] OVH Oauth application key", + "required" : "1", + "shortdesc" : "OVH Oauth application key", + "order" : 1} + all_opt["application_secret"] = { + "getopt" : "s:", + "longopt" : "application-secret", + "help" : "-s, --application-secret=[application-secret] OVH Oauth application secret", + "required" : "1", + "shortdesc" : "OVH Oauth application secret", + "order" : 2} + all_opt["token"] = { + "getopt" : "t:", + "longopt" : "token", + "help" : "-t, --token=[token] OVH Oauth token ", + "required" : "1", + "shortdesc" : "OVH Oauth token ", + "order" : 3} + all_opt["region"] = { + "getopt" : "r:", + "longopt" : "region", + "help" : "-r, --region=[region] OVH region (example: ovh-ca)", + "required" : "1", + "shortdesc" : "OVH region", + "order" : 4} + all_opt["service_name"] = { + "getopt" : "n:", + "longopt" : "service-name", + "help" : "-n, --service-name=[service-name] OVH service name", + "required" : "1", + "shortdesc" : "OVH service name", + "order" : 5} + all_opt["instance_id"] = { + "getopt" : "i:", + "longopt" : "instance-id", + "help" : "-i, --instance-id=[instance-id] OVH instance id", + "required" : "1", + "shortdesc" : "OVH service name", + "order" : 6} + +def ovh_login(options): + session = ovh.Client( + endpoint=options["--region"], + application_key=options["--application-key"], + application_secret=options["--application-secret"], + consumer_key=options["--token"], + ) + options["session"] = session; + return session; + +def status(options, expected_status): + session = options["session"] + status_url = "/cloud/project/%s/instance/%s" % (options['--service-name'], options['--instance-id']) + response = session.get(status_url) + return True if response["status"] == expected_status else False + +def main(): + atexit.register(atexit_handler) + + device_opt = ["application_key", "application_secret", "token", "region", "service_name", "instance_id", "no_password"] + + define_new_opts() + options = check_input(device_opt, process_input(device_opt), other_conditions=True) + + docs = {} + docs["shortdesc"] = "Fence agent for OVH Cloud (REST API)" + docs["longdesc"] = "Fence agent for OVH Cloud (REST API) with authentication via Oauth" + docs["vendorurl"] = "https://api.ovh.com/" + show_docs(options, docs) + + run_delay(options) + + session = ovh_login(options); + + if options["--action"] == "off": + try: + url = "/cloud/project/%s/instance/%s/rescueMode" % (options['--service-name'], options['--instance-id']) + response = session.post(url, rescue=True) + if response["adminPassword"] != None: + result = 1 + while not status(options, "RESCUE"): + time.sleep(POLL_INTERVAL_SECONDS) + except ovh.exceptions.BadParametersError as exception: + print(exception) + result = 0 + except Exception as exception: + print(exception) + result = 0 + + if options["--action"] == "on": + try: + url = "/cloud/project/%s/instance/%s/rescueMode" % (options['--service-name'], options['--instance-id']) + response = session.post(url, rescue=False) + if response["adminPassword"] == None: + result = 1 + while not status(options, "ACTIVE"): + time.sleep(POLL_INTERVAL_SECONDS) + except ovh.exceptions.BadParametersError as exception: + print(exception) + result = 0 + except Exception as exception: + print(exception) + result = 0 + + sys.exit(result) + +if __name__ == "__main__": + main() From c388b1cd2d132b0384baa41eb7d24a52966c84e8 Mon Sep 17 00:00:00 2001 From: Cymen Vig Date: Sun, 6 May 2018 20:22:48 +0000 Subject: [PATCH 2/6] remove duplicate exception handler --- agents/ovh_cloud_rest/fence_ovh_cloud_rest.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py b/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py index 7e1f0f5df..c8e17fec3 100644 --- a/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py +++ b/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py @@ -96,9 +96,6 @@ def main(): result = 1 while not status(options, "RESCUE"): time.sleep(POLL_INTERVAL_SECONDS) - except ovh.exceptions.BadParametersError as exception: - print(exception) - result = 0 except Exception as exception: print(exception) result = 0 @@ -111,9 +108,6 @@ def main(): result = 1 while not status(options, "ACTIVE"): time.sleep(POLL_INTERVAL_SECONDS) - except ovh.exceptions.BadParametersError as exception: - print(exception) - result = 0 except Exception as exception: print(exception) result = 0 From 9d49547cddbb0f56c1f2352b0bdc6dc328726170 Mon Sep 17 00:00:00 2001 From: Cymen Vig Date: Sun, 6 May 2018 20:23:24 +0000 Subject: [PATCH 3/6] share rescue_url --- agents/ovh_cloud_rest/fence_ovh_cloud_rest.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py b/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py index c8e17fec3..aa39aadb3 100644 --- a/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py +++ b/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py @@ -88,10 +88,11 @@ def main(): session = ovh_login(options); + rescue_url = "/cloud/project/%s/instance/%s/rescueMode" % (options['--service-name'], options['--instance-id']) + if options["--action"] == "off": try: - url = "/cloud/project/%s/instance/%s/rescueMode" % (options['--service-name'], options['--instance-id']) - response = session.post(url, rescue=True) + response = session.post(rescue_url, rescue=True) if response["adminPassword"] != None: result = 1 while not status(options, "RESCUE"): @@ -102,8 +103,7 @@ def main(): if options["--action"] == "on": try: - url = "/cloud/project/%s/instance/%s/rescueMode" % (options['--service-name'], options['--instance-id']) - response = session.post(url, rescue=False) + response = session.post(rescue_url, rescue=False) if response["adminPassword"] == None: result = 1 while not status(options, "ACTIVE"): From 4e9d45f91e8f55be214816bc86b80fab2fccf951 Mon Sep 17 00:00:00 2001 From: Cymen Vig Date: Sun, 6 May 2018 20:36:56 +0000 Subject: [PATCH 4/6] update CI to install ovh (pip) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 6aa799eb8..d07fff77d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ before_install: - pip install pexpect - pip install boto3 - pip install google-api-python-client + - pip install ovh before_script: - wget https://github.com/Openwsman/openwsman/archive/v2.6.3.tar.gz From 3b704901cb3e99d578aca4ca99642343fa6ff50f Mon Sep 17 00:00:00 2001 From: Cymen Vig Date: Sun, 6 May 2018 20:55:05 +0000 Subject: [PATCH 5/6] add metadata file for fence_ovh_cloud_rest --- tests/data/metadata/fence_ovh_cloud_rest.xml | 112 +++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 tests/data/metadata/fence_ovh_cloud_rest.xml diff --git a/tests/data/metadata/fence_ovh_cloud_rest.xml b/tests/data/metadata/fence_ovh_cloud_rest.xml new file mode 100644 index 000000000..922142a9f --- /dev/null +++ b/tests/data/metadata/fence_ovh_cloud_rest.xml @@ -0,0 +1,112 @@ + + +Fence agent for OVH Cloud (REST API) with authentication via Oauth +https://api.ovh.com/ + + + + + Fencing action + + + + + OVH Oauth application key + + + + + OVH Oauth application secret + + + + + OVH Oauth token + + + + + OVH region + + + + + OVH service name + + + + + OVH service name + + + + + Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. + + + + + Verbose mode + + + + + Write debug information to given file + + + + + Write debug information to given file + + + + + Display version information and exit + + + + + Display help and exit + + + + + Wait X seconds before fencing is started + + + + + Wait X seconds for cmd prompt after login + + + + + Test X seconds for status change after ON/OFF + + + + + Wait X seconds after issuing ON/OFF + + + + + Wait X seconds for cmd prompt after issuing command + + + + + Count of attempts to retry power on + + + + + + + + + + + + + From a94b269946182b85e9d8d271e79a47a38f89fb8d Mon Sep 17 00:00:00 2001 From: Cymen Vig Date: Mon, 7 May 2018 02:22:09 +0000 Subject: [PATCH 6/6] move obh import above fencing imports --- agents/ovh_cloud_rest/fence_ovh_cloud_rest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py b/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py index aa39aadb3..63c0bc730 100644 --- a/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py +++ b/agents/ovh_cloud_rest/fence_ovh_cloud_rest.py @@ -3,10 +3,11 @@ import sys import time import atexit +import ovh sys.path.append("@FENCEAGENTSLIBDIR@") +sys.path.append("/root/fence-agents/lib") from fencing import * from fencing import fail_usage, run_command, run_delay -import ovh POLL_INTERVAL_SECONDS = 1