blob: a84908f9896de02f980fc43d20eb7d3718ab918e [file] [log] [blame] [edit]
/**
* Copyright © 2025 IBM 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 "chassis_status_monitor.hpp"
#include "types.hpp"
#include <format>
namespace phosphor::power::util
{
constexpr auto INVENTORY_MGR_SERVICE = "xyz.openbmc_project.Inventory.Manager";
constexpr auto POWER_SEQUENCER_SERVICE = "org.openbmc.control.Power";
constexpr auto CHASSIS_INPUT_POWER_SERVICE =
"xyz.openbmc_project.Power.Chassis";
constexpr auto POWER_SUPPLY_SERVICE = "xyz.openbmc_project.Power.PSUMonitor";
constexpr auto CHASSIS_POWER_PATH = "/org/openbmc/control/power{}";
constexpr auto CHASSIS_INPUT_POWER_STATUS_PATH =
"/xyz/openbmc_project/power/chassis/chassis{}";
constexpr auto POWER_SUPPLIES_STATUS_PATH =
"/xyz/openbmc_project/power/power_supplies/chassis{}/psus";
BMCChassisStatusMonitor::BMCChassisStatusMonitor(
sdbusplus::bus_t& bus, size_t number, const std::string& inventoryPath,
const ChassisStatusMonitorOptions& options) :
bus{bus}, number{number}, inventoryPath{inventoryPath}, options{options}
{
chassisPowerPath = std::format(CHASSIS_POWER_PATH, number);
chassisInputPowerStatusPath =
std::format(CHASSIS_INPUT_POWER_STATUS_PATH, number);
powerSuppliesStatusPath = std::format(POWER_SUPPLIES_STATUS_PATH, number);
addMatches();
getAllProperties();
}
void BMCChassisStatusMonitor::addMatches()
{
if (options.isPresentMonitored || options.isAvailableMonitored ||
options.isEnabledMonitored)
{
addNameOwnerChangedMatch(INVENTORY_MGR_SERVICE);
addInterfacesAddedMatch(inventoryPath);
if (options.isPresentMonitored)
{
addPropertiesChangedMatch(inventoryPath, INVENTORY_IFACE);
}
if (options.isAvailableMonitored)
{
addPropertiesChangedMatch(inventoryPath, AVAILABILITY_IFACE);
}
if (options.isEnabledMonitored)
{
addPropertiesChangedMatch(inventoryPath, ENABLE_IFACE);
}
}
if (options.isPowerStateMonitored || options.isPowerGoodMonitored)
{
addNameOwnerChangedMatch(POWER_SEQUENCER_SERVICE);
addInterfacesAddedMatch(chassisPowerPath);
addPropertiesChangedMatch(chassisPowerPath, POWER_IFACE);
}
if (options.isInputPowerStatusMonitored)
{
addNameOwnerChangedMatch(CHASSIS_INPUT_POWER_SERVICE);
addInterfacesAddedMatch(chassisInputPowerStatusPath);
addPropertiesChangedMatch(chassisInputPowerStatusPath,
POWER_SYSTEM_INPUTS_IFACE);
}
if (options.isPowerSuppliesStatusMonitored)
{
addNameOwnerChangedMatch(POWER_SUPPLY_SERVICE);
addInterfacesAddedMatch(powerSuppliesStatusPath);
addPropertiesChangedMatch(powerSuppliesStatusPath,
POWER_SYSTEM_INPUTS_IFACE);
}
}
template <typename T>
void BMCChassisStatusMonitor::getProperty(
const std::string& service, const std::string& path,
const std::string& interface, const std::string& propertyName,
std::optional<T>& optionalValue)
{
try
{
T value;
util::getProperty(interface, propertyName, path, service, bus, value);
optionalValue = value;
}
catch (...)
{}
}
void BMCChassisStatusMonitor::getInventoryManagerProperties()
{
if (options.isPresentMonitored)
{
getProperty(INVENTORY_MGR_SERVICE, inventoryPath, INVENTORY_IFACE,
PRESENT_PROP, isPresentValue);
}
if (options.isAvailableMonitored)
{
getProperty(INVENTORY_MGR_SERVICE, inventoryPath, AVAILABILITY_IFACE,
AVAILABLE_PROP, isAvailableValue);
}
if (options.isEnabledMonitored)
{
getProperty(INVENTORY_MGR_SERVICE, inventoryPath, ENABLE_IFACE,
ENABLED_PROP, isEnabledValue);
}
}
void BMCChassisStatusMonitor::getPowerSequencerProperties()
{
if (options.isPowerStateMonitored)
{
getProperty(POWER_SEQUENCER_SERVICE, chassisPowerPath, POWER_IFACE,
POWER_STATE_PROP, powerStateValue);
}
if (options.isPowerGoodMonitored)
{
getProperty(POWER_SEQUENCER_SERVICE, chassisPowerPath, POWER_IFACE,
POWER_GOOD_PROP, powerGoodValue);
}
}
void BMCChassisStatusMonitor::getChassisInputPowerProperties()
{
if (options.isInputPowerStatusMonitored)
{
getProperty(CHASSIS_INPUT_POWER_SERVICE, chassisInputPowerStatusPath,
POWER_SYSTEM_INPUTS_IFACE, STATUS_PROP,
inputPowerStatusValue);
}
}
void BMCChassisStatusMonitor::getPowerSupplyProperties()
{
if (options.isPowerSuppliesStatusMonitored)
{
getProperty(POWER_SUPPLY_SERVICE, powerSuppliesStatusPath,
POWER_SYSTEM_INPUTS_IFACE, STATUS_PROP,
powerSuppliesStatusValue);
}
}
template <typename T>
void BMCChassisStatusMonitor::storeProperty(const DbusPropertyMap& properties,
const std::string& propertyName,
std::optional<T>& optionalValue)
{
try
{
auto it = properties.find(propertyName);
if (it != properties.end())
{
optionalValue = std::get<T>(it->second);
}
}
catch (...)
{}
}
void BMCChassisStatusMonitor::storeProperties(const DbusPropertyMap& properties,
const std::string& path,
const std::string& interface)
{
try
{
if (interface == INVENTORY_IFACE)
{
storeProperty(properties, PRESENT_PROP, isPresentValue);
}
else if (interface == AVAILABILITY_IFACE)
{
storeProperty(properties, AVAILABLE_PROP, isAvailableValue);
}
else if (interface == ENABLE_IFACE)
{
storeProperty(properties, ENABLED_PROP, isEnabledValue);
}
else if (interface == POWER_IFACE)
{
storeProperty(properties, POWER_STATE_PROP, powerStateValue);
storeProperty(properties, POWER_GOOD_PROP, powerGoodValue);
}
else if (interface == POWER_SYSTEM_INPUTS_IFACE)
{
if (path == chassisInputPowerStatusPath)
{
storeProperty(properties, STATUS_PROP, inputPowerStatusValue);
}
else if (path == powerSuppliesStatusPath)
{
storeProperty(properties, STATUS_PROP,
powerSuppliesStatusValue);
}
}
}
catch (...)
{}
}
void BMCChassisStatusMonitor::nameOwnerChangedCallback(
sdbusplus::message_t& message)
{
try
{
std::string name, oldOwner, newOwner;
message.read(name, oldOwner, newOwner);
if (!newOwner.empty())
{
if (name == INVENTORY_MGR_SERVICE)
{
getInventoryManagerProperties();
}
else if (name == POWER_SEQUENCER_SERVICE)
{
getPowerSequencerProperties();
}
else if (name == CHASSIS_INPUT_POWER_SERVICE)
{
getChassisInputPowerProperties();
}
else if (name == POWER_SUPPLY_SERVICE)
{
getPowerSupplyProperties();
}
}
}
catch (...)
{}
}
void BMCChassisStatusMonitor::interfacesAddedCallback(
sdbusplus::message_t& message)
{
try
{
sdbusplus::message::object_path path;
std::map<std::string, DbusPropertyMap> interfaces;
message.read(path, interfaces);
for (const auto& [interface, properties] : interfaces)
{
storeProperties(properties, path, interface);
}
}
catch (...)
{}
}
void BMCChassisStatusMonitor::propertiesChangedCallback(
sdbusplus::message_t& message)
{
try
{
std::string interface;
DbusPropertyMap changedProperties;
std::vector<std::string> invalidatedProperties;
message.read(interface, changedProperties, invalidatedProperties);
storeProperties(changedProperties, message.get_path(), interface);
}
catch (...)
{}
}
} // namespace phosphor::power::util