diff options
author | Raptor Engineering Development Team <support@raptorengineering.com> | 2018-01-19 07:20:20 -0600 |
---|---|---|
committer | Raptor Engineering Development Team <support@raptorengineering.com> | 2019-04-19 10:26:09 +0000 |
commit | e4712537429cbd15fe555ba01e180a08e53a1f42 (patch) | |
tree | df179afbf0205795d081dfc421cf18e5b3be5f46 /pyiplobserver | |
parent | d7f9af037393ef5d0a57e12573145d0b7c2668a4 (diff) | |
download | talos-skeleton-e4712537429cbd15fe555ba01e180a08e53a1f42.tar.gz talos-skeleton-e4712537429cbd15fe555ba01e180a08e53a1f42.zip |
Add new IPL status observer and Talos LED driver
Diffstat (limited to 'pyiplobserver')
l--------- | pyiplobserver/Makefile | 1 | ||||
-rw-r--r-- | pyiplobserver/ipl_status_observer.py | 246 | ||||
l--------- | pyiplobserver/setup.cfg | 1 | ||||
-rw-r--r-- | pyiplobserver/setup.py | 6 |
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'], + ) |