1 #include "config.h"
2 
3 #include "dump_manager_system.hpp"
4 
5 #include "dump_utils.hpp"
6 #include "system_dump_entry.hpp"
7 #include "xyz/openbmc_project/Common/error.hpp"
8 
9 #include <fmt/core.h>
10 
11 #include <phosphor-logging/elog-errors.hpp>
12 #include <phosphor-logging/elog.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 
27     // Get the timestamp
28     std::time_t timeStamp = std::time(nullptr);
29 
30     // System dump can get created due to a fault in server
31     // or by request from user. A system dump by fault is
32     // first reported here, but for a user requested dump an
33     // entry will be created first with invalid source id.
34     // Since there can be only one system dump creation at a time,
35     // if there is an entry with invalid sourceId update that.
36     for (auto& entry : entries)
37     {
38         openpower::dump::system::Entry* sysEntry =
39             dynamic_cast<openpower::dump::system::Entry*>(entry.second.get());
40         if (sysEntry->sourceDumpId() == INVALID_SOURCE_ID)
41         {
42             sysEntry->update(timeStamp, size, dumpId);
43             return;
44         }
45     }
46 
47     // Get the id
48     auto id = lastEntryId + 1;
49     auto idString = std::to_string(id);
50     auto objPath = std::filesystem::path(baseEntryPath) / idString;
51 
52     try
53     {
54         entries.insert(std::make_pair(
55             id, std::make_unique<system::Entry>(
56                     bus, objPath.c_str(), id, timeStamp, size, dumpId,
57                     phosphor::dump::OperationStatus::Completed, *this)));
58     }
59     catch (const std::invalid_argument& e)
60     {
61         log<level::ERR>(
62             fmt::format(
63                 "Error in creating system dump entry, errormsg({}), "
64                 "OBJECTPATH({}), ID({}), TIMESTAMP({}),SIZE({}), SOURCEID({})",
65                 e.what(), objPath.c_str(), id, timeStamp, size, dumpId)
66                 .c_str());
67         report<InternalFailure>();
68         return;
69     }
70     lastEntryId++;
71     return;
72 }
73 
74 sdbusplus::message::object_path
75     Manager::createDump(phosphor::dump::DumpCreateParams params)
76 {
77     constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
78     constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
79     constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
80     constexpr auto DIAG_MOD_TARGET = "obmc-host-crash@0.target";
81 
82     if (!params.empty())
83     {
84         log<level::WARNING>("System dump accepts no additional parameters");
85     }
86 
87     using NotAllowed =
88         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
89     using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
90 
91     // Allow creating system dump only when the host is up.
92     if (!phosphor::dump::isHostRunning())
93     {
94         elog<NotAllowed>(
95             Reason("System dump can be initiated only when the host is up"));
96         return std::string();
97     }
98 
99     auto b = sdbusplus::bus::new_default();
100     auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
101                                       SYSTEMD_INTERFACE, "StartUnit");
102     method.append(DIAG_MOD_TARGET); // unit to activate
103     method.append("replace");
104     bus.call_noreply(method);
105 
106     auto id = lastEntryId + 1;
107     auto idString = std::to_string(id);
108     auto objPath = std::filesystem::path(baseEntryPath) / idString;
109     std::time_t timeStamp = std::time(nullptr);
110 
111     try
112     {
113         entries.insert(std::make_pair(
114             id, std::make_unique<system::Entry>(
115                     bus, objPath.c_str(), id, timeStamp, 0, INVALID_SOURCE_ID,
116                     phosphor::dump::OperationStatus::InProgress, *this)));
117     }
118     catch (const std::invalid_argument& e)
119     {
120         log<level::ERR>(
121             fmt::format("Error in creating system dump entry, errormsg({}), "
122                         "OBJECTPATH({}), ID({})",
123                         e.what(), objPath.c_str(), id)
124                 .c_str());
125         elog<InternalFailure>();
126         return std::string();
127     }
128     lastEntryId++;
129     return objPath.string();
130 }
131 
132 } // namespace system
133 } // namespace dump
134 } // namespace openpower
135