xref: /openbmc/phosphor-pid-control/dbus/dbuspassiveredundancy.cpp (revision 7ca8887ccbcf8b55c6cead875da70541073ff6b1)
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