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     std::time_t timeStamp = std::time(nullptr);
30 
31     // If there is an entry with invalid id update that.
32     // If there a completed one with same source id ignore it
33     // if there is no invalid id, create new entry
34     openpower::dump::resource::Entry* upEntry = NULL;
35     for (auto& entry : entries)
36     {
37         openpower::dump::resource::Entry* resEntry =
38             dynamic_cast<openpower::dump::resource::Entry*>(entry.second.get());
39 
40         // If there is already a completed entry with input source id then
41         // ignore this notification.
42         if ((resEntry->sourceDumpId() == dumpId) &&
43             (resEntry->status() == phosphor::dump::OperationStatus::Completed))
44         {
45             log<level::INFO>(
46                 fmt::format("Resource dump entry with source dump id({}) is "
47                             "already present with entry id({})",
48                             dumpId, resEntry->getDumpId())
49                     .c_str());
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         log<level::INFO>(
67             fmt::format("Resource Dump Notify: Updating dumpId({}) "
68                         "with source Id({}) Size({})",
69                         upEntry->getDumpId(), dumpId, size)
70                 .c_str());
71         upEntry->update(timeStamp, size, dumpId);
72         return;
73     }
74 
75     // Get the id
76     auto id = lastEntryId + 1;
77     auto idString = std::to_string(id);
78     auto objPath = std::filesystem::path(baseEntryPath) / idString;
79 
80     try
81     {
82         log<level::INFO>(fmt::format("Resouce Dump Notify: creating new dump "
83                                      "entry dumpId({}) Id({}) Size({})",
84                                      id, dumpId, size)
85                              .c_str());
86         entries.insert(std::make_pair(
87             id, std::make_unique<resource::Entry>(
88                     bus, objPath.c_str(), id, timeStamp, size, dumpId,
89                     std::string(), std::string(),
90                     phosphor::dump::OperationStatus::Completed, *this)));
91     }
92     catch (const std::invalid_argument& e)
93     {
94         log<level::ERR>(fmt::format("Error in creating resource dump entry, "
95                                     "errormsg({}),OBJECTPATH({}),ID({}),"
96                                     "TIMESTAMP({}),SIZE({}),SOURCEID({})",
97                                     e.what(), objPath.c_str(), id, timeStamp,
98                                     size, dumpId)
99                             .c_str());
100         report<InternalFailure>();
101         return;
102     }
103     lastEntryId++;
104 }
105 
106 sdbusplus::message::object_path
107     Manager::createDump(phosphor::dump::DumpCreateParams params)
108 {
109 
110     using NotAllowed =
111         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
112     using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
113 
114     // Allow creating resource dump only when the host is up.
115     if (!phosphor::dump::isHostRunning())
116     {
117         elog<NotAllowed>(
118             Reason("Resource dump can be initiated only when the host is up"));
119         return std::string();
120     }
121 
122     using InvalidArgument =
123         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
124     using Argument = xyz::openbmc_project::Common::InvalidArgument;
125     using CreateParameters =
126         sdbusplus::com::ibm::Dump::server::Create::CreateParameters;
127 
128     auto id = lastEntryId + 1;
129     auto idString = std::to_string(id);
130     auto objPath = std::filesystem::path(baseEntryPath) / idString;
131     std::time_t timeStamp = std::time(nullptr);
132 
133     std::string vspString;
134     auto iter = params.find(
135         sdbusplus::com::ibm::Dump::server::Create::
136             convertCreateParametersToString(CreateParameters::VSPString));
137     if (iter == params.end())
138     {
139         // Host will generate a default dump if no resource selector string
140         // is provided. The default dump will be a non-disruptive system dump.
141         log<level::INFO>(
142             "VSP string is not provided, a non-disruptive system dump will be "
143             "generated by the host");
144     }
145     else
146     {
147         try
148         {
149             vspString = std::get<std::string>(iter->second);
150         }
151         catch (const std::bad_variant_access& e)
152         {
153             // Exception will be raised if the input is not string
154             log<level::ERR>(
155                 fmt::format("An invalid  vsp string is passed errormsg({})",
156                             e.what())
157                     .c_str());
158             elog<InvalidArgument>(Argument::ARGUMENT_NAME("VSP_STRING"),
159                                   Argument::ARGUMENT_VALUE("INVALID INPUT"));
160         }
161     }
162 
163     std::string pwd;
164     iter = params.find(
165         sdbusplus::com::ibm::Dump::server::Create::
166             convertCreateParametersToString(CreateParameters::Password));
167     if (iter == params.end())
168     {
169         log<level::INFO>("Password is not provided for resource dump");
170     }
171     else
172     {
173         try
174         {
175             pwd = std::get<std::string>(iter->second);
176         }
177         catch (const std::bad_variant_access& e)
178         {
179             // Exception will be raised if the input is not string
180             log<level::ERR>(
181                 fmt::format("An invalid password string is passed errormsg({})",
182                             e.what())
183                     .c_str());
184             elog<InvalidArgument>(Argument::ARGUMENT_NAME("PASSWORD"),
185                                   Argument::ARGUMENT_VALUE("INVALID INPUT"));
186         }
187     }
188 
189     try
190     {
191         entries.insert(std::make_pair(
192             id, std::make_unique<resource::Entry>(
193                     bus, objPath.c_str(), id, timeStamp, 0, INVALID_SOURCE_ID,
194                     vspString, pwd, phosphor::dump::OperationStatus::InProgress,
195                     *this)));
196     }
197     catch (const std::invalid_argument& e)
198     {
199         log<level::ERR>(
200             fmt::format(
201                 "Error in creating resource dump "
202                 "entry,errormsg({}),OBJECTPATH({}), VSPSTRING({}), ID({})",
203                 e.what(), objPath.c_str(), vspString, id)
204                 .c_str());
205         elog<InternalFailure>();
206         return std::string();
207     }
208     lastEntryId++;
209     return objPath.string();
210 }
211 
212 } // namespace resource
213 } // namespace dump
214 } // namespace openpower
215