1#!/usr/bin/env python
2
3import os
4import sys
5
6# TODO: openbmc/openbmc#2994 remove python 2 support
7try:  # python 2
8    import gobject
9except ImportError:  # python 3
10    from gi.repository import GObject as gobject
11import dbus
12import dbus.service
13import dbus.mainloop.glib
14import obmc.dbuslib.propertycacher as PropertyCacher
15from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager
16
17
18INTF_NAME = "org.openbmc.InventoryItem"
19DBUS_NAME = "org.openbmc.Inventory"
20
21FRUS = {}
22
23
24class Inventory(DbusProperties, DbusObjectManager):
25    def __init__(self, bus, name):
26        super(Inventory, self).__init__(conn=bus, object_path=name)
27
28
29class InventoryItem(DbusProperties):
30    def __init__(self, bus, name, data):
31        super(InventoryItem, self).__init__(conn=bus, object_path=name)
32
33        self.name = name
34
35        if "present" not in data:
36            data["present"] = "False"
37        if "fault" not in data:
38            data["fault"] = "False"
39        if "version" not in data:
40            data["version"] = ""
41
42        self.SetMultiple(INTF_NAME, data)
43
44        # this will load properties from cache
45        PropertyCacher.load(name, INTF_NAME, self.properties)
46
47    @dbus.service.method(INTF_NAME, in_signature="a{sv}", out_signature="")
48    def update(self, data):
49        self.SetMultiple(INTF_NAME, data)
50        PropertyCacher.save(self.name, INTF_NAME, self.properties)
51
52    @dbus.service.method(INTF_NAME, in_signature="s", out_signature="")
53    def setPresent(self, present):
54        self.Set(INTF_NAME, "present", present)
55        PropertyCacher.save(self.name, INTF_NAME, self.properties)
56
57    @dbus.service.method(INTF_NAME, in_signature="s", out_signature="")
58    def setFault(self, fault):
59        self.Set(INTF_NAME, "fault", fault)
60        PropertyCacher.save(self.name, INTF_NAME, self.properties)
61
62
63def getVersion():
64    version = "Error"
65    with open("/etc/os-release", "r") as f:
66        for line in f:
67            p = line.rstrip("\n")
68            parts = line.rstrip("\n").split("=")
69            if parts[0] == "VERSION_ID":
70                version = parts[1]
71                version = version.strip('"')
72    return version
73
74
75if __name__ == "__main__":
76    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
77    bus = get_dbus()
78    mainloop = gobject.MainLoop()
79    obj_parent = Inventory(bus, "/org/openbmc/inventory")
80    INVENTORY_FILE = os.path.join(
81        sys.prefix, "share", "inventory", "inventory.json"
82    )
83
84    if os.path.exists(INVENTORY_FILE):
85        import json
86
87        with open(INVENTORY_FILE, "r") as f:
88            try:
89                inv = json.load(f)
90            except ValueError:
91                print("Invalid JSON detected in " + INVENTORY_FILE)
92            else:
93                FRUS = inv
94    else:
95        try:
96            import obmc_system_config as System
97
98            FRUS = System.FRU_INSTANCES
99        except ImportError:
100            pass
101
102    for f in list(FRUS.keys()):
103        import obmc.inventory
104
105        obj_path = f.replace("<inventory_root>", obmc.inventory.INVENTORY_ROOT)
106        obj = InventoryItem(bus, obj_path, FRUS[f])
107        obj_parent.add(obj_path, obj)
108
109        # TODO:  this is a hack to update bmc inventory item with version
110        # should be done by flash object
111        if FRUS[f]["fru_type"] == "BMC":
112            version = getVersion()
113            obj.update({"version": version})
114
115    obj_parent.unmask_signals()
116    name = dbus.service.BusName(DBUS_NAME, bus)
117    print("Running Inventory Manager")
118    mainloop.run()
119
120# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
121