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/log.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 = "org.openbmc.Association";
32 constexpr auto ENDPOINTS_PROPERTY = "endpoints";
33 constexpr auto RESOLVED_PROPERTY = "Resolved";
34 
35 using namespace phosphor::logging;
36 using EndpointList = std::vector<std::string>;
37 using EndpointsProperty = sdbusplus::message::variant<EndpointList>;
38 
39 void ResolveCallout::operator()(Context ctx)
40 {
41     // Resolve all errors for this callout:
42     // 1) Read the 'endpoints' property for the callout/fault object
43     //
44     // 2) Follow each endpoint to its log entry
45     //
46     // 3) Set the Resolved property to true on the entry
47 
48     try
49     {
50         auto path = callout + "/fault";
51         auto busName = SDBusPlus::getBusName(path, ASSOCIATION_IFACE);
52 
53         if (busName.empty())
54         {
55             // Just means there are no error logs with this callout
56             return;
57         }
58 
59         auto endpoints = SDBusPlus::callMethodAndRead<EndpointsProperty>(
60             busName, path, PROPERTY_IFACE, "Get", ASSOCIATION_IFACE,
61             ENDPOINTS_PROPERTY);
62 
63         const auto& logEntries =
64             sdbusplus::message::variant_ns::get<EndpointList>(endpoints);
65 
66         // Resolve each log entry
67         for (const auto& logEntry : logEntries)
68         {
69             resolve(logEntry);
70         }
71     }
72     catch (const std::exception& e)
73     {
74         log<level::ERR>("Failed getting callout fault associations",
75                         entry("CALLOUT=%s", callout.c_str()),
76                         entry("ERROR=%s", e.what()));
77     }
78 }
79 
80 void ResolveCallout::resolve(const std::string& logEntry)
81 {
82     try
83     {
84         static std::string busName;
85         if (busName.empty())
86         {
87             busName = SDBusPlus::getBusName(logEntry, LOGGING_IFACE);
88             if (busName.empty())
89             {
90                 return;
91             }
92         }
93 
94         sdbusplus::message::variant<bool> resolved = true;
95 
96         auto response =
97             SDBusPlus::callMethod(busName, logEntry, PROPERTY_IFACE, "Set",
98                                   LOGGING_IFACE, RESOLVED_PROPERTY, resolved);
99 
100         if (response.is_method_error())
101         {
102             log<level::ERR>(
103                 "Failed to set Resolved property on an error log entry",
104                 entry("ENTRY=%s", logEntry.c_str()));
105         }
106     }
107     catch (const std::exception& e)
108     {
109         log<level::ERR>("Unable to resolve error log entry",
110                         entry("ENTRY=%s", logEntry.c_str()),
111                         entry("ERROR=%s", e.what()));
112     }
113 }
114 
115 } // namespace monitoring
116 } // namespace dbus
117 } // namespace phosphor
118