blob: 6fe2702377fb87001ae132e229255c48f6ab803f [file] [log] [blame]
Adriana Kobylak2d8fa222017-03-15 12:34:32 -05001#include "config.h"
Gunnar Millsf6ed5892018-09-07 17:08:02 -05002
Adriana Kobylak2d8fa222017-03-15 12:34:32 -05003#include "item_updater.hpp"
Gunnar Millsf6ed5892018-09-07 17:08:02 -05004
Gunnar Millsf6ed5892018-09-07 17:08:02 -05005#include "xyz/openbmc_project/Common/error.hpp"
6
Lei YUa9ac9272019-02-22 16:38:35 +08007#include <filesystem>
Gunnar Millsf6ed5892018-09-07 17:08:02 -05008#include <phosphor-logging/elog-errors.hpp>
9#include <phosphor-logging/log.hpp>
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050010
11namespace openpower
12{
13namespace software
14{
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050015namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050016{
Lei YUa9ac9272019-02-22 16:38:35 +080017namespace server = sdbusplus::xyz::openbmc_project::Software::server;
18namespace fs = std::filesystem;
19
Eddie James13fc66a2017-08-31 15:36:44 -050020using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050021using namespace phosphor::logging;
22
Lei YUa9ac9272019-02-22 16:38:35 +080023void ItemUpdater::createActivation(sdbusplus::message::message& m)
24{
25 using SVersion = server::Version;
26 using VersionPurpose = SVersion::VersionPurpose;
Lei YUa9ac9272019-02-22 16:38:35 +080027
28 sdbusplus::message::object_path objPath;
Patrick Williams573552a2020-06-05 16:21:05 -050029 std::map<std::string, std::map<std::string, std::variant<std::string>>>
Lei YUa9ac9272019-02-22 16:38:35 +080030 interfaces;
31 m.read(objPath, interfaces);
32
33 std::string path(std::move(objPath));
34 std::string filePath;
35 auto purpose = VersionPurpose::Unknown;
36 std::string version;
37
38 for (const auto& intf : interfaces)
39 {
40 if (intf.first == VERSION_IFACE)
41 {
42 for (const auto& property : intf.second)
43 {
44 if (property.first == "Purpose")
45 {
46 // Only process the Host and System images
47 auto value = SVersion::convertVersionPurposeFromString(
Patrick Williams550f31b2020-05-13 11:15:24 -050048 std::get<std::string>(property.second));
Lei YUa9ac9272019-02-22 16:38:35 +080049
50 if (value == VersionPurpose::Host ||
51 value == VersionPurpose::System)
52 {
53 purpose = value;
54 }
55 }
56 else if (property.first == "Version")
57 {
Patrick Williams550f31b2020-05-13 11:15:24 -050058 version = std::get<std::string>(property.second);
Lei YUa9ac9272019-02-22 16:38:35 +080059 }
60 }
61 }
62 else if (intf.first == FILEPATH_IFACE)
63 {
64 for (const auto& property : intf.second)
65 {
66 if (property.first == "Path")
67 {
Patrick Williams550f31b2020-05-13 11:15:24 -050068 filePath = std::get<std::string>(property.second);
Lei YUa9ac9272019-02-22 16:38:35 +080069 }
70 }
71 }
72 }
73 if ((filePath.empty()) || (purpose == VersionPurpose::Unknown))
74 {
75 return;
76 }
77
78 // Version id is the last item in the path
79 auto pos = path.rfind("/");
80 if (pos == std::string::npos)
81 {
82 log<level::ERR>("No version id found in object path",
83 entry("OBJPATH=%s", path.c_str()));
84 return;
85 }
86
87 auto versionId = path.substr(pos + 1);
88
89 if (activations.find(versionId) == activations.end())
90 {
91 // Determine the Activation state by processing the given image dir.
92 auto activationState = server::Activation::Activations::Invalid;
93 AssociationList associations = {};
94 if (validateImage(filePath))
95 {
96 activationState = server::Activation::Activations::Ready;
97 // Create an association to the host inventory item
98 associations.emplace_back(std::make_tuple(
99 ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION,
100 HOST_INVENTORY_PATH));
101 }
102
103 fs::path manifestPath(filePath);
104 manifestPath /= MANIFEST_FILE;
105 std::string extendedVersion =
106 (Version::getValue(
107 manifestPath.string(),
108 std::map<std::string, std::string>{{"extended_version", ""}}))
109 .begin()
110 ->second;
111
112 auto activation = createActivationObject(
113 path, versionId, extendedVersion, activationState, associations);
114 activations.emplace(versionId, std::move(activation));
115
116 auto versionPtr =
117 createVersionObject(path, versionId, version, purpose, filePath);
118 versions.emplace(versionId, std::move(versionPtr));
119 }
120 return;
121}
122
Lei YUf3ce4332019-02-21 14:09:49 +0800123void ItemUpdater::createActiveAssociation(const std::string& path)
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500124{
Lei YUf3ce4332019-02-21 14:09:49 +0800125 assocs.emplace_back(
126 std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path));
127 associations(assocs);
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500128}
129
Adriana Kobylak3c810372020-07-15 16:47:03 -0500130void ItemUpdater::createUpdateableAssociation(const std::string& path)
131{
132 assocs.emplace_back(std::make_tuple(UPDATEABLE_FWD_ASSOCIATION,
133 UPDATEABLE_REV_ASSOCIATION, path));
134 associations(assocs);
135}
136
Lei YUf3ce4332019-02-21 14:09:49 +0800137void ItemUpdater::updateFunctionalAssociation(const std::string& versionId)
Saqib Khan7254f0e2017-04-10 21:45:37 -0500138{
Lei YUf3ce4332019-02-21 14:09:49 +0800139 std::string path = std::string{SOFTWARE_OBJPATH} + '/' + versionId;
140 // remove all functional associations
141 for (auto iter = assocs.begin(); iter != assocs.end();)
Saqib Khan4c5d7442017-07-18 00:43:52 -0500142 {
Lei YUf3ce4332019-02-21 14:09:49 +0800143 if ((std::get<0>(*iter)).compare(FUNCTIONAL_FWD_ASSOCIATION) == 0)
Saqib Khan4c5d7442017-07-18 00:43:52 -0500144 {
Lei YUf3ce4332019-02-21 14:09:49 +0800145 iter = assocs.erase(iter);
Saqib Khan4c5d7442017-07-18 00:43:52 -0500146 }
Lei YUf3ce4332019-02-21 14:09:49 +0800147 else
Saqib Khan2be9ba92017-09-26 22:44:10 -0500148 {
Lei YUf3ce4332019-02-21 14:09:49 +0800149 ++iter;
Saqib Khan2be9ba92017-09-26 22:44:10 -0500150 }
Saqib Khan4c5d7442017-07-18 00:43:52 -0500151 }
Lei YUf3ce4332019-02-21 14:09:49 +0800152 assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION,
153 FUNCTIONAL_REV_ASSOCIATION, path));
154 associations(assocs);
Saqib Khan7254f0e2017-04-10 21:45:37 -0500155}
156
Lei YUf3ce4332019-02-21 14:09:49 +0800157void ItemUpdater::removeAssociation(const std::string& path)
Saqib Khana8ade7e2017-04-12 10:27:56 -0500158{
Lei YUf3ce4332019-02-21 14:09:49 +0800159 for (auto iter = assocs.begin(); iter != assocs.end();)
Saqib Khana8ade7e2017-04-12 10:27:56 -0500160 {
Lei YUf3ce4332019-02-21 14:09:49 +0800161 if ((std::get<2>(*iter)).compare(path) == 0)
162 {
163 iter = assocs.erase(iter);
164 associations(assocs);
165 }
166 else
167 {
168 ++iter;
169 }
170 }
171}
172
173bool ItemUpdater::erase(std::string entryId)
174{
175 if (isVersionFunctional(entryId) && isChassisOn())
176 {
177 log<level::ERR>(("Error: Version " + entryId +
178 " is currently active and running on the host."
179 " Unable to remove.")
180 .c_str());
181 return false;
182 }
183
184 // Removing entry in versions map
185 auto it = versions.find(entryId);
186 if (it == versions.end())
187 {
188 log<level::ERR>(("Error: Failed to find version " + entryId +
189 " in item updater versions map."
190 " Unable to remove.")
191 .c_str());
Saqib Khana8ade7e2017-04-12 10:27:56 -0500192 }
193 else
194 {
Lei YUf3ce4332019-02-21 14:09:49 +0800195 versions.erase(entryId);
Saqib Khana8ade7e2017-04-12 10:27:56 -0500196 }
Saqib Khana8ade7e2017-04-12 10:27:56 -0500197
Lei YUf3ce4332019-02-21 14:09:49 +0800198 // Removing entry in activations map
199 auto ita = activations.find(entryId);
200 if (ita == activations.end())
Adriana Kobylak0bd65052018-07-09 10:55:56 -0500201 {
Lei YUf3ce4332019-02-21 14:09:49 +0800202 log<level::ERR>(("Error: Failed to find version " + entryId +
203 " in item updater activations map."
204 " Unable to remove.")
205 .c_str());
Adriana Kobylak0bd65052018-07-09 10:55:56 -0500206 }
Lei YUf3ce4332019-02-21 14:09:49 +0800207 else
Michael Tritzbb31f022017-11-22 11:51:29 -0600208 {
Lei YUf3ce4332019-02-21 14:09:49 +0800209 removeAssociation(ita->second->path);
210 activations.erase(entryId);
Michael Tritzbb31f022017-11-22 11:51:29 -0600211 }
Eddie James13fc66a2017-08-31 15:36:44 -0500212 return true;
213}
214
215bool ItemUpdater::isChassisOn()
216{
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600217 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
218 MAPPER_INTERFACE, "GetObject");
Eddie James13fc66a2017-08-31 15:36:44 -0500219
220 mapperCall.append(CHASSIS_STATE_PATH,
221 std::vector<std::string>({CHASSIS_STATE_OBJ}));
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500222
223 std::map<std::string, std::vector<std::string>> mapperResponse;
224
225 try
226 {
227 auto mapperResponseMsg = bus.call(mapperCall);
228 mapperResponseMsg.read(mapperResponse);
229 if (mapperResponse.empty())
230 {
231 log<level::ERR>("Invalid Response from mapper");
232 elog<InternalFailure>();
233 }
234 }
235 catch (const sdbusplus::exception::SdBusError& e)
Eddie James13fc66a2017-08-31 15:36:44 -0500236 {
237 log<level::ERR>("Error in Mapper call");
238 elog<InternalFailure>();
239 }
Eddie James13fc66a2017-08-31 15:36:44 -0500240
241 auto method = bus.new_method_call((mapperResponse.begin()->first).c_str(),
242 CHASSIS_STATE_PATH,
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600243 SYSTEMD_PROPERTY_INTERFACE, "Get");
Eddie James13fc66a2017-08-31 15:36:44 -0500244 method.append(CHASSIS_STATE_OBJ, "CurrentPowerState");
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500245
Patrick Williams212102e2020-05-13 17:50:50 -0500246 std::variant<std::string> currentChassisState;
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500247
248 try
249 {
250 auto response = bus.call(method);
251 response.read(currentChassisState);
Patrick Williams550f31b2020-05-13 11:15:24 -0500252 auto strParam = std::get<std::string>(currentChassisState);
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500253 return (strParam != CHASSIS_STATE_OFF);
254 }
255 catch (const sdbusplus::exception::SdBusError& e)
Eddie James13fc66a2017-08-31 15:36:44 -0500256 {
257 log<level::ERR>("Error in fetching current Chassis State",
Gunnar Mills850d5f62017-10-19 17:04:38 -0500258 entry("MAPPERRESPONSE=%s",
Eddie James13fc66a2017-08-31 15:36:44 -0500259 (mapperResponse.begin()->first).c_str()));
260 elog<InternalFailure>();
261 }
Eddie James13fc66a2017-08-31 15:36:44 -0500262}
263
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500264} // namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500265} // namespace software
266} // namespace openpower