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 = std::optional<boost::container::flat_map<
61 const char*, probe_type_codes, CmpStr>::const_iterator>;
62 FoundProbeTypeT findProbeType(const std::string& probe);
63
64 struct PerformScan : std::enable_shared_from_this<PerformScan>
65 {
66 PerformScan(nlohmann::json& systemConfiguration,
67 nlohmann::json& missingConfigurations,
68 std::list<nlohmann::json>& configurations,
69 sdbusplus::asio::object_server& objServer,
70 std::function<void()>&& callback);
71 void updateSystemConfiguration(const nlohmann::json& recordRef,
72 const std::string& probeName,
73 FoundDevices& foundDevices);
74 void run();
75 virtual ~PerformScan();
76 nlohmann::json& _systemConfiguration;
77 nlohmann::json& _missingConfigurations;
78 std::list<nlohmann::json> _configurations;
79 sdbusplus::asio::object_server& objServer;
80 std::function<void()> _callback;
81 bool _passed = false;
82 MapperGetSubTreeResponse dbusProbeObjects;
83 std::vector<std::string> passedProbes;
84 };
85
86 // this class finds the needed dbus fields and on destruction runs the probe
87 struct PerformProbe : std::enable_shared_from_this<PerformProbe>
88 {
89 PerformProbe(nlohmann::json& recordRef,
90 const std::vector<std::string>& probeCommand,
91 std::string probeName, std::shared_ptr<PerformScan>& scanPtr);
92 virtual ~PerformProbe();
93
94 nlohmann::json& recordRef;
95 std::vector<std::string> _probeCommand;
96 std::string probeName;
97 std::shared_ptr<PerformScan> scan;
98 };
99
logDeviceAdded(const nlohmann::json & record)100 inline void logDeviceAdded(const nlohmann::json& record)
101 {
102 if (!deviceHasLogging(record))
103 {
104 return;
105 }
106 auto findType = record.find("Type");
107 auto findAsset =
108 record.find("xyz.openbmc_project.Inventory.Decorator.Asset");
109
110 std::string model = "Unknown";
111 std::string type = "Unknown";
112 std::string sn = "Unknown";
113 std::string name = "Unknown";
114
115 if (findType != record.end())
116 {
117 type = findType->get<std::string>();
118 }
119 if (findAsset != record.end())
120 {
121 auto findModel = findAsset->find("Model");
122 auto findSn = findAsset->find("SerialNumber");
123 if (findModel != findAsset->end())
124 {
125 model = findModel->get<std::string>();
126 }
127 if (findSn != findAsset->end())
128 {
129 const std::string* getSn = findSn->get_ptr<const std::string*>();
130 if (getSn != nullptr)
131 {
132 sn = *getSn;
133 }
134 else
135 {
136 sn = findSn->dump();
137 }
138 }
139 }
140
141 auto findName = record.find("Name");
142 if (findName != record.end())
143 {
144 name = findName->get<std::string>();
145 }
146
147 sd_journal_send("MESSAGE=Inventory Added: %s", name.c_str(), "PRIORITY=%i",
148 LOG_INFO, "REDFISH_MESSAGE_ID=%s",
149 "OpenBMC.0.1.InventoryAdded",
150 "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
151 type.c_str(), sn.c_str(), "NAME=%s", name.c_str(), NULL);
152 }
153
logDeviceRemoved(const nlohmann::json & record)154 inline void logDeviceRemoved(const nlohmann::json& record)
155 {
156 if (!deviceHasLogging(record))
157 {
158 return;
159 }
160 auto findType = record.find("Type");
161 auto findAsset =
162 record.find("xyz.openbmc_project.Inventory.Decorator.Asset");
163
164 std::string model = "Unknown";
165 std::string type = "Unknown";
166 std::string sn = "Unknown";
167 std::string name = "Unknown";
168
169 if (findType != record.end())
170 {
171 type = findType->get<std::string>();
172 }
173 if (findAsset != record.end())
174 {
175 auto findModel = findAsset->find("Model");
176 auto findSn = findAsset->find("SerialNumber");
177 if (findModel != findAsset->end())
178 {
179 model = findModel->get<std::string>();
180 }
181 if (findSn != findAsset->end())
182 {
183 const std::string* getSn = findSn->get_ptr<const std::string*>();
184 if (getSn != nullptr)
185 {
186 sn = *getSn;
187 }
188 else
189 {
190 sn = findSn->dump();
191 }
192 }
193 }
194
195 auto findName = record.find("Name");
196 if (findName != record.end())
197 {
198 name = findName->get<std::string>();
199 }
200
201 sd_journal_send("MESSAGE=Inventory Removed: %s", name.c_str(),
202 "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
203 "OpenBMC.0.1.InventoryRemoved",
204 "REDFISH_MESSAGE_ARGS=%s,%s,%s", model.c_str(),
205 type.c_str(), sn.c_str(), "NAME=%s", name.c_str(), NULL);
206 }
207