| Adriana Kobylak | 2d8fa22 | 2017-03-15 12:34:32 -0500 | [diff] [blame] | 1 | #include "config.h" | 
| Gunnar Mills | f6ed589 | 2018-09-07 17:08:02 -0500 | [diff] [blame] | 2 |  | 
| Adriana Kobylak | 2d8fa22 | 2017-03-15 12:34:32 -0500 | [diff] [blame] | 3 | #include "item_updater.hpp" | 
| Gunnar Mills | f6ed589 | 2018-09-07 17:08:02 -0500 | [diff] [blame] | 4 |  | 
| Gunnar Mills | f6ed589 | 2018-09-07 17:08:02 -0500 | [diff] [blame] | 5 | #include "xyz/openbmc_project/Common/error.hpp" | 
 | 6 |  | 
| Gunnar Mills | f6ed589 | 2018-09-07 17:08:02 -0500 | [diff] [blame] | 7 | #include <phosphor-logging/elog-errors.hpp> | 
 | 8 | #include <phosphor-logging/log.hpp> | 
| Adriana Kobylak | 2d8fa22 | 2017-03-15 12:34:32 -0500 | [diff] [blame] | 9 |  | 
| Brad Bishop | 8facccf | 2020-11-04 09:44:58 -0500 | [diff] [blame] | 10 | #include <filesystem> | 
 | 11 |  | 
| Adriana Kobylak | 2d8fa22 | 2017-03-15 12:34:32 -0500 | [diff] [blame] | 12 | namespace openpower | 
 | 13 | { | 
 | 14 | namespace software | 
 | 15 | { | 
| Adriana Kobylak | befe5ce | 2017-04-05 15:57:44 -0500 | [diff] [blame] | 16 | namespace updater | 
| Adriana Kobylak | 2d8fa22 | 2017-03-15 12:34:32 -0500 | [diff] [blame] | 17 | { | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 18 | namespace server = sdbusplus::xyz::openbmc_project::Software::server; | 
 | 19 | namespace fs = std::filesystem; | 
 | 20 |  | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 21 | using namespace sdbusplus::xyz::openbmc_project::Common::Error; | 
| Adriana Kobylak | b66ac3a | 2017-03-28 13:33:20 -0500 | [diff] [blame] | 22 | using namespace phosphor::logging; | 
 | 23 |  | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 24 | void ItemUpdater::createActivation(sdbusplus::message::message& m) | 
 | 25 | { | 
 | 26 |     using SVersion = server::Version; | 
 | 27 |     using VersionPurpose = SVersion::VersionPurpose; | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 28 |  | 
 | 29 |     sdbusplus::message::object_path objPath; | 
| Patrick Williams | 573552a | 2020-06-05 16:21:05 -0500 | [diff] [blame] | 30 |     std::map<std::string, std::map<std::string, std::variant<std::string>>> | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 31 |         interfaces; | 
 | 32 |     m.read(objPath, interfaces); | 
 | 33 |  | 
 | 34 |     std::string path(std::move(objPath)); | 
 | 35 |     std::string filePath; | 
 | 36 |     auto purpose = VersionPurpose::Unknown; | 
 | 37 |     std::string version; | 
 | 38 |  | 
 | 39 |     for (const auto& intf : interfaces) | 
 | 40 |     { | 
 | 41 |         if (intf.first == VERSION_IFACE) | 
 | 42 |         { | 
 | 43 |             for (const auto& property : intf.second) | 
 | 44 |             { | 
 | 45 |                 if (property.first == "Purpose") | 
 | 46 |                 { | 
 | 47 |                     // Only process the Host and System images | 
 | 48 |                     auto value = SVersion::convertVersionPurposeFromString( | 
| Patrick Williams | 550f31b | 2020-05-13 11:15:24 -0500 | [diff] [blame] | 49 |                         std::get<std::string>(property.second)); | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 50 |  | 
 | 51 |                     if (value == VersionPurpose::Host || | 
 | 52 |                         value == VersionPurpose::System) | 
 | 53 |                     { | 
 | 54 |                         purpose = value; | 
 | 55 |                     } | 
 | 56 |                 } | 
 | 57 |                 else if (property.first == "Version") | 
 | 58 |                 { | 
| Patrick Williams | 550f31b | 2020-05-13 11:15:24 -0500 | [diff] [blame] | 59 |                     version = std::get<std::string>(property.second); | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 60 |                 } | 
 | 61 |             } | 
 | 62 |         } | 
 | 63 |         else if (intf.first == FILEPATH_IFACE) | 
 | 64 |         { | 
 | 65 |             for (const auto& property : intf.second) | 
 | 66 |             { | 
 | 67 |                 if (property.first == "Path") | 
 | 68 |                 { | 
| Patrick Williams | 550f31b | 2020-05-13 11:15:24 -0500 | [diff] [blame] | 69 |                     filePath = std::get<std::string>(property.second); | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 70 |                 } | 
 | 71 |             } | 
 | 72 |         } | 
 | 73 |     } | 
 | 74 |     if ((filePath.empty()) || (purpose == VersionPurpose::Unknown)) | 
 | 75 |     { | 
 | 76 |         return; | 
 | 77 |     } | 
 | 78 |  | 
 | 79 |     // Version id is the last item in the path | 
 | 80 |     auto pos = path.rfind("/"); | 
 | 81 |     if (pos == std::string::npos) | 
 | 82 |     { | 
 | 83 |         log<level::ERR>("No version id found in object path", | 
 | 84 |                         entry("OBJPATH=%s", path.c_str())); | 
 | 85 |         return; | 
 | 86 |     } | 
 | 87 |  | 
 | 88 |     auto versionId = path.substr(pos + 1); | 
 | 89 |  | 
 | 90 |     if (activations.find(versionId) == activations.end()) | 
 | 91 |     { | 
 | 92 |         // Determine the Activation state by processing the given image dir. | 
 | 93 |         auto activationState = server::Activation::Activations::Invalid; | 
 | 94 |         AssociationList associations = {}; | 
 | 95 |         if (validateImage(filePath)) | 
 | 96 |         { | 
 | 97 |             activationState = server::Activation::Activations::Ready; | 
 | 98 |             // Create an association to the host inventory item | 
 | 99 |             associations.emplace_back(std::make_tuple( | 
 | 100 |                 ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION, | 
 | 101 |                 HOST_INVENTORY_PATH)); | 
 | 102 |         } | 
 | 103 |  | 
 | 104 |         fs::path manifestPath(filePath); | 
 | 105 |         manifestPath /= MANIFEST_FILE; | 
 | 106 |         std::string extendedVersion = | 
 | 107 |             (Version::getValue( | 
 | 108 |                  manifestPath.string(), | 
 | 109 |                  std::map<std::string, std::string>{{"extended_version", ""}})) | 
 | 110 |                 .begin() | 
 | 111 |                 ->second; | 
 | 112 |  | 
 | 113 |         auto activation = createActivationObject( | 
 | 114 |             path, versionId, extendedVersion, activationState, associations); | 
 | 115 |         activations.emplace(versionId, std::move(activation)); | 
 | 116 |  | 
 | 117 |         auto versionPtr = | 
 | 118 |             createVersionObject(path, versionId, version, purpose, filePath); | 
 | 119 |         versions.emplace(versionId, std::move(versionPtr)); | 
 | 120 |     } | 
 | 121 |     return; | 
 | 122 | } | 
 | 123 |  | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 124 | void ItemUpdater::createActiveAssociation(const std::string& path) | 
| Adriana Kobylak | 2d8fa22 | 2017-03-15 12:34:32 -0500 | [diff] [blame] | 125 | { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 126 |     assocs.emplace_back( | 
 | 127 |         std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path)); | 
 | 128 |     associations(assocs); | 
| Adriana Kobylak | 2d8fa22 | 2017-03-15 12:34:32 -0500 | [diff] [blame] | 129 | } | 
 | 130 |  | 
| Adriana Kobylak | 3c81037 | 2020-07-15 16:47:03 -0500 | [diff] [blame] | 131 | void ItemUpdater::createUpdateableAssociation(const std::string& path) | 
 | 132 | { | 
 | 133 |     assocs.emplace_back(std::make_tuple(UPDATEABLE_FWD_ASSOCIATION, | 
 | 134 |                                         UPDATEABLE_REV_ASSOCIATION, path)); | 
 | 135 |     associations(assocs); | 
 | 136 | } | 
 | 137 |  | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 138 | void ItemUpdater::updateFunctionalAssociation(const std::string& versionId) | 
| Saqib Khan | 7254f0e | 2017-04-10 21:45:37 -0500 | [diff] [blame] | 139 | { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 140 |     std::string path = std::string{SOFTWARE_OBJPATH} + '/' + versionId; | 
 | 141 |     // remove all functional associations | 
 | 142 |     for (auto iter = assocs.begin(); iter != assocs.end();) | 
| Saqib Khan | 4c5d744 | 2017-07-18 00:43:52 -0500 | [diff] [blame] | 143 |     { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 144 |         if ((std::get<0>(*iter)).compare(FUNCTIONAL_FWD_ASSOCIATION) == 0) | 
| Saqib Khan | 4c5d744 | 2017-07-18 00:43:52 -0500 | [diff] [blame] | 145 |         { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 146 |             iter = assocs.erase(iter); | 
| Saqib Khan | 4c5d744 | 2017-07-18 00:43:52 -0500 | [diff] [blame] | 147 |         } | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 148 |         else | 
| Saqib Khan | 2be9ba9 | 2017-09-26 22:44:10 -0500 | [diff] [blame] | 149 |         { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 150 |             ++iter; | 
| Saqib Khan | 2be9ba9 | 2017-09-26 22:44:10 -0500 | [diff] [blame] | 151 |         } | 
| Saqib Khan | 4c5d744 | 2017-07-18 00:43:52 -0500 | [diff] [blame] | 152 |     } | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 153 |     assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION, | 
 | 154 |                                         FUNCTIONAL_REV_ASSOCIATION, path)); | 
 | 155 |     associations(assocs); | 
| Saqib Khan | 7254f0e | 2017-04-10 21:45:37 -0500 | [diff] [blame] | 156 | } | 
 | 157 |  | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 158 | void ItemUpdater::removeAssociation(const std::string& path) | 
| Saqib Khan | a8ade7e | 2017-04-12 10:27:56 -0500 | [diff] [blame] | 159 | { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 160 |     for (auto iter = assocs.begin(); iter != assocs.end();) | 
| Saqib Khan | a8ade7e | 2017-04-12 10:27:56 -0500 | [diff] [blame] | 161 |     { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 162 |         if ((std::get<2>(*iter)).compare(path) == 0) | 
 | 163 |         { | 
 | 164 |             iter = assocs.erase(iter); | 
 | 165 |             associations(assocs); | 
 | 166 |         } | 
 | 167 |         else | 
 | 168 |         { | 
 | 169 |             ++iter; | 
 | 170 |         } | 
 | 171 |     } | 
 | 172 | } | 
 | 173 |  | 
 | 174 | bool ItemUpdater::erase(std::string entryId) | 
 | 175 | { | 
 | 176 |     if (isVersionFunctional(entryId) && isChassisOn()) | 
 | 177 |     { | 
 | 178 |         log<level::ERR>(("Error: Version " + entryId + | 
 | 179 |                          " is currently active and running on the host." | 
 | 180 |                          " Unable to remove.") | 
 | 181 |                             .c_str()); | 
 | 182 |         return false; | 
 | 183 |     } | 
 | 184 |  | 
 | 185 |     // Removing entry in versions map | 
 | 186 |     auto it = versions.find(entryId); | 
 | 187 |     if (it == versions.end()) | 
 | 188 |     { | 
 | 189 |         log<level::ERR>(("Error: Failed to find version " + entryId + | 
 | 190 |                          " in item updater versions map." | 
 | 191 |                          " Unable to remove.") | 
 | 192 |                             .c_str()); | 
| Saqib Khan | a8ade7e | 2017-04-12 10:27:56 -0500 | [diff] [blame] | 193 |     } | 
 | 194 |     else | 
 | 195 |     { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 196 |         versions.erase(entryId); | 
| Saqib Khan | a8ade7e | 2017-04-12 10:27:56 -0500 | [diff] [blame] | 197 |     } | 
| Saqib Khan | a8ade7e | 2017-04-12 10:27:56 -0500 | [diff] [blame] | 198 |  | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 199 |     // Removing entry in activations map | 
 | 200 |     auto ita = activations.find(entryId); | 
 | 201 |     if (ita == activations.end()) | 
| Adriana Kobylak | 0bd6505 | 2018-07-09 10:55:56 -0500 | [diff] [blame] | 202 |     { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 203 |         log<level::ERR>(("Error: Failed to find version " + entryId + | 
 | 204 |                          " in item updater activations map." | 
 | 205 |                          " Unable to remove.") | 
 | 206 |                             .c_str()); | 
| Adriana Kobylak | 0bd6505 | 2018-07-09 10:55:56 -0500 | [diff] [blame] | 207 |     } | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 208 |     else | 
| Michael Tritz | bb31f02 | 2017-11-22 11:51:29 -0600 | [diff] [blame] | 209 |     { | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 210 |         removeAssociation(ita->second->path); | 
 | 211 |         activations.erase(entryId); | 
| Michael Tritz | bb31f02 | 2017-11-22 11:51:29 -0600 | [diff] [blame] | 212 |     } | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 213 |     return true; | 
 | 214 | } | 
 | 215 |  | 
 | 216 | bool ItemUpdater::isChassisOn() | 
 | 217 | { | 
| Adriana Kobylak | 70dcb63 | 2018-02-27 15:46:52 -0600 | [diff] [blame] | 218 |     auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, | 
 | 219 |                                           MAPPER_INTERFACE, "GetObject"); | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 220 |  | 
 | 221 |     mapperCall.append(CHASSIS_STATE_PATH, | 
 | 222 |                       std::vector<std::string>({CHASSIS_STATE_OBJ})); | 
| Adriana Kobylak | b8cb0cc | 2019-05-31 09:58:04 -0500 | [diff] [blame] | 223 |  | 
 | 224 |     std::map<std::string, std::vector<std::string>> mapperResponse; | 
 | 225 |  | 
 | 226 |     try | 
 | 227 |     { | 
 | 228 |         auto mapperResponseMsg = bus.call(mapperCall); | 
 | 229 |         mapperResponseMsg.read(mapperResponse); | 
 | 230 |         if (mapperResponse.empty()) | 
 | 231 |         { | 
 | 232 |             log<level::ERR>("Invalid Response from mapper"); | 
 | 233 |             elog<InternalFailure>(); | 
 | 234 |         } | 
 | 235 |     } | 
| Patrick Williams | 7b5685d | 2021-09-02 09:32:14 -0500 | [diff] [blame] | 236 |     catch (const sdbusplus::exception::exception& e) | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 237 |     { | 
 | 238 |         log<level::ERR>("Error in Mapper call"); | 
 | 239 |         elog<InternalFailure>(); | 
 | 240 |     } | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 241 |  | 
 | 242 |     auto method = bus.new_method_call((mapperResponse.begin()->first).c_str(), | 
 | 243 |                                       CHASSIS_STATE_PATH, | 
| Adriana Kobylak | 70dcb63 | 2018-02-27 15:46:52 -0600 | [diff] [blame] | 244 |                                       SYSTEMD_PROPERTY_INTERFACE, "Get"); | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 245 |     method.append(CHASSIS_STATE_OBJ, "CurrentPowerState"); | 
| Adriana Kobylak | b8cb0cc | 2019-05-31 09:58:04 -0500 | [diff] [blame] | 246 |  | 
| Patrick Williams | 212102e | 2020-05-13 17:50:50 -0500 | [diff] [blame] | 247 |     std::variant<std::string> currentChassisState; | 
| Adriana Kobylak | b8cb0cc | 2019-05-31 09:58:04 -0500 | [diff] [blame] | 248 |  | 
 | 249 |     try | 
 | 250 |     { | 
 | 251 |         auto response = bus.call(method); | 
 | 252 |         response.read(currentChassisState); | 
| Patrick Williams | 550f31b | 2020-05-13 11:15:24 -0500 | [diff] [blame] | 253 |         auto strParam = std::get<std::string>(currentChassisState); | 
| Adriana Kobylak | b8cb0cc | 2019-05-31 09:58:04 -0500 | [diff] [blame] | 254 |         return (strParam != CHASSIS_STATE_OFF); | 
 | 255 |     } | 
| Patrick Williams | 7b5685d | 2021-09-02 09:32:14 -0500 | [diff] [blame] | 256 |     catch (const sdbusplus::exception::exception& e) | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 257 |     { | 
 | 258 |         log<level::ERR>("Error in fetching current Chassis State", | 
| Gunnar Mills | 850d5f6 | 2017-10-19 17:04:38 -0500 | [diff] [blame] | 259 |                         entry("MAPPERRESPONSE=%s", | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 260 |                               (mapperResponse.begin()->first).c_str())); | 
 | 261 |         elog<InternalFailure>(); | 
 | 262 |     } | 
| Eddie James | 13fc66a | 2017-08-31 15:36:44 -0500 | [diff] [blame] | 263 | } | 
 | 264 |  | 
| Adriana Kobylak | befe5ce | 2017-04-05 15:57:44 -0500 | [diff] [blame] | 265 | } // namespace updater | 
| Adriana Kobylak | 2d8fa22 | 2017-03-15 12:34:32 -0500 | [diff] [blame] | 266 | } // namespace software | 
 | 267 | } // namespace openpower |