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