1 #include "activation_static.hpp" 2 3 #include "item_updater.hpp" 4 5 #include <filesystem> 6 #include <phosphor-logging/log.hpp> 7 8 namespace openpower 9 { 10 namespace software 11 { 12 namespace updater 13 { 14 namespace fs = std::filesystem; 15 namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server; 16 17 using namespace phosphor::logging; 18 19 auto ActivationStatic::activation(Activations value) -> Activations 20 { 21 22 auto ret = value; 23 if (value != softwareServer::Activation::Activations::Active) 24 { 25 redundancyPriority.reset(nullptr); 26 } 27 28 if (value == softwareServer::Activation::Activations::Activating) 29 { 30 if (parent.freeSpace()) 31 { 32 startActivation(); 33 } 34 else 35 { 36 ret = softwareServer::Activation::Activations::Failed; 37 } 38 } 39 else 40 { 41 activationBlocksTransition.reset(nullptr); 42 activationProgress.reset(nullptr); 43 } 44 45 return softwareServer::Activation::activation(ret); 46 } 47 48 void ActivationStatic::startActivation() 49 { 50 fs::path pnorFile; 51 fs::path imagePath(IMG_DIR); 52 imagePath /= versionId; 53 54 for (const auto& entry : fs::directory_iterator(imagePath)) 55 { 56 if (entry.path().extension() == ".pnor") 57 { 58 pnorFile = entry; 59 break; 60 } 61 } 62 if (pnorFile.empty()) 63 { 64 log<level::ERR>("Unable to find pnor file", 65 entry("DIR=%s", imagePath.c_str())); 66 return; 67 } 68 69 if (!activationProgress) 70 { 71 activationProgress = std::make_unique<ActivationProgress>(bus, path); 72 } 73 74 if (!activationBlocksTransition) 75 { 76 activationBlocksTransition = 77 std::make_unique<ActivationBlocksTransition>(bus, path); 78 } 79 80 // TODO: check why the signal is still received without calling this 81 // function? 82 subscribeToSystemdSignals(); 83 84 log<level::INFO>("Start programming...", 85 entry("PNOR=%s", pnorFile.c_str())); 86 87 std::string pnorFileEscaped = pnorFile.string(); 88 // Escape all '/' to '-' 89 std::replace(pnorFileEscaped.begin(), pnorFileEscaped.end(), '/', '-'); 90 91 constexpr auto updatePNORService = "openpower-pnor-update@"; 92 pnorUpdateUnit = 93 std::string(updatePNORService) + pnorFileEscaped + ".service"; 94 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 95 SYSTEMD_INTERFACE, "StartUnit"); 96 method.append(pnorUpdateUnit, "replace"); 97 bus.call_noreply(method); 98 99 activationProgress->progress(10); 100 } 101 102 void ActivationStatic::unitStateChange(sdbusplus::message::message& msg) 103 { 104 uint32_t newStateID{}; 105 sdbusplus::message::object_path newStateObjPath; 106 std::string newStateUnit{}; 107 std::string newStateResult{}; 108 109 // Read the msg and populate each variable 110 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult); 111 112 if (newStateUnit == pnorUpdateUnit) 113 { 114 if (newStateResult == "done") 115 { 116 finishActivation(); 117 } 118 if (newStateResult == "failed" || newStateResult == "dependency") 119 { 120 Activation::activation( 121 softwareServer::Activation::Activations::Failed); 122 } 123 } 124 } 125 126 void ActivationStatic::finishActivation() 127 { 128 activationProgress->progress(90); 129 130 // Set Redundancy Priority before setting to Active 131 if (!redundancyPriority) 132 { 133 redundancyPriority = 134 std::make_unique<RedundancyPriority>(bus, path, *this, 0); 135 } 136 137 activationProgress->progress(100); 138 139 activationBlocksTransition.reset(); 140 activationProgress.reset(); 141 142 unsubscribeFromSystemdSignals(); 143 // Remove version object from image manager 144 deleteImageManagerObject(); 145 // Create active association 146 parent.createActiveAssociation(path); 147 // Create functional assocaition 148 parent.updateFunctionalAssociation(versionId); 149 150 Activation::activation(Activation::Activations::Active); 151 } 152 153 } // namespace updater 154 } // namespace software 155 } // namespace openpower 156