From 16b79a023e6d438b242e0e4dd245362f836bf79b Mon Sep 17 00:00:00 2001 From: Alex Brett Date: Tue, 18 Jun 2024 14:53:16 +0000 Subject: [PATCH 1/3] IH-621: Add IPMI host power on support and remove DRAC DRAC power on support relies upon a Dell supplemental pack which is no longer available, so remove it. Add IPMI power on support using ipmitool, which should work with virtually any modern server which has a BMC, regardless of vendor. Signed-off-by: Alex Brett --- ocaml/idl/datamodel_host.ml | 2 +- scripts/Makefile | 2 +- scripts/poweron/DRAC.py | 60 ------------------------------------- scripts/poweron/IPMI.py | 46 ++++++++++++++++++++++++++++ scripts/poweron/power-on.py | 10 +++---- 5 files changed, 53 insertions(+), 67 deletions(-) delete mode 100644 scripts/poweron/DRAC.py create mode 100644 scripts/poweron/IPMI.py diff --git a/ocaml/idl/datamodel_host.ml b/ocaml/idl/datamodel_host.ml index 2f9d1d7ed83..dad24eabf17 100644 --- a/ocaml/idl/datamodel_host.ml +++ b/ocaml/idl/datamodel_host.ml @@ -1375,7 +1375,7 @@ let set_power_on_mode = (Ref _host, "self", "The host") ; ( String , "power_on_mode" - , "power-on-mode can be empty, wake-on-lan, DRAC or other" + , "power-on-mode can be empty, wake-on-lan, IPMI or other" ) ; (Map (String, String), "power_on_config", "Power on config") ] diff --git a/scripts/Makefile b/scripts/Makefile index 020cbbeff49..18e923c69fa 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -178,7 +178,7 @@ endif # poweron $(IPROG) poweron/wlan.py $(DESTDIR)$(PLUGINDIR)/wlan.py $(IPROG) poweron/wlan.py $(DESTDIR)$(PLUGINDIR)/wake-on-lan - $(IPROG) poweron/DRAC.py $(DESTDIR)$(PLUGINDIR)/DRAC.py + $(IPROG) poweron/IPMI.py $(DESTDIR)$(PLUGINDIR)/IPMI.py $(IPROG) poweron/power-on.py $(DESTDIR)$(PLUGINDIR)/power-on-host # YUM plugins $(IPROG) yum-plugins/accesstoken.py $(DESTDIR)$(YUMPLUGINDIR) diff --git a/scripts/poweron/DRAC.py b/scripts/poweron/DRAC.py deleted file mode 100644 index bace3a177a4..00000000000 --- a/scripts/poweron/DRAC.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python3 - -import os.path -import sys - -import xcp.cmd as cmd - - -class DRAC_NO_SUPP_PACK(Exception): - """Base Exception class for all transfer plugin errors.""" - - def __init__(self, *args): - Exception.__init__(self, *args) - - -class DRAC_POWERON_FAILED(Exception): - """Base Exception class for all transfer plugin errors.""" - - def __init__(self, *args): - Exception.__init__(self, *args) - - -drac_path = "/opt/dell/srvadmin/sbin/racadm" - - -def DRAC(power_on_ip, user, password): - if not os.path.exists(drac_path): - raise DRAC_NO_SUPP_PACK() - - (rc, stdout, stderr) = cmd.runCmd( - [ - drac_path, - "-r", - power_on_ip, - "-u", - user, - "-p", - password, - "serveraction", - "powerup", - ], - with_stdout=True, - with_stderr=True, - ) - if rc != 0: - raise DRAC_POWERON_FAILED(stderr) - return stdout - - -def main(): - if len(sys.argv) < 3: - exit(0) - ip = sys.argv[1] - user = sys.argv[2] - password = sys.argv[3] - print(DRAC(ip, user, password)) - - -if __name__ == "__main__": - main() diff --git a/scripts/poweron/IPMI.py b/scripts/poweron/IPMI.py new file mode 100644 index 00000000000..73a452af888 --- /dev/null +++ b/scripts/poweron/IPMI.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +import os.path +import sys + +import xcp.cmd as cmd + + +class IPMI_POWERON_FAILED(Exception): + """IPMI Poweron exception""" + pass + +ipmi_path = "/usr/bin/ipmitool" + +def IPMI(power_on_ip, user, password): + (rc, stdout, stderr) = cmd.runCmd( + [ + ipmi_path, + "-H", + power_on_ip, + "-I", "lanplus", + "-U", + user, + "-P", + password, + "chassis", "power", "on" + ], + with_stdout=True, + with_stderr=True, + ) + if rc != 0: + raise IPMI_POWERON_FAILED(stderr) + return stdout + + +def main(): + if len(sys.argv) < 3: + exit(0) + ip = sys.argv[1] + user = sys.argv[2] + password = sys.argv[3] + print(IPMI(ip, user, password)) + + +if __name__ == "__main__": + main() diff --git a/scripts/poweron/power-on.py b/scripts/poweron/power-on.py index 34fec2f1e60..a76726a5019 100644 --- a/scripts/poweron/power-on.py +++ b/scripts/poweron/power-on.py @@ -41,14 +41,14 @@ def main(session, args): power_on_config = session.xenapi.host.get_power_on_config(remote_host) - if mode == "DRAC": + if mode == "IPMI": ip = power_on_config["power_on_ip"] user = power_on_config["power_on_user"] secret = power_on_config["power_on_password_secret"] secretref = session.xenapi.secret.get_by_uuid(secret) password = session.xenapi.secret.get_value(secretref) - modu = __import__("DRAC") - modu.DRAC(ip, user, password) + modu = __import__("IPMI") + modu.IPMI(ip, user, password) return waitForXapi(session, remote_host) elif mode == "wake-on-lan": modu = __import__("wlan") @@ -60,8 +60,8 @@ def main(session, args): modu = __import__(mode) except ModuleNotFoundError as e: # iLO.py was removed as part of REQ-811, so tell user why they are receiving this error - if mode == "iLO": - syslog.syslog(syslog.LOG_ERR, "iLO script was removed") + if mode in ["iLO", "DRAC"]: + syslog.syslog(syslog.LOG_ERR, f"{mode} script has been removed") raise e modu.custom(session, remote_host, power_on_config) From 1b06e51cefecd38b24934afc0422a167647d8a3f Mon Sep 17 00:00:00 2001 From: Alex Brett Date: Fri, 5 Jul 2024 10:50:22 +0000 Subject: [PATCH 2/3] IH-621 Add changed line to power_on_mode As per review comment. Signed-off-by: Alex Brett --- ocaml/idl/datamodel_host.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/ocaml/idl/datamodel_host.ml b/ocaml/idl/datamodel_host.ml index dad24eabf17..b7d34350819 100644 --- a/ocaml/idl/datamodel_host.ml +++ b/ocaml/idl/datamodel_host.ml @@ -1367,6 +1367,7 @@ let set_power_on_mode = [ (Published, rel_cowley, "") ; (Changed, rel_stockholm, "Removed iLO script") + ; (Changed, "24.19.0", "Replaced DRAC mode with IPMI") ] ~in_product_since:rel_midnight_ride ~doc:"Set the power-on-mode, host, user and password" From 331c564e0f6d472dc456c2f34cf6ca5d5c248a29 Mon Sep 17 00:00:00 2001 From: Alex Brett Date: Fri, 5 Jul 2024 15:37:10 +0000 Subject: [PATCH 3/3] IH-621: Python tweaks suggested by pylint Signed-off-by: Alex Brett --- scripts/poweron/IPMI.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/scripts/poweron/IPMI.py b/scripts/poweron/IPMI.py index 73a452af888..0f70607bf6f 100644 --- a/scripts/poweron/IPMI.py +++ b/scripts/poweron/IPMI.py @@ -1,10 +1,7 @@ #!/usr/bin/env python3 -import os.path import sys - -import xcp.cmd as cmd - +from xcp import cmd class IPMI_POWERON_FAILED(Exception): """IPMI Poweron exception""" @@ -35,7 +32,7 @@ def IPMI(power_on_ip, user, password): def main(): if len(sys.argv) < 3: - exit(0) + sys.exit(1) ip = sys.argv[1] user = sys.argv[2] password = sys.argv[3]