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
createDump(phosphor::dump::DumpCreateParams params)109 sdbusplus::message::object_path Manager::createDump(
110 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