summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2019-01-15 11:40:34 -0600
committerMatt Spinler <spinler@us.ibm.com>2019-01-18 11:01:55 -0600
commit16caaee13f0904db7b7cf91192020f385bb1f8a9 (patch)
tree35e06b81cd242f022b588c2d850cb369fea2d0cd
parent318bd892a6d283319002b96216b1b746864089d9 (diff)
downloadbmcweb-16caaee13f0904db7b7cf91192020f385bb1f8a9.tar.gz
bmcweb-16caaee13f0904db7b7cf91192020f385bb1f8a9.zip
REST: Add framework for returning method response
If a method has an output argument in the introspection data, it has data that should be returned in the response JSON. This code finds the output type in the introspection data, and adds two function stubs: one to convert the output data in the sd_bus message to JSON, and another to handle combining the possible multiple method responses (from different services or interfaces) into 1 output. It also adds some logic on what to do if multiple methods are called and only a subset fail or return data. That logic can be summarized as: * if any method passes, consider it a success * return all the data that comes back, though the merging is done in a future commit. Change-Id: Ic50a3a88bb9d83672f7aed2b832217122e182048 Signed-off-by: Matt Spinler <spinler@us.ibm.com>
-rw-r--r--include/openbmc_dbus_rest.hpp109
1 files changed, 92 insertions, 17 deletions
diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp
index 7eae73b..895f436 100644
--- a/include/openbmc_dbus_rest.hpp
+++ b/include/openbmc_dbus_rest.hpp
@@ -40,6 +40,7 @@ const std::string badReqMsg = "400 Bad Request";
const std::string methodNotAllowedMsg = "405 Method Not Allowed";
const std::string forbiddenMsg = "403 Forbidden";
const std::string methodFailedMsg = "500 Method Call Failed";
+const std::string methodOutputFailedMsg = "500 Method Output Error";
const std::string notFoundDesc =
"org.freedesktop.DBus.Error.FileNotFound: path or object not found";
@@ -402,12 +403,50 @@ struct InProgressActionData
InProgressActionData(crow::Response &res) : res(res){};
~InProgressActionData()
{
- // If still no JSON filled in, then we never found the method.
- if (res.jsonValue.is_null())
+ // Methods could have been called across different owners
+ // and interfaces, where some calls failed and some passed.
+ //
+ // The rules for this are:
+ // * if no method was called - error
+ // * if a method failed and none passed - error
+ // (converse: if at least one method passed - OK)
+ // * for the method output:
+ // * if output processing didn't fail, return the data
+
+ // Only deal with method returns if nothing failed earlier
+ if (res.result() == boost::beast::http::status::ok)
{
- setErrorResponse(res, boost::beast::http::status::not_found,
- methodNotFoundDesc, notFoundMsg);
+ if (!methodPassed)
+ {
+ if (methodFailed)
+ {
+ setErrorResponse(res,
+ boost::beast::http::status::bad_request,
+ "Method call failed", methodFailedMsg);
+ }
+ else
+ {
+ setErrorResponse(res, boost::beast::http::status::not_found,
+ methodNotFoundDesc, notFoundMsg);
+ }
+ }
+ else
+ {
+ if (outputFailed)
+ {
+ setErrorResponse(
+ res, boost::beast::http::status::internal_server_error,
+ "Method output failure", methodOutputFailedMsg);
+ }
+ else
+ {
+ res.jsonValue = {{"status", "ok"},
+ {"message", "200 OK"},
+ {"data", methodResponse}};
+ }
+ }
}
+
res.end();
}
@@ -420,6 +459,10 @@ struct InProgressActionData
std::string path;
std::string methodName;
std::string interfaceName;
+ bool methodPassed = false;
+ bool methodFailed = false;
+ bool outputFailed = false;
+ nlohmann::json methodResponse;
nlohmann::json arguments;
};
@@ -752,6 +795,18 @@ int convertJsonToDbus(sd_bus_message *m, const std::string &arg_type,
return r;
}
+int convertDBusToJSON(const std::string &returnType,
+ sdbusplus::message::message &m, nlohmann::json &response)
+{
+ return 0;
+}
+
+void handleMethodResponse(std::shared_ptr<InProgressActionData> transaction,
+ sdbusplus::message::message &m,
+ const std::string &returnType)
+{
+}
+
void findActionOnInterface(std::shared_ptr<InProgressActionData> transaction,
const std::string &connectionName)
{
@@ -818,9 +873,31 @@ void findActionOnInterface(std::shared_ptr<InProgressActionData> transaction,
tinyxml2::XMLElement *argumentNode =
methodNode->FirstChildElement("arg");
+ std::string returnType;
+
+ // Find the output type
+ while (argumentNode != nullptr)
+ {
+ const char *argDirection =
+ argumentNode->Attribute("direction");
+ const char *argType =
+ argumentNode->Attribute("type");
+ if (argDirection != nullptr &&
+ argType != nullptr &&
+ std::string(argDirection) == "out")
+ {
+ returnType = argType;
+ break;
+ }
+ argumentNode =
+ argumentNode->NextSiblingElement("arg");
+ }
+
nlohmann::json::const_iterator argIt =
transaction->arguments.begin();
+ argumentNode = methodNode->FirstChildElement("arg");
+
while (argumentNode != nullptr)
{
const char *argDirection =
@@ -853,23 +930,21 @@ void findActionOnInterface(std::shared_ptr<InProgressActionData> transaction,
}
crow::connections::systemBus->async_send(
- m,
- [transaction](boost::system::error_code ec,
- sdbusplus::message::message &m) {
+ m, [transaction, returnType](
+ boost::system::error_code ec,
+ sdbusplus::message::message &m) {
if (ec)
{
- setErrorResponse(
- transaction->res,
- boost::beast::http::status::
- internal_server_error,
- "Method call failed",
- methodFailedMsg);
+ transaction->methodFailed = true;
return;
}
- transaction->res.jsonValue = {
- {"status", "ok"},
- {"message", "200 OK"},
- {"data", nullptr}};
+ else
+ {
+ transaction->methodPassed = true;
+ }
+
+ handleMethodResponse(transaction, m,
+ returnType);
});
break;
}
OpenPOWER on IntegriCloud