| Adriana Kobylak | 55f9e83 | 2017-05-14 16:13:00 -0500 | [diff] [blame] | 1 | #include <experimental/filesystem> | 
| Adriana Kobylak | befe5ce | 2017-04-05 15:57:44 -0500 | [diff] [blame] | 2 | #include "activation.hpp" | 
| Adriana Kobylak | 692b555 | 2017-04-17 14:02:58 -0500 | [diff] [blame] | 3 | #include "config.h" | 
| Saqib Khan | 81bac88 | 2017-06-08 12:17:01 -0500 | [diff] [blame] | 4 | #include "item_updater.hpp" | 
| Michael Tritz | 60bc20f | 2017-07-29 23:32:21 -0500 | [diff] [blame] | 5 | #include "serialize.hpp" | 
| Adriana Kobylak | befe5ce | 2017-04-05 15:57:44 -0500 | [diff] [blame] | 6 |  | 
|  | 7 | namespace openpower | 
|  | 8 | { | 
|  | 9 | namespace software | 
|  | 10 | { | 
|  | 11 | namespace updater | 
|  | 12 | { | 
|  | 13 |  | 
| Adriana Kobylak | 55f9e83 | 2017-05-14 16:13:00 -0500 | [diff] [blame] | 14 | namespace fs = std::experimental::filesystem; | 
| Adriana Kobylak | 99c8c0e | 2017-04-17 13:39:11 -0500 | [diff] [blame] | 15 | namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server; | 
|  | 16 |  | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 17 | constexpr auto SYSTEMD_SERVICE   = "org.freedesktop.systemd1"; | 
|  | 18 | constexpr auto SYSTEMD_OBJ_PATH  = "/org/freedesktop/systemd1"; | 
|  | 19 |  | 
|  | 20 | void Activation::subscribeToSystemdSignals() | 
|  | 21 | { | 
|  | 22 | auto method = this->bus.new_method_call(SYSTEMD_SERVICE, | 
|  | 23 | SYSTEMD_OBJ_PATH, | 
|  | 24 | SYSTEMD_INTERFACE, | 
|  | 25 | "Subscribe"); | 
|  | 26 | this->bus.call_noreply(method); | 
|  | 27 |  | 
|  | 28 | return; | 
|  | 29 | } | 
|  | 30 |  | 
| Michael Tritz | 1cb127f | 2017-07-26 15:40:38 -0500 | [diff] [blame] | 31 | void Activation::unsubscribeFromSystemdSignals() | 
|  | 32 | { | 
|  | 33 | auto method = this->bus.new_method_call(SYSTEMD_SERVICE, | 
|  | 34 | SYSTEMD_OBJ_PATH, | 
|  | 35 | SYSTEMD_INTERFACE, | 
|  | 36 | "Unsubscribe"); | 
|  | 37 | this->bus.call_noreply(method); | 
|  | 38 |  | 
|  | 39 | return; | 
|  | 40 | } | 
|  | 41 |  | 
| Saqib Khan | 2af5c49 | 2017-07-17 16:15:13 -0500 | [diff] [blame] | 42 | void Activation::createSymlinks() | 
|  | 43 | { | 
|  | 44 | if (!fs::is_directory(PNOR_ACTIVE_PATH)) | 
|  | 45 | { | 
|  | 46 | fs::create_directories(PNOR_ACTIVE_PATH); | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | // If the RW or RO active links exist, remove them and create new | 
|  | 50 | // ones pointing to the active version. | 
|  | 51 | if (fs::is_symlink(PNOR_RO_ACTIVE_PATH)) | 
|  | 52 | { | 
|  | 53 | fs::remove(PNOR_RO_ACTIVE_PATH); | 
|  | 54 | } | 
|  | 55 | fs::create_directory_symlink(PNOR_RO_PREFIX + versionId, | 
|  | 56 | PNOR_RO_ACTIVE_PATH); | 
|  | 57 | if (fs::is_symlink(PNOR_RW_ACTIVE_PATH)) | 
|  | 58 | { | 
|  | 59 | fs::remove(PNOR_RW_ACTIVE_PATH); | 
|  | 60 | } | 
|  | 61 | fs::create_directory_symlink(PNOR_RW_PREFIX + versionId, | 
|  | 62 | PNOR_RW_ACTIVE_PATH); | 
|  | 63 |  | 
|  | 64 | // There is only one preserved directory as it is not tied to a | 
|  | 65 | // version, so just create the link if it doesn't exist already | 
|  | 66 | if (!fs::is_symlink(PNOR_PRSV_ACTIVE_PATH)) | 
|  | 67 | { | 
|  | 68 | fs::create_directory_symlink(PNOR_PRSV, | 
|  | 69 | PNOR_PRSV_ACTIVE_PATH); | 
|  | 70 | } | 
|  | 71 | } | 
|  | 72 |  | 
| Michael Tritz | 1cb127f | 2017-07-26 15:40:38 -0500 | [diff] [blame] | 73 | void Activation::startActivation() | 
|  | 74 | { | 
|  | 75 | // Since the squashfs image has not yet been loaded to pnor and the | 
|  | 76 | // RW volumes have not yet been created, we need to start the | 
|  | 77 | // service files for each of those actions. | 
|  | 78 |  | 
|  | 79 | if (!activationProgress) | 
|  | 80 | { | 
|  | 81 | activationProgress = std::make_unique<ActivationProgress>( | 
|  | 82 | bus, path); | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | if (!activationBlocksTransition) | 
|  | 86 | { | 
|  | 87 | activationBlocksTransition = | 
|  | 88 | std::make_unique<ActivationBlocksTransition>(bus, path); | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | constexpr auto squashfsMountService = | 
|  | 92 | "obmc-flash-bios-squashfsmount@"; | 
|  | 93 | auto squashfsMountServiceFile = std::string(squashfsMountService) + | 
|  | 94 | versionId + ".service"; | 
|  | 95 | auto method = bus.new_method_call( | 
|  | 96 | SYSTEMD_BUSNAME, | 
|  | 97 | SYSTEMD_PATH, | 
|  | 98 | SYSTEMD_INTERFACE, | 
|  | 99 | "StartUnit"); | 
|  | 100 | method.append(squashfsMountServiceFile, "replace"); | 
|  | 101 | bus.call_noreply(method); | 
|  | 102 |  | 
|  | 103 | constexpr auto ubimountService = "obmc-flash-bios-ubimount@"; | 
|  | 104 | auto ubimountServiceFile = std::string(ubimountService) + | 
|  | 105 | versionId + ".service"; | 
|  | 106 | method = bus.new_method_call( | 
|  | 107 | SYSTEMD_BUSNAME, | 
|  | 108 | SYSTEMD_PATH, | 
|  | 109 | SYSTEMD_INTERFACE, | 
|  | 110 | "StartUnit"); | 
|  | 111 | method.append(ubimountServiceFile, "replace"); | 
|  | 112 | bus.call_noreply(method); | 
|  | 113 |  | 
|  | 114 | activationProgress->progress(10); | 
|  | 115 | } | 
|  | 116 |  | 
|  | 117 | void Activation::finishActivation() | 
|  | 118 | { | 
|  | 119 | activationProgress->progress(90); | 
|  | 120 | createSymlinks(); | 
|  | 121 |  | 
|  | 122 | // Set Redundancy Priority before setting to Active | 
|  | 123 | if (!redundancyPriority) | 
|  | 124 | { | 
|  | 125 | redundancyPriority = std::make_unique<RedundancyPriority>( | 
|  | 126 | bus, path, *this, 0); | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | activationProgress->progress(100); | 
|  | 130 |  | 
|  | 131 | activationBlocksTransition.reset(nullptr); | 
|  | 132 | activationProgress.reset(nullptr); | 
|  | 133 |  | 
|  | 134 | squashfsLoaded = false; | 
|  | 135 | rwVolumesCreated = false; | 
|  | 136 | Activation::unsubscribeFromSystemdSignals(); | 
|  | 137 | } | 
|  | 138 |  | 
| Adriana Kobylak | befe5ce | 2017-04-05 15:57:44 -0500 | [diff] [blame] | 139 | auto Activation::activation(Activations value) -> | 
|  | 140 | Activations | 
|  | 141 | { | 
| Saqib Khan | 942df8a | 2017-06-01 14:09:27 -0500 | [diff] [blame] | 142 |  | 
|  | 143 | if (value != softwareServer::Activation::Activations::Active) | 
|  | 144 | { | 
|  | 145 | redundancyPriority.reset(nullptr); | 
|  | 146 | } | 
|  | 147 |  | 
| Adriana Kobylak | 99c8c0e | 2017-04-17 13:39:11 -0500 | [diff] [blame] | 148 | if (value == softwareServer::Activation::Activations::Activating) | 
|  | 149 | { | 
| Adriana Kobylak | 2fdb931 | 2017-05-14 19:08:26 -0500 | [diff] [blame] | 150 | softwareServer::Activation::activation(value); | 
|  | 151 |  | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 152 | if (squashfsLoaded == false && rwVolumesCreated == false) | 
| Adriana Kobylak | 99c8c0e | 2017-04-17 13:39:11 -0500 | [diff] [blame] | 153 | { | 
| Michael Tritz | 1cb127f | 2017-07-26 15:40:38 -0500 | [diff] [blame] | 154 | Activation::startActivation(); | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 155 | return softwareServer::Activation::activation(value); | 
|  | 156 | } | 
|  | 157 | else if (squashfsLoaded == true && rwVolumesCreated == true) | 
|  | 158 | { | 
|  | 159 | // Only when the squashfs image is finished loading AND the RW | 
| Michael Tritz | 1cb127f | 2017-07-26 15:40:38 -0500 | [diff] [blame] | 160 | // volumes have been created do we proceed with activation. To | 
|  | 161 | // verify that this happened, we check for the mount dirs PNOR_PRSV | 
|  | 162 | // and PNOR_RW_PREFIX_<versionid>, as well as the image dir R0. | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 163 |  | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 164 | if ((fs::is_directory(PNOR_PRSV)) && | 
|  | 165 | (fs::is_directory(PNOR_RW_PREFIX + versionId)) && | 
|  | 166 | (fs::is_directory(PNOR_RO_PREFIX + versionId))) | 
|  | 167 | { | 
| Michael Tritz | 1cb127f | 2017-07-26 15:40:38 -0500 | [diff] [blame] | 168 | Activation::finishActivation(); | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 169 | return softwareServer::Activation::activation( | 
|  | 170 | softwareServer::Activation::Activations::Active); | 
|  | 171 | } | 
|  | 172 | else | 
|  | 173 | { | 
| Saqib Khan | cb9df4e | 2017-06-26 11:06:07 -0500 | [diff] [blame] | 174 | activationBlocksTransition.reset(nullptr); | 
| Michael Tritz | 1793b64 | 2017-06-28 18:35:58 -0500 | [diff] [blame] | 175 | activationProgress.reset(nullptr); | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 176 | return softwareServer::Activation::activation( | 
|  | 177 | softwareServer::Activation::Activations::Failed); | 
|  | 178 | } | 
| Adriana Kobylak | 55f9e83 | 2017-05-14 16:13:00 -0500 | [diff] [blame] | 179 | } | 
| Adriana Kobylak | 692b555 | 2017-04-17 14:02:58 -0500 | [diff] [blame] | 180 | } | 
| Adriana Kobylak | 2fdb931 | 2017-05-14 19:08:26 -0500 | [diff] [blame] | 181 | else | 
|  | 182 | { | 
|  | 183 | activationBlocksTransition.reset(nullptr); | 
| Michael Tritz | 1793b64 | 2017-06-28 18:35:58 -0500 | [diff] [blame] | 184 | activationProgress.reset(nullptr); | 
| Adriana Kobylak | 2fdb931 | 2017-05-14 19:08:26 -0500 | [diff] [blame] | 185 | } | 
| Michael Tritz | 1cb127f | 2017-07-26 15:40:38 -0500 | [diff] [blame] | 186 |  | 
|  | 187 | return softwareServer::Activation::activation(value); | 
| Adriana Kobylak | 2fdb931 | 2017-05-14 19:08:26 -0500 | [diff] [blame] | 188 | } | 
|  | 189 |  | 
|  | 190 | auto Activation::requestedActivation(RequestedActivations value) -> | 
|  | 191 | RequestedActivations | 
|  | 192 | { | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 193 | squashfsLoaded = false; | 
|  | 194 | rwVolumesCreated = false; | 
|  | 195 |  | 
| Adriana Kobylak | 2fdb931 | 2017-05-14 19:08:26 -0500 | [diff] [blame] | 196 | if ((value == softwareServer::Activation::RequestedActivations::Active) && | 
|  | 197 | (softwareServer::Activation::requestedActivation() != | 
|  | 198 | softwareServer::Activation::RequestedActivations::Active)) | 
|  | 199 | { | 
|  | 200 | if ((softwareServer::Activation::activation() == | 
|  | 201 | softwareServer::Activation::Activations::Ready) || | 
|  | 202 | (softwareServer::Activation::activation() == | 
|  | 203 | softwareServer::Activation::Activations::Failed)) | 
|  | 204 | { | 
|  | 205 | Activation::activation( | 
|  | 206 | softwareServer::Activation::Activations::Activating); | 
|  | 207 |  | 
|  | 208 | } | 
|  | 209 | } | 
| Adriana Kobylak | 99c8c0e | 2017-04-17 13:39:11 -0500 | [diff] [blame] | 210 | return softwareServer::Activation::requestedActivation(value); | 
| Adriana Kobylak | befe5ce | 2017-04-05 15:57:44 -0500 | [diff] [blame] | 211 | } | 
|  | 212 |  | 
| Saqib Khan | 2021b4c | 2017-06-07 14:37:36 -0500 | [diff] [blame] | 213 | uint8_t RedundancyPriority::priority(uint8_t value) | 
|  | 214 | { | 
| Saqib Khan | b8e7f31 | 2017-08-12 10:24:10 -0500 | [diff] [blame] | 215 | parent.parent.freePriority(value, parent.versionId); | 
| Saqib Khan | 2af5c49 | 2017-07-17 16:15:13 -0500 | [diff] [blame] | 216 |  | 
|  | 217 | if(parent.parent.isLowestPriority(value)) | 
|  | 218 | { | 
|  | 219 | // Need to update the symlinks to point to Software Version | 
|  | 220 | // with lowest priority. | 
|  | 221 | parent.createSymlinks(); | 
|  | 222 | } | 
|  | 223 |  | 
| Michael Tritz | 60bc20f | 2017-07-29 23:32:21 -0500 | [diff] [blame] | 224 | storeToFile(parent.versionId, value); | 
| Saqib Khan | 2021b4c | 2017-06-07 14:37:36 -0500 | [diff] [blame] | 225 | return softwareServer::RedundancyPriority::priority(value); | 
|  | 226 | } | 
|  | 227 |  | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 228 | void Activation::unitStateChange(sdbusplus::message::message& msg) | 
|  | 229 | { | 
|  | 230 | uint32_t newStateID {}; | 
|  | 231 | sdbusplus::message::object_path newStateObjPath; | 
|  | 232 | std::string newStateUnit{}; | 
|  | 233 | std::string newStateResult{}; | 
|  | 234 |  | 
|  | 235 | //Read the msg and populate each variable | 
|  | 236 | msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult); | 
|  | 237 |  | 
|  | 238 | auto squashfsMountServiceFile = | 
|  | 239 | "obmc-flash-bios-squashfsmount@" + versionId + ".service"; | 
|  | 240 |  | 
|  | 241 | auto ubimountServiceFile = | 
|  | 242 | "obmc-flash-bios-ubimount@" + versionId + ".service"; | 
|  | 243 |  | 
|  | 244 | if(newStateUnit == squashfsMountServiceFile && newStateResult == "done") | 
|  | 245 | { | 
| Michael Tritz | 1793b64 | 2017-06-28 18:35:58 -0500 | [diff] [blame] | 246 | squashfsLoaded = true; | 
|  | 247 | activationProgress->progress(activationProgress->progress() + 20); | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 248 | } | 
|  | 249 |  | 
|  | 250 | if(newStateUnit == ubimountServiceFile && newStateResult == "done") | 
|  | 251 | { | 
|  | 252 | rwVolumesCreated = true; | 
| Michael Tritz | 1793b64 | 2017-06-28 18:35:58 -0500 | [diff] [blame] | 253 | activationProgress->progress(activationProgress->progress() + 50); | 
| Michael Tritz | 9d25b60 | 2017-06-14 14:41:43 -0500 | [diff] [blame] | 254 | } | 
|  | 255 |  | 
|  | 256 | if(squashfsLoaded && rwVolumesCreated) | 
|  | 257 | { | 
|  | 258 | Activation::activation( | 
|  | 259 | softwareServer::Activation::Activations::Activating); | 
|  | 260 | } | 
|  | 261 |  | 
|  | 262 | if((newStateUnit == squashfsMountServiceFile || | 
|  | 263 | newStateUnit == ubimountServiceFile) && | 
|  | 264 | (newStateResult == "failed" || newStateResult == "dependency")) | 
|  | 265 | { | 
|  | 266 | Activation::activation(softwareServer::Activation::Activations::Failed); | 
|  | 267 | } | 
|  | 268 |  | 
|  | 269 | return; | 
|  | 270 | } | 
|  | 271 |  | 
| Leonel Gonzalez | 9c8adfa | 2017-07-12 11:08:40 -0500 | [diff] [blame] | 272 | void Activation::delete_() | 
|  | 273 | { | 
|  | 274 | parent.erase(versionId); | 
|  | 275 | } | 
|  | 276 |  | 
| Adriana Kobylak | befe5ce | 2017-04-05 15:57:44 -0500 | [diff] [blame] | 277 | } // namespace updater | 
|  | 278 | } // namespace software | 
|  | 279 | } // namespace openpower |