198b704e1SJames Feist /*
298b704e1SJames Feist // Copyright (c) 2019 Intel Corporation
398b704e1SJames Feist //
498b704e1SJames Feist // Licensed under the Apache License, Version 2.0 (the "License");
598b704e1SJames Feist // you may not use this file except in compliance with the License.
698b704e1SJames Feist // You may obtain a copy of the License at
798b704e1SJames Feist //
898b704e1SJames Feist // http://www.apache.org/licenses/LICENSE-2.0
998b704e1SJames Feist //
1098b704e1SJames Feist // Unless required by applicable law or agreed to in writing, software
1198b704e1SJames Feist // distributed under the License is distributed on an "AS IS" BASIS,
1298b704e1SJames Feist // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1398b704e1SJames Feist // See the License for the specific language governing permissions and
1498b704e1SJames Feist // limitations under the License.
1598b704e1SJames Feist */
1698b704e1SJames Feist
1798b704e1SJames Feist #include "dbuspassiveredundancy.hpp"
1898b704e1SJames Feist
1998b704e1SJames Feist #include <sdbusplus/bus.hpp>
2098b704e1SJames Feist #include <sdbusplus/bus/match.hpp>
21a83a3eccSPatrick Venture
22a83a3eccSPatrick Venture #include <iostream>
2398b704e1SJames Feist #include <set>
2498b704e1SJames Feist #include <unordered_map>
2598b704e1SJames Feist #include <variant>
2698b704e1SJames Feist
27a076487aSPatrick Venture namespace pid_control
28a076487aSPatrick Venture {
29a076487aSPatrick Venture
3098b704e1SJames Feist namespace properties
3198b704e1SJames Feist {
3298b704e1SJames Feist
3398b704e1SJames Feist constexpr const char* interface = "org.freedesktop.DBus.Properties";
3498b704e1SJames Feist constexpr const char* get = "Get";
3598b704e1SJames Feist constexpr const char* getAll = "GetAll";
3698b704e1SJames Feist
3798b704e1SJames Feist } // namespace properties
3898b704e1SJames Feist
3998b704e1SJames Feist namespace redundancy
4098b704e1SJames Feist {
4198b704e1SJames Feist
4298b704e1SJames Feist constexpr const char* collection = "Collection";
4398b704e1SJames Feist constexpr const char* status = "Status";
4498b704e1SJames Feist constexpr const char* interface = "xyz.openbmc_project.Control.FanRedundancy";
4598b704e1SJames Feist
4698b704e1SJames Feist } // namespace redundancy
4798b704e1SJames Feist
DbusPassiveRedundancy(sdbusplus::bus_t & bus)48b228bc30SPatrick Williams DbusPassiveRedundancy::DbusPassiveRedundancy(sdbusplus::bus_t& bus) :
4998b704e1SJames Feist match(bus,
5098b704e1SJames Feist "type='signal',member='PropertiesChanged',arg0namespace='" +
5198b704e1SJames Feist std::string(redundancy::interface) + "'",
522922eebeSJayanth Othayoth
532922eebeSJayanth Othayoth [this](sdbusplus::message_t& message) {
5498b704e1SJames Feist std::string objectName;
55bd63bcacSPatrick Williams std::unordered_map<
56bd63bcacSPatrick Williams std::string,
5798b704e1SJames Feist std::variant<std::string, std::vector<std::string>>>
5898b704e1SJames Feist result;
5998b704e1SJames Feist try
6098b704e1SJames Feist {
6198b704e1SJames Feist message.read(objectName, result);
6298b704e1SJames Feist }
630001ee02SPatrick Williams catch (const sdbusplus::exception_t&)
6498b704e1SJames Feist {
6598b704e1SJames Feist std::cerr << "Error reading match data";
6698b704e1SJames Feist return;
6798b704e1SJames Feist }
6898b704e1SJames Feist auto findStatus = result.find("Status");
6998b704e1SJames Feist if (findStatus == result.end())
7098b704e1SJames Feist {
7198b704e1SJames Feist return;
7298b704e1SJames Feist }
7398b704e1SJames Feist std::string status = std::get<std::string>(findStatus->second);
7498b704e1SJames Feist
75bd63bcacSPatrick Williams auto methodCall = passiveBus.new_method_call(
76bd63bcacSPatrick Williams message.get_sender(), message.get_path(),
7798b704e1SJames Feist properties::interface, properties::get);
7898b704e1SJames Feist methodCall.append(redundancy::interface, redundancy::collection);
7998b704e1SJames Feist std::variant<std::vector<std::string>> collection;
8098b704e1SJames Feist
8198b704e1SJames Feist try
8298b704e1SJames Feist {
8398b704e1SJames Feist auto reply = passiveBus.call(methodCall);
8498b704e1SJames Feist reply.read(collection);
8598b704e1SJames Feist }
860001ee02SPatrick Williams catch (const sdbusplus::exception_t&)
8798b704e1SJames Feist {
8898b704e1SJames Feist std::cerr << "Error reading match data";
8998b704e1SJames Feist return;
9098b704e1SJames Feist }
9198b704e1SJames Feist
9298b704e1SJames Feist auto data = std::get<std::vector<std::string>>(collection);
9398b704e1SJames Feist if (status.rfind("Failed") != std::string::npos)
9498b704e1SJames Feist {
9598b704e1SJames Feist failed.insert(data.begin(), data.end());
9698b704e1SJames Feist }
9798b704e1SJames Feist else
9898b704e1SJames Feist {
9998b704e1SJames Feist for (const auto& d : data)
10098b704e1SJames Feist {
10198b704e1SJames Feist failed.erase(d);
10298b704e1SJames Feist }
10398b704e1SJames Feist }
1042922eebeSJayanth Othayoth }),
10598b704e1SJames Feist passiveBus(bus)
10698b704e1SJames Feist {
10798b704e1SJames Feist populateFailures();
10898b704e1SJames Feist }
10998b704e1SJames Feist
populateFailures(void)11098b704e1SJames Feist void DbusPassiveRedundancy::populateFailures(void)
11198b704e1SJames Feist {
11298b704e1SJames Feist auto mapper = passiveBus.new_method_call(
11398b704e1SJames Feist "xyz.openbmc_project.ObjectMapper",
11498b704e1SJames Feist "/xyz/openbmc_project/object_mapper",
11598b704e1SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree");
11698b704e1SJames Feist mapper.append("/", 0, std::array<const char*, 1>{redundancy::interface});
11798b704e1SJames Feist std::unordered_map<
11898b704e1SJames Feist std::string, std::unordered_map<std::string, std::vector<std::string>>>
11998b704e1SJames Feist respData;
12098b704e1SJames Feist try
12198b704e1SJames Feist {
12298b704e1SJames Feist auto resp = passiveBus.call(mapper);
12398b704e1SJames Feist resp.read(respData);
12498b704e1SJames Feist }
1250001ee02SPatrick Williams catch (const sdbusplus::exception_t&)
12698b704e1SJames Feist {
12798b704e1SJames Feist std::cerr << "Populate Failures Mapper Error\n";
12898b704e1SJames Feist return;
12998b704e1SJames Feist }
13098b704e1SJames Feist
13198b704e1SJames Feist /*
13298b704e1SJames Feist * The subtree response looks like:
13398b704e1SJames Feist * {path :
13498b704e1SJames Feist * {busname:
13598b704e1SJames Feist * {interface, interface, interface, ...}
13698b704e1SJames Feist * }
13798b704e1SJames Feist * }
13898b704e1SJames Feist *
139*7ca8887cSManojkiran Eda * This loops through this structure to pre-populate the already failed
140*7ca8887cSManojkiran Eda * items
14198b704e1SJames Feist */
14298b704e1SJames Feist
14398b704e1SJames Feist for (const auto& [path, interfaceDict] : respData)
14498b704e1SJames Feist {
14598b704e1SJames Feist for (const auto& [owner, _] : interfaceDict)
14698b704e1SJames Feist {
147bd63bcacSPatrick Williams auto call = passiveBus.new_method_call(
148bd63bcacSPatrick Williams owner.c_str(), path.c_str(), properties::interface,
14998b704e1SJames Feist properties::getAll);
15098b704e1SJames Feist call.append(redundancy::interface);
15198b704e1SJames Feist
15298b704e1SJames Feist std::unordered_map<
15398b704e1SJames Feist std::string,
15498b704e1SJames Feist std::variant<std::string, std::vector<std::string>>>
15598b704e1SJames Feist getAll;
15698b704e1SJames Feist try
15798b704e1SJames Feist {
15898b704e1SJames Feist auto data = passiveBus.call(call);
15998b704e1SJames Feist data.read(getAll);
16098b704e1SJames Feist }
1610001ee02SPatrick Williams catch (const sdbusplus::exception_t&)
16298b704e1SJames Feist {
16398b704e1SJames Feist std::cerr << "Populate Failures Mapper Error\n";
16498b704e1SJames Feist return;
16598b704e1SJames Feist }
16698b704e1SJames Feist std::string status =
16798b704e1SJames Feist std::get<std::string>(getAll[redundancy::status]);
16898b704e1SJames Feist if (status.rfind("Failed") == std::string::npos)
16998b704e1SJames Feist {
17098b704e1SJames Feist continue;
17198b704e1SJames Feist }
17298b704e1SJames Feist std::vector<std::string> collection =
17398b704e1SJames Feist std::get<std::vector<std::string>>(
17498b704e1SJames Feist getAll[redundancy::collection]);
17598b704e1SJames Feist failed.insert(collection.begin(), collection.end());
17698b704e1SJames Feist }
17798b704e1SJames Feist }
17898b704e1SJames Feist }
17998b704e1SJames Feist
getFailed()18098b704e1SJames Feist const std::set<std::string>& DbusPassiveRedundancy::getFailed()
18198b704e1SJames Feist {
18298b704e1SJames Feist return failed;
18398b704e1SJames Feist }
184a076487aSPatrick Venture
185a076487aSPatrick Venture } // namespace pid_control
186