diff options
author | Saqib Khan <khansa@us.ibm.com> | 2017-08-10 15:29:34 -0500 |
---|---|---|
committer | Michael Tritz <mtritz@us.ibm.com> | 2017-08-30 12:46:12 -0500 |
commit | 1eef62de893e619a8bc0c250e0b439178da11e8f (patch) | |
tree | b3f252891a0a6d3bbda400da819e482e9a559006 | |
parent | b60add1e003373cbd48423d4ee60d0b580031f39 (diff) | |
download | phosphor-bmc-code-mgmt-1eef62de893e619a8bc0c250e0b439178da11e8f.tar.gz phosphor-bmc-code-mgmt-1eef62de893e619a8bc0c250e0b439178da11e8f.zip |
BMC: Restore version and activation dbus objects on BMC reboot.
- Read the /media/ dir for active bmc versions. Each active
version has a /etc/os-release inside /media/ which is used to
recreate the version and activation objects.
Resolves openbmc/openbmc#2137
Change-Id: I40e97396b0912095868172a5a6566e2189a3446b
Signed-off-by: Saqib Khan <khansa@us.ibm.com>
-rwxr-xr-x | configure.ac | 6 | ||||
-rw-r--r-- | item_updater.cpp | 108 | ||||
-rw-r--r-- | serialize.cpp | 61 | ||||
-rw-r--r-- | serialize.hpp | 3 | ||||
-rw-r--r-- | version.cpp | 4 | ||||
-rwxr-xr-x | version.hpp | 5 |
6 files changed, 155 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac index 22eece4..c7730a3 100755 --- a/configure.ac +++ b/configure.ac @@ -76,6 +76,12 @@ AC_DEFINE(VERSION_IFACE, "xyz.openbmc_project.Software.Version", [The software version manager interface]) AC_DEFINE(FILEPATH_IFACE, "xyz.openbmc_project.Common.FilePath", [The common file path interface]) +AC_DEFINE(OS_RELEASE_FILE, "/etc/os-release", + [The name of the BMC table of contents file]) +AC_DEFINE(MEDIA_DIR, "/media/", + [The base dir where all RO partitions are mounted]) +AC_DEFINE(BMC_RO_PREFIX, "/media/ro-", + [The prefix path for the versioned read-only bmc partitions]) AC_DEFINE(PERSIST_DIR, "/var/lib/obmc/phosphor-bmc-code-mgmt/", [The dir where activation data is stored in files]) AC_DEFINE(SYSTEMD_BUSNAME, "org.freedesktop.systemd1", diff --git a/item_updater.cpp b/item_updater.cpp index aa072ef..7d7df3f 100644 --- a/item_updater.cpp +++ b/item_updater.cpp @@ -145,40 +145,88 @@ void ItemUpdater::createActivation(sdbusplus::message::message& msg) void ItemUpdater::processBMCImage() { - using VersionClass = phosphor::software::manager::Version; - - auto purpose = server::Version::VersionPurpose::BMC; - auto version = phosphor::software::manager::Version::getBMCVersion(); - auto id = phosphor::software::manager::Version::getId(version); - auto path = std::string{SOFTWARE_OBJPATH} + '/' + id; - // Create an association to the BMC inventory item AssociationList associations{(std::make_tuple( ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION, bmcInventoryPath))}; - activations.insert(std::make_pair( - id, - std::make_unique<Activation>( - bus, - path, - *this, - id, - server::Activation::Activations::Active, - associations))); - versions.insert(std::make_pair( - id, - std::make_unique<VersionClass>( + // Read os-release from folders under /media/ to get + // BMC Software Versions. + for(const auto& iter : fs::directory_iterator(MEDIA_DIR)) + { + auto activationState = server::Activation::Activations::Active; + static const auto BMC_RO_PREFIX_LEN = strlen(BMC_RO_PREFIX); + + // Check if the BMC_RO_PREFIXis the prefix of the iter.path + if (0 == iter.path().native().compare(0, BMC_RO_PREFIX_LEN, + BMC_RO_PREFIX)) + { + auto osRelease = iter.path() / OS_RELEASE_FILE; + if (!fs::is_regular_file(osRelease)) + { + log<level::ERR>("Failed to read osRelease\n", + entry("FileName=%s", osRelease.string())); + activationState = server::Activation::Activations::Invalid; + } + auto version = + phosphor::software::manager::Version:: + getBMCVersion(osRelease); + if (version.empty()) + { + log<level::ERR>("Failed to read version from osRelease", + entry("FILENAME=%s", osRelease.string())); + activationState = server::Activation::Activations::Invalid; + } + // The versionId is extracted from the path + // for example /media/ro-2a1022fe + auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN); + auto purpose = server::Version::VersionPurpose::BMC; + auto path = fs::path(SOFTWARE_OBJPATH) / id; + + // Create Activation instance for this version. + activations.insert(std::make_pair( + id, + std::make_unique<Activation>( + bus, + path, + *this, + id, + server::Activation::Activations::Active, + associations))); + + // If Active, create RedundancyPriority instance for this version. + if (activationState == server::Activation::Activations::Active) + { + uint8_t priority = std::numeric_limits<uint8_t>::max(); + if (!restoreFromFile(id, priority)) + { + log<level::ERR>("Unable to restore priority from file.", + entry("VERSIONID=%s", id)); + } + activations.find(id)->second->redundancyPriority = + std::make_unique<RedundancyPriority>( bus, path, - version, - purpose, - "", - std::bind(&ItemUpdater::erase, + *(activations.find(id)->second), + priority); + } + + // Create Version instance for this version. + versions.insert(std::make_pair( + id, + std::make_unique< + phosphor::software::manager::Version>( + bus, + path, + version, + purpose, + "", + std::bind(&ItemUpdater::erase, this, std::placeholders::_1)))); - + } + } return; } @@ -186,6 +234,17 @@ void ItemUpdater::erase(std::string entryId) { // Delete ReadOnly partitions removeReadOnlyPartition(entryId); + removeFile(entryId); + + // Remove the priority environment variable. + auto serviceFile = "obmc-flash-bmc-setenv@" + entryId + ".service"; + auto method = bus.new_method_call( + SYSTEMD_BUSNAME, + SYSTEMD_PATH, + SYSTEMD_INTERFACE, + "StartUnit"); + method.append(serviceFile, "replace"); + bus.call_noreply(method); // Removing entry in versions map auto it = versions.find(entryId); @@ -212,7 +271,6 @@ void ItemUpdater::erase(std::string entryId) // If not, don't continue. this->activations.erase(entryId); - removeFile(entryId); } ItemUpdater::ActivationStatus ItemUpdater::validateSquashFSImage( diff --git a/serialize.cpp b/serialize.cpp index 8c97c89..da9e878 100644 --- a/serialize.cpp +++ b/serialize.cpp @@ -3,6 +3,7 @@ #include <cereal/archives/json.hpp> #include <fstream> #include "serialize.hpp" +#include <sdbusplus/server.hpp> namespace phosphor { @@ -15,6 +16,8 @@ namespace fs = std::experimental::filesystem; void storeToFile(std::string versionId, uint8_t priority) { + auto bus = sdbusplus::bus::new_default(); + if(!fs::is_directory(PERSIST_DIR)) { fs::create_directory(PERSIST_DIR); @@ -24,17 +27,69 @@ void storeToFile(std::string versionId, uint8_t priority) std::ofstream os(path.c_str()); cereal::JSONOutputArchive oarchive(os); oarchive(cereal::make_nvp("priority", priority)); + + std::string serviceFile = "obmc-flash-bmc-setenv@" + versionId + "\\x3d" + + std::to_string(priority) + ".service"; + auto method = bus.new_method_call( + SYSTEMD_BUSNAME, + SYSTEMD_PATH, + SYSTEMD_INTERFACE, + "StartUnit"); + method.append(serviceFile, "replace"); + bus.call_noreply(method); } -void restoreFromFile(std::string versionId, uint8_t& priority) +bool restoreFromFile(std::string versionId, uint8_t& priority) { std::string path = PERSIST_DIR + versionId; if (fs::exists(path)) { std::ifstream is(path.c_str(), std::ios::in); - cereal::JSONInputArchive iarchive(is); - iarchive(cereal::make_nvp("priority", priority)); + try + { + cereal::JSONInputArchive iarchive(is); + iarchive(cereal::make_nvp("priority", priority)); + return true; + } + catch(cereal::RapidJSONException& e) + { + fs::remove(path); + } } + + // Find the mtd device "u-boot-env" to retrieve the environment variables + std::ifstream mtdDevices("/proc/mtd"); + std::string device, devicePath; + + try + { + while (std::getline(mtdDevices, device)) { + if (device.find("u-boot-env") != std::string::npos) + { + devicePath = "/dev/" + device.substr(0, device.find(':')); + break; + } + } + + if (!devicePath.empty()) + { + std::ifstream input(devicePath.c_str()); + std::string envVars; + std::getline(input, envVars); + + if (envVars.find(versionId) != std::string::npos) + { + // Grab the environment variable for this versionId. These + // variables follow the format "versionId=priority\0" + auto var = envVars.substr(envVars.find(versionId)); + priority = std::stoi(var.substr(var.find('=') + 1)); + return true; + } + } + } + catch (const std::exception& e){} + + return false; } void removeFile(std::string versionId) diff --git a/serialize.hpp b/serialize.hpp index 7b6461f..03eea99 100644 --- a/serialize.hpp +++ b/serialize.hpp @@ -21,8 +21,9 @@ void storeToFile(std::string versionId, uint8_t priority); /** @brief Serialization function - restores activation information from file * @param[in] versionId - The version for which to retrieve information. * @param[in] priority - RedundancyPriority reference for that version. + * @return true if restore was successful, false if not **/ -void restoreFromFile(std::string versionId, uint8_t& priority); +bool restoreFromFile(std::string versionId, uint8_t& priority); /** @brief Removes the serial file for a given version. * @param[in] versionId - The version for which to remove a file, if it exists. diff --git a/version.cpp b/version.cpp index c7fab30..35df88f 100644 --- a/version.cpp +++ b/version.cpp @@ -72,13 +72,13 @@ std::string Version::getId(const std::string& version) return hexId.str(); } -std::string Version::getBMCVersion() +std::string Version::getBMCVersion(const std::string& releaseFilePath) { std::string versionKey = "VERSION_ID="; std::string version{}; std::ifstream efile; std::string line; - efile.open("/etc/os-release"); + efile.open(releaseFilePath); while (getline(efile, line)) { diff --git a/version.hpp b/version.hpp index ef6747f..cbc2bd7 100755 --- a/version.hpp +++ b/version.hpp @@ -73,9 +73,12 @@ class Version : public VersionInherit /** * @brief Get the active bmc version identifier. * + * @param[in] releaseFilePath - The Path to file which contains + * the release version. + * * @return The version identifier. */ - static std::string getBMCVersion(); + static std::string getBMCVersion(const std::string& releaseFilePath); /** * @brief Delete the d-bus object and image. |