xref: /openbmc/phosphor-debug-collector/dump-extensions/openpower-dumps/dump_manager_system.cpp (revision d1f670fe7ea219c643f8b630e8c2d7b333f16e35)
1 #include "config.h"
2 
3 #include "dump_manager_system.hpp"
4 
5 #include "dump_utils.hpp"
6 #include "op_dump_consts.hpp"
7 #include "system_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 system
19 {
20 
21 using namespace phosphor::logging;
22 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
23 
24 void Manager::notify(uint32_t dumpId, uint64_t size)
25 {
26     // Get the timestamp
27     uint64_t timeStamp =
28         std::chrono::duration_cast<std::chrono::microseconds>(
29             std::chrono::system_clock::now().time_since_epoch())
30             .count();
31 
32     // System dump can get created due to a fault in server
33     // or by request from user. A system dump by fault is
34     // first reported here, but for a user requested dump an
35     // entry will be created first with invalid source id.
36     // Since there can be only one system dump creation at a time,
37     // if there is an entry with invalid sourceId update that.
38     for (auto& entry : entries)
39     {
40         openpower::dump::system::Entry* sysEntry =
41             dynamic_cast<openpower::dump::system::Entry*>(entry.second.get());
42         if (sysEntry->sourceDumpId() == INVALID_SOURCE_ID)
43         {
44             sysEntry->update(timeStamp, size, dumpId);
45             return;
46         }
47     }
48 
49     // Get the id
50     auto id = lastEntryId + 1;
51     auto idString = std::to_string(id);
52     auto objPath = std::filesystem::path(baseEntryPath) / idString;
53 
54     // TODO: Get the originator Id, Type from the persisted file.
55     // For now replacing it with null
56     try
57     {
58         entries.insert(std::make_pair(
59             id, std::make_unique<system::Entry>(
60                     bus, objPath.c_str(), id, timeStamp, size, dumpId,
61                     phosphor::dump::OperationStatus::Completed, std::string(),
62                     originatorTypes::Internal, *this)));
63     }
64     catch (const std::invalid_argument& e)
65     {
66         lg2::error(
67             "Error in creating system dump entry, errormsg: {ERROR}, "
68             "OBJECTPATH: {OBJECT_PATH}, ID: {ID}, TIMESTAMP: {TIMESTAMP}, "
69             "SIZE: {SIZE}, SOURCEID: {SOURCE_ID}",
70             "ERROR", e, "OBJECT_PATH", objPath, "ID", id, "TIMESTAMP",
71             timeStamp, "SIZE", size, "SOURCE_ID", dumpId);
72         report<InternalFailure>();
73         return;
74     }
75     lastEntryId++;
76     return;
77 }
78 
79 sdbusplus::message::object_path
80     Manager::createDump(phosphor::dump::DumpCreateParams params)
81 {
82     constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
83     constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
84     constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
85     constexpr auto DIAG_MOD_TARGET = "obmc-host-crash@0.target";
86 
87     if (params.size() > CREATE_DUMP_MAX_PARAMS)
88     {
89         lg2::warning(
90             "System dump accepts not more than 2 additional parameters");
91     }
92 
93     using NotAllowed =
94         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
95     using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
96 
97     // Allow creating system dump only when the host is up.
98     if (!phosphor::dump::isHostRunning())
99     {
100         elog<NotAllowed>(
101             Reason("System dump can be initiated only when the host is up"));
102         return std::string();
103     }
104 
105     // Get the originator id and type from params
106     std::string originatorId;
107     originatorTypes originatorType;
108 
109     phosphor::dump::extractOriginatorProperties(params, originatorId,
110                                                 originatorType);
111 
112     auto b = sdbusplus::bus::new_default();
113     auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
114                                       SYSTEMD_INTERFACE, "StartUnit");
115     method.append(DIAG_MOD_TARGET); // unit to activate
116     method.append("replace");
117     bus.call_noreply(method);
118 
119     auto id = lastEntryId + 1;
120     auto idString = std::to_string(id);
121     auto objPath = std::filesystem::path(baseEntryPath) / idString;
122     uint64_t timeStamp =
123         std::chrono::duration_cast<std::chrono::microseconds>(
124             std::chrono::system_clock::now().time_since_epoch())
125             .count();
126 
127     try
128     {
129         entries.insert(std::make_pair(
130             id, std::make_unique<system::Entry>(
131                     bus, objPath.c_str(), id, timeStamp, 0, INVALID_SOURCE_ID,
132                     phosphor::dump::OperationStatus::InProgress, originatorId,
133                     originatorType, *this)));
134     }
135     catch (const std::invalid_argument& e)
136     {
137         lg2::error("Error in creating system dump entry, errormsg: {ERROR}, "
138                    "OBJECTPATH: {OBJECT_PATH}, ID: {ID}",
139                    "ERROR", e, "OBJECT_PATH", objPath, "ID", id);
140         elog<InternalFailure>();
141         return std::string();
142     }
143     lastEntryId++;
144     return objPath.string();
145 }
146 
147 } // namespace system
148 } // namespace dump
149 } // namespace openpower
150