1 /**
2  * Copyright © 2017 IBM 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 #include "resolve_errors.hpp"
17 
18 #include "sdbusplus.hpp"
19 
20 #include <phosphor-logging/lg2.hpp>
21 
22 namespace phosphor
23 {
24 namespace dbus
25 {
26 namespace monitoring
27 {
28 
29 constexpr auto LOGGING_IFACE = "xyz.openbmc_project.Logging.Entry";
30 constexpr auto PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
31 constexpr auto ASSOCIATION_IFACE = "xyz.openbmc_project.Association";
32 constexpr auto ENDPOINTS_PROPERTY = "endpoints";
33 constexpr auto RESOLVED_PROPERTY = "Resolved";
34 
35 using EndpointList = std::vector<std::string>;
36 using EndpointsProperty = std::variant<EndpointList>;
37 
operator ()(Context)38 void ResolveCallout::operator()(Context /* ctx */)
39 {
40     // Resolve all errors for this callout:
41     // 1) Read the 'endpoints' property for the callout/fault object
42     //
43     // 2) Follow each endpoint to its log entry
44     //
45     // 3) Set the Resolved property to true on the entry
46 
47     try
48     {
49         auto path = callout + "/fault";
50         auto busName = SDBusPlus::getBusName(path, ASSOCIATION_IFACE);
51 
52         if (busName.empty())
53         {
54             // Just means there are no error logs with this callout
55             return;
56         }
57 
58         auto endpoints = SDBusPlus::callMethodAndRead<EndpointsProperty>(
59             busName, path, PROPERTY_IFACE, "Get", ASSOCIATION_IFACE,
60             ENDPOINTS_PROPERTY);
61 
62         const auto& logEntries = std::get<EndpointList>(endpoints);
63 
64         // Resolve each log entry
65         for (const auto& logEntry : logEntries)
66         {
67             resolve(logEntry);
68         }
69     }
70     catch (const std::exception& e)
71     {
72         lg2::error("Failed getting callout fault associations: {ERROR}, {PATH}",
73                    "ERROR", e, "PATH", callout);
74     }
75 }
76 
resolve(const std::string & logEntry)77 void ResolveCallout::resolve(const std::string& logEntry)
78 {
79     try
80     {
81         static std::string busName;
82         if (busName.empty())
83         {
84             busName = SDBusPlus::getBusName(logEntry, LOGGING_IFACE);
85             if (busName.empty())
86             {
87                 return;
88             }
89         }
90 
91         std::variant<bool> resolved = true;
92 
93         SDBusPlus::callMethod(busName, logEntry, PROPERTY_IFACE, "Set",
94                               LOGGING_IFACE, RESOLVED_PROPERTY, resolved);
95     }
96     catch (const std::exception& e)
97     {
98         lg2::error("Unable to resolve error log entry {ENTRY}: {ERROR}",
99                    "ENTRY", logEntry, "ERROR", e);
100     }
101 }
102 
103 } // namespace monitoring
104 } // namespace dbus
105 } // namespace phosphor
106