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