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