1 #pragma once
2 
3 #include "config.h"
4 
5 #include "file.hpp"
6 #include "occ_errors.hpp"
7 
8 #include <systemd/sd-journal.h>
9 
10 #include <nlohmann/json.hpp>
11 #include <xyz/openbmc_project/Logging/Create/server.hpp>
12 
13 using FFDCFormat =
14     sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat;
15 using FFDCFiles = std::vector<
16     std::tuple<FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>>;
17 
18 namespace open_power
19 {
20 namespace occ
21 {
22 
23 /** @class FFDCFile
24  *  @brief Represents a single file that will get opened when created and
25  *         deleted when the object is destructed
26  */
27 class FFDCFile
28 {
29   public:
30     FFDCFile() = delete;
31     FFDCFile(const FFDCFile&) = delete;
32     FFDCFile& operator=(const FFDCFile&) = delete;
33     FFDCFile(FFDCFile&&) = delete;
34     FFDCFile& operator=(FFDCFile&&) = delete;
35 
36     /**
37      * @brief Constructor
38      *
39      * Opens the file and saves the descriptor
40      *
41      * @param[in] name - The filename
42      */
43     explicit FFDCFile(const std::filesystem::path& name);
44 
45     /**
46      * @brief Destructor - Deletes the file
47      */
~FFDCFile()48     ~FFDCFile()
49     {
50         std::filesystem::remove(_name);
51     }
52 
53     /**
54      * @brief Returns the file descriptor
55      *
56      * @return int - The descriptor
57      */
fd()58     int fd()
59     {
60         return _fd();
61     }
62 
63   private:
64     /**
65      * @brief The file descriptor holder
66      */
67     FileDescriptor _fd;
68 
69     /**
70      * @brief The filename
71      */
72     const std::filesystem::path _name;
73 };
74 
75 /** @class FFDC
76  *  @brief Monitors for SBE FFDC availability
77  */
78 class FFDC : public Error
79 {
80   public:
81     FFDC() = delete;
82     FFDC(const FFDC&) = delete;
83     FFDC& operator=(const FFDC&) = delete;
84     FFDC(FFDC&&) = default;
85     FFDC& operator=(FFDC&&) = default;
86 
87     /** @brief Constructs the FFDC object
88      *
89      *  @param[in] event    - reference to sd_event unique_ptr
90      *  @param[in] file     - File used by driver to communicate FFDC data
91      *  @param[in] instance - OCC instance number
92      */
FFDC(EventPtr & event,const fs::path & file,unsigned int instance)93     FFDC(EventPtr& event, const fs::path& file, unsigned int instance) :
94         Error(event, file, nullptr), instance(instance)
95     {
96         // Nothing to do here.
97     }
98 
~FFDC()99     ~FFDC()
100     {
101         for (auto&& it : temporaryFiles)
102         {
103             close(it.second);
104             fs::remove(it.first);
105         }
106     }
107 
108     /** @brief Helper function to create a PEL with the OpenPower DBus
109      *         interface
110      *
111      * @param[in] path - the DBus error path
112      * @param[in] src6 - the SBE error SRC6 word
113      * @param[in] msg - the error message
114      * @param[in] fd - the file descriptor for any FFDC
115      */
116     static uint32_t createPEL(const char* path, uint32_t src6, const char* msg,
117                               int fd = -1);
118 
119     /** @brief Helper function to create a PEL for the OCC reset with the
120      * OpenPower DBus interface
121      *
122      * @param[in] instance - the OCC instance id
123      * @param[in] path - the DBus error path
124      * @param[in] err - the error return code
125      * @param[in] callout - the PEL callout path
126      */
127     static void createOCCResetPEL(unsigned int instance, const char* path,
128                                   int err, const char* callout);
129 
130     /**
131      * @brief Create a file containing the latest journal traces for the
132      *        specified executable and add it to the file list.
133      *
134      * @param[in] fileList     - where to add the new file
135      * @param[in] executable   - name of app to collect
136      * @param[in] lines        - number of journal lines to save
137      *
138      * @return std::unique_ptr<FFDCFile> - The file object
139      */
140     static std::unique_ptr<FFDCFile>
141         addJournalEntries(FFDCFiles& fileList, const std::string& executable,
142                           unsigned int lines);
143 
144   private:
145     /** @brief OCC instance number. Ex, 0,1, etc */
146     unsigned int instance;
147 
148     /** @brief Stores the temporary files and file descriptors
149      *         in usage. They will be cleaned up when the class
150      *         is destroyed (when the application exits).
151      */
152     std::vector<std::pair<fs::path, int>> temporaryFiles;
153 
154     /** @brief When the error event is received, analyzes it
155      *         and makes a callback to error handler if the
156      *         content denotes an error condition
157      */
158     void analyzeEvent() override;
159 
160     /**
161      * @brief Returns an FFDCFile containing the JSON data
162      *
163      * @param[in] ffdcData - The JSON data to write to a file
164      *
165      * @return std::unique_ptr<FFDCFile> - The file object
166      */
167     static std::unique_ptr<FFDCFile>
168         makeJsonFFDCFile(const nlohmann::json& ffdcData);
169 
170     /**
171      * @brief Returns a JSON structure containing the previous N journal
172      * entries.
173      *
174      * @param[in] numLines   - Number of lines of journal to retrieve
175      * @param[in] executable - name of app to collect for
176      *
177      * @return JSON object that was created
178      */
179     static nlohmann::json getJournalEntries(int numLines,
180                                             std::string executable);
181 
182     /**
183      * @brief Gets the realtime (wallclock) timestamp for the current journal
184      * entry.
185      *
186      * @param journal current journal entry
187      * @return timestamp as a date/time string
188      */
189     static std::string getTimeStamp(sd_journal* journal);
190 
191     /**
192      * @brief Gets the value of the specified field for the current journal
193      * entry.
194      *
195      * Returns an empty string if the current journal entry does not have the
196      * specified field.
197      *
198      * @param journal current journal entry
199      * @param field journal field name
200      * @return field value
201      */
202     static std::string getFieldValue(sd_journal* journal,
203                                      const std::string& field);
204 };
205 
206 /**
207  * @class JournalCloser
208  *  @brief Automatically closes the journal when the object goes out of scope.
209  */
210 class JournalCloser
211 {
212   public:
213     // Specify which compiler-generated methods we want
214     JournalCloser() = delete;
215     JournalCloser(const JournalCloser&) = delete;
216     JournalCloser(JournalCloser&&) = delete;
217     JournalCloser& operator=(const JournalCloser&) = delete;
218     JournalCloser& operator=(JournalCloser&&) = delete;
219 
JournalCloser(sd_journal * journal)220     JournalCloser(sd_journal* journal) : journal{journal} {}
221 
~JournalCloser()222     ~JournalCloser()
223     {
224         sd_journal_close(journal);
225     }
226 
227   private:
228     sd_journal* journal{nullptr};
229 };
230 
231 } // namespace occ
232 } // namespace open_power
233