diff options
| author | James Feist <james.feist@linux.intel.com> | 2019-06-03 16:24:53 -0700 |
|---|---|---|
| committer | James Feist <james.feist@linux.intel.com> | 2019-06-05 17:21:16 +0000 |
| commit | 98b704e179f12d987179fe6b0ea6234d1bace48f (patch) | |
| tree | 860597ad14a89ed655fd0f46c2a7360f4a4805fe /dbus | |
| parent | 926411e10deeaff6e44b71ff4b80fa26e086965f (diff) | |
| download | phosphor-pid-control-98b704e179f12d987179fe6b0ea6234d1bace48f.tar.gz phosphor-pid-control-98b704e179f12d987179fe6b0ea6234d1bace48f.zip | |
Add Fan Redundancy Support
This adds fan redundancy support to passive sensors.
If there are redundancy interfaces on dbus, we'll fail
a sensor if the status is set to failed.
Tested: Set Redundancy to Failed On Dbus, saw all fans
in collection boost. Then restarted swampd, came up
and still boosted. Set redundancy OK, and they all slowed
down.
Change-Id: I8879bef1471bbc168435d6b22dd20006b9dca133
Signed-off-by: James Feist <james.feist@linux.intel.com>
Diffstat (limited to 'dbus')
| -rw-r--r-- | dbus/dbuspassive.cpp | 26 | ||||
| -rw-r--r-- | dbus/dbuspassive.hpp | 17 | ||||
| -rw-r--r-- | dbus/dbuspassiveredundancy.cpp | 177 | ||||
| -rw-r--r-- | dbus/dbuspassiveredundancy.hpp | 43 |
4 files changed, 252 insertions, 11 deletions
diff --git a/dbus/dbuspassive.cpp b/dbus/dbuspassive.cpp index a154b02..a0dbc57 100644 --- a/dbus/dbuspassive.cpp +++ b/dbus/dbuspassive.cpp @@ -15,6 +15,7 @@ */ #include "dbuspassive.hpp" +#include "dbuspassiveredundancy.hpp" #include "util.hpp" #include <chrono> @@ -27,7 +28,8 @@ std::unique_ptr<ReadInterface> DbusPassive::createDbusPassive( sdbusplus::bus::bus& bus, const std::string& type, const std::string& id, - DbusHelperInterface* helper, const conf::SensorConfig* info) + DbusHelperInterface* helper, const conf::SensorConfig* info, + const std::shared_ptr<DbusPassiveRedundancy>& redundancy) { if (helper == nullptr) { @@ -69,15 +71,19 @@ std::unique_ptr<ReadInterface> DbusPassive::createDbusPassive( } return std::make_unique<DbusPassive>(bus, type, id, helper, settings, - failed); + failed, path, redundancy); } -DbusPassive::DbusPassive(sdbusplus::bus::bus& bus, const std::string& type, - const std::string& id, DbusHelperInterface* helper, - const struct SensorProperties& settings, bool failed) : +DbusPassive::DbusPassive( + sdbusplus::bus::bus& bus, const std::string& type, const std::string& id, + DbusHelperInterface* helper, const struct SensorProperties& settings, + bool failed, const std::string& path, + const std::shared_ptr<DbusPassiveRedundancy>& redundancy) : ReadInterface(), _bus(bus), _signal(bus, getMatch(type, id).c_str(), dbusHandleSignal, this), - _id(id), _helper(helper), _failed(failed) + _id(id), _helper(helper), _failed(failed), path(path), + redundancy(redundancy) + { _scale = settings.scale; _value = settings.value * pow(10, _scale); @@ -105,6 +111,14 @@ void DbusPassive::setValue(double value) bool DbusPassive::getFailed(void) const { + if (redundancy) + { + const std::set<std::string>& failures = redundancy->getFailed(); + if (failures.find(path) != failures.end()) + { + return true; + } + } return _failed; } diff --git a/dbus/dbuspassive.hpp b/dbus/dbuspassive.hpp index ebc831d..f00a2ea 100644 --- a/dbus/dbuspassive.hpp +++ b/dbus/dbuspassive.hpp @@ -1,6 +1,7 @@ #pragma once #include "conf.hpp" +#include "dbuspassiveredundancy.hpp" #include "interfaces.hpp" #include "util.hpp" @@ -34,14 +35,17 @@ int dbusHandleSignal(sd_bus_message* msg, void* data, sd_bus_error* err); class DbusPassive : public ReadInterface { public: - static std::unique_ptr<ReadInterface> - createDbusPassive(sdbusplus::bus::bus& bus, const std::string& type, - const std::string& id, DbusHelperInterface* helper, - const conf::SensorConfig* info); + static std::unique_ptr<ReadInterface> createDbusPassive( + sdbusplus::bus::bus& bus, const std::string& type, + const std::string& id, DbusHelperInterface* helper, + const conf::SensorConfig* info, + const std::shared_ptr<DbusPassiveRedundancy>& redundancy); DbusPassive(sdbusplus::bus::bus& bus, const std::string& type, const std::string& id, DbusHelperInterface* helper, - const struct SensorProperties& settings, bool failed); + const struct SensorProperties& settings, bool failed, + const std::string& path, + const std::shared_ptr<DbusPassiveRedundancy>& redundancy); ReadReturn read(void) override; bool getFailed(void) const override; @@ -65,6 +69,9 @@ class DbusPassive : public ReadInterface double _max = 0; double _min = 0; bool _failed = false; + + std::string path; + std::shared_ptr<DbusPassiveRedundancy> redundancy; /* The last time the value was refreshed, not necessarily changed. */ std::chrono::high_resolution_clock::time_point _updated; }; diff --git a/dbus/dbuspassiveredundancy.cpp b/dbus/dbuspassiveredundancy.cpp new file mode 100644 index 0000000..c7a1d0f --- /dev/null +++ b/dbus/dbuspassiveredundancy.cpp @@ -0,0 +1,177 @@ +/* +// Copyright (c) 2019 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#include "dbuspassiveredundancy.hpp" + +#include <iostream> +#include <sdbusplus/bus.hpp> +#include <sdbusplus/bus/match.hpp> +#include <set> +#include <unordered_map> +#include <variant> + +namespace properties +{ + +constexpr const char* interface = "org.freedesktop.DBus.Properties"; +constexpr const char* get = "Get"; +constexpr const char* getAll = "GetAll"; + +} // namespace properties + +namespace redundancy +{ + +constexpr const char* collection = "Collection"; +constexpr const char* status = "Status"; +constexpr const char* interface = "xyz.openbmc_project.Control.FanRedundancy"; + +} // namespace redundancy + +DbusPassiveRedundancy::DbusPassiveRedundancy(sdbusplus::bus::bus& bus) : + match(bus, + "type='signal',member='PropertiesChanged',arg0namespace='" + + std::string(redundancy::interface) + "'", + std::move([this](sdbusplus::message::message& message) { + std::string objectName; + std::unordered_map< + std::string, + std::variant<std::string, std::vector<std::string>>> + result; + try + { + message.read(objectName, result); + } + catch (sdbusplus::exception_t&) + { + std::cerr << "Error reading match data"; + return; + } + auto findStatus = result.find("Status"); + if (findStatus == result.end()) + { + return; + } + std::string status = std::get<std::string>(findStatus->second); + + auto methodCall = passiveBus.new_method_call( + message.get_sender(), message.get_path(), + properties::interface, properties::get); + methodCall.append(redundancy::interface, redundancy::collection); + std::variant<std::vector<std::string>> collection; + + try + { + auto reply = passiveBus.call(methodCall); + reply.read(collection); + } + catch (sdbusplus::exception_t&) + { + std::cerr << "Error reading match data"; + return; + } + + auto data = std::get<std::vector<std::string>>(collection); + if (status.rfind("Failed") != std::string::npos) + { + failed.insert(data.begin(), data.end()); + } + else + { + for (const auto& d : data) + { + failed.erase(d); + } + } + })), + passiveBus(bus) +{ + populateFailures(); +} + +void DbusPassiveRedundancy::populateFailures(void) +{ + auto mapper = passiveBus.new_method_call( + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree"); + mapper.append("/", 0, std::array<const char*, 1>{redundancy::interface}); + std::unordered_map< + std::string, std::unordered_map<std::string, std::vector<std::string>>> + respData; + try + { + auto resp = passiveBus.call(mapper); + resp.read(respData); + } + catch (sdbusplus::exception_t&) + { + std::cerr << "Populate Failures Mapper Error\n"; + return; + } + + /* + * The subtree response looks like: + * {path : + * {busname: + * {interface, interface, interface, ...} + * } + * } + * + * This loops through this structure to pre-poulate the already failed items + */ + + for (const auto& [path, interfaceDict] : respData) + { + for (const auto& [owner, _] : interfaceDict) + { + auto call = passiveBus.new_method_call(owner.c_str(), path.c_str(), + properties::interface, + properties::getAll); + call.append(redundancy::interface); + + std::unordered_map< + std::string, + std::variant<std::string, std::vector<std::string>>> + getAll; + try + { + auto data = passiveBus.call(call); + data.read(getAll); + } + catch (sdbusplus::exception_t&) + { + std::cerr << "Populate Failures Mapper Error\n"; + return; + } + std::string status = + std::get<std::string>(getAll[redundancy::status]); + if (status.rfind("Failed") == std::string::npos) + { + continue; + } + std::vector<std::string> collection = + std::get<std::vector<std::string>>( + getAll[redundancy::collection]); + failed.insert(collection.begin(), collection.end()); + } + } +} + +const std::set<std::string>& DbusPassiveRedundancy::getFailed() +{ + return failed; +}
\ No newline at end of file diff --git a/dbus/dbuspassiveredundancy.hpp b/dbus/dbuspassiveredundancy.hpp new file mode 100644 index 0000000..3d7e2a6 --- /dev/null +++ b/dbus/dbuspassiveredundancy.hpp @@ -0,0 +1,43 @@ +/* +// Copyright (c) 2019 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#pragma once + +#include <sdbusplus/bus.hpp> +#include <sdbusplus/bus/match.hpp> +#include <set> + +/* + * DbusPassiveRedundancy monitors the fan redundancy interface via dbus match + * for changes. When the "Status" property changes to Failed, all sensors in + * the interface's "Collection" property are added to the failed member. This + * set can then be queried by a sensor to see if they are part of a failed + * redundancy collection. When this happens, they get marked as failed. + */ + +class DbusPassiveRedundancy +{ + public: + DbusPassiveRedundancy(sdbusplus::bus::bus& bus); + const std::set<std::string>& getFailed(void); + + private: + void populateFailures(void); + + sdbusplus::bus::match::match match; + std::set<std::string> failed; + sdbusplus::bus::bus& passiveBus; +}; |

