File 0001-fence_gce-new-agent.patch of Package fence-agents.10129
From cab1e1b5fcf119b34f96829f5c618191b02cbc3e Mon Sep 17 00:00:00 2001
From: Helen Koike <helen.koike@collabora.com>
Date: Sat, 18 Nov 2017 17:10:24 -0200
Subject: [PATCH] fence_gce: new agent
First implementation of GCE agent
---
.travis.yml | 1 +
configure.ac | 3 ++
fence/agents/gce/fence_gce.py | 110 ++++++++++++++++++++++++++++++++++++++
tests/data/metadata/fence_gce.xml | 110 ++++++++++++++++++++++++++++++++++++++
4 files changed, 224 insertions(+)
create mode 100644 fence/agents/gce/fence_gce.py
create mode 100644 tests/data/metadata/fence_gce.xml
Index: fence-agents-4.0.17/configure.ac
===================================================================
--- fence-agents-4.0.17.orig/configure.ac
+++ fence-agents-4.0.17/configure.ac
@@ -158,6 +158,10 @@ AC_PYTHON_MODULE(pexpect, 1)
AC_PYTHON_MODULE(pycurl, 1)
AC_PYTHON_MODULE(requests, 1)
+if echo "$AGENTS_LIST" | grep -q gce; then
+ AC_PYTHON_MODULE(googleapiclient, 1)
+fi
+
## path to 3rd-party binaries
AC_PATH_PROG([IPMITOOL_PATH], [ipmitool], [/usr/bin/ipmitool])
AC_PATH_PROG([AMTTOOL_PATH], [amttool], [/usr/bin/amttool])
Index: fence-agents-4.0.17/fence/agents/gce/fence_gce.py
===================================================================
--- /dev/null
+++ fence-agents-4.0.17/fence/agents/gce/fence_gce.py
@@ -0,0 +1,110 @@
+#!@PYTHON@ -tt
+
+import atexit
+import sys
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from googleapiclient import discovery
+from oauth2client.client import GoogleCredentials
+
+from fencing import *
+from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay
+
+
+def get_nodes_list(conn, options):
+ result = {}
+ try:
+ instanceList = conn.instances().list(project=options["--project"], zone=options["--zone"]).execute()
+ for instance in instanceList["items"]:
+ status = "unknown"
+ if instance["status"] == "RUNNING":
+ status = "on"
+ elif instance["status"] == "TERMINATED":
+ status = "off"
+ result[instance["id"]] = (instance["name"], status)
+ # TODO: check which Exceptions it can throw
+ except:
+ fail_usage("Failed: Unable to connect to GCE. Check your configuration.")
+
+ return result
+
+def get_power_status(conn, options):
+ try:
+ instance = conn.instances().get(project=options["--project"], zone=options["--zone"],
+ instance=options["--plug"]).execute()
+ if instance["status"] == "RUNNING":
+ return "on"
+ elif instance["status"] == "TERMINATED":
+ return "off"
+ else:
+ return "unknown"
+ # TODO: check which Exceptions it can throw
+ except:
+ fail_usage("Failed: Unable to connect to GCE. Check your configuration.")
+
+def set_power_status(conn, options):
+ try:
+ if (options["--action"]=="off"):
+ conn.instances().stop(project=options["--project"], zone=options["--zone"],
+ instance=options["--plug"]).execute()
+ elif (options["--action"]=="on"):
+ conn.instances().start(project=options["--project"], zone=options["--zone"],
+ instance=options["--plug"]).execute()
+ # TODO: check which Exceptions it can throw
+ except :
+ fail_usage("Failed: Unable to connect to GCE. Check your configuration.")
+
+def define_new_opts():
+ all_opt["zone"] = {
+ "getopt" : ":",
+ "longopt" : "zone",
+ "help" : "--zone=[name] Zone, e.g. us-central1-b",
+ "shortdesc" : "Zone.",
+ "required" : "0",
+ "order" : 2
+ }
+ all_opt["project"] = {
+ "getopt" : ":",
+ "longopt" : "project",
+ "help" : "--project=[name] Project",
+ "shortdesc" : "Project.",
+ "required" : "0",
+ "order" : 3
+ }
+
+def main():
+ conn = None
+
+ device_opt = ["port", "no_password", "zone", "project"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["power_timeout"]["default"] = "60"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for GCE (Google Cloud Engine)"
+ docs["longdesc"] = "fence_gce is an I/O Fencing agent for GCE (Google Cloud " \
+ "Engine). It uses the googleapiclient library to connect to GCE.\n" \
+ "googleapiclient can be configured with Google SDK CLI or by " \
+ "executing 'gcloud auth application-default login'.\n" \
+ "For instructions see: https://cloud.google.com/compute/docs/tutorials/python-guide"
+ docs["vendorurl"] = "http://cloud.google.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ try:
+ credentials = GoogleCredentials.get_application_default()
+ conn = discovery.build('compute', 'v1', credentials=credentials)
+ except:
+ fail_usage("Failed: Unable to connect to GCE. Check your configuration.")
+
+ # Operate the fencing device
+ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
Index: fence-agents-4.0.17/tests/data/metadata/fence_gce.xml
===================================================================
--- /dev/null
+++ fence-agents-4.0.17/tests/data/metadata/fence_gce.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_gce" shortdesc="Fence agent for GCE (Google Cloud Engine)" >
+<longdesc>fence_gce is an I/O Fencing agent for GCE (Google Cloud Engine). It uses the googleapiclient library to connect to GCE.
+googleapiclient can be configured with Google SDK CLI or by executing 'gcloud auth application-default login'.
+For instructions see: https://cloud.google.com/compute/docs/tutorials/python-guide</longdesc>
+<vendor-url>http://cloud.google.com</vendor-url>
+<parameters>
+ <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="zone" unique="0" required="0">
+ <getopt mixed="--zone=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Zone.</shortdesc>
+ </parameter>
+ <parameter name="project" unique="0" required="0">
+ <getopt mixed="--project=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Project.</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</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="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="60" />
+ <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="0" />
+ <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="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</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="validate-all" />
+</actions>
+</resource-agent>