blob: 5c14e618c80494dedd975285da8249c7f17f97ab [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"
19#include "prepare_systemd.hpp"
20#include "update_systemd.hpp"
21#include "verify_systemd.hpp"
22
23#include <cstdio>
24#include <exception>
25#include <nlohmann/json.hpp>
26#include <sdbusplus/bus.hpp>
27#include <string>
28#include <vector>
29
30namespace ipmi_flash
31{
32
33std::vector<HandlerConfig> buildHandlerFromJson(const nlohmann::json& data)
34{
35 std::vector<HandlerConfig> handlers;
36
37 for (const auto& item : data)
38 {
39 try
40 {
41 HandlerConfig output;
42
43 /* at() throws an exception when the key is not present. */
44 item.at("blob").get_to(output.blobId);
45
46 /* handler is required. */
47 const auto& h = item.at("handler");
48 const std::string handlerType = h.at("type");
49 if (handlerType == "file")
50 {
51 const auto& path = h.at("path");
52 output.handler = std::make_unique<FileHandler>(path);
53 }
54 else
55 {
56 throw std::runtime_error("Invalid handler type: " +
57 handlerType);
58 }
59
60 /* actions are required (presently). */
61 const auto& a = item.at("actions");
62 std::unique_ptr<ActionPack> pack = std::make_unique<ActionPack>();
63
64 /* It hasn't been fully determined if any action being optional is
65 * useful, so for now they will be required.
66 * TODO: Evaluate how the behaviors change if some actions are
67 * missing, does the code just assume it was successful? I would
68 * think not.
69 */
70 const auto& prep = a.at("preparation");
71 const std::string prepareType = prep.at("type");
72 if (prepareType == "systemd")
73 {
74 const auto& unit = prep.at("unit");
75 pack->preparation = SystemdPreparation::CreatePreparation(
76 sdbusplus::bus::new_default(), unit);
77 }
78 else
79 {
80 throw std::runtime_error("Invalid preparation type: " +
81 prepareType);
82 }
83
84 const auto& verify = a.at("verification");
85 const std::string verifyType = verify.at("type");
86 if (verifyType == "fileSystemdVerify")
87 {
88 const auto& path = verify.at("path");
89 const auto& unit = verify.at("unit");
90 pack->verification = SystemdVerification::CreateVerification(
91 sdbusplus::bus::new_default(), path, unit);
92 }
93 else
94 {
95 throw std::runtime_error("Invalid verification type:" +
96 verifyType);
97 }
98
99 const auto& update = a.at("update");
100 const std::string updateType = update.at("type");
101 if (updateType == "reboot")
102 {
103 static constexpr auto rebootTarget = "reboot.target";
104 static constexpr auto rebootMode = "replace-irreversibly";
105 pack->update = SystemdUpdateMechanism::CreateSystemdUpdate(
106 sdbusplus::bus::new_default(), rebootTarget, rebootMode);
107 }
108 else if (updateType == "systemd")
109 {
110 const auto& unit = update.at("unit");
111 pack->update = SystemdUpdateMechanism::CreateSystemdUpdate(
112 sdbusplus::bus::new_default(), unit);
113 }
114 else
115 {
116 throw std::runtime_error("Invalid update type: " + updateType);
117 }
118
119 output.actions = std::move(pack);
120 handlers.push_back(std::move(output));
121 }
122 catch (const std::exception& e)
123 {
124 /* TODO: Once phosphor-logging supports unit-test injection, fix
125 * this to log.
126 */
127 std::fprintf(stderr,
128 "Excepted building HandlerConfig from json: %s\n",
129 e.what());
130 }
131 }
132
133 return handlers;
134}
135
136} // namespace ipmi_flash