1*c893f43dSJason Ling /* 2*c893f43dSJason Ling * Copyright 2019 Google Inc. 3*c893f43dSJason Ling * 4*c893f43dSJason Ling * Licensed under the Apache License, Version 2.0 (the "License"); 5*c893f43dSJason Ling * you may not use this file except in compliance with the License. 6*c893f43dSJason Ling * You may obtain a copy of the License at 7*c893f43dSJason Ling * 8*c893f43dSJason Ling * http://www.apache.org/licenses/LICENSE-2.0 9*c893f43dSJason Ling * 10*c893f43dSJason Ling * Unless required by applicable law or agreed to in writing, software 11*c893f43dSJason Ling * distributed under the License is distributed on an "AS IS" BASIS, 12*c893f43dSJason Ling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*c893f43dSJason Ling * See the License for the specific language governing permissions and 14*c893f43dSJason Ling * limitations under the License. 15*c893f43dSJason Ling */ 16*c893f43dSJason Ling #include "firmware_handlers_builder.hpp" 17*c893f43dSJason Ling 18*c893f43dSJason Ling #include "file_handler.hpp" 19*c893f43dSJason Ling #include "fs.hpp" 20*c893f43dSJason Ling #include "skip_action.hpp" 21*c893f43dSJason Ling 22*c893f43dSJason Ling #include <nlohmann/json.hpp> 23*c893f43dSJason Ling 24*c893f43dSJason Ling #include <algorithm> 25*c893f43dSJason Ling #include <cstdio> 26*c893f43dSJason Ling #include <exception> 27*c893f43dSJason Ling #include <fstream> 28*c893f43dSJason Ling #include <regex> 29*c893f43dSJason Ling #include <string> 30*c893f43dSJason Ling #include <vector> 31*c893f43dSJason Ling 32*c893f43dSJason Ling namespace ipmi_flash 33*c893f43dSJason Ling { 34*c893f43dSJason Ling std::vector<HandlerConfig<ActionPack>> 35*c893f43dSJason Ling FirmwareHandlersBuilder::buildHandlerFromJson(const nlohmann::json& data) 36*c893f43dSJason Ling { 37*c893f43dSJason Ling std::vector<HandlerConfig<ActionPack>> handlers; 38*c893f43dSJason Ling 39*c893f43dSJason Ling for (const auto& item : data) 40*c893f43dSJason Ling { 41*c893f43dSJason Ling try 42*c893f43dSJason Ling { 43*c893f43dSJason Ling HandlerConfig<ActionPack> output; 44*c893f43dSJason Ling 45*c893f43dSJason Ling /* at() throws an exception when the key is not present. */ 46*c893f43dSJason Ling item.at("blob").get_to(output.blobId); 47*c893f43dSJason Ling 48*c893f43dSJason Ling /* name must be: /flash/... */ 49*c893f43dSJason Ling if (!std::regex_match(output.blobId, std::regex("^\\/flash\\/.+"))) 50*c893f43dSJason Ling { 51*c893f43dSJason Ling throw std::runtime_error("Invalid blob name: '" + 52*c893f43dSJason Ling output.blobId + 53*c893f43dSJason Ling "' must start with /flash/"); 54*c893f43dSJason Ling } 55*c893f43dSJason Ling 56*c893f43dSJason Ling /* handler is required. */ 57*c893f43dSJason Ling const auto& h = item.at("handler"); 58*c893f43dSJason Ling const std::string handlerType = h.at("type"); 59*c893f43dSJason Ling if (handlerType == "file") 60*c893f43dSJason Ling { 61*c893f43dSJason Ling const auto& path = h.at("path"); 62*c893f43dSJason Ling output.handler = std::make_unique<FileHandler>(path); 63*c893f43dSJason Ling } 64*c893f43dSJason Ling else 65*c893f43dSJason Ling { 66*c893f43dSJason Ling throw std::runtime_error("Invalid handler type: " + 67*c893f43dSJason Ling handlerType); 68*c893f43dSJason Ling } 69*c893f43dSJason Ling 70*c893f43dSJason Ling /* actions are required (presently). */ 71*c893f43dSJason Ling const auto& a = item.at("actions"); 72*c893f43dSJason Ling std::unique_ptr<ActionPack> pack = std::make_unique<ActionPack>(); 73*c893f43dSJason Ling 74*c893f43dSJason Ling /* to make an action optional, assign type "skip" */ 75*c893f43dSJason Ling const auto& prep = a.at("preparation"); 76*c893f43dSJason Ling const std::string prepareType = prep.at("type"); 77*c893f43dSJason Ling if (prepareType == "systemd") 78*c893f43dSJason Ling { 79*c893f43dSJason Ling pack->preparation = std::move(buildSystemd(prep)); 80*c893f43dSJason Ling } 81*c893f43dSJason Ling else if (prepareType == "skip") 82*c893f43dSJason Ling { 83*c893f43dSJason Ling pack->preparation = SkipAction::CreateSkipAction(); 84*c893f43dSJason Ling } 85*c893f43dSJason Ling else 86*c893f43dSJason Ling { 87*c893f43dSJason Ling throw std::runtime_error("Invalid preparation type: " + 88*c893f43dSJason Ling prepareType); 89*c893f43dSJason Ling } 90*c893f43dSJason Ling 91*c893f43dSJason Ling const auto& verify = a.at("verification"); 92*c893f43dSJason Ling const std::string verifyType = verify.at("type"); 93*c893f43dSJason Ling if (verifyType == "fileSystemdVerify") 94*c893f43dSJason Ling { 95*c893f43dSJason Ling pack->verification = std::move(buildFileSystemd(verify)); 96*c893f43dSJason Ling } 97*c893f43dSJason Ling else if (verifyType == "systemd") 98*c893f43dSJason Ling { 99*c893f43dSJason Ling pack->verification = std::move(buildSystemd(verify)); 100*c893f43dSJason Ling } 101*c893f43dSJason Ling else if (verifyType == "skip") 102*c893f43dSJason Ling { 103*c893f43dSJason Ling pack->verification = SkipAction::CreateSkipAction(); 104*c893f43dSJason Ling } 105*c893f43dSJason Ling else 106*c893f43dSJason Ling { 107*c893f43dSJason Ling throw std::runtime_error("Invalid verification type:" + 108*c893f43dSJason Ling verifyType); 109*c893f43dSJason Ling } 110*c893f43dSJason Ling 111*c893f43dSJason Ling const auto& update = a.at("update"); 112*c893f43dSJason Ling const std::string updateType = update.at("type"); 113*c893f43dSJason Ling if (updateType == "reboot") 114*c893f43dSJason Ling { 115*c893f43dSJason Ling pack->update = SystemdNoFile::CreateSystemdNoFile( 116*c893f43dSJason Ling sdbusplus::bus::new_default(), "reboot.target", 117*c893f43dSJason Ling "replace-irreversibly"); 118*c893f43dSJason Ling } 119*c893f43dSJason Ling else if (updateType == "fileSystemdUpdate") 120*c893f43dSJason Ling { 121*c893f43dSJason Ling pack->update = std::move(buildFileSystemd(update)); 122*c893f43dSJason Ling } 123*c893f43dSJason Ling else if (updateType == "systemd") 124*c893f43dSJason Ling { 125*c893f43dSJason Ling pack->update = std::move(buildSystemd(update)); 126*c893f43dSJason Ling } 127*c893f43dSJason Ling else if (updateType == "skip") 128*c893f43dSJason Ling { 129*c893f43dSJason Ling pack->update = SkipAction::CreateSkipAction(); 130*c893f43dSJason Ling } 131*c893f43dSJason Ling else 132*c893f43dSJason Ling { 133*c893f43dSJason Ling throw std::runtime_error("Invalid update type: " + updateType); 134*c893f43dSJason Ling } 135*c893f43dSJason Ling 136*c893f43dSJason Ling output.actions = std::move(pack); 137*c893f43dSJason Ling handlers.push_back(std::move(output)); 138*c893f43dSJason Ling } 139*c893f43dSJason Ling catch (const std::exception& e) 140*c893f43dSJason Ling { 141*c893f43dSJason Ling /* TODO: Once phosphor-logging supports unit-test injection, fix 142*c893f43dSJason Ling * this to log. 143*c893f43dSJason Ling */ 144*c893f43dSJason Ling std::fprintf(stderr, 145*c893f43dSJason Ling "Excepted building HandlerConfig from json: %s\n", 146*c893f43dSJason Ling e.what()); 147*c893f43dSJason Ling } 148*c893f43dSJason Ling } 149*c893f43dSJason Ling 150*c893f43dSJason Ling return handlers; 151*c893f43dSJason Ling } 152*c893f43dSJason Ling } // namespace ipmi_flash 153