diff options
author | Yong Li <yong.b.li@linux.intel.com> | 2018-01-04 08:59:03 +0300 |
---|---|---|
committer | Yong Li <yong.b.li@linux.intel.com> | 2018-01-18 08:32:37 +0300 |
commit | e31fc4f8e8e2870745ee82d38ba1f79480001f0b (patch) | |
tree | 04b92a9eb7ded075763e0ccf2b4bb18736b96244 /tools | |
parent | 592c7b91e2c4e307bdc18febcd38257da2049791 (diff) | |
download | provingground-e31fc4f8e8e2870745ee82d38ba1f79480001f0b.tar.xz |
Add prop_wait tool
OPENBMC2-919 Add a tool to query the dbus property,
to check if it is the expected value.
Used by chassis/power control
Change-Id: Ia5d421e4ca1c9e699b881ec007020359b1411bbf
Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/prop_wait/.clang-format | 98 | ||||
-rw-r--r-- | tools/prop_wait/CMakeLists.txt | 24 | ||||
-rw-r--r-- | tools/prop_wait/include/argument.hpp | 48 | ||||
-rw-r--r-- | tools/prop_wait/src/argument.cpp | 100 | ||||
-rw-r--r-- | tools/prop_wait/src/prop_wait.cpp | 151 |
5 files changed, 421 insertions, 0 deletions
diff --git a/tools/prop_wait/.clang-format b/tools/prop_wait/.clang-format new file mode 100644 index 0000000..e949c5e --- /dev/null +++ b/tools/prop_wait/.clang-format @@ -0,0 +1,98 @@ +--- +BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: true +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + + - Regex: '^[<"](crow)' + Priority: 5 + - Regex: '^[<"](boost)' + Priority: 6 + - Regex: '^[<"](gtest|gmock)' + Priority: 7 + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*\.hpp>' + Priority: 2 + - Regex: '^<.*' + Priority: 3 + - Regex: '.*' + Priority: 4 +IndentCaseLabels: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +TabWidth: 8 +UseTab: Never +... + diff --git a/tools/prop_wait/CMakeLists.txt b/tools/prop_wait/CMakeLists.txt new file mode 100644 index 0000000..78ccff1 --- /dev/null +++ b/tools/prop_wait/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR) +project(prop_wait CXX) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(GNUInstallDirs) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +set(SRC_FILES + src/prop_wait.cpp + src/argument.cpp +) + +# import phosphor-logging +find_package(PkgConfig REQUIRED) +pkg_check_modules(LOGGING phosphor-logging REQUIRED) +include_directories(${LOGGING_INCLUDE_DIRS}) +link_directories(${LOGGING_LIBRARY_DIRS}) + +add_executable(${PROJECT_NAME} ${SRC_FILES}) +target_link_libraries(${PROJECT_NAME} ${LOGGING_LIBRARIES}) + +install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file diff --git a/tools/prop_wait/include/argument.hpp b/tools/prop_wait/include/argument.hpp new file mode 100644 index 0000000..19391df --- /dev/null +++ b/tools/prop_wait/include/argument.hpp @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2017 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 <getopt.h> +#include <map> +#include <string> + +/** + * Parses command line arguments. + */ +class ArgumentParser +{ + public: + ArgumentParser(int argc, char** argv); + ArgumentParser() = delete; + ArgumentParser(const ArgumentParser&) = delete; + ArgumentParser(ArgumentParser&&) = default; + ArgumentParser& operator=(const ArgumentParser&) = delete; + ArgumentParser& operator=(ArgumentParser&&) = default; + ~ArgumentParser() = default; + const std::string& operator[](const std::string& opt); + + static void usage(char** argv); + + static const std::string true_string; + static const std::string empty_string; + + private: + std::map<const std::string, std::string> arguments; + + static const option options[]; + static const char* optionstr; +}; diff --git a/tools/prop_wait/src/argument.cpp b/tools/prop_wait/src/argument.cpp new file mode 100644 index 0000000..8e5f799 --- /dev/null +++ b/tools/prop_wait/src/argument.cpp @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2017 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 "argument.hpp" +#include <algorithm> +#include <cassert> +#include <iostream> +#include <iterator> +#include <string> + +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 << " --path=<Dbus Object path> Dbus object path.\n" + << " Ex: /org/openbmc/control/power0\n"; + + std::cerr + << " --service=<Dbus Service name> Dbus Service name.\n" + << " Ex: org.openbmc.control.Power\n"; + std::cerr + << " --interface=<Dbus interface name> Dbus interface name.\n" + << " Ex: org.openbmc.control.Power\n"; + std::cerr + << " --property=<Dbus property name> Dbus property name.\n" + << " Ex: pgood\n"; + + std::cerr + << " --expect=<expected value> Dbus property value.\n" + << " Ex: 1\n"; + + std::cerr << std::flush; +} + +const option ArgumentParser::options[] = +{ + {"path", required_argument, NULL, 'p'}, + {"service", required_argument, NULL, 's'}, + {"interface", required_argument, NULL, 'i'}, + {"property", required_argument, NULL, 'r'}, + {"expect", required_argument, NULL, 'e'}, + {"help", no_argument, NULL, 'h'}, + {0, 0, 0, 0}, +}; + +const char* ArgumentParser::optionstr = "p:s:i:r:e:?h"; + +const std::string ArgumentParser::true_string = "true"; +const std::string ArgumentParser::empty_string = ""; diff --git a/tools/prop_wait/src/prop_wait.cpp b/tools/prop_wait/src/prop_wait.cpp new file mode 100644 index 0000000..e2e04c7 --- /dev/null +++ b/tools/prop_wait/src/prop_wait.cpp @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2017 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. + */ + +// A tool used to wait for a dbus property(int32_t) to be the expected value +#include <unistd.h> +#include <phosphor-logging/log.hpp> +#include <sdbusplus/bus.hpp> +#include <sdbusplus/bus/match.hpp> +#include <cstdio> +#include <cstdlib> +#include <fstream> +#include <iostream> +#include <string> +#include "argument.hpp" + +static bool Waiting = true; +static auto property = ArgumentParser::empty_string; +static auto expect_val = ArgumentParser::empty_string; + +static int propChanged(sd_bus_message* msg, void* userData, + sd_bus_error* retError) +{ + std::string iface; + std::map<std::string, sdbusplus::message::variant<int32_t>> data; + + auto sdPlusMsg = sdbusplus::message::message(msg); + + sdPlusMsg.read(iface, data); + + auto prop = data.find(property); + + if (prop != data.end()) + { + int32_t prop_val = -1; + prop_val = sdbusplus::message::variant_ns::get<int32_t>(prop->second); + + if (prop_val == std::stoi(expect_val)) + { + Waiting = false; + } + else + { + Waiting = true; + } + } + + return 0; +} + +static void ExitWithError(const char* err, char** argv) +{ + ArgumentParser::usage(argv); + std::cerr << std::endl; + std::cerr << "ERROR: " << err << std::endl; + exit(-1); +} + +int main(int argc, char* argv[]) +{ + auto options = ArgumentParser(argc, argv); + + auto path = options["path"]; + if (path == ArgumentParser::empty_string) + { + ExitWithError("path not specified", argv); + } + + auto service = options["service"]; + if (service == ArgumentParser::empty_string) + { + ExitWithError("service not specified", argv); + } + + auto interface = options["interface"]; + if (interface == ArgumentParser::empty_string) + { + ExitWithError("interface not specified", argv); + } + + property = options["property"]; + if (property == ArgumentParser::empty_string) + { + ExitWithError("property not specified", argv); + } + + expect_val = options["expect"]; + if (expect_val == ArgumentParser::empty_string) + { + ExitWithError("expect value not specified", argv); + } + + auto bus = sdbusplus::bus::new_default(); + + std::string match_str = + sdbusplus::bus::match::rules::propertiesChanged(path, interface); + + sdbusplus::message::variant<int32_t> prop_val = -1; + + auto method = bus.new_method_call(std::string(service).c_str(), + std::string(path).c_str(), + "org.freedesktop.DBus.Properties", "Get"); + + method.append(interface, property); + + auto reply = bus.call(method); + reply.read(prop_val); + if (reply.is_method_error()) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in method call to get property"); + return -1; + } + + if (prop_val == std::stoi(expect_val)) + { + return 0; + } + else + { + Waiting = true; + } + + // Setup Signal Handler + sdbusplus::bus::match::match waitSignals(bus, match_str.c_str(), + propChanged, nullptr); + // Wait for signal + while (Waiting) + { + bus.process_discard(); + if (!Waiting) + { + break; + } + bus.wait(); + } + + return 0; +} |