summaryrefslogtreecommitdiff
path: root/redfish-core/lib/update_service.hpp
diff options
context:
space:
mode:
authorAndrew Geissler <geissonator@yahoo.com>2019-03-05 04:11:54 +0300
committerEd Tanous <ed.tanous@intel.com>2019-04-11 00:42:09 +0300
commit0e7de46f9b6365bad4e79a3933112750c5bf7853 (patch)
tree7dc54d68dfaec9639b5e16f537ff7f648f043599 /redfish-core/lib/update_service.hpp
parent87d847298c57168b1af9bc8bbf201073ef3e76fe (diff)
downloadbmcweb-0e7de46f9b6365bad4e79a3933112750c5bf7853.tar.xz
fw-update: Support host image update
Per the Redfish schema for the UpdateService, it supports all SoftwareInventory targets. On OpenBMC this is currently the BMC and the Host (BIOS) firmware. Introduced a new fwUpdateInProgress static variable so that the signal subscription could be disabled once the required interface was added. This prevented multiple call backs and multiple activations of the same image. Tested: Verified that a host and BMC image update worked as expected on a witherspoon system. $ curl -k -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/octet-stream" -X POST -T ./obmc-phosphor-image-witherspoon.ubi.mtd.tar https://${BMC_IP}/redfish/v1/UpdateService { "@Message.ExtendedInfo": [ { "@odata.type": "/redfish/v1/$metadata#Message.v1_0_0.Message", "Message": "Successfully Completed Request", "MessageArgs": [], "MessageId": "Base.1.4.0.Success", "Resolution": "None", "Severity": "OK" } ] } Change-Id: I7bb9381f1b79bf65604464b628ef98646951d840 Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Diffstat (limited to 'redfish-core/lib/update_service.hpp')
-rw-r--r--redfish-core/lib/update_service.hpp142
1 files changed, 92 insertions, 50 deletions
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index aaaf85baf4..9f16e1e95c 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -24,7 +24,10 @@
namespace redfish
{
+// Match signals added on software path
static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
+// Only allow one update at a time
+static bool fwUpdateInProgress = false;
class UpdateService : public Node
{
@@ -58,36 +61,113 @@ class UpdateService : public Node
{"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
res.end();
}
- static void activateImage(const std::string &objPath)
+ static void cleanUp()
{
+ fwUpdateInProgress = false;
+ fwUpdateMatcher = nullptr;
+ }
+ static void activateImage(const std::string &objPath,
+ const std::string &service)
+ {
+ BMCWEB_LOG_DEBUG << "Activate image for " << objPath << " " << service;
crow::connections::systemBus->async_method_call(
- [objPath](const boost::system::error_code error_code) {
+ [](const boost::system::error_code error_code) {
if (error_code)
{
BMCWEB_LOG_DEBUG << "error_code = " << error_code;
BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
}
},
- "xyz.openbmc_project.Software.BMC.Updater", objPath,
- "org.freedesktop.DBus.Properties", "Set",
+ service, objPath, "org.freedesktop.DBus.Properties", "Set",
"xyz.openbmc_project.Software.Activation", "RequestedActivation",
std::variant<std::string>(
"xyz.openbmc_project.Software.Activation.RequestedActivations."
"Active"));
}
+ static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
+ boost::asio::deadline_timer &timeout,
+ sdbusplus::message::message &m)
+ {
+ std::vector<std::pair<
+ std::string,
+ std::vector<std::pair<std::string, std::variant<std::string>>>>>
+ interfacesProperties;
+
+ sdbusplus::message::object_path objPath;
+
+ m.read(objPath, interfacesProperties);
+
+ BMCWEB_LOG_DEBUG << "obj path = " << objPath.str;
+ for (auto &interface : interfacesProperties)
+ {
+ BMCWEB_LOG_DEBUG << "interface = " << interface.first;
+
+ if (interface.first == "xyz.openbmc_project.Software.Activation")
+ {
+ // Found our interface, disable callbacks
+ fwUpdateMatcher = nullptr;
+
+ // Retrieve service and activate
+ crow::connections::systemBus->async_method_call(
+ [objPath, asyncResp, &timeout](
+ const boost::system::error_code error_code,
+ const std::vector<std::pair<
+ std::string, std::vector<std::string>>> &objInfo) {
+ if (error_code)
+ {
+ BMCWEB_LOG_DEBUG << "error_code = " << error_code;
+ BMCWEB_LOG_DEBUG << "error msg = "
+ << error_code.message();
+ messages::internalError(asyncResp->res);
+ cleanUp();
+ return;
+ }
+ // Ensure we only got one service back
+ if (objInfo.size() != 1)
+ {
+ BMCWEB_LOG_ERROR << "Invalid Object Size "
+ << objInfo.size();
+ messages::internalError(asyncResp->res);
+ cleanUp();
+ return;
+ }
+ // cancel timer only when
+ // xyz.openbmc_project.Software.Activation interface
+ // is added
+ boost::system::error_code ec;
+ timeout.cancel(ec);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "error canceling timer " << ec;
+ }
+ UpdateService::activateImage(objPath.str,
+ objInfo[0].first);
+ redfish::messages::success(asyncResp->res);
+ fwUpdateInProgress = false;
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetObject",
+ objPath.str,
+ std::array<const char *, 1>{
+ "xyz.openbmc_project.Software.Activation"});
+ }
+ }
+ }
void doPost(crow::Response &res, const crow::Request &req,
const std::vector<std::string> &params) override
{
BMCWEB_LOG_DEBUG << "doPost...";
// Only allow one FW update at a time
- if (fwUpdateMatcher != nullptr)
+ if (fwUpdateInProgress != false)
{
res.addHeader("Retry-After", "30");
- messages::serviceTemporarilyUnavailable(res, "3");
+ messages::serviceTemporarilyUnavailable(res, "30");
res.end();
return;
}
+
// Make this const static so it survives outside this method
static boost::asio::deadline_timer timeout(
*req.ioService, boost::posix_time::seconds(5));
@@ -95,7 +175,7 @@ class UpdateService : public Node
timeout.expires_from_now(boost::posix_time::seconds(5));
timeout.async_wait([&res](const boost::system::error_code &ec) {
- fwUpdateMatcher = nullptr;
+ cleanUp();
if (ec == boost::asio::error::operation_aborted)
{
// expected, we were canceled before the timer completed.
@@ -115,52 +195,14 @@ class UpdateService : public Node
res.end();
});
- auto callback = [&res](sdbusplus::message::message &m) {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+ auto callback = [asyncResp](sdbusplus::message::message &m) {
BMCWEB_LOG_DEBUG << "Match fired";
-
- if (m.is_method_error())
- {
- BMCWEB_LOG_DEBUG << "Dbus method error!!!";
- res.end();
- return;
- }
- std::vector<std::pair<
- std::string,
- std::vector<std::pair<std::string, std::variant<std::string>>>>>
- interfacesProperties;
-
- sdbusplus::message::object_path objPath;
-
- m.read(objPath, interfacesProperties); // Read in the object path
- // that was just created
- // std::string str_objpath = objPath.str; // keep a copy for
- // constructing response message
- BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; // str_objpath;
- for (auto &interface : interfacesProperties)
- {
- BMCWEB_LOG_DEBUG << "interface = " << interface.first;
-
- if (interface.first ==
- "xyz.openbmc_project.Software.Activation")
- {
- // cancel timer only when
- // xyz.openbmc_project.Software.Activation interface is
- // added
- boost::system::error_code ec;
- timeout.cancel(ec);
- if (ec)
- {
- BMCWEB_LOG_ERROR << "error canceling timer " << ec;
- }
- UpdateService::activateImage(objPath.str); // str_objpath);
- redfish::messages::success(res);
- BMCWEB_LOG_DEBUG << "ending response";
- res.end();
- fwUpdateMatcher = nullptr;
- }
- }
+ softwareInterfaceAdded(asyncResp, timeout, m);
};
+ fwUpdateInProgress = true;
+
fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
*crow::connections::systemBus,
"interface='org.freedesktop.DBus.ObjectManager',type='signal',"