Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3156321
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/gce/fence_gce.py b/agents/gce/fence_gce.py
index 3abb5207..3af5bfc8 100644
--- a/agents/gce/fence_gce.py
+++ b/agents/gce/fence_gce.py
@@ -1,114 +1,173 @@
#!@PYTHON@ -tt
import atexit
+import logging
+import platform
import sys
+import time
sys.path.append("@FENCEAGENTSLIBDIR@")
import googleapiclient.discovery
from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action
+
+LOGGER = logging
+
+
def translate_status(instance_status):
"Returns on | off | unknown."
if instance_status == "RUNNING":
return "on"
elif instance_status == "TERMINATED":
return "off"
return "unknown"
def get_nodes_list(conn, options):
result = {}
try:
instanceList = conn.instances().list(project=options["--project"], zone=options["--zone"]).execute()
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)))
return result
+
def get_power_status(conn, options):
try:
instance = conn.instances().get(
project=options["--project"],
zone=options["--zone"],
instance=options["--plug"]).execute()
return translate_status(instance["status"])
except Exception as err:
fail_usage("Failed: get_power_status: {}".format(str(err)))
+def wait_for_operation(conn, project, zone, operation):
+ while True:
+ result = conn.zoneOperations().get(
+ project=project,
+ zone=zone,
+ operation=operation['name']).execute()
+ if result['status'] == 'DONE':
+ if 'error' in result:
+ raise Exception(result['error'])
+ return
+ time.sleep(1)
+
+
def set_power_status(conn, options):
try:
if options["--action"] == "off":
- conn.instances().stop(
+ LOGGER.info("Issuing poweroff of %s in zone %s" % (options["--plug"], options["--zone"]))
+ operation = conn.instances().stop(
project=options["--project"],
zone=options["--zone"],
instance=options["--plug"]).execute()
+ wait_for_operation(conn, options["--project"], options["--zone"], operation)
+ LOGGER.info("Poweroff of %s in zone %s complete" % (options["--plug"], options["--zone"]))
elif options["--action"] == "on":
- conn.instances().start(
+ LOGGER.info("Issuing poweron of %s in zone %s" % (options["--plug"], options["--zone"]))
+ operation = conn.instances().start(
project=options["--project"],
zone=options["--zone"],
instance=options["--plug"]).execute()
+ wait_for_operation(conn, options["--project"], options["--zone"], operation)
+ LOGGER.info("Poweron of %s in zone %s complete" % (options["--plug"], options["--zone"]))
except Exception as err:
fail_usage("Failed: set_power_status: {}".format(str(err)))
def define_new_opts():
all_opt["zone"] = {
"getopt" : ":",
"longopt" : "zone",
"help" : "--zone=[name] Zone, e.g. us-central1-b",
"shortdesc" : "Zone.",
"required" : "1",
"order" : 2
}
all_opt["project"] = {
"getopt" : ":",
"longopt" : "project",
"help" : "--project=[name] Project ID",
"shortdesc" : "Project ID.",
"required" : "1",
"order" : 3
}
+ all_opt["logging"] = {
+ "getopt" : ":",
+ "longopt" : "logging",
+ "help" : "--logging=[bool] Logging, true/false",
+ "shortdesc" : "Stackdriver-logging support.",
+ "longdesc" : "If enabled (set to true), IP failover logs will be posted to stackdriver logging.",
+ "required" : "0",
+ "default" : "false",
+ "order" : 4
+ }
def main():
conn = None
+ global LOGGER
+
+ hostname = platform.node()
- device_opt = ["port", "no_password", "zone", "project"]
+ device_opt = ["port", "no_password", "zone", "project", "logging"]
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)
+ # Prepare logging
+ logging_env = options.get('--logging')
+ if logging_env:
+ logging_env = logging_env.lower()
+ if any(x in logging_env for x in ['yes', 'true', 'enabled']):
+ try:
+ import google.cloud.logging.handlers
+ client = google.cloud.logging.Client()
+ handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname)
+ formatter = logging.Formatter('gcp:stonish "%(message)s"')
+ LOGGER = logging.getLogger(hostname)
+ handler.setFormatter(formatter)
+ LOGGER.addHandler(handler)
+ LOGGER.setLevel(logging.INFO)
+ except ImportError:
+ LOGGER.error('Couldn\'t import google.cloud.logging, '
+ 'disabling Stackdriver-logging support')
+
+ # Prepare cli
try:
credentials = None
if tuple(googleapiclient.__version__) < tuple("1.6.0"):
import oauth2client.client
credentials = oauth2client.client.GoogleCredentials.get_application_default()
conn = googleapiclient.discovery.build('compute', 'v1', credentials=credentials)
except Exception as err:
fail_usage("Failed: Create GCE compute v1 connection: {}".format(str(err)))
# 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()
diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml
index 2a147f21..805ecc6b 100644
--- a/tests/data/metadata/fence_gce.xml
+++ b/tests/data/metadata/fence_gce.xml
@@ -1,111 +1,116 @@
<?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="1">
<getopt mixed="--zone=[name]" />
<content type="string" />
<shortdesc lang="en">Zone.</shortdesc>
</parameter>
<parameter name="project" unique="0" required="1">
<getopt mixed="--project=[name]" />
<content type="string" />
<shortdesc lang="en">Project ID.</shortdesc>
</parameter>
+ <parameter name="logging" unique="0" required="0">
+ <getopt mixed="--logging=[bool]" />
+ <content type="string" default="false" />
+ <shortdesc lang="en">Stackdriver-logging support.</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="manpage" />
<action name="validate-all" />
</actions>
</resource-agent>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Feb 27, 5:36 AM (1 d, 19 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1466214
Default Alt Text
(10 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment