summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie James <eajames@us.ibm.com>2017-08-31 15:36:44 -0500
committerPatrick Williams <patrick@stwcx.xyz>2017-09-13 21:33:35 +0000
commit13fc66ad2ec8d6e65dfb025e5c149c0256ff070d (patch)
treee5e4858516f1fb774bb974061126c512ccd224f0
parent3588acc8b011f7f39e19ddf77daf5b4e512a37da (diff)
downloadopenpower-pnor-code-mgmt-13fc66ad2ec8d6e65dfb025e5c149c0256ff070d.tar.gz
openpower-pnor-code-mgmt-13fc66ad2ec8d6e65dfb025e5c149c0256ff070d.zip
Add checks for currently running host image before erasing
- Check for Host state and the Active image. If the image we're trying to erase matches the Active image and the host is running, fail to erase the image. Resolves openbmc/openbmc#1986 Change-Id: Ia9488c9ede585494fa4449ef0e83af35d50d03f8 Signed-off-by: Eddie James <eajames@us.ibm.com>
-rw-r--r--item_updater.cpp82
-rwxr-xr-xitem_updater.hpp14
2 files changed, 96 insertions, 0 deletions
diff --git a/item_updater.cpp b/item_updater.cpp
index fcec2b1d4..1539f95c9 100644
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -1,7 +1,9 @@
#include <string>
#include <experimental/filesystem>
#include <fstream>
+#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
+#include "xyz/openbmc_project/Common/error.hpp"
#include <xyz/openbmc_project/Software/Version/server.hpp>
#include "version.hpp"
#include "config.h"
@@ -20,9 +22,15 @@ namespace updater
namespace server = sdbusplus::xyz::openbmc_project::Software::server;
namespace fs = std::experimental::filesystem;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using namespace phosphor::logging;
constexpr auto squashFSImage = "pnor.xz.squashfs";
+constexpr auto CHASSIS_STATE_PATH = "/xyz/openbmc_project/state/chassis0";
+constexpr auto CHASSIS_STATE_OBJ = "xyz.openbmc_project.State.Chassis";
+constexpr auto CHASSIS_STATE_OFF =
+ "xyz.openbmc_project.State.Chassis.PowerState.Off";
+constexpr auto SYSTEMD_PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
void ItemUpdater::createActivation(sdbusplus::message::message& m)
{
@@ -314,6 +322,74 @@ void ItemUpdater::reset()
return;
}
+bool ItemUpdater::isVersionFunctional(std::string versionId)
+{
+ if (!fs::exists(PNOR_RO_ACTIVE_PATH))
+ {
+ return false;
+ }
+
+ fs::path activeRO = fs::read_symlink(PNOR_RO_ACTIVE_PATH);
+
+ if (!fs::is_directory(activeRO))
+ {
+ return false;
+ }
+
+ if (activeRO.string().find(versionId) == std::string::npos)
+ {
+ return false;
+ }
+
+ // active PNOR is the version we're checking
+ return true;
+}
+
+bool ItemUpdater::isChassisOn()
+{
+ auto mapperCall = bus.new_method_call(
+ MAPPER_BUSNAME,
+ MAPPER_PATH,
+ MAPPER_INTERFACE,
+ "GetObject");
+
+ mapperCall.append(CHASSIS_STATE_PATH,
+ std::vector<std::string>({CHASSIS_STATE_OBJ}));
+ auto mapperResponseMsg = bus.call(mapperCall);
+ if (mapperResponseMsg.is_method_error())
+ {
+ log<level::ERR>("Error in Mapper call");
+ elog<InternalFailure>();
+ }
+ using MapperResponseType = std::map<std::string, std::vector<std::string>>;
+ MapperResponseType mapperResponse;
+ mapperResponseMsg.read(mapperResponse);
+ if (mapperResponse.empty())
+ {
+ log<level::ERR>("Invalid Response from mapper");
+ elog<InternalFailure>();
+ }
+
+ auto method = bus.new_method_call((mapperResponse.begin()->first).c_str(),
+ CHASSIS_STATE_PATH,
+ SYSTEMD_PROPERTY_INTERFACE,
+ "Get");
+ method.append(CHASSIS_STATE_OBJ, "CurrentPowerState");
+ auto response = bus.call(method);
+ if (response.is_method_error())
+ {
+ log<level::ERR>("Error in fetching current Chassis State",
+ entry("MapperResponse=%s",
+ (mapperResponse.begin()->first).c_str()));
+ elog<InternalFailure>();
+ }
+ sdbusplus::message::variant<std::string> currentChassisState;
+ response.read(currentChassisState);
+ auto strParam =
+ sdbusplus::message::variant_ns::get<std::string>(currentChassisState);
+ return (strParam != CHASSIS_STATE_OFF);
+}
+
void ItemUpdater::freePriority(uint8_t value, const std::string& versionId)
{
//TODO openbmc/openbmc#1896 Improve the performance of this function
@@ -347,6 +423,12 @@ bool ItemUpdater::isLowestPriority(uint8_t value)
void ItemUpdater::erase(std::string entryId)
{
+ if (isVersionFunctional(entryId) && isChassisOn()) {
+ log<level::ERR>(("Error: Version " + entryId + \
+ " is currently active and running on the host." \
+ " Unable to remove.").c_str());
+ return;
+ }
// Remove priority persistence file
removeFile(entryId);
diff --git a/item_updater.hpp b/item_updater.hpp
index 812c9fe26..8e6637ad9 100755
--- a/item_updater.hpp
+++ b/item_updater.hpp
@@ -151,6 +151,20 @@ class ItemUpdater : public ItemUpdaterInherit
/** @brief Host factory reset - clears PNOR partitions for each
* Activation dbus object */
void reset() override;
+
+ /** @brief Check whether the provided image id is the functional one
+ *
+ * @param[in] - versionId - The id of the image to check.
+ *
+ * @return - Returns true if this version is currently functional.
+ */
+ static bool isVersionFunctional(std::string versionId);
+
+ /** @brief Check whether the host is running
+ *
+ * @return - Returns true if the Chassis is powered on.
+ */
+ bool isChassisOn();
};
} // namespace updater
OpenPOWER on IntegriCloud