1 /*
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 */
16 /// \file entity_manager.hpp
17
18 #pragma once
19
20 #include "utils.hpp"
21
22 #include <systemd/sd-journal.h>
23
24 #include <boost/container/flat_map.hpp>
25 #include <nlohmann/json.hpp>
26 #include <sdbusplus/asio/object_server.hpp>
27
28 #include <iostream>
29 #include <list>
30 #include <optional>
31 #include <string>
32
33 struct DBusDeviceDescriptor
34 {
35 DBusInterface interface;
36 std::string path;
37 };
38
39 using FoundDevices = std::vector<DBusDeviceDescriptor>;
40
41 struct CmpStr
42 {
operator ()CmpStr43 bool operator()(const char* a, const char* b) const
44 {
45 return std::strcmp(a, b) < 0;
46 }
47 };
48
49 // underscore T for collison with dbus c api
50 enum class probe_type_codes
51 {
52 FALSE_T,
53 TRUE_T,
54 AND,
55 OR,
56 FOUND,
57 MATCH_ONE
58 };
59
60 using FoundProbeTypeT =
61 std::optional<boost::container::flat_map<const char*, probe_type_codes,
62 CmpStr>::const_iterator>;
63 FoundProbeTypeT findProbeType(const std::string& probe);
64
65 struct PerformScan : std::enable_shared_from_this<PerformScan>
66 {
67 PerformScan(nlohmann::json& systemConfiguration,
68 nlohmann::json& missingConfigurations,
69 std::list<nlohmann::json>& configurations,
70 sdbusplus::asio::object_server& objServer,
71 std::function<void()>&& callback);
72 void updateSystemConfiguration(const nlohmann::json& recordRef,
73 const std::string& probeName,
74 FoundDevices& foundDevices);
75 void run();
76 virtual ~PerformScan();
77 nlohmann::json& _systemConfiguration;
78 nlohmann::json& _missingConfigurations;
79 std::list<nlohmann::json> _configurations;
80 sdbusplus::asio::object_server& objServer;
81 std::function<void()> _callback;
82 bool _passed = false;
83 MapperGetSubTreeResponse dbusProbeObjects;
84 std::vector<std::string> passedProbes;
85 };
86
87 // this class finds the needed dbus fields and on destruction runs the probe
88 struct PerformProbe : std::enable_shared_from_this<PerformProbe>
89 {
90 PerformProbe(nlohmann::json& recordRef,
91 const std::vector<std::string>& probeCommand,
92 std::string probeName, std::shared_ptr<PerformScan>& scanPtr);
93 virtual ~PerformProbe();
94
95 nlohmann::json& recordRef;
96 std::vector<std::string> _probeCommand;
97 std::string probeName;
98 std::shared_ptr<PerformScan> scan;
99 };
100
logDeviceAdded(const nlohmann::json & record)101 inline void logDeviceAdded(const nlohmann::json& record)
102 {
103 if (!deviceHasLogging(record))
104 {
105 return;
106 }
107 auto findType = record.find("Type");
108 auto findAsset =
109 record.find("xyz.openbmc_project.Inventory.Decorator.Asset");
110
111 std::string model = "Unknown";
112 std::string type = "Unknown";
113 std::string sn = "Unknown";
114 std::string name = "Unknown";
115
116 if (findType != record.end())
117 {
118 type = findType->get<std::string>();
119 }
120 if (findAsset != record.end())
121 {
122 auto findModel = findAsset->find("Model");
123 auto findSn = findAsset->find("SerialNumber");
124 if (findModel != findAsset->end())
125 {
126 model = findModel->get<std::string>();
127 }
128 if (findSn != findAsset->end())
129 {
130 const std::string* getSn = findSn->get_ptr<const std::string*>();
131 if (getSn != nullptr)
132 {
133 sn = *getSn;
134 }
135 else
136 {
137 sn = findSn->dump();
138 }
139 }
140 }
141
142 auto findName = record.find("Name");
143 if (findName != record.end())
144 {
145 name = findName->get<std::string>();
146 }
147
148 sd_journal_send("MESSAGE=Inventory Added: %s", name.c_str(), "PRIORITY=%i",
149 LOG_INFO, "REDFISH_MESSAGE_ID=%s",
150 "OpenBMC.0.1.InventoryAdded",
151 "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
152 type.c_str(), sn.c_str(), "NAME=%s", name.c_str(), NULL);
153 }
154
logDeviceRemoved(const nlohmann::json & record)155 inline void logDeviceRemoved(const nlohmann::json& record)
156 {
157 if (!deviceHasLogging(record))
158 {
159 return;
160 }
161 auto findType = record.find("Type");
162 auto findAsset =
163 record.find("xyz.openbmc_project.Inventory.Decorator.Asset");
164
165 std::string model = "Unknown";
166 std::string type = "Unknown";
167 std::string sn = "Unknown";
168 std::string name = "Unknown";
169
170 if (findType != record.end())
171 {
172 type = findType->get<std::string>();
173 }
174 if (findAsset != record.end())
175 {
176 auto findModel = findAsset->find("Model");
177 auto findSn = findAsset->find("SerialNumber");
178 if (findModel != findAsset->end())
179 {
180 model = findModel->get<std::string>();
181 }
182 if (findSn != findAsset->end())
183 {
184 const std::string* getSn = findSn->get_ptr<const std::string*>();
185 if (getSn != nullptr)
186 {
187 sn = *getSn;
188 }
189 else
190 {
191 sn = findSn->dump();
192 }
193 }
194 }
195
196 auto findName = record.find("Name");
197 if (findName != record.end())
198 {
199 name = findName->get<std::string>();
200 }
201
202 sd_journal_send("MESSAGE=Inventory Removed: %s", name.c_str(),
203 "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
204 "OpenBMC.0.1.InventoryRemoved",
205 "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
206 type.c_str(), sn.c_str(), "NAME=%s", name.c_str(), NULL);
207 }
208