blob: 095161c5451e7f1544d65ebe4ba54d5781928623 [file] [log] [blame]
Patrick Venture298930a2019-07-03 11:44:52 -07001/*
2 * Copyright 2019 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "buildjson.hpp"
17
18#include "file_handler.hpp"
Patrick Venturea6b4abd2019-07-19 10:58:55 -070019#include "fs.hpp"
Patrick Venturecf066ac2019-08-06 09:03:47 -070020#include "general_systemd.hpp"
Patrick Ventured53d60a2020-04-07 09:01:34 -070021#include "skip_action.hpp"
Patrick Venture298930a2019-07-03 11:44:52 -070022
Patrick Venture9b37b092020-05-28 20:58:57 -070023#include <nlohmann/json.hpp>
Patrick Venture9b37b092020-05-28 20:58:57 -070024#include <sdbusplus/bus.hpp>
25
Patrick Venturea6b4abd2019-07-19 10:58:55 -070026#include <algorithm>
Patrick Venture298930a2019-07-03 11:44:52 -070027#include <cstdio>
28#include <exception>
Patrick Venturea6b4abd2019-07-19 10:58:55 -070029#include <fstream>
Patrick Venture097435f2019-08-15 07:39:48 -070030#include <regex>
Patrick Venture298930a2019-07-03 11:44:52 -070031#include <string>
32#include <vector>
33
34namespace ipmi_flash
35{
36
Patrick Venture9cce5a22019-08-06 09:24:46 -070037std::unique_ptr<TriggerableActionInterface>
38 buildFileSystemd(const nlohmann::json& data)
39{
40 /* This type of action requires a path and unit, and optionally a mode. */
41 const auto& path = data.at("path");
42 const auto& unit = data.at("unit");
43
44 /* the mode parameter is optional. */
45 std::string systemdMode = "replace";
46 const auto& mode = data.find("mode");
47 if (mode != data.end())
48 {
49 systemdMode = data.at("mode").get<std::string>();
50 }
51
52 return SystemdWithStatusFile::CreateSystemdWithStatusFile(
53 sdbusplus::bus::new_default(), path, unit, systemdMode);
54}
55
Patrick Venturee0216d22019-08-21 10:17:39 -070056std::unique_ptr<TriggerableActionInterface>
57 buildSystemd(const nlohmann::json& data)
58{
59 /* This type of action requires a unit, and optionally a mode. */
60 const auto& unit = data.at("unit");
61
62 /* the mode parameter is optional. */
63 std::string systemdMode = "replace";
64 const auto& mode = data.find("mode");
65 if (mode != data.end())
66 {
67 systemdMode = data.at("mode").get<std::string>();
68 }
69
70 return SystemdNoFile::CreateSystemdNoFile(sdbusplus::bus::new_default(),
71 unit, systemdMode);
72}
73
Patrick Venture298930a2019-07-03 11:44:52 -070074std::vector<HandlerConfig> buildHandlerFromJson(const nlohmann::json& data)
75{
76 std::vector<HandlerConfig> handlers;
77
78 for (const auto& item : data)
79 {
80 try
81 {
82 HandlerConfig output;
83
84 /* at() throws an exception when the key is not present. */
85 item.at("blob").get_to(output.blobId);
86
Patrick Venture097435f2019-08-15 07:39:48 -070087 /* name must be: /flash/... */
88 if (!std::regex_match(output.blobId, std::regex("^\\/flash\\/.+")))
89 {
90 throw std::runtime_error("Invalid blob name: '" +
91 output.blobId +
92 "' must start with /flash/");
93 }
94
Patrick Venture298930a2019-07-03 11:44:52 -070095 /* handler is required. */
96 const auto& h = item.at("handler");
97 const std::string handlerType = h.at("type");
98 if (handlerType == "file")
99 {
100 const auto& path = h.at("path");
101 output.handler = std::make_unique<FileHandler>(path);
102 }
103 else
104 {
105 throw std::runtime_error("Invalid handler type: " +
106 handlerType);
107 }
108
109 /* actions are required (presently). */
110 const auto& a = item.at("actions");
111 std::unique_ptr<ActionPack> pack = std::make_unique<ActionPack>();
112
Patrick Ventured53d60a2020-04-07 09:01:34 -0700113 /* to make an action optional, assign type "skip" */
Patrick Venture298930a2019-07-03 11:44:52 -0700114 const auto& prep = a.at("preparation");
115 const std::string prepareType = prep.at("type");
116 if (prepareType == "systemd")
117 {
Patrick Venturee0216d22019-08-21 10:17:39 -0700118 pack->preparation = std::move(buildSystemd(prep));
Patrick Venture298930a2019-07-03 11:44:52 -0700119 }
Patrick Ventured53d60a2020-04-07 09:01:34 -0700120 else if (prepareType == "skip")
121 {
122 pack->preparation = SkipAction::CreateSkipAction();
123 }
Patrick Venture298930a2019-07-03 11:44:52 -0700124 else
125 {
126 throw std::runtime_error("Invalid preparation type: " +
127 prepareType);
128 }
129
130 const auto& verify = a.at("verification");
131 const std::string verifyType = verify.at("type");
132 if (verifyType == "fileSystemdVerify")
133 {
Patrick Venture9cce5a22019-08-06 09:24:46 -0700134 pack->verification = std::move(buildFileSystemd(verify));
Patrick Venture298930a2019-07-03 11:44:52 -0700135 }
William A. Kennington III2d434c82019-11-22 18:42:35 -0800136 else if (verifyType == "systemd")
137 {
138 pack->verification = std::move(buildSystemd(verify));
139 }
Patrick Ventured53d60a2020-04-07 09:01:34 -0700140 else if (verifyType == "skip")
141 {
142 pack->verification = SkipAction::CreateSkipAction();
143 }
Patrick Venture298930a2019-07-03 11:44:52 -0700144 else
145 {
146 throw std::runtime_error("Invalid verification type:" +
147 verifyType);
148 }
149
150 const auto& update = a.at("update");
151 const std::string updateType = update.at("type");
152 if (updateType == "reboot")
153 {
Patrick Venturee0216d22019-08-21 10:17:39 -0700154 pack->update = SystemdNoFile::CreateSystemdNoFile(
Patrick Venture44564902019-08-21 09:46:32 -0700155 sdbusplus::bus::new_default(), "reboot.target",
156 "replace-irreversibly");
Patrick Venture298930a2019-07-03 11:44:52 -0700157 }
Patrick Venturec2baac92019-08-05 13:30:38 -0700158 else if (updateType == "fileSystemdUpdate")
159 {
Patrick Venture9cce5a22019-08-06 09:24:46 -0700160 pack->update = std::move(buildFileSystemd(update));
Patrick Venturec2baac92019-08-05 13:30:38 -0700161 }
Patrick Venture298930a2019-07-03 11:44:52 -0700162 else if (updateType == "systemd")
163 {
Patrick Venturee0216d22019-08-21 10:17:39 -0700164 pack->update = std::move(buildSystemd(update));
Patrick Venture298930a2019-07-03 11:44:52 -0700165 }
Patrick Ventured53d60a2020-04-07 09:01:34 -0700166 else if (updateType == "skip")
167 {
168 pack->update = SkipAction::CreateSkipAction();
169 }
Patrick Venture298930a2019-07-03 11:44:52 -0700170 else
171 {
172 throw std::runtime_error("Invalid update type: " + updateType);
173 }
174
175 output.actions = std::move(pack);
176 handlers.push_back(std::move(output));
177 }
178 catch (const std::exception& e)
179 {
180 /* TODO: Once phosphor-logging supports unit-test injection, fix
181 * this to log.
182 */
183 std::fprintf(stderr,
184 "Excepted building HandlerConfig from json: %s\n",
185 e.what());
186 }
187 }
188
189 return handlers;
190}
191
Patrick Venturea6b4abd2019-07-19 10:58:55 -0700192std::vector<HandlerConfig> BuildHandlerConfigs(const std::string& directory)
193{
Patrick Venturea6b4abd2019-07-19 10:58:55 -0700194 std::vector<HandlerConfig> output;
195
196 std::vector<std::string> jsonPaths = GetJsonList(directory);
197
198 for (const auto& path : jsonPaths)
199 {
200 std::ifstream jsonFile(path);
201 if (!jsonFile.is_open())
202 {
Patrick Venture1ab824a2020-05-26 19:29:57 -0700203 std::fprintf(stderr, "Unable to open json file: %s\n",
204 path.c_str());
Patrick Venturea6b4abd2019-07-19 10:58:55 -0700205 continue;
206 }
207
208 auto data = nlohmann::json::parse(jsonFile, nullptr, false);
209 if (data.is_discarded())
210 {
Patrick Venture1ab824a2020-05-26 19:29:57 -0700211 std::fprintf(stderr, "Parsing json failed: %s\n", path.c_str());
Patrick Venturea6b4abd2019-07-19 10:58:55 -0700212 }
213
214 std::vector<HandlerConfig> configs = buildHandlerFromJson(data);
215 std::move(configs.begin(), configs.end(), std::back_inserter(output));
216 }
217
218 return output;
219}
220
Patrick Venture298930a2019-07-03 11:44:52 -0700221} // namespace ipmi_flash