blob: 2ccd4902bd89983714723adbfa3ebf78108cf0d0 [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>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070023
Ed Tanousf8b6e552025-06-27 13:27:50 -070024#include <array>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070025#include <iostream>
James Feist98b704e2019-06-03 16:24:53 -070026#include <set>
Ed Tanousf8b6e552025-06-27 13:27:50 -070027#include <string>
James Feist98b704e2019-06-03 16:24:53 -070028#include <unordered_map>
29#include <variant>
Ed Tanousf8b6e552025-06-27 13:27:50 -070030#include <vector>
James Feist98b704e2019-06-03 16:24:53 -070031
Patrick Venturea0764872020-08-08 07:48:43 -070032namespace pid_control
33{
34
James Feist98b704e2019-06-03 16:24:53 -070035namespace properties
36{
37
38constexpr const char* interface = "org.freedesktop.DBus.Properties";
39constexpr const char* get = "Get";
40constexpr const char* getAll = "GetAll";
41
42} // namespace properties
43
44namespace redundancy
45{
46
47constexpr const char* collection = "Collection";
48constexpr const char* status = "Status";
49constexpr const char* interface = "xyz.openbmc_project.Control.FanRedundancy";
50
51} // namespace redundancy
52
Patrick Williamsb228bc32022-07-22 19:26:56 -050053DbusPassiveRedundancy::DbusPassiveRedundancy(sdbusplus::bus_t& bus) :
James Feist98b704e2019-06-03 16:24:53 -070054 match(bus,
55 "type='signal',member='PropertiesChanged',arg0namespace='" +
56 std::string(redundancy::interface) + "'",
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -060057
58 [this](sdbusplus::message_t& message) {
Patrick Williamsbd63bca2024-08-16 15:21:10 -040059 std::string objectName;
60 std::unordered_map<
61 std::string,
62 std::variant<std::string, std::vector<std::string>>>
63 result;
64 try
65 {
66 message.read(objectName, result);
67 }
68 catch (const sdbusplus::exception_t&)
69 {
70 std::cerr << "Error reading match data";
71 return;
72 }
73 auto findStatus = result.find("Status");
74 if (findStatus == result.end())
75 {
76 return;
77 }
78 std::string status = std::get<std::string>(findStatus->second);
James Feist98b704e2019-06-03 16:24:53 -070079
Patrick Williamsbd63bca2024-08-16 15:21:10 -040080 auto methodCall = passiveBus.new_method_call(
81 message.get_sender(), message.get_path(),
82 properties::interface, properties::get);
83 methodCall.append(redundancy::interface, redundancy::collection);
84 std::variant<std::vector<std::string>> collection;
James Feist98b704e2019-06-03 16:24:53 -070085
Patrick Williamsbd63bca2024-08-16 15:21:10 -040086 try
87 {
88 auto reply = passiveBus.call(methodCall);
89 reply.read(collection);
90 }
91 catch (const sdbusplus::exception_t&)
92 {
93 std::cerr << "Error reading match data";
94 return;
95 }
James Feist98b704e2019-06-03 16:24:53 -070096
Patrick Williamsbd63bca2024-08-16 15:21:10 -040097 auto data = std::get<std::vector<std::string>>(collection);
98 if (status.rfind("Failed") != std::string::npos)
99 {
100 failed.insert(data.begin(), data.end());
101 }
102 else
103 {
104 for (const auto& d : data)
105 {
106 failed.erase(d);
107 }
108 }
Jayanth Othayoth2922eeb2024-12-08 07:47:37 -0600109 }),
Patrick Williamse1dbb592023-10-20 11:19:22 -0500110 passiveBus(bus)
James Feist98b704e2019-06-03 16:24:53 -0700111{
112 populateFailures();
113}
114
115void DbusPassiveRedundancy::populateFailures(void)
116{
117 auto mapper = passiveBus.new_method_call(
118 "xyz.openbmc_project.ObjectMapper",
119 "/xyz/openbmc_project/object_mapper",
120 "xyz.openbmc_project.ObjectMapper", "GetSubTree");
121 mapper.append("/", 0, std::array<const char*, 1>{redundancy::interface});
122 std::unordered_map<
123 std::string, std::unordered_map<std::string, std::vector<std::string>>>
124 respData;
125 try
126 {
127 auto resp = passiveBus.call(mapper);
128 resp.read(respData);
129 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500130 catch (const sdbusplus::exception_t&)
James Feist98b704e2019-06-03 16:24:53 -0700131 {
132 std::cerr << "Populate Failures Mapper Error\n";
133 return;
134 }
135
136 /*
137 * The subtree response looks like:
138 * {path :
139 * {busname:
140 * {interface, interface, interface, ...}
141 * }
142 * }
143 *
Manojkiran Eda7ca88872024-06-17 11:55:48 +0530144 * This loops through this structure to pre-populate the already failed
145 * items
James Feist98b704e2019-06-03 16:24:53 -0700146 */
147
148 for (const auto& [path, interfaceDict] : respData)
149 {
150 for (const auto& [owner, _] : interfaceDict)
151 {
Patrick Williamsbd63bca2024-08-16 15:21:10 -0400152 auto call = passiveBus.new_method_call(
153 owner.c_str(), path.c_str(), properties::interface,
154 properties::getAll);
James Feist98b704e2019-06-03 16:24:53 -0700155 call.append(redundancy::interface);
156
157 std::unordered_map<
158 std::string,
159 std::variant<std::string, std::vector<std::string>>>
160 getAll;
161 try
162 {
163 auto data = passiveBus.call(call);
164 data.read(getAll);
165 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500166 catch (const sdbusplus::exception_t&)
James Feist98b704e2019-06-03 16:24:53 -0700167 {
168 std::cerr << "Populate Failures Mapper Error\n";
169 return;
170 }
171 std::string status =
172 std::get<std::string>(getAll[redundancy::status]);
173 if (status.rfind("Failed") == std::string::npos)
174 {
175 continue;
176 }
177 std::vector<std::string> collection =
178 std::get<std::vector<std::string>>(
179 getAll[redundancy::collection]);
180 failed.insert(collection.begin(), collection.end());
181 }
182 }
183}
184
185const std::set<std::string>& DbusPassiveRedundancy::getFailed()
186{
187 return failed;
Patrick Venturea0764872020-08-08 07:48:43 -0700188}
189
190} // namespace pid_control