1 #include "config.h"
2 
3 #include "item_updater.hpp"
4 
5 #include "xyz/openbmc_project/Common/error.hpp"
6 
7 #include <phosphor-logging/elog-errors.hpp>
8 #include <phosphor-logging/log.hpp>
9 
10 namespace openpower
11 {
12 namespace software
13 {
14 namespace updater
15 {
16 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
17 using namespace phosphor::logging;
18 
19 void ItemUpdater::createActiveAssociation(const std::string& path)
20 {
21     assocs.emplace_back(
22         std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path));
23     associations(assocs);
24 }
25 
26 void ItemUpdater::updateFunctionalAssociation(const std::string& versionId)
27 {
28     std::string path = std::string{SOFTWARE_OBJPATH} + '/' + versionId;
29     // remove all functional associations
30     for (auto iter = assocs.begin(); iter != assocs.end();)
31     {
32         if ((std::get<0>(*iter)).compare(FUNCTIONAL_FWD_ASSOCIATION) == 0)
33         {
34             iter = assocs.erase(iter);
35         }
36         else
37         {
38             ++iter;
39         }
40     }
41     assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION,
42                                         FUNCTIONAL_REV_ASSOCIATION, path));
43     associations(assocs);
44 }
45 
46 void ItemUpdater::removeAssociation(const std::string& path)
47 {
48     for (auto iter = assocs.begin(); iter != assocs.end();)
49     {
50         if ((std::get<2>(*iter)).compare(path) == 0)
51         {
52             iter = assocs.erase(iter);
53             associations(assocs);
54         }
55         else
56         {
57             ++iter;
58         }
59     }
60 }
61 
62 bool ItemUpdater::erase(std::string entryId)
63 {
64     if (isVersionFunctional(entryId) && isChassisOn())
65     {
66         log<level::ERR>(("Error: Version " + entryId +
67                          " is currently active and running on the host."
68                          " Unable to remove.")
69                             .c_str());
70         return false;
71     }
72 
73     // Removing entry in versions map
74     auto it = versions.find(entryId);
75     if (it == versions.end())
76     {
77         log<level::ERR>(("Error: Failed to find version " + entryId +
78                          " in item updater versions map."
79                          " Unable to remove.")
80                             .c_str());
81     }
82     else
83     {
84         versions.erase(entryId);
85     }
86 
87     // Removing entry in activations map
88     auto ita = activations.find(entryId);
89     if (ita == activations.end())
90     {
91         log<level::ERR>(("Error: Failed to find version " + entryId +
92                          " in item updater activations map."
93                          " Unable to remove.")
94                             .c_str());
95     }
96     else
97     {
98         removeAssociation(ita->second->path);
99         activations.erase(entryId);
100     }
101     return true;
102 }
103 
104 bool ItemUpdater::isChassisOn()
105 {
106     auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
107                                           MAPPER_INTERFACE, "GetObject");
108 
109     mapperCall.append(CHASSIS_STATE_PATH,
110                       std::vector<std::string>({CHASSIS_STATE_OBJ}));
111     auto mapperResponseMsg = bus.call(mapperCall);
112     if (mapperResponseMsg.is_method_error())
113     {
114         log<level::ERR>("Error in Mapper call");
115         elog<InternalFailure>();
116     }
117     using MapperResponseType = std::map<std::string, std::vector<std::string>>;
118     MapperResponseType mapperResponse;
119     mapperResponseMsg.read(mapperResponse);
120     if (mapperResponse.empty())
121     {
122         log<level::ERR>("Invalid Response from mapper");
123         elog<InternalFailure>();
124     }
125 
126     auto method = bus.new_method_call((mapperResponse.begin()->first).c_str(),
127                                       CHASSIS_STATE_PATH,
128                                       SYSTEMD_PROPERTY_INTERFACE, "Get");
129     method.append(CHASSIS_STATE_OBJ, "CurrentPowerState");
130     auto response = bus.call(method);
131     if (response.is_method_error())
132     {
133         log<level::ERR>("Error in fetching current Chassis State",
134                         entry("MAPPERRESPONSE=%s",
135                               (mapperResponse.begin()->first).c_str()));
136         elog<InternalFailure>();
137     }
138     sdbusplus::message::variant<std::string> currentChassisState;
139     response.read(currentChassisState);
140     auto strParam =
141         sdbusplus::message::variant_ns::get<std::string>(currentChassisState);
142     return (strParam != CHASSIS_STATE_OFF);
143 }
144 
145 } // namespace updater
146 } // namespace software
147 } // namespace openpower
148