1 #include "config.h"
2 
3 #include "dump_manager_resource.hpp"
4 
5 #include "dump_utils.hpp"
6 #include "op_dump_consts.hpp"
7 #include "resource_dump_entry.hpp"
8 #include "xyz/openbmc_project/Common/error.hpp"
9 
10 #include <phosphor-logging/elog-errors.hpp>
11 #include <phosphor-logging/elog.hpp>
12 #include <phosphor-logging/lg2.hpp>
13 
14 namespace openpower
15 {
16 namespace dump
17 {
18 namespace resource
19 {
20 
21 using namespace phosphor::logging;
22 using InternalFailure =
23     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
24 
notify(uint32_t dumpId,uint64_t size)25 void Manager::notify(uint32_t dumpId, uint64_t size)
26 {
27     // Get the timestamp
28     uint64_t timeStamp =
29         std::chrono::duration_cast<std::chrono::microseconds>(
30             std::chrono::system_clock::now().time_since_epoch())
31             .count();
32 
33     // If there is an entry with invalid id update that.
34     // If there a completed one with same source id ignore it
35     // if there is no invalid id, create new entry
36     openpower::dump::resource::Entry* upEntry = NULL;
37     for (auto& entry : entries)
38     {
39         openpower::dump::resource::Entry* resEntry =
40             dynamic_cast<openpower::dump::resource::Entry*>(entry.second.get());
41 
42         // If there is already a completed entry with input source id then
43         // ignore this notification.
44         if ((resEntry->sourceDumpId() == dumpId) &&
45             (resEntry->status() == phosphor::dump::OperationStatus::Completed))
46         {
47             lg2::info("Resource dump entry with source dump id: {DUMP_ID} "
48                       "is already present with entry id: {ENTRY_ID}",
49                       "DUMP_ID", dumpId, "ENTRY_ID", resEntry->getDumpId());
50             return;
51         }
52 
53         // Save the first entry with INVALID_SOURCE_ID
54         // but continue in the loop to make sure the
55         // new entry is not duplicate
56         if ((resEntry->status() ==
57              phosphor::dump::OperationStatus::InProgress) &&
58             (resEntry->sourceDumpId() == INVALID_SOURCE_ID) &&
59             (upEntry == NULL))
60         {
61             upEntry = resEntry;
62         }
63     }
64     if (upEntry != NULL)
65     {
66         lg2::info("Resource Dump Notify: Updating dumpId: {DUMP_ID} with "
67                   "source Id: {SOURCE_ID} Size: {SIZE}",
68                   "DUMP_ID", upEntry->getDumpId(), "SOURCE_ID", dumpId, "SIZE",
69                   size);
70         upEntry->update(timeStamp, size, dumpId);
71         return;
72     }
73 
74     // Get the id
75     auto id = lastEntryId + 1;
76     auto idString = std::to_string(id);
77     auto objPath = std::filesystem::path(baseEntryPath) / idString;
78 
79     // TODO: Get the originator Id, type from the persisted file.
80     // For now replacing it with null
81 
82     try
83     {
84         lg2::info(
85             "Resouce Dump Notify: creating new dump entry dumpId: {DUMP_ID} "
86             "Id: {ID} Size: {SIZE}",
87             "DUMP_ID", id, "ID", dumpId, "SIZE", size);
88         entries.insert(std::make_pair(
89             id, std::make_unique<resource::Entry>(
90                     bus, objPath.c_str(), id, timeStamp, size, dumpId,
91                     std::string(), std::string(),
92                     phosphor::dump::OperationStatus::Completed, std::string(),
93                     originatorTypes::Internal, *this)));
94     }
95     catch (const std::invalid_argument& e)
96     {
97         lg2::error(
98             "Error in creating resource dump entry, errormsg: {ERROR}, "
99             "OBJECTPATH: {OBJECT_PATH}, ID: {ID}, TIMESTAMP: {TIMESTAMP}, "
100             "SIZE: {SIZE}, SOURCEID: {SOURCE_ID}",
101             "ERROR", e, "OBJECT_PATH", objPath, "ID", id, "TIMESTAMP",
102             timeStamp, "SIZE", size, "SOURCE_ID", dumpId);
103         report<InternalFailure>();
104         return;
105     }
106     lastEntryId++;
107 }
108 
109 sdbusplus::message::object_path
createDump(phosphor::dump::DumpCreateParams params)110     Manager::createDump(phosphor::dump::DumpCreateParams params)
111 {
112     using NotAllowed =
113         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
114     using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
115 
116     // Allow creating resource dump only when the host is up.
117     if (!phosphor::dump::isHostRunning())
118     {
119         elog<NotAllowed>(
120             Reason("Resource dump can be initiated only when the host is up"));
121         return std::string();
122     }
123 
124     using InvalidArgument =
125         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
126     using Argument = xyz::openbmc_project::Common::InvalidArgument;
127     using CreateParameters =
128         sdbusplus::com::ibm::Dump::server::Create::CreateParameters;
129 
130     auto id = lastEntryId + 1;
131     auto idString = std::to_string(id);
132     auto objPath = std::filesystem::path(baseEntryPath) / idString;
133     uint64_t timeStamp =
134         std::chrono::duration_cast<std::chrono::microseconds>(
135             std::chrono::system_clock::now().time_since_epoch())
136             .count();
137 
138     std::string vspString;
139     auto iter = params.find(
140         sdbusplus::com::ibm::Dump::server::Create::
141             convertCreateParametersToString(CreateParameters::VSPString));
142     if (iter == params.end())
143     {
144         // Host will generate a default dump if no resource selector string
145         // is provided. The default dump will be a non-disruptive system dump.
146         lg2::info(
147             "VSP string is not provided, a non-disruptive system dump will be "
148             "generated by the host");
149     }
150     else
151     {
152         try
153         {
154             vspString = std::get<std::string>(iter->second);
155         }
156         catch (const std::bad_variant_access& e)
157         {
158             // Exception will be raised if the input is not string
159             lg2::error("An invalid vsp string is passed, errormsg: {ERROR}",
160                        "ERROR", e);
161             elog<InvalidArgument>(Argument::ARGUMENT_NAME("VSP_STRING"),
162                                   Argument::ARGUMENT_VALUE("INVALID INPUT"));
163         }
164     }
165 
166     std::string pwd;
167     iter = params.find(
168         sdbusplus::com::ibm::Dump::server::Create::
169             convertCreateParametersToString(CreateParameters::Password));
170     if (iter == params.end())
171     {
172         lg2::info("Password is not provided for resource dump");
173     }
174     else
175     {
176         try
177         {
178             pwd = std::get<std::string>(iter->second);
179         }
180         catch (const std::bad_variant_access& e)
181         {
182             // Exception will be raised if the input is not string
183             lg2::error(
184                 "An invalid password string is passed, errormsg: {ERROR}",
185                 "ERROR", e);
186             elog<InvalidArgument>(Argument::ARGUMENT_NAME("PASSWORD"),
187                                   Argument::ARGUMENT_VALUE("INVALID INPUT"));
188         }
189     }
190 
191     // Get the originator id and type from params
192     std::string originatorId;
193     originatorTypes originatorType;
194 
195     phosphor::dump::extractOriginatorProperties(params, originatorId,
196                                                 originatorType);
197 
198     try
199     {
200         entries.insert(std::make_pair(
201             id, std::make_unique<resource::Entry>(
202                     bus, objPath.c_str(), id, timeStamp, 0, INVALID_SOURCE_ID,
203                     vspString, pwd, phosphor::dump::OperationStatus::InProgress,
204                     originatorId, originatorType, *this)));
205     }
206     catch (const std::invalid_argument& e)
207     {
208         lg2::error(
209             "Error in creating resource dump entry, errormsg: {ERROR}, "
210             "OBJECTPATH: {OBJECT_PATH}, VSPSTRING: {VSP_STRING}, ID: {ID}",
211             "ERROR", e, "OBJECT_PATH", objPath, "VSP_STRING", vspString, "ID",
212             id);
213         elog<InternalFailure>();
214         return std::string();
215     }
216     lastEntryId++;
217     return objPath.string();
218 }
219 
220 } // namespace resource
221 } // namespace dump
222 } // namespace openpower
223