Blob Blame History Raw
--- a/fence/agents/compute/fence_compute.py	2016-11-10 18:03:41.473498575 +1100
+++ b/fence/agents/compute/fence_compute.py	2016-11-10 12:45:28.766603941 +1100
@@ -45,7 +45,7 @@ def get_power_status(_, options):
 					else:
 						logging.debug("Unknown status detected from nova: " + service.state)
 					break
-		except ConnectionError as (err):
+		except ConnectionError as err:
 			logging.warning("Nova connection failed: " + str(err))
 	return status
 
@@ -160,7 +160,7 @@ def set_power_status(_, options):
 		return
 
 	if options["--action"] == "on":
-		if get_power_status(_, options) == "on":
+		if get_power_status(_, options) != "on":
 			# Forcing the service back up in case it was disabled
 			nova.services.enable(options["--plug"], 'nova-compute')
 			try:
@@ -168,7 +168,7 @@ def set_power_status(_, options):
 				nova.services.force_down(
 					options["--plug"], "nova-compute", force_down=False)
 			except Exception as e:
-				# In theory, if foce_down=False fails, that's for the exact
+				# In theory, if force_down=False fails, that's for the exact
 				# same possible reasons that below with force_down=True
 				# eg. either an incompatible version or an old client.
 				# Since it's about forcing back to a default value, there is
@@ -202,7 +202,7 @@ def set_power_status(_, options):
 			#
 			# Some callers (such as Pacemaker) will have a timer
 			# running and kill us if necessary
-			logging.debug("Waiting for nova to update it's internal state for %s" % options["--plug"])
+			logging.debug("Waiting for nova to update its internal state for %s" % options["--plug"])
 			time.sleep(1)
 
 	if not _host_evacuate(options):
@@ -236,49 +236,45 @@ def fix_domain(options):
 				# One hopes they don't appear interleaved as A.com B.com A.com B.com
 				logging.debug("Calculated the same domain from: %s" % hypervisor.hypervisor_hostname)
 
-			elif options.has_key("--domain") and options["--domain"] == calculated:
+			elif "--domain" in options and options["--domain"] == calculated:
 				# Supplied domain name is valid 
 				return
 
-			elif options.has_key("--domain"):
+			elif "--domain" in options:
 				# Warn in case nova isn't available at some point
 				logging.warning("Supplied domain '%s' does not match the one calculated from: %s"
 					      % (options["--domain"], hypervisor.hypervisor_hostname))
 
 			last_domain = calculated
 
-	if len(domains) == 0 and not options.has_key("--domain"):
+	if len(domains) == 0 and "--domain" not in options:
 		logging.error("Could not calculate the domain names used by compute nodes in nova")
 
-	elif len(domains) == 1 and not options.has_key("--domain"):
+	elif len(domains) == 1 and "--domain" not in options:
 		options["--domain"] = last_domain
-		return options["--domain"]
 
 	elif len(domains) == 1:
 		logging.error("Overriding supplied domain '%s' does not match the one calculated from: %s"
 			      % (options["--domain"], hypervisor.hypervisor_hostname))
 		options["--domain"] = last_domain
-		return options["--domain"]
 
 	elif len(domains) > 1:
 		logging.error("The supplied domain '%s' did not match any used inside nova: %s"
 			      % (options["--domain"], repr(domains)))
 		sys.exit(1)
 
-	return None
-
 def fix_plug_name(options):
 	if options["--action"] == "list":
 		return
 
-	if not options.has_key("--plug"):
+	if "--plug" not in options:
 		return
 
-	calculated = fix_domain(options)
+	fix_domain(options)
 	short_plug = options["--plug"].split('.')[0]
-	logging.debug("Checking target '%s' against calculated domain '%s'"% (options["--plug"], calculated))
+	logging.debug("Checking target '%s' against calculated domain '%s'"% (options["--plug"], options["--domain"]))
 
-	if not options.has_key("--domain"):
+	if "--domain" not in options:
 		# Nothing supplied and nova not available... what to do... nothing
 		return
 
@@ -286,7 +282,7 @@ def fix_plug_name(options):
 		# Ensure any domain is stripped off since nova isn't using FQDN
 		options["--plug"] = short_plug
 
-	elif options["--plug"].find(options["--domain"]):
+	elif options["--domain"] in options["--plug"]:
 		# Plug already contains the domain, don't re-add 
 		return
 
@@ -306,6 +302,37 @@ def get_plugs_list(_, options):
 			result[shorthost] = ("", None)
 	return result
 
+def create_nova_connection(options):
+	global nova
+
+	try:
+		from novaclient import client
+		from novaclient.exceptions import NotAcceptable
+	except ImportError:
+		fail_usage("Nova not found or not accessible")
+
+	versions = [ "2.11", "2" ]
+	for version in versions:
+		nova = client.Client(version,
+				     options["--username"],
+				     options["--password"],
+				     options["--tenant-name"],
+				     options["--auth-url"],
+				     insecure=options["--insecure"],
+				     region_name=options["--region-name"],
+				     endpoint_type=options["--endpoint-type"],
+				     http_log_debug=options.has_key("--verbose"))
+		try:
+			nova.hypervisors.list()
+			return
+
+		except NotAcceptable as e:
+			logging.warning(e)
+
+		except Exception as e:
+			logging.warning("Nova connection failed. %s: %s" % (e.__class__.__name__, e))
+			
+	logging.warning("Couldn't obtain a supported connection to nova, tried: %s\n" % repr(versions))
 
 def define_new_opts():
 	all_opt["endpoint-type"] = {
@@ -329,12 +356,30 @@ def define_new_opts():
 	all_opt["auth-url"] = {
 		"getopt" : "k:",
 		"longopt" : "auth-url",
-		"help" : "-k, --auth-url=[tenant]        Keystone Admin Auth URL",
+		"help" : "-k, --auth-url=[url]           Keystone Admin Auth URL",
 		"required" : "0",
 		"shortdesc" : "Keystone Admin Auth URL",
 		"default" : "",
 		"order": 1,
 	}
+	all_opt["region-name"] = {
+		"getopt" : "",
+		"longopt" : "region-name",
+		"help" : "--region-name=[region]         Region Name",
+		"required" : "0",
+		"shortdesc" : "Region Name",
+		"default" : "",
+		"order": 1,
+	}
+	all_opt["insecure"] = {
+		"getopt" : "",
+		"longopt" : "insecure",
+		"help" : "--insecure                     Explicitly allow agent to perform \"insecure\" TLS (https) requests",
+		"required" : "0",
+		"shortdesc" : "Allow Insecure TLS Requests",
+		"default" : "False",
+		"order": 2,
+	}
 	all_opt["domain"] = {
 		"getopt" : "d:",
 		"longopt" : "domain",
@@ -373,12 +418,11 @@ def define_new_opts():
 
 def main():
 	global override_status
-	global nova
 	atexit.register(atexit_handler)
 
 	device_opt = ["login", "passwd", "tenant-name", "auth-url", "fabric_fencing", "on_target",
 		"no_login", "no_password", "port", "domain", "no-shared-storage", "endpoint-type",
-		"record-only", "instance-filtering"]
+		"record-only", "instance-filtering", "insecure", "region-name"]
 	define_new_opts()
 	all_opt["shell_timeout"]["default"] = "180"
 
@@ -391,19 +435,15 @@ def main():
 
 	show_docs(options, docs)
 
+	if options["--record-only"] in [ "2", "Disabled", "disabled" ]:
+		sys.exit(0)
+
 	run_delay(options)
 
-	try:
-		from novaclient import client as nova_client
-	except ImportError:
-		fail_usage("nova not found or not accessible")
+	create_nova_connection(options)
 
 	fix_plug_name(options)
-
-	if options["--record-only"] in [ "2", "Disabled", "disabled" ]:
-		sys.exit(0)
-
-	elif options["--record-only"] in [ "1", "True", "true", "Yes", "yes"]:
+	if options["--record-only"] in [ "1", "True", "true", "Yes", "yes"]:
 		if options["--action"] == "on":
 			set_attrd_status(options["--plug"], "no", options)
 			sys.exit(0)
@@ -412,17 +452,9 @@ def main():
 			set_attrd_status(options["--plug"], "yes", options)
 			sys.exit(0)
 
-		elif options["--action"] in ["monitor"]:
+		elif options["--action"] in ["monitor", "status"]:
 			sys.exit(0)
 
-	# The first argument is the Nova client version
-	nova = nova_client.Client('2',
-		options["--username"],
-		options["--password"],
-		options["--tenant-name"],
-		options["--auth-url"],
-		endpoint_type=options["--endpoint-type"])
-
 	if options["--action"] in ["off", "reboot"]:
 		# Pretend we're 'on' so that the fencing library will always call set_power_status(off)
 		override_status = "on"