summaryrefslogtreecommitdiffstats
path: root/pyiplobserver
diff options
context:
space:
mode:
authorRaptor Engineering Development Team <support@raptorengineering.com>2018-01-19 07:20:20 -0600
committerRaptor Engineering Development Team <support@raptorengineering.com>2019-04-19 10:26:09 +0000
commite4712537429cbd15fe555ba01e180a08e53a1f42 (patch)
treedf179afbf0205795d081dfc421cf18e5b3be5f46 /pyiplobserver
parentd7f9af037393ef5d0a57e12573145d0b7c2668a4 (diff)
downloadtalos-skeleton-e4712537429cbd15fe555ba01e180a08e53a1f42.tar.gz
talos-skeleton-e4712537429cbd15fe555ba01e180a08e53a1f42.zip
Add new IPL status observer and Talos LED driver
Diffstat (limited to 'pyiplobserver')
l---------pyiplobserver/Makefile1
-rw-r--r--pyiplobserver/ipl_status_observer.py246
l---------pyiplobserver/setup.cfg1
-rw-r--r--pyiplobserver/setup.py6
4 files changed, 254 insertions, 0 deletions
diff --git a/pyiplobserver/Makefile b/pyiplobserver/Makefile
new file mode 120000
index 0000000..76a90fc
--- /dev/null
+++ b/pyiplobserver/Makefile
@@ -0,0 +1 @@
+../Makefile.python \ No newline at end of file
diff --git a/pyiplobserver/ipl_status_observer.py b/pyiplobserver/ipl_status_observer.py
new file mode 100644
index 0000000..34e8f34
--- /dev/null
+++ b/pyiplobserver/ipl_status_observer.py
@@ -0,0 +1,246 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 Raptor Engineering, LLC
+# Released under the terms of the GPL v3
+#
+# Get current istep with
+# busctl get-property org.openbmc.status.IPL /org/openbmc/status/IPL org.openbmc.status.IPL current_istep
+# Get current status with
+# busctl get-property org.openbmc.status.IPL /org/openbmc/status/IPL org.openbmc.status.IPL current_status
+
+import gobject
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+import os
+import subprocess
+import traceback
+import obmc.dbuslib.propertycacher as PropertyCacher
+from obmc.dbuslib.bindings import DbusProperties, DbusObjectManager, get_dbus
+import obmc.enums
+import obmc_system_config as System
+import obmc.mapper.utils
+import obmc.inventory
+import obmc.system
+
+DBUS_NAME = 'org.openbmc.status.IPL'
+OBJ_NAME = u'/org/openbmc/status/IPL'
+
+HOST_STATUS_RUNNING = "xyz.openbmc_project.State.Host.HostState.Running"
+
+IPL_SBE_DONE_ISTEP_MAJOR = 5
+IPL_SBE_DONE_ISTEP_MINOR = 2
+
+IPL_HOSTBOOT_START_ISTEP_MAJOR = 6
+IPL_HOSTBOOT_START_ISTEP_MINOR = 0
+
+IPL_COMPLETE_ISTEP_MAJOR = 21
+IPL_COMPLETE_ISTEP_MINOR = 3
+
+class IPLStatus(DbusProperties, DbusObjectManager):
+ def __init__(self, bus, obj_name):
+ super(IPLStatus, self).__init__(
+ conn=bus,
+ object_path=obj_name)
+ self.bus = bus
+ self.prev_access_fail_count = 0;
+ self.activateMonitoring = False
+ self.last_status = "";
+ self.last_istep = "";
+
+ host_state_dev = self.bus.get_object("xyz.openbmc_project.State.Host", u'/xyz/openbmc_project/state/host0')
+ host_state_iface = dbus.Interface(host_state_dev, 'org.freedesktop.DBus.Properties')
+ host_state_value = host_state_iface.Get("xyz.openbmc_project.State.Host", "CurrentHostState")
+ if host_state_value is not None:
+ if (host_state_value == HOST_STATUS_RUNNING):
+ self.activateMonitoring = True
+
+ self.Set(DBUS_NAME, "current_istep", "")
+ self.Set(DBUS_NAME, "current_status", "UNKNOWN")
+
+ bus.add_signal_receiver(
+ self.HostStatusChangeHandler,
+ dbus_interface="org.freedesktop.DBus.Properties",
+ signal_name="PropertiesChanged",
+ path=u'/xyz/openbmc_project/state/host0')
+
+ gobject.timeout_add(100, self.readIPLStatus)
+
+ print "IPLStatus Init Done"
+
+ def readIPLStatus(self):
+ try:
+ # Set up defaults
+ current_status = "OFFLINE"
+ current_istep = ""
+ sbe_fetch_failed = False
+ hostboot_fetch_failed = False
+ sbe_istep_major = 0
+ sbe_istep_minor = 0
+ hostboot_istep_major = 0
+ hostboot_istep_minor = 0
+
+ if (self.activateMonitoring == False):
+ # Publish offline status
+ if (self.last_status != current_status):
+ self.Set(DBUS_NAME, "current_status", current_status)
+ self.IPLStatusChanged(current_status)
+ self.last_status = current_status
+ if (self.last_istep != current_istep):
+ self.Set(DBUS_NAME, "current_istep", current_istep)
+ self.IPLStepChanged(current_istep)
+ self.last_istep = current_istep
+
+ return True;
+
+ # Get SBE status
+ proc = subprocess.Popen(["pdbg", "-b", "kernel", "-p0", "getcfam", "0x2809"], stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'), shell=False)
+ (out, err) = proc.communicate()
+ status_data = out.split("=")
+ if (len(status_data) > 1):
+ try:
+ binary_status_data = bin(int(status_data[1], 16))
+ except ValueError:
+ sbe_fetch_failed = True
+
+ if (sbe_fetch_failed == False):
+ try:
+ sbe_istep_major = int(binary_status_data[14:22], 2)
+ sbe_istep_minor = int(binary_status_data[22:28], 2)
+ sbe_istep = str(sbe_istep_major) + "," + str(sbe_istep_minor)
+ except ValueError:
+ sbe_fetch_failed = True
+ else:
+ sbe_fetch_failed = True
+
+ # Determine if hostboot should be checked for activity
+ hostboot_active = False
+ if (sbe_fetch_failed):
+ # Check if hostboot is running
+ hostboot_active = True
+ if ((sbe_istep_major == IPL_SBE_DONE_ISTEP_MAJOR) and (sbe_istep_minor == IPL_SBE_DONE_ISTEP_MINOR)):
+ # Hostboot should definitely be running
+ hostboot_active = True
+
+ # Get hostboot status
+ if (hostboot_active == False):
+ if (sbe_fetch_failed == False):
+ hostboot_istep_major = sbe_istep_major
+ hostboot_istep_minor = sbe_istep_minor
+ hostboot_istep = sbe_istep
+ else:
+ proc = subprocess.Popen(["pdbg", "-b", "kernel", "-p0", "getcfam", "0x283c"], stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'), shell=False)
+ (out, err) = proc.communicate()
+ status_data = out.split("=")
+ if (len(status_data) > 1):
+ try:
+ binary_status_data = bin(int(status_data[1], 16))
+ except ValueError:
+ hostboot_fetch_failed = True
+
+ if (hostboot_fetch_failed == False):
+ try:
+ hostboot_istep_magic = int(binary_status_data[2:10], 2)
+ hostboot_istep_major = int(binary_status_data[18:26], 2)
+ hostboot_istep_minor = int(binary_status_data[26:34], 2)
+ except ValueError:
+ hostboot_fetch_failed = True
+ if (hostboot_fetch_failed == False):
+ if (hostboot_istep_magic != 170):
+ hostboot_istep_major = 0
+ hostboot_istep_minor = 0
+ hostboot_istep = str(hostboot_istep_major) + "," + str(hostboot_istep_minor)
+ else:
+ hostboot_fetch_failed = True
+
+ if ((sbe_fetch_failed == False) and (hostboot_fetch_failed == False)):
+ # Figure out system status
+ current_istep_major = sbe_istep_major
+ current_istep_minor = sbe_istep_minor
+ if (hostboot_istep_major > current_istep_major):
+ current_istep_major = hostboot_istep_major
+ if (hostboot_istep_minor > current_istep_minor):
+ current_istep_minor = hostboot_istep_minor
+ current_istep = str(current_istep_major) + "," + str(current_istep_minor)
+
+ # Asseble status strings
+ current_status = "OFFLINE"
+ if ((current_istep_major > 0) or (current_istep_minor > 0 )):
+ current_status = "IPL_RUNNING"
+ if ((current_istep_major == IPL_COMPLETE_ISTEP_MAJOR) and (current_istep_minor == IPL_COMPLETE_ISTEP_MINOR)):
+ current_status = "IPL_COMPLETE"
+
+ # Reset failure counter
+ self.prev_access_fail_count = 0
+ else:
+ # Increment failure counter
+ if (self.prev_access_fail_count < 255):
+ self.prev_access_fail_count += 1
+
+ # Since it is extremely unlikely that both fetches will fail unless the host is offline, simply check that both fetches passed or failed before continuing
+ if (sbe_fetch_failed == hostboot_fetch_failed):
+ # Check error results multiple times before signalling unexpected offline status
+ if ((current_status == "OFFLINE") and (self.prev_access_fail_count < 10)):
+ return True
+
+ # Publish status
+ if (self.last_status != current_status):
+ self.Set(DBUS_NAME, "current_status", current_status)
+ self.IPLStatusChanged(current_status)
+ self.last_status = current_status
+ if (self.last_istep != current_istep):
+ self.Set(DBUS_NAME, "current_istep", current_istep)
+ self.IPLStepChanged(current_istep)
+ self.last_istep = current_istep
+
+ return True
+ except Exception as e:
+ print(e)
+ traceback.print_exc()
+ return True
+
+ def HostStatusChangeHandler(self, interface_name, changed_properties,
+ invalidated_properties):
+ value = changed_properties.get('CurrentHostState')
+ if value is not None:
+ if (value == HOST_STATUS_RUNNING):
+ self.activateMonitoring = True
+ else:
+ self.activateMonitoring = False
+
+ @dbus.service.method(DBUS_NAME, in_signature='', out_signature='s')
+ def getCurrentIPLStatus(self):
+ return self.Get(DBUS_NAME, "current_status")
+
+ @dbus.service.signal(DBUS_NAME)
+ def IPLStatusChanged(self, message):
+ # Signal is emitted on method return
+ pass
+
+ @dbus.service.method(DBUS_NAME, in_signature='', out_signature='s')
+ def getCurrentIPLIStep(self):
+ return self.Get(DBUS_NAME, "current_istep")
+
+ @dbus.service.signal(DBUS_NAME)
+ def IPLStepChanged(self, message):
+ # Signal is emitted on method return
+ pass
+
+ def NewObjectHandler(self, obj_path, iprops, bus_name=None):
+ current_istep = self.Get(DBUS_NAME, "current_istep")
+
+ if obj_path in System.EXIT_STATE_DEPEND[current_istep]:
+ print "New object: "+obj_path+" ("+bus_name+")"
+
+if __name__ == '__main__':
+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+ bus = get_dbus()
+ obj = IPLStatus(bus, OBJ_NAME)
+ mainloop = gobject.MainLoop()
+ obj.unmask_signals()
+ name = dbus.service.BusName(DBUS_NAME, bus)
+
+ print "Running IPLStatus"
+ mainloop.run()
+
+# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
diff --git a/pyiplobserver/setup.cfg b/pyiplobserver/setup.cfg
new file mode 120000
index 0000000..29939b5
--- /dev/null
+++ b/pyiplobserver/setup.cfg
@@ -0,0 +1 @@
+../setup.cfg \ No newline at end of file
diff --git a/pyiplobserver/setup.py b/pyiplobserver/setup.py
new file mode 100644
index 0000000..f2dd46b
--- /dev/null
+++ b/pyiplobserver/setup.py
@@ -0,0 +1,6 @@
+from distutils.core import setup
+
+setup(name='pyiplobserver',
+ version='1.0',
+ scripts=['ipl_status_observer.py'],
+ )
OpenPOWER on IntegriCloud