1 #pragma once
2 
3 #include "fs.hpp"
4 #include "handler_config.hpp"
5 #include "status.hpp"
6 
7 #include <nlohmann/json.hpp>
8 
9 #include <array>
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 namespace ipmi_flash
15 {
16 /**
17  * build a systemd file triggerable action from json data
18  */
19 std::unique_ptr<TriggerableActionInterface>
20     buildFileSystemd(const nlohmann::json& data);
21 
22 /**
23  * build a systemd triggerable action from json data
24  */
25 std::unique_ptr<TriggerableActionInterface>
26     buildSystemd(const nlohmann::json& data);
27 
28 constexpr std::array defaultConfigPaths = {
29     "/usr/share/phosphor-ipmi-flash",
30     "/run/phosphor-ipmi-flash",
31 };
32 
33 /* HandlersBuilderIfc is a helper class that builds Handlers from the json files
34  * found within a specified directory.
35  * The child class that inherits from HandlersBuilderIfc should implement
36  * buildHandlersConfigs to perform json validation and parsing.
37  *
38  */
39 template <typename T>
40 struct HandlersBuilderIfc
41 {
42     virtual ~HandlersBuilderIfc() = default;
43 
44     /**
45      * Builds configurations from the default set of paths used by the blob
46      * handler.
47      */
buildHandlerConfigsFromDefaultPathsipmi_flash::HandlersBuilderIfc48     std::vector<HandlerConfig<T>> buildHandlerConfigsFromDefaultPaths()
49     {
50         std::vector<HandlerConfig<T>> ret;
51         for (auto path : defaultConfigPaths)
52         {
53             auto tmp = buildHandlerConfigs(path);
54             std::move(tmp.begin(), tmp.end(), std::back_inserter(ret));
55         }
56         return ret;
57     }
58 
59     /**
60      * Given a folder of json configs, build the configurations.
61      *
62      * @param[in] directory - the directory to search (recursively).
63      * @return list of HandlerConfig objects.
64      */
buildHandlerConfigsipmi_flash::HandlersBuilderIfc65     std::vector<HandlerConfig<T>> buildHandlerConfigs(const char* directory)
66     {
67         std::vector<HandlerConfig<T>> output;
68 
69         std::vector<std::string> jsonPaths = GetJsonList(directory);
70         for (const auto& path : jsonPaths)
71         {
72             std::ifstream jsonFile(path);
73             if (!jsonFile.is_open())
74             {
75                 std::fprintf(stderr, "Unable to open json file: %s\n",
76                              path.c_str());
77                 continue;
78             }
79 
80             auto data = nlohmann::json::parse(jsonFile, nullptr, false);
81             if (data.is_discarded())
82             {
83                 std::fprintf(stderr, "Parsing json failed: %s\n", path.c_str());
84                 continue;
85             }
86 
87             std::vector<HandlerConfig<T>> configs = buildHandlerFromJson(data);
88             std::move(configs.begin(), configs.end(),
89                       std::back_inserter(output));
90         }
91         return output;
92     };
93 
94     /**
95      * Given a list of handlers as json data, construct the appropriate
96      * HandlerConfig objects.  This method is meant to be called per json
97      * configuration file found.
98      *
99      * The list will only contain validly build HandlerConfig objects.  Any
100      * invalid configuration is skipped. The hope is that the BMC firmware
101      * update configuration will never be invalid, but if another aspect is
102      * invalid, it can be fixed with a BMC firmware update once the bug is
103      * identified.
104      *
105      * This code does not validate that the blob specified is unique, that
106      * should be handled at a higher layer.
107      *
108      * @param[in] data - json data from a json file.
109      * @return list of HandlerConfig objects.
110      */
111     virtual std::vector<HandlerConfig<T>>
112         buildHandlerFromJson(const nlohmann::json& data) = 0;
113 };
114 } // namespace ipmi_flash
115