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