Blame SOURCES/bz1214359-2-fence_compute.patch

e4ffb1
From 21c2154bedceb6ebef1cae369768280d4b0f8652 Mon Sep 17 00:00:00 2001
e4ffb1
From: Marek 'marx' Grac <mgrac@redhat.com>
e4ffb1
Date: Fri, 5 Jun 2015 18:07:55 +0200
e4ffb1
Subject: [PATCH 2/4] fence_compute: Improvement of fence agent
e4ffb1
e4ffb1
---
e4ffb1
 fence/agents/compute/fence_compute.py | 73 ++++++++++++++++++++++-------------
e4ffb1
 fence/agents/lib/fencing.py.py        |  6 ++-
e4ffb1
 2 files changed, 50 insertions(+), 29 deletions(-)
e4ffb1
e4ffb1
diff --git a/fence/agents/compute/fence_compute.py b/fence/agents/compute/fence_compute.py
e4ffb1
index 2b37de7..66cf08f 100644
e4ffb1
--- a/fence/agents/compute/fence_compute.py
e4ffb1
+++ b/fence/agents/compute/fence_compute.py
e4ffb1
@@ -4,11 +4,11 @@ import sys
e4ffb1
 import time
e4ffb1
 import atexit
e4ffb1
 import logging
e4ffb1
+import requests.exceptions
e4ffb1
 
e4ffb1
 sys.path.append("@FENCEAGENTSLIBDIR@")
e4ffb1
 from fencing import *
e4ffb1
 from fencing import fail_usage, is_executable, run_command, run_delay
e4ffb1
-from novaclient import client as nova_client
e4ffb1
 
e4ffb1
 #BEGIN_VERSION_GENERATION
e4ffb1
 RELEASE_VERSION="4.0.11"
e4ffb1
@@ -32,18 +32,18 @@ def get_power_status(_, options):
e4ffb1
 	if nova:
e4ffb1
 		try:
e4ffb1
 			services = nova.services.list(host=options["--plug"])
e4ffb1
-		except Exception, e:
e4ffb1
-			fail_usage(str(e))
e4ffb1
-
e4ffb1
-		for service in services:
e4ffb1
-			if service.binary == "nova-compute":
e4ffb1
-				if service.state == "up":
e4ffb1
-					status = "on"
e4ffb1
-				elif service.state == "down":
e4ffb1
-					status = "down"
e4ffb1
-				else:
e4ffb1
-					logging.debug("Unknown status detected from nova: " + service.state)
e4ffb1
-				break
e4ffb1
+
e4ffb1
+			for service in services:
e4ffb1
+				if service.binary == "nova-compute":
e4ffb1
+					if service.state == "up":
e4ffb1
+						status = "on"
e4ffb1
+					elif service.state == "down":
e4ffb1
+						status = "off"
e4ffb1
+					else:
e4ffb1
+						logging.debug("Unknown status detected from nova: " + service.state)
e4ffb1
+					break
e4ffb1
+		except ConnectionError as (err):
e4ffb1
+			logging.warning("Nova connection failed: " + str(err))
e4ffb1
 	return status
e4ffb1
 
e4ffb1
 # NOTE(sbauza); We mimic the host-evacuate module since it's only a contrib
e4ffb1
@@ -143,15 +143,6 @@ def define_new_opts():
e4ffb1
 		"default" : "",
e4ffb1
 		"order": 1,
e4ffb1
 	}
e4ffb1
-	all_opt["novatool-path"] = {
e4ffb1
-		"getopt" : "i:",
e4ffb1
-		"longopt" : "novatool-path",
e4ffb1
-		"help" : "-i, --novatool-path=[path]     Path to nova binary",
e4ffb1
-		"required" : "0",
e4ffb1
-		"shortdesc" : "Path to nova binary",
e4ffb1
-		"default" : "@NOVA_PATH@",
e4ffb1
-		"order": 6,
e4ffb1
-	}
e4ffb1
 	all_opt["domain"] = {
e4ffb1
 		"getopt" : "d:",
e4ffb1
 		"longopt" : "domain",
e4ffb1
@@ -177,7 +168,7 @@ def main():
e4ffb1
 	atexit.register(atexit_handler)
e4ffb1
 
e4ffb1
 	device_opt = ["login", "passwd", "tenant-name", "auth-url",
e4ffb1
-		"novatool-path", "no_login", "no_password", "port", "domain", "no-shared-storage"]
e4ffb1
+		"no_login", "no_password", "port", "domain", "no-shared-storage"]
e4ffb1
 	define_new_opts()
e4ffb1
 	all_opt["shell_timeout"]["default"] = "180"
e4ffb1
 
e4ffb1
@@ -192,6 +183,15 @@ def main():
e4ffb1
 
e4ffb1
 	run_delay(options)
e4ffb1
 
e4ffb1
+	try:
e4ffb1
+		from novaclient import client as nova_client
e4ffb1
+	except ImportError:
e4ffb1
+		fail_usage("nova not found or not accessible")
e4ffb1
+
e4ffb1
+	# Potentially we should make this a pacemaker feature
e4ffb1
+	if options["--action"] != "list" and options["--domain"] != "" and options.has_key("--plug"):
e4ffb1
+		options["--plug"] = options["--plug"] + "." + options["--domain"]
e4ffb1
+
e4ffb1
 	# The first argument is the Nova client version
e4ffb1
 	nova = nova_client.Client('2',
e4ffb1
 		options["--username"],
e4ffb1
@@ -199,6 +199,29 @@ def main():
e4ffb1
 		options["--tenant-name"],
e4ffb1
 		options["--auth-url"])
e4ffb1
 
e4ffb1
+	if options["--action"] in ["on", "off", "reboot" ]:
e4ffb1
+		try:
e4ffb1
+			nova.services.list(host=options["--plug"])
e4ffb1
+		except ConnectionError as (err):
e4ffb1
+			# Yes, exit(0)
e4ffb1
+			#
e4ffb1
+			# Its possible that the control plane on which this
e4ffb1
+			# agent depends is not functional
e4ffb1
+			#
e4ffb1
+			# In this situation, fencing is waiting for resource
e4ffb1
+			# recovery and resource recovery is waiting for
e4ffb1
+			# fencing.
e4ffb1
+			#
e4ffb1
+			# To break the cycle, we all the fencing agent to
e4ffb1
+			# return 'done' immediately so that we can recover the
e4ffb1
+			# control plane. We then rely on the NovaCompute RA
e4ffb1
+			# to call this agent directly once the control plane
e4ffb1
+			# is up.
e4ffb1
+			#
e4ffb1
+			# Yes its horrible, but still better than nova itself.
e4ffb1
+			logging.warning("Nova connection failed: %s " % str(err))
e4ffb1
+			sys.exit(0)
e4ffb1
+
e4ffb1
 	if options["--action"] in ["off", "reboot"]:
e4ffb1
 		# Pretend we're 'on' so that the fencing library will always call set_power_status(off)
e4ffb1
 		override_status = "on"
e4ffb1
@@ -207,10 +230,6 @@ def main():
e4ffb1
 		# Pretend we're 'off' so that the fencing library will always call set_power_status(on)
e4ffb1
 		override_status = "off"
e4ffb1
 
e4ffb1
-	# Potentially we should make this a pacemaker feature
e4ffb1
-	if options["--action"] != "list" and options["--domain"] != "" and options.has_key("--plug"):
e4ffb1
-		options["--plug"] = options["--plug"]+"."+options["--domain"]
e4ffb1
-
e4ffb1
 	result = fence_action(None, options, set_power_status, get_power_status, get_plugs_list, None)
e4ffb1
 	sys.exit(result)
e4ffb1
 
e4ffb1
diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
e4ffb1
index f893082..29b3a94 100644
e4ffb1
--- a/fence/agents/lib/fencing.py.py
e4ffb1
+++ b/fence/agents/lib/fencing.py.py
e4ffb1
@@ -1109,9 +1109,11 @@ def fence_login(options, re_login_string=r"(login\s*: )|(Login Name:  )|(usernam
e4ffb1
 					conn.log_expect(options, options["--command-prompt"], int(options["--login-timeout"]))
e4ffb1
 			except KeyError:
e4ffb1
 				fail(EC_PASSWORD_MISSING)
e4ffb1
-	except pexpect.EOF:
e4ffb1
+	except pexpect.EOF, exception:
e4ffb1
+		logging.debug("%s", str(exception))
e4ffb1
 		fail(EC_LOGIN_DENIED)
e4ffb1
-	except pexpect.TIMEOUT:
e4ffb1
+	except pexpect.TIMEOUT, exception:
e4ffb1
+		logging.debug("%s", str(exception))
e4ffb1
 		fail(EC_LOGIN_DENIED)
e4ffb1
 	return conn
e4ffb1
 
e4ffb1
-- 
e4ffb1
1.9.3
e4ffb1