blob: 501aa5e40fb7f9901afc58341a7b00c2a1719346 [file] [log] [blame]
James Feist98b704e2019-06-03 16:24:53 -07001/*
2// Copyright (c) 2019 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
17#include "dbuspassiveredundancy.hpp"
18
James Feist98b704e2019-06-03 16:24:53 -070019#include <sdbusplus/bus.hpp>
20#include <sdbusplus/bus/match.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070021
22#include <iostream>
James Feist98b704e2019-06-03 16:24:53 -070023#include <set>
24#include <unordered_map>
25#include <variant>
26
Patrick Venturea0764872020-08-08 07:48:43 -070027namespace pid_control
28{
29
James Feist98b704e2019-06-03 16:24:53 -070030namespace properties
31{
32
33constexpr const char* interface = "org.freedesktop.DBus.Properties";
34constexpr const char* get = "Get";
35constexpr const char* getAll = "GetAll";
36
37} // namespace properties
38
39namespace redundancy
40{
41
42constexpr const char* collection = "Collection";
43constexpr const char* status = "Status";
44constexpr const char* interface = "xyz.openbmc_project.Control.FanRedundancy";
45
46} // namespace redundancy
47
Patrick Williamsb228bc32022-07-22 19:26:56 -050048DbusPassiveRedundancy::DbusPassiveRedundancy(sdbusplus::bus_t& bus) :
James Feist98b704e2019-06-03 16:24:53 -070049 match(bus,
50 "type='signal',member='PropertiesChanged',arg0namespace='" +
51 std::string(redundancy::interface) + "'",
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -060052
53 [this](sdbusplus::message_t& message) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -040054 std::string objectName;
55 std::unordered_map<
56 std::string,
57 std::variant<std::string, std::vector<std::string>>>
58 result;
59 try
60 {
61 message.read(objectName, result);
62 }
63 catch (const sdbusplus::exception_t&)
64 {
65 std::cerr << "Error reading match data";
66 return;
67 }
68 auto findStatus = result.find("Status");
69 if (findStatus == result.end())
70 {
71 return;
72 }
73 std::string status = std::get<std::string>(findStatus->second);
James Feist98b704e2019-06-03 16:24:53 -070074
Patrick Williamsbd63bca2024-08-16 15:21:10 -040075 auto methodCall = passiveBus.new_method_call(
76 message.get_sender(), message.get_path(),
77 properties::interface, properties::get);
78 methodCall.append(redundancy::interface, redundancy::collection);
79 std::variant<std::vector<std::string>> collection;
James Feist98b704e2019-06-03 16:24:53 -070080
Patrick Williamsbd63bca2024-08-16 15:21:10 -040081 try
82 {
83 auto reply = passiveBus.call(methodCall);
84 reply.read(collection);
85 }
86 catch (const sdbusplus::exception_t&)
87 {
88 std::cerr << "Error reading match data";
89 return;
90 }
James Feist98b704e2019-06-03 16:24:53 -070091
Patrick Williamsbd63bca2024-08-16 15:21:10 -040092 auto data = std::get<std::vector<std::string>>(collection);
93 if (status.rfind("Failed") != std::string::npos)
94 {
95 failed.insert(data.begin(), data.end());
96 }
97 else
98 {
99 for (const auto& d : data)
100 {
101 failed.erase(d);
102 }
103 }
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -0600104 }),
Patrick Williamse1dbb592023-10-20 11:19:22 -0500105 passiveBus(bus)
James Feist98b704e2019-06-03 16:24:53 -0700106{
107 populateFailures();
108}
109
110void DbusPassiveRedundancy::populateFailures(void)
111{
112 auto mapper = passiveBus.new_method_call(
113 "xyz.openbmc_project.ObjectMapper",
114 "/xyz/openbmc_project/object_mapper",
115 "xyz.openbmc_project.ObjectMapper", "GetSubTree");
116 mapper.append("/", 0, std::array<const char*, 1>{redundancy::interface});
117 std::unordered_map<
118 std::string, std::unordered_map<std::string, std::vector<std::string>>>
119 respData;
120 try
121 {
122 auto resp = passiveBus.call(mapper);
123 resp.read(respData);
124 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500125 catch (const sdbusplus::exception_t&)
James Feist98b704e2019-06-03 16:24:53 -0700126 {
127 std::cerr << "Populate Failures Mapper Error\n";
128 return;
129 }
130
131 /*
132 * The subtree response looks like:
133 * {path :
134 * {busname:
135 * {interface, interface, interface, ...}
136 * }
137 * }
138 *
Manojkiran Eda7ca88872024-06-17 11:55:48 +0530139 * This loops through this structure to pre-populate the already failed
140 * items
James Feist98b704e2019-06-03 16:24:53 -0700141 */
142
143 for (const auto& [path, interfaceDict] : respData)
144 {
145 for (const auto& [owner, _] : interfaceDict)
146 {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400147 auto call = passiveBus.new_method_call(
148 owner.c_str(), path.c_str(), properties::interface,
149 properties::getAll);
James Feist98b704e2019-06-03 16:24:53 -0700150 call.append(redundancy::interface);
151
152 std::unordered_map<
153 std::string,
154 std::variant<std::string, std::vector<std::string>>>
155 getAll;
156 try
157 {
158 auto data = passiveBus.call(call);
159 data.read(getAll);
160 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500161 catch (const sdbusplus::exception_t&)
James Feist98b704e2019-06-03 16:24:53 -0700162 {
163 std::cerr << "Populate Failures Mapper Error\n";
164 return;
165 }
166 std::string status =
167 std::get<std::string>(getAll[redundancy::status]);
168 if (status.rfind("Failed") == std::string::npos)
169 {
170 continue;
171 }
172 std::vector<std::string> collection =
173 std::get<std::vector<std::string>>(
174 getAll[redundancy::collection]);
175 failed.insert(collection.begin(), collection.end());
176 }
177 }
178}
179
180const std::set<std::string>& DbusPassiveRedundancy::getFailed()
181{
182 return failed;
Patrick Venturea0764872020-08-08 07:48:43 -0700183}
184
185} // namespace pid_control