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