1 /* 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 "firmware_handlers_builder.hpp" 17 18 #include "file_handler.hpp" 19 #include "fs.hpp" 20 #include "skip_action.hpp" 21 22 #include <nlohmann/json.hpp> 23 24 #include <algorithm> 25 #include <cstdio> 26 #include <exception> 27 #include <fstream> 28 #include <regex> 29 #include <string> 30 #include <vector> 31 32 namespace ipmi_flash 33 { 34 std::vector<HandlerConfig<ActionPack>> 35 FirmwareHandlersBuilder::buildHandlerFromJson(const nlohmann::json& data) 36 { 37 std::vector<HandlerConfig<ActionPack>> handlers; 38 39 for (const auto& item : data) 40 { 41 try 42 { 43 HandlerConfig<ActionPack> output; 44 45 /* at() throws an exception when the key is not present. */ 46 item.at("blob").get_to(output.blobId); 47 48 /* name must be: /flash/... */ 49 if (!std::regex_match(output.blobId, std::regex("^\\/flash\\/.+"))) 50 { 51 throw std::runtime_error("Invalid blob name: '" + 52 output.blobId + 53 "' must start with /flash/"); 54 } 55 56 /* handler is required. */ 57 const auto& h = item.at("handler"); 58 const std::string handlerType = h.at("type"); 59 if (handlerType == "file") 60 { 61 const auto& path = h.at("path"); 62 output.handler = std::make_unique<FileHandler>(path); 63 } 64 else 65 { 66 throw std::runtime_error("Invalid handler type: " + 67 handlerType); 68 } 69 70 /* actions are required (presently). */ 71 const auto& a = item.at("actions"); 72 std::unique_ptr<ActionPack> pack = std::make_unique<ActionPack>(); 73 74 /* to make an action optional, assign type "skip" */ 75 const auto& prep = a.at("preparation"); 76 const std::string prepareType = prep.at("type"); 77 if (prepareType == "systemd") 78 { 79 pack->preparation = std::move(buildSystemd(prep)); 80 } 81 else if (prepareType == "skip") 82 { 83 pack->preparation = SkipAction::CreateSkipAction(); 84 } 85 else 86 { 87 throw std::runtime_error("Invalid preparation type: " + 88 prepareType); 89 } 90 91 const auto& verify = a.at("verification"); 92 const std::string verifyType = verify.at("type"); 93 if (verifyType == "fileSystemdVerify") 94 { 95 pack->verification = std::move(buildFileSystemd(verify)); 96 } 97 else if (verifyType == "systemd") 98 { 99 pack->verification = std::move(buildSystemd(verify)); 100 } 101 else if (verifyType == "skip") 102 { 103 pack->verification = SkipAction::CreateSkipAction(); 104 } 105 else 106 { 107 throw std::runtime_error("Invalid verification type:" + 108 verifyType); 109 } 110 111 const auto& update = a.at("update"); 112 const std::string updateType = update.at("type"); 113 if (updateType == "reboot") 114 { 115 pack->update = SystemdNoFile::CreateSystemdNoFile( 116 sdbusplus::bus::new_default(), "reboot.target", 117 "replace-irreversibly"); 118 } 119 else if (updateType == "fileSystemdUpdate") 120 { 121 pack->update = std::move(buildFileSystemd(update)); 122 } 123 else if (updateType == "systemd") 124 { 125 pack->update = std::move(buildSystemd(update)); 126 } 127 else if (updateType == "skip") 128 { 129 pack->update = SkipAction::CreateSkipAction(); 130 } 131 else 132 { 133 throw std::runtime_error("Invalid update type: " + updateType); 134 } 135 136 output.actions = std::move(pack); 137 handlers.push_back(std::move(output)); 138 } 139 catch (const std::exception& e) 140 { 141 /* TODO: Once phosphor-logging supports unit-test injection, fix 142 * this to log. 143 */ 144 std::fprintf(stderr, 145 "Excepted building HandlerConfig from json: %s\n", 146 e.what()); 147 } 148 } 149 150 return handlers; 151 } 152 } // namespace ipmi_flash 153