|
|
674a4f |
From 59ae9d00060da5329d7ca538974498292bbe1d91 Mon Sep 17 00:00:00 2001
|
|
|
674a4f |
From: Helen Koike <helen.koike@collabora.com>
|
|
|
674a4f |
Date: Tue, 26 Jun 2018 10:18:29 -0300
|
|
|
674a4f |
Subject: [PATCH 1/7] fence_gce: add support for stackdriver logging
|
|
|
674a4f |
|
|
|
674a4f |
Add --logging option to enable sending logs to google stackdriver
|
|
|
674a4f |
---
|
|
|
674a4f |
agents/gce/fence_gce.py | 65 +++++++++++++++++++++++++++++++++++++--
|
|
|
674a4f |
tests/data/metadata/fence_gce.xml | 5 +++
|
|
|
674a4f |
2 files changed, 67 insertions(+), 3 deletions(-)
|
|
|
674a4f |
|
|
|
674a4f |
diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py
|
|
|
674a4f |
index 3abb5207..3af5bfc8 100644
|
|
|
674a4f |
--- a/agents/gce/fence_gce.py
|
|
|
674a4f |
+++ b/agents/gce/fence_gce.py
|
|
|
674a4f |
@@ -1,12 +1,19 @@
|
|
|
674a4f |
#!@PYTHON@ -tt
|
|
|
674a4f |
|
|
|
674a4f |
import atexit
|
|
|
674a4f |
+import logging
|
|
|
674a4f |
+import platform
|
|
|
674a4f |
import sys
|
|
|
674a4f |
+import time
|
|
|
674a4f |
sys.path.append("@FENCEAGENTSLIBDIR@")
|
|
|
674a4f |
|
|
|
674a4f |
import googleapiclient.discovery
|
|
|
674a4f |
from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action
|
|
|
674a4f |
|
|
|
674a4f |
+
|
|
|
674a4f |
+LOGGER = logging
|
|
|
674a4f |
+
|
|
|
674a4f |
+
|
|
|
674a4f |
def translate_status(instance_status):
|
|
|
674a4f |
"Returns on | off | unknown."
|
|
|
674a4f |
if instance_status == "RUNNING":
|
|
|
674a4f |
@@ -27,6 +34,7 @@ def get_nodes_list(conn, options):
|
|
|
674a4f |
|
|
|
674a4f |
return result
|
|
|
674a4f |
|
|
|
674a4f |
+
|
|
|
674a4f |
def get_power_status(conn, options):
|
|
|
674a4f |
try:
|
|
|
674a4f |
instance = conn.instances().get(
|
|
|
674a4f |
@@ -38,18 +46,37 @@ def get_power_status(conn, options):
|
|
|
674a4f |
fail_usage("Failed: get_power_status: {}".format(str(err)))
|
|
|
674a4f |
|
|
|
674a4f |
|
|
|
674a4f |
+def wait_for_operation(conn, project, zone, operation):
|
|
|
674a4f |
+ while True:
|
|
|
674a4f |
+ result = conn.zoneOperations().get(
|
|
|
674a4f |
+ project=project,
|
|
|
674a4f |
+ zone=zone,
|
|
|
674a4f |
+ operation=operation['name']).execute()
|
|
|
674a4f |
+ if result['status'] == 'DONE':
|
|
|
674a4f |
+ if 'error' in result:
|
|
|
674a4f |
+ raise Exception(result['error'])
|
|
|
674a4f |
+ return
|
|
|
674a4f |
+ time.sleep(1)
|
|
|
674a4f |
+
|
|
|
674a4f |
+
|
|
|
674a4f |
def set_power_status(conn, options):
|
|
|
674a4f |
try:
|
|
|
674a4f |
if options["--action"] == "off":
|
|
|
674a4f |
- conn.instances().stop(
|
|
|
674a4f |
+ LOGGER.info("Issuing poweroff of %s in zone %s" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ operation = conn.instances().stop(
|
|
|
674a4f |
project=options["--project"],
|
|
|
674a4f |
zone=options["--zone"],
|
|
|
674a4f |
instance=options["--plug"]).execute()
|
|
|
674a4f |
+ wait_for_operation(conn, options["--project"], options["--zone"], operation)
|
|
|
674a4f |
+ LOGGER.info("Poweroff of %s in zone %s complete" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
elif options["--action"] == "on":
|
|
|
674a4f |
- conn.instances().start(
|
|
|
674a4f |
+ LOGGER.info("Issuing poweron of %s in zone %s" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ operation = conn.instances().start(
|
|
|
674a4f |
project=options["--project"],
|
|
|
674a4f |
zone=options["--zone"],
|
|
|
674a4f |
instance=options["--plug"]).execute()
|
|
|
674a4f |
+ wait_for_operation(conn, options["--project"], options["--zone"], operation)
|
|
|
674a4f |
+ LOGGER.info("Poweron of %s in zone %s complete" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
except Exception as err:
|
|
|
674a4f |
fail_usage("Failed: set_power_status: {}".format(str(err)))
|
|
|
674a4f |
|
|
|
674a4f |
@@ -71,11 +98,24 @@ def define_new_opts():
|
|
|
674a4f |
"required" : "1",
|
|
|
674a4f |
"order" : 3
|
|
|
674a4f |
}
|
|
|
674a4f |
+ all_opt["logging"] = {
|
|
|
674a4f |
+ "getopt" : ":",
|
|
|
674a4f |
+ "longopt" : "logging",
|
|
|
674a4f |
+ "help" : "--logging=[bool] Logging, true/false",
|
|
|
674a4f |
+ "shortdesc" : "Stackdriver-logging support.",
|
|
|
674a4f |
+ "longdesc" : "If enabled (set to true), IP failover logs will be posted to stackdriver logging.",
|
|
|
674a4f |
+ "required" : "0",
|
|
|
674a4f |
+ "default" : "false",
|
|
|
674a4f |
+ "order" : 4
|
|
|
674a4f |
+ }
|
|
|
674a4f |
|
|
|
674a4f |
def main():
|
|
|
674a4f |
conn = None
|
|
|
674a4f |
+ global LOGGER
|
|
|
674a4f |
+
|
|
|
674a4f |
+ hostname = platform.node()
|
|
|
674a4f |
|
|
|
674a4f |
- device_opt = ["port", "no_password", "zone", "project"]
|
|
|
674a4f |
+ device_opt = ["port", "no_password", "zone", "project", "logging"]
|
|
|
674a4f |
|
|
|
674a4f |
atexit.register(atexit_handler)
|
|
|
674a4f |
|
|
|
674a4f |
@@ -97,6 +137,25 @@ def main():
|
|
|
674a4f |
|
|
|
674a4f |
run_delay(options)
|
|
|
674a4f |
|
|
|
674a4f |
+ # Prepare logging
|
|
|
674a4f |
+ logging_env = options.get('--logging')
|
|
|
674a4f |
+ if logging_env:
|
|
|
674a4f |
+ logging_env = logging_env.lower()
|
|
|
674a4f |
+ if any(x in logging_env for x in ['yes', 'true', 'enabled']):
|
|
|
674a4f |
+ try:
|
|
|
674a4f |
+ import google.cloud.logging.handlers
|
|
|
674a4f |
+ client = google.cloud.logging.Client()
|
|
|
674a4f |
+ handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname)
|
|
|
674a4f |
+ formatter = logging.Formatter('gcp:stonish "%(message)s"')
|
|
|
674a4f |
+ LOGGER = logging.getLogger(hostname)
|
|
|
674a4f |
+ handler.setFormatter(formatter)
|
|
|
674a4f |
+ LOGGER.addHandler(handler)
|
|
|
674a4f |
+ LOGGER.setLevel(logging.INFO)
|
|
|
674a4f |
+ except ImportError:
|
|
|
674a4f |
+ LOGGER.error('Couldn\'t import google.cloud.logging, '
|
|
|
674a4f |
+ 'disabling Stackdriver-logging support')
|
|
|
674a4f |
+
|
|
|
674a4f |
+ # Prepare cli
|
|
|
674a4f |
try:
|
|
|
674a4f |
credentials = None
|
|
|
674a4f |
if tuple(googleapiclient.__version__) < tuple("1.6.0"):
|
|
|
674a4f |
diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
index 2a147f21..805ecc6b 100644
|
|
|
674a4f |
--- a/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
+++ b/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
@@ -30,6 +30,11 @@ For instructions see: https://cloud.google.com/compute/docs/tutorials/python-gui
|
|
|
674a4f |
<content type="string" />
|
|
|
674a4f |
<shortdesc lang="en">Project ID.</shortdesc>
|
|
|
674a4f |
</parameter>
|
|
|
674a4f |
+ <parameter name="logging" unique="0" required="0">
|
|
|
674a4f |
+ <getopt mixed="--logging=[bool]" />
|
|
|
674a4f |
+ <content type="string" default="false" />
|
|
|
674a4f |
+ <shortdesc lang="en">Stackdriver-logging support.</shortdesc>
|
|
|
674a4f |
+ </parameter>
|
|
|
674a4f |
<parameter name="quiet" unique="0" required="0">
|
|
|
674a4f |
<getopt mixed="-q, --quiet" />
|
|
|
674a4f |
<content type="boolean" />
|
|
|
674a4f |
|
|
|
674a4f |
From bb34acd8b0b150599c393d56dd81a7d8185b27d3 Mon Sep 17 00:00:00 2001
|
|
|
674a4f |
From: Helen Koike <helen.koike@collabora.com>
|
|
|
674a4f |
Date: Tue, 26 Jun 2018 10:44:41 -0300
|
|
|
674a4f |
Subject: [PATCH 2/7] fence_gce: set project and zone as not required
|
|
|
674a4f |
|
|
|
674a4f |
Try to retrieve the GCE project if the script is being executed inside a
|
|
|
674a4f |
GCE machine if --project is not provided.
|
|
|
674a4f |
Try to retrieve the zone automatically from GCE if --zone is not
|
|
|
674a4f |
provided.
|
|
|
674a4f |
---
|
|
|
674a4f |
agents/gce/fence_gce.py | 63 +++++++++++++++++++++++++++++++++++++--
|
|
|
674a4f |
tests/data/metadata/fence_gce.xml | 4 +--
|
|
|
674a4f |
2 files changed, 63 insertions(+), 4 deletions(-)
|
|
|
674a4f |
|
|
|
674a4f |
diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py
|
|
|
674a4f |
index 3af5bfc8..e53dc5a6 100644
|
|
|
674a4f |
--- a/agents/gce/fence_gce.py
|
|
|
674a4f |
+++ b/agents/gce/fence_gce.py
|
|
|
674a4f |
@@ -12,6 +12,8 @@
|
|
|
674a4f |
|
|
|
674a4f |
|
|
|
674a4f |
LOGGER = logging
|
|
|
674a4f |
+METADATA_SERVER = 'http://metadata.google.internal/computeMetadata/v1/'
|
|
|
674a4f |
+METADATA_HEADERS = {'Metadata-Flavor': 'Google'}
|
|
|
674a4f |
|
|
|
674a4f |
|
|
|
674a4f |
def translate_status(instance_status):
|
|
|
674a4f |
@@ -81,13 +83,56 @@ def set_power_status(conn, options):
|
|
|
674a4f |
fail_usage("Failed: set_power_status: {}".format(str(err)))
|
|
|
674a4f |
|
|
|
674a4f |
|
|
|
674a4f |
+def get_instance(conn, project, zone, instance):
|
|
|
674a4f |
+ request = conn.instances().get(
|
|
|
674a4f |
+ project=project, zone=zone, instance=instance)
|
|
|
674a4f |
+ return request.execute()
|
|
|
674a4f |
+
|
|
|
674a4f |
+
|
|
|
674a4f |
+def get_zone(conn, project, instance):
|
|
|
674a4f |
+ request = conn.instances().aggregatedList(project=project)
|
|
|
674a4f |
+ while request is not None:
|
|
|
674a4f |
+ response = request.execute()
|
|
|
674a4f |
+ zones = response.get('items', {})
|
|
|
674a4f |
+ for zone in zones.values():
|
|
|
674a4f |
+ for inst in zone.get('instances', []):
|
|
|
674a4f |
+ if inst['name'] == instance:
|
|
|
674a4f |
+ return inst['zone'].split("/")[-1]
|
|
|
674a4f |
+ request = conn.instances().aggregatedList_next(
|
|
|
674a4f |
+ previous_request=request, previous_response=response)
|
|
|
674a4f |
+ raise Exception("Unable to find instance %s" % (instance))
|
|
|
674a4f |
+
|
|
|
674a4f |
+
|
|
|
674a4f |
+def get_metadata(metadata_key, params=None, timeout=None):
|
|
|
674a4f |
+ """Performs a GET request with the metadata headers.
|
|
|
674a4f |
+
|
|
|
674a4f |
+ Args:
|
|
|
674a4f |
+ metadata_key: string, the metadata to perform a GET request on.
|
|
|
674a4f |
+ params: dictionary, the query parameters in the GET request.
|
|
|
674a4f |
+ timeout: int, timeout in seconds for metadata requests.
|
|
|
674a4f |
+
|
|
|
674a4f |
+ Returns:
|
|
|
674a4f |
+ HTTP response from the GET request.
|
|
|
674a4f |
+
|
|
|
674a4f |
+ Raises:
|
|
|
674a4f |
+ urlerror.HTTPError: raises when the GET request fails.
|
|
|
674a4f |
+ """
|
|
|
674a4f |
+ timeout = timeout or 60
|
|
|
674a4f |
+ metadata_url = os.path.join(METADATA_SERVER, metadata_key)
|
|
|
674a4f |
+ params = urlparse.urlencode(params or {})
|
|
|
674a4f |
+ url = '%s?%s' % (metadata_url, params)
|
|
|
674a4f |
+ request = urlrequest.Request(url, headers=METADATA_HEADERS)
|
|
|
674a4f |
+ request_opener = urlrequest.build_opener(urlrequest.ProxyHandler({}))
|
|
|
674a4f |
+ return request_opener.open(request, timeout=timeout * 1.1).read()
|
|
|
674a4f |
+
|
|
|
674a4f |
+
|
|
|
674a4f |
def define_new_opts():
|
|
|
674a4f |
all_opt["zone"] = {
|
|
|
674a4f |
"getopt" : ":",
|
|
|
674a4f |
"longopt" : "zone",
|
|
|
674a4f |
"help" : "--zone=[name] Zone, e.g. us-central1-b",
|
|
|
674a4f |
"shortdesc" : "Zone.",
|
|
|
674a4f |
- "required" : "1",
|
|
|
674a4f |
+ "required" : "0",
|
|
|
674a4f |
"order" : 2
|
|
|
674a4f |
}
|
|
|
674a4f |
all_opt["project"] = {
|
|
|
674a4f |
@@ -95,7 +140,7 @@ def define_new_opts():
|
|
|
674a4f |
"longopt" : "project",
|
|
|
674a4f |
"help" : "--project=[name] Project ID",
|
|
|
674a4f |
"shortdesc" : "Project ID.",
|
|
|
674a4f |
- "required" : "1",
|
|
|
674a4f |
+ "required" : "0",
|
|
|
674a4f |
"order" : 3
|
|
|
674a4f |
}
|
|
|
674a4f |
all_opt["logging"] = {
|
|
|
674a4f |
@@ -109,6 +154,7 @@ def define_new_opts():
|
|
|
674a4f |
"order" : 4
|
|
|
674a4f |
}
|
|
|
674a4f |
|
|
|
674a4f |
+
|
|
|
674a4f |
def main():
|
|
|
674a4f |
conn = None
|
|
|
674a4f |
global LOGGER
|
|
|
674a4f |
@@ -165,6 +211,19 @@ def main():
|
|
|
674a4f |
except Exception as err:
|
|
|
674a4f |
fail_usage("Failed: Create GCE compute v1 connection: {}".format(str(err)))
|
|
|
674a4f |
|
|
|
674a4f |
+ # Get project and zone
|
|
|
674a4f |
+ if not options.get("--project"):
|
|
|
674a4f |
+ try:
|
|
|
674a4f |
+ options["--project"] = get_metadata('project/project-id')
|
|
|
674a4f |
+ except Exception as err:
|
|
|
674a4f |
+ fail_usage("Failed retrieving GCE project. Please provide --project option: {}".format(str(err)))
|
|
|
674a4f |
+
|
|
|
674a4f |
+ if not options.get("--zone"):
|
|
|
674a4f |
+ try:
|
|
|
674a4f |
+ options["--zone"] = get_zone(conn, options['--project'], options['--plug'])
|
|
|
674a4f |
+ except Exception as err:
|
|
|
674a4f |
+ fail_usage("Failed retrieving GCE zone. Please provide --zone option: {}".format(str(err)))
|
|
|
674a4f |
+
|
|
|
674a4f |
# Operate the fencing device
|
|
|
674a4f |
result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list)
|
|
|
674a4f |
sys.exit(result)
|
|
|
674a4f |
diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
index 805ecc6b..507b8385 100644
|
|
|
674a4f |
--- a/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
+++ b/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
@@ -20,12 +20,12 @@ For instructions see: https://cloud.google.com/compute/docs/tutorials/python-gui
|
|
|
674a4f |
<content type="string" />
|
|
|
674a4f |
<shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
|
|
|
674a4f |
</parameter>
|
|
|
674a4f |
- <parameter name="zone" unique="0" required="1">
|
|
|
674a4f |
+ <parameter name="zone" unique="0" required="0">
|
|
|
674a4f |
<getopt mixed="--zone=[name]" />
|
|
|
674a4f |
<content type="string" />
|
|
|
674a4f |
<shortdesc lang="en">Zone.</shortdesc>
|
|
|
674a4f |
</parameter>
|
|
|
674a4f |
- <parameter name="project" unique="0" required="1">
|
|
|
674a4f |
+ <parameter name="project" unique="0" required="0">
|
|
|
674a4f |
<getopt mixed="--project=[name]" />
|
|
|
674a4f |
<content type="string" />
|
|
|
674a4f |
<shortdesc lang="en">Project ID.</shortdesc>
|
|
|
674a4f |
|
|
|
674a4f |
From 8ae1af8068d1718a861a25bf954e14392384fa55 Mon Sep 17 00:00:00 2001
|
|
|
674a4f |
From: Helen Koike <helen.koike@collabora.com>
|
|
|
674a4f |
Date: Wed, 4 Jul 2018 09:25:46 -0300
|
|
|
674a4f |
Subject: [PATCH 3/7] fence_gce: add power cycle as default method
|
|
|
674a4f |
|
|
|
674a4f |
Add function to power cycle an instance and set cycle as the default
|
|
|
674a4f |
method to reboot.
|
|
|
674a4f |
---
|
|
|
674a4f |
agents/gce/fence_gce.py | 21 +++++++++++++++++++--
|
|
|
674a4f |
tests/data/metadata/fence_gce.xml | 8 ++++++++
|
|
|
674a4f |
2 files changed, 27 insertions(+), 2 deletions(-)
|
|
|
674a4f |
|
|
|
674a4f |
diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py
|
|
|
674a4f |
index e53dc5a6..3f77dc24 100644
|
|
|
674a4f |
--- a/agents/gce/fence_gce.py
|
|
|
674a4f |
+++ b/agents/gce/fence_gce.py
|
|
|
674a4f |
@@ -83,6 +83,21 @@ def set_power_status(conn, options):
|
|
|
674a4f |
fail_usage("Failed: set_power_status: {}".format(str(err)))
|
|
|
674a4f |
|
|
|
674a4f |
|
|
|
674a4f |
+def power_cycle(conn, options):
|
|
|
674a4f |
+ try:
|
|
|
674a4f |
+ LOGGER.info('Issuing reset of %s in zone %s' % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ operation = conn.instances().reset(
|
|
|
674a4f |
+ project=options["--project"],
|
|
|
674a4f |
+ zone=options["--zone"],
|
|
|
674a4f |
+ instance=options["--plug"]).execute()
|
|
|
674a4f |
+ wait_for_operation(conn, options["--project"], options["--zone"], operation)
|
|
|
674a4f |
+ LOGGER.info('Reset of %s in zone %s complete' % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ return True
|
|
|
674a4f |
+ except Exception as err:
|
|
|
674a4f |
+ LOGGER.error("Failed: power_cycle: {}".format(str(err)))
|
|
|
674a4f |
+ return False
|
|
|
674a4f |
+
|
|
|
674a4f |
+
|
|
|
674a4f |
def get_instance(conn, project, zone, instance):
|
|
|
674a4f |
request = conn.instances().get(
|
|
|
674a4f |
project=project, zone=zone, instance=instance)
|
|
|
674a4f |
@@ -161,13 +176,15 @@ def main():
|
|
|
674a4f |
|
|
|
674a4f |
hostname = platform.node()
|
|
|
674a4f |
|
|
|
674a4f |
- device_opt = ["port", "no_password", "zone", "project", "logging"]
|
|
|
674a4f |
+ device_opt = ["port", "no_password", "zone", "project", "logging", "method"]
|
|
|
674a4f |
|
|
|
674a4f |
atexit.register(atexit_handler)
|
|
|
674a4f |
|
|
|
674a4f |
define_new_opts()
|
|
|
674a4f |
|
|
|
674a4f |
all_opt["power_timeout"]["default"] = "60"
|
|
|
674a4f |
+ all_opt["method"]["default"] = "cycle"
|
|
|
674a4f |
+ all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: cycle)"
|
|
|
674a4f |
|
|
|
674a4f |
options = check_input(device_opt, process_input(device_opt))
|
|
|
674a4f |
|
|
|
674a4f |
@@ -225,7 +242,7 @@ def main():
|
|
|
674a4f |
fail_usage("Failed retrieving GCE zone. Please provide --zone option: {}".format(str(err)))
|
|
|
674a4f |
|
|
|
674a4f |
# Operate the fencing device
|
|
|
674a4f |
- result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list)
|
|
|
674a4f |
+ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list, power_cycle)
|
|
|
674a4f |
sys.exit(result)
|
|
|
674a4f |
|
|
|
674a4f |
if __name__ == "__main__":
|
|
|
674a4f |
diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
index 507b8385..f522550f 100644
|
|
|
674a4f |
--- a/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
+++ b/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
@@ -10,6 +10,14 @@ For instructions see: https://cloud.google.com/compute/docs/tutorials/python-gui
|
|
|
674a4f |
<content type="string" default="reboot" />
|
|
|
674a4f |
<shortdesc lang="en">Fencing action</shortdesc>
|
|
|
674a4f |
</parameter>
|
|
|
674a4f |
+ <parameter name="method" unique="0" required="0">
|
|
|
674a4f |
+ <getopt mixed="-m, --method=[method]" />
|
|
|
674a4f |
+ <content type="select" default="cycle" >
|
|
|
674a4f |
+ <option value="onoff" />
|
|
|
674a4f |
+ <option value="cycle" />
|
|
|
674a4f |
+ </content>
|
|
|
674a4f |
+ <shortdesc lang="en">Method to fence</shortdesc>
|
|
|
674a4f |
+ </parameter>
|
|
|
674a4f |
<parameter name="plug" unique="0" required="1" obsoletes="port">
|
|
|
674a4f |
<getopt mixed="-n, --plug=[id]" />
|
|
|
674a4f |
<content type="string" />
|
|
|
674a4f |
|
|
|
674a4f |
From 68644764695b79a3b75826fe009ea7da675677f7 Mon Sep 17 00:00:00 2001
|
|
|
674a4f |
From: Helen Koike <helen.koike@collabora.com>
|
|
|
674a4f |
Date: Thu, 5 Jul 2018 11:04:32 -0300
|
|
|
674a4f |
Subject: [PATCH 4/7] fence_gce: add missing imports to retrieve the project
|
|
|
674a4f |
|
|
|
674a4f |
---
|
|
|
674a4f |
agents/gce/fence_gce.py | 9 +++++++++
|
|
|
674a4f |
1 file changed, 9 insertions(+)
|
|
|
674a4f |
|
|
|
674a4f |
diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py
|
|
|
674a4f |
index 3f77dc24..9b7b5e55 100644
|
|
|
674a4f |
--- a/agents/gce/fence_gce.py
|
|
|
674a4f |
+++ b/agents/gce/fence_gce.py
|
|
|
674a4f |
@@ -2,9 +2,18 @@
|
|
|
674a4f |
|
|
|
674a4f |
import atexit
|
|
|
674a4f |
import logging
|
|
|
674a4f |
+import os
|
|
|
674a4f |
import platform
|
|
|
674a4f |
import sys
|
|
|
674a4f |
import time
|
|
|
674a4f |
+if sys.version_info >= (3, 0):
|
|
|
674a4f |
+ # Python 3 imports.
|
|
|
674a4f |
+ import urllib.parse as urlparse
|
|
|
674a4f |
+ import urllib.request as urlrequest
|
|
|
674a4f |
+else:
|
|
|
674a4f |
+ # Python 2 imports.
|
|
|
674a4f |
+ import urllib as urlparse
|
|
|
674a4f |
+ import urllib2 as urlrequest
|
|
|
674a4f |
sys.path.append("@FENCEAGENTSLIBDIR@")
|
|
|
674a4f |
|
|
|
674a4f |
import googleapiclient.discovery
|
|
|
674a4f |
|
|
|
674a4f |
From f8f3f11187341622c26e4e439dfda6a37ad660b0 Mon Sep 17 00:00:00 2001
|
|
|
674a4f |
From: Helen Koike <helen.koike@collabora.com>
|
|
|
674a4f |
Date: Thu, 5 Jul 2018 11:05:32 -0300
|
|
|
674a4f |
Subject: [PATCH 5/7] fence_gce: s/--loging/--stackdriver-logging/
|
|
|
674a4f |
|
|
|
674a4f |
---
|
|
|
674a4f |
agents/gce/fence_gce.py | 42 ++++++++++++++++++---------------------
|
|
|
674a4f |
tests/data/metadata/fence_gce.xml | 11 +++++++---
|
|
|
674a4f |
2 files changed, 27 insertions(+), 26 deletions(-)
|
|
|
674a4f |
|
|
|
674a4f |
diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py
|
|
|
674a4f |
index 9b7b5e55..a6befe39 100644
|
|
|
674a4f |
--- a/agents/gce/fence_gce.py
|
|
|
674a4f |
+++ b/agents/gce/fence_gce.py
|
|
|
674a4f |
@@ -167,14 +167,13 @@ def define_new_opts():
|
|
|
674a4f |
"required" : "0",
|
|
|
674a4f |
"order" : 3
|
|
|
674a4f |
}
|
|
|
674a4f |
- all_opt["logging"] = {
|
|
|
674a4f |
- "getopt" : ":",
|
|
|
674a4f |
- "longopt" : "logging",
|
|
|
674a4f |
- "help" : "--logging=[bool] Logging, true/false",
|
|
|
674a4f |
+ all_opt["stackdriver-logging"] = {
|
|
|
674a4f |
+ "getopt" : "",
|
|
|
674a4f |
+ "longopt" : "stackdriver-logging",
|
|
|
674a4f |
+ "help" : "--stackdriver-logging Enable Logging to Stackdriver",
|
|
|
674a4f |
"shortdesc" : "Stackdriver-logging support.",
|
|
|
674a4f |
- "longdesc" : "If enabled (set to true), IP failover logs will be posted to stackdriver logging.",
|
|
|
674a4f |
+ "longdesc" : "If enabled IP failover logs will be posted to stackdriver logging.",
|
|
|
674a4f |
"required" : "0",
|
|
|
674a4f |
- "default" : "false",
|
|
|
674a4f |
"order" : 4
|
|
|
674a4f |
}
|
|
|
674a4f |
|
|
|
674a4f |
@@ -185,7 +184,7 @@ def main():
|
|
|
674a4f |
|
|
|
674a4f |
hostname = platform.node()
|
|
|
674a4f |
|
|
|
674a4f |
- device_opt = ["port", "no_password", "zone", "project", "logging", "method"]
|
|
|
674a4f |
+ device_opt = ["port", "no_password", "zone", "project", "stackdriver-logging", "method"]
|
|
|
674a4f |
|
|
|
674a4f |
atexit.register(atexit_handler)
|
|
|
674a4f |
|
|
|
674a4f |
@@ -210,22 +209,19 @@ def main():
|
|
|
674a4f |
run_delay(options)
|
|
|
674a4f |
|
|
|
674a4f |
# Prepare logging
|
|
|
674a4f |
- logging_env = options.get('--logging')
|
|
|
674a4f |
- if logging_env:
|
|
|
674a4f |
- logging_env = logging_env.lower()
|
|
|
674a4f |
- if any(x in logging_env for x in ['yes', 'true', 'enabled']):
|
|
|
674a4f |
- try:
|
|
|
674a4f |
- import google.cloud.logging.handlers
|
|
|
674a4f |
- client = google.cloud.logging.Client()
|
|
|
674a4f |
- handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname)
|
|
|
674a4f |
- formatter = logging.Formatter('gcp:stonish "%(message)s"')
|
|
|
674a4f |
- LOGGER = logging.getLogger(hostname)
|
|
|
674a4f |
- handler.setFormatter(formatter)
|
|
|
674a4f |
- LOGGER.addHandler(handler)
|
|
|
674a4f |
- LOGGER.setLevel(logging.INFO)
|
|
|
674a4f |
- except ImportError:
|
|
|
674a4f |
- LOGGER.error('Couldn\'t import google.cloud.logging, '
|
|
|
674a4f |
- 'disabling Stackdriver-logging support')
|
|
|
674a4f |
+ if options.get('--stackdriver-logging'):
|
|
|
674a4f |
+ try:
|
|
|
674a4f |
+ import google.cloud.logging.handlers
|
|
|
674a4f |
+ client = google.cloud.logging.Client()
|
|
|
674a4f |
+ handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname)
|
|
|
674a4f |
+ formatter = logging.Formatter('gcp:stonish "%(message)s"')
|
|
|
674a4f |
+ LOGGER = logging.getLogger(hostname)
|
|
|
674a4f |
+ handler.setFormatter(formatter)
|
|
|
674a4f |
+ LOGGER.addHandler(handler)
|
|
|
674a4f |
+ LOGGER.setLevel(logging.INFO)
|
|
|
674a4f |
+ except ImportError:
|
|
|
674a4f |
+ LOGGER.error('Couldn\'t import google.cloud.logging, '
|
|
|
674a4f |
+ 'disabling Stackdriver-logging support')
|
|
|
674a4f |
|
|
|
674a4f |
# Prepare cli
|
|
|
674a4f |
try:
|
|
|
674a4f |
diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
index f522550f..79b82ebb 100644
|
|
|
674a4f |
--- a/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
+++ b/tests/data/metadata/fence_gce.xml
|
|
|
674a4f |
@@ -38,9 +38,14 @@ For instructions see: https://cloud.google.com/compute/docs/tutorials/python-gui
|
|
|
674a4f |
<content type="string" />
|
|
|
674a4f |
<shortdesc lang="en">Project ID.</shortdesc>
|
|
|
674a4f |
</parameter>
|
|
|
674a4f |
- <parameter name="logging" unique="0" required="0">
|
|
|
674a4f |
- <getopt mixed="--logging=[bool]" />
|
|
|
674a4f |
- <content type="string" default="false" />
|
|
|
674a4f |
+ <parameter name="stackdriver-logging" unique="0" required="0" deprecated="1">
|
|
|
674a4f |
+ <getopt mixed="--stackdriver-logging" />
|
|
|
674a4f |
+ <content type="boolean" />
|
|
|
674a4f |
+ <shortdesc lang="en">Stackdriver-logging support.</shortdesc>
|
|
|
674a4f |
+ </parameter>
|
|
|
674a4f |
+ <parameter name="stackdriver_logging" unique="0" required="0" obsoletes="stackdriver-logging">
|
|
|
674a4f |
+ <getopt mixed="--stackdriver-logging" />
|
|
|
674a4f |
+ <content type="boolean" />
|
|
|
674a4f |
<shortdesc lang="en">Stackdriver-logging support.</shortdesc>
|
|
|
674a4f |
</parameter>
|
|
|
674a4f |
<parameter name="quiet" unique="0" required="0">
|
|
|
674a4f |
|
|
|
674a4f |
From 9ae0a072424fa982e1d18a2cb661628c38601c3a Mon Sep 17 00:00:00 2001
|
|
|
674a4f |
From: Helen Koike <helen.koike@collabora.com>
|
|
|
674a4f |
Date: Sat, 7 Jul 2018 18:42:01 -0300
|
|
|
674a4f |
Subject: [PATCH 6/7] fence_gce: use root logger for stackdriver
|
|
|
674a4f |
|
|
|
674a4f |
---
|
|
|
674a4f |
agents/gce/fence_gce.py | 29 +++++++++++++++--------------
|
|
|
674a4f |
1 file changed, 15 insertions(+), 14 deletions(-)
|
|
|
674a4f |
|
|
|
674a4f |
diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py
|
|
|
674a4f |
index a6befe39..1d5095ae 100644
|
|
|
674a4f |
--- a/agents/gce/fence_gce.py
|
|
|
674a4f |
+++ b/agents/gce/fence_gce.py
|
|
|
674a4f |
@@ -20,7 +20,6 @@
|
|
|
674a4f |
from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action
|
|
|
674a4f |
|
|
|
674a4f |
|
|
|
674a4f |
-LOGGER = logging
|
|
|
674a4f |
METADATA_SERVER = 'http://metadata.google.internal/computeMetadata/v1/'
|
|
|
674a4f |
METADATA_HEADERS = {'Metadata-Flavor': 'Google'}
|
|
|
674a4f |
|
|
|
674a4f |
@@ -73,37 +72,37 @@ def wait_for_operation(conn, project, zone, operation):
|
|
|
674a4f |
def set_power_status(conn, options):
|
|
|
674a4f |
try:
|
|
|
674a4f |
if options["--action"] == "off":
|
|
|
674a4f |
- LOGGER.info("Issuing poweroff of %s in zone %s" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ logging.info("Issuing poweroff of %s in zone %s" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
operation = conn.instances().stop(
|
|
|
674a4f |
project=options["--project"],
|
|
|
674a4f |
zone=options["--zone"],
|
|
|
674a4f |
instance=options["--plug"]).execute()
|
|
|
674a4f |
wait_for_operation(conn, options["--project"], options["--zone"], operation)
|
|
|
674a4f |
- LOGGER.info("Poweroff of %s in zone %s complete" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ logging.info("Poweroff of %s in zone %s complete" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
elif options["--action"] == "on":
|
|
|
674a4f |
- LOGGER.info("Issuing poweron of %s in zone %s" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ logging.info("Issuing poweron of %s in zone %s" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
operation = conn.instances().start(
|
|
|
674a4f |
project=options["--project"],
|
|
|
674a4f |
zone=options["--zone"],
|
|
|
674a4f |
instance=options["--plug"]).execute()
|
|
|
674a4f |
wait_for_operation(conn, options["--project"], options["--zone"], operation)
|
|
|
674a4f |
- LOGGER.info("Poweron of %s in zone %s complete" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ logging.info("Poweron of %s in zone %s complete" % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
except Exception as err:
|
|
|
674a4f |
fail_usage("Failed: set_power_status: {}".format(str(err)))
|
|
|
674a4f |
|
|
|
674a4f |
|
|
|
674a4f |
def power_cycle(conn, options):
|
|
|
674a4f |
try:
|
|
|
674a4f |
- LOGGER.info('Issuing reset of %s in zone %s' % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ logging.info('Issuing reset of %s in zone %s' % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
operation = conn.instances().reset(
|
|
|
674a4f |
project=options["--project"],
|
|
|
674a4f |
zone=options["--zone"],
|
|
|
674a4f |
instance=options["--plug"]).execute()
|
|
|
674a4f |
wait_for_operation(conn, options["--project"], options["--zone"], operation)
|
|
|
674a4f |
- LOGGER.info('Reset of %s in zone %s complete' % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
+ logging.info('Reset of %s in zone %s complete' % (options["--plug"], options["--zone"]))
|
|
|
674a4f |
return True
|
|
|
674a4f |
except Exception as err:
|
|
|
674a4f |
- LOGGER.error("Failed: power_cycle: {}".format(str(err)))
|
|
|
674a4f |
+ logging.error("Failed: power_cycle: {}".format(str(err)))
|
|
|
674a4f |
return False
|
|
|
674a4f |
|
|
|
674a4f |
|
|
|
674a4f |
@@ -180,7 +179,6 @@ def define_new_opts():
|
|
|
674a4f |
|
|
|
674a4f |
def main():
|
|
|
674a4f |
conn = None
|
|
|
674a4f |
- global LOGGER
|
|
|
674a4f |
|
|
|
674a4f |
hostname = platform.node()
|
|
|
674a4f |
|
|
|
674a4f |
@@ -209,18 +207,21 @@ def main():
|
|
|
674a4f |
run_delay(options)
|
|
|
674a4f |
|
|
|
674a4f |
# Prepare logging
|
|
|
674a4f |
- if options.get('--stackdriver-logging'):
|
|
|
674a4f |
+ if options.get('--stackdriver-logging') is not None:
|
|
|
674a4f |
try:
|
|
|
674a4f |
import google.cloud.logging.handlers
|
|
|
674a4f |
client = google.cloud.logging.Client()
|
|
|
674a4f |
handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname)
|
|
|
674a4f |
+ handler.setLevel(logging.INFO)
|
|
|
674a4f |
formatter = logging.Formatter('gcp:stonish "%(message)s"')
|
|
|
674a4f |
- LOGGER = logging.getLogger(hostname)
|
|
|
674a4f |
handler.setFormatter(formatter)
|
|
|
674a4f |
- LOGGER.addHandler(handler)
|
|
|
674a4f |
- LOGGER.setLevel(logging.INFO)
|
|
|
674a4f |
+ root_logger = logging.getLogger()
|
|
|
674a4f |
+ if options.get('--verbose') is None:
|
|
|
674a4f |
+ root_logger.setLevel(logging.INFO)
|
|
|
674a4f |
+ logging.getLogger("googleapiclient").setLevel(logging.ERROR)
|
|
|
674a4f |
+ root_logger.addHandler(handler)
|
|
|
674a4f |
except ImportError:
|
|
|
674a4f |
- LOGGER.error('Couldn\'t import google.cloud.logging, '
|
|
|
674a4f |
+ logging.error('Couldn\'t import google.cloud.logging, '
|
|
|
674a4f |
'disabling Stackdriver-logging support')
|
|
|
674a4f |
|
|
|
674a4f |
# Prepare cli
|
|
|
674a4f |
|
|
|
674a4f |
From a52e643708908539d6e5fdb5d36a6cea935e4481 Mon Sep 17 00:00:00 2001
|
|
|
674a4f |
From: Helen Koike <helen.koike@collabora.com>
|
|
|
674a4f |
Date: Wed, 11 Jul 2018 17:16:49 -0300
|
|
|
674a4f |
Subject: [PATCH 7/7] fence_gce: minor changes in logging
|
|
|
674a4f |
|
|
|
674a4f |
- Remove hostname (use --plug instead).
|
|
|
674a4f |
- Supress messages from googleapiclient and oauth2client if not error in
|
|
|
674a4f |
non verbose mode.
|
|
|
674a4f |
- s/stonish/stonith
|
|
|
674a4f |
---
|
|
|
674a4f |
agents/gce/fence_gce.py | 13 ++++++-------
|
|
|
674a4f |
1 file changed, 6 insertions(+), 7 deletions(-)
|
|
|
674a4f |
|
|
|
674a4f |
diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py
|
|
|
674a4f |
index 1d5095ae..3eca0139 100644
|
|
|
674a4f |
--- a/agents/gce/fence_gce.py
|
|
|
674a4f |
+++ b/agents/gce/fence_gce.py
|
|
|
674a4f |
@@ -3,7 +3,6 @@
|
|
|
674a4f |
import atexit
|
|
|
674a4f |
import logging
|
|
|
674a4f |
import os
|
|
|
674a4f |
-import platform
|
|
|
674a4f |
import sys
|
|
|
674a4f |
import time
|
|
|
674a4f |
if sys.version_info >= (3, 0):
|
|
|
674a4f |
@@ -180,8 +179,6 @@ def define_new_opts():
|
|
|
674a4f |
def main():
|
|
|
674a4f |
conn = None
|
|
|
674a4f |
|
|
|
674a4f |
- hostname = platform.node()
|
|
|
674a4f |
-
|
|
|
674a4f |
device_opt = ["port", "no_password", "zone", "project", "stackdriver-logging", "method"]
|
|
|
674a4f |
|
|
|
674a4f |
atexit.register(atexit_handler)
|
|
|
674a4f |
@@ -207,18 +204,20 @@ def main():
|
|
|
674a4f |
run_delay(options)
|
|
|
674a4f |
|
|
|
674a4f |
# Prepare logging
|
|
|
674a4f |
- if options.get('--stackdriver-logging') is not None:
|
|
|
674a4f |
+ if options.get('--verbose') is None:
|
|
|
674a4f |
+ logging.getLogger('googleapiclient').setLevel(logging.ERROR)
|
|
|
674a4f |
+ logging.getLogger('oauth2client').setLevel(logging.ERROR)
|
|
|
674a4f |
+ if options.get('--stackdriver-logging') is not None and options.get('--plug'):
|
|
|
674a4f |
try:
|
|
|
674a4f |
import google.cloud.logging.handlers
|
|
|
674a4f |
client = google.cloud.logging.Client()
|
|
|
674a4f |
- handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=hostname)
|
|
|
674a4f |
+ handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=options['--plug'])
|
|
|
674a4f |
handler.setLevel(logging.INFO)
|
|
|
674a4f |
- formatter = logging.Formatter('gcp:stonish "%(message)s"')
|
|
|
674a4f |
+ formatter = logging.Formatter('gcp:stonith "%(message)s"')
|
|
|
674a4f |
handler.setFormatter(formatter)
|
|
|
674a4f |
root_logger = logging.getLogger()
|
|
|
674a4f |
if options.get('--verbose') is None:
|
|
|
674a4f |
root_logger.setLevel(logging.INFO)
|
|
|
674a4f |
- logging.getLogger("googleapiclient").setLevel(logging.ERROR)
|
|
|
674a4f |
root_logger.addHandler(handler)
|
|
|
674a4f |
except ImportError:
|
|
|
674a4f |
logging.error('Couldn\'t import google.cloud.logging, '
|