[dbusconfiguration] Allow partial configurations
In a few cases (cpu sensors, etc.) we can
add sensor during runtime, that aren't an error to be missing
when the system is off, or are optional (add-in cards).
Add a dbus match to restart on sensors added, and don't
add configurations that are missing a sensor.
Tested-by: Turned on debug, noticed on cpu sensors being
added daemon restarted correctly. Also noticed daemon
didn't crash with no configuration.
Change-Id: Ide0bd03c12e380e5aad56b1da06e34a5fc5cdb9f
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/dbus/dbusconfiguration.cpp b/dbus/dbusconfiguration.cpp
index 0443854..5f8558d 100644
--- a/dbus/dbusconfiguration.cpp
+++ b/dbus/dbusconfiguration.cpp
@@ -46,6 +46,8 @@
namespace dbus_configuration
{
+namespace variant_ns = sdbusplus::message::variant_ns;
+
bool findSensor(const std::unordered_map<std::string, std::string>& sensors,
const std::string& search,
std::pair<std::string, std::string>& sensor)
@@ -124,6 +126,16 @@
std::cout << "}\n\n";
}
+int eventHandler(sd_bus_message*, void*, sd_bus_error*)
+{
+ // do a brief sleep as we tend to get a bunch of these events at
+ // once
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ std::cout << "New configuration detected, restarting\n.";
+ std::exit(EXIT_SUCCESS); // service file should make us restart
+ return 1;
+}
+
void init(sdbusplus::bus::bus& bus)
{
using DbusVariantType =
@@ -136,22 +148,20 @@
std::unordered_map<std::string,
std::unordered_map<std::string, DbusVariantType>>>;
- // install watch for properties changed
- std::function<void(sdbusplus::message::message & message)> eventHandler =
- [](const sdbusplus::message::message&) {
- // do a brief sleep as we tend to get a bunch of these events at
- // once
- std::this_thread::sleep_for(std::chrono::seconds(5));
- std::cout << "New configuration detected, restarting\n.";
- std::exit(EXIT_SUCCESS); // service file should make us restart
- };
-
- static sdbusplus::bus::match::match match(
+ // restart on configuration properties changed
+ static sdbusplus::bus::match::match configMatch(
bus,
"type='signal',member='PropertiesChanged',arg0namespace='" +
std::string(pidConfigurationInterface) + "'",
eventHandler);
+ // restart on sensors changed
+ static sdbusplus::bus::match::match sensorAdded(
+ bus,
+ "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/"
+ "sensors/'",
+ eventHandler);
+
auto mapper =
bus.new_method_call("xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
@@ -275,8 +285,7 @@
const auto& zone = findZone->second;
size_t index = 1;
const std::string& name =
- sdbusplus::message::variant_ns::get<std::string>(
- zone.at("Name"));
+ variant_ns::get<std::string>(zone.at("Name"));
auto it = std::find(zoneIndex.begin(), zoneIndex.end(), name);
if (it == zoneIndex.end())
{
@@ -301,8 +310,7 @@
const auto& base =
configuration.second.at(pidConfigurationInterface);
const std::vector<std::string>& zones =
- sdbusplus::message::variant_ns::get<std::vector<std::string>>(
- base.at("Zones"));
+ variant_ns::get<std::vector<std::string>>(base.at("Zones"));
for (const std::string& zone : zones)
{
auto it = std::find(zoneIndex.begin(), zoneIndex.end(), zone);
@@ -317,11 +325,79 @@
index = zoneIndex.end() - it;
}
PIDConf& conf = ZoneConfig[index];
+
+ std::vector<std::string> sensorNames =
+ variant_ns::get<std::vector<std::string>>(
+ base.at("Inputs"));
+ auto findOutputs =
+ base.find("Outputs"); // currently only fans have outputs
+ if (findOutputs != base.end())
+ {
+ std::vector<std::string> outputs =
+ variant_ns::get<std::vector<std::string>>(
+ findOutputs->second);
+ sensorNames.insert(sensorNames.end(), outputs.begin(),
+ outputs.end());
+ }
+ bool sensorsAvailable = sensorNames.size();
+ std::vector<std::string> inputs;
+ for (const std::string& sensorName : sensorNames)
+ {
+ std::string name = sensorName;
+ // replace spaces with underscores to be legal on dbus
+ std::replace(name.begin(), name.end(), ' ', '_');
+ std::pair<std::string, std::string> sensorPathIfacePair;
+
+ if (!findSensor(sensors, name, sensorPathIfacePair))
+ {
+ sensorsAvailable = false;
+ break;
+ }
+ if (sensorPathIfacePair.second == sensorInterface)
+ {
+ inputs.push_back(name);
+ auto& config = SensorConfig[name];
+ config.type =
+ variant_ns::get<std::string>(base.at("Class"));
+ config.readpath = sensorPathIfacePair.first;
+ // todo: maybe un-hardcode this if we run into slower
+ // timeouts with sensors
+ if (config.type == "temp")
+ {
+ config.timeout = 500;
+ }
+ }
+ else if (sensorPathIfacePair.second == pwmInterface)
+ {
+ // copy so we can modify it
+ for (std::string otherSensor : sensorNames)
+ {
+ if (otherSensor == sensorName)
+ {
+ continue;
+ }
+ std::replace(otherSensor.begin(), otherSensor.end(),
+ ' ', '_');
+ auto& config = SensorConfig[otherSensor];
+ config.writepath = sensorPathIfacePair.first;
+ // todo: un-hardcode this if there are fans with
+ // different ranges
+ config.max = 255;
+ config.min = 0;
+ }
+ }
+ }
+ // if the sensors aren't available in the current state, don't
+ // add them to the configuration.
+ if (!sensorsAvailable)
+ {
+ continue;
+ }
struct controller_info& info =
- conf[sdbusplus::message::variant_ns::get<std::string>(
- base.at("Name"))];
- info.type = sdbusplus::message::variant_ns::get<std::string>(
- base.at("Class"));
+ conf[variant_ns::get<std::string>(base.at("Name"))];
+ info.inputs = std::move(inputs);
+
+ info.type = variant_ns::get<std::string>(base.at("Class"));
// todo: auto generation yaml -> c script seems to discard this
// value for fans, verify this is okay
if (info.type == "fan")
@@ -354,67 +430,6 @@
VariantToFloatVisitor(), base.at("SlewNeg"));
info.pidInfo.slew_pos = mapbox::util::apply_visitor(
VariantToFloatVisitor(), base.at("SlewPos"));
-
- std::vector<std::string> sensorNames =
- sdbusplus::message::variant_ns::get<
- std::vector<std::string>>(base.at("Inputs"));
- auto findOutputs =
- base.find("Outputs"); // currently only fans have outputs
- if (findOutputs != base.end())
- {
- std::vector<std::string> outputs =
- sdbusplus::message::variant_ns::get<
- std::vector<std::string>>(findOutputs->second);
- sensorNames.insert(sensorNames.end(), outputs.begin(),
- outputs.end());
- }
- for (const std::string& sensorName : sensorNames)
- {
- std::string name = sensorName;
- // replace spaces with underscores to be legal on dbus
- std::replace(name.begin(), name.end(), ' ', '_');
- std::pair<std::string, std::string> sensorPathIfacePair;
-
- if (!findSensor(sensors, name, sensorPathIfacePair))
- {
- throw std::runtime_error(
- "Could not map configuration to sensor " + name);
- }
- if (sensorPathIfacePair.second == sensorInterface)
- {
- info.inputs.push_back(name);
- auto& config = SensorConfig[name];
- config.type =
- sdbusplus::message::variant_ns::get<std::string>(
- base.at("Class"));
- config.readpath = sensorPathIfacePair.first;
- // todo: maybe un-hardcode this if we run into slower
- // timeouts with sensors
- if (config.type == "temp")
- {
- config.timeout = 500;
- }
- }
- if (sensorPathIfacePair.second == pwmInterface)
- {
- // copy so we can modify it
- for (std::string otherSensor : sensorNames)
- {
- if (otherSensor == sensorName)
- {
- continue;
- }
- std::replace(otherSensor.begin(), otherSensor.end(),
- ' ', '_');
- auto& config = SensorConfig[otherSensor];
- config.writepath = sensorPathIfacePair.first;
- // todo: un-hardcode this if there are fans with
- // different ranges
- config.max = 255;
- config.min = 0;
- }
- }
- }
}
}
auto findStepwise =
@@ -423,8 +438,7 @@
{
const auto& base = findStepwise->second;
const std::vector<std::string>& zones =
- sdbusplus::message::variant_ns::get<std::vector<std::string>>(
- base.at("Zones"));
+ variant_ns::get<std::vector<std::string>>(base.at("Zones"));
for (const std::string& zone : zones)
{
auto it = std::find(zoneIndex.begin(), zoneIndex.end(), zone);
@@ -439,9 +453,43 @@
index = zoneIndex.end() - it;
}
PIDConf& conf = ZoneConfig[index];
+
+ std::vector<std::string> inputs;
+ std::vector<std::string> sensorNames =
+ variant_ns::get<std::vector<std::string>>(
+ base.at("Inputs"));
+
+ bool sensorFound = sensorNames.size();
+ for (const std::string& sensorName : sensorNames)
+ {
+ std::string name = sensorName;
+ // replace spaces with underscores to be legal on dbus
+ std::replace(name.begin(), name.end(), ' ', '_');
+ std::pair<std::string, std::string> sensorPathIfacePair;
+
+ if (!findSensor(sensors, name, sensorPathIfacePair))
+ {
+ sensorFound = false;
+ break;
+ }
+
+ inputs.push_back(name);
+ auto& config = SensorConfig[name];
+ config.readpath = sensorPathIfacePair.first;
+ config.type = "temp";
+ // todo: maybe un-hardcode this if we run into slower
+ // timeouts with sensors
+
+ config.timeout = 500;
+ }
+ if (!sensorFound)
+ {
+ continue;
+ }
struct controller_info& info =
- conf[sdbusplus::message::variant_ns::get<std::string>(
- base.at("Name"))];
+ conf[variant_ns::get<std::string>(base.at("Name"))];
+ info.inputs = std::move(inputs);
+
info.type = "stepwise";
info.stepwiseInfo.ts = 1.0; // currently unused
info.stepwiseInfo.positiveHysteresis = 0.0;
@@ -461,8 +509,7 @@
findNegHyst->second);
}
std::vector<double> readings =
- sdbusplus::message::variant_ns::get<std::vector<double>>(
- base.at("Reading"));
+ variant_ns::get<std::vector<double>>(base.at("Reading"));
if (readings.size() > ec::maxStepwisePoints)
{
throw std::invalid_argument("Too many stepwise points.");
@@ -480,8 +527,7 @@
std::numeric_limits<float>::quiet_NaN();
}
std::vector<double> outputs =
- sdbusplus::message::variant_ns::get<std::vector<double>>(
- base.at("Output"));
+ variant_ns::get<std::vector<double>>(base.at("Output"));
if (readings.size() != outputs.size())
{
throw std::invalid_argument(
@@ -494,35 +540,6 @@
info.stepwiseInfo.output[outputs.size()] =
std::numeric_limits<float>::quiet_NaN();
}
-
- std::vector<std::string> sensorNames =
- sdbusplus::message::variant_ns::get<
- std::vector<std::string>>(base.at("Inputs"));
-
- for (const std::string& sensorName : sensorNames)
- {
- std::string name = sensorName;
- // replace spaces with underscores to be legal on dbus
- std::replace(name.begin(), name.end(), ' ', '_');
- std::pair<std::string, std::string> sensorPathIfacePair;
-
- if (!findSensor(sensors, name, sensorPathIfacePair))
- {
- // todo(james): if we can't find a sensor, delete it
- // from config, we'll find it on rescan
- throw std::runtime_error(
- "Could not map configuration to sensor " + name);
- }
-
- info.inputs.push_back(name);
- auto& config = SensorConfig[name];
- config.readpath = sensorPathIfacePair.first;
- config.type = "temp";
- // todo: maybe un-hardcode this if we run into slower
- // timeouts with sensors
-
- config.timeout = 500;
- }
}
}
}
@@ -530,5 +547,13 @@
{
debugPrint();
}
+ if (ZoneConfig.empty())
+ {
+ std::cerr << "No fan zones, application pausing until reboot\n";
+ while (1)
+ {
+ bus.process_discard();
+ }
+ }
}
} // namespace dbus_configuration