summaryrefslogtreecommitdiffstats
path: root/agents/ironic/fence_ironic.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:50:17 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:50:17 +0000
commit86ed03f8adee56c050c73018537371c230a664a6 (patch)
treeeae3d04cdf1c49848e5a671327ab38297f4acb0d /agents/ironic/fence_ironic.py
parentInitial commit. (diff)
downloadfence-agents-upstream.tar.xz
fence-agents-upstream.zip
Adding upstream version 4.12.1.upstream/4.12.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'agents/ironic/fence_ironic.py')
-rw-r--r--agents/ironic/fence_ironic.py130
1 files changed, 130 insertions, 0 deletions
diff --git a/agents/ironic/fence_ironic.py b/agents/ironic/fence_ironic.py
new file mode 100644
index 0000000..66d84fc
--- /dev/null
+++ b/agents/ironic/fence_ironic.py
@@ -0,0 +1,130 @@
+#!@PYTHON@ -tt
+
+import atexit
+import logging
+import os
+import re
+import sys
+from pipes import quote
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, is_executable, run_command, run_delay
+
+def get_name_or_uuid(options):
+ return options["--uuid"] if "--uuid" in options else options["--plug"]
+
+def get_power_status(_, options):
+ output = ironic_run_command(options, "status")
+ stdout = output[1]
+ match = re.search('power[\\s]*([a-zA-Z]{2,3})', str(stdout))
+ status = match.group(1) if match else None
+ return status
+
+def set_power_status(_, options):
+ ironic_run_command(options, options["--action"])
+ return
+
+def get_devices_list(_, options):
+ nodes = {}
+ output = ironic_run_command(options, "list")
+ stdout = output[1]
+ for line in stdout.splitlines():
+ uuid = "UUID"
+ try:
+ (uuid, name, state) = line.split(',')
+ except ValueError:
+ pass
+ if "UUID" in uuid:
+ continue # skip line header
+ match = re.search('power[\\s]*([a-zA-Z]{2,3})', state)
+ status = match.group(1) if match else None
+ nodes[uuid] = (name, status)
+
+ return nodes
+
+def ironic_run_command(options, action, timeout=None):
+ cmd = options["--openstack-path"] + " baremetal"
+ env = os.environ.copy()
+ # --username / -l
+ if "--username" in options and len(options["--username"]) != 0:
+ env["OS_USERNAME"] = options["--username"]
+
+ # --password / -p
+ if "--password" in options:
+ env["OS_PASSWORD"] = options["--password"]
+
+ # --tenant-name -t
+ if "--tenant-name" in options:
+ env["OS_TENANT_NAME"] = options["--tenant-name"]
+
+ # --auth-url
+ if "--auth-url" in options:
+ env["OS_AUTH_URL"] = options["--auth-url"]
+
+ # --action / -o
+ if action == "status":
+ cmd += " show %s -c power_state --format value" % (get_name_or_uuid(options))
+ elif action in ["on", "off"]:
+ cmd += " power %s %s" % (action, get_name_or_uuid(options))
+ elif action == "list":
+ cmd += " list -c 'Instance UUID' -c Name -c 'Power State' --format csv --quote minimal"
+
+
+ logging.debug("cmd -> %s" % cmd)
+ return run_command(options, cmd, timeout, env)
+
+def define_new_opts():
+ all_opt["auth-url"] = {
+ "getopt" : ":",
+ "longopt" : "auth-url",
+ "help" : "--auth-url=[authurl] Auth URL",
+ "required" : "1",
+ "shortdesc" : "Keystone Admin Auth URL",
+ "order": 1
+ }
+ all_opt["tenant-name"] = {
+ "getopt" : "t:",
+ "longopt" : "tenant-name",
+ "help" : "-t, --tenant-name=[tenant] Tenantname",
+ "required" : "0",
+ "shortdesc" : "Keystone Admin Tenant",
+ "default": "admin",
+ "order": 1
+ }
+ all_opt["openstack-path"] = {
+ "getopt" : ":",
+ "longopt" : "openstack-path",
+ "help" : "--openstack-path=[path] Path to openstack binary",
+ "required" : "0",
+ "shortdesc" : "Path to the OpenStack binary",
+ "default" : "@OPENSTACK_PATH@",
+ "order": 200
+ }
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["login", "passwd", "port", "auth-url", "tenant-name", "openstack-path"]
+ define_new_opts()
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for OpenStack's Ironic (Bare Metal as a service) service"
+ docs["longdesc"] = "fence_ironic is a Fencing agent \
+which can be used with machines controlled by the Ironic service. \
+This agent calls the openstack CLI. \
+WARNING! This fence agent is not intended for production use. Relying on a functional ironic service for fencing is not a good design choice."
+ docs["vendorurl"] = "https://wiki.openstack.org/wiki/Ironic"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if not is_executable(options["--openstack-path"]):
+ fail_usage("openstack tool not found or not accessible")
+
+ result = fence_action(None, options, set_power_status, get_power_status, get_devices_list)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()