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      */
48     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 (recurisvely).
63      * @return list of HandlerConfig objects.
64      */
65     std::vector<HandlerConfig<T>> buildHandlerConfigs(const char* directory)
66     {
67 
68         std::vector<HandlerConfig<T>> output;
69 
70         std::vector<std::string> jsonPaths = GetJsonList(directory);
71         for (const auto& path : jsonPaths)
72         {
73             std::ifstream jsonFile(path);
74             if (!jsonFile.is_open())
75             {
76                 std::fprintf(stderr, "Unable to open json file: %s\n",
77                              path.c_str());
78                 continue;
79             }
80 
81             auto data = nlohmann::json::parse(jsonFile, nullptr, false);
82             if (data.is_discarded())
83             {
84                 std::fprintf(stderr, "Parsing json failed: %s\n", path.c_str());
85                 continue;
86             }
87 
88             std::vector<HandlerConfig<T>> configs = buildHandlerFromJson(data);
89             std::move(configs.begin(), configs.end(),
90                       std::back_inserter(output));
91         }
92         return output;
93     };
94 
95     /**
96      * Given a list of handlers as json data, construct the appropriate
97      * HandlerConfig objects.  This method is meant to be called per json
98      * configuration file found.
99      *
100      * The list will only contain validly build HandlerConfig objects.  Any
101      * invalid configuration is skipped. The hope is that the BMC firmware
102      * update configuration will never be invalid, but if another aspect is
103      * invalid, it can be fixed with a BMC firmware update once the bug is
104      * identified.
105      *
106      * This code does not validate that the blob specified is unique, that
107      * should be handled at a higher layer.
108      *
109      * @param[in] data - json data from a json file.
110      * @return list of HandlerConfig objects.
111      */
112     virtual std::vector<HandlerConfig<T>>
113         buildHandlerFromJson(const nlohmann::json& data) = 0;
114 };
115 } // namespace ipmi_flash
116