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     using NotAllowed =
117         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
118     using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
119 
120     // Allow creating resource dump only when the host is up.
121     if (!phosphor::dump::isHostRunning())
122     {
123         elog<NotAllowed>(
124             Reason("Resource dump can be initiated only when the host is up"));
125         return std::string();
126     }
127 
128     using InvalidArgument =
129         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
130     using Argument = xyz::openbmc_project::Common::InvalidArgument;
131     using CreateParameters =
132         sdbusplus::com::ibm::Dump::server::Create::CreateParameters;
133 
134     auto id = lastEntryId + 1;
135     auto idString = std::to_string(id);
136     auto objPath = std::filesystem::path(baseEntryPath) / idString;
137     uint64_t timeStamp =
138         std::chrono::duration_cast<std::chrono::microseconds>(
139             std::chrono::system_clock::now().time_since_epoch())
140             .count();
141 
142     std::string vspString;
143     auto iter = params.find(
144         sdbusplus::com::ibm::Dump::server::Create::
145             convertCreateParametersToString(CreateParameters::VSPString));
146     if (iter == params.end())
147     {
148         // Host will generate a default dump if no resource selector string
149         // is provided. The default dump will be a non-disruptive system dump.
150         log<level::INFO>(
151             "VSP string is not provided, a non-disruptive system dump will be "
152             "generated by the host");
153     }
154     else
155     {
156         try
157         {
158             vspString = std::get<std::string>(iter->second);
159         }
160         catch (const std::bad_variant_access& e)
161         {
162             // Exception will be raised if the input is not string
163             log<level::ERR>(
164                 fmt::format("An invalid  vsp string is passed errormsg({})",
165                             e.what())
166                     .c_str());
167             elog<InvalidArgument>(Argument::ARGUMENT_NAME("VSP_STRING"),
168                                   Argument::ARGUMENT_VALUE("INVALID INPUT"));
169         }
170     }
171 
172     std::string pwd;
173     iter = params.find(
174         sdbusplus::com::ibm::Dump::server::Create::
175             convertCreateParametersToString(CreateParameters::Password));
176     if (iter == params.end())
177     {
178         log<level::INFO>("Password is not provided for resource dump");
179     }
180     else
181     {
182         try
183         {
184             pwd = std::get<std::string>(iter->second);
185         }
186         catch (const std::bad_variant_access& e)
187         {
188             // Exception will be raised if the input is not string
189             log<level::ERR>(
190                 fmt::format("An invalid password string is passed errormsg({})",
191                             e.what())
192                     .c_str());
193             elog<InvalidArgument>(Argument::ARGUMENT_NAME("PASSWORD"),
194                                   Argument::ARGUMENT_VALUE("INVALID INPUT"));
195         }
196     }
197 
198     // Get the originator id and type from params
199     std::string originatorId;
200     originatorTypes originatorType;
201 
202     phosphor::dump::extractOriginatorProperties(params, originatorId,
203                                                 originatorType);
204 
205     try
206     {
207         entries.insert(std::make_pair(
208             id, std::make_unique<resource::Entry>(
209                     bus, objPath.c_str(), id, timeStamp, 0, INVALID_SOURCE_ID,
210                     vspString, pwd, phosphor::dump::OperationStatus::InProgress,
211                     originatorId, originatorType, *this)));
212     }
213     catch (const std::invalid_argument& e)
214     {
215         log<level::ERR>(
216             fmt::format(
217                 "Error in creating resource dump "
218                 "entry,errormsg({}),OBJECTPATH({}), VSPSTRING({}), ID({})",
219                 e.what(), objPath.c_str(), vspString, id)
220                 .c_str());
221         elog<InternalFailure>();
222         return std::string();
223     }
224     lastEntryId++;
225     return objPath.string();
226 }
227 
228 } // namespace resource
229 } // namespace dump
230 } // namespace openpower
231