blob: 8aa8935efbed858c6c74d479f2ddaa628ef9e08f [file] [log] [blame]
James Feist1df06a42019-04-11 14:23:04 -07001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
Brad Bishope45d8c72022-05-25 15:12:53 -040016/// \file entity_manager.hpp
James Feist1df06a42019-04-11 14:23:04 -070017
18#pragma once
19
Christopher Meisfc9e7fd2025-04-03 13:13:35 +020020#include "../utils.hpp"
Christopher Meisf7252572025-06-11 13:22:05 +020021#include "configuration.hpp"
Alexander Hansen57604ed2025-06-27 13:22:28 +020022#include "dbus_interface.hpp"
Alexander Hansen0ab32b32025-06-27 14:50:33 +020023#include "power_status_monitor.hpp"
Christopher Meiscf6a75b2025-06-03 07:53:50 +020024#include "topology.hpp"
James Feist733f7652019-11-13 14:32:29 -080025
James Feist1df06a42019-04-11 14:23:04 -070026#include <systemd/sd-journal.h>
27
James Feist733f7652019-11-13 14:32:29 -080028#include <boost/container/flat_map.hpp>
James Feist1a996582019-05-14 15:10:06 -070029#include <nlohmann/json.hpp>
Christopher Meiscf6a75b2025-06-03 07:53:50 +020030#include <sdbusplus/asio/connection.hpp>
James Feist4dc617b2020-05-01 09:54:47 -070031#include <sdbusplus/asio/object_server.hpp>
James Feist8c505da2020-05-28 10:06:33 -070032
James Feist1df06a42019-04-11 14:23:04 -070033#include <string>
34
Christopher Meiscf6a75b2025-06-03 07:53:50 +020035class EntityManager
36{
37 public:
38 explicit EntityManager(
Alexander Hansena555acf2025-06-27 11:59:10 +020039 std::shared_ptr<sdbusplus::asio::connection>& systemBus,
40 boost::asio::io_context& io);
Christopher Meiscf6a75b2025-06-03 07:53:50 +020041
Alexander Hansen3b7678c2025-07-22 18:33:23 +020042 // disable copy
43 EntityManager(const EntityManager&) = delete;
44 EntityManager& operator=(const EntityManager&) = delete;
45
46 // disable move
47 EntityManager(EntityManager&&) = delete;
48 EntityManager& operator=(EntityManager&&) = delete;
49
50 ~EntityManager() = default;
51
Christopher Meiscf6a75b2025-06-03 07:53:50 +020052 std::shared_ptr<sdbusplus::asio::connection> systemBus;
53 sdbusplus::asio::object_server objServer;
54 std::shared_ptr<sdbusplus::asio::dbus_interface> entityIface;
Christopher Meisf7252572025-06-11 13:22:05 +020055 Configuration configuration;
Christopher Meiscf6a75b2025-06-03 07:53:50 +020056 nlohmann::json lastJson;
57 nlohmann::json systemConfiguration;
58 Topology topology;
Alexander Hansena555acf2025-06-27 11:59:10 +020059 boost::asio::io_context& io;
Christopher Meiscf6a75b2025-06-03 07:53:50 +020060
Alexander Hansen57604ed2025-06-27 13:22:28 +020061 dbus_interface::EMDBusInterface dbus_interface;
62
Alexander Hansen0ab32b32025-06-27 14:50:33 +020063 power::PowerStatusMonitor powerStatus;
64
Christopher Meiscf6a75b2025-06-03 07:53:50 +020065 void propertiesChangedCallback();
66 void registerCallback(const std::string& path);
67 void publishNewConfiguration(const size_t& instance, size_t count,
68 boost::asio::steady_timer& timer,
69 nlohmann::json newConfiguration);
70 void postToDbus(const nlohmann::json& newConfiguration);
71 void pruneConfiguration(bool powerOff, const std::string& name,
72 const nlohmann::json& device);
73
Alexander Hansenad28e402025-06-25 12:38:20 +020074 void handleCurrentConfigurationJson();
Alexander Hansen0f7bd782025-06-27 13:39:53 +020075
76 private:
77 std::unique_ptr<sdbusplus::bus::match_t> nameOwnerChangedMatch = nullptr;
78 std::unique_ptr<sdbusplus::bus::match_t> interfacesAddedMatch = nullptr;
79 std::unique_ptr<sdbusplus::bus::match_t> interfacesRemovedMatch = nullptr;
Alexander Hansen95ab18f2025-06-27 13:58:10 +020080
81 bool scannedPowerOff = false;
82 bool scannedPowerOn = false;
83
Alexander Hansen16d40022025-06-27 14:22:56 +020084 bool propertiesChangedInProgress = false;
Alexander Hansenb1340da2025-06-27 14:29:13 +020085 boost::asio::steady_timer propertiesChangedTimer;
Alexander Hansenfc1b1e22025-06-27 14:34:11 +020086 size_t propertiesChangedInstance = 0;
Alexander Hansen16d40022025-06-27 14:22:56 +020087
Alexander Hansen60803182025-06-27 14:41:28 +020088 boost::container::flat_map<std::string, sdbusplus::bus::match_t>
89 dbusMatches;
90
Alexander Hansen95ab18f2025-06-27 13:58:10 +020091 void startRemovedTimer(boost::asio::steady_timer& timer,
92 nlohmann::json& systemConfiguration);
Christopher Meisf7252572025-06-11 13:22:05 +020093 void initFilters(const std::unordered_set<std::string>& probeInterfaces);
Christopher Meiscf6a75b2025-06-03 07:53:50 +020094};
95
James Feist1a996582019-05-14 15:10:06 -070096inline void logDeviceAdded(const nlohmann::json& record)
James Feist1df06a42019-04-11 14:23:04 -070097{
James Feist1ffa4a42020-04-22 18:27:17 -070098 if (!deviceHasLogging(record))
99 {
100 return;
101 }
James Feist1a996582019-05-14 15:10:06 -0700102 auto findType = record.find("Type");
103 auto findAsset =
104 record.find("xyz.openbmc_project.Inventory.Decorator.Asset");
105
Konstantin Aladysheve7ac9c92021-09-10 09:20:17 +0300106 std::string model = "Unknown";
James Feist1a996582019-05-14 15:10:06 -0700107 std::string type = "Unknown";
Konstantin Aladysheve7ac9c92021-09-10 09:20:17 +0300108 std::string sn = "Unknown";
Matt Spinler200bf402022-08-04 09:14:18 -0500109 std::string name = "Unknown";
James Feist1a996582019-05-14 15:10:06 -0700110
111 if (findType != record.end())
112 {
113 type = findType->get<std::string>();
114 }
115 if (findAsset != record.end())
116 {
117 auto findModel = findAsset->find("Model");
118 auto findSn = findAsset->find("SerialNumber");
119 if (findModel != findAsset->end())
120 {
121 model = findModel->get<std::string>();
122 }
123 if (findSn != findAsset->end())
124 {
James Feistf5125b02019-06-06 11:27:43 -0700125 const std::string* getSn = findSn->get_ptr<const std::string*>();
126 if (getSn != nullptr)
127 {
128 sn = *getSn;
129 }
130 else
131 {
132 sn = findSn->dump();
133 }
James Feist1a996582019-05-14 15:10:06 -0700134 }
135 }
136
Matt Spinler200bf402022-08-04 09:14:18 -0500137 auto findName = record.find("Name");
138 if (findName != record.end())
139 {
140 name = findName->get<std::string>();
141 }
142
143 sd_journal_send("MESSAGE=Inventory Added: %s", name.c_str(), "PRIORITY=%i",
144 LOG_INFO, "REDFISH_MESSAGE_ID=%s",
145 "OpenBMC.0.1.InventoryAdded",
James Feist1a996582019-05-14 15:10:06 -0700146 "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
Matt Spinler200bf402022-08-04 09:14:18 -0500147 type.c_str(), sn.c_str(), "NAME=%s", name.c_str(), NULL);
James Feist1df06a42019-04-11 14:23:04 -0700148}
149
James Feist1a996582019-05-14 15:10:06 -0700150inline void logDeviceRemoved(const nlohmann::json& record)
James Feist1df06a42019-04-11 14:23:04 -0700151{
James Feist1ffa4a42020-04-22 18:27:17 -0700152 if (!deviceHasLogging(record))
153 {
154 return;
155 }
James Feist1a996582019-05-14 15:10:06 -0700156 auto findType = record.find("Type");
157 auto findAsset =
158 record.find("xyz.openbmc_project.Inventory.Decorator.Asset");
159
Konstantin Aladysheve7ac9c92021-09-10 09:20:17 +0300160 std::string model = "Unknown";
James Feist1a996582019-05-14 15:10:06 -0700161 std::string type = "Unknown";
Konstantin Aladysheve7ac9c92021-09-10 09:20:17 +0300162 std::string sn = "Unknown";
Matt Spinler200bf402022-08-04 09:14:18 -0500163 std::string name = "Unknown";
James Feist1a996582019-05-14 15:10:06 -0700164
165 if (findType != record.end())
166 {
167 type = findType->get<std::string>();
168 }
169 if (findAsset != record.end())
170 {
171 auto findModel = findAsset->find("Model");
172 auto findSn = findAsset->find("SerialNumber");
173 if (findModel != findAsset->end())
174 {
175 model = findModel->get<std::string>();
176 }
177 if (findSn != findAsset->end())
178 {
James Feistf5125b02019-06-06 11:27:43 -0700179 const std::string* getSn = findSn->get_ptr<const std::string*>();
180 if (getSn != nullptr)
181 {
182 sn = *getSn;
183 }
184 else
185 {
186 sn = findSn->dump();
187 }
James Feist1a996582019-05-14 15:10:06 -0700188 }
189 }
James Feist1df06a42019-04-11 14:23:04 -0700190
Matt Spinler200bf402022-08-04 09:14:18 -0500191 auto findName = record.find("Name");
192 if (findName != record.end())
193 {
194 name = findName->get<std::string>();
195 }
196
197 sd_journal_send("MESSAGE=Inventory Removed: %s", name.c_str(),
198 "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
199 "OpenBMC.0.1.InventoryRemoved",
James Feist1a996582019-05-14 15:10:06 -0700200 "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
Matt Spinler200bf402022-08-04 09:14:18 -0500201 type.c_str(), sn.c_str(), "NAME=%s", name.c_str(), NULL);
James Feist4dc617b2020-05-01 09:54:47 -0700202}