From 6ad28430764b7d16ee7abcb9965b76ea5583008f Mon Sep 17 00:00:00 2001 From: Matthew Barth Date: Tue, 22 Aug 2017 11:18:19 -0500 Subject: Create fan monitor init mode Allowing fan monitor to run in an init mode will set the fans to a functional state at each poweron for fans that were non-functional at poweroff. Then fan monitor can be started in monitor mode after the fans have ramped up to full speed and can begin being monitored for faults. This also allows for the removal of fan monitor doing a sd_notify prior to fan control starting. Change-Id: I634c9b4ec8bb30860dea54c8abd1cd6c56831d25 Signed-off-by: Matthew Barth --- monitor/Makefile.am | 1 + monitor/argument.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ monitor/fan.cpp | 48 +++++++++++++++------------- monitor/fan.hpp | 15 ++++++++- monitor/main.cpp | 49 ++++++++++++++++++++-------- 5 files changed, 166 insertions(+), 37 deletions(-) create mode 100644 monitor/argument.cpp diff --git a/monitor/Makefile.am b/monitor/Makefile.am index 7b5fdae..4e2d599 100644 --- a/monitor/Makefile.am +++ b/monitor/Makefile.am @@ -5,6 +5,7 @@ sbin_PROGRAMS = \ phosphor-fan-monitor phosphor_fan_monitor_SOURCES = \ + argument.cpp \ fan.cpp \ main.cpp \ tach_sensor.cpp diff --git a/monitor/argument.cpp b/monitor/argument.cpp new file mode 100644 index 0000000..2fbef68 --- /dev/null +++ b/monitor/argument.cpp @@ -0,0 +1,90 @@ +/** + * Copyright © 2017 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 +#include +#include +#include "argument.hpp" + +namespace phosphor +{ +namespace fan +{ +namespace util +{ + +ArgumentParser::ArgumentParser(int argc, char** argv) +{ + auto option = 0; + while (-1 != (option = getopt_long(argc, argv, optionstr, options, NULL))) + { + if ((option == '?') || (option == 'h')) + { + usage(argv); + exit(-1); + } + + auto i = &options[0]; + while ((i->val != option) && (i->val != 0)) + { + ++i; + } + + if (i->val) + { + arguments[i->name] = (i->has_arg ? optarg : true_string); + } + } +} + +const std::string& ArgumentParser::operator[](const std::string& opt) +{ + auto i = arguments.find(opt); + if (i == arguments.end()) + { + return empty_string; + } + else + { + return i->second; + } +} + +void ArgumentParser::usage(char** argv) +{ + std::cerr << "Usage: " << argv[0] << " [options]\n"; + std::cerr << "Options:\n"; + std::cerr << " --help Print this menu\n"; + std::cerr << " --init Set fans to functional\n"; + std::cerr << " --monitor Start fan funcitonal monitoring\n"; + std::cerr << std::flush; +} + +const option ArgumentParser::options[] = +{ + { "init", no_argument, NULL, 'i' }, + { "monitor", no_argument, NULL, 'm' }, + { "help", no_argument, NULL, 'h' }, + { 0, 0, 0, 0 }, +}; + +const char* ArgumentParser::optionstr = "imh?"; + +const std::string ArgumentParser::true_string = "true"; +const std::string ArgumentParser::empty_string = ""; + +} +} +} diff --git a/monitor/fan.cpp b/monitor/fan.cpp index 6d88d2a..054c67d 100644 --- a/monitor/fan.cpp +++ b/monitor/fan.cpp @@ -37,7 +37,8 @@ constexpr auto OPERATIONAL_STATUS_INTF = "xyz.openbmc_project.State.Decorator.OperationalStatus"; -Fan::Fan(sdbusplus::bus::bus& bus, +Fan::Fan(Mode mode, + sdbusplus::bus::bus& bus, phosphor::fan::event::EventPtr& events, const FanDefinition& def) : _bus(bus), @@ -45,33 +46,36 @@ Fan::Fan(sdbusplus::bus::bus& bus, _deviation(std::get(def)), _numSensorFailsForNonFunc(std::get(def)) { - auto& sensors = std::get(def); + //Start from a known state of functional + updateInventory(true); - for (auto& s : sensors) + // Setup tach sensors for monitoring when in monitor mode + if (mode != Mode::init) { - try + auto& sensors = std::get(def); + for (auto& s : sensors) { - _sensors.emplace_back( - std::make_unique( - bus, - *this, - std::get(s), - std::get(s), - std::get(def), - events)); + try + { + _sensors.emplace_back( + std::make_unique( + bus, + *this, + std::get(s), + std::get(s), + std::get(def), + events)); + } + catch (InvalidSensorError& e) + { + + } } - catch (InvalidSensorError& e) - { - } + //The TachSensors will now have already read the input + //and target values, so check them. + tachChanged(); } - - //Start from a known state of functional - updateInventory(true); - - //The TachSensors will now have already read the input - //and target values, so check them. - tachChanged(); } diff --git a/monitor/fan.hpp b/monitor/fan.hpp index 0004353..3da75cf 100644 --- a/monitor/fan.hpp +++ b/monitor/fan.hpp @@ -14,6 +14,17 @@ namespace fan namespace monitor { +/** + * The mode fan monitor will run in: + * - init - only do the initialization steps + * - monitor - run normal monitoring algorithm + */ +enum class Mode +{ + init, + monitor +}; + /** * @class InvalidSensorError * @@ -75,11 +86,13 @@ class Fan /** * @brief Constructor * + * @param mode - mode of fan monitor * @param bus - the dbus object * @param events - pointer to sd_event object * @param def - the fan definition structure */ - Fan(sdbusplus::bus::bus& bus, + Fan(Mode mode, + sdbusplus::bus::bus& bus, phosphor::fan::event::EventPtr& events, const FanDefinition& def); diff --git a/monitor/main.cpp b/monitor/main.cpp index b9c1d81..f887232 100644 --- a/monitor/main.cpp +++ b/monitor/main.cpp @@ -16,6 +16,7 @@ #include #include #include +#include "argument.hpp" #include "event.hpp" #include "fan.hpp" #include "fan_defs.hpp" @@ -23,12 +24,33 @@ using namespace phosphor::fan::monitor; using namespace phosphor::logging; - -int main() +int main(int argc, char* argv[]) { auto bus = sdbusplus::bus::new_default(); sd_event* events = nullptr; std::vector> fans; + phosphor::fan::util::ArgumentParser args(argc, argv); + + if (argc != 2) + { + args.usage(argv); + exit(-1); + } + + Mode mode; + if (args["init"] == "true") + { + mode = Mode::init; + } + else if (args["monitor"] == "true") + { + mode = Mode::monitor; + } + else + { + args.usage(argv); + exit(-1); + } auto r = sd_event_default(&events); if (r < 0) @@ -46,23 +68,22 @@ int main() for (const auto& fanDef : fanDefinitions) { - fans.emplace_back(std::make_unique(bus, eventPtr, fanDef)); + fans.emplace_back(std::make_unique(mode, bus, eventPtr, fanDef)); } - //Tell systemd we are initialized - r = sd_notify(0, "READY=1"); - if (r < 1) // 0 = nothing sent, < 0 is a failure + if (mode == Mode::init) { - log("sd_notify did not send anything", - entry("ERROR=%d", r)); - return -1; + // Fans were initialized to be functional, exit + return 0; } - - r = sd_event_loop(eventPtr.get()); - if (r < 0) + else { - log("Failed call to sd_event_loop", - entry("ERROR=%s", strerror(-r))); + r = sd_event_loop(eventPtr.get()); + if (r < 0) + { + log("Failed call to sd_event_loop", + entry("ERROR=%s", strerror(-r))); + } } return -1; -- cgit v1.2.1