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     try
84     {
85         log<level::INFO>(fmt::format("Resouce Dump Notify: creating new dump "
86                                      "entry dumpId({}) Id({}) Size({})",
87                                      id, dumpId, size)
88                              .c_str());
89         entries.insert(std::make_pair(
90             id, std::make_unique<resource::Entry>(
91                     bus, objPath.c_str(), id, timeStamp, size, dumpId,
92                     std::string(), std::string(),
93                     phosphor::dump::OperationStatus::Completed, *this)));
94     }
95     catch (const std::invalid_argument& e)
96     {
97         log<level::ERR>(fmt::format("Error in creating resource dump entry, "
98                                     "errormsg({}),OBJECTPATH({}),ID({}),"
99                                     "TIMESTAMP({}),SIZE({}),SOURCEID({})",
100                                     e.what(), objPath.c_str(), id, timeStamp,
101                                     size, dumpId)
102                             .c_str());
103         report<InternalFailure>();
104         return;
105     }
106     lastEntryId++;
107 }
108 
109 sdbusplus::message::object_path
110     Manager::createDump(phosphor::dump::DumpCreateParams params)
111 {
112 
113     using NotAllowed =
114         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
115     using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
116 
117     // Allow creating resource dump only when the host is up.
118     if (!phosphor::dump::isHostRunning())
119     {
120         elog<NotAllowed>(
121             Reason("Resource dump can be initiated only when the host is up"));
122         return std::string();
123     }
124 
125     using InvalidArgument =
126         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
127     using Argument = xyz::openbmc_project::Common::InvalidArgument;
128     using CreateParameters =
129         sdbusplus::com::ibm::Dump::server::Create::CreateParameters;
130 
131     auto id = lastEntryId + 1;
132     auto idString = std::to_string(id);
133     auto objPath = std::filesystem::path(baseEntryPath) / idString;
134     uint64_t timeStamp =
135         std::chrono::duration_cast<std::chrono::microseconds>(
136             std::chrono::system_clock::now().time_since_epoch())
137             .count();
138 
139     std::string vspString;
140     auto iter = params.find(
141         sdbusplus::com::ibm::Dump::server::Create::
142             convertCreateParametersToString(CreateParameters::VSPString));
143     if (iter == params.end())
144     {
145         // Host will generate a default dump if no resource selector string
146         // is provided. The default dump will be a non-disruptive system dump.
147         log<level::INFO>(
148             "VSP string is not provided, a non-disruptive system dump will be "
149             "generated by the host");
150     }
151     else
152     {
153         try
154         {
155             vspString = std::get<std::string>(iter->second);
156         }
157         catch (const std::bad_variant_access& e)
158         {
159             // Exception will be raised if the input is not string
160             log<level::ERR>(
161                 fmt::format("An invalid  vsp string is passed errormsg({})",
162                             e.what())
163                     .c_str());
164             elog<InvalidArgument>(Argument::ARGUMENT_NAME("VSP_STRING"),
165                                   Argument::ARGUMENT_VALUE("INVALID INPUT"));
166         }
167     }
168 
169     std::string pwd;
170     iter = params.find(
171         sdbusplus::com::ibm::Dump::server::Create::
172             convertCreateParametersToString(CreateParameters::Password));
173     if (iter == params.end())
174     {
175         log<level::INFO>("Password is not provided for resource dump");
176     }
177     else
178     {
179         try
180         {
181             pwd = std::get<std::string>(iter->second);
182         }
183         catch (const std::bad_variant_access& e)
184         {
185             // Exception will be raised if the input is not string
186             log<level::ERR>(
187                 fmt::format("An invalid password string is passed errormsg({})",
188                             e.what())
189                     .c_str());
190             elog<InvalidArgument>(Argument::ARGUMENT_NAME("PASSWORD"),
191                                   Argument::ARGUMENT_VALUE("INVALID INPUT"));
192         }
193     }
194 
195     try
196     {
197         entries.insert(std::make_pair(
198             id, std::make_unique<resource::Entry>(
199                     bus, objPath.c_str(), id, timeStamp, 0, INVALID_SOURCE_ID,
200                     vspString, pwd, phosphor::dump::OperationStatus::InProgress,
201                     *this)));
202     }
203     catch (const std::invalid_argument& e)
204     {
205         log<level::ERR>(
206             fmt::format(
207                 "Error in creating resource dump "
208                 "entry,errormsg({}),OBJECTPATH({}), VSPSTRING({}), ID({})",
209                 e.what(), objPath.c_str(), vspString, id)
210                 .c_str());
211         elog<InternalFailure>();
212         return std::string();
213     }
214     lastEntryId++;
215     return objPath.string();
216 }
217 
218 } // namespace resource
219 } // namespace dump
220 } // namespace openpower
221