blob: 76dded979370bc847fac9e0458b05fdc7cdfafa9 [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>
Ed Tanousf8b6e552025-06-27 13:27:50 -070021#include <sdbusplus/exception.hpp>
22#include <sdbusplus/message.hpp>
Alexander Hansen1ec3d132025-10-27 17:19:50 +010023#include <xyz/openbmc_project/ObjectMapper/common.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070024
Ed Tanousf8b6e552025-06-27 13:27:50 -070025#include <array>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070026#include <iostream>
James Feist98b704e2019-06-03 16:24:53 -070027#include <set>
Ed Tanousf8b6e552025-06-27 13:27:50 -070028#include <string>
James Feist98b704e2019-06-03 16:24:53 -070029#include <unordered_map>
30#include <variant>
Ed Tanousf8b6e552025-06-27 13:27:50 -070031#include <vector>
James Feist98b704e2019-06-03 16:24:53 -070032
Alexander Hansen1ec3d132025-10-27 17:19:50 +010033using ObjectMapper = sdbusplus::common::xyz::openbmc_project::ObjectMapper;
34
Patrick Venturea0764872020-08-08 07:48:43 -070035namespace pid_control
36{
37
James Feist98b704e2019-06-03 16:24:53 -070038namespace properties
39{
40
41constexpr const char* interface = "org.freedesktop.DBus.Properties";
42constexpr const char* get = "Get";
43constexpr const char* getAll = "GetAll";
44
45} // namespace properties
46
47namespace redundancy
48{
49
50constexpr const char* collection = "Collection";
51constexpr const char* status = "Status";
52constexpr const char* interface = "xyz.openbmc_project.Control.FanRedundancy";
53
54} // namespace redundancy
55
Patrick Williamsb228bc32022-07-22 19:26:56 -050056DbusPassiveRedundancy::DbusPassiveRedundancy(sdbusplus::bus_t& bus) :
James Feist98b704e2019-06-03 16:24:53 -070057 match(bus,
58 "type='signal',member='PropertiesChanged',arg0namespace='" +
59 std::string(redundancy::interface) + "'",
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -060060
61 [this](sdbusplus::message_t& message) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -040062 std::string objectName;
63 std::unordered_map<
64 std::string,
65 std::variant<std::string, std::vector<std::string>>>
66 result;
67 try
68 {
69 message.read(objectName, result);
70 }
71 catch (const sdbusplus::exception_t&)
72 {
73 std::cerr << "Error reading match data";
74 return;
75 }
76 auto findStatus = result.find("Status");
77 if (findStatus == result.end())
78 {
79 return;
80 }
81 std::string status = std::get<std::string>(findStatus->second);
James Feist98b704e2019-06-03 16:24:53 -070082
Patrick Williamsbd63bca2024-08-16 15:21:10 -040083 auto methodCall = passiveBus.new_method_call(
84 message.get_sender(), message.get_path(),
85 properties::interface, properties::get);
86 methodCall.append(redundancy::interface, redundancy::collection);
87 std::variant<std::vector<std::string>> collection;
James Feist98b704e2019-06-03 16:24:53 -070088
Patrick Williamsbd63bca2024-08-16 15:21:10 -040089 try
90 {
91 auto reply = passiveBus.call(methodCall);
92 reply.read(collection);
93 }
94 catch (const sdbusplus::exception_t&)
95 {
96 std::cerr << "Error reading match data";
97 return;
98 }
James Feist98b704e2019-06-03 16:24:53 -070099
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400100 auto data = std::get<std::vector<std::string>>(collection);
101 if (status.rfind("Failed") != std::string::npos)
102 {
103 failed.insert(data.begin(), data.end());
104 }
105 else
106 {
107 for (const auto& d : data)
108 {
109 failed.erase(d);
110 }
111 }
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -0600112 }),
Patrick Williamse1dbb592023-10-20 11:19:22 -0500113 passiveBus(bus)
James Feist98b704e2019-06-03 16:24:53 -0700114{
115 populateFailures();
116}
117
118void DbusPassiveRedundancy::populateFailures(void)
119{
120 auto mapper = passiveBus.new_method_call(
Alexander Hansen1ec3d132025-10-27 17:19:50 +0100121 ObjectMapper::default_service, ObjectMapper::instance_path,
122 ObjectMapper::interface, ObjectMapper::method_names::get_sub_tree);
James Feist98b704e2019-06-03 16:24:53 -0700123 mapper.append("/", 0, std::array<const char*, 1>{redundancy::interface});
124 std::unordered_map<
125 std::string, std::unordered_map<std::string, std::vector<std::string>>>
126 respData;
127 try
128 {
129 auto resp = passiveBus.call(mapper);
130 resp.read(respData);
131 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500132 catch (const sdbusplus::exception_t&)
James Feist98b704e2019-06-03 16:24:53 -0700133 {
134 std::cerr << "Populate Failures Mapper Error\n";
135 return;
136 }
137
138 /*
139 * The subtree response looks like:
140 * {path :
141 * {busname:
142 * {interface, interface, interface, ...}
143 * }
144 * }
145 *
Manojkiran Eda7ca88872024-06-17 11:55:48 +0530146 * This loops through this structure to pre-populate the already failed
147 * items
James Feist98b704e2019-06-03 16:24:53 -0700148 */
149
150 for (const auto& [path, interfaceDict] : respData)
151 {
152 for (const auto& [owner, _] : interfaceDict)
153 {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400154 auto call = passiveBus.new_method_call(
155 owner.c_str(), path.c_str(), properties::interface,
156 properties::getAll);
James Feist98b704e2019-06-03 16:24:53 -0700157 call.append(redundancy::interface);
158
159 std::unordered_map<
160 std::string,
161 std::variant<std::string, std::vector<std::string>>>
162 getAll;
163 try
164 {
165 auto data = passiveBus.call(call);
166 data.read(getAll);
167 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500168 catch (const sdbusplus::exception_t&)
James Feist98b704e2019-06-03 16:24:53 -0700169 {
170 std::cerr << "Populate Failures Mapper Error\n";
171 return;
172 }
173 std::string status =
174 std::get<std::string>(getAll[redundancy::status]);
175 if (status.rfind("Failed") == std::string::npos)
176 {
177 continue;
178 }
179 std::vector<std::string> collection =
180 std::get<std::vector<std::string>>(
181 getAll[redundancy::collection]);
182 failed.insert(collection.begin(), collection.end());
183 }
184 }
185}
186
187const std::set<std::string>& DbusPassiveRedundancy::getFailed()
188{
189 return failed;
Patrick Venturea0764872020-08-08 07:48:43 -0700190}
191
192} // namespace pid_control